From 8200b5810d50fc4c0ea6d827d96494430fe39102 Mon Sep 17 00:00:00 2001 From: MaMe82 Date: Tue, 20 Nov 2018 15:24:40 +0100 Subject: [PATCH] serive,webclient,cli: Crash fix USB; partial CLI rework; reworked USB gadget deployment --- cli_client/cmd_db.go | 2 + cli_client/cmd_led.go | 39 +- cli_client/cmd_root.go | 2 +- cli_client/cmd_system.go | 51 ++ cli_client/cmd_usb.go | 249 -------- cli_client/cmd_usb_new.go | 95 +-- cli_client/rpc_client.go | 71 +-- dist/scripts/serial-teminal.sh | 13 + dist/scripts/servicestart.sh | 10 +- dist/scripts/startup.sh | 3 + dist/scripts/trigger-aware.sh | 57 ++ dist/ums/flashdrive/.gitkeep | 0 hid/controller.go | 18 + hid/keyboard_led.go | 5 +- proto/gopherjs/grpc.pb.gopherjs.go | 24 +- proto/grpc.pb.go | 699 ++++++++++----------- proto/grpc.proto | 5 +- service/SubSysTriggerAction.go | 14 +- service/SubSysUSB.go | 38 +- service/rpc_server.go | 29 +- web_client/hvueCompUSBSettings.go | 2 +- web_client/hvueComponentsTriggerActions.go | 2 +- web_client/mvuexGlobalState.go | 8 +- web_client/rpcClient.go | 6 +- 24 files changed, 617 insertions(+), 825 deletions(-) create mode 100644 cli_client/cmd_system.go delete mode 100644 cli_client/cmd_usb.go create mode 100644 dist/scripts/serial-teminal.sh create mode 100644 dist/scripts/startup.sh create mode 100755 dist/scripts/trigger-aware.sh create mode 100644 dist/ums/flashdrive/.gitkeep diff --git a/cli_client/cmd_db.go b/cli_client/cmd_db.go index 8a7fcf1..7253c04 100644 --- a/cli_client/cmd_db.go +++ b/cli_client/cmd_db.go @@ -94,4 +94,6 @@ func init() { cmdDBBackup.Flags().StringVarP(&tmpDBBackupName, "name", "n", "","Name of backup") cmdDBRestore.Flags().StringVarP(&tmpDBBackupName, "name", "n", "","Name of backup") + cmdDBList.Flags().BoolVar(&BoolJson, "json", false, "Output results as JSON if applicable") + } diff --git a/cli_client/cmd_led.go b/cli_client/cmd_led.go index fe9e1f8..beaf451 100644 --- a/cli_client/cmd_led.go +++ b/cli_client/cmd_led.go @@ -2,6 +2,7 @@ package cli_client import ( "github.com/spf13/cobra" + "os" pb "github.com/mame82/P4wnP1_go/proto" "fmt" @@ -12,35 +13,25 @@ var blink_count uint32 // usbCmd represents the usb command var ledCmd = &cobra.Command{ - Use: "LED", + Use: "led", Short: "Set or Get LED state of P4wnP1", -} - -var ledGetCmd = &cobra.Command{ - Use: "get", - Short: "Get LED blink count", Run: func(cmd *cobra.Command, args []string) { - if ls, err := ClientGetLED(StrRemoteHost, StrRemotePort); err == nil { - fmt.Printf("LED blink count %v\n", ls.BlinkCount) - } else { - log.Println(err) - } - }, -} - -var ledSetCmd = &cobra.Command{ - Use: "set", - Short: "Set LED blink count", - Run: func(cmd *cobra.Command, args []string) { - blink := cmd.Flags().Lookup("blink") - if blink.Changed { + if cmd.Flags().Lookup("blink").Changed { + // blink flag has been set if err := ClientSetLED(StrRemoteHost, StrRemotePort, pb.LEDSettings{BlinkCount: blink_count}); err == nil { - fmt.Printf("LED blink count set to %v\n", blink.Value) + fmt.Printf("LED blink count set to %v\n", blink_count) } else { log.Println(err) + os.Exit(-1) } } else { - cmd.Usage() + // blink flag has not been set, retrieve current blink count + if ls, err := ClientGetLED(StrRemoteHost, StrRemotePort); err == nil { + fmt.Printf("LED blink count %v\n", ls.BlinkCount) + } else { + log.Println(err) + os.Exit(-1) + } } }, } @@ -48,8 +39,6 @@ var ledSetCmd = &cobra.Command{ func init() { rootCmd.AddCommand(ledCmd) - ledCmd.AddCommand(ledGetCmd) - ledCmd.AddCommand(ledSetCmd) - ledSetCmd.Flags().Uint32VarP(&blink_count,"blink", "b", 0,"Set blink count (0: Off, 1..254: blink n times, >254: On)") + ledCmd.Flags().Uint32VarP(&blink_count,"blink", "b", 0,"Set blink count (0: Off, 1..254: blink n times, >254: On)") } diff --git a/cli_client/cmd_root.go b/cli_client/cmd_root.go index a2e1bd2..fac6ce3 100644 --- a/cli_client/cmd_root.go +++ b/cli_client/cmd_root.go @@ -11,6 +11,7 @@ import ( var ( StrRemoteHost string StrRemotePort string + BoolJson bool ) @@ -45,7 +46,6 @@ func Execute() { func init() { rootCmd.PersistentFlags().StringVar(&StrRemoteHost, "host", "localhost", "The host with the listening P4wnP1 RPC server") rootCmd.PersistentFlags().StringVar(&StrRemotePort, "port", "50051", "The port on which the P4wnP1 RPC server is listening") - rootCmd.PersistentFlags().BoolVar(&BoolJson, "json", false, "Output results as JSON if applicable") /* // Cobra also supports local flags, which will only run diff --git a/cli_client/cmd_system.go b/cli_client/cmd_system.go new file mode 100644 index 0000000..0b0bf2e --- /dev/null +++ b/cli_client/cmd_system.go @@ -0,0 +1,51 @@ +package cli_client + +import ( + "fmt" + "github.com/spf13/cobra" + "os" +) + + + + +func init() { + cmdSystem := &cobra.Command{ + Use: "system", + Short: "system commands", + } + + cmdSystemReboot := &cobra.Command{ + Use: "reboot", + Short: "reboot P4wnP1", + Run: func(cmd *cobra.Command, args []string) { + err := ClientReboot(StrRemoteHost, StrRemotePort, TIMEOUT_LONG) + if err != nil { + fmt.Println(" failed") + fmt.Println(err.Error()) + os.Exit(-1) + } + fmt.Println(" success") + }, + + } + + cmdSystemShutdown := &cobra.Command{ + Use: "shutdown", + Short: "shutdown P4wnP1", + Run: func(cmd *cobra.Command, args []string) { + err := ClientReboot(StrRemoteHost, StrRemotePort, TIMEOUT_LONG) + if err != nil { + fmt.Println(" failed") + fmt.Println(err.Error()) + os.Exit(-1) + } + fmt.Println(" success") + }, + + } + + + rootCmd.AddCommand(cmdSystem) + cmdSystem.AddCommand(cmdSystemReboot, cmdSystemShutdown) +} diff --git a/cli_client/cmd_usb.go b/cli_client/cmd_usb.go deleted file mode 100644 index 103fa5a..0000000 --- a/cli_client/cmd_usb.go +++ /dev/null @@ -1,249 +0,0 @@ -package cli_client - -import ( - "fmt" - "github.com/spf13/cobra" - "log" - - "github.com/davecgh/go-spew/spew" - "google.golang.org/grpc/status" -) - -//Empty settings used to store cobra flags -var ( - //tmpGadgetSettings = pb.GadgetSettings{CdcEcmSettings:&pb.GadgetSettingsEthernet{},RndisSettings:&pb.GadgetSettingsEthernet{}} - tmpNoAutoDeploy = false - tmpDisableGadget bool = false - tmpUseHIDKeyboard uint8 = 0 - tmpUseHIDMouse uint8 = 0 - tmpUseHIDRaw uint8 = 0 - tmpUseRNDIS uint8 = 0 - tmpUseECM uint8 = 0 - tmpUseSerial uint8 = 0 - tmpUseUMS uint8 = 0 - tmpUMSFile string = "" - tmpUMSCdromMode bool = false - -) - -func init(){ - //Configure spew for struct deep printing (disable using printer interface for gRPC structs) - spew.Config.Indent="\t" - spew.Config.DisableMethods = true - spew.Config.DisablePointerAddresses = true -} - -// usbCmd represents the usb command -var usbCmd = &cobra.Command{ - Use: "USB", - Short: "Set, get or deploy USB Gadget settings", -} - -var usbGetCmd = &cobra.Command{ - Use: "get", - Short: "Get USB Gadget settings", - Long: ``, - Run: cobraUsbGet, -} - -var usbGetDeployedCmd = &cobra.Command{ - Use: "deployed", - Short: "Get deployed USB Gadget settings (the currently running configuration for the kernel module)", - Long: ``, - Run: cobraUsbGetDeployed, -} - -var usbSetDeployeCmd = &cobra.Command{ - Use: "deploy", - Short: "Deployed the USB Gadget settings (as running configuration for the kernel module)", - Long: ``, - Run: cobraUsbDeploySettings, -} - -var usbSetCmd = &cobra.Command{ - Use: "set", - Short: "set USB Gadget settings", - Long: ``, - Run: cobraUsbSet, -} - -func cobraUsbSet(cmd *cobra.Command, args []string) { - gs, err := ClientGetGadgetSettings(StrRemoteHost, StrRemotePort) - if err != nil { - log.Println(err) - return - } - - fmt.Printf("Old USB Gadget Settings:\n%s", spew.Sdump(gs)) - - if tmpDisableGadget { - fmt.Println("Setting gadget to disabled (won't get bound to UDC after deployment)") - gs.Enabled = false - } else { - fmt.Println("Setting gadget to enabled (will be usable after deployment)") - gs.Enabled = true - } - - if (cmd.Flags().Lookup("rndis").Changed) { - if tmpUseRNDIS == 0 { - fmt.Println("Disabeling RNDIS") - gs.Use_RNDIS = false - } else { - fmt.Println("Enabeling RNDIS") - gs.Use_RNDIS = true - } - } - - if (cmd.Flags().Lookup("cdc-ecm").Changed) { - if tmpUseECM == 0 { - fmt.Println("Disabeling CDC ECM") - gs.Use_CDC_ECM = false - } else { - fmt.Println("Enabeling CDC ECM") - gs.Use_CDC_ECM = true - } - } - - if (cmd.Flags().Lookup("serial").Changed) { - if tmpUseSerial == 0 { - fmt.Println("Disabeling Serial") - gs.Use_SERIAL = false - } else { - fmt.Println("Enabeling Serial") - gs.Use_SERIAL = true - } - } - - if (cmd.Flags().Lookup("hid-keyboard").Changed) { - if tmpUseHIDKeyboard == 0 { - fmt.Println("Disabeling HID keyboard") - gs.Use_HID_KEYBOARD = false - } else { - fmt.Println("Enabeling HID keyboard") - gs.Use_HID_KEYBOARD = true - } - } - - if (cmd.Flags().Lookup("hid-mouse").Changed) { - if tmpUseHIDMouse == 0 { - fmt.Println("Disabeling HID mouse") - gs.Use_HID_MOUSE = false - } else { - fmt.Println("Enabeling HID mouse") - gs.Use_HID_MOUSE = true - } - } - - if (cmd.Flags().Lookup("hid-raw").Changed) { - if tmpUseHIDRaw == 0 { - fmt.Println("Disabeling HID raw device") - gs.Use_HID_RAW = false - } else { - fmt.Println("Enabeling HID raw device") - gs.Use_HID_RAW = true - } - } - - if (cmd.Flags().Lookup("ums").Changed) { - if tmpUseUMS == 0 { - fmt.Println("Disabeling USB Mass Storage") - gs.Use_UMS = false - } else { - fmt.Println("Enabeling USB Mass Storage") - gs.Use_UMS = true - - gs.UmsSettings.Cdrom = tmpUMSCdromMode - if tmpUMSCdromMode { - fmt.Println("Setting USB Mass Storage to CD-Rom mode") - } else { - fmt.Println("Setting USB Mass Storage to flash drive mode") - } - - if cmd.Flags().Lookup("ums-file").Changed { - fmt.Printf("Serving USB Mass Storage from '%s'\n", tmpUMSFile) - gs.UmsSettings.File = tmpUMSFile - } - } - } - - - - - //Try to set the change config - err = ClientSetGadgetSettings(StrRemoteHost, StrRemotePort, *gs) - if err != nil { - //ToDo: Adopt parsing of Error Message to other gRPC calls - log.Printf("Error setting new gadget settings: %v\n", status.Convert(err).Message()) - return - } - - gs, err = ClientGetGadgetSettings(StrRemoteHost, StrRemotePort) - if err != nil { - log.Println(err) - return - } - - fmt.Printf("New USB Gadget Settings:\n%s", spew.Sdump(gs)) - - //if "auto deploy" isn't disabled, we deploy the gadget immediately to ConfigFS - if !tmpNoAutoDeploy { - fmt.Println("Auto-deploy the new settings...") - if gs, err := ClientDeployGadgetSettings(StrRemoteHost, StrRemotePort); err != nil { - fmt.Printf("Error deploying Gadget Settings: %v\nReverted to:\n%s", err, spew.Sdump(gs)) - } else { - fmt.Printf("Successfully deployed:\n%s", spew.Sdump(gs)) - } - } - - return -} - -func cobraUsbGet(cmd *cobra.Command, args []string) { - if gs, err := ClientGetGadgetSettings(StrRemoteHost, StrRemotePort); err == nil { - fmt.Printf("USB Gadget Settings:\n%s", spew.Sdump(gs)) - } else { - log.Println(err) - } -} - -func cobraUsbDeploySettings(cmd *cobra.Command, args []string) { - - if gs, err := ClientDeployGadgetSettings(StrRemoteHost, StrRemotePort); err != nil { - fmt.Printf("Error deploying Gadget Settings: %v\nReverted to:\n%s", err, spew.Sdump(gs)) - } else { - fmt.Printf("Successfully deployed:\n%s", spew.Sdump(gs)) - } - -} - - -func cobraUsbGetDeployed(cmd *cobra.Command, args []string) { - if gs, err := ClientGetDeployedGadgetSettings(StrRemoteHost, StrRemotePort); err == nil { - fmt.Printf("Deployed USB Gadget Settings:\n%s", spew.Sdump(gs)) - } else { - log.Println(err) - } -} - -func init() { -// rootCmd.AddCommand(usbCmd) - usbCmd.AddCommand(usbGetCmd) - usbCmd.AddCommand(usbSetCmd) - usbGetCmd.AddCommand(usbGetDeployedCmd) - usbSetCmd.AddCommand(usbSetDeployeCmd) - - usbSetCmd.Flags().BoolVarP(&tmpNoAutoDeploy, "no-deploy","n", false, "If this flag is set, the gadget isn't deployed automatically (allows further changes before deployment)") - usbSetCmd.Flags().BoolVarP(&tmpDisableGadget, "disabled","d", false, "If this flag is set, the gadget stays inactive after deployment (not bound to UDC)") - usbSetCmd.Flags().Uint8VarP(&tmpUseRNDIS, "rndis", "r",0,"Use the RNDIS gadget function (0: disable, 1..n: enable)") - usbSetCmd.Flags().Uint8VarP(&tmpUseECM, "cdc-ecm", "e",0,"Use the CDC ECM gadget function (0: disable, 1..n: enable)") - usbSetCmd.Flags().Uint8VarP(&tmpUseSerial, "serial", "s",0,"Use the SERIAL gadget function (0: disable, 1..n: enable)") - - usbSetCmd.Flags().Uint8VarP(&tmpUseHIDKeyboard, "hid-keyboard", "k",0,"Use the HID KEYBOARD gadget function (0: disable, 1..n: enable)") - usbSetCmd.Flags().Uint8VarP(&tmpUseHIDMouse, "hid-mouse", "m",0,"Use the HID MOUSE gadget function (0: disable, 1..n: enable)") - usbSetCmd.Flags().Uint8VarP(&tmpUseHIDRaw, "hid-raw", "g",0,"Use the HID RAW gadget function (0: disable, 1..n: enable)") - - usbSetCmd.Flags().Uint8VarP(&tmpUseUMS, "ums", "u",0,"Use the USB Mass Storage gadget function (0: disable, 1..n: enable)") - - usbSetCmd.Flags().BoolVar(&tmpUMSCdromMode, "ums-cdrom", false, "If this flag is set, UMS emulates a CD-Rom instead of a flashdrive (ignored, if UMS disabled)") - usbSetCmd.Flags().StringVar(&tmpUMSFile, "ums-file", "", "Path to the image or block device backing UMS (ignored, if UMS disabled)") -} diff --git a/cli_client/cmd_usb_new.go b/cli_client/cmd_usb_new.go index 947a091..2011704 100644 --- a/cli_client/cmd_usb_new.go +++ b/cli_client/cmd_usb_new.go @@ -3,12 +3,10 @@ package cli_client import ( "encoding/json" "fmt" - "github.com/davecgh/go-spew/spew" + pb "github.com/mame82/P4wnP1_go/proto" "github.com/spf13/cobra" - "google.golang.org/grpc/status" "log" "os" - pb "github.com/mame82/P4wnP1_go/proto" ) type devPath int @@ -37,6 +35,8 @@ var ( tmpUsbPid = "0x1347" tmpUsbManufacturer = "MaMe82" tmpUsbProduct = "P4wnP1 by MaMe82" + + ) @@ -79,85 +79,84 @@ func PrintGadgetSettings(gs *pb.GadgetSettings, useJson bool) { } func usbSet(cmd *cobra.Command, args []string) { - gs, err := ClientGetGadgetSettings(StrRemoteHost, StrRemotePort) + newGs, err := ClientGetDeployedGadgetSettings(StrRemoteHost, StrRemotePort) if err != nil { log.Println(err) return } - gs.Pid = tmpUsbPid - gs.Vid = tmpUsbVid - gs.Product = tmpUsbProduct - gs.Manufacturer = tmpUsbManufacturer - gs.Serial = tmpUsbSerialnumber - gs.Enabled = !tmpUsbDisableGadget - gs.Use_RNDIS = tmpUsbUseRNDIS - gs.Use_CDC_ECM = tmpUsbUseECM - gs.Use_SERIAL = tmpUsbUseSerial - gs.Use_HID_KEYBOARD = tmpUsbUseHIDKeyboard - gs.Use_HID_MOUSE = tmpUsbUseHIDMouse - gs.Use_HID_RAW = tmpUsbUseHIDRaw - gs.Use_UMS = tmpUsbUseUMS + fPid := cmd.Flags().Lookup("pid") + fVid := cmd.Flags().Lookup("vid") + fProduct := cmd.Flags().Lookup("product") + fManufacturer := cmd.Flags().Lookup("manufacturer") + fSerialno := cmd.Flags().Lookup("sn") + + if fVid.Changed { + newGs.Vid = tmpUsbVid + } + if fPid.Changed { + newGs.Pid = tmpUsbPid + } + if fManufacturer.Changed { + newGs.Manufacturer = tmpUsbManufacturer + } + if fProduct.Changed { + newGs.Product = tmpUsbProduct + } + if fSerialno.Changed { + newGs.Serial = tmpUsbSerialnumber + } + + + newGs.Enabled = !tmpUsbDisableGadget + newGs.Use_RNDIS = tmpUsbUseRNDIS + newGs.Use_CDC_ECM = tmpUsbUseECM + newGs.Use_SERIAL = tmpUsbUseSerial + newGs.Use_HID_KEYBOARD = tmpUsbUseHIDKeyboard + newGs.Use_HID_MOUSE = tmpUsbUseHIDMouse + newGs.Use_HID_RAW = tmpUsbUseHIDRaw + newGs.Use_UMS = tmpUsbUseUMS if tmpUsbUseUMS { - gs.UmsSettings.Cdrom = tmpUsbUMSCdromMode + newGs.UmsSettings.Cdrom = tmpUsbUMSCdromMode if cmd.Flags().Lookup("ums-file").Changed { - fmt.Printf("Serving USB Mass Storage from '%s'\n", tmpUMSFile) - gs.UmsSettings.File = tmpUMSFile + fmt.Printf("Serving USB Mass Storage from '%s'\n", tmpUsbUMSFile) + newGs.UmsSettings.File = tmpUsbUMSFile } } //Update service settings - err = ClientSetGadgetSettings(StrRemoteHost, StrRemotePort, *gs) + deployedGs,err := ClientDeployGadgetSettings(StrRemoteHost, StrRemotePort, newGs) if err != nil { - fmt.Printf("Error setting new gadget settings: %v\n", status.Convert(err).Message()) + fmt.Printf("Error deploying Gadget Settings: %v\nReverted to:\n%+v", err, deployedGs) os.Exit(-1) return } - //deploy updated settings and fetch result (effectively deployed settings) - if gs, err := ClientDeployGadgetSettings(StrRemoteHost, StrRemotePort); err != nil { - fmt.Printf("Error deploying Gadget Settings: %v\nReverted to:\n%s", err, spew.Sdump(gs)) - os.Exit(-1) - } + if BoolJson { - PrintGadgetSettings(gs,true) + PrintGadgetSettings(deployedGs,true) } else { fmt.Println("Successfully deployed USB gadget settings") - PrintGadgetSettings(gs,false) + PrintGadgetSettings(deployedGs,false) } return } func usbMount(cmd *cobra.Command, args []string) { - gs, err := ClientGetGadgetSettings(StrRemoteHost, StrRemotePort) + gs, err := ClientGetDeployedGadgetSettings(StrRemoteHost, StrRemotePort) if err != nil { log.Println(err) return } - /* - gs.Pid = tmpUsbPid - gs.Vid = tmpUsbVid - gs.Product = tmpUsbProduct - gs.Manufacturer = tmpUsbManufacturer - gs.Serial = tmpUsbSerialnumber - gs.Enabled = !tmpUsbDisableGadget - gs.Use_RNDIS = tmpUsbUseRNDIS - gs.Use_CDC_ECM = tmpUsbUseECM - gs.Use_SERIAL = tmpUsbUseSerial - gs.Use_HID_KEYBOARD = tmpUsbUseHIDKeyboard - gs.Use_HID_MOUSE = tmpUsbUseHIDMouse - gs.Use_HID_RAW = tmpUsbUseHIDRaw - gs.Use_UMS = tmpUsbUseUMS - */ if gs.Use_UMS { //gs.UmsSettings.Cdrom = tmpUsbUMSCdromMode if cmd.Flags().Lookup("ums-file").Changed { - fmt.Printf("Serving USB Mass Storage from '%s'\n", tmpUMSFile) + fmt.Printf("Serving USB Mass Storage from '%s'\n", tmpUsbUMSFile) //gs.UmsSettings.File = tmpUMSFile ClientMountUMSImage(StrRemoteHost, StrRemotePort, tmpUsbUMSFile, tmpUsbUMSCdromMode) } @@ -171,7 +170,7 @@ func usbMount(cmd *cobra.Command, args []string) { } func usbGet(cmd *cobra.Command, args []string) { - if gs, err := ClientGetGadgetSettings(StrRemoteHost, StrRemotePort); err == nil { + if gs, err := ClientGetDeployedGadgetSettings(StrRemoteHost, StrRemotePort); err == nil { if BoolJson { PrintGadgetSettings(gs,true) } else { @@ -335,4 +334,6 @@ func init() { cmdUsbMount.Flags().BoolVar(&tmpUsbUMSCdromMode, "ums-cdrom", false, "If this flag is set, UMS emulates a CD-Rom instead of a flashdrive (ignored, if UMS disabled)") cmdUsbMount.Flags().StringVar(&tmpUsbUMSFile, "ums-file", "", "Path to the image or block device backing UMS (ignored, if UMS disabled)") + cmdUsb.PersistentFlags().BoolVar(&BoolJson, "json", false, "Output results as JSON if applicable") + } diff --git a/cli_client/rpc_client.go b/cli_client/rpc_client.go index 21746dd..bce558c 100644 --- a/cli_client/rpc_client.go +++ b/cli_client/rpc_client.go @@ -108,17 +108,6 @@ func clientCreateTempDirOfFile(host string, port string, dir string, prefix stri return } -/* -func ClientUploadFileFromSrcPath(host string, port string, srcPath string, destPath string, forceOverwrite bool) (err error) { - //open local file for reading - flag := os.O_RDONLY - f, err := os.OpenFile(srcPath, flag, os.ModePerm) - if err != nil { return err } - defer f.Close() - - return ClientUploadFile(host,port,f,destPath,forceOverwrite) -} -*/ func ClientRegisterEvent(host string, port string, evtType int64) (err error) { // open gRPC Client @@ -205,28 +194,51 @@ func ClientGetLED(host string, port string) (ls *pb.LEDSettings, err error) { return } -func ClientGetGadgetSettings(host string, port string) (gs *pb.GadgetSettings, err error) { - conn, client, ctx, cancel, err := ClientConnectServer(host, port) - defer conn.Close() - defer cancel() - if err != nil { return } +func ClientReboot(host string, port string, timeout time.Duration) (err error) { + address := host + ":" + port + connection, err := grpc.Dial(address, grpc.WithInsecure()) + if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) } + defer connection.Close() - gs, err = client.GetGadgetSettings(ctx, &pb.Empty{}) - if err != nil { - log.Printf("Error getting USB Gadget Settings: %+v", err) + rpcClient := pb.NewP4WNP1Client(connection) + ctx := context.Background() + if timeout > 0 { + ctxNew,cancel := context.WithTimeout(ctx, timeout) + ctx = ctxNew + defer cancel() } + _,err = rpcClient.Reboot(ctx, &pb.Empty{}) return } -func ClientDeployGadgetSettings(host string, port string) (gs *pb.GadgetSettings, err error) { +func ClientShutdown(host string, port string, timeout time.Duration) (err error) { + address := host + ":" + port + connection, err := grpc.Dial(address, grpc.WithInsecure()) + if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) } + defer connection.Close() + + rpcClient := pb.NewP4WNP1Client(connection) + ctx := context.Background() + if timeout > 0 { + ctxNew,cancel := context.WithTimeout(ctx, timeout) + ctx = ctxNew + defer cancel() + } + + _,err = rpcClient.Shutdown(ctx, &pb.Empty{}) + return +} + + +func ClientDeployGadgetSettings(host string, port string, newGs *pb.GadgetSettings) (gs *pb.GadgetSettings, err error) { conn, client, ctx, cancel, err := ClientConnectServer(host, port) defer conn.Close() defer cancel() if err != nil { return } - gs, err = client.DeployGadgetSetting(ctx, &pb.Empty{}) + gs, err = client.DeployGadgetSetting(ctx, newGs) if err != nil { log.Printf("Error deploying current USB Gadget Settings: %+v", err) //We have an error case, thus gs isn't submitted by the gRPC server (even if the value is provided) @@ -252,23 +264,6 @@ func ClientGetDeployedGadgetSettings(host string, port string) (gs *pb.GadgetSet return } - -func ClientSetGadgetSettings(host string, port string, gs pb.GadgetSettings) (err error) { - conn, client, ctx, cancel, err := ClientConnectServer(host, port) - defer conn.Close() - defer cancel() - if err != nil { return } - - _, err = client.SetGadgetSettings(ctx, &gs) - //Only forward the error - /* - if err != nil { - log.Printf("Error setting GadgetSettings %d: %+v", gs, err) - } - */ - return -} - func ClientSetLED(host string, port string, ls pb.LEDSettings) (err error) { conn, client, ctx, cancel, err := ClientConnectServer(host, port) defer conn.Close() diff --git a/dist/scripts/serial-teminal.sh b/dist/scripts/serial-teminal.sh new file mode 100644 index 0000000..25dd6dc --- /dev/null +++ b/dist/scripts/serial-teminal.sh @@ -0,0 +1,13 @@ +#!/bin/bash +echo "$TRIGGER" +if [ "$TRIGGER" = "TRIGGER_USB_GADGET_CONNECTED" ]; then + echo "USB gadget connected, starting terminal for ttyGS0" + # start systemd service unit, which spwans agetty for ttyGS0 if needed + service serial-getty@ttyGS0 start +fi + +if [ "$TRIGGER" = "TRIGGER_USB_GADGET_DISCONNECTED" ]; then + echo "USB gadget disconnected, stopping terminal for ttyGS0" + # stop systemd service unit, which spwans agetty for ttyGS0 + service serial-getty@ttyGS0 stop +fi diff --git a/dist/scripts/servicestart.sh b/dist/scripts/servicestart.sh index ae828a3..df40b5c 100644 --- a/dist/scripts/servicestart.sh +++ b/dist/scripts/servicestart.sh @@ -1,7 +1,11 @@ #!/bin/bash -# Enable USB functions RNDIS, CDC ECM (don't disable other functions which already have been enabled) -P4wnP1_cli usb set --rndis 1 --cdc-ecm 1 +# fallback script, called in case the configured 'Startup Master Template' fails +# the script uses the CLI client to do basic configuration and make P4wnP1 reachable +# Additionally it serves as example on how to use the CLI client to configure P4wnP1 A.L.O.A. + +# Enable USB functions RNDIS, CDC ECM +P4wnP1_cli usb set --vid 0x1d6c --pid 0x1347 --manufacturer "MaMe82" --sn "deadbeef1337" --product "P4wnP1 by MaMe82" --rndis --cdc-ecm # Configure USB ethernet interface "usbeth" to run a DHCP server # - use IPv4 172.16.0.1 for interface with netmask 255.255.255.252 @@ -22,4 +26,4 @@ P4wnP1_cli WIFI set ap -r US -c 6 -s "💥🖥💥 Ⓟ➃ⓌⓃ🅟❶" -k "MaMe # - add a DHCP range from 172.24.0.10 to 172.24.0.20 with a lease time of 5 minutes P4wnP1_cli NET set server -i wlan0 -a 172.24.0.1 -m 255.255.255.0 -o "3:" -o "6:" -r "172.24.0.10|172.24.0.20|5m" -P4wnP1_cli LED set -b 5 +P4wnP1_cli led -b 2 diff --git a/dist/scripts/startup.sh b/dist/scripts/startup.sh new file mode 100644 index 0000000..3c2ed9a --- /dev/null +++ b/dist/scripts/startup.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +P4wnP1_cli led -b 1 diff --git a/dist/scripts/trigger-aware.sh b/dist/scripts/trigger-aware.sh new file mode 100755 index 0000000..b8325b9 --- /dev/null +++ b/dist/scripts/trigger-aware.sh @@ -0,0 +1,57 @@ +#!/bin/bash +if [ "$TRIGGER" = "" ]; then + echo "Script not called from TriggerAction" + exit +fi + +if [ "$TRIGGER" = "TRIGGER_SERVICE_STARTED" ]; then + echo "Script called from service started" +fi + +if [ "$TRIGGER" = "TRIGGER_USB_GADGET_CONNECTED" ]; then + echo "Script called from Trigger USB gadget connected" +fi + +if [ "$TRIGGER" = "TRIGGER_USB_GADGET_DISCONNECTED" ]; then + echo "Script called from Trigger USB gadget disconnected" +fi + +if [ "$TRIGGER" = "TRIGGER_WIFI_AP_STARTED" ]; then + echo "Script called from Trigger WiFi Access Point started" +fi + +if [ "$TRIGGER" = "TRIGGER_WIFI_CONNECTED_AS_STA" ]; then + echo "Script called from Trigger Connected to existing WiFi" +fi + +if [ "$TRIGGER" = "TRIGGER_SSH_LOGIN" ]; then + echo "Script called from Trigger SSH login for user: $SSH_LOGIN_USER" +fi + +if [ "$TRIGGER" = "TRIGGER_DHCP_LEASE_GRANTED" ]; then + echo "Script called from Trigger DHCP lease granted" + echo "\tInterface: $DHCP_LEASE_IFACE" + echo "\tMac: $DHCP_LEASE_MAC" + echo "\tIP: $DHCP_LEASE_IP" + echo "\tHost: $DHCP_LEASE_HOST" +fi + +if [ "$TRIGGER" = "TRIGGER_GROUP_RECEIVE" ]; then + echo "Script called from Trigger Received value on group channel" + echo "\tGroup: $GROUP" + echo "\tValue: $VALUE" +fi + +if [ "$TRIGGER" = "TRIGGER_GROUP_RECEIVE_MULTI" ]; then + echo "Script called from Trigger Received multiple values on group channel" + echo "\tGroup: $GROUP" + echo "\tValues: $VALUES" + echo "\tType: $MULTI_TYPE" +fi + +if [ "$TRIGGER" = "TRIGGER_GPIO_IN" ]; then + echo "Script called from Trigger GPIO in" + echo "\tGPIO pin: $GPIO_PIN" + echo "\tPin Level: $GPIO_LEVEL" +fi + diff --git a/dist/ums/flashdrive/.gitkeep b/dist/ums/flashdrive/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hid/controller.go b/hid/controller.go index 45a8dc7..a081d6b 100644 --- a/hid/controller.go +++ b/hid/controller.go @@ -61,12 +61,17 @@ type HIDController struct { ctx context.Context cancel context.CancelFunc eventHandler EventHandler + + abortLock *sync.Mutex + isAborted bool } func NewHIDController(ctx context.Context, keyboardDevicePath string, keyboardMapPath string, mouseDevicePath string) (ctl *HIDController, err error) { //ToDo: check if hidcontroller could work with a context with cancellation, which then could be cancelled on reuse of the object if hidControllerReuse == nil { hidControllerReuse = &HIDController{} + hidControllerReuse.abortLock = &sync.Mutex{} + hidControllerReuse.isAborted = true hidControllerReuse.initMasterVM() //clone VM to pool @@ -82,6 +87,11 @@ func NewHIDController(ctx context.Context, keyboardDevicePath string, keyboardMa } + hidControllerReuse.abortLock.Lock() + defer hidControllerReuse.abortLock.Unlock() + + hidControllerReuse.isAborted = false + ctx,cancel := context.WithCancel(ctx) hidControllerReuse.ctx = ctx hidControllerReuse.cancel = cancel @@ -125,6 +135,14 @@ func (ctl *HIDController) emitEvent(event Event) { } func (ctl *HIDController) Abort() { + ctl.abortLock.Lock() + defer ctl.abortLock.Unlock() + + if ctl.isAborted { + return + } + ctl.isAborted = true + // stop the old LED reader if present // !! Keyboard.Close() has to be called before sending IRQ to VMs (there're JS function which register // blocking callbacks to the Keyboard's LED reader, which would hinder the VM interrupt in triggering) diff --git a/hid/keyboard_led.go b/hid/keyboard_led.go index 6da74f9..7da6560 100644 --- a/hid/keyboard_led.go +++ b/hid/keyboard_led.go @@ -151,8 +151,9 @@ func (w *KeyboardLEDStateWatcher) RetrieveNewListener() (l *KeyboardLEDStateList // of the listener to deal with this interrupt and close the channel after the interrupt is consumed (wrting to the channel // happens only once) // - close ledStateFile -func (w *KeyboardLEDStateWatcher) Stop() error { - w.ledStateFile.Close() //produces an error in readLoop which gets translated to an interrupt +func (w *KeyboardLEDStateWatcher) Stop() (err error) { + //ToDo: A crash occurs from time to time, if the underlying file is already gone (gadget destroyed), this has to be called before the file is removed + err = w.ledStateFile.Close() //produces an error in readLoop which gets translated to an interrupt return nil } diff --git a/proto/gopherjs/grpc.pb.gopherjs.go b/proto/gopherjs/grpc.pb.gopherjs.go index f2d33d0..11e9ab8 100644 --- a/proto/gopherjs/grpc.pb.gopherjs.go +++ b/proto/gopherjs/grpc.pb.gopherjs.go @@ -6479,9 +6479,7 @@ type P4WNP1Client interface { ListStoredBluetoothSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*StringMessageArray, error) // USB gadget GetDeployedGadgetSetting(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*GadgetSettings, error) - DeployGadgetSetting(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*GadgetSettings, error) - GetGadgetSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*GadgetSettings, error) - SetGadgetSettings(ctx context.Context, in *GadgetSettings, opts ...grpcweb.CallOption) (*GadgetSettings, error) + DeployGadgetSetting(ctx context.Context, in *GadgetSettings, opts ...grpcweb.CallOption) (*GadgetSettings, error) GetLEDSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*LEDSettings, error) SetLEDSettings(ctx context.Context, in *LEDSettings, opts ...grpcweb.CallOption) (*Empty, error) MountUMSFile(ctx context.Context, in *GadgetSettingsUMS, opts ...grpcweb.CallOption) (*Empty, error) @@ -6694,7 +6692,7 @@ func (c *p4WNP1Client) GetDeployedGadgetSetting(ctx context.Context, in *Empty, return new(GadgetSettings).Unmarshal(resp) } -func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*GadgetSettings, error) { +func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *GadgetSettings, opts ...grpcweb.CallOption) (*GadgetSettings, error) { resp, err := c.client.RPCCall(ctx, "DeployGadgetSetting", in.Marshal(), opts...) if err != nil { return nil, err @@ -6703,24 +6701,6 @@ func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *Empty, opts return new(GadgetSettings).Unmarshal(resp) } -func (c *p4WNP1Client) GetGadgetSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*GadgetSettings, error) { - resp, err := c.client.RPCCall(ctx, "GetGadgetSettings", in.Marshal(), opts...) - if err != nil { - return nil, err - } - - return new(GadgetSettings).Unmarshal(resp) -} - -func (c *p4WNP1Client) SetGadgetSettings(ctx context.Context, in *GadgetSettings, opts ...grpcweb.CallOption) (*GadgetSettings, error) { - resp, err := c.client.RPCCall(ctx, "SetGadgetSettings", in.Marshal(), opts...) - if err != nil { - return nil, err - } - - return new(GadgetSettings).Unmarshal(resp) -} - func (c *p4WNP1Client) GetLEDSettings(ctx context.Context, in *Empty, opts ...grpcweb.CallOption) (*LEDSettings, error) { resp, err := c.client.RPCCall(ctx, "GetLEDSettings", in.Marshal(), opts...) if err != nil { diff --git a/proto/grpc.pb.go b/proto/grpc.pb.go index 1174318..7f874dd 100644 --- a/proto/grpc.pb.go +++ b/proto/grpc.pb.go @@ -3051,9 +3051,7 @@ type P4WNP1Client interface { ListStoredBluetoothSettings(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StringMessageArray, error) // USB gadget GetDeployedGadgetSetting(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GadgetSettings, error) - DeployGadgetSetting(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GadgetSettings, error) - GetGadgetSettings(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GadgetSettings, error) - SetGadgetSettings(ctx context.Context, in *GadgetSettings, opts ...grpc.CallOption) (*GadgetSettings, error) + DeployGadgetSetting(ctx context.Context, in *GadgetSettings, opts ...grpc.CallOption) (*GadgetSettings, error) GetLEDSettings(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LEDSettings, error) SetLEDSettings(ctx context.Context, in *LEDSettings, opts ...grpc.CallOption) (*Empty, error) MountUMSFile(ctx context.Context, in *GadgetSettingsUMS, opts ...grpc.CallOption) (*Empty, error) @@ -3263,7 +3261,7 @@ func (c *p4WNP1Client) GetDeployedGadgetSetting(ctx context.Context, in *Empty, return out, nil } -func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GadgetSettings, error) { +func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *GadgetSettings, opts ...grpc.CallOption) (*GadgetSettings, error) { out := new(GadgetSettings) err := grpc.Invoke(ctx, "/P4wnP1_grpc.P4WNP1/DeployGadgetSetting", in, out, c.cc, opts...) if err != nil { @@ -3272,24 +3270,6 @@ func (c *p4WNP1Client) DeployGadgetSetting(ctx context.Context, in *Empty, opts return out, nil } -func (c *p4WNP1Client) GetGadgetSettings(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GadgetSettings, error) { - out := new(GadgetSettings) - err := grpc.Invoke(ctx, "/P4wnP1_grpc.P4WNP1/GetGadgetSettings", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *p4WNP1Client) SetGadgetSettings(ctx context.Context, in *GadgetSettings, opts ...grpc.CallOption) (*GadgetSettings, error) { - out := new(GadgetSettings) - err := grpc.Invoke(ctx, "/P4wnP1_grpc.P4WNP1/SetGadgetSettings", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *p4WNP1Client) GetLEDSettings(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LEDSettings, error) { out := new(LEDSettings) err := grpc.Invoke(ctx, "/P4wnP1_grpc.P4WNP1/GetLEDSettings", in, out, c.cc, opts...) @@ -3952,9 +3932,7 @@ type P4WNP1Server interface { ListStoredBluetoothSettings(context.Context, *Empty) (*StringMessageArray, error) // USB gadget GetDeployedGadgetSetting(context.Context, *Empty) (*GadgetSettings, error) - DeployGadgetSetting(context.Context, *Empty) (*GadgetSettings, error) - GetGadgetSettings(context.Context, *Empty) (*GadgetSettings, error) - SetGadgetSettings(context.Context, *GadgetSettings) (*GadgetSettings, error) + DeployGadgetSetting(context.Context, *GadgetSettings) (*GadgetSettings, error) GetLEDSettings(context.Context, *Empty) (*LEDSettings, error) SetLEDSettings(context.Context, *LEDSettings) (*Empty, error) MountUMSFile(context.Context, *GadgetSettingsUMS) (*Empty, error) @@ -4278,7 +4256,7 @@ func _P4WNP1_GetDeployedGadgetSetting_Handler(srv interface{}, ctx context.Conte } func _P4WNP1_DeployGadgetSetting_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(GadgetSettings) if err := dec(in); err != nil { return nil, err } @@ -4290,43 +4268,7 @@ func _P4WNP1_DeployGadgetSetting_Handler(srv interface{}, ctx context.Context, d FullMethod: "/P4wnP1_grpc.P4WNP1/DeployGadgetSetting", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(P4WNP1Server).DeployGadgetSetting(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _P4WNP1_GetGadgetSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(P4WNP1Server).GetGadgetSettings(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/P4wnP1_grpc.P4WNP1/GetGadgetSettings", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(P4WNP1Server).GetGadgetSettings(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _P4WNP1_SetGadgetSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GadgetSettings) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(P4WNP1Server).SetGadgetSettings(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/P4wnP1_grpc.P4WNP1/SetGadgetSettings", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(P4WNP1Server).SetGadgetSettings(ctx, req.(*GadgetSettings)) + return srv.(P4WNP1Server).DeployGadgetSetting(ctx, req.(*GadgetSettings)) } return interceptor(ctx, in, info, handler) } @@ -5636,14 +5578,6 @@ var _P4WNP1_serviceDesc = grpc.ServiceDesc{ MethodName: "DeployGadgetSetting", Handler: _P4WNP1_DeployGadgetSetting_Handler, }, - { - MethodName: "GetGadgetSettings", - Handler: _P4WNP1_GetGadgetSettings_Handler, - }, - { - MethodName: "SetGadgetSettings", - Handler: _P4WNP1_SetGadgetSettings_Handler, - }, { MethodName: "GetLEDSettings", Handler: _P4WNP1_GetLEDSettings_Handler, @@ -5930,317 +5864,316 @@ var _P4WNP1_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("grpc.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 4980 bytes of a gzipped FileDescriptorProto + // 4963 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5c, 0x4b, 0x73, 0x23, 0x47, - 0x72, 0x06, 0x08, 0xbe, 0x90, 0x20, 0xc8, 0x66, 0xcd, 0x90, 0xc4, 0x70, 0xde, 0xbd, 0x23, 0x69, - 0x96, 0x92, 0xa8, 0x15, 0x77, 0x76, 0xa4, 0xd5, 0x4a, 0xd6, 0xe2, 0x45, 0x00, 0x33, 0x20, 0x00, - 0x75, 0x03, 0x43, 0xed, 0xcb, 0xbd, 0x8d, 0xee, 0x22, 0xd8, 0x9a, 0x46, 0x37, 0xdc, 0x0f, 0x52, - 0xb4, 0x23, 0x36, 0xc2, 0x1b, 0xe1, 0x88, 0x3d, 0xf8, 0xee, 0x83, 0x7f, 0x83, 0x7d, 0xb2, 0x7f, - 0x86, 0x7f, 0x88, 0x2f, 0x7b, 0xf3, 0xc5, 0x17, 0x3b, 0xaa, 0xaa, 0xdf, 0xe8, 0xe6, 0x6b, 0xa4, - 0x5b, 0x57, 0x56, 0xe6, 0x57, 0x55, 0x59, 0x99, 0x59, 0x59, 0x59, 0x20, 0x01, 0x26, 0xd6, 0x4c, - 0xd9, 0x9f, 0x59, 0xa6, 0x63, 0xa2, 0xd2, 0xe0, 0xc5, 0xb9, 0x31, 0xf8, 0x54, 0x22, 0x24, 0xfe, - 0x5f, 0x17, 0x60, 0xfd, 0x48, 0xb6, 0x1d, 0x6c, 0x0d, 0xf1, 0x74, 0xa6, 0xcb, 0x0e, 0x46, 0x2f, - 0x61, 0xc7, 0xf1, 0xbe, 0x25, 0x43, 0x9e, 0x62, 0x69, 0xac, 0xbb, 0xd8, 0x31, 0x4d, 0xe7, 0xb4, - 0x92, 0x7f, 0x92, 0x7f, 0x5e, 0x14, 0xb6, 0xfc, 0xee, 0x9e, 0x3c, 0xc5, 0x35, 0xbf, 0x13, 0xed, - 0xc1, 0x66, 0x5c, 0xce, 0xb5, 0xc7, 0x95, 0x05, 0x2a, 0xb1, 0x11, 0x95, 0x18, 0xd9, 0x63, 0xf4, - 0x11, 0xa0, 0x38, 0xef, 0xb9, 0x76, 0xa2, 0x55, 0x0a, 0x94, 0x99, 0x8b, 0x32, 0x1f, 0x6b, 0x27, - 0x1a, 0xaa, 0xc2, 0xc3, 0x38, 0xb7, 0x63, 0x69, 0x93, 0x09, 0xb6, 0x24, 0x59, 0x71, 0x34, 0xd3, - 0xb0, 0x2b, 0x8b, 0x54, 0x70, 0x37, 0x2a, 0x38, 0x64, 0x2c, 0x55, 0xc6, 0x81, 0x5e, 0xc0, 0x76, - 0x0c, 0xc2, 0x96, 0x0c, 0xec, 0x9c, 0x9b, 0xd6, 0xdb, 0xca, 0xd2, 0x93, 0xc2, 0xf3, 0xa2, 0x70, - 0x37, 0x2a, 0x6b, 0xf7, 0x58, 0x1f, 0xff, 0x0f, 0xf0, 0x40, 0xc0, 0x7f, 0xe7, 0x62, 0xdb, 0x89, - 0xeb, 0x48, 0x74, 0x4c, 0x4b, 0x9e, 0x60, 0xc4, 0xc3, 0xda, 0x30, 0x22, 0xe7, 0xe9, 0x27, 0x46, - 0x43, 0x9f, 0xc1, 0xaa, 0x8f, 0x4d, 0xb5, 0x51, 0x3a, 0xb8, 0xbf, 0x1f, 0xd9, 0x81, 0xfd, 0x38, - 0xb2, 0x10, 0x30, 0xf3, 0xff, 0x98, 0x87, 0xc7, 0x81, 0x76, 0xbd, 0x69, 0x88, 0xd8, 0x71, 0x34, - 0x63, 0x62, 0xdf, 0x64, 0x02, 0x5f, 0xc0, 0xaa, 0xed, 0x89, 0x79, 0x13, 0x78, 0x14, 0x9b, 0x40, - 0x30, 0x86, 0x0f, 0x2e, 0x04, 0xfc, 0xfc, 0x3f, 0xe5, 0x61, 0x73, 0xae, 0x1f, 0xfd, 0x0a, 0x16, - 0x14, 0x8d, 0x8e, 0x55, 0x3a, 0xf8, 0x30, 0x1d, 0xab, 0x6e, 0x1a, 0x8e, 0x65, 0xea, 0x3a, 0xb6, - 0x3a, 0xc6, 0x89, 0x69, 0x4d, 0x65, 0xb2, 0x0d, 0xc2, 0x82, 0xa2, 0xa1, 0x9f, 0xc3, 0x82, 0xec, - 0x4f, 0xe4, 0x27, 0xe9, 0xc2, 0xd5, 0x09, 0x36, 0x82, 0xa5, 0x0a, 0x0b, 0xb2, 0xcd, 0xef, 0xc1, - 0x76, 0x7a, 0x2f, 0xe2, 0xa0, 0x30, 0xd3, 0x0c, 0x6f, 0xe1, 0xe4, 0x93, 0xff, 0xdf, 0x3c, 0xec, - 0x04, 0xcc, 0xde, 0x4e, 0x8a, 0xd8, 0x3a, 0xd3, 0x14, 0x4c, 0xcc, 0xc0, 0xc2, 0x13, 0x8d, 0x68, - 0x5c, 0x32, 0x2d, 0xc9, 0x35, 0xfc, 0x16, 0x05, 0x58, 0x15, 0xee, 0xfa, 0xed, 0xbe, 0x35, 0x0a, - 0xfa, 0x88, 0x65, 0xdb, 0xd8, 0x3a, 0x63, 0x32, 0x8a, 0x69, 0x18, 0x58, 0x71, 0xe8, 0x0a, 0x56, - 0x85, 0x0d, 0xd6, 0xd1, 0xb7, 0xea, 0x8c, 0x8c, 0xbe, 0x84, 0x45, 0xe7, 0x62, 0x86, 0xa9, 0x2d, - 0xaf, 0x1f, 0x3c, 0x4f, 0x5f, 0x60, 0x7c, 0x56, 0xc3, 0x8b, 0x19, 0x16, 0xa8, 0x14, 0x7a, 0x04, - 0xa5, 0xa9, 0xac, 0x90, 0x61, 0x88, 0x91, 0x7a, 0x76, 0x5d, 0x9c, 0xca, 0x4a, 0xdf, 0xa2, 0x7b, - 0xf9, 0x18, 0x4a, 0x63, 0x4b, 0x53, 0x27, 0xcc, 0x88, 0x2b, 0x4b, 0xb4, 0x1f, 0x18, 0x89, 0x30, - 0xf0, 0xff, 0xbd, 0x08, 0xf7, 0x53, 0x36, 0x21, 0x50, 0x57, 0x05, 0x56, 0x66, 0xe6, 0x39, 0xb6, - 0xb0, 0xea, 0xad, 0xd8, 0x6f, 0xa2, 0x27, 0x50, 0xf2, 0x96, 0x26, 0x8f, 0x75, 0xec, 0x2d, 0x2f, - 0x4a, 0x42, 0x3f, 0x05, 0xee, 0x44, 0xb6, 0x1d, 0x29, 0xca, 0x56, 0x60, 0x5a, 0x20, 0xf4, 0x7a, - 0x84, 0x95, 0x87, 0x35, 0x55, 0xb3, 0x15, 0xf3, 0x0c, 0x5b, 0x94, 0x6d, 0x91, 0xb2, 0xc5, 0x68, - 0x68, 0x17, 0x56, 0xc7, 0xa6, 0xa1, 0xd2, 0xfe, 0x25, 0xda, 0x1f, 0xb4, 0xd1, 0x3e, 0xdc, 0xd1, - 0x35, 0xe3, 0xad, 0xa4, 0xe3, 0x33, 0xac, 0x4b, 0x36, 0x56, 0x5c, 0x4b, 0x73, 0x2e, 0x2a, 0xcb, - 0x94, 0x6d, 0x93, 0x74, 0x75, 0x49, 0x8f, 0xe8, 0x75, 0xa0, 0x03, 0xd8, 0xa2, 0x4c, 0x58, 0xb2, - 0xb5, 0xe9, 0x4c, 0xc7, 0xd2, 0x4c, 0xd6, 0x2c, 0xcd, 0x98, 0x54, 0x56, 0xa8, 0xc4, 0x1d, 0xd6, - 0x29, 0xd2, 0xbe, 0x01, 0xeb, 0x42, 0x5b, 0xb0, 0x3c, 0xb6, 0x24, 0xac, 0x5a, 0x95, 0x55, 0xca, - 0xb4, 0x34, 0xb6, 0x9a, 0xaa, 0x85, 0x1e, 0x02, 0x9c, 0x6a, 0x93, 0x53, 0xc9, 0x9e, 0x61, 0xac, - 0x56, 0x8a, 0xb4, 0xab, 0x48, 0x28, 0x22, 0x21, 0x90, 0x6e, 0xdd, 0x3c, 0x97, 0xb0, 0x81, 0xad, - 0xc9, 0x45, 0x05, 0x58, 0xb7, 0x6e, 0x9e, 0x37, 0x29, 0x81, 0x68, 0x51, 0x56, 0xcf, 0xb0, 0xe5, - 0x68, 0x36, 0x19, 0xbe, 0xc4, 0xb4, 0x18, 0x21, 0xa1, 0x8f, 0x01, 0x79, 0x53, 0xf5, 0xf4, 0x48, - 0x23, 0xd8, 0x1a, 0x5b, 0x19, 0xeb, 0xa9, 0x87, 0x1d, 0x64, 0x3c, 0x15, 0x8f, 0xdd, 0x89, 0xf4, - 0x16, 0x5f, 0xd8, 0x95, 0x32, 0x1b, 0x8f, 0x52, 0x5e, 0xe3, 0x0b, 0xb6, 0x9f, 0x96, 0x76, 0x26, - 0x2b, 0x17, 0x95, 0x75, 0x6f, 0x3f, 0x59, 0x13, 0xfd, 0x12, 0x2a, 0x4a, 0xb0, 0xff, 0x64, 0xac, - 0x13, 0x6d, 0xe2, 0x5a, 0xd4, 0x0f, 0x2b, 0x1b, 0x94, 0x75, 0x27, 0xec, 0xaf, 0x47, 0xbb, 0xd1, - 0x7b, 0xb0, 0x6e, 0x3b, 0xb2, 0xa3, 0x29, 0x92, 0xac, 0xaa, 0x16, 0xb6, 0xed, 0x0a, 0x47, 0x05, - 0xca, 0x8c, 0x5a, 0x65, 0x44, 0xfe, 0xaf, 0x8b, 0xf0, 0xe8, 0x72, 0x87, 0x27, 0xd3, 0xf3, 0x21, - 0x88, 0xb9, 0xad, 0x09, 0x7e, 0x13, 0x7d, 0x08, 0x9b, 0xc1, 0xb9, 0x22, 0x9d, 0x61, 0xcb, 0x26, - 0xf3, 0x22, 0x46, 0x57, 0x16, 0xb8, 0xa0, 0xe3, 0x0d, 0xa3, 0x13, 0x73, 0x9a, 0xca, 0x86, 0x7b, - 0x22, 0x2b, 0x8e, 0x6b, 0x61, 0x8b, 0x5a, 0x5d, 0x59, 0x88, 0xd1, 0xd0, 0x31, 0x20, 0xdb, 0x9d, - 0xcd, 0x4c, 0xcb, 0xc1, 0xaa, 0x14, 0x04, 0xbc, 0x45, 0x1a, 0x67, 0x9e, 0x5f, 0x15, 0xa4, 0x82, - 0x60, 0xb3, 0x19, 0x60, 0x04, 0x2e, 0x23, 0x02, 0xa7, 0xb8, 0x96, 0x85, 0x0d, 0x27, 0x84, 0x5d, - 0xba, 0x21, 0xec, 0x86, 0x87, 0x10, 0x80, 0xbe, 0x0f, 0x1b, 0x8a, 0x2e, 0xdb, 0xb6, 0x64, 0x9e, - 0x48, 0x2a, 0x26, 0x51, 0x80, 0x1a, 0xf7, 0x9a, 0x50, 0xa6, 0xe4, 0xfe, 0x49, 0x83, 0x12, 0x11, - 0x82, 0x45, 0xea, 0xe9, 0x2b, 0xd4, 0xd3, 0xe9, 0x37, 0x31, 0x09, 0xfb, 0xd4, 0xb4, 0x1c, 0x16, - 0x03, 0x56, 0x59, 0x8c, 0xa0, 0x14, 0x1a, 0x23, 0x9e, 0xc2, 0x9a, 0x66, 0x4b, 0xf2, 0x99, 0xac, - 0xe9, 0xd4, 0xb7, 0x98, 0x09, 0x97, 0x34, 0xbb, 0xea, 0x93, 0xd0, 0xaf, 0x60, 0xd7, 0x66, 0xb1, - 0xc7, 0x3f, 0x06, 0x25, 0x2f, 0xc0, 0x19, 0xf2, 0xcc, 0x33, 0xea, 0x1d, 0x8f, 0x23, 0x12, 0xab, - 0xb0, 0xd5, 0x93, 0x67, 0xe8, 0x2b, 0xb8, 0x9f, 0x21, 0x3c, 0x93, 0x0d, 0xd7, 0x33, 0xf9, 0x4a, - 0x9a, 0xf4, 0x40, 0x36, 0x5c, 0xf4, 0x4b, 0xb8, 0x97, 0x21, 0x3e, 0x31, 0x3c, 0x37, 0xd8, 0x4e, - 0x13, 0x6e, 0x19, 0xfc, 0x77, 0xc0, 0xc5, 0x8e, 0x75, 0x11, 0x3b, 0xa8, 0x06, 0xeb, 0xf1, 0xa3, - 0xbe, 0x92, 0x7f, 0x52, 0x78, 0x5e, 0x3a, 0xd8, 0x8d, 0xed, 0x4d, 0x8c, 0x45, 0x48, 0x48, 0x10, - 0x25, 0xd3, 0xd3, 0x93, 0x25, 0x2b, 0xf4, 0x9b, 0xff, 0x37, 0x80, 0x72, 0x8c, 0x0d, 0xad, 0xc3, - 0x82, 0xc6, 0xa2, 0x66, 0x59, 0x58, 0xd0, 0x54, 0x62, 0xdb, 0xa6, 0x81, 0xc5, 0x53, 0xd3, 0x3f, - 0x0b, 0xfc, 0x26, 0x89, 0x6c, 0x9a, 0x4d, 0xa4, 0xce, 0xfc, 0x00, 0x19, 0xb4, 0xd1, 0x03, 0x28, - 0x6a, 0xd3, 0xa9, 0xeb, 0x44, 0xc2, 0x62, 0x48, 0x40, 0x5d, 0x58, 0xf7, 0xd6, 0x2e, 0x3a, 0x32, - 0xb1, 0x42, 0xcf, 0xd2, 0xf8, 0xb4, 0xd5, 0x88, 0x31, 0xce, 0x76, 0x4e, 0x48, 0xc8, 0xa2, 0x6f, - 0x01, 0xb9, 0xf6, 0xb8, 0x25, 0xab, 0x13, 0xec, 0x47, 0x67, 0xac, 0x52, 0x3b, 0x2b, 0x1d, 0xbc, - 0x9f, 0x86, 0x38, 0x12, 0x6b, 0x09, 0xee, 0x76, 0x4e, 0x48, 0xc1, 0x40, 0x32, 0x6c, 0x05, 0xd4, - 0x06, 0x09, 0xea, 0x3e, 0xf8, 0x0a, 0x05, 0xff, 0xe9, 0xa5, 0xe0, 0x51, 0x81, 0x76, 0x4e, 0x48, - 0x47, 0x42, 0x1d, 0x28, 0x93, 0xa4, 0xb0, 0x3a, 0xf0, 0x35, 0xb1, 0x4a, 0xa1, 0x9f, 0xa6, 0x41, - 0x1f, 0x47, 0x19, 0xdb, 0x39, 0x21, 0x2e, 0x49, 0xf4, 0x40, 0x08, 0xc1, 0xf4, 0xab, 0xb6, 0xe8, - 0xc8, 0xd4, 0x2f, 0x32, 0xf4, 0x70, 0x3c, 0xc7, 0x4d, 0xf4, 0x30, 0x8f, 0x41, 0x73, 0x2b, 0xfb, - 0xb4, 0x6b, 0x4e, 0x34, 0x83, 0xba, 0x4d, 0xe9, 0xe0, 0x41, 0xea, 0x4e, 0x89, 0x6d, 0xca, 0xd3, - 0xce, 0x09, 0x01, 0x3f, 0x12, 0x80, 0x53, 0x4f, 0x95, 0x59, 0x17, 0xcb, 0x36, 0x6e, 0x59, 0xb2, - 0x41, 0xd6, 0x58, 0xa2, 0x18, 0xcf, 0xd2, 0x30, 0x1a, 0xed, 0xfa, 0x20, 0xca, 0xdb, 0xce, 0x09, - 0x73, 0xf2, 0xe8, 0x10, 0xd6, 0x26, 0x96, 0xe9, 0xce, 0x04, 0xac, 0x60, 0x62, 0x7d, 0x6b, 0x14, - 0xef, 0x49, 0x1a, 0x5e, 0x2b, 0xc2, 0xd7, 0xce, 0x09, 0x31, 0x39, 0x34, 0x82, 0xcd, 0x68, 0xfb, - 0xc8, 0xd5, 0x1d, 0x8d, 0x1e, 0x3e, 0xa5, 0x83, 0xf7, 0xae, 0x02, 0xa3, 0xcc, 0xed, 0x9c, 0x30, - 0x8f, 0x80, 0x5e, 0xc0, 0xf2, 0x64, 0xa6, 0x99, 0x1d, 0x83, 0x1e, 0x56, 0x19, 0x4e, 0xda, 0x1a, - 0x74, 0xfa, 0x1d, 0xa2, 0x2a, 0x8f, 0x17, 0x35, 0x00, 0xc6, 0xb2, 0x7d, 0x2a, 0x2a, 0x96, 0x36, - 0x73, 0xe8, 0xd9, 0x95, 0x74, 0x08, 0x2f, 0x1c, 0x90, 0xed, 0xae, 0x05, 0x9c, 0xed, 0xbc, 0x10, - 0x91, 0x43, 0x55, 0x28, 0x9e, 0x6a, 0xaa, 0x07, 0xc2, 0xa5, 0xd8, 0x52, 0x04, 0xa4, 0xdd, 0x69, - 0x04, 0x18, 0xa1, 0x14, 0x52, 0x60, 0x5b, 0xc5, 0x33, 0xdd, 0xbc, 0xf0, 0xc3, 0xb8, 0x9f, 0x67, - 0x57, 0x36, 0x53, 0xcc, 0x9e, 0xe1, 0x35, 0x52, 0x05, 0xda, 0x79, 0x21, 0x03, 0x0a, 0xed, 0x41, - 0x41, 0x37, 0x27, 0x15, 0x44, 0x11, 0xb7, 0x53, 0x10, 0xbb, 0xe6, 0xa4, 0x9d, 0x17, 0x08, 0x13, - 0x7a, 0x09, 0x2b, 0x44, 0x47, 0x7d, 0xd7, 0xa9, 0xdc, 0x49, 0x51, 0x28, 0xe3, 0x27, 0xfa, 0xec, - 0xbb, 0x64, 0x29, 0x3e, 0x33, 0xfa, 0x12, 0x8a, 0x74, 0x73, 0x44, 0x6c, 0xa8, 0x95, 0xbb, 0x29, - 0x76, 0xeb, 0x49, 0xfa, 0x3c, 0x44, 0x0d, 0x81, 0x40, 0xad, 0x08, 0x2b, 0xde, 0x56, 0xd5, 0x56, - 0x61, 0x99, 0xb1, 0xf2, 0x3b, 0xb0, 0x95, 0x1a, 0x96, 0xf8, 0xfb, 0x70, 0x2f, 0x33, 0xba, 0xf0, - 0x8f, 0xe0, 0xc1, 0x65, 0xd1, 0x81, 0xdf, 0x86, 0xbb, 0x69, 0x2e, 0x1e, 0x01, 0x9d, 0x77, 0x55, - 0xfe, 0x13, 0xd8, 0x48, 0xf8, 0x1d, 0x89, 0xba, 0x3a, 0xf9, 0x18, 0xd9, 0x5e, 0xaa, 0x5f, 0x14, - 0x42, 0x02, 0x7f, 0x0f, 0x76, 0x32, 0x9c, 0x8c, 0xef, 0xc0, 0x9d, 0x14, 0x13, 0x27, 0x78, 0x54, - 0x1f, 0x91, 0x4b, 0x57, 0x48, 0x40, 0x77, 0x61, 0xe9, 0x4c, 0xd6, 0x5d, 0x76, 0xa0, 0x2c, 0x09, - 0xac, 0xc1, 0xff, 0x25, 0x0f, 0x95, 0x2c, 0x77, 0xb9, 0x02, 0x70, 0x1b, 0x96, 0x29, 0x86, 0x5d, - 0x29, 0x3c, 0x29, 0x3c, 0x5f, 0x12, 0xbc, 0x16, 0x7a, 0xe9, 0x5d, 0x36, 0x16, 0xe9, 0x65, 0x23, - 0xee, 0x13, 0x73, 0x63, 0x84, 0xd7, 0x0c, 0xfe, 0xbf, 0xf2, 0xc1, 0xe1, 0xc6, 0xbc, 0x0d, 0xdd, - 0x87, 0x22, 0x31, 0x0e, 0x96, 0x52, 0xb0, 0xf1, 0x57, 0x09, 0x81, 0x0e, 0xff, 0x15, 0xc0, 0xcc, - 0xd5, 0xf5, 0xd1, 0xac, 0x61, 0x9e, 0xb3, 0x24, 0x6d, 0xfd, 0xe0, 0x61, 0x7c, 0x30, 0x8a, 0x32, - 0x08, 0x98, 0x84, 0x88, 0x00, 0xfa, 0x0c, 0x80, 0x79, 0x72, 0x53, 0x9d, 0xf8, 0x17, 0xa3, 0x9d, - 0x14, 0x71, 0xd2, 0x2d, 0x44, 0x58, 0xd1, 0x07, 0xb0, 0xa1, 0xe2, 0xb1, 0xe9, 0x1a, 0x0a, 0x96, - 0xa6, 0x9a, 0xae, 0x6b, 0x2c, 0x9f, 0x2b, 0x08, 0xeb, 0x3e, 0xf9, 0x88, 0x52, 0xf9, 0xcf, 0x60, - 0x2b, 0x35, 0x04, 0xa0, 0x47, 0x00, 0x36, 0xfd, 0x8a, 0xe8, 0x35, 0x42, 0xe1, 0x5f, 0xc2, 0xdd, - 0x34, 0xb7, 0xbf, 0x52, 0xee, 0x7f, 0xf2, 0xf0, 0xe0, 0x32, 0xff, 0x26, 0x19, 0xab, 0x93, 0x72, - 0x31, 0x8f, 0xd2, 0xd0, 0x2b, 0x6f, 0xf7, 0x98, 0x42, 0x5f, 0x5e, 0x3b, 0x78, 0xec, 0xfb, 0x1f, - 0x91, 0x1d, 0xc5, 0x61, 0x21, 0x80, 0x50, 0xd1, 0x26, 0x94, 0x0f, 0x47, 0xdd, 0xae, 0x24, 0x36, - 0x87, 0xc3, 0x4e, 0xaf, 0x25, 0x72, 0x39, 0x54, 0x82, 0x95, 0x5e, 0x73, 0x78, 0xdc, 0x17, 0x5e, - 0x73, 0x79, 0xb4, 0x0a, 0x8b, 0xc7, 0x9d, 0xc3, 0x0e, 0xb7, 0x80, 0x56, 0xa0, 0x30, 0x12, 0x6b, - 0x5c, 0x01, 0x95, 0xa1, 0x58, 0xeb, 0x8e, 0x9a, 0xc3, 0x7e, 0x7f, 0xd8, 0xe6, 0x16, 0xd1, 0x1d, - 0xd8, 0x18, 0x0a, 0x9d, 0x56, 0xab, 0x29, 0x48, 0xd5, 0xfa, 0xb0, 0xd3, 0xef, 0x89, 0xdc, 0x12, - 0x5f, 0x82, 0x62, 0x10, 0x84, 0xf8, 0x3f, 0x40, 0x39, 0x16, 0x61, 0x2e, 0x37, 0xa2, 0x4f, 0xa2, - 0x4e, 0xb1, 0x7e, 0x70, 0x6f, 0xce, 0x00, 0xfa, 0xae, 0xf3, 0x86, 0x30, 0xf8, 0xfe, 0xd2, 0x84, - 0x8d, 0x44, 0x18, 0xba, 0x95, 0xdb, 0x9d, 0xc3, 0x2e, 0x89, 0x11, 0xef, 0x50, 0x40, 0xf9, 0xc5, - 0x5c, 0x01, 0x25, 0x3e, 0xf9, 0x63, 0xed, 0x50, 0x4b, 0xa9, 0x9d, 0xfc, 0x4b, 0x01, 0xd6, 0xa2, - 0x5d, 0x41, 0x2e, 0x9f, 0x8f, 0xe4, 0xf2, 0xbb, 0xb0, 0xaa, 0x6a, 0x36, 0xc9, 0xfd, 0x54, 0x2f, - 0x8b, 0x0c, 0xda, 0xc4, 0x08, 0x2d, 0x3c, 0x71, 0x75, 0xd9, 0x31, 0xad, 0x0b, 0xaf, 0x38, 0x16, - 0xa1, 0xa0, 0xaf, 0x61, 0x8d, 0xa4, 0xc7, 0x9a, 0x31, 0x91, 0xa6, 0xa6, 0xea, 0x47, 0x81, 0x07, - 0x73, 0x73, 0x3b, 0x66, 0x4c, 0x47, 0xa6, 0x8a, 0x85, 0xd2, 0x79, 0xd8, 0x40, 0x2f, 0xa1, 0x28, - 0xbb, 0xce, 0x29, 0x93, 0x5e, 0x4a, 0xd9, 0x16, 0x22, 0x5d, 0x75, 0x9d, 0x53, 0x2a, 0xba, 0x2a, - 0x7b, 0x5f, 0x24, 0xf3, 0x55, 0x4e, 0x65, 0xc3, 0xc0, 0x3a, 0x4d, 0x26, 0xcb, 0x82, 0xdf, 0x44, - 0xfb, 0xb0, 0x2c, 0xcf, 0xa4, 0x9a, 0x28, 0x7a, 0x89, 0xe0, 0xce, 0x1c, 0x5c, 0x4d, 0x14, 0xeb, - 0x27, 0x13, 0x61, 0x49, 0x9e, 0xd5, 0x44, 0x11, 0x7d, 0x4d, 0xae, 0x41, 0x1a, 0xb9, 0x5a, 0xd5, - 0x44, 0x51, 0xd2, 0x35, 0xdb, 0xa9, 0xac, 0xd2, 0xf4, 0x3d, 0x53, 0xb0, 0xcc, 0xf8, 0x6b, 0xa2, - 0xd8, 0xd5, 0x6c, 0x6a, 0x72, 0xa7, 0x9a, 0x8a, 0x25, 0xdb, 0xd6, 0xfc, 0xcb, 0xfa, 0x2a, 0x21, - 0x88, 0xb6, 0xa6, 0x92, 0xb0, 0x69, 0xe0, 0xef, 0xa7, 0xa6, 0xe1, 0xdd, 0x9b, 0xbd, 0x16, 0xff, - 0xef, 0x79, 0x28, 0xd2, 0x9d, 0x71, 0x88, 0xab, 0xee, 0xc3, 0x22, 0x55, 0x40, 0x9e, 0x2a, 0x60, - 0x77, 0x7e, 0x6b, 0x09, 0x17, 0xd5, 0x00, 0xe5, 0x8b, 0xae, 0x7e, 0x21, 0xbe, 0x7a, 0x04, 0x8b, - 0x74, 0x1e, 0x6c, 0xab, 0xe8, 0x37, 0xaa, 0x43, 0xf2, 0xee, 0xe7, 0xdd, 0x49, 0x2f, 0xb1, 0xa1, - 0xa4, 0x04, 0x7f, 0x00, 0x10, 0xaa, 0x80, 0x0c, 0x23, 0x8a, 0x9d, 0x86, 0x6f, 0x47, 0xe4, 0x1b, - 0x71, 0x50, 0x18, 0x88, 0xaf, 0xbd, 0x1b, 0x0c, 0xf9, 0xe4, 0x9f, 0x42, 0x59, 0x74, 0x2c, 0xb2, - 0xd5, 0xd8, 0xb6, 0x89, 0xa9, 0x73, 0x50, 0x98, 0xda, 0x13, 0xbf, 0x52, 0x36, 0xb5, 0x27, 0xfc, - 0xcf, 0x00, 0xc5, 0x58, 0xaa, 0x96, 0x25, 0x5f, 0x10, 0x93, 0x9c, 0xda, 0x13, 0xfa, 0x4d, 0xef, - 0x52, 0x45, 0x21, 0x68, 0xf3, 0xfb, 0xb0, 0xd6, 0x3c, 0xc3, 0x86, 0xe3, 0x79, 0x13, 0x31, 0x51, - 0xb2, 0x69, 0xd8, 0x20, 0x41, 0x87, 0x42, 0x17, 0x84, 0x08, 0x85, 0x97, 0x01, 0x28, 0x3f, 0x75, - 0x6c, 0xb4, 0x0b, 0x2b, 0x8e, 0x4d, 0x07, 0x64, 0xb3, 0x68, 0xe7, 0x04, 0x9f, 0x80, 0xb6, 0x61, - 0xc9, 0x19, 0x9b, 0x26, 0xd3, 0xe9, 0x6a, 0x3b, 0x27, 0xb0, 0x26, 0xaa, 0xc0, 0xb2, 0xa3, 0x19, - 0xce, 0xcb, 0x17, 0x54, 0xab, 0x05, 0x92, 0x16, 0xb2, 0x76, 0x6d, 0x09, 0x0a, 0x67, 0xb2, 0xce, - 0x77, 0x61, 0x89, 0x0e, 0x41, 0xd4, 0xe2, 0x84, 0xb3, 0x60, 0xf5, 0xb4, 0x4f, 0x82, 0x83, 0x73, - 0x21, 0xc5, 0xac, 0xc2, 0xa9, 0xf9, 0x27, 0x2a, 0xff, 0x47, 0xb8, 0x4b, 0x7c, 0xbf, 0xa1, 0x59, - 0x7d, 0xeb, 0x50, 0xd3, 0xb1, 0xbf, 0x50, 0x0e, 0x0a, 0xaa, 0xe6, 0xa7, 0x0e, 0xe4, 0x93, 0x18, - 0xd7, 0xcc, 0xc2, 0x27, 0xda, 0xf7, 0x9e, 0xd2, 0xbd, 0x16, 0x51, 0x89, 0x69, 0xe8, 0x17, 0x87, - 0xa6, 0xae, 0x7a, 0x95, 0x8a, 0x55, 0x21, 0x42, 0x21, 0x67, 0x55, 0x62, 0x04, 0x7b, 0x66, 0x1a, - 0x36, 0x66, 0xee, 0x6e, 0xbb, 0xba, 0x33, 0x90, 0x83, 0x52, 0x7b, 0x84, 0xc2, 0xff, 0x73, 0x1e, - 0x36, 0x04, 0x2c, 0xab, 0xd1, 0x69, 0xfd, 0x02, 0x96, 0x4f, 0xd8, 0x40, 0xf9, 0x94, 0x53, 0xb9, - 0xaa, 0x28, 0xd8, 0xb6, 0xb5, 0xb1, 0x8e, 0xd9, 0xd8, 0x82, 0xc7, 0x4c, 0xb6, 0xf8, 0x44, 0xd3, - 0xb1, 0x11, 0x5e, 0x7a, 0x83, 0x36, 0x89, 0xa2, 0x36, 0x39, 0x0c, 0x99, 0xbe, 0x05, 0xd6, 0x20, - 0xeb, 0xd7, 0xb1, 0xe1, 0x1d, 0xbf, 0xe4, 0x93, 0x6f, 0x00, 0x17, 0xce, 0xc6, 0x5b, 0xc2, 0x03, - 0x28, 0x5a, 0x58, 0x56, 0xeb, 0xa6, 0x6b, 0x38, 0xde, 0x3e, 0x84, 0x04, 0xb2, 0x41, 0xaa, 0xec, - 0xc8, 0x74, 0xc4, 0x35, 0x81, 0x7e, 0xf3, 0xff, 0x99, 0x07, 0xee, 0xd8, 0xd2, 0x1c, 0xfc, 0x23, - 0xaf, 0x6a, 0x9b, 0x04, 0xa6, 0x19, 0x49, 0x77, 0xd9, 0x8e, 0x78, 0x2d, 0x5a, 0x59, 0x72, 0x6d, - 0xa7, 0x67, 0x3a, 0xcd, 0xef, 0x49, 0xf4, 0xf1, 0x0a, 0x95, 0x51, 0x5a, 0x30, 0xef, 0xa5, 0xc8, - 0xbc, 0xdf, 0x83, 0x0d, 0x32, 0xe3, 0x8e, 0x71, 0x62, 0xfa, 0xb3, 0x46, 0xb0, 0x38, 0x0b, 0x77, - 0x8e, 0x7e, 0xf3, 0x7f, 0x02, 0x2e, 0x64, 0xf3, 0x94, 0x94, 0x76, 0x0c, 0x90, 0xc8, 0xa1, 0xfd, - 0x3d, 0x9b, 0x76, 0x41, 0xa0, 0xdf, 0x84, 0x46, 0xe3, 0x12, 0x2b, 0x76, 0x05, 0xb1, 0x67, 0x6a, - 0xaa, 0x43, 0xcd, 0xab, 0x0d, 0x17, 0x04, 0xbf, 0x49, 0xb6, 0x4d, 0xb3, 0x1b, 0x9a, 0xe5, 0x95, - 0x52, 0x59, 0x83, 0xff, 0x2d, 0x70, 0x41, 0x52, 0x13, 0xf1, 0x59, 0x96, 0xc9, 0x44, 0xed, 0x2c, - 0xa4, 0xa0, 0xf7, 0x61, 0xdd, 0xd1, 0xa6, 0xd8, 0x74, 0x1d, 0x11, 0x2b, 0xa6, 0xa1, 0xda, 0x5e, - 0x98, 0x4b, 0x50, 0xf9, 0x47, 0xb0, 0x16, 0x60, 0xbf, 0x32, 0xc7, 0xc9, 0xfa, 0x08, 0xff, 0x2c, - 0x32, 0xf6, 0x2b, 0x73, 0x4c, 0xc3, 0x35, 0x07, 0x05, 0x4d, 0x65, 0x25, 0x9a, 0xb2, 0x40, 0x3e, - 0xf9, 0x37, 0x50, 0x69, 0x77, 0x1a, 0x82, 0x6b, 0x18, 0x9a, 0x31, 0x79, 0x65, 0x8e, 0x69, 0xb4, - 0x15, 0xa8, 0xd5, 0x47, 0x10, 0x0b, 0xb4, 0xe2, 0x82, 0x60, 0xf1, 0x6c, 0xda, 0x51, 0x7d, 0x2d, - 0x91, 0x6f, 0xb2, 0xb1, 0xb6, 0xe9, 0x5a, 0x0a, 0xf6, 0xa2, 0xae, 0xd7, 0xe2, 0xff, 0x04, 0x1b, - 0x91, 0x95, 0x53, 0xb8, 0x0f, 0xa1, 0xf0, 0x9d, 0x39, 0xf6, 0xde, 0x2d, 0xe2, 0xe1, 0x37, 0x3a, - 0x51, 0x81, 0x70, 0x11, 0x2d, 0x69, 0xf6, 0xa1, 0x66, 0x68, 0xf6, 0x69, 0x70, 0x34, 0x47, 0x28, - 0xa1, 0xb7, 0xbe, 0xb2, 0x4d, 0x23, 0x3c, 0x9c, 0x7d, 0x0a, 0xbf, 0x0f, 0xa5, 0x6e, 0xb3, 0x11, - 0x9c, 0xfd, 0x8f, 0xa1, 0x34, 0xa6, 0x15, 0x6d, 0x25, 0xf0, 0x8d, 0xb2, 0x00, 0x94, 0x44, 0x9d, - 0x83, 0xff, 0x1e, 0xee, 0x8d, 0xc4, 0xda, 0x3b, 0x64, 0x29, 0x9f, 0xcd, 0x65, 0x29, 0xf1, 0x77, - 0x26, 0x76, 0xbb, 0x4a, 0xc9, 0x53, 0xfe, 0xba, 0x04, 0xeb, 0xf1, 0x4e, 0x62, 0x66, 0xd8, 0x60, - 0x49, 0x89, 0xf7, 0x4a, 0xe0, 0x35, 0xc9, 0x06, 0x9e, 0x69, 0xaa, 0x7f, 0xce, 0x9c, 0x69, 0x2a, - 0x7b, 0x80, 0xf1, 0xcf, 0x3c, 0xf2, 0x39, 0x57, 0xad, 0x65, 0xaf, 0x18, 0xf1, 0x6a, 0x2d, 0xad, - 0x5b, 0x9b, 0xaa, 0xab, 0x38, 0xde, 0x23, 0x86, 0xdf, 0xa4, 0x1b, 0x8a, 0x2d, 0x4d, 0x66, 0xb9, - 0x05, 0xd9, 0x50, 0xda, 0x42, 0x8f, 0xa0, 0xe4, 0xda, 0x58, 0xaa, 0x37, 0xea, 0x52, 0xb3, 0x7e, - 0xe4, 0x15, 0xf6, 0x8b, 0xae, 0x8d, 0xeb, 0x8d, 0x7a, 0xb3, 0x7e, 0x44, 0x32, 0x01, 0xd2, 0x2f, - 0xf4, 0x1a, 0x1d, 0xd1, 0xab, 0xe8, 0xaf, 0xba, 0x36, 0xa6, 0x6d, 0xf4, 0x1c, 0x38, 0xd2, 0xd9, - 0xee, 0x34, 0xa4, 0xd7, 0xcd, 0xdf, 0xd4, 0xfa, 0x55, 0xa1, 0xe1, 0x65, 0x0b, 0xeb, 0xae, 0x8d, - 0xdb, 0x9d, 0x86, 0x4f, 0x45, 0x3c, 0x94, 0x7d, 0xce, 0xa3, 0xfe, 0x48, 0x6c, 0x7a, 0xd5, 0xd0, - 0x12, 0x63, 0xa3, 0x24, 0x7f, 0x2a, 0x84, 0x47, 0xa8, 0x1e, 0x7b, 0x15, 0xcf, 0x22, 0xe3, 0x10, - 0xaa, 0xc7, 0x68, 0x07, 0x56, 0x48, 0xff, 0xe8, 0x48, 0xf4, 0x0a, 0x9a, 0xcb, 0xae, 0x8d, 0x47, - 0x47, 0x22, 0x7a, 0x08, 0x40, 0x3a, 0xc4, 0xa6, 0xd0, 0xa9, 0x76, 0xfd, 0x62, 0xbe, 0x6b, 0x63, - 0x46, 0x40, 0xaf, 0x60, 0xdd, 0x32, 0x54, 0xcd, 0x0e, 0xeb, 0xcc, 0xeb, 0x29, 0xcf, 0x64, 0xf1, - 0xbd, 0x6a, 0x3a, 0xa7, 0xd8, 0x32, 0xb0, 0x23, 0x94, 0xa9, 0x68, 0xb0, 0x85, 0x47, 0xc0, 0x29, - 0xaa, 0x22, 0x61, 0x65, 0x1a, 0xa2, 0x6d, 0x5c, 0x1f, 0x6d, 0x5d, 0x51, 0x95, 0xa6, 0x32, 0x0d, - 0xe0, 0xaa, 0xb0, 0xe6, 0x4e, 0x23, 0x13, 0xe3, 0x52, 0x1e, 0x12, 0xe3, 0x50, 0xa3, 0x23, 0x51, - 0x28, 0xb9, 0xd3, 0x70, 0x46, 0x9f, 0xc2, 0x96, 0x8a, 0xcf, 0x24, 0x12, 0x17, 0xa5, 0x53, 0x4d, - 0x95, 0xde, 0xe2, 0x8b, 0xb1, 0x29, 0x5b, 0x2a, 0x2d, 0x75, 0x14, 0x05, 0xa4, 0xe2, 0x33, 0x12, - 0x7f, 0xda, 0x9a, 0xfa, 0xda, 0xeb, 0x41, 0x1f, 0x02, 0x8a, 0x89, 0x4c, 0x4d, 0xd7, 0xc6, 0xb4, - 0xd4, 0x51, 0x14, 0x36, 0x42, 0xfe, 0x23, 0x42, 0x46, 0x1f, 0x00, 0x17, 0x63, 0xb6, 0xe4, 0x73, - 0x5a, 0xdb, 0x28, 0x0a, 0xe5, 0x90, 0x55, 0x90, 0xcf, 0xf9, 0x01, 0x6c, 0xa7, 0xaf, 0x9a, 0x66, - 0x93, 0xa6, 0xed, 0xd0, 0x67, 0x0f, 0xff, 0x02, 0x43, 0x08, 0x55, 0x55, 0xb5, 0xd0, 0x3d, 0x58, - 0x25, 0xf8, 0xb4, 0x8f, 0xd9, 0xff, 0x8a, 0x8a, 0xcf, 0x48, 0x17, 0xff, 0x15, 0x6c, 0xce, 0x2d, - 0x9e, 0x44, 0x64, 0x45, 0xb5, 0xcc, 0xa9, 0xe7, 0x42, 0xac, 0x41, 0x62, 0x18, 0x39, 0x94, 0xfc, - 0x5a, 0x33, 0xf9, 0xe6, 0xff, 0x92, 0x87, 0x47, 0x81, 0xe6, 0x6f, 0x1f, 0x01, 0x6a, 0x73, 0x11, - 0x20, 0x5e, 0xdc, 0xf4, 0x87, 0xe8, 0x18, 0x0e, 0xb6, 0x4e, 0x64, 0x05, 0xa7, 0x04, 0x03, 0x09, - 0x9e, 0xb2, 0x4b, 0x27, 0x56, 0x33, 0xd9, 0xd1, 0x17, 0xb0, 0x48, 0x53, 0x75, 0x56, 0x69, 0xbf, - 0xee, 0x20, 0x54, 0x86, 0xff, 0x73, 0x01, 0xee, 0x65, 0x23, 0xa7, 0x9d, 0x8d, 0x5f, 0x7b, 0xe7, - 0x20, 0xbb, 0x37, 0x7e, 0x78, 0xbd, 0xd1, 0xf6, 0x23, 0x09, 0x3b, 0x09, 0xe5, 0x33, 0xef, 0xd1, - 0xea, 0x85, 0x1f, 0xaa, 0x43, 0x0a, 0xc9, 0x1b, 0x0c, 0xec, 0x4c, 0x65, 0xfb, 0xed, 0x0b, 0x2f, - 0x56, 0x05, 0xed, 0x68, 0x24, 0x5c, 0x8a, 0x47, 0xc2, 0x3e, 0x20, 0xf5, 0x54, 0x99, 0xb1, 0xc7, - 0x89, 0x20, 0xb7, 0x67, 0xc5, 0xf5, 0xc7, 0xb1, 0x49, 0x36, 0xda, 0xf5, 0x41, 0x9c, 0x4d, 0x48, - 0x11, 0x45, 0xcf, 0xa0, 0xec, 0x6f, 0x43, 0xc7, 0x18, 0xd9, 0xd8, 0x0b, 0x71, 0x71, 0x22, 0x5f, - 0x87, 0x45, 0x7a, 0x07, 0x03, 0x58, 0x3e, 0xaa, 0xf6, 0x46, 0xd5, 0x2e, 0x97, 0x43, 0x1b, 0x50, - 0x22, 0x63, 0x48, 0xf5, 0x6e, 0xa7, 0xd9, 0x1b, 0x72, 0xf9, 0x80, 0x20, 0x36, 0x85, 0x37, 0x4d, - 0x81, 0x5b, 0x20, 0x77, 0xfb, 0x51, 0xef, 0xa8, 0xda, 0xab, 0xb6, 0x9a, 0x0d, 0xae, 0xc0, 0xff, - 0x5f, 0x01, 0xd0, 0xfc, 0xac, 0xc2, 0x6c, 0x7e, 0x60, 0x5a, 0xc1, 0x19, 0x15, 0x52, 0xd0, 0x73, - 0xd8, 0x60, 0xad, 0x40, 0xdd, 0xfe, 0xef, 0x3b, 0x12, 0x64, 0x5a, 0x6f, 0xc3, 0xb2, 0x4d, 0xb3, - 0x3a, 0x4f, 0xe3, 0x21, 0x01, 0xed, 0x01, 0x67, 0x98, 0x0e, 0xb9, 0x58, 0x9a, 0x96, 0xe6, 0xc8, - 0xf4, 0x9d, 0x84, 0x25, 0x5e, 0x73, 0x74, 0xb4, 0x0f, 0x48, 0x35, 0x7b, 0xa6, 0x53, 0xd3, 0x0c, - 0x35, 0x1c, 0x96, 0xed, 0x45, 0x4a, 0x0f, 0xc9, 0x5e, 0x14, 0x59, 0xd7, 0xc7, 0xb2, 0xf2, 0xd6, - 0xab, 0xf5, 0xb2, 0x63, 0x24, 0x41, 0x45, 0x2f, 0x60, 0xd9, 0x92, 0x8d, 0x09, 0xb6, 0x2b, 0x2b, - 0xd4, 0x8a, 0x1f, 0x64, 0x6c, 0x99, 0x40, 0x98, 0x04, 0x8f, 0x17, 0x1d, 0xc2, 0x8a, 0x39, 0x63, - 0xcf, 0x4c, 0xec, 0x9e, 0xfa, 0xd1, 0x15, 0x3b, 0xbd, 0xdf, 0x67, 0xec, 0x4d, 0xc3, 0xb1, 0x2e, - 0x04, 0x5f, 0x18, 0xd5, 0xa1, 0xc4, 0xde, 0x52, 0xdb, 0xa6, 0xed, 0xd8, 0x95, 0x22, 0xc5, 0x7a, - 0x9a, 0x85, 0x15, 0x70, 0x0a, 0x51, 0xa9, 0xdd, 0x2f, 0x60, 0x2d, 0x8a, 0x4e, 0x4e, 0xe2, 0xb7, - 0xf8, 0xc2, 0xdb, 0x37, 0xf2, 0x19, 0xaf, 0x88, 0x14, 0xbd, 0x8a, 0xc8, 0x17, 0x0b, 0x9f, 0xe7, - 0x79, 0x13, 0x36, 0x12, 0x6b, 0xa4, 0x19, 0x0d, 0xf9, 0xe8, 0x9a, 0xe7, 0x41, 0x91, 0x34, 0x42, - 0x09, 0xfa, 0x47, 0xb3, 0x19, 0xf6, 0x23, 0x60, 0x84, 0x12, 0xec, 0x39, 0xcd, 0x4e, 0xa3, 0x7b, - 0x4e, 0x08, 0xfc, 0xe7, 0x70, 0x37, 0x6d, 0x45, 0xf4, 0x56, 0x2a, 0x2b, 0xc1, 0xad, 0x54, 0x56, - 0x68, 0xd6, 0x37, 0xf3, 0xf0, 0x17, 0xb4, 0x19, 0xbf, 0x02, 0x4b, 0xcd, 0xe9, 0xcc, 0xb9, 0xd8, - 0xfb, 0x3c, 0xf2, 0xd3, 0x86, 0xf9, 0x5f, 0x50, 0xa0, 0x15, 0x28, 0xf4, 0xaa, 0x03, 0x2e, 0x87, - 0x56, 0x61, 0x71, 0x50, 0xed, 0x8d, 0xb8, 0x3c, 0x5a, 0x86, 0x85, 0x56, 0x8f, 0x5b, 0xd8, 0x7b, - 0x05, 0x5b, 0xa9, 0xe5, 0x50, 0xb4, 0x06, 0xab, 0x62, 0xf3, 0x9b, 0x51, 0xb3, 0x57, 0x6f, 0x72, - 0x39, 0x82, 0x50, 0xed, 0x35, 0x98, 0x5c, 0x9f, 0xb8, 0x0d, 0x82, 0xf5, 0xe6, 0xb7, 0xd5, 0xfa, - 0x50, 0x0a, 0x98, 0x0a, 0x7b, 0x1f, 0x03, 0x97, 0xac, 0x76, 0x12, 0xfe, 0x91, 0x37, 0x72, 0xa3, - 0x7f, 0xdc, 0xe3, 0xf2, 0x04, 0xaa, 0x7f, 0x78, 0xc8, 0x2d, 0xec, 0x7d, 0x02, 0x10, 0x56, 0x37, - 0x89, 0xd7, 0x0a, 0x1d, 0xb1, 0xd3, 0x6b, 0xb1, 0x7a, 0xdc, 0x61, 0xb5, 0xdb, 0x25, 0x0d, 0x5a, - 0x8f, 0xab, 0xf5, 0x87, 0x6d, 0x6e, 0x61, 0xef, 0x63, 0x58, 0x8b, 0x56, 0xc3, 0x08, 0x52, 0xb7, - 0x7f, 0xcc, 0xc0, 0xdb, 0x9d, 0x56, 0x9b, 0xcb, 0x13, 0x94, 0x61, 0xbf, 0xd5, 0xea, 0x36, 0xb9, - 0x85, 0xbd, 0x06, 0x6c, 0x24, 0x6a, 0x3c, 0x04, 0x78, 0xd4, 0x7b, 0xdd, 0x23, 0x13, 0xc9, 0x91, - 0xa9, 0x55, 0x07, 0x6c, 0x42, 0xe2, 0xb0, 0xca, 0x2d, 0xa0, 0x3b, 0xb0, 0x21, 0x0e, 0xab, 0xd2, - 0x61, 0xb5, 0xd3, 0xed, 0xbf, 0x69, 0x0a, 0x52, 0x75, 0xc0, 0x15, 0xf6, 0x1a, 0x50, 0x8e, 0x95, - 0x3a, 0xd0, 0x16, 0x6c, 0x12, 0xae, 0x5e, 0x7f, 0x28, 0xd5, 0xfb, 0xbd, 0x5e, 0xb3, 0x3e, 0x6c, - 0x36, 0xb8, 0x1c, 0x2a, 0xc2, 0x52, 0x75, 0x20, 0x8d, 0x08, 0xe0, 0x26, 0x94, 0x09, 0x47, 0xd8, - 0xbb, 0xb0, 0xf7, 0x3e, 0x2b, 0x78, 0xf9, 0x15, 0x23, 0xa2, 0xdd, 0xe3, 0x41, 0xf5, 0x40, 0x1a, - 0x88, 0xaf, 0xd9, 0xfc, 0xfb, 0x83, 0x66, 0x8f, 0xcb, 0xef, 0xfd, 0x0d, 0x70, 0xc9, 0x4b, 0x1c, - 0x99, 0xdf, 0xf0, 0x88, 0xe8, 0x90, 0x83, 0xb5, 0x5a, 0x55, 0x6c, 0x4b, 0x62, 0x5d, 0xe8, 0x0c, - 0x86, 0x22, 0x8b, 0x66, 0x24, 0xd5, 0xf2, 0x09, 0x0b, 0x07, 0xff, 0xf1, 0x19, 0x2c, 0x0f, 0x5e, - 0x1c, 0xf7, 0x06, 0x9f, 0xa2, 0x13, 0x78, 0xda, 0xc2, 0xce, 0x15, 0xbf, 0x42, 0x40, 0xf1, 0x33, - 0x83, 0x18, 0xd3, 0xee, 0x4d, 0x7e, 0xb7, 0xc4, 0xe7, 0xd0, 0x9f, 0xf3, 0xf0, 0x8c, 0x1d, 0x8c, - 0x57, 0x8c, 0x75, 0x13, 0xdc, 0x9b, 0x4e, 0xe2, 0x0d, 0xdc, 0x8b, 0x2e, 0x36, 0xfe, 0x43, 0xa8, - 0xb4, 0x45, 0x5e, 0xe7, 0xf7, 0x55, 0x7c, 0x0e, 0x7d, 0x07, 0x0f, 0x12, 0x6b, 0x8b, 0x43, 0x5f, - 0x07, 0xe6, 0xba, 0x63, 0x7d, 0x0b, 0xbb, 0x62, 0x64, 0x0d, 0x89, 0xdf, 0x67, 0x3d, 0xbb, 0xce, - 0xef, 0xa5, 0x76, 0x53, 0x96, 0xca, 0xe7, 0xd0, 0xef, 0x60, 0x27, 0xb1, 0x8a, 0xf0, 0x60, 0xbb, - 0xfc, 0x07, 0x6f, 0xbb, 0x57, 0xf4, 0xf3, 0x39, 0xf4, 0x7b, 0xd8, 0x26, 0xa9, 0x18, 0x9e, 0xc7, - 0xfe, 0x28, 0x5d, 0x36, 0x3d, 0x8f, 0xcb, 0x98, 0xfa, 0x6f, 0x61, 0xb7, 0x85, 0x1d, 0x3a, 0x80, - 0x3a, 0x3f, 0x42, 0xbc, 0x24, 0x19, 0xab, 0xd8, 0x5d, 0x63, 0xe6, 0x7f, 0x80, 0x87, 0xde, 0x33, - 0xc2, 0x8f, 0x02, 0xff, 0x0d, 0x81, 0xd7, 0x31, 0xfb, 0x4d, 0xe4, 0x4d, 0xe1, 0xd3, 0xb5, 0x21, - 0xc0, 0x23, 0x0a, 0xe6, 0x27, 0xa2, 0x3f, 0x04, 0xe6, 0x10, 0xee, 0x77, 0x35, 0x3b, 0x53, 0xc5, - 0x69, 0xce, 0xf3, 0x38, 0x7b, 0x10, 0x56, 0x0c, 0xcd, 0xa1, 0x23, 0xa8, 0xb4, 0xb0, 0xe3, 0xcf, - 0x33, 0x76, 0x05, 0x48, 0x85, 0xbc, 0xec, 0x46, 0xce, 0xe7, 0x50, 0x1b, 0xee, 0x30, 0xac, 0x77, - 0x46, 0x3a, 0x84, 0xcd, 0x16, 0x76, 0x12, 0xb7, 0xfa, 0x5b, 0xe0, 0xf4, 0x61, 0x53, 0x9c, 0xc3, - 0xb9, 0x4c, 0xe6, 0x2a, 0xc0, 0x5f, 0xc3, 0x7a, 0x0b, 0x3b, 0xd1, 0xca, 0x48, 0xda, 0xac, 0x2a, - 0x31, 0x5a, 0x84, 0x9b, 0x21, 0x88, 0x71, 0x84, 0x4c, 0xee, 0x0c, 0x5b, 0x68, 0xc0, 0xda, 0x91, - 0xe9, 0x1a, 0xce, 0xe8, 0x48, 0xa4, 0xe9, 0xe8, 0x15, 0xb7, 0xd8, 0x0c, 0x94, 0x01, 0x70, 0xd4, - 0x9a, 0x46, 0x62, 0x2d, 0xfc, 0x55, 0x57, 0x8c, 0x33, 0xb3, 0x9e, 0x93, 0x81, 0xf8, 0x0d, 0xdc, - 0x0d, 0xa2, 0x40, 0x14, 0xf5, 0x32, 0x6b, 0xbf, 0x42, 0xdd, 0x43, 0x3f, 0x26, 0xfe, 0xa0, 0xa8, - 0xaf, 0x09, 0x6a, 0xe8, 0xf3, 0xd7, 0x45, 0x4d, 0x5f, 0x75, 0x17, 0x2a, 0x31, 0x6f, 0x7f, 0x37, - 0xb4, 0x1e, 0x6c, 0x85, 0x7e, 0x1e, 0x85, 0xba, 0xa5, 0x87, 0xbf, 0x82, 0x4d, 0x82, 0x37, 0x9a, - 0xda, 0x9d, 0xa9, 0x3c, 0xc1, 0x75, 0x76, 0x87, 0xbf, 0x1d, 0x56, 0x1f, 0xb6, 0xa3, 0x58, 0x87, - 0xba, 0x6c, 0x9f, 0xaa, 0x16, 0xb9, 0xe4, 0xdc, 0x3a, 0xfc, 0xac, 0xb1, 0xda, 0xa9, 0x77, 0xa7, - 0x79, 0x98, 0x5e, 0xd3, 0xf4, 0x8c, 0x70, 0xf7, 0x41, 0x56, 0xb7, 0xed, 0xea, 0x0e, 0x85, 0xdb, - 0x88, 0xc2, 0xbd, 0x32, 0xc7, 0x57, 0x21, 0x66, 0x17, 0x51, 0x69, 0x18, 0xdf, 0x6a, 0x77, 0x1a, - 0xc4, 0xa2, 0x83, 0xca, 0x2a, 0xab, 0xc3, 0x66, 0x4b, 0x5d, 0x39, 0xc5, 0x26, 0xa0, 0x76, 0xa7, - 0x51, 0x97, 0x0d, 0x05, 0xeb, 0xe1, 0x2c, 0x2f, 0x01, 0xcc, 0xb2, 0x92, 0x1d, 0x36, 0x35, 0xaf, - 0xee, 0x1c, 0xf0, 0xa7, 0xdb, 0xc9, 0xc3, 0x4c, 0x7c, 0xb2, 0x9f, 0x7c, 0x0e, 0xd5, 0x60, 0x3b, - 0x98, 0x56, 0x55, 0xd7, 0xaf, 0x80, 0xcb, 0x4a, 0x5f, 0xb6, 0x62, 0x73, 0xf2, 0x6b, 0xe1, 0x97, - 0xad, 0xee, 0xbd, 0x64, 0x57, 0x6a, 0x1d, 0x9d, 0x4e, 0xb0, 0x74, 0x28, 0x06, 0xef, 0x2c, 0x89, - 0x6d, 0x4d, 0xbe, 0xbf, 0x64, 0x4c, 0xf0, 0x35, 0xc0, 0xa1, 0xe8, 0x3f, 0xf9, 0xa0, 0xf8, 0x4e, - 0x25, 0xde, 0xa5, 0x12, 0x1a, 0x4b, 0xbe, 0x13, 0xd1, 0x1d, 0x28, 0x1f, 0x8a, 0x2d, 0xec, 0xf8, - 0xaf, 0x23, 0x09, 0xbc, 0xc4, 0xdb, 0x4a, 0x02, 0x2f, 0xf9, 0xa4, 0xc2, 0xe7, 0xd0, 0x1f, 0x61, - 0xeb, 0x50, 0xac, 0x5b, 0x58, 0x76, 0x70, 0xec, 0x75, 0x0d, 0x25, 0x7e, 0x2f, 0x98, 0xf2, 0xb6, - 0xb7, 0xcb, 0x5f, 0xc6, 0x12, 0x8c, 0xf0, 0x6b, 0x28, 0xd1, 0xf7, 0xc2, 0x2e, 0x2d, 0x75, 0x24, - 0x76, 0x25, 0xfa, 0x28, 0x9a, 0x54, 0x1f, 0xe9, 0xe2, 0x73, 0x3f, 0xcb, 0xa3, 0x16, 0x94, 0x9a, - 0xca, 0x69, 0xf0, 0x5e, 0x74, 0x59, 0x70, 0xbb, 0xa4, 0x8f, 0xcf, 0xa1, 0x0e, 0x20, 0x16, 0x2d, - 0x63, 0x3f, 0x2f, 0xc8, 0x7e, 0x50, 0xde, 0xdd, 0x4e, 0x7f, 0xd4, 0xe6, 0x73, 0xe8, 0x4b, 0x58, - 0x6b, 0x61, 0x27, 0x7c, 0x0c, 0x4f, 0xb3, 0xd7, 0x6c, 0xe9, 0x43, 0x16, 0xd1, 0xb0, 0x11, 0x10, - 0xeb, 0xa7, 0xac, 0x50, 0x72, 0x33, 0x1c, 0x01, 0x36, 0x69, 0xc4, 0x3e, 0xd6, 0x4e, 0xc2, 0xf5, - 0x7c, 0x90, 0x60, 0xcf, 0xfa, 0x0d, 0x47, 0xe6, 0xf9, 0xbc, 0x15, 0x9c, 0xa6, 0x31, 0xdc, 0xcb, - 0xf4, 0x9e, 0xad, 0x43, 0x8a, 0x58, 0x89, 0x1e, 0xa6, 0xd7, 0x06, 0xcd, 0x5e, 0x77, 0x97, 0x20, - 0x86, 0x07, 0xe9, 0xb5, 0x11, 0xd3, 0x57, 0x7c, 0x04, 0xf7, 0x62, 0x27, 0xe9, 0x3b, 0xc2, 0x79, - 0xc7, 0x55, 0xca, 0xd4, 0x6e, 0x79, 0x5c, 0x49, 0xf0, 0x98, 0x4d, 0x2d, 0xbb, 0xfe, 0x7b, 0xcd, - 0x5a, 0x72, 0xc6, 0x8c, 0x4d, 0xf8, 0xa0, 0x85, 0x9d, 0xaa, 0xae, 0x5f, 0x5d, 0xc2, 0x4e, 0x5b, - 0xc2, 0x7e, 0xbc, 0xfe, 0x76, 0x15, 0x06, 0x9f, 0x43, 0x3a, 0x3c, 0x8b, 0xe4, 0xff, 0xd9, 0xa3, - 0x5d, 0xa6, 0xfc, 0x6b, 0x2e, 0x99, 0xcf, 0x21, 0xc5, 0xbb, 0x17, 0x65, 0x8f, 0x93, 0x5e, 0x1c, - 0xbf, 0x91, 0xdb, 0x7c, 0x07, 0x7c, 0xe0, 0x36, 0x3f, 0xf6, 0x82, 0x7e, 0x03, 0xef, 0x45, 0x1d, - 0xea, 0x76, 0xc3, 0xa5, 0x2f, 0x83, 0x42, 0x87, 0x9e, 0xf5, 0x43, 0x42, 0xff, 0x1e, 0x7e, 0x12, - 0xfa, 0xc5, 0xcd, 0x2c, 0xec, 0x1a, 0x4e, 0x22, 0xc0, 0xfd, 0x88, 0x49, 0xcd, 0xfd, 0xb9, 0xc3, - 0xd5, 0xe9, 0x49, 0x52, 0x84, 0x3a, 0x9e, 0x57, 0x02, 0x48, 0xf6, 0x09, 0x78, 0xa6, 0xcb, 0x4a, - 0x32, 0x1f, 0x48, 0x72, 0x5d, 0x3d, 0xc0, 0xef, 0xe0, 0x5e, 0xfa, 0x00, 0x55, 0x55, 0x7d, 0x67, - 0xf0, 0xbf, 0xf5, 0xab, 0x53, 0xf3, 0xb3, 0x9f, 0x9a, 0x67, 0xf8, 0xc7, 0xc3, 0x1f, 0xcd, 0x54, - 0x72, 0x24, 0xbe, 0x2b, 0x7e, 0xac, 0xf4, 0x90, 0xec, 0xbf, 0xb5, 0x9d, 0x74, 0x61, 0x8b, 0x22, - 0xce, 0x59, 0xc8, 0x15, 0xd3, 0x4d, 0xb7, 0xe9, 0x31, 0xfc, 0x24, 0xea, 0x89, 0x59, 0x76, 0x72, - 0x99, 0xb3, 0x5c, 0x43, 0xcf, 0x8f, 0x2f, 0x1b, 0x83, 0x98, 0xca, 0x3b, 0xe1, 0x0f, 0xc8, 0x3e, - 0x86, 0x2e, 0x3f, 0xa7, 0x98, 0x9b, 0x7b, 0xfa, 0x37, 0xb0, 0x73, 0x2c, 0x6b, 0x4e, 0xda, 0x0f, - 0xc0, 0xaf, 0xfc, 0x93, 0x8a, 0x0c, 0xc8, 0x0e, 0xdc, 0x39, 0xd4, 0x2c, 0x3c, 0xf7, 0xc3, 0xd6, - 0xcb, 0x7e, 0x7d, 0x9f, 0x09, 0x75, 0x97, 0xe9, 0x33, 0xf1, 0xf7, 0xdb, 0x97, 0xfd, 0x79, 0x71, - 0x06, 0xd4, 0x1b, 0xb8, 0x43, 0x95, 0x96, 0x40, 0xfa, 0x69, 0x22, 0x8b, 0xcf, 0xfe, 0x4b, 0xe8, - 0xcc, 0xaa, 0xdb, 0x4e, 0x70, 0x98, 0x24, 0xb0, 0xaf, 0x5f, 0x7e, 0x88, 0x0b, 0xf2, 0x39, 0x74, - 0x0c, 0xbb, 0x51, 0x43, 0xfa, 0xe1, 0x80, 0x7b, 0x04, 0x38, 0xb4, 0xa0, 0x1b, 0x00, 0x67, 0xd9, - 0x4f, 0x25, 0xf4, 0xfc, 0x04, 0xda, 0xad, 0xdd, 0xbe, 0x42, 0x35, 0x2a, 0x5b, 0x8e, 0x3b, 0xbb, - 0x06, 0xe4, 0xe5, 0x17, 0x89, 0x2e, 0x54, 0xc4, 0x2c, 0xb4, 0x9b, 0x2f, 0xf7, 0x4b, 0x58, 0x6d, - 0xd4, 0x6a, 0xb2, 0xf2, 0xd6, 0x9d, 0xdd, 0x42, 0xfa, 0x2b, 0x28, 0x36, 0x6a, 0x02, 0xb6, 0x89, - 0xb2, 0x6e, 0x95, 0xfc, 0xde, 0x0d, 0x75, 0x1d, 0x5c, 0x92, 0x6f, 0x1d, 0x5e, 0x63, 0x75, 0xa4, - 0xf0, 0x0f, 0x0a, 0xde, 0x21, 0x5c, 0xdf, 0x09, 0xf1, 0x7c, 0x2d, 0xbd, 0x4b, 0x55, 0x8a, 0x24, - 0xba, 0xfe, 0xdf, 0x73, 0xb6, 0x66, 0x9a, 0x79, 0x6b, 0xac, 0x17, 0xb0, 0x2a, 0x9e, 0xba, 0x8e, - 0x6a, 0x9e, 0x1b, 0x37, 0xa8, 0x56, 0x1c, 0xc0, 0xb2, 0x80, 0xc7, 0xa6, 0xe9, 0x5c, 0x5f, 0x66, - 0xbc, 0x4c, 0xff, 0xff, 0xc4, 0xcf, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x24, 0xd9, 0x58, 0xc6, - 0x8d, 0x42, 0x00, 0x00, + 0x72, 0x06, 0x08, 0x3e, 0x80, 0x04, 0x41, 0x36, 0x6b, 0x86, 0x24, 0x86, 0xf3, 0xee, 0x1d, 0x49, + 0xb3, 0x94, 0x44, 0xad, 0xb8, 0xb3, 0x23, 0xad, 0x56, 0xb2, 0x16, 0x2f, 0x02, 0x98, 0x01, 0x01, + 0xa8, 0x1b, 0x18, 0x6a, 0x5f, 0xee, 0x6d, 0x74, 0x17, 0xc1, 0xd6, 0x34, 0xba, 0xe1, 0x7e, 0x90, + 0xa2, 0x1d, 0xb1, 0x11, 0xde, 0x08, 0x47, 0xec, 0xc1, 0x77, 0x1f, 0x7c, 0xf5, 0xd5, 0xbe, 0xf9, + 0x67, 0xf8, 0x87, 0xf8, 0xb2, 0x37, 0x5f, 0x7c, 0xb1, 0xa3, 0xaa, 0xfa, 0x09, 0x74, 0x83, 0x8f, + 0x91, 0x6e, 0x5d, 0x59, 0x99, 0x5f, 0x55, 0x65, 0x65, 0x66, 0x65, 0x65, 0x81, 0x04, 0x18, 0x5b, + 0x53, 0xe5, 0x60, 0x6a, 0x99, 0x8e, 0x89, 0x8a, 0xfd, 0x17, 0x17, 0x46, 0xff, 0x53, 0x89, 0x90, + 0xf8, 0x7f, 0x5d, 0x82, 0x8d, 0x63, 0xd9, 0x76, 0xb0, 0x35, 0xc0, 0x93, 0xa9, 0x2e, 0x3b, 0x18, + 0xbd, 0x84, 0x5d, 0xc7, 0xfb, 0x96, 0x0c, 0x79, 0x82, 0xa5, 0x91, 0xee, 0x62, 0xc7, 0x34, 0x9d, + 0xb3, 0x72, 0xf6, 0x49, 0xf6, 0x79, 0x41, 0xd8, 0xf6, 0xbb, 0xbb, 0xf2, 0x04, 0x57, 0xfd, 0x4e, + 0xb4, 0x0f, 0x5b, 0x71, 0x39, 0xd7, 0x1e, 0x95, 0x97, 0xa8, 0xc4, 0x66, 0x54, 0x62, 0x68, 0x8f, + 0xd0, 0x47, 0x80, 0xe2, 0xbc, 0x17, 0xda, 0xa9, 0x56, 0xce, 0x51, 0x66, 0x2e, 0xca, 0x7c, 0xa2, + 0x9d, 0x6a, 0xa8, 0x02, 0x0f, 0xe3, 0xdc, 0x8e, 0xa5, 0x8d, 0xc7, 0xd8, 0x92, 0x64, 0xc5, 0xd1, + 0x4c, 0xc3, 0x2e, 0x2f, 0x53, 0xc1, 0xbd, 0xa8, 0xe0, 0x80, 0xb1, 0x54, 0x18, 0x07, 0x7a, 0x01, + 0x3b, 0x31, 0x08, 0x5b, 0x32, 0xb0, 0x73, 0x61, 0x5a, 0x6f, 0xcb, 0x2b, 0x4f, 0x72, 0xcf, 0x0b, + 0xc2, 0xdd, 0xa8, 0xac, 0xdd, 0x65, 0x7d, 0xfc, 0x3f, 0xc0, 0x03, 0x01, 0xff, 0x9d, 0x8b, 0x6d, + 0x27, 0xae, 0x23, 0xd1, 0x31, 0x2d, 0x79, 0x8c, 0x11, 0x0f, 0xeb, 0x83, 0x88, 0x9c, 0xa7, 0x9f, + 0x18, 0x0d, 0x7d, 0x06, 0x79, 0x1f, 0x9b, 0x6a, 0xa3, 0x78, 0x78, 0xff, 0x20, 0xb2, 0x03, 0x07, + 0x71, 0x64, 0x21, 0x60, 0xe6, 0xff, 0x31, 0x0b, 0x8f, 0x03, 0xed, 0x7a, 0xd3, 0x10, 0xb1, 0xe3, + 0x68, 0xc6, 0xd8, 0xbe, 0xc9, 0x04, 0xbe, 0x80, 0xbc, 0xed, 0x89, 0x79, 0x13, 0x78, 0x14, 0x9b, + 0x40, 0x30, 0x86, 0x0f, 0x2e, 0x04, 0xfc, 0xfc, 0x3f, 0x65, 0x61, 0x6b, 0xae, 0x1f, 0xfd, 0x0a, + 0x96, 0x14, 0x8d, 0x8e, 0x55, 0x3c, 0xfc, 0x30, 0x19, 0xab, 0x66, 0x1a, 0x8e, 0x65, 0xea, 0x3a, + 0xb6, 0xda, 0xc6, 0xa9, 0x69, 0x4d, 0x64, 0xb2, 0x0d, 0xc2, 0x92, 0xa2, 0xa1, 0x9f, 0xc3, 0x92, + 0xec, 0x4f, 0xe4, 0x27, 0xc9, 0xc2, 0x95, 0x31, 0x36, 0x82, 0xa5, 0x0a, 0x4b, 0xb2, 0xcd, 0xef, + 0xc3, 0x4e, 0x72, 0x2f, 0xe2, 0x20, 0x37, 0xd5, 0x0c, 0x6f, 0xe1, 0xe4, 0x93, 0xff, 0xdf, 0x2c, + 0xec, 0x06, 0xcc, 0xde, 0x4e, 0x8a, 0xd8, 0x3a, 0xd7, 0x14, 0x4c, 0xcc, 0xc0, 0xc2, 0x63, 0x8d, + 0x68, 0x5c, 0x32, 0x2d, 0xc9, 0x35, 0xfc, 0x16, 0x05, 0xc8, 0x0b, 0x77, 0xfd, 0x76, 0xcf, 0x1a, + 0x06, 0x7d, 0xc4, 0xb2, 0x6d, 0x6c, 0x9d, 0x33, 0x19, 0xc5, 0x34, 0x0c, 0xac, 0x38, 0x74, 0x05, + 0x79, 0x61, 0x93, 0x75, 0xf4, 0xac, 0x1a, 0x23, 0xa3, 0x2f, 0x61, 0xd9, 0xb9, 0x9c, 0x62, 0x6a, + 0xcb, 0x1b, 0x87, 0xcf, 0x93, 0x17, 0x18, 0x9f, 0xd5, 0xe0, 0x72, 0x8a, 0x05, 0x2a, 0x85, 0x1e, + 0x41, 0x71, 0x22, 0x2b, 0x64, 0x18, 0x62, 0xa4, 0x9e, 0x5d, 0x17, 0x26, 0xb2, 0xd2, 0xb3, 0xe8, + 0x5e, 0x3e, 0x86, 0xe2, 0xc8, 0xd2, 0xd4, 0x31, 0x33, 0xe2, 0xf2, 0x0a, 0xed, 0x07, 0x46, 0x22, + 0x0c, 0xfc, 0x7f, 0x2f, 0xc3, 0xfd, 0x84, 0x4d, 0x08, 0xd4, 0x55, 0x86, 0xb5, 0xa9, 0x79, 0x81, + 0x2d, 0xac, 0x7a, 0x2b, 0xf6, 0x9b, 0xe8, 0x09, 0x14, 0xbd, 0xa5, 0xc9, 0x23, 0x1d, 0x7b, 0xcb, + 0x8b, 0x92, 0xd0, 0x4f, 0x81, 0x3b, 0x95, 0x6d, 0x47, 0x8a, 0xb2, 0xe5, 0x98, 0x16, 0x08, 0xbd, + 0x16, 0x61, 0xe5, 0x61, 0x5d, 0xd5, 0x6c, 0xc5, 0x3c, 0xc7, 0x16, 0x65, 0x5b, 0xa6, 0x6c, 0x31, + 0x1a, 0xda, 0x83, 0xfc, 0xc8, 0x34, 0x54, 0xda, 0xbf, 0x42, 0xfb, 0x83, 0x36, 0x3a, 0x80, 0x3b, + 0xba, 0x66, 0xbc, 0x95, 0x74, 0x7c, 0x8e, 0x75, 0xc9, 0xc6, 0x8a, 0x6b, 0x69, 0xce, 0x65, 0x79, + 0x95, 0xb2, 0x6d, 0x91, 0xae, 0x0e, 0xe9, 0x11, 0xbd, 0x0e, 0x74, 0x08, 0xdb, 0x94, 0x09, 0x4b, + 0xb6, 0x36, 0x99, 0xea, 0x58, 0x9a, 0xca, 0x9a, 0xa5, 0x19, 0xe3, 0xf2, 0x1a, 0x95, 0xb8, 0xc3, + 0x3a, 0x45, 0xda, 0xd7, 0x67, 0x5d, 0x68, 0x1b, 0x56, 0x47, 0x96, 0x84, 0x55, 0xab, 0x9c, 0xa7, + 0x4c, 0x2b, 0x23, 0xab, 0xa1, 0x5a, 0xe8, 0x21, 0xc0, 0x99, 0x36, 0x3e, 0x93, 0xec, 0x29, 0xc6, + 0x6a, 0xb9, 0x40, 0xbb, 0x0a, 0x84, 0x22, 0x12, 0x02, 0xe9, 0xd6, 0xcd, 0x0b, 0x09, 0x1b, 0xd8, + 0x1a, 0x5f, 0x96, 0x81, 0x75, 0xeb, 0xe6, 0x45, 0x83, 0x12, 0x88, 0x16, 0x65, 0xf5, 0x1c, 0x5b, + 0x8e, 0x66, 0x93, 0xe1, 0x8b, 0x4c, 0x8b, 0x11, 0x12, 0xfa, 0x18, 0x90, 0x37, 0x55, 0x4f, 0x8f, + 0x34, 0x82, 0xad, 0xb3, 0x95, 0xb1, 0x9e, 0x5a, 0xd8, 0x41, 0xc6, 0x53, 0xf1, 0xc8, 0x1d, 0x4b, + 0x6f, 0xf1, 0xa5, 0x5d, 0x2e, 0xb1, 0xf1, 0x28, 0xe5, 0x35, 0xbe, 0x64, 0xfb, 0x69, 0x69, 0xe7, + 0xb2, 0x72, 0x59, 0xde, 0xf0, 0xf6, 0x93, 0x35, 0xd1, 0x2f, 0xa1, 0xac, 0x04, 0xfb, 0x4f, 0xc6, + 0x3a, 0xd5, 0xc6, 0xae, 0x45, 0xfd, 0xb0, 0xbc, 0x49, 0x59, 0x77, 0xc3, 0xfe, 0x5a, 0xb4, 0x1b, + 0xbd, 0x07, 0x1b, 0xb6, 0x23, 0x3b, 0x9a, 0x22, 0xc9, 0xaa, 0x6a, 0x61, 0xdb, 0x2e, 0x73, 0x54, + 0xa0, 0xc4, 0xa8, 0x15, 0x46, 0xe4, 0xff, 0xba, 0x0c, 0x8f, 0x16, 0x3b, 0x3c, 0x99, 0x9e, 0x0f, + 0x41, 0xcc, 0x6d, 0x5d, 0xf0, 0x9b, 0xe8, 0x43, 0xd8, 0x0a, 0xce, 0x15, 0xe9, 0x1c, 0x5b, 0x36, + 0x99, 0x17, 0x31, 0xba, 0x92, 0xc0, 0x05, 0x1d, 0x6f, 0x18, 0x9d, 0x98, 0xd3, 0x44, 0x36, 0xdc, + 0x53, 0x59, 0x71, 0x5c, 0x0b, 0x5b, 0xd4, 0xea, 0x4a, 0x42, 0x8c, 0x86, 0x4e, 0x00, 0xd9, 0xee, + 0x74, 0x6a, 0x5a, 0x0e, 0x56, 0xa5, 0x20, 0xe0, 0x2d, 0xd3, 0x38, 0xf3, 0xfc, 0xaa, 0x20, 0x15, + 0x04, 0x9b, 0xad, 0x00, 0x23, 0x70, 0x19, 0x11, 0x38, 0xc5, 0xb5, 0x2c, 0x6c, 0x38, 0x21, 0xec, + 0xca, 0x0d, 0x61, 0x37, 0x3d, 0x84, 0x00, 0xf4, 0x7d, 0xd8, 0x54, 0x74, 0xd9, 0xb6, 0x25, 0xf3, + 0x54, 0x52, 0x31, 0x89, 0x02, 0xd4, 0xb8, 0xd7, 0x85, 0x12, 0x25, 0xf7, 0x4e, 0xeb, 0x94, 0x88, + 0x10, 0x2c, 0x53, 0x4f, 0x5f, 0xa3, 0x9e, 0x4e, 0xbf, 0x89, 0x49, 0xd8, 0x67, 0xa6, 0xe5, 0xb0, + 0x18, 0x90, 0x67, 0x31, 0x82, 0x52, 0x68, 0x8c, 0x78, 0x0a, 0xeb, 0x9a, 0x2d, 0xc9, 0xe7, 0xb2, + 0xa6, 0x53, 0xdf, 0x62, 0x26, 0x5c, 0xd4, 0xec, 0x8a, 0x4f, 0x42, 0xbf, 0x82, 0x3d, 0x9b, 0xc5, + 0x1e, 0xff, 0x18, 0x94, 0xbc, 0x00, 0x67, 0xc8, 0x53, 0xcf, 0xa8, 0x77, 0x3d, 0x8e, 0x48, 0xac, + 0xc2, 0x56, 0x57, 0x9e, 0xa2, 0xaf, 0xe0, 0x7e, 0x8a, 0xf0, 0x54, 0x36, 0x5c, 0xcf, 0xe4, 0xcb, + 0x49, 0xd2, 0x7d, 0xd9, 0x70, 0xd1, 0x2f, 0xe1, 0x5e, 0x8a, 0xf8, 0xd8, 0xf0, 0xdc, 0x60, 0x27, + 0x49, 0xb8, 0x69, 0xf0, 0xdf, 0x01, 0x17, 0x3b, 0xd6, 0x45, 0xec, 0xa0, 0x2a, 0x6c, 0xc4, 0x8f, + 0xfa, 0x72, 0xf6, 0x49, 0xee, 0x79, 0xf1, 0x70, 0x2f, 0xb6, 0x37, 0x31, 0x16, 0x61, 0x46, 0x82, + 0x28, 0x99, 0x9e, 0x9e, 0x2c, 0x59, 0xa1, 0xdf, 0xfc, 0xbf, 0x03, 0x94, 0x62, 0x6c, 0x68, 0x03, + 0x96, 0x34, 0x16, 0x35, 0x4b, 0xc2, 0x92, 0xa6, 0x12, 0xdb, 0x36, 0x0d, 0x2c, 0x9e, 0x99, 0xfe, + 0x59, 0xe0, 0x37, 0x49, 0x64, 0xd3, 0x6c, 0x22, 0x75, 0xee, 0x07, 0xc8, 0xa0, 0x8d, 0x1e, 0x40, + 0x41, 0x9b, 0x4c, 0x5c, 0x27, 0x12, 0x16, 0x43, 0x02, 0xea, 0xc0, 0x86, 0xb7, 0x76, 0xd1, 0x91, + 0x89, 0x15, 0x7a, 0x96, 0xc6, 0x27, 0xad, 0x46, 0x8c, 0x71, 0xb6, 0x32, 0xc2, 0x8c, 0x2c, 0xfa, + 0x16, 0x90, 0x6b, 0x8f, 0x9a, 0xb2, 0x3a, 0xc6, 0x7e, 0x74, 0xc6, 0x2a, 0xb5, 0xb3, 0xe2, 0xe1, + 0xfb, 0x49, 0x88, 0x43, 0xb1, 0x3a, 0xc3, 0xdd, 0xca, 0x08, 0x09, 0x18, 0x48, 0x86, 0xed, 0x80, + 0x5a, 0x27, 0x41, 0xdd, 0x07, 0x5f, 0xa3, 0xe0, 0x3f, 0x5d, 0x08, 0x1e, 0x15, 0x68, 0x65, 0x84, + 0x64, 0x24, 0xd4, 0x86, 0x12, 0x49, 0x0a, 0x2b, 0x7d, 0x5f, 0x13, 0x79, 0x0a, 0xfd, 0x34, 0x09, + 0xfa, 0x24, 0xca, 0xd8, 0xca, 0x08, 0x71, 0x49, 0xa2, 0x07, 0x42, 0x08, 0xa6, 0x5f, 0xb1, 0x45, + 0x47, 0xa6, 0x7e, 0x91, 0xa2, 0x87, 0x93, 0x39, 0x6e, 0xa2, 0x87, 0x79, 0x0c, 0x9a, 0x5b, 0xd9, + 0x67, 0x1d, 0x73, 0xac, 0x19, 0xd4, 0x6d, 0x8a, 0x87, 0x0f, 0x12, 0x77, 0x4a, 0x6c, 0x51, 0x9e, + 0x56, 0x46, 0x08, 0xf8, 0x91, 0x00, 0x9c, 0x7a, 0xa6, 0x4c, 0x3b, 0x58, 0xb6, 0x71, 0xd3, 0x92, + 0x0d, 0xb2, 0xc6, 0x22, 0xc5, 0x78, 0x96, 0x84, 0x51, 0x6f, 0xd5, 0xfa, 0x51, 0xde, 0x56, 0x46, + 0x98, 0x93, 0x47, 0x47, 0xb0, 0x3e, 0xb6, 0x4c, 0x77, 0x2a, 0x60, 0x05, 0x13, 0xeb, 0x5b, 0xa7, + 0x78, 0x4f, 0x92, 0xf0, 0x9a, 0x11, 0xbe, 0x56, 0x46, 0x88, 0xc9, 0xa1, 0x21, 0x6c, 0x45, 0xdb, + 0xc7, 0xae, 0xee, 0x68, 0xf4, 0xf0, 0x29, 0x1e, 0xbe, 0x77, 0x15, 0x18, 0x65, 0x6e, 0x65, 0x84, + 0x79, 0x04, 0xf4, 0x02, 0x56, 0xc7, 0x53, 0xcd, 0x6c, 0x1b, 0xf4, 0xb0, 0x4a, 0x71, 0xd2, 0x66, + 0xbf, 0xdd, 0x6b, 0x13, 0x55, 0x79, 0xbc, 0xa8, 0x0e, 0x30, 0x92, 0xed, 0x33, 0x51, 0xb1, 0xb4, + 0xa9, 0x43, 0xcf, 0xae, 0x59, 0x87, 0xf0, 0xc2, 0x01, 0xd9, 0xee, 0x6a, 0xc0, 0xd9, 0xca, 0x0a, + 0x11, 0x39, 0x54, 0x81, 0xc2, 0x99, 0xa6, 0x7a, 0x20, 0x5c, 0x82, 0x2d, 0x45, 0x40, 0x5a, 0xed, + 0x7a, 0x80, 0x11, 0x4a, 0x21, 0x05, 0x76, 0x54, 0x3c, 0xd5, 0xcd, 0x4b, 0x3f, 0x8c, 0xfb, 0x79, + 0x76, 0x79, 0x2b, 0xc1, 0xec, 0x19, 0x5e, 0x3d, 0x51, 0xa0, 0x95, 0x15, 0x52, 0xa0, 0xd0, 0x3e, + 0xe4, 0x74, 0x73, 0x5c, 0x46, 0x14, 0x71, 0x27, 0x01, 0xb1, 0x63, 0x8e, 0x5b, 0x59, 0x81, 0x30, + 0xa1, 0x97, 0xb0, 0x46, 0x74, 0xd4, 0x73, 0x9d, 0xf2, 0x9d, 0x04, 0x85, 0x32, 0x7e, 0xa2, 0xcf, + 0x9e, 0x4b, 0x96, 0xe2, 0x33, 0xa3, 0x2f, 0xa1, 0x40, 0x37, 0x47, 0xc4, 0x86, 0x5a, 0xbe, 0x9b, + 0x60, 0xb7, 0x9e, 0xa4, 0xcf, 0x43, 0xd4, 0x10, 0x08, 0x54, 0x0b, 0xb0, 0xe6, 0x6d, 0x55, 0x35, + 0x0f, 0xab, 0x8c, 0x95, 0xdf, 0x85, 0xed, 0xc4, 0xb0, 0xc4, 0xdf, 0x87, 0x7b, 0xa9, 0xd1, 0x85, + 0x7f, 0x04, 0x0f, 0x16, 0x45, 0x07, 0x7e, 0x07, 0xee, 0x26, 0xb9, 0x78, 0x04, 0x74, 0xde, 0x55, + 0xf9, 0x4f, 0x60, 0x73, 0xc6, 0xef, 0x48, 0xd4, 0xd5, 0xc9, 0xc7, 0xd0, 0xf6, 0x52, 0xfd, 0x82, + 0x10, 0x12, 0xf8, 0x7b, 0xb0, 0x9b, 0xe2, 0x64, 0x7c, 0x1b, 0xee, 0x24, 0x98, 0x38, 0xc1, 0xa3, + 0xfa, 0x88, 0x5c, 0xba, 0x42, 0x02, 0xba, 0x0b, 0x2b, 0xe7, 0xb2, 0xee, 0xb2, 0x03, 0x65, 0x45, + 0x60, 0x0d, 0xfe, 0x2f, 0x59, 0x28, 0xa7, 0xb9, 0xcb, 0x15, 0x80, 0x3b, 0xb0, 0x4a, 0x31, 0xec, + 0x72, 0xee, 0x49, 0xee, 0xf9, 0x8a, 0xe0, 0xb5, 0xd0, 0x4b, 0xef, 0xb2, 0xb1, 0x4c, 0x2f, 0x1b, + 0x71, 0x9f, 0x98, 0x1b, 0x23, 0xbc, 0x66, 0xf0, 0xff, 0x95, 0x0d, 0x0e, 0x37, 0xe6, 0x6d, 0xe8, + 0x3e, 0x14, 0x88, 0x71, 0xb0, 0x94, 0x82, 0x8d, 0x9f, 0x27, 0x04, 0x3a, 0xfc, 0x57, 0x00, 0x53, + 0x57, 0xd7, 0x87, 0xd3, 0xba, 0x79, 0xc1, 0x92, 0xb4, 0x8d, 0xc3, 0x87, 0xf1, 0xc1, 0x28, 0x4a, + 0x3f, 0x60, 0x12, 0x22, 0x02, 0xe8, 0x33, 0x00, 0xe6, 0xc9, 0x0d, 0x75, 0xec, 0x5f, 0x8c, 0x76, + 0x13, 0xc4, 0x49, 0xb7, 0x10, 0x61, 0x45, 0x1f, 0xc0, 0xa6, 0x8a, 0x47, 0xa6, 0x6b, 0x28, 0x58, + 0x9a, 0x68, 0xba, 0xae, 0xb1, 0x7c, 0x2e, 0x27, 0x6c, 0xf8, 0xe4, 0x63, 0x4a, 0xe5, 0x3f, 0x83, + 0xed, 0xc4, 0x10, 0x80, 0x1e, 0x01, 0xd8, 0xf4, 0x2b, 0xa2, 0xd7, 0x08, 0x85, 0x7f, 0x09, 0x77, + 0x93, 0xdc, 0xfe, 0x4a, 0xb9, 0xff, 0xc9, 0xc2, 0x83, 0x45, 0xfe, 0x4d, 0x32, 0x56, 0x27, 0xe1, + 0x62, 0x1e, 0xa5, 0xa1, 0x57, 0xde, 0xee, 0x31, 0x85, 0xbe, 0xbc, 0x76, 0xf0, 0x38, 0xf0, 0x3f, + 0x22, 0x3b, 0x8a, 0xc3, 0x42, 0x00, 0xa1, 0xa2, 0x2d, 0x28, 0x1d, 0x0d, 0x3b, 0x1d, 0x49, 0x6c, + 0x0c, 0x06, 0xed, 0x6e, 0x53, 0xe4, 0x32, 0xa8, 0x08, 0x6b, 0xdd, 0xc6, 0xe0, 0xa4, 0x27, 0xbc, + 0xe6, 0xb2, 0x28, 0x0f, 0xcb, 0x27, 0xed, 0xa3, 0x36, 0xb7, 0x84, 0xd6, 0x20, 0x37, 0x14, 0xab, + 0x5c, 0x0e, 0x95, 0xa0, 0x50, 0xed, 0x0c, 0x1b, 0x83, 0x5e, 0x6f, 0xd0, 0xe2, 0x96, 0xd1, 0x1d, + 0xd8, 0x1c, 0x08, 0xed, 0x66, 0xb3, 0x21, 0x48, 0x95, 0xda, 0xa0, 0xdd, 0xeb, 0x8a, 0xdc, 0x0a, + 0x5f, 0x84, 0x42, 0x10, 0x84, 0xf8, 0x3f, 0x40, 0x29, 0x16, 0x61, 0x16, 0x1b, 0xd1, 0x27, 0x51, + 0xa7, 0xd8, 0x38, 0xbc, 0x37, 0x67, 0x00, 0x3d, 0xd7, 0x79, 0x43, 0x18, 0x7c, 0x7f, 0x69, 0xc0, + 0xe6, 0x4c, 0x18, 0xba, 0x95, 0xdb, 0x5d, 0xc0, 0x1e, 0x89, 0x11, 0xef, 0x50, 0x40, 0xf9, 0xc5, + 0x5c, 0x01, 0x25, 0x3e, 0xf9, 0x13, 0xed, 0x48, 0x4b, 0xa8, 0x9d, 0xfc, 0x4b, 0x0e, 0xd6, 0xa3, + 0x5d, 0x41, 0x2e, 0x9f, 0x8d, 0xe4, 0xf2, 0x7b, 0x90, 0x57, 0x35, 0x9b, 0xe4, 0x7e, 0xaa, 0x97, + 0x45, 0x06, 0x6d, 0x62, 0x84, 0x16, 0x1e, 0xbb, 0xba, 0xec, 0x98, 0xd6, 0xa5, 0x57, 0x1c, 0x8b, + 0x50, 0xd0, 0xd7, 0xb0, 0x4e, 0xd2, 0x63, 0xcd, 0x18, 0x4b, 0x13, 0x53, 0xf5, 0xa3, 0xc0, 0x83, + 0xb9, 0xb9, 0x9d, 0x30, 0xa6, 0x63, 0x53, 0xc5, 0x42, 0xf1, 0x22, 0x6c, 0xa0, 0x97, 0x50, 0x90, + 0x5d, 0xe7, 0x8c, 0x49, 0xaf, 0x24, 0x6c, 0x0b, 0x91, 0xae, 0xb8, 0xce, 0x19, 0x15, 0xcd, 0xcb, + 0xde, 0x17, 0xc9, 0x7c, 0x95, 0x33, 0xd9, 0x30, 0xb0, 0x4e, 0x93, 0xc9, 0x92, 0xe0, 0x37, 0xd1, + 0x01, 0xac, 0xca, 0x53, 0xa9, 0x2a, 0x8a, 0x5e, 0x22, 0xb8, 0x3b, 0x07, 0x57, 0x15, 0xc5, 0xda, + 0xe9, 0x58, 0x58, 0x91, 0xa7, 0x55, 0x51, 0x44, 0x5f, 0x93, 0x6b, 0x90, 0x46, 0xae, 0x56, 0x55, + 0x51, 0x94, 0x74, 0xcd, 0x76, 0xca, 0x79, 0x9a, 0xbe, 0xa7, 0x0a, 0x96, 0x18, 0x7f, 0x55, 0x14, + 0x3b, 0x9a, 0x4d, 0x4d, 0xee, 0x4c, 0x53, 0xb1, 0x64, 0xdb, 0x9a, 0x7f, 0x59, 0xcf, 0x13, 0x82, + 0x68, 0x6b, 0x2a, 0x09, 0x9b, 0x06, 0xfe, 0x7e, 0x62, 0x1a, 0xde, 0xbd, 0xd9, 0x6b, 0xf1, 0xff, + 0x91, 0x85, 0x02, 0xdd, 0x19, 0x87, 0xb8, 0xea, 0x01, 0x2c, 0x53, 0x05, 0x64, 0xa9, 0x02, 0xf6, + 0xe6, 0xb7, 0x96, 0x70, 0x51, 0x0d, 0x50, 0xbe, 0xe8, 0xea, 0x97, 0xe2, 0xab, 0x47, 0xb0, 0x4c, + 0xe7, 0xc1, 0xb6, 0x8a, 0x7e, 0xa3, 0x1a, 0xcc, 0xde, 0xfd, 0xbc, 0x3b, 0xe9, 0x02, 0x1b, 0x9a, + 0x95, 0xe0, 0x0f, 0x01, 0x42, 0x15, 0x90, 0x61, 0x44, 0xb1, 0x5d, 0xf7, 0xed, 0x88, 0x7c, 0x23, + 0x0e, 0x72, 0x7d, 0xf1, 0xb5, 0x77, 0x83, 0x21, 0x9f, 0xfc, 0x53, 0x28, 0x89, 0x8e, 0x45, 0xb6, + 0x1a, 0xdb, 0x36, 0x31, 0x75, 0x0e, 0x72, 0x13, 0x7b, 0xec, 0x57, 0xca, 0x26, 0xf6, 0x98, 0xff, + 0x19, 0xa0, 0x18, 0x4b, 0xc5, 0xb2, 0xe4, 0x4b, 0x62, 0x92, 0x13, 0x7b, 0x4c, 0xbf, 0xe9, 0x5d, + 0xaa, 0x20, 0x04, 0x6d, 0xfe, 0x00, 0xd6, 0x1b, 0xe7, 0xd8, 0x70, 0x3c, 0x6f, 0x22, 0x26, 0x4a, + 0x36, 0x0d, 0x1b, 0x24, 0xe8, 0x50, 0xe8, 0x9c, 0x10, 0xa1, 0xf0, 0x32, 0x00, 0xe5, 0xa7, 0x8e, + 0x8d, 0xf6, 0x60, 0xcd, 0xb1, 0xe9, 0x80, 0x6c, 0x16, 0xad, 0x8c, 0xe0, 0x13, 0xd0, 0x0e, 0xac, + 0x38, 0x23, 0xd3, 0x64, 0x3a, 0xcd, 0xb7, 0x32, 0x02, 0x6b, 0xa2, 0x32, 0xac, 0x3a, 0x9a, 0xe1, + 0xbc, 0x7c, 0x41, 0xb5, 0x9a, 0x23, 0x69, 0x21, 0x6b, 0x57, 0x57, 0x20, 0x77, 0x2e, 0xeb, 0x7c, + 0x07, 0x56, 0xe8, 0x10, 0x44, 0x2d, 0x4e, 0x38, 0x0b, 0x56, 0x4f, 0xfb, 0x24, 0x38, 0x38, 0x97, + 0x12, 0xcc, 0x2a, 0x9c, 0x9a, 0x7f, 0xa2, 0xf2, 0x7f, 0x84, 0xbb, 0xc4, 0xf7, 0xeb, 0x9a, 0xd5, + 0xb3, 0x8e, 0x34, 0x1d, 0xfb, 0x0b, 0xe5, 0x20, 0xa7, 0x6a, 0x7e, 0xea, 0x40, 0x3e, 0x89, 0x71, + 0x4d, 0x2d, 0x7c, 0xaa, 0x7d, 0xef, 0x29, 0xdd, 0x6b, 0x11, 0x95, 0x98, 0x86, 0x7e, 0x79, 0x64, + 0xea, 0xaa, 0x57, 0xa9, 0xc8, 0x0b, 0x11, 0x0a, 0x39, 0xab, 0x66, 0x46, 0xb0, 0xa7, 0xa6, 0x61, + 0x63, 0xe6, 0xee, 0xb6, 0xab, 0x3b, 0x7d, 0x39, 0x28, 0xb5, 0x47, 0x28, 0xfc, 0x3f, 0x67, 0x61, + 0x53, 0xc0, 0xb2, 0x1a, 0x9d, 0xd6, 0x2f, 0x60, 0xf5, 0x94, 0x0d, 0x94, 0x4d, 0x38, 0x95, 0x2b, + 0x8a, 0x82, 0x6d, 0x5b, 0x1b, 0xe9, 0x98, 0x8d, 0x2d, 0x78, 0xcc, 0x64, 0x8b, 0x4f, 0x35, 0x1d, + 0x1b, 0xe1, 0xa5, 0x37, 0x68, 0x93, 0x28, 0x6a, 0x93, 0xc3, 0x90, 0xe9, 0x5b, 0x60, 0x0d, 0xb2, + 0x7e, 0x1d, 0x1b, 0xde, 0xf1, 0x4b, 0x3e, 0xf9, 0x3a, 0x70, 0xe1, 0x6c, 0xbc, 0x25, 0x3c, 0x80, + 0x82, 0x85, 0x65, 0xb5, 0x66, 0xba, 0x86, 0xe3, 0xed, 0x43, 0x48, 0x20, 0x1b, 0xa4, 0xca, 0x8e, + 0x4c, 0x47, 0x5c, 0x17, 0xe8, 0x37, 0xff, 0x9f, 0x59, 0xe0, 0x4e, 0x2c, 0xcd, 0xc1, 0x3f, 0xf2, + 0xaa, 0x76, 0x48, 0x60, 0x9a, 0x92, 0x74, 0x97, 0xed, 0x88, 0xd7, 0xa2, 0x95, 0x25, 0xd7, 0x76, + 0xba, 0xa6, 0xd3, 0xf8, 0x9e, 0x44, 0x1f, 0xaf, 0x50, 0x19, 0xa5, 0x05, 0xf3, 0x5e, 0x89, 0xcc, + 0xfb, 0x3d, 0xd8, 0x24, 0x33, 0x6e, 0x1b, 0xa7, 0xa6, 0x3f, 0x6b, 0x04, 0xcb, 0xd3, 0x70, 0xe7, + 0xe8, 0x37, 0xff, 0x27, 0xe0, 0x42, 0x36, 0x4f, 0x49, 0x49, 0xc7, 0x00, 0x89, 0x1c, 0xda, 0xdf, + 0xb3, 0x69, 0xe7, 0x04, 0xfa, 0x4d, 0x68, 0x34, 0x2e, 0xb1, 0x62, 0x57, 0x10, 0x7b, 0x26, 0xa6, + 0x3a, 0xd0, 0xbc, 0xda, 0x70, 0x4e, 0xf0, 0x9b, 0x64, 0xdb, 0x34, 0xbb, 0xae, 0x59, 0x5e, 0x29, + 0x95, 0x35, 0xf8, 0xdf, 0x02, 0x17, 0x24, 0x35, 0x11, 0x9f, 0x65, 0x99, 0x4c, 0xd4, 0xce, 0x42, + 0x0a, 0x7a, 0x1f, 0x36, 0x1c, 0x6d, 0x82, 0x4d, 0xd7, 0x11, 0xb1, 0x62, 0x1a, 0xaa, 0xed, 0x85, + 0xb9, 0x19, 0x2a, 0xff, 0x08, 0xd6, 0x03, 0xec, 0x57, 0xe6, 0x68, 0xb6, 0x3e, 0xc2, 0x3f, 0x8b, + 0x8c, 0xfd, 0xca, 0x1c, 0xd1, 0x70, 0xcd, 0x41, 0x4e, 0x53, 0x59, 0x89, 0xa6, 0x24, 0x90, 0x4f, + 0xfe, 0x0d, 0x94, 0x5b, 0xed, 0xba, 0xe0, 0x1a, 0x86, 0x66, 0x8c, 0x5f, 0x99, 0x23, 0x1a, 0x6d, + 0x05, 0x6a, 0xf5, 0x11, 0xc4, 0x1c, 0xad, 0xb8, 0x20, 0x58, 0x3e, 0x9f, 0xb4, 0x55, 0x5f, 0x4b, + 0xe4, 0x9b, 0x6c, 0xac, 0x6d, 0xba, 0x96, 0x82, 0xbd, 0xa8, 0xeb, 0xb5, 0xf8, 0x3f, 0xc1, 0x66, + 0x64, 0xe5, 0x14, 0xee, 0x43, 0xc8, 0x7d, 0x67, 0x8e, 0xbc, 0x77, 0x8b, 0x78, 0xf8, 0x8d, 0x4e, + 0x54, 0x20, 0x5c, 0x44, 0x4b, 0x9a, 0x7d, 0xa4, 0x19, 0x9a, 0x7d, 0x16, 0x1c, 0xcd, 0x11, 0x4a, + 0xe8, 0xad, 0xaf, 0x6c, 0xd3, 0x08, 0x0f, 0x67, 0x9f, 0xc2, 0x1f, 0x40, 0xb1, 0xd3, 0xa8, 0x07, + 0x67, 0xff, 0x63, 0x28, 0x8e, 0x68, 0x45, 0x5b, 0x09, 0x7c, 0xa3, 0x24, 0x00, 0x25, 0x51, 0xe7, + 0xe0, 0xbf, 0x87, 0x7b, 0x43, 0xb1, 0xfa, 0x0e, 0x59, 0xca, 0x67, 0x73, 0x59, 0x4a, 0xfc, 0x9d, + 0x89, 0xdd, 0xae, 0x12, 0xf2, 0x94, 0xbf, 0xae, 0xc0, 0x46, 0xbc, 0x93, 0x98, 0x19, 0x36, 0x58, + 0x52, 0xe2, 0xbd, 0x12, 0x78, 0x4d, 0xb2, 0x81, 0xe7, 0x9a, 0xea, 0x9f, 0x33, 0xe7, 0x9a, 0xca, + 0x1e, 0x60, 0xfc, 0x33, 0x8f, 0x7c, 0xce, 0x55, 0x6b, 0xd9, 0x2b, 0x46, 0xbc, 0x5a, 0x4b, 0xeb, + 0xd6, 0xa6, 0xea, 0x2a, 0x8e, 0xf7, 0x88, 0xe1, 0x37, 0xe9, 0x86, 0x62, 0x4b, 0x93, 0x59, 0x6e, + 0x41, 0x36, 0x94, 0xb6, 0xd0, 0x23, 0x28, 0xba, 0x36, 0x96, 0x6a, 0xf5, 0x9a, 0xd4, 0xa8, 0x1d, + 0x7b, 0x85, 0xfd, 0x82, 0x6b, 0xe3, 0x5a, 0xbd, 0xd6, 0xa8, 0x1d, 0x93, 0x4c, 0x80, 0xf4, 0x0b, + 0xdd, 0x7a, 0x5b, 0xf4, 0x2a, 0xfa, 0x79, 0xd7, 0xc6, 0xb4, 0x8d, 0x9e, 0x03, 0x47, 0x3a, 0x5b, + 0xed, 0xba, 0xf4, 0xba, 0xf1, 0x9b, 0x6a, 0xaf, 0x22, 0xd4, 0xbd, 0x6c, 0x61, 0xc3, 0xb5, 0x71, + 0xab, 0x5d, 0xf7, 0xa9, 0x88, 0x87, 0x92, 0xcf, 0x79, 0xdc, 0x1b, 0x8a, 0x0d, 0xaf, 0x1a, 0x5a, + 0x64, 0x6c, 0x94, 0xe4, 0x4f, 0x85, 0xf0, 0x08, 0x95, 0x13, 0xaf, 0xe2, 0x59, 0x60, 0x1c, 0x42, + 0xe5, 0x04, 0xed, 0xc2, 0x1a, 0xe9, 0x1f, 0x1e, 0x8b, 0x5e, 0x41, 0x73, 0xd5, 0xb5, 0xf1, 0xf0, + 0x58, 0x44, 0x0f, 0x01, 0x48, 0x87, 0xd8, 0x10, 0xda, 0x95, 0x8e, 0x5f, 0xcc, 0x77, 0x6d, 0xcc, + 0x08, 0xe8, 0x15, 0x6c, 0x58, 0x86, 0xaa, 0xd9, 0x61, 0x9d, 0x79, 0x23, 0xe1, 0x99, 0x2c, 0xbe, + 0x57, 0x0d, 0xe7, 0x0c, 0x5b, 0x06, 0x76, 0x84, 0x12, 0x15, 0x0d, 0xb6, 0xf0, 0x18, 0x38, 0x45, + 0x55, 0x24, 0xac, 0x4c, 0x42, 0xb4, 0xcd, 0xeb, 0xa3, 0x6d, 0x28, 0xaa, 0xd2, 0x50, 0x26, 0x01, + 0x5c, 0x05, 0xd6, 0xdd, 0x49, 0x64, 0x62, 0x5c, 0xc2, 0x43, 0x62, 0x1c, 0x6a, 0x78, 0x2c, 0x0a, + 0x45, 0x77, 0x12, 0xce, 0xe8, 0x53, 0xd8, 0x56, 0xf1, 0xb9, 0x44, 0xe2, 0xa2, 0x74, 0xa6, 0xa9, + 0xd2, 0x5b, 0x7c, 0x39, 0x32, 0x65, 0x4b, 0xa5, 0xa5, 0x8e, 0x82, 0x80, 0x54, 0x7c, 0x4e, 0xe2, + 0x4f, 0x4b, 0x53, 0x5f, 0x7b, 0x3d, 0xe8, 0x43, 0x40, 0x31, 0x91, 0x89, 0xe9, 0xda, 0x98, 0x96, + 0x3a, 0x0a, 0xc2, 0x66, 0xc8, 0x7f, 0x4c, 0xc8, 0xe8, 0x03, 0xe0, 0x62, 0xcc, 0x96, 0x7c, 0x41, + 0x6b, 0x1b, 0x05, 0xa1, 0x14, 0xb2, 0x0a, 0xf2, 0x05, 0xdf, 0x87, 0x9d, 0xe4, 0x55, 0xd3, 0x6c, + 0xd2, 0xb4, 0x1d, 0xfa, 0xec, 0xe1, 0x5f, 0x60, 0x08, 0xa1, 0xa2, 0xaa, 0x16, 0xba, 0x07, 0x79, + 0x82, 0x4f, 0xfb, 0x98, 0xfd, 0xaf, 0xa9, 0xf8, 0x9c, 0x74, 0xf1, 0x5f, 0xc1, 0xd6, 0xdc, 0xe2, + 0x49, 0x44, 0x56, 0x54, 0xcb, 0x9c, 0x78, 0x2e, 0xc4, 0x1a, 0x24, 0x86, 0x91, 0x43, 0xc9, 0xaf, + 0x35, 0x93, 0x6f, 0xfe, 0x2f, 0x59, 0x78, 0x14, 0x68, 0xfe, 0xf6, 0x11, 0xa0, 0x3a, 0x17, 0x01, + 0xe2, 0xc5, 0x4d, 0x7f, 0x88, 0xb6, 0xe1, 0x60, 0xeb, 0x54, 0x56, 0x70, 0x42, 0x30, 0x90, 0xe0, + 0x29, 0xbb, 0x74, 0x62, 0x35, 0x95, 0x1d, 0x7d, 0x01, 0xcb, 0x34, 0x55, 0x67, 0x95, 0xf6, 0xeb, + 0x0e, 0x42, 0x65, 0xf8, 0x3f, 0xe7, 0xe0, 0x5e, 0x3a, 0x72, 0xd2, 0xd9, 0xf8, 0xb5, 0x77, 0x0e, + 0xb2, 0x7b, 0xe3, 0x87, 0xd7, 0x1b, 0xed, 0x20, 0x92, 0xb0, 0x93, 0x50, 0x3e, 0xf5, 0x1e, 0xad, + 0x5e, 0xf8, 0xa1, 0x3a, 0xa4, 0x90, 0xbc, 0xc1, 0xc0, 0xce, 0x44, 0xb6, 0xdf, 0xbe, 0xf0, 0x62, + 0x55, 0xd0, 0x8e, 0x46, 0xc2, 0x95, 0x78, 0x24, 0xec, 0x01, 0x52, 0xcf, 0x94, 0x29, 0x7b, 0x9c, + 0x08, 0x72, 0x7b, 0x56, 0x5c, 0x7f, 0x1c, 0x9b, 0x64, 0xbd, 0x55, 0xeb, 0xc7, 0xd9, 0x84, 0x04, + 0x51, 0xf4, 0x0c, 0x4a, 0xfe, 0x36, 0xb4, 0x8d, 0xa1, 0x8d, 0xbd, 0x10, 0x17, 0x27, 0xf2, 0x35, + 0x58, 0xa6, 0x77, 0x30, 0x80, 0xd5, 0xe3, 0x4a, 0x77, 0x58, 0xe9, 0x70, 0x19, 0xb4, 0x09, 0x45, + 0x32, 0x86, 0x54, 0xeb, 0xb4, 0x1b, 0xdd, 0x01, 0x97, 0x0d, 0x08, 0x62, 0x43, 0x78, 0xd3, 0x10, + 0xb8, 0x25, 0x72, 0xb7, 0x1f, 0x76, 0x8f, 0x2b, 0xdd, 0x4a, 0xb3, 0x51, 0xe7, 0x72, 0xfc, 0xff, + 0xe5, 0x00, 0xcd, 0xcf, 0x2a, 0xcc, 0xe6, 0xfb, 0xa6, 0x15, 0x9c, 0x51, 0x21, 0x05, 0x3d, 0x87, + 0x4d, 0xd6, 0x0a, 0xd4, 0xed, 0xff, 0xbe, 0x63, 0x86, 0x4c, 0xeb, 0x6d, 0x58, 0xb6, 0x69, 0x56, + 0xe7, 0x69, 0x3c, 0x24, 0xa0, 0x7d, 0xe0, 0x0c, 0xd3, 0x21, 0x17, 0x4b, 0xd3, 0xd2, 0x1c, 0x99, + 0xbe, 0x93, 0xb0, 0xc4, 0x6b, 0x8e, 0x8e, 0x0e, 0x00, 0xa9, 0x66, 0xd7, 0x74, 0xaa, 0x9a, 0xa1, + 0x86, 0xc3, 0xb2, 0xbd, 0x48, 0xe8, 0x21, 0xd9, 0x8b, 0x22, 0xeb, 0xfa, 0x48, 0x56, 0xde, 0x7a, + 0xb5, 0x5e, 0x76, 0x8c, 0xcc, 0x50, 0xd1, 0x0b, 0x58, 0xb5, 0x64, 0x63, 0x8c, 0xed, 0xf2, 0x1a, + 0xb5, 0xe2, 0x07, 0x29, 0x5b, 0x26, 0x10, 0x26, 0xc1, 0xe3, 0x45, 0x47, 0xb0, 0x66, 0x4e, 0xd9, + 0x33, 0x13, 0xbb, 0xa7, 0x7e, 0x74, 0xc5, 0x4e, 0x1f, 0xf4, 0x18, 0x7b, 0xc3, 0x70, 0xac, 0x4b, + 0xc1, 0x17, 0x46, 0x35, 0x28, 0xb2, 0xb7, 0xd4, 0x96, 0x69, 0x3b, 0x76, 0xb9, 0x40, 0xb1, 0x9e, + 0xa6, 0x61, 0x05, 0x9c, 0x42, 0x54, 0x6a, 0xef, 0x0b, 0x58, 0x8f, 0xa2, 0x93, 0x93, 0xf8, 0x2d, + 0xbe, 0xf4, 0xf6, 0x8d, 0x7c, 0xc6, 0x2b, 0x22, 0x05, 0xaf, 0x22, 0xf2, 0xc5, 0xd2, 0xe7, 0x59, + 0xde, 0x84, 0xcd, 0x99, 0x35, 0xd2, 0x8c, 0x86, 0x7c, 0x74, 0xcc, 0x8b, 0xa0, 0x48, 0x1a, 0xa1, + 0x04, 0xfd, 0xc3, 0xe9, 0x14, 0xfb, 0x11, 0x30, 0x42, 0x09, 0xf6, 0x9c, 0x66, 0xa7, 0xd1, 0x3d, + 0x27, 0x04, 0xfe, 0x73, 0xb8, 0x9b, 0xb4, 0x22, 0x7a, 0x2b, 0x95, 0x95, 0xe0, 0x56, 0x2a, 0x2b, + 0x34, 0xeb, 0x9b, 0x7a, 0xf8, 0x4b, 0xda, 0x94, 0x5f, 0x83, 0x95, 0xc6, 0x64, 0xea, 0x5c, 0xee, + 0x7f, 0x1e, 0xf9, 0x69, 0xc3, 0xfc, 0x2f, 0x28, 0xd0, 0x1a, 0xe4, 0xba, 0x95, 0x3e, 0x97, 0x41, + 0x79, 0x58, 0xee, 0x57, 0xba, 0x43, 0x2e, 0x8b, 0x56, 0x61, 0xa9, 0xd9, 0xe5, 0x96, 0xf6, 0x5f, + 0xc1, 0x76, 0x62, 0x39, 0x14, 0xad, 0x43, 0x5e, 0x6c, 0x7c, 0x33, 0x6c, 0x74, 0x6b, 0x0d, 0x2e, + 0x43, 0x10, 0x2a, 0xdd, 0x3a, 0x93, 0xeb, 0x11, 0xb7, 0x41, 0xb0, 0xd1, 0xf8, 0xb6, 0x52, 0x1b, + 0x48, 0x01, 0x53, 0x6e, 0xff, 0x63, 0xe0, 0x66, 0xab, 0x9d, 0x84, 0x7f, 0xe8, 0x8d, 0x5c, 0xef, + 0x9d, 0x74, 0xb9, 0x2c, 0x81, 0xea, 0x1d, 0x1d, 0x71, 0x4b, 0xfb, 0x9f, 0x00, 0x84, 0xd5, 0x4d, + 0xe2, 0xb5, 0x42, 0x5b, 0x6c, 0x77, 0x9b, 0xac, 0x1e, 0x77, 0x54, 0xe9, 0x74, 0x48, 0x83, 0xd6, + 0xe3, 0xaa, 0xbd, 0x41, 0x8b, 0x5b, 0xda, 0xff, 0x18, 0xd6, 0xa3, 0xd5, 0x30, 0x82, 0xd4, 0xe9, + 0x9d, 0x30, 0xf0, 0x56, 0xbb, 0xd9, 0xe2, 0xb2, 0x04, 0x65, 0xd0, 0x6b, 0x36, 0x3b, 0x0d, 0x6e, + 0x69, 0xbf, 0x0e, 0x9b, 0x33, 0x35, 0x1e, 0x02, 0x3c, 0xec, 0xbe, 0xee, 0x92, 0x89, 0x64, 0xc8, + 0xd4, 0x2a, 0x7d, 0x36, 0x21, 0x71, 0x50, 0xe1, 0x96, 0xd0, 0x1d, 0xd8, 0x14, 0x07, 0x15, 0xe9, + 0xa8, 0xd2, 0xee, 0xf4, 0xde, 0x34, 0x04, 0xa9, 0xd2, 0xe7, 0x72, 0xfb, 0x75, 0x28, 0xc5, 0x4a, + 0x1d, 0x68, 0x1b, 0xb6, 0x08, 0x57, 0xb7, 0x37, 0x90, 0x6a, 0xbd, 0x6e, 0xb7, 0x51, 0x1b, 0x34, + 0xea, 0x5c, 0x06, 0x15, 0x60, 0xa5, 0xd2, 0x97, 0x86, 0x04, 0x70, 0x0b, 0x4a, 0x84, 0x23, 0xec, + 0x5d, 0xda, 0x7f, 0x9f, 0x15, 0xbc, 0xfc, 0x8a, 0x11, 0xd1, 0xee, 0x49, 0xbf, 0x72, 0x28, 0xf5, + 0xc5, 0xd7, 0x6c, 0xfe, 0xbd, 0x7e, 0xa3, 0xcb, 0x65, 0xf7, 0xff, 0x06, 0xb8, 0xd9, 0x4b, 0x1c, + 0x99, 0xdf, 0xe0, 0x98, 0xe8, 0x90, 0x83, 0xf5, 0x6a, 0x45, 0x6c, 0x49, 0x62, 0x4d, 0x68, 0xf7, + 0x07, 0x22, 0x8b, 0x66, 0x24, 0xd5, 0xf2, 0x09, 0x4b, 0x87, 0xff, 0xf6, 0x12, 0x56, 0xfb, 0x2f, + 0x4e, 0xba, 0xfd, 0x4f, 0xd1, 0x29, 0x3c, 0x6d, 0x62, 0xe7, 0x8a, 0x5f, 0x21, 0xa0, 0xf8, 0x99, + 0x41, 0x8c, 0x69, 0xef, 0x26, 0xbf, 0x5b, 0xe2, 0x33, 0xe8, 0xcf, 0x59, 0x78, 0xc6, 0x0e, 0xc6, + 0x2b, 0xc6, 0xba, 0x09, 0xee, 0x4d, 0x27, 0xf1, 0x06, 0xee, 0x45, 0x17, 0x1b, 0xff, 0x21, 0x54, + 0xd2, 0x22, 0xaf, 0xf3, 0xfb, 0x2a, 0x3e, 0x83, 0xbe, 0x83, 0x07, 0x33, 0x6b, 0x8b, 0x43, 0x5f, + 0x07, 0xe6, 0xba, 0x63, 0x7d, 0x0b, 0x7b, 0x62, 0x64, 0x0d, 0x33, 0xbf, 0xcf, 0x7a, 0x76, 0x9d, + 0xdf, 0x4b, 0xed, 0x25, 0x2c, 0x95, 0xcf, 0xa0, 0xdf, 0xc1, 0xee, 0xcc, 0x2a, 0xc2, 0x83, 0x6d, + 0xf1, 0x0f, 0xde, 0xf6, 0xae, 0xe8, 0xe7, 0x33, 0xe8, 0xf7, 0xb0, 0x43, 0x52, 0x31, 0x3c, 0x8f, + 0xfd, 0x51, 0xb2, 0x6c, 0x72, 0x1e, 0x97, 0x32, 0xf5, 0xdf, 0xc2, 0x5e, 0x13, 0x3b, 0x74, 0x00, + 0x75, 0x7e, 0x84, 0x78, 0x49, 0x32, 0x56, 0xb1, 0xbb, 0xc6, 0xcc, 0xff, 0x00, 0x0f, 0xbd, 0x67, + 0x84, 0x1f, 0x05, 0xfe, 0x1b, 0x02, 0xaf, 0x63, 0xf6, 0x9b, 0xc8, 0x9b, 0xc2, 0x27, 0x6b, 0x43, + 0x80, 0x47, 0x14, 0xcc, 0x4f, 0x44, 0x7f, 0x08, 0xcc, 0x01, 0xdc, 0xef, 0x68, 0x76, 0xaa, 0x8a, + 0x93, 0x9c, 0xe7, 0x71, 0xfa, 0x20, 0xac, 0x18, 0x9a, 0x41, 0xc7, 0x50, 0x6e, 0x62, 0xc7, 0x9f, + 0x67, 0xec, 0x0a, 0x90, 0x08, 0xb9, 0xe8, 0x46, 0x4e, 0x75, 0x79, 0x87, 0x61, 0xc5, 0x91, 0x16, + 0x49, 0x5d, 0x05, 0xf9, 0x6b, 0xd8, 0x68, 0x62, 0x27, 0x5a, 0x89, 0x48, 0x9a, 0x57, 0x39, 0x46, + 0x8b, 0x70, 0x33, 0x04, 0x31, 0x8e, 0x90, 0xca, 0x9d, 0xa2, 0xfb, 0x3a, 0xac, 0x1f, 0x9b, 0xae, + 0xe1, 0x0c, 0x8f, 0x45, 0x9a, 0xfe, 0x5d, 0x71, 0x6b, 0x4c, 0x41, 0xe9, 0x03, 0x47, 0x77, 0x6f, + 0x28, 0x56, 0xc3, 0x5f, 0x51, 0xc5, 0x38, 0x53, 0xeb, 0x27, 0x29, 0x88, 0xdf, 0xc0, 0xdd, 0xc0, + 0xeb, 0xa2, 0xa8, 0x8b, 0xac, 0xeb, 0x0a, 0x75, 0x0f, 0xfc, 0x18, 0xf4, 0x83, 0xa2, 0xbe, 0x26, + 0xa8, 0xa1, 0x8f, 0x5d, 0x17, 0x35, 0x79, 0xd5, 0x1d, 0x28, 0xc7, 0xbc, 0xeb, 0xdd, 0xd0, 0xba, + 0xb0, 0x1d, 0xfa, 0x55, 0x14, 0xea, 0x96, 0x1e, 0xf5, 0x0a, 0xb6, 0x08, 0xde, 0x70, 0x62, 0xb7, + 0x27, 0xf2, 0x18, 0xd7, 0xd8, 0x9d, 0xf9, 0x76, 0x58, 0x3d, 0xd8, 0x89, 0x62, 0x1d, 0xe9, 0xb2, + 0x7d, 0xa6, 0x5a, 0xe4, 0x52, 0x71, 0x6b, 0x77, 0x5f, 0x67, 0xb5, 0x4a, 0xef, 0x0e, 0xf1, 0x30, + 0xb9, 0x86, 0xe8, 0x19, 0xe1, 0xde, 0x83, 0xb4, 0x6e, 0xdb, 0xd5, 0x1d, 0x0a, 0xb7, 0x19, 0x85, + 0x7b, 0x65, 0x8e, 0xae, 0x42, 0x4c, 0x2f, 0x5a, 0xd2, 0xb0, 0xb9, 0xdd, 0x6a, 0xd7, 0x89, 0x45, + 0x07, 0x95, 0x4c, 0x56, 0xf7, 0x4c, 0x97, 0xba, 0x72, 0x8a, 0x0d, 0x40, 0xad, 0x76, 0xbd, 0x26, + 0x1b, 0x0a, 0xd6, 0xc3, 0x59, 0x2e, 0x00, 0x4c, 0xb3, 0x92, 0x5d, 0x36, 0x35, 0xaf, 0xce, 0x1b, + 0xf0, 0x27, 0xdb, 0xc9, 0xc3, 0x54, 0x7c, 0xb2, 0x9f, 0x7c, 0x06, 0x55, 0x61, 0x27, 0x98, 0x56, + 0x45, 0xd7, 0xaf, 0x80, 0x4b, 0x4b, 0x17, 0xb6, 0x63, 0x73, 0xf2, 0x6b, 0xcf, 0x8b, 0x56, 0xf7, + 0xde, 0x6c, 0x57, 0x62, 0xdd, 0x9a, 0x4e, 0xb0, 0x78, 0x24, 0x06, 0xef, 0x1a, 0x33, 0xdb, 0x3a, + 0xfb, 0xde, 0x91, 0x32, 0xc1, 0xd7, 0x00, 0x47, 0xa2, 0xff, 0xc4, 0x82, 0xe2, 0x3b, 0x35, 0xf3, + 0x0e, 0x34, 0xa3, 0xb1, 0xd9, 0x77, 0x19, 0xba, 0x03, 0xa5, 0x23, 0xb1, 0x89, 0x1d, 0xff, 0x35, + 0x62, 0x06, 0x6f, 0xe6, 0x2d, 0x63, 0x06, 0x6f, 0xf6, 0x09, 0x83, 0xcf, 0xa0, 0x3f, 0xc2, 0xf6, + 0x91, 0x58, 0xb3, 0xb0, 0xec, 0xe0, 0xd8, 0x6b, 0x16, 0x9a, 0xf9, 0x7d, 0x5e, 0xc2, 0x5b, 0xda, + 0x1e, 0xbf, 0x88, 0x25, 0x18, 0xe1, 0xd7, 0x50, 0xa4, 0xef, 0x73, 0x1d, 0x5a, 0x5a, 0x98, 0xd9, + 0x95, 0xe8, 0x23, 0xe4, 0xac, 0xfa, 0x48, 0x17, 0x9f, 0xf9, 0x59, 0x16, 0x35, 0xa1, 0xd8, 0x50, + 0xce, 0x82, 0xf7, 0x99, 0x45, 0xc1, 0x6d, 0x41, 0x1f, 0x9f, 0x41, 0x6d, 0x40, 0x2c, 0x5a, 0xc6, + 0x9e, 0xf3, 0xd3, 0x1f, 0x70, 0xf7, 0x76, 0x92, 0x1f, 0x91, 0xf9, 0x0c, 0xfa, 0x12, 0xd6, 0x9b, + 0xd8, 0x09, 0x1f, 0x9f, 0x93, 0xec, 0x35, 0x5d, 0xfa, 0x88, 0x45, 0x34, 0x6c, 0x04, 0xc4, 0xda, + 0x19, 0x2b, 0x4c, 0xdc, 0x0c, 0x47, 0x80, 0x2d, 0x1a, 0xb1, 0x4f, 0xb4, 0xd3, 0x70, 0x3d, 0x1f, + 0xcc, 0xb0, 0xa7, 0xfd, 0x66, 0x22, 0xf5, 0x7c, 0xde, 0x0e, 0x4e, 0xd3, 0x18, 0xee, 0x22, 0xbd, + 0xa7, 0xeb, 0x90, 0x22, 0x96, 0xa3, 0x87, 0xe9, 0xb5, 0x41, 0xd3, 0xd7, 0xdd, 0x21, 0x88, 0xe1, + 0x41, 0x7a, 0x6d, 0xc4, 0xe4, 0x15, 0x1f, 0xc3, 0xbd, 0xd8, 0x49, 0xfa, 0x8e, 0x70, 0xde, 0x71, + 0x95, 0x30, 0xb5, 0x5b, 0x1e, 0x57, 0x12, 0x3c, 0x66, 0x53, 0x4b, 0xaf, 0xb7, 0x5e, 0xb3, 0x76, + 0x9b, 0x32, 0x63, 0x13, 0x3e, 0x68, 0x62, 0xa7, 0xa2, 0xeb, 0x57, 0x97, 0x8c, 0x93, 0x96, 0x70, + 0x10, 0xaf, 0x77, 0x5d, 0x85, 0xc1, 0x67, 0x90, 0x0e, 0xcf, 0x22, 0xf9, 0x76, 0xfa, 0x68, 0x8b, + 0x94, 0x7f, 0xcd, 0x25, 0xf3, 0x19, 0xa4, 0x78, 0xf7, 0x90, 0xf4, 0x71, 0x92, 0x8b, 0xd1, 0x37, + 0x72, 0x9b, 0xef, 0x80, 0x0f, 0xdc, 0xe6, 0xc7, 0x5e, 0xd0, 0x6f, 0xe0, 0xbd, 0xa8, 0x43, 0xdd, + 0x6e, 0xb8, 0xe4, 0x65, 0x50, 0xe8, 0xd0, 0xb3, 0x7e, 0x48, 0xe8, 0xdf, 0xc3, 0x4f, 0x42, 0xbf, + 0xb8, 0x99, 0x85, 0x5d, 0xc3, 0x49, 0x04, 0xb8, 0x1f, 0x31, 0xa9, 0xb9, 0x3f, 0x2f, 0xb8, 0x3a, + 0x3d, 0x99, 0x15, 0xa1, 0x8e, 0xe7, 0x5d, 0xb9, 0x67, 0xfb, 0x04, 0x3c, 0xd5, 0x65, 0x65, 0x36, + 0x1f, 0x98, 0xe5, 0xba, 0x7a, 0x80, 0xdf, 0xc1, 0xbd, 0xe4, 0x01, 0x2a, 0xaa, 0xfa, 0xce, 0xe0, + 0x7f, 0xeb, 0x57, 0x83, 0xe6, 0x67, 0x3f, 0x31, 0xcf, 0xf1, 0x8f, 0x87, 0x3f, 0x9c, 0xaa, 0xe4, + 0x48, 0x7c, 0x57, 0xfc, 0xd8, 0x55, 0x7f, 0xb6, 0xff, 0xd6, 0x76, 0xd2, 0x81, 0x6d, 0x8a, 0x38, + 0x67, 0x21, 0x57, 0x4c, 0x37, 0xd9, 0xa6, 0x47, 0xf0, 0x93, 0xa8, 0x27, 0xa6, 0xd9, 0xc9, 0x22, + 0x67, 0xb9, 0x86, 0x9e, 0x1f, 0x2f, 0x1a, 0x83, 0x98, 0xca, 0x3b, 0xe1, 0xf7, 0xc9, 0x3e, 0x86, + 0x2e, 0x3f, 0xa7, 0x98, 0x9b, 0x7b, 0xfa, 0x37, 0xb0, 0x7b, 0x22, 0x6b, 0x4e, 0xd2, 0x0f, 0xae, + 0xaf, 0xfc, 0x13, 0x86, 0x14, 0xc8, 0x36, 0xdc, 0x39, 0xd2, 0x2c, 0x3c, 0xf7, 0x43, 0xd2, 0x45, + 0xbf, 0x76, 0x4f, 0x85, 0xba, 0xcb, 0xf4, 0x39, 0xf3, 0xf7, 0xd2, 0x8b, 0xfe, 0x9c, 0x37, 0x05, + 0xea, 0x0d, 0xdc, 0xa1, 0x4a, 0x9b, 0x41, 0xfa, 0xe9, 0x4c, 0x16, 0x9f, 0xfe, 0x97, 0xc7, 0xa9, + 0x55, 0xae, 0xdd, 0xe0, 0x30, 0x99, 0xc1, 0xbe, 0x7e, 0xf9, 0x21, 0x2e, 0xc8, 0x67, 0xd0, 0x09, + 0xec, 0x45, 0x0d, 0xe9, 0x87, 0x03, 0xee, 0x12, 0xe0, 0xd0, 0x82, 0x6e, 0x00, 0x9c, 0x66, 0x3f, + 0xe5, 0xd0, 0xf3, 0x67, 0xd0, 0x6e, 0xed, 0xf6, 0x65, 0xaa, 0x51, 0xd9, 0x72, 0xdc, 0xe9, 0x35, + 0x20, 0x17, 0x5f, 0x24, 0x3a, 0x50, 0x16, 0xd3, 0xd0, 0x6e, 0xbe, 0xdc, 0x2f, 0x21, 0x5f, 0xaf, + 0x56, 0x65, 0xe5, 0xad, 0x3b, 0xbd, 0x85, 0xf4, 0x57, 0x50, 0xa8, 0x57, 0x05, 0x6c, 0x13, 0x65, + 0xdd, 0x2a, 0xf9, 0xbd, 0x1b, 0xea, 0x3a, 0xb8, 0x24, 0xdf, 0x3a, 0xbc, 0xc6, 0xea, 0x48, 0xe1, + 0x0f, 0xf8, 0xdf, 0x21, 0x5c, 0xdf, 0x09, 0xf1, 0x7c, 0x2d, 0xbd, 0x4b, 0x55, 0x8a, 0x24, 0xba, + 0xfe, 0xdf, 0x4f, 0x36, 0xa7, 0x9a, 0x79, 0x6b, 0xac, 0x17, 0x90, 0x17, 0xcf, 0x5c, 0x47, 0x35, + 0x2f, 0x8c, 0x1b, 0x54, 0x2b, 0x0e, 0x61, 0x55, 0xc0, 0x23, 0xd3, 0x74, 0xae, 0x2f, 0x33, 0x5a, + 0xa5, 0xff, 0xef, 0xe1, 0xe7, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x37, 0xcf, 0xba, 0xd4, 0xfd, + 0x41, 0x00, 0x00, } diff --git a/proto/grpc.proto b/proto/grpc.proto index 887842e..97ff30b 100644 --- a/proto/grpc.proto +++ b/proto/grpc.proto @@ -21,9 +21,8 @@ service P4WNP1 { //USB gadget rpc GetDeployedGadgetSetting (Empty) returns (GadgetSettings) { } - rpc DeployGadgetSetting (Empty) returns (GadgetSettings) { } - rpc GetGadgetSettings (Empty) returns (GadgetSettings) { } - rpc SetGadgetSettings (GadgetSettings) returns (GadgetSettings) { } + rpc DeployGadgetSetting (GadgetSettings) returns (GadgetSettings) { } + rpc GetLEDSettings (Empty) returns (LEDSettings) { } rpc SetLEDSettings (LEDSettings) returns (Empty) { } rpc MountUMSFile (GadgetSettingsUMS) returns (Empty) { } diff --git a/service/SubSysTriggerAction.go b/service/SubSysTriggerAction.go index 43c5993..165482a 100644 --- a/service/SubSysTriggerAction.go +++ b/service/SubSysTriggerAction.go @@ -42,7 +42,7 @@ var triggerTypeString = map[triggerType]string { triggerTypeSshLogin: "TRIGGER_SSH_LOGIN", triggerTypeDhcpLeaseGranted: "TRIGGER_DHCP_LEASE_GRANTED", triggerTypeGroupReceive: "TRIGGER_GROUP_RECEIVE", - triggerTypeGroupReceiveMulti: "TRIGGER_GROUP_RECEIVE_SEQUENCE", + triggerTypeGroupReceiveMulti: "TRIGGER_GROUP_RECEIVE_MULTI", triggerTypeGpioIn: "TRIGGER_GPIO_IN", } @@ -495,12 +495,12 @@ func (tam *TriggerActionManager) executeActionBashScript(evt *pb.Event, ta *pb.T switch tt { case triggerTypeGpioIn: gpioPinName := ta.Trigger.(*pb.TriggerAction_GpioIn).GpioIn.GpioName - env = append(env, fmt.Sprintf("GPIO_PIN=%s", gpioPinName)) + env = append(env, fmt.Sprintf("GPIO_PIN='%s'", gpioPinName)) _,level,_ := DeconstructEventTriggerGpioIn(evt) if level { - env = append(env, fmt.Sprintf("GPIO_LEVEL='HIGH'")) + env = append(env, fmt.Sprintf("GPIO_LEVEL=HIGH")) } else { - env = append(env, fmt.Sprintf("GPIO_LEVEL='LOW'")) + env = append(env, fmt.Sprintf("GPIO_LEVEL=LOW")) } case triggerTypeGroupReceiveMulti: groupName := ta.Trigger.(*pb.TriggerAction_GroupReceiveMulti).GroupReceiveMulti.GroupName @@ -511,15 +511,15 @@ func (tam *TriggerActionManager) executeActionBashScript(evt *pb.Event, ta *pb.T for _,v := range values { bashArray += fmt.Sprintf("%d ", v)} bashArray += ")" env = append(env, - fmt.Sprintf("GROUP='%s'", groupName), + fmt.Sprintf("GROUP=%s", groupName), fmt.Sprintf("VALUES=%s", bashArray), - fmt.Sprintf("MULTI_TYPE='%s'", pb.GroupReceiveMultiType_name[int32(rtype)]), + fmt.Sprintf("MULTI_TYPE=%s", pb.GroupReceiveMultiType_name[int32(rtype)]), ) case triggerTypeGroupReceive: groupName := ta.Trigger.(*pb.TriggerAction_GroupReceive).GroupReceive.GroupName value := ta.Trigger.(*pb.TriggerAction_GroupReceive).GroupReceive.Value env = append(env, - fmt.Sprintf("GROUP='%s'", groupName), + fmt.Sprintf("GROUP=%s", groupName), fmt.Sprintf("VALUE=%d", value), ) case triggerTypeDhcpLeaseGranted: diff --git a/service/SubSysUSB.go b/service/SubSysUSB.go index 184bc8f..c55fb70 100644 --- a/service/SubSysUSB.go +++ b/service/SubSysUSB.go @@ -84,7 +84,7 @@ var ( ) type UsbManagerState struct { - UndeployedGadgetSettings *pb.GadgetSettings + //UndeployedGadgetSettings *pb.GadgetSettings DevicePath map[string]string } @@ -186,8 +186,8 @@ func NewUSBGadgetManager(rooSvc *Service) (newUGM *UsbGadgetManager, err error) defGS := GetDefaultGadgetSettings() - newUGM.State.UndeployedGadgetSettings = &defGS //preload state with default settings - err = newUGM.DeployGadgetSettings(newUGM.State.UndeployedGadgetSettings) + //newUGM.State.UndeployedGadgetSettings = &defGS //preload state with default settings + err = newUGM.DeployGadgetSettings(&defGS) if err != nil { newUGM.Usable = false return newUGM,nil @@ -197,7 +197,7 @@ func NewUSBGadgetManager(rooSvc *Service) (newUGM *UsbGadgetManager, err error) -func ValidateGadgetSetting(gs pb.GadgetSettings) error { +func ValidateGadgetSetting(gs *pb.GadgetSettings) error { /* ToDo: validations - Done: check host_addr/dev_addr of RNDIS + CDC ECM to be valid MAC addresses via regex - check host_addr/dev_addr of RNDIS + CDC ECM for duplicates @@ -495,6 +495,8 @@ func (gm *UsbGadgetManager) ParseGadgetState(gadgetName string) (result *pb.Gadg // remove path result.UmsSettings.File = filepath.Base(result.UmsSettings.File) } + } else { + result.UmsSettings = &pb.GadgetSettingsUMS{} } //check if UDC is set (Gadget enabled) @@ -526,19 +528,34 @@ func MountUMSFile(filename string) error { return nil } -func (gm *UsbGadgetManager) DeployGadgetSettings(settings *pb.GadgetSettings) error { +func (gm *UsbGadgetManager) DeployGadgetSettings(settings *pb.GadgetSettings) (err error) { if !gm.Usable { return ErrUsbNotUsable } - fmt.Println("DeployGadgetSettings before lock ...") + //fmt.Println("DeployGadgetSettings before lock ...") //Lock, only one change at a time gm.gadgetSettingsLock.Lock() - defer gm.gadgetSettingsLock.Unlock() - fmt.Println("DeployGadgetSettings beyond lock ...") + //defer gm.gadgetSettingsLock.Unlock() + defer func() { + //fmt.Println("UNLOCKING DeployGadgetSettings") + gm.gadgetSettingsLock.Unlock() + }() + //fmt.Println("DeployGadgetSettings beyond lock ...") + + err = ValidateGadgetSetting(settings) + if err != nil { + return + } + + //Crash fix: abort HID controller before destorying gadget, to avoid crashes by attempting to close filedescriptors of non existent files + if gm.hidCtl != nil { + gm.hidCtl.Abort() + } fmt.Println("... deconstruct old gadget") + //ToDo: Former gadgets are destroyed without testing if there're changes, this should be aborted if GadgetSettingsState == GetDeployedGadgetSettings() gm.DestroyGadget(USB_GADGET_NAME) var usesUSBEthernet bool @@ -746,10 +763,12 @@ func (gm *UsbGadgetManager) DeployGadgetSettings(settings *pb.GadgetSettings) er } log.Printf("Enabeling gadget for UDC: %s\n", udcName) if err = ioutil.WriteFile(USB_GADGET_DIR+"/UDC", []byte(udcName), os.ModePerm); err != nil { + fmt.Println("... error enabling gadget:", err) return err } - //update device path' + //update device path + log.Println("Retrieving path to HID devices") if devPath,errF := enumDevicePath(USB_FUNCTION_HID_KEYBOARD_name); errF == nil { gm.State.DevicePath[USB_FUNCTION_HID_KEYBOARD_name] = devPath } if devPath,errF := enumDevicePath(USB_FUNCTION_HID_MOUSE_name); errF == nil { gm.State.DevicePath[USB_FUNCTION_HID_MOUSE_name] = devPath } if devPath,errF := enumDevicePath(USB_FUNCTION_HID_RAW_name); errF == nil { gm.State.DevicePath[USB_FUNCTION_HID_RAW_name] = devPath } @@ -759,6 +778,7 @@ func (gm *UsbGadgetManager) DeployGadgetSettings(settings *pb.GadgetSettings) er devPathKeyboard := gm.State.DevicePath[USB_FUNCTION_HID_KEYBOARD_name] devPathMouse := gm.State.DevicePath[USB_FUNCTION_HID_MOUSE_name] + //log.Printf("Starting HID controller (kbd %s, mouse %s)...\n", devPathKeyboard, devPathMouse) var errH error gm.hidCtl, errH = hid.NewHIDController(context.Background(), devPathKeyboard, PATH_KEYBOARD_LANGUAGE_MAPS, devPathMouse) gm.hidCtl.SetEventHandler(gm) diff --git a/service/rpc_server.go b/service/rpc_server.go index 99b1548..5c76d1a 100644 --- a/service/rpc_server.go +++ b/service/rpc_server.go @@ -456,11 +456,7 @@ func (s *server) DeployStoredUSBSettings(ctx context.Context, m *pb.StringMessag defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_USB)) ws,err := s.GetStoredUSBSettings(ctx,m) if err != nil { return &pb.GadgetSettings{},err } - st,err = s.SetGadgetSettings(ctx, ws) - if err != nil { - return - } - _,err = s.DeployGadgetSetting(ctx, &pb.Empty{}) + st,err = s.DeployGadgetSetting(ctx, ws) return } @@ -954,15 +950,14 @@ func (s *server) GetDeployedGadgetSetting(ctx context.Context, e *pb.Empty) (gs return } -func (s *server) DeployGadgetSetting(context.Context, *pb.Empty) (gs *pb.GadgetSettings, err error) { +func (s *server) DeployGadgetSetting(ctx context.Context, newGs *pb.GadgetSettings) (gs *pb.GadgetSettings, err error) { log.Printf("Called DeployGadgetSettings\n") defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_USB)) gs_backup,_ := s.rootSvc.SubSysUSB.ParseGadgetState(USB_GADGET_NAME) - //ToDo: Former gadgets are destroyed without testing if there're changes, this should be aborted if GadgetSettingsState == GetDeployedGadgetSettings() - //s.rootSvc.SubSysUSB.DestroyGadget(USB_GADGET_NAME) //already done by deploy - errg := s.rootSvc.SubSysUSB.DeployGadgetSettings(s.rootSvc.SubSysUSB.State.UndeployedGadgetSettings) + + errg := s.rootSvc.SubSysUSB.DeployGadgetSettings(newGs) err = nil if errg != nil { err = errors.New(fmt.Sprintf("Deploying new gadget settings failed, reverted to old ones: %v", errg)) @@ -973,22 +968,6 @@ func (s *server) DeployGadgetSetting(context.Context, *pb.Empty) (gs *pb.GadgetS return } -func (s *server) GetGadgetSettings(context.Context, *pb.Empty) (*pb.GadgetSettings, error) { - return s.rootSvc.SubSysUSB.State.UndeployedGadgetSettings, nil -} - -func (s *server) SetGadgetSettings(ctx context.Context, gs *pb.GadgetSettings) (res *pb.GadgetSettings, err error) { - defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_USB)) - if err = ValidateGadgetSetting(*gs); err != nil { - //We return the validation error and the current (unchanged) GadgetSettingsState - res = s.rootSvc.SubSysUSB.State.UndeployedGadgetSettings - return - } - s.rootSvc.SubSysUSB.State.UndeployedGadgetSettings = gs - res = s.rootSvc.SubSysUSB.State.UndeployedGadgetSettings - return -} - func (s *server) GetLEDSettings(context.Context, *pb.Empty) (res *pb.LEDSettings, err error) { // res, err = ServiceState.Led.GetLed() state := s.rootSvc.SubSysLed.GetState() diff --git a/web_client/hvueCompUSBSettings.go b/web_client/hvueCompUSBSettings.go index 327bf44..5b3e365 100644 --- a/web_client/hvueCompUSBSettings.go +++ b/web_client/hvueCompUSBSettings.go @@ -219,7 +219,7 @@ const (
- USB Gadget Settings ({{ currentGadgetSettings.UmsSettings }}) + USB Gadget Settings diff --git a/web_client/hvueComponentsTriggerActions.go b/web_client/hvueComponentsTriggerActions.go index 0721262..3981d3e 100644 --- a/web_client/hvueComponentsTriggerActions.go +++ b/web_client/hvueComponentsTriggerActions.go @@ -922,7 +922,7 @@ const templateAction = ` Type - Name of the stored settings template to load + Select the type of the template to load diff --git a/web_client/mvuexGlobalState.go b/web_client/mvuexGlobalState.go index 7f26494..f032caf 100644 --- a/web_client/mvuexGlobalState.go +++ b/web_client/mvuexGlobalState.go @@ -1504,15 +1504,9 @@ func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.Action //get current GadgetSettings curGS := state.CurrentGadgetSettings.toGo() - //try to set them via gRPC (the server holds an internal state, setting != deploying) - err := RpcClient.SetRemoteGadgetSettings(curGS, defaultTimeoutShort) - if err != nil { - QuasarNotifyError("Error in pre-check of new USB gadget settings", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) - return - } //try to deploy the, now set, remote GadgetSettings via gRPC - _, err = RpcClient.DeployRemoteGadgetSettings(defaultTimeout) + _, err := RpcClient.DeployRemoteGadgetSettings(defaultTimeout, curGS) if err != nil { QuasarNotifyError("Error while deploying new USB gadget settings", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) return diff --git a/web_client/rpcClient.go b/web_client/rpcClient.go index 47129db..9c54038 100644 --- a/web_client/rpcClient.go +++ b/web_client/rpcClient.go @@ -678,6 +678,7 @@ func (rpc *Rpc) GetDeployedGadgetSettings(timeout time.Duration) (*pb.GadgetSett } +/* func (rpc *Rpc) SetRemoteGadgetSettings(targetGS *pb.GadgetSettings, timeout time.Duration) (err error) { //gs := vue.GetVM(c).Get("gadgetSettings") println("SetRemoteGadgetSettings called") @@ -696,15 +697,16 @@ func (rpc *Rpc) SetRemoteGadgetSettings(targetGS *pb.GadgetSettings, timeout tim return nil } +*/ -func (rpc *Rpc) DeployRemoteGadgetSettings(timeout time.Duration) (*pb.GadgetSettings, error) { +func (rpc *Rpc) DeployRemoteGadgetSettings(timeout time.Duration, targetGS *pb.GadgetSettings) (*pb.GadgetSettings, error) { //gs := vue.GetVM(c).Get("gadgetSettings") println("DeployRemoteGadgetSettings called") ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - return rpc.Client.DeployGadgetSetting(ctx, &pb.Empty{}) + return rpc.Client.DeployGadgetSetting(ctx, targetGS) }