From 51490ae6e67557e36728251adb349da50268aa7d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 16 Mar 2021 13:32:05 +0000 Subject: [PATCH] Fault injection add lws_xos: xoshiro256 PRNG --- .sai.json | 4 + READMEs/README.fault-injection.md | 356 +++++++++++++++--- READMEs/README.udp.md | 8 +- doc-assets/fault-injection.png | Bin 0 -> 246170 bytes include/libwebsockets/lws-adopt.h | 8 +- include/libwebsockets/lws-client.h | 7 +- include/libwebsockets/lws-context-vhost.h | 10 +- include/libwebsockets/lws-fault-injection.h | 124 +++++- include/libwebsockets/lws-misc.h | 2 +- .../libwebsockets/lws-secure-streams-client.h | 1 + include/libwebsockets/lws-secure-streams.h | 2 +- lib/core-net/adopt.c | 23 +- lib/core-net/client/connect.c | 57 ++- lib/core-net/client/connect2.c | 12 +- lib/core-net/client/connect3.c | 22 +- lib/core-net/close.c | 2 +- lib/core-net/output.c | 23 +- lib/core-net/private-lib-core-net.h | 4 +- lib/core-net/route.c | 5 + lib/core-net/vhost.c | 58 ++- lib/core-net/wsi.c | 12 + lib/core/context.c | 136 +++++-- lib/core/libwebsockets.c | 51 ++- lib/core/private-lib-core.h | 4 +- lib/misc/CMakeLists.txt | 1 + lib/misc/prng.c | 80 ++++ lib/plat/unix/unix-service.c | 1 + lib/roles/h2/http2.c | 3 + lib/roles/http/server/server.c | 20 +- lib/roles/raw-skt/ops-raw-skt.c | 17 +- lib/secure-streams/policy-json.c | 15 + .../private-lib-secure-streams.h | 6 +- lib/secure-streams/secure-streams-client.c | 55 ++- lib/secure-streams/secure-streams-process.c | 55 ++- lib/secure-streams/secure-streams-serialize.c | 31 +- lib/secure-streams/secure-streams.c | 40 +- lib/system/async-dns/async-dns.c | 4 +- lib/system/dhcpclient/dhcpc4.c | 2 +- lib/system/fault-injection/fault-injection.c | 305 +++++++++++++-- lib/system/ntpclient/ntpclient.c | 2 +- .../api-tests/api-test-lws_dsh/main.c | 94 ++++- .../api-tests/api-test-lws_struct-json/main.c | 3 +- .../api-tests/api-test-lws_tokenize/main.c | 10 +- .../minimal-http-client-fi/CMakeLists.txt | 37 -- .../minimal-http-client-fi/README.md | 76 ---- .../minimal-http-client.c | 346 ----------------- .../minimal-http-client-fi/warmcat.com.cer | 21 -- .../minimal-http-client/CMakeLists.txt | 110 +++++- .../minimal-http-client/minimal-http-client.c | 54 ++- .../minimal-http-server-eventlib-foreign.c | 3 + .../minimal-raw-adopt-udp.c | 3 +- .../minimal-secure-streams-proxy/main.c | 39 +- .../minimal-secure-streams.c | 21 +- 53 files changed, 1543 insertions(+), 842 deletions(-) create mode 100644 doc-assets/fault-injection.png create mode 100644 lib/misc/prng.c delete mode 100644 minimal-examples/http-client/minimal-http-client-fi/CMakeLists.txt delete mode 100644 minimal-examples/http-client/minimal-http-client-fi/README.md delete mode 100644 minimal-examples/http-client/minimal-http-client-fi/minimal-http-client.c delete mode 100644 minimal-examples/http-client/minimal-http-client-fi/warmcat.com.cer diff --git a/.sai.json b/.sai.json index 692203e73..1d9fcfc98 100644 --- a/.sai.json +++ b/.sai.json @@ -117,6 +117,10 @@ "cmake": "-DLWS_WITH_UDP=0", "platforms": "w10/x86_64-amd/msvc, w10/x86_64-amd/noptmsvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, w10/x86_64-amd/mingw32, w10/x86_64-amd/mingw64, netbsd/aarch64BE-bcm2837-a53/gcc, w10/x86_64-amd/wmbedtlsmsvc" }, + "fault-injection": { + "cmake": "-DLWS_WITH_SYS_FAULT_INJECTION=1 -DLWS_WITH_MINIMAL_EXAMPLES=1", + "platforms": "w10/x86_64-amd/msvc" + }, "esp32-heltec": { "cmake": "-DLWS_IPV6=0", "cpack": "esp-heltec-wb32", diff --git a/READMEs/README.fault-injection.md b/READMEs/README.fault-injection.md index d2b21245d..b7e3f3076 100644 --- a/READMEs/README.fault-injection.md +++ b/READMEs/README.fault-injection.md @@ -1,40 +1,116 @@ # `lws_fi` Fault Injection -To provide better quality there's a need to not just test the code paths for -normal operation, but also that it acts correctly under various fault -conditions that may be difficult to arrange at test-time. +Most efforts during development go towards trying to make the system do what +it is supposed to do during normal operation. -Code handling the failures may be anywhere including during early initialization -or in user code before lws intialization. +But to provide reliable quality there's a need to not just test the code paths +for normal operation, but also to be able to easily confirm that they act +correctly under various fault conditions that may be difficult to arrange at +test-time. It's otherwise very easy for error conditions that are low +probability to be overlooked and turn out to do the wrong thing, eg, try to +clean up things they had not actually initialized, or forget to free things etc. -To help with this lws has `LWS_WITH_SYS_FAULT_INJECTION` build option that -provides a simple but powerful api for fault injection in any lws or user code. +Code handling the operational failures we want to check may be anywhere, +including during early initialization or in user code before lws intialization. + +To help with this lws has a `LWS_WITH_SYS_FAULT_INJECTION` build option that +provides a simple but powerful api for targeted fault injection in any lws or +user code, and provides a wide range of well-known internal faults inside lws +you can trigger from outside. ## Fault contexts and faults -`lws_fi_t` objects represent a named fault injection rules, just in terms of -whether and how often to inject the fault. +The basic idea is objects in the user code can choose to initialize "fault +contexts" inside objects, that list named, well-known "faults" that the code +supoorts and that the user wants to inject. -`lws_fi_ctx_t` objects are linked-lists of `lws_fi_t` objects. When Fault -Injection is enabled at build-time, the key system objects like the -`lws_context`, `lws_vhost`, `wsi` and Secure Stream handles / SSPC handles -contain their own `lws_fi_ctx_t` lists that may have any number of `lws_fi_t` -added to them. +Although these "fault contexts" can be embedded in objects directly at object +creation time, eg, for lws in the lws_context creation info struct, or the +client connection info struct, or Secure Stream info struct, it's usually +inconvenient to pass the desired faults directly deep into the code and attach +them at creation time. Eg, if you want to cause a fault in a wsi instantiated +by a Secure Stream, that is internal lws code one step removed from the Secure +Stream object creation making it difficult to arrange. -`lws_fi_ctx_t` objects are hierarchical, if a named rule is not found in, eg, -a wsi Fault injection context, then the vhost and finally the lws_context Fault -Injection contexts are searched for it before giving up. This allows for both -global and individual overridden Fault Injection rules at each level. +For that reason, faults have a targeted inheritance scheme using namespace +paths, it's usually enough to just list the faults you want at context creation +time and they will be filter down to the internal objects you want to target +when they are created later. -## Integrating fault injection conditionals into code +![Fault Injection Overview](../doc-assets/fault-injection.png) -A simple api `lws_fi(fi_ctx, "name")` is provided that returns 0 if no fault to -be injected, or 1 if the fault should be synthesized. If there is no rule -matching "name", the answer is always to not inject a fault, ie, returns 0. +A fault injection request is made in `lws_fi_t` objects, specifying the +fault name and whether, and how often to inject the fault. + +The "fault context" objects `lws_fi_ctx_t` embedded in the creation info +structs are linked-lists of `lws_fi_t` objects. When Fault Injection is enabled +at build-time, the key system objects like the `lws_context`, `lws_vhost`, `wsi` +and Secure Stream handles / SSPC handles contain their own `lws_fi_ctx_t` lists +that may have any number of `lws_fi_t` added to them. + +When downstream objects are created, eg, when an lws_context creates a Secure +Stream, in addition to using any faults provided directly in the SS info, +the lws_context faults are consulted to see if any relate to that streamtype +and should be applied. + +Although faults can be added to objects at creation, it is far more convenient +to just pass a list of faults you want into the lws_context and have the +objects later match them using namespacing, described later. + +## Integrating fault injection conditionals into code in private lws code + +A simple query api `lws_fi(fi_ctx, "name")` is provided that returns 0 if no +fault to be injected, or 1 if the fault should be synthesized. If there is no +rule matching "name", the answer is always to not inject a fault, ie, returns 0. + +Similarly for convenience if FAULT_INJECTION is disabled at build, the `lws_fi()` +call always returns the constant `0`. By default then just enabling Fault Injection at build does not have any impact -on code operation since the user must first add the fault injection rules he -wants. +on code operation since the user must also add the fault injection rules he +wants to the objects's Fault Injection context. + +## Integrating fault injection conditionals into user code with public apis + +These public apis query the fault context in a wsi, lws_context, ss handle, or +sspc handle (client side of proxy) to find any matching rule, if so they return +1 if the conditions (eg, probability) are met and the fault should be injected. + +These allow user code to use the whole Fault Injection system without having to +understand anything except the common object like a wsi they want to query and +the name of the fault rule they are checking. + +|FI context owner|Public API| +|---|---| +|lws_context|`int lws_fi_user_context_fi(struct lws_context *ctx, const char *rule)`| +|wsi|`int lws_fi_user_wsi_fi(struct lws *wsi, const char *rule)`| +|ss handle|`int lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *rule)`| +|sspc handle|`int lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *rule)`| + +For example, the minimal-http-client user code example contains this in its +ESTABLISHED callback + +``` + if (lws_fi_user_wsi_fi(wsi, "user_reject_at_est")) + return -1; +``` + +which can be triggered by running it with + +`lws-minimal-http-client --fault-injection 'wsi/user_reject_at_est'`, causing + +``` +... +[2021/03/11 13:41:05:2769] U: Connected to 46.105.127.147, http response: 200 +[2021/03/11 13:41:05:2776] W: lws_fi: Injecting fault unk->user_reject_at_est +[2021/03/11 13:41:05:2789] E: CLIENT_CONNECTION_ERROR: HS: disallowed at ESTABLISHED +... +``` + +When `LWS_WITH_SYS_FAULT_INJECTION` is disabled, these public apis become +preprocessor defines to `(0)`, so the related code is removed by the compiler. + +## Types of fault injection "when" strategy The api keeps track of each time the context was asked and uses this information to drive the decision about when to say yes, according to the type of rule @@ -44,49 +120,215 @@ to drive the decision about when to say yes, according to the type of rule |`LWSFI_ALWAYS`|Unconditionally inject the fault| |`LWSFI_DETERMINISTIC`|after `pre` times without the fault, the next `count` times exhibit the fault`| |`LWSFI_PROBABILISTIC`|exhibit a fault `pre` percentage of the time| -|`LWSFI_PATTERN`|Reference `pre` bits pointed to by `pattern` and fault if the bit set| +|`LWSFI_PATTERN`|Reference `pre` bits pointed to by `pattern` and fault if the bit set, pointing to static array| +|`LWSFI_PATTERN_ALLOC`|Reference `pre` bits pointed to by `pattern` and fault if the bit set, pointing to allocated array, freed when fault goes out of scope| + +Probabalistic choices are sourced from a PRNG with a seed set in the context +creation info Fault Injection Context. By default the lws helper +`lws_cmdline_option_handle_builtin()` sets this to the time in us, but it can +be overridden using `--fault-seed `, and the effective PRNG seed is +logged when the commandline options are initially parsed. ## Addings Fault Injection Rules to `lws_fi_ctx_t` -User code should prepare a `lws_fi_ctx_t` cleared down to zero if necessary, -and one of these, eg on the stack +Typically the lws_context is used as the central, toplevel place to define +faults. This is done by adding prepared `lws_fi_t` objects on the stack one by +one to the context creation info struct's `.fic` member, using +`lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi);`, this will allocate and copy +the provided `fi` into the allocation, and attach it to the `lws_fi_ctx_t` list. -``` -typedef struct lws_fi { - const char *name; - uint8_t *pattern; - uint64_t pre__prob1; - uint64_t count__prob2; - char type; /* LWSFI_* */ -} lws_fi_t; -``` - -and call `lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi);`, this will -allocate and copy the provided `fi` into the allocation, and attach it to -the `lws_fi_ctx_t` list. - -The creation info struct associated with the context, vhost, wsi or Secure -Stream has a `*fi` pointer you can set to your `lws_fi_ctx_t`, when creating -the object it will take ownership of any `lws_fi_t` you attached to it. - -So the `lws_fi_ctx_t` and the `lws_fi_t` used as a template for adding the -rules may be on the stack and safely and go out of scope after the object -creation api is called. The `lws_fi_t` `name` is also copied into the -allocation and does not need to continue to exist after it is added to the -`lws_fi_ctx_t`. The only exception is the `pattern` member if used, the -array pointed to is not copied and must exist for the lifetime of the rule. +When the context (or other object using the same scheme) is created, it imports +all the faults from the info structure `.fic` and takes ownership of them, +leaving the info `.fic` empty and ready to go out of scope. ## Passing in fault injection rules A key requirement is that Fault Injection rules must be availble to the code creating an object before the object has been created. This is why the user -code prepares a temporary context listing his rules, and offers it as part of -the creation info struct, rather than waiting for the object to be created and -then attach Fault Injection rules... it's too late to test faults during the -creation by then otherwise. +code prepares a Fault Injection context listing his rules in the creation info +struct, rather than waiting for the object to be created and then attach Fault +Injection rules... it's too late then to test faults during the creation. + +## Directly applying fault contexts + +You can pass in a Fault Injection context prepared with lws_fi_t added to it +when creating the following kinds of objects + +|Object being created|info struct|Fault injection Context member| +|---|---|---| +|lws context|struct lws_context_creation_info|`fic`| +|vhost|struct lws_context_creation_info|`fic`| +|Secure Stream|struct lws_ss_info|`fic`| +|client wsi|struct lws_client_connect_info|`fic`| + +However typically the approach is just provide a list of faults at context +creation time, and let the objects match and inherit using namespacing, +described next. ## Using the namespace to target specific instances -Wsi client connection can directly have fault injection objects attached to it -at client connection creation time. +Lws objects created by the user can directly have a Fault Injection context +attached to them at creation time, so the fault injection objects directly +relate to the object. +But in other common scenarios, there is no direct visibility of the object that +we want to trigger faults in, it may not exist until some time later. Eg, we +want to trigger faults in the listen socket of a vhost. To allow this, the +fault names can be structured with a /path/ type namespace so objects created +later can inherit faults. + +Notice that if you are directly creating the vhost, Secure Stream or wsi, you +can directly attach the subrule yourself without the namespacing needed. The +namespacing is used when you have access to a higher level object at creation- +time, like the lws_context, and it will itself create the object you want to +target without your having any direct access to it. + +|namespace form|effect| +|---|---| +|**vh=myvhost/**subrule|subrule is inherited by the vhost named "myvhost" when it is created| +|**vh/**subrule|subrule is inherited by any vhost when it is created| +|**ss=mystream/**subrule|subrule is inherited by SS of streamtype "mystream" (also covers SSPC / proxy client)| +|**ss/**subrule|subrule is inherited by all SS of any streamtype (also covers SSPC / proxy client)| +|**wsi=myname/**subrule|subrule is inherited by client wsi created with `info->fi_wsi_name` "myname"| +|**wsi/**subrule|subrule is inherited by any wsi| + +Namespaces can be combined, for example `vh=myvhost/wsi/listenskt` will set the +`listenskt` fault on wsi created by the server vhost "myvhost", ie, it will +cause the listen socket for the vhost to error out on creation. + +In the case of wsi migration when it's the network connection wsi on an h2 +connection that is migrated to be SID 1, the attached faults also migrate. + +Here is which Fault Injection Contexts each type of object inherits matching +Fault Injection rules from: + +|Object type|Initialized with|Inherit matching faults from| +|---|---|---| +|context|`struct lws_context_creation_info` .fic|-| +|vhost|`struct lws_context_creation_info` .fic|context FIC| +|client wsi|`struct lws_client_connect_info` .fic|context FIC, vhost FIC| +|ss / sspc|`lws_ss_info_t` .fic|context FIC| +|ss / sspc wsi|-|context FIC, vhost FIC, ss / sspc .fic| + +Since everything can be reached from the lws_context fault context, directly or +by additional inheritence, and that's the most convenient to set from the +outside, that's typically the original source of all injected faults. + +## Integration with minimal examples + +All the minimal examples that use the `lws_cmdline_option_handle_builtin()` api +can take an additional `--fault-injection "...,..."` switch, which automatically +parses the comma-separated list in the argument to add faults with the given +name to the lws_context. For example, + +`lws-minimal-http-client --fault-injection "wsi/dnsfail"` + +will force all wsi dns lookups to fail for that run of the example. + +### Specifying when to inject the fault + +By default, if you just give the name part, if the namespace is absent or +matches an object, the fault will be injected every time. It's also possible +to make the fault inject itself at a random probability, or in a cyclic pattern, +by giving additional information in brackets, eg + +|Syntax|Meaning| +|---|---| +|`wsi/thefault`|Inject the fault every time| +|`wsi/thefault(10%)`|Randomly inject the fault at 10% probability| +|`wsi/thefault(.............X.X)`|Inject the fault on the 14th and 16th try, every 16 tries| + +You must quote the strings containing these symbols, since they may otherwise be +interpreted by your shell. + +## Well-known fault names in lws + +|Scope|Namespc|Name|Fault effect| +|---|---|---|---| +|context||`ctx_createfail1`|Fail context creation immediately at entry| +|context||`ctx_createfail_plugin_init`|Fail context creation as if a plugin init failed (if plugins enabled)| +|context||`ctx_createfail_evlib_plugin`|Fail context creation due to event lib plugin failed init (if evlib plugins enabled)| +|context||`ctx_createfail_evlib_sel`|Fail context creation due to unable to select event lib| +|context||`ctx_createfail_oom_ctx`|Fail context creation due to OOM on context object| +|context||`ctx_createfail_privdrop`|Fail context creation due to failure dropping privileges| +|context||`ctx_createfail_maxfds`|Fail context creation due to unable to determine process fd limit| +|context||`ctx_createfail_oom_fds`|Fail context creation due to OOM on fds table| +|context||`ctx_createfail_plat_init`|Fail context creation due to platform init failed| +|context||`ctx_createfail_evlib_init`|Fail context creation due to event lib init failed| +|context||`ctx_createfail_evlib_pt`|Fail context creation due to event lib pt init failed| +|context||`ctx_createfail_sys_vh`|Fail context creation due to system vhost creation failed| +|context||`ctx_createfail_sys_vh_init`|Fail context creaton due to system vhost init failed| +|context||`ctx_createfail_def_vh`|Fail context creation due to default vhost creation failed| +|context||`ctx_createfail_ss_pol1`|Fail context creation due to ss policy parse start failed (if policy enabled)| +|context||`ctx_createfail_ss_pol2`|Fail context creation due to ss policy parse failed (if policy enabled)| +|context||`ctx_createfail_ss_pol3`|Fail context creation due to ss policy set failed (if policy enabled)| +|vhost|`vh`|`vh_create_oom`|Fail vh creation on vh object alloc OOM| +|vhost|`vh`|`vh_create_pcols_oom`|Fail vh creation at protocols alloc OOM| +|vhost|`vh`|`vh_create_access_log_open_fail`|Fail vh creation due to unable to open access log (LWS_WITH_ACCESS_LOG)| +|vhost|`vh`|`vh_create_ssl_srv`|Fail server ssl_ctx init| +|vhost|`vh`|`vh_create_ssl_cli`|Fail client ssl_ctx init| +|vhost|`vh`|`vh_create_srv_init`|Fail server init| +|vhost|`vh`|`vh_create_protocol_init`|Fail late protocol init (for late vhost creation)| +|srv vhost|`vh=xxx/wsi`|`listenskt`|Causes `socket()` allocation for vhost listen socket to fail| +|cli wsi|`wsi`|`dnsfail`|Sync: `getaddrinfo()` is not called and a EAI_FAIL return synthesized, Async: request not started and immediate fail synthesized| +|cli wsi|`wsi`|`sendfail`|Attempts to send data on the wsi socket fail| +|cli wsi|`wsi`|`connfail`|Attempts to connect on the wsi socket fail| +|cli wsi|`wsi`|`createfail`|Creating the client wsi itself fails| +|udp wsi|`wsi`|`udp_rx_loss`|Drop UDP RX that was actually received, useful with probabalistic mode| +|udp wsi|`wsi`|`udp_tx_loss`|Drop UDP TX so that it's not actually sent, useful with probabalistic mode| +|srv ss|`ss`|`ss_srv_vh_fail`|Secure Streams Server vhost creation forced to fail| +|cli ss|`ss`|`ss_no_streamtype_policy`|The policy for the streamtype is made to seem as if it is missing| +|sspc|`ss`|`sspc_fail_on_linkup`|Reject the connection to the proxy when we hear it has succeeded, it will provoke endless retries| +|sspc|`ss`|`sspc_fake_rxparse_disconnect_me`|Force client-proxy link parse to seem to ask to be disconnected, it will provoke endless retries| +|sspc|`ss`|`sspc_fake_rxparse_destroy_me`|Force client-proxy link parse to seem to ask to destroy the SS, it will destroy the SS cleanly| +|sspc|`ss`|`sspc_link_write_fail`|Force write on the link to fail, it will provoke endless retries| +|sspc|`ss`|`sspc_create_oom`|Cause the sspc handle allocation to fail as if OOM at creation time| +|sspc|`ss`|`sspc_fail_metadata_set`|Cause the metadata allocation to fail| +|sspc|`ss`|`sspc_rx_fake_destroy_me`|Make it seem that client's user code *rx() returned DESTROY_ME| +|sspc|`ss`|`sspc_rx_metadata_oom`|Cause metadata from proxy allocation to fail| +|ssproxy|`ss`|`ssproxy_dsh_create_oom`|Cause proxy's creation of DSH to fail| +|ssproxy|`ss`|`ssproxy_dsh_rx_queue_oom`|Cause proxy's allocation in the onward SS->P[->C] DSH rx direction to fail as if OOM, this causes the onward connection to disconnect| +|ssproxy|`wsi`|`ssproxy_client_adopt_oom`|Cause proxy to be unable to allocate for new client - proxy link connection object| +|ssproxy|`wsi`|`ssproxy_client_write_fail`|Cause proxy write to client to fail| +|ssproxy|`wsi`|`sspc_dsh_ss2p_oom`|Cause ss->proxy dsh allocation to fail| +|ssproxy|`ss`|`ssproxy_onward_conn_fail`|Act as if proxy onward client connection failed immediately| +|ssproxy|`ss`|`ssproxy_dsh_c2p_pay_oom`|Cause proxy's DSH alloc for C->P payload to fail| + + +## Well-known namespace targets + +Namespaces can be used to target these more precisely, for example even though +we are only passing the faults we want inject at the lws_context, we can use +the namespace "paths" to target only the wsis created by other things. + +To target wsis from SS-based connections, you can use `ss=stream_type_name/`, +eg for captive portal detection, to have it unable to find its policy entry: + +`ss=captive_portal_detect/ss_no_streamtype_policy` (disables CPD from operating) + +...to force it to fail to resolve the server DNS: + +`ss=captive_portal_detect/wsi/dnsfail` (this makes CPD feel there is no internet) + +...to target the connection part of the captive portal testing instead: + +`ss=captive_portal_detect/wsi/connfail` (this also makes CPD feel there is no internet) + +### Well-known internal wsi type names + +Wsi created for internal features like Async DNS processing can also be targeted + +|wsi target|Meaning| +|---|---| +|`wsi=asyncdns/`|UDP wsi used by lws Async DNS support to talk to DNS servers| +|`wsi=dhcpc/`|UDP wsi used by lws DHCP Client| +|`wsi=ntpclient/`|UDP wsi used by lws NTP Client| + +For example, passing in at lws_context level `wsi=asyncdns/udp_tx_loss` +will force async dns to be unable to resolve anything since its UDP tx is +being suppressed. + +At client connection creation time, user code can also specify their own names +to match on these `wsi=xxx/` namespace parts, so the faults only apply to +specific wsi they are creating themselves later. This is done by setting the +client creation info struct `.fi_wsi_name` to the string "xxx". diff --git a/READMEs/README.udp.md b/READMEs/README.udp.md index ee3d94eda..e986be8b2 100644 --- a/READMEs/README.udp.md +++ b/READMEs/README.udp.md @@ -44,7 +44,7 @@ In the callback, it should simply call `lws_callback_on_writable()` for the udp ## Simulating packetloss -lws now allows you to set the amount of simulated packetloss on udp rx and tx in -the context creation info struct, using `.udp_loss_sim_tx_pc` and `.udp_loss_sim_rx_pc`, -the values are percentages between 0 and 100. 0, the default, means no packetloss. - +You can simulate udp packetloss at tx and rx by using the Fault Injection apis +with the well-known fault names "udp_tx_loss" and "udp_rx_loss", typically +with the probabilistic setting, in commandline format something like +`--fault-injection "wsi/udp_tx_loss(10%)"` diff --git a/doc-assets/fault-injection.png b/doc-assets/fault-injection.png new file mode 100644 index 0000000000000000000000000000000000000000..acaf9d42b5cb651665ca50cc2b6a09208ddde858 GIT binary patch literal 246170 zcmd43cRbep`v&~EkWtAhp(0XLDkNl+kup*#M9L=dPJsVI`HD6@nlA=$H3 z_6pfN$EW-5{{H@X{(Js-dbvlquFrd%@AEv)<2c?|z!5Dq#+6(v34&l$Kd5|^AZRG~ z=O;ZazH{Vl9v}Y0aQ>kFC4yk*ApfC6pLUVOH#r?u^c;^lSU6rjd(oV@eEITjYx{GT zOwXP--|cYGGI~UYiy$@=>dK18U1EkhT(2B&Sd?FCdUd%`;{@wL`cw4Ml$I4Lrrz%p z1y#0Mt+<@F^vo{j5altAyv^Xz7p*qC2AVcW?4W~ zN9U*2E~fAOsKIKc+gVewh3ReVrJDVhBP(O3WrIr6Lu&gyhCGJGO7XTKaW!!hSvGO`9~` z&MPpjj^S84vyX>;2U(nBA+$QSf z_{?}uTa1=vc$vwAfdLymA@)pzG_$OhCq+eZL(bCsH?B!}{ya%R@u~vls`0m5S107? zg-y#>ztWDE>$%P>!B(eC#GX35$5+9{MUrpJ78Wk9m42m^{Ejuz)y@$%AF&hUb_{8Z zyU1AC+WOY_D<3#OZDV6|U( zi@c7J9~Cz@wbeE^_lZYpJQ57F$ZgxFq9Ybmroje3M(&fLmI-Au-_#l6l}Qr-tWWov@!LY72Mq1o>cvqTjp1HyXF6_ zzQ??sxHU&O7;K#?u_svlE_MamtQr?^%T+yRwZ@)V;GxLSlvZqzl&&AAd<1UTI zPo7-PEhs2BLjQpI_P}|`wL}WDQp56;i;RJu-hB(v$S;V+z@VV|4<9}VZr`phZS2Po zleM{|z;)vJI;8^og#78>+_G+)_wVOioSQ0T5D579i5${tDXFO$t`inRtvRc>Lo1rK zlv6O)nUbs2dtMtpH&72-%j?Uh9)>R}g}dhZiibxD^|0d}PZSIdV}5q*RbZlhl$`7? zu~ehJx%*jeCXf42hFnxqA^n-KKaV`~)|a8LA+@RHIqToBT4jikereZsW7nyd2~VF^ z&Od&blasT&T~Ki5co=`EP!)H0<@Y)t%IJSWvbtX~%e-3h zoTB&SQYK3Zg5T$s7gU?#eKleF{kbt-k( z(#G1_1Qit(oztheoraokhlPdp8LpuEbcne-qk?-wf_1AOLEGQ<_U&6?>(BhFH%Z;e zU)=jQe$zL~x~)w;k@j|JalTL@e{f*nbWKgo@-2VEZQ+$^bToM2DJI%H!`)?gq*bH_ zvp1J*k$2Xn)sj7Fqq7seT~yuX1TV2!omDlIJ7i~iL73&7<=>oidVaiuXS_c-KJn$t z#^#?FU%eb@%XP?T8-5_G<2$7%x;~x+}z8vr8mB|o=d-8W@2rw{qJI#4lUe?j116CJ;9ku&wM*MGxJx@ zwQJYXHMSjl$ehTa5Z+?zOgYcMYsel{W|yHSv+Dru+UV*eJV9Jc%&N1LT1)THSTGIM z_xjkc4@2doj@DN^HeV5gGTztXa)wv)5Prn_+`v*Nu;lA3StONk<1sm}|4| ztxanx{BPk84&NeSrdh8M#;=Z26DCx}%EF*o?<-XG4axuQurn&%1Hr&2&z>nCKYmAW z_ik03*rP{}zAF#eaCPrw?Nav354|<eVGFjIb^B$)mfGKpPksbaSfe6 z{fX3d7FnE;k&%fH9#E{UttHv6de^hk+?R0Zj8*c_rQD|^puXizHJ&<~+orAd`)>km zc2%Lj`tF@_GxmT}F}0y}|F&)0GP1KL>4>l->#*rsqVAf%g7RBi@rO^JGDIaQhVkpA zolsU){Z{+nfaI~O-pAHZeT$>UsT1(PzY?wO?KQ?-8@l+^0wUZ{92q zm0zOgyH;ir5a93Mck%oC+cKK=$bzbi(MX+RenA1%d`LD zqx=3;ziDsrtJCu;DBt2|*nO|+y*3Zmtvh#oV`5_Jx#(wF(xz6dVqe`TX1B}x2*DwI zhOqc}|LRZEzsIV4_eK#Bk-pjo)E6&Zq7ZBR9;TL=+^)hOG0l1(!p(uG`@EMR6qJ?1 z__2gy`}QeDm}7wuAsko?LLvEFW=Z@yn)}k1?XNL^J4c8RwON+hAEWjKxf6c_E&mKk z*c+Q1K6!Z_f|;8;F2On~H6(W{c{ z8M0bz8JUE1wiWR`sUX7c^#&!wRNskhEl2Cca*%~i(DV8qEGcHu z{!$P_Fz})b9M|2N)uI8+^X1DI<>c2U3hsW?^n7ki3Sz`$e|?2zF!kRdmtQF>FE<(Z z^0a(;{`asnpO~0fCstx-AS<~QDJfr5Qf@p=;Ytw{5;`mTi z#S6&5&d%=IU2=7cm3`i-1lJjYU{zu^aHD>o`3wM!DuIOsIQf012J%X*loOwaUdau{ z4KJ+f5}lipt2dXlzq<60U)_MAghEKPpQnE9*njbt+NZyX+sK>5i;siK`QV-)-NlD>)E_mpEO3GP*g~21b`;_a&Hn8YNM@0$Yh_6;S zu~udG&Yj_aO)5u^hP|(>Wa;nkALd?DYr}kIr2W+vqJ0H{@@^^gzrAR+Y<_XJuO&-> zC_!nYW8@N3(7AI&Mdz&yw{{*kab)e*45VggB>wjE{{#`|dY14C~&3wq8H`cFTe=@(r zUL}5&0zI-S3z23Xy-hugR$*^+byT7t*S_4}>JjF?H*S2cT(gS4m5uBS*a$-^Vw03( zcLVWvtuu}>Bl(G#mXk+}m6~pihHd{G&p^j2a{QqcJ+)%h53HkN{cSZhHBa#RszjJ) zB?@lKY7uf}T18wrv5Gz==PMC9Q2gl8qY^;-Z(sjHd(-tVcRtUfLRBGZ3*DzVQX9A) z3kDvj7gIajBd>wQ(5zS5r+LW*2N&6>ZCJd`R=hr-^zX54-MEHX_)od3Bg!cX%E~mr z({5Z$k$>x4zVP)MH%#97vk+14)L1Mh-L+elb=DTDdE*)6zjbx}+J;{ahSRL%CAU>W zS(Ioo$vAi-Rrj+1gY7wcZ*N6{_Z`*Zbk&~XjhXE~4_*7a)*R>jzJE7+7~7F$Sz{Gl z&7P!9^Mr}+h;9SQw2!}%|NCSKD? zaeu9fi0+9KA5v023=cDQuctYpJEbK%-kf0?lCko?(MrpPg@^MhUy?4gtcklFmDD1p znYA-8ahm=-x(mq%YTk_Ax;kqQar2~@%+L90%}xO+^A<(P+hr3Ah^*hX%MIr zrG8BE;T3;-)L^4qi4Pyvq2Le-2M_w=(DowpdQef^_IO8h9q@nO$C!|k(qfYng>hO( zZNm<3-@RKarglR~s5W!Su(LK_q9oDRkuL%8{Auj$U({^6e%q+}jQiBUx~C~ANOjRE zDbDHT#oY8Sb_SXV@R?pyz%slvNZY1aAKXdURWo+8(QHm^nH!y(q4|5LgJV5?=$LMl znNSGF(N0*kn`>F=Uu+LFxs=~=0&k_G+n}tRnPhztV6L{8mhe`% zM9opZl$@OGcP{GXT5rt2WNxy*UsZ=pBW6ycIV!`17Z9+r%t6}n6C&cC3?*; zeqH(pR7cG9e-lU0vJftS_$H!}Yx&T?d`3&i#m=6zPfY9<>gzuh!lb7>M9!Q`mLkJl zvyT`egso~f$1&gf8^_Y61@2!3`1vJKF|DF38pNuRu{+sHo?9CrG@J=>LR?ojEih5< zxbD6|HkuO%2lgNpP!Q~H4&H2$lg9p51xxcJT5o6h@9eE6YEw_{0gyoF@vgkw!2kWT zloXXP{#1VTkqBLC+rY%;t?HRiQ*7vJ1$|#oy�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
wF=_SBD(fS9PP?MIBbbH;Z<_1ghEt2GKLoFXN8 zJ8j(xmk;t9->yLN(R`g>oxH3nvsL_gA9wS`?soCaUB%)%PQt?uT)2I8NFOiY*E zi!^iWh2XmE-2)Q}lgG<@j_)}q{S4A<9vn}ESpp^V zQ;8|8JES+d%FHH`0ZRF`QOs=Yy!5ai5E;``Pa!Vd*;tYSF7G~OUKI7LE||!@w;^PF z*3fCwIx>8f>U-R3HS6t|S#u}LJY~K#^6-~J1VU@Erb}oHA}40f>trX%nr-{v*Haa| zQ+n8S=f0+2z*Ctq{obrB=Q)jIGiGBZr6P8pzzlF{Y4@H}0ZoZ#-07Z-KbCg>k7O7Z zwSY}Z2O?YRYrgX(T*E8H6aVC95nR)uk!M-1Y zWH=IktbrjfK4!!}m%}>~6 zPb>Qja^Swo-^a&xgUce%NT$`7qTq4kwiWc%jQ;1vZEa=%qSV-HQb_6QIc{9%#Y3FD z>OU)U5pui5Cv7w+kqL)`8#`^qx{mxAZ6Yk5h!0os)|O?_!-BIDp>>IAjcs$lW4zHI z{K6}8#tp`CQVb;*hg~qmuCZhE`pW?>^;n{RlIo>h{e`Ie(`3HcmGS1XoS<_}Jo`MF!y3EXvu zgSF47oJBb){dUvt(xnU0V*~B?bBL@3mz%yGX)$O=+N{~Lleeq*O_^f#!c2R|ziW5z zewcc)tMYh}ctbBg`!KHU@-`;d?(&%prb?@5Vk`d=T(oF9L zx$EHFiOZJ{5DSdZ6u7!4UN5Ix${aEMdb>#zoSYQMwO7F?U><0Q2d3v|0ck96`f*_@ z78|;L{d)M`sh#GDib5<2&b1OWX<83)3nAonywmp3#%7nI5aUkOj)#sM(IP@i680gu znA~{(uq<*IlI(*o-;PyNR<^~W*{F5v(gzRXnchKw6%1Fz5eg;E7eTo!yyjaC<- ziG)~FtYiIDdAUhngaOVxHRPaqHDNkVUa+qc&&}rz)eJK7Pj6@Ue>dB|r=kC~*A*2N zToybxK0(Db>)Y3W3|lkUl5J}__myctX3n3V()bltEM5+4P;aV2nP^qIdQDLPP@k4) zl!S_^a$NSIL)XBS)FW(dTV5*15RM*X0l7D~vR|J*`oIJ_uiubb#5r8P{HMk4m(7Fj z>v#pEE65-eDIr!E#P^w5nwOL~YMI@=4okZ+tP4-KVCIc_K#rv(;C5oe93=HmNS8?! z;Y9&uySh;JvsX6;qwzf$?8=gU2+&PG3Wr>!`hllva=LCv&V>sT1G{=)iQXb;msyti zpCXr6?n(0MhwMX=s5jQrKH54s$We?7ZI;MQ5T_DWH1?jQ>m8Sl$w$}kv%62eV2DRe zOl)i`FN1I(w4tdP8S-4Y?EU-ghY!~fG7$iqPxoi+Db+1L{WwGo>~}1?v-`KvB;}^< z-ya9R?F!&WSVQ@qf;&{8lj&abFb+~zlxv16J9LmU`5u0J?0d>wKAQsuW*7d{|R# z?PFt3-IL~~mT(NNasx}Ms$!_eO`7Slu1|YchA`Fl%~G#d8j+IA@c*5YHB)oPZbfh> zI8@A31=n9pq8=uoBpZSHK< zKL_OQ0E|-bjR)eT5Vh99r)4SyCNQ7W@Q*MCpkt2Yc|kH?JGcpUJdCS;!GlbUFUU3g z<27gQTpDL9%bHc*Zf@}vArc)4g8&gLy^{VHD+}bGzJ47`Aw&HM6;xl`O1xu)MG34L zOc0dtpcQ2ysqv`)wK%IDyQj~ZrNW7et$+Uc^CEDFn>H86j{dlu+qW&J7CK?q zE;(}SjBt2e%s6A;gQ9!#Kjy{6#Kv_~5)t#dyptD2tY>{sW&g6L3;J_K6-zE#UgWge zh86$7m7E4wiTjdjp-KP{c(5>wtgP%eeJa7HSEv7K&dyuW<#las;`k+=wBR2mwRCPz zRX_;x95cqWd`l>3srN_kk$O%&oD64!8boq{tOpLX!uvJkJa8gXks>aJq7UJ})4b}rH7bQOvJ+Ea++$?+2!jVT5&|QDcBkHT;Lg!gOl@l8Xt$#i zpk$W|k1VX}{$_2f>5gx=7M|bQ%FcasU|?W<2jSiN+;T|N6+x*JYZ{pxM_uzTy*xw2 zZ~n@Q!RAzGIenCQwn9{M)^~oFw+t8F+6*ai?DB9a?hVRo>}iUwmX|NSePjj(wjD z*)gL=K`ZY1iB41~)1+{U31M--BCh?Rv0Bl z69a&{C5e8}YTg>vY18D$0Y&bMJ2l94ggJ7)!nTNidGeQprXp>)6we@hzPkWkw4L$r-Ry3g}mHhx*3yvw+pMzPt zO{SEKl%wnCM7t(Ac@duX$+_1sTyyWHAC^jqoPP0Q=)>#1wgJZt4IGGjXXksR;bw|| zldk`5$bdTsF56I{WL8362ausu^BFT{@4L0?DH56znyU z?u(6)j{$U*TI|lCHwOq|QmM=DBXF2}{c3JxnWAQXe8`mJ$Byanj~sSyBKb{W_(u41 zrug`M@h2;A>8{r>C0%Ecc-24mD4~c|X_NhZv1Wx6j+ea6yDuYx04<=Ucz^UySa$Qb zC+~aB2s5%l9l0>4`*ga1DXa^>cUDg5sYE3IFoAuo)C<>_I~D}k{{bWl&hT^$x^?f) zU(Kvd({5iuc!M{ur>~!O@Zg+>YWdV~!hdJP;(on)MPfxrAA`y3fGHpLZ*Zh!fliQ= zob2FX1RCn>Q(IhBWk^-xO!Wx_4CiMx13gCM{upI|<+b`Y`z4Sm!iT*X8IJzG7>=M| z{ox)Es4m3)UAlJdcFS(jC~`QSakJ8S!HE34UgDf%!*;}LGIV@{vQ{h zac5W8&`_HX#vmKkM|bBA%0PE^ z>&^q4;vOpl%z?SDJF=f3EajasKsk5*yuQuOeUMb`uz+B|%j;61^5ct*ICK7xZP@l; z7Jfk=@FaWB@7KHcYGh%Q6ff@WUVqL13RO9Yix0GB@Fay;(SJ{N$66-l z&I4ZzI|7b|q$}l|y6uT?q3NH#eqDnH&F?-fAmg=$)Np3S_rnF3_>4QPgH(wDQS=;q zAw!hHXHdXbgwE;P8o~;DpG{tIv0D7SSgKw=KC7t;yZY5E(?P&jTn+EqyPoW5^-8KYsIG*CVDms2Ukrw8w#*KwZC- z$VHylvd-Pyvef8p=?FiDgu<;=@K4)0IGSmjaSyrcYcn%nW*=@poTJAh=MCaYHi5Q~ z_KO)$E8DOuy)n>e_#x68ff6bJh;{nxw$KN(iC~wTfARktQ-WH29X|q+KPR5tVg0uw~U}cmN}{z z?BK99n$;L>By1FAI0k$$zz*TYs^>(?Rp(0z9rR?xv0jhTJVuPT&irngqO_&kxOU(E z@zC~g_!A*lU!`;*-x(lI45!>mkN)Cbv*@glz0!BA{o0=k0w4mn(ug{5(dF|+(~k>u z75FV=2iQ5FBET3YHj-J4R*thB{f+2_M5{3Vq$&+w&9OF_=g+rhhKn`1@EZwl3NNCK zzzZcD3E}#mhK`PQ(((*-xN}pKRcEl4*$WsTQsW!-Wa5p}OLv zCYQYMECv$WgC?S{9d&Pl3$_f8&2-O~aErhac z!-#as^y!M!g`gAbetaiSJ|`Os`=#aUSP+A?&!F@#y2X}T=sSEPnpSP(GO3zq0vlOv z#-n-2*R5cSR5$tXtSgi}CHh*XoZu=q=k)v9fp`GzbSipOQJ}+sQXtvk?$h zglgCx3-FhKN|K7Yiux-jd3C3+RNuHb&>;a?8;;7lT26O@T2h(F#O09L@$Yqtuez&h zJ@N_*haR4F+rf+agYJqTa4R$N3^fT&gV&@<-E)teKHZXZf;1!f?d)!Ps#pATS#7FD zNC#B1V@$~#p(b0+P>HHWRBTM*$kHL{-@tp|C0wOd<}&CxhHgJ>|$YT3JdmK3Xs~PBeA>%qv^PA#O2-U=&3^MWlGSXat7{f$pg32C@71 zcR2;IKl4GPs=O>mxoy|3Zf{l*NFbXfWqR!O@%0s6*{PYCPXAf)$i=>oiE4`cWpWOq z<;{1D81gFY_;*Y7vox+R2aE?f@pC&Xf%h|twsoI*WlQpB;oBhEcV^rF*C4ryJi}tGb%(_5?z|Tyd zC*@(Yh0G2m8Q$um35y4A;XI0>5|HdE0y5%WDDUc(H1I+Qu=%!z0FaGZ0#L;ep)!>Am~+;lPc6%&$zPyZ7AaWy|`(lfV9= zQC{LS9`4@rp_P8imTr%V1A2+Ol_-U`fdn}PQ6F|F^0Wh)CL^(vLaZe00wD;Q-1|wm zOWM7AaIKYxVhD4YwJV#%%BzNchnfG-bTE3WPF3(?K@ebw>P8vcb%y^d&jTU#&}bxD zm^*vvkrBkSY@_ACwcJNh)1TbmXbb#8}ezsRgK&OMB{ z_42u(ZJ@S#`s!7uO07z8Q4vw#d?Ag|qNZB&=%ViL$3^GY8&VLS2xq^77Os5jAqciL zGxPI#qy;7CXh6}%QuQ%el#Nr2;q)b-V5_LC_#VVo~8_q{7w)wuZA~aoVURgt+?%otobhw^2eI)D@5(Eo@VZ^pg zGJjqzs6-uWsD<%a)MJ^Js%y@`f8&joAXlke7$d6&o-Z^3Z_h?g?bb`ik$f-q4{m#1 zY@enLh$i0ZkCm4m9vSi&8ALR{N5e=GQjwhM!HNKNcv64Zcj*)riLkyATC$nWiRo;; z1iBQXePuPZ*1aXhd26{d$&%Ez<^Ss5fxz8JjfXuNLq-LPTWC^RVXmz#rYBrtjq35d z6)jN|bGa=`-9nE|?P*BUSYX=pNr?(rGh_~}39UpNBl5G8o}dW3)VfW}mi=b#|2Wp@ zmYF1p%zkri>8;e~3?9G||~? zxSidV)JDKD;mXwnpCCGvUsG1`KXGG`#Mr^U zEx3FXyHj#TUE7(NXrh zfN~Cf=$u&mO7z)85gARX`lQD-K)DsAqOy!Z+owbu&24(>8#{eRn#*-uY?8S@TGbIdVTJa(T zAs;dyU5q9Vo|aJ)+>djU4{zgj4MWUz=sa4{ zC^A^*=d5;OfD`%ebhtI1Z;Xdg9-(1uJ8D^{fVc176^P?BQ?dmL=G0yTlFeEv`I%8n zLhxKrvgA3O8PHMx5`#(k!qfo5yIk%3)>+Ew+oh?SRm{>eGFJ0ZrZ9ksG7-lX0TU+I ziwfL&l8MFoJjSl9E>dJJSbrA&PHo@^+c2AmPH&Ucort>Pve+Q8{^q2F(0UGLroV7jrSeOY2D^EM{OLaONiPruo^zzWt}v zTb7sb<7JAk;_%QQh~ALDUsk)$?$shw7rD9dn8Op3&iSM>rJ_$9I%CGZ+a0^*a}E;# zSq9Nn^JQzQ`zEAYGz{1fq%GAJ_Z&xfK-DR(^0wq(d{s;>#0Fk?$ZOyLQEIMTvL0D( zRJz52{%x3tMDQZ1c&J)u&YLIJKtYCxrBoBO=$$+BZge;59A{6ji_=oZQk&q76vh}9 z4YEAay=^T2w6d}#XOsDFLt^AI>M-bAjsPr>f@%SLYJZdTJx7gN14o(PC16c3N-<3$ zcVJs0%Vg}mls_r7fnuJ+t`LhCeV9 zfPp`g5LLtbFYYo#!B~6Pn_b;g!xo)l?d0I&F>3P^Loa1M$zp7h`+@K=X!qBGV@llj^xuX{_>)26&%N7kP#`OW? z=~G*b!{e3Ih{K(}4;wfdN@%yd{8wL+7|wCFHD;~vM*)nW65Yb@im9==`!X}vPz!*+ zG4WPJHD>gA>YkOw99TUyBaP8DcC;(D%^g-fH3~B}-qkkf0wc)?=4@!z)3UPqzOd3Q zaQTZWr!7F$d;8?s=bD zn?I7_{A=MT_A!bey z#TbV6Nb|gjSc52L_k$D%?@6Exu}iteJHCSA7b}gh>Bo=7)D8V#qX^n0nq&Wqhq4Ff zvHmD}XS-hq33^wdgcE2pJ_ytrotWaGhfUpJcT`;p9Y}c+kfpa_X8^AYV zv6X_I(eKbgFE4myr0Jw66W*k*2d+!fGaEE$rOP83+IX-|F-_(Qptugb@%mT$();%Z zWJq+X=5WiuR*cYH{e0W@?W_(}hPCM8=H@Vc`hSUU|0T^ObUC@_)=Ss!8;bmT3iSs4 zRQ~<@%S)cGmbWsv(aw$h;%_g=dqM=A)pY9gX>s`-E)D$N?all5fBJ>dg^)_FK*(^F zl{~IYKb}j^z3pu?=N0R*1p3H?A4agZAoW7HnLd5Pgyzo?cHwmsH9vJgxGM;X$Zx{8 zZM&an3i@Stf0nkrft+ptNnKa>aW(c-D|T|D*r?AMf`<)N@~2<$V=y&HqdvA~&+ zSA4V)Ju7#k#zcK24;bZ9UEz?X79v(tKn;_^J(V}A2++*k5KtQwvc=o;-B5AG3H)Q+ zF-Mv9JE|<=uELcF7~zf;`%w&_HV(6L3(X}Zg9fopfLCQi1=8rXGh(h35ansZ&>3ImL+paCRn}gQ^H@j20Laj7L5^FtC}y8dlUjM|-R{ zTe~hm@Qk%}Z(^xQ0ns_g7bF&CLH|4LxBuWiVZ6{IXb(^x2JXXTrS_uQ<{h6ucTQVJ zr&s#Y#kS3k6DxdwaoH%03`>`jZCmK-Muq);>nl(a?o2?_hL~P5dfODt)?>;eiV5^v z@C#=Z$i#6-a9ohXW!H}2%O~Xti08#I&x7y-aTi*?!|ofcjf|K==nJk-E_Qf2(pG<3 zS;63An1^C~3KYR86KZN9W89RIA}8VECe~8WXGDCr>koHAtgFi_xQU>I!CK#xP^ng5%W$#StN!Szw#PxjN!A0cQ|)<{KoTr1|7%2 z&+lo>o%d|rWX=f{xqZiu)5eaoq&f!Z5F_#qaqr+Q=Yu{xw@Nq5bDTS621^X69hNLz zD(LpqH}wItEx7Pv;kYE!9PvyXfFdHU`OExx(rX>n-L?ql)XSbbL==DcuqSHfQk%~H z-mMPmI#J9*o=sy6L;uNHU?G(n6Vv*So1i>0nS=S?d$NOhOpE^^;#XUI4QzsE+wtCq zxHocWW?H-dcYIe#-?4|}Ihk{wTrvjYA}du~3Fsv*vsi54oic$6H=hCpq%eQ*X|M_; zRl>d(Y#$>ro1oAIyg`s=fwV=~N~z6vE+OI*QVq8Au>_T|t$lh^zN40G3`~csd`2K* zAPG^kfRliaDR!^T!ZD|L0*%o038%m!ZVieC#}sRCtrys8x8vs4U!HM$Yui%^^6@c6 zYvl#)CPt+QpJ+(L4seqSE-?cHI1(gTzCnT6o9$+Y^v$BK_2=M##66e|NQehH377iuY7HMd?o-O zQ-4MR_`~g}8sO;G(mX`l&y0_aJ53&g1BsfUNQjJ}y}kTHwShK7b-tU7D%W}fFquMf+l zcdZrd0Vq!3;0j`xi54qh+O(o~JMFadOCLYp@ZW#ap;r!C`9quV%QPX*#K2DduLeO| zcT4u*a4?{P!Cs-#tYugCog*CZsNEjTm^W|4k$CeLw*XYh?_17!Y|0vX zJ=(w`&K^m#P~-h2mP@u_m%qT4c`D4YNGO>j*22#Lu~C91!!tQGKixoa)9LHiodMw4 zN1;LpK#T%Yz;@xn-1KN?cNsyU#_wEomQPkSYT#rAq--?mfoG)Q{D1+XZna8-7U0Lp z==D|($j~1}P_d8dN1Q1-#9fhzdUDA8MgD^at$ChQeVeMVUs0kK;?`-r-ANQih~&sG z0A^#gn1V^d(2u82omxu~O8u}W#L_%jg+^Y0E41E1ZwlZi<9_F*)Lv{FmzJzmu)BeQ zPV4Fi55%Ko|3n165PcJ&EY8HpPQ6u;Aj+GW55hWc+w9C+w{G!!`rK*ny%RMJ8{>vO zI*kp;6c5|jXAh1}iK^J3CVCq!Ez{BgzkmOhkwhO_7wp&55MIZhYKeHN-dQs1MZDvw zIRMV%Rr7eT{uVjy)#=2TE8ybPvs6Y75p12@)gpK zV7fzHyVhcqF`dp;uvbX}fODXClK%1}8j@Dp0sTSr3a6GMWah)%W~W%xw_m#gp%#O& ztX;X19+^={;R46c9rtT3cyXfz;WF<1UJF&hJfgIEUGXXhv{!{?7XAal;0AQ=c%5U! zM6ON7h#&d+`BP@h==ZK;7cn~_?U7%dZ3aW=793%~I&pxoNVwR>ughKeo;`c!VgEEV zNORUWV|khS$`pW6)4H00*4A0|PdfO2{xg2hlK)GrI&u26Tr_Sa`FA|JkFFPJha=%6{*;vZk#5m3IZ$` zgImQ6UM5{`9_31O&|uQx+4aLw3J`9^g(V76PVWma4`-cZdbF+klpYs8MHW2S{w!pC zzxX5=cKg)UiZYWCgl+Spc3v{>6j!{H8^5cQotV+mlFLZcw$X%?$f3P+|1h)NL(O&U!uM}774{_ky z_3QQ)dKqdC6R$GW@sr&a^?>~}jQL%mVW(B4|!mJOSz~0m7 zbX^|}_NKun?eHQ2RPSaN_uIXS4Q&l484=z*YBFKuNQWWwXE_D$lNCqD-<#J@2O_(t zIAysyOg&e^%7tm;NNtED_r#Yaz=F2c`f*l>L2 z10QN~dEDN3w0;<|#F^YVBi5k*zF<0dWp?eebt->9X4mfBxfEYUCh&QwxkXz!ckcV_ z@>cxo$J%Gm$s` zqKWP}$^~d!XwSb_Or_Bh(2sh~y<2csn5+%TxV-1HnE!+Hto-pTI{59O(;1hJ*bJux zGU%}t?#opNW;AZ%D~-nv!CCy;(WIdb{; z`}vEE^B3UbE6lP4gG~(l)~t`(`s2nSIl|x}Y8+Zh^|w}(*-I`;;M?9uXXupQyLVmm z9`}@(If>mJS&pGnnr957vz$hh#q#Ehf7Sd1i>iWZ*YvTuNsB)E^%>u=bc`_>9`7vJ zn90&0a##$>zpZ+q-~Ra+awq>yJfK~qTN*A@6w7ylm@V4b=kl+Y=?eEHI%M-Mzh zTW5Lf*}yL@TQ-9?NmJZC<#~J!=1C^>ja^XLc3k{grNs0XT9AMzb?}PFbc>bsr9;J};NEh4aX;Pcdc+UBU@R*XrKk911;5-p z<`Y0+{-Z~e4%e)LQUWO=Y1b|dgv8d_SrmFa93efmGa`4K^$qLKtj}2Lhe+>1CAmh} z>GIzhgVW&&qgpCzzvZz`yXjAo~|di+bt@Zm9RPMn-Tns@ZEdqk_pmxk*LwX z5QPQRAKC!FH1|#)F>5(?kt`;LT0ovo90;N_YcQ0NFbm|ZjpopI1BBp*8%1fw6^&-T zB7QZ02aYAhy!z{)H&j<>nrr8IQ_UeQv7(Mqm6muaNn+Cg12#Dc^=}ljAdS~Xy2gK! zQ|G$i3topjfZ-hZaO7D)3zD6$H@ywo=$~gCQ(#GazkcjGlj(X&GiD zVla7jl1B@=vdrmyL}`cByiEIcy9=Hz=t6-R#Fh2Z3!yMbmX=fUvTL`LrJVu;;ehRym^&Tkvy4_KTAEy|^yRNx2(D z(^H?}OAD>%RQkT}HuwKlzi)@>gH48}vhT_|1;)9aI1I2>fk;`=j^g zkWs=5YwTcyQRj(O@LMb=S-~eXXapvv! z3?}V4p|u0rXioYxx65o4wn1a|i~YZf)+~y~~Lcl3FUwPi1aBVu$C= z4h;MxW@RiOnL7B{hV|=>Pt3D-a=MnV;n3r{FArDYe zC`4R%jEVZ1peRP)uV2ch_l-%fllwh{RZ8#Dnx6oM(jGj8)hacN{F$jB!-E5?X<=ZX zDB;>_$7$NNYo?!HIFPBFgqcVFSbLIy_ z?Tj^(N_>wFFSU~>!?zjtF(2sRQS9|qG99tdnmSL&q>?=brybV<{}Pl}2rSrPsfnNY zdc1LZWRN&t;Z2wS5y%rIw%|ZcohnCdMZbXSlAN$0f`CTAmP-vg^p%<&K;H5nW$_Ax zn1%$FTlMYoua`Z3G(Kt8%M zA$9_h)l$!%ZNF@UN zC?;MA7EX&jVgFGh01*(671KOjl$22+vB`5CbyGtdzRVK8p#e`HeWBrtDhfdEyyfvJ zx)y6?v$-m-I7GsLsiB!MR{sT0C1ZK*?rU0ay|`)TPIb~HLdbGo;5~6j<)mK6-5-a3 zpY#hYz0{C$pXA$`ZrJ}wQteNTgRP#|)@CQlUYNRm3DN-nG7Jyeq_|!utTW{ki9cu6 z;8@ggMHe1;j~h2^U-NMDbk$cL+h>lG5MXehlE&(Kcs@Lx z_TWDthfvB$8EO)L;oMhV7XrO?w0nd@dw->os-FJ(Q$ z!S(YFbZRg%{I$uT#Ne*Cq09L26$HH{;m;8PiD9r%-cywt8W{-!CU52k8um=ZM!GiF z=0SA!tnu}Jv*PRV)dIfTs>h!=k5XQcQF$9#7eytr#_M0J3vS@>qes7*a<0dK0ps4~ z|8%6XwOrb1qM)~r7`{`WrI;tJyKrF;1$*fOHC0vKdF}aV4@H^XJI$Pi4y^$qAQyF_ zO!@@+S0hM@{!iPDbOd87Ue3*Z%q);+p8jm=He|PbfAPU-|wc zb`KJMzam}GWatcucj(wK&e%|%WF#XAyA8>#X>rqw;$Vif($h69Cnxs*4xRc__3R_D zqrAhm6JcZl@9H~vbl_}|aZFc!iYV~j&Ol927;K*K$U5FzT}3K%%43wpKp=CJsO#AnLx5;d+ z_DH=o2&YgXUB#Y~h(0pV=DiQYiWY{3F+5+_j33^5YvNn>7_q%Ubp75dZl6DUwsS`J zr{(aFMAO17MTp(Pn}@H(Niv*NU!L4CwYd?6o-&BK_1AGepBB@2dmj;D$7l5DE*Gks z{D8!TJ3`&Xu9lWrogxdWat<9@gSH1-e+F$8< zO-$HACSd(TDihZd+W|2$rNmPxF_qW0QIr@k$VeiHVfZMfBU|3AByhA%=m-Z5a{*!S z*|Etow(P`=f46u1noFwlPC0x-)gR)m1GONdO+rrnmmgs6XiAm<9mEX(%<7!IZHH)q zI))6;{wvMlM3z2$_^Y{U;K%T+JKui$4y#&yQD0A4*`n9AB5kEEXU1fXep`F=(6_ly z?lqkH`uo($pnIAV9=IMFe<*0w!bpo4<K{E&vl4#SHqdaZz)bm@(cH9AkRLt-YqXrW}6Iv}_fQGTQ<+d0J#F zQ4A@&IvOG+PGZk!jjym5UWfxg>>1Sv{R&LSy-Td;Jv?J~@`(%F5+Q}4oAZR*h>VGC zvTpnJr(~zCJg$tlXRs*ls(T%4f`y!#ovqA>`(w%$dHe6g+AG}OSuJmZkP0$YnY+b6 z`^nGU#31EmZ;94zH!J*+V3p--#iJhUs^<)=} zu)trWBx*!59!!(<5DP}WavfY5UjOkoR$#rlZ`7Hj9{#w9Z7WHE8h{u+C=oyo z+Vs{!R>eG#FjmJ3S(i~QI;#oCP=deyGrgywr@JLbn(~R%EL!|CX z<*m+ufJSWZ{{61|HGl;V46Sox|EvioB0KI9?<=QxXycDP!op2(0hy7h@Oz;A3waBp z?*-Duf^hR)5B%U;xlK4MNFe3^9Oy=Y3e09q87FAkP+S>6KMti+`;6*Q^1kheNS9B#HU2@POYoY=;=eyPcm|bn908Vc~Xpn25@ph^>X5 zYv0XaDz{&%?jplO25B&@F8)CxM4PGvCbrEf2@X9>cpA{P0GB!Wr}hYK11LUwGg6IH z-qlxDRFrJ^?vs5Ci!2dp=?b90b@=BJ7782?J=o{F0=Eir0$c^|!HH45H(m~PD!=5K zzW3wGX>QV=d9s^LJkNzB>at=o_ju>7T{+EoM}TIH)a-%0%V(N13MkU303)A*&`Q<2 z7cTkIm)9w5Bpz)DWA4tcR=Ruj6Sfbfy9=iu&-s48^duXXBg2{-pFoKeLolc;8BHUw z!gU>|iC?qpo}uHq)}4!5bf*KTmdspV^PAmnbTWwdLXQL9OD1&r`9VidivcYmJ2$L( z)%ehGPCjLd#mkTDEf>lxxsacx4rC&Rfc&3!tRw%ac>V+zyzwuDwF+qCrrI$p&`W>9 z9PP%$^Pn+kuvp3~huAi~ewf6hF3F`s(8O`c+oM`AnkHByZ4=Wl(lXW|7yWguS+s)p zFbXG4ie6sMzBU7S7}>=vXK&NL%?6*BH!;0mfQKMe!%gL#*nqKvO_dMCsZM@yERp2{ z*tdupc*_pGP0AUMDa$GQyr=r-ZvE`=(Na_o7z~)Aj^8u-#)A6VQXy9@8<8w=hydI& zLk;2`+hrQuoil5eSIndX)OVx4qU*6YMx2$g;k3shxB5~DWF+9C#N-m!?syX zReUeo0GFfc^n6nolY$5eRaB7Et7F*^Zy|PmF_je#YoG&sTmcA!%2`dhDo+I%Q9bGO zv194}83*0~L}p#@xZQxAA;`$C!z>hq3=rq!)jy8E=1=3+ z*;-vz12GuIULp8KfI)yxXn4QJ!49vNR=ylC#iCKZ0M!oW&BL z!N2QA=B)V$Gjl!4@pXn)=??!!3Kj6fhZh{?u0!byD!7t-AlyKw<&T4G2Kiv5rNSep zV-tP>@lS>Q?tSqYSwpn?yw)6raYM<$Ac;@0e+zzpvNHQJl(R(ws22s=rAw<4p1&VX zQ{y>tqB?T`JR2abM*TZ|YC%kkUh)54^5<~%+H%l#f==9r{?cvyykIJZJX_Jq&`@kd zOc{6w{ynHwsrBTNTo7V3Se_rwz}0xaf^Cmism$(Yu8{HoCc3rPt`d&kOD+6bp#pmP z^r_{O`Kfl7)+ozImbGp1thEI+*RIoknx<(GRC6v}`^F@*eY`b1ZBOnNK1>ng4R|#~C312;+vzeKuXH#h z!|Ak?#yE1-v_m8T0-p|a;Hqaf2oiX|qkRd?@0t1P0Y$wt)85IO@ zOZBK%FdV^JHs4s;P~TZN5Z;VD+FqcVNJYfZlHLNAh~SZKVe%)4V2^}ZxF9Qn@sz7W2OQv^%S~@UWHV$LIN$y z2P#IW!D7Th&d+5+!Xcf?W&+%1*5Hm!0iTO%VgEUqnO%Q>uxNVh_<2&A`;%7kSL5wB zO6+*c5r#aIq|WUrA$jB8OAJ?AmLv_9BnF+D$VOe0N@jtU>wihtz3uIcPI-E%>nTY!D$&EWmzRun!tjV^P_&c#6kdDy?BwW1_;4V`@@GdFBmai@V` z{LqsaPd>^V3s*Ixq4I%PFT|@U-!N|cc-H|oKr%NA0;f&8JLMN&%V?uKn+IH-?Cc`a z9cpzTG{X(aIK51Q!YRVTGs@sz4H7*!i%U8X@lzM~~Fkve`5Xz^;x(C-3F z+WusI^RISKNT~E)Bve4@eJ3>^@ITx;;+sGY0i5u<`4mpt*50!=ZVF27)&Apmr^+{W zwXNvd_ASjm@36vm2|b;mYGMa8ex62RIOOYlq_*cdP%W>Rc0JQ(h=DtAZPO#K6}tzA z#<3(0inNDJ(r>Nh@s887y%WWe7^ z!0L~q2GXOEa-GzMD)?x#@y?j5rgURjUa{Y)yY1c6_S_huC zEaWj%>N?zfzB)KIMkV`o@Y=5_{oJ?G$ZmR(9o29Q~(S-E(y^DX%Q`R$frnk)w&wp0(%}Q6%zT=z@+NBI%|%$arl*dA|?$|$Hib-#;BG(Z5^8( zChMfO_gE0Q$bQVlwg&OckcLegYKo<_TlX96Zcq>3v{W}F0Ygrqa3M1L9ly`5jHHWA z&u^!FPW?}Pv4(-@Y7T2>>vbc<;t0S(9&uVrVv`;Az3;22&>^an7q=MJ{)lmShg3zA z&r2H>WbKCJs(iihe_Vi}_Ga24$y6k=QlB1XbIn&rDAt{7r>(3y&CExJc$EHOAjok{ z>Z7@$NL#9|uQEvo4ph?TI+>UYTXfSrtBRBUEcf^{K0?zpjRM9%pQWz6O?E$C)F5NgL99YVTBNcdv5EnY)E3_m~Thai?Skw98pJCxA8@F z!9`?z>IyebYje#68yxqJ(Mt@C#UAnt_mx_JHp}7kIDi@fOTvusnA$Wq>)31l^mH3n zS4a+%?++O!yTp_X#-QVL@!^k8pO(z1G`AQ6dkaYP3guMeiw5+6p^GNTK67gO#GX*o zmWbQcdbK9hnT*w8%5s88?C9)Vwqf|zo-#zx-))jszBnr}L)41x5Dp|ltH2TxJp%{s zmyrCtdKC>!u&mMg^G*}JS#|?Trt~y)T)n<|2*URfmEullN9p& zdiv3mxgJq!0Z1UK^a0$2ShUog&D#CEF`@R>1W(Pru%h%2@9v@VXXXv^Y%*ydCR6`y zr6c`wj%4l9{zRnOW%N1ewc6GJ)DN6Eeqo6l;Nx@Z%@b3_$+ez8WBD*?`Mroond#}W zWOM3TVT{N~>E-CQE(|jS>5`g5up!*sZdt|}+^eV%urk?u(yHMzc*6gy(W$eeARy3p zu2}i#@#@2uC*Jq(z&W~F5;bRW3+2_T=ymmRjvTqfa1p}y>j((-#Nk%a(%ScET;D!@ zuF=2gYkL*mn9$+d=&$Y&&9PAN^Y@R$LtoHSIWNNAK~odrZS3vYxNj(vLE%U{-~1sdXpr8U98 zMweo{YXV~ons`hbkTyAYSp{JdJ&)%r{C`>dtU%cl*7S4V?M78iO+{Kjrpi*dbtNKa zNt-Q4`i1f18%xjbA^u$`=|le*VOu-br6UQVb_}Gi&G$^=ivn~8=Gi$6Cid?h-?nig-%&0|LMU54$2=&lCbO(*c5fA z@FTTi3p+Q7(Mdbpe3`mnZm9~OoLwo+eXj=7Tn=e9r5@YkMdic7Cl#S`Vh(_tof$z{+|F49~EPE?Siez4-XwpDCvw`f(-VsTm2&s_OmP%QLtjI_iB_*(E|9lVwoIWt$WGP^SzAga6Z>>~uZ|I|sI-%<8&CG`rWw2d zr^T{k)V{Pp7bx1>`$ekA7&vGIsy&&Fh|*UDh@tE*CyR-BBf>AOmg=%~(43f!H%ZXu z&6{ryutxr~jh(5E?)hSFxB@aS`(B*qYzI9oeP;Y$~p!N?|sEyxC?%LDFoJ zW<3Gy6)!6)u<2+GSd$nUZvd`*xAQ-J`@XqX>)CQjPg{8wE4R;YsJyOlKL5^O(ntHw z{|=g%-13E*sjO36rB{$-De>A4Haw< zQz%5g_3lA`DL-`-{)58K%4bqE@6f@Z|DR|~phnCPcV{}=h6-khE)=d3jUJ7b)dFb>F`hN>bg+$qcvZm{DKsoc+>A6b(u(}=0I>ZcInFXBh%)5bwGA0c zjkS>>F2I_rtS=6PiGA|$b{OI06jprffUXkG!zv2b?4g~2IH~on@J^I|&DVMu=5dfw zOhw^@I&5HfejP{vQMR!kS#ji5rj<<5>hg^DZ7r`S;8YL3dQ3b zZ;1{a_O3~7pxxX!Ku1Yc#Uk6$!{c{Oi$8y+007w~HFv0NM{ARj{|ncs|zM9RerQGJ1vWO=xlF zYSSa~9 ztWlYA?DWXemYc7Vct^UlNkK1U^?{l z^pGk%j`8vV-x0cpmPBOu7+c$&s@=YG=LVo_yY2Vs6{%kQ{&ei#T<3qub}==>kq3Kg2La0Kw8%CW z9w;pm5&UKNxpeA}DdQbm`c8Qhoio_Q9IO(|Khn)`@bF!H8RvB$_9CXn@v zAO|9|q#=7&ULOCY_ng3W&7`sj9F~NmXwSJy%$n7$er{3e)!Af)nZcl3Y~EY89N@jA z3wQzMEj>@1p5^6S7iZHtrr=b&j2;LA1SMlk>lvsDK)qt_`R_GclLr3tPW3F*I?}k5 z+yJxMN&o2)uk6mmfHsDcVl=w|i3-4liVlpfAu$IH)HC3ZD+sAxU3>C)(K8NGS^4is z71>MtXFsM3&%zaAqx12Z67P*^fYoIx_6{2AL3(JL#dWB>{1Qdh;> z=&m3h3cabgxcsSKL!bp%AjwsNt`7V2eQL+S3(RyIC>}rQ9~#0Kmhp<^pKZ!sq#*I zUrbVV1ZsaV{;z|qiy+E+_AGffm&0`3YTouwkW}`)*XS^Sr44?gq*2=#WF<;RQFyTC z>3$u5NFs^PvWH1vGa$gmOsO#uBLFUORCFzTz>knrE=L}KupnMiiBNR3y{6 zh*M?N7qxkjVgA|m)bl6^#J&YOP2e=hB#~7MX54Z3nvO!rv(f_Oq6riQQAUbl;F5+M zB`FoEeBsZmDDeacV)nJ_`;2J64g8RDG^fIb%DSx3sNK7zl%nq(hqzQ4MIa!4;Zl9w z>lL4Y%%*MKyLp5<&uGfn~3x{rZ(4=~Gi8!WiMtuiVA&taloIuLCl^IjXP+%t?DmM9U zJy-OJcrsDKlh{j=gIqa7)F${XSd#{*#}JK$wdE6Ge{w z{yAs@3x@q{%=T|XQB2YQJ5LGVa>_2oC#ye?766w{yMEzo<2&OuMZ!VQ=$AXB(#8ApJ2Ino`ge$<#d-m+f8uG-^ug~l8qeutT+(O&(RmdtxHfF6I?h#Z_ z(G9>DtWusoGjjf`FEn1JQ>Tl*z+?8?$>4^kPRU6^oxRHKBDO=$$`LJeNBNKIHG+m0 ze~q&`Hn5x_jJbi5Pr=UN_t#!pjpzL@011YV$}6O)yGIYj;0srdL zeM4n=`FbWS8DG%Gv5J%~TrOjsBer$!J#EIJ`1ti$J9PMW(B5S)eu@6H=4GCutZw1M zY*vFsj$^AFuH51~#t}7Cv*+6sbx!*E;OijD1lLvpaPs6w3g4tJy_J}+!vS;Asn&mi zzy#X1%N$J-pE>jX^R3C_dhOINHRN*hRj_v}es#Q>AjBkT80N{V zQZOM{MCZh^$Ky}S7Kk@*0I3}GhtR!We6=VHk`M;pIc`@cP6K+SP~NP-C|)~EReXu= z@O{nOwR@1<_E>DJ7J`)LZ{8$3ZX_<%hkN1&$7N)+gzkiV4)2it()4vj#Z*{XD+B++ zx&L>h&pQ=8c-WXxr0e6AL1Y-t@w_v+um;xu%k>TRy;_%}?#npa10uYWp>{(Nrimxz z%C#~BfV95BmWP)dwFVB1Tvqe`_3L|m3Od;u_*0m=-F`>lkQ;1j>XE!dLEC3d{jf{r zFKJmXat+(3hy5I%f{$}v5b`N06G7c^ny)T?eG-pT6fI)E#r_+cclCcpfdwG^c23tz zQeoCd7!l|~yKlb+u#sK5^rcm<{B%e6=p|V2|6(`jxC^U?ug9S%1q|&z1E_=HiYy%6@ksJv>|4yT~<0gIQX@ zw>Pe5tVVbQNz)m-g*2}I@1Ru|cLtms8K+%#!7I$naXQK_ugv}cDO4Lx%ABR1wjB& z>4s`G*47_zmjrq8a*7Up6L1epQyhA>{wo?lI`D%oeJzQ=4rgyxUGe?ooJ4x{E;4mv;^Z&ibG znx3c$k+rMut~J)CDWe`IX5weP#%1OEW;{beOEB2m$m#DWJaA7;RF2cm7`bEnN|^B4 zG4=F?KU!hjmW$i zW62iO9kMy<)vJ zJDqFQZ}y_Nd~i6vX$}j`WUU_#4TJVJLB9pJ*fb^huh~IRtlaZY&Z~vzbzCsb|1s(j zw^_f}8|dr%4(z*x4IC4W%%3{7+|b~DGad30R_r?EC&e!a__S%{S2e$F=k)zKs!Pv& zH0aqg_KS-c4blCB`@tLK>-VMR7Lb$v3quYdDmHc0CpnYT*g~knsHLJZT)_Zge)pK+ zsY+Ny_;fTZLoF5(6BE;BS*l|L5HqRi5tfUYFgmD2(>}BbNHlUNq4G=;h1z*zq=bXY zW+JcK?UVj4%nkWp4b3RUgK?7^r*>=q371+y}+%m(uZh;x13+!js<7_@z-o1rknV zLl@!}ak~-ouMVXsjkYotAUa48ecF61-NcUP7y?Vt17dYu9~6$5Y+_;p*wTRdihCij zI{`*Yd|As&Nh78xvTOz(T!3jB&v#F=yU;L)!vgJAs$#_Pxp8^oXg-< zUwfgZRN_q{riOSIOEyw#+u>_WsIKU^@b{aCdQ@3pY*cQ1l-gIcoBxgF&{~Rjqkr!o z?MI1-+gPP1A7G(ydL*YFN}Zm zQ+h%EzitH2*49jU?4xc#)FWdssASb(}7yHqVkjLVm2|$ z$Jf`m)i=<%Poh2Ka~975TjDUT$A(ob5CsVC-8<12u(!i=tmA1P$~>A|{Egj`uBhi1 zVEesGr}4^mSBe`LF!7a`8M6w=ilo(`cGXySI?D7(Sr$WeAB?NqvNiwv!>Rv6S4Ktk zs}H;>lZTSuu&=LG8#;LK^|`BdWT+qythKi{1H;^?CcBl;`ve~E*Rhg+v^#os6f9h}E&3f=ReKp)+?mzcK z{N+=oB4g=*UYIWg5FCmUY@IuwlJxQMqZz|eym|BLYxWRd5p`>!;gyw@6V5r(_R)GE ziItdg_u3!^eUkGop(zrv`|q{v;C2oV;PG;8EvkkA>?6)8PHzY|N488}NSTHYyz|*5 zbYCKxCy2=y65}Tb@$7r&Bj-)fY(pc-CYb%jvdoHxiL#jur6K$wIqpIL!HHt^GID%3 zjh6Ov=cYMlDPwPIK3uD<9W2qEkV_=h}*wM-bLUi4ne@%O5^uz{PeI-k*BZej5MwE$LE8OwV4_43|5 zdzuETn62Wg3QS?34DgE_KM3#Ck#BlysD+phi5}(=c*%Ro{pF9=yhCu8i(>n~s)zK> zr=^>`%uSaWE3&t?zP{b`MR-Cav_7=o^eCq$(RJmzlh%KbLn$&$$Gz#C!aEh&0u>K{ zkk5s-4=1XW+`A{Mb;8SH8Few$6HbNfR z(8AlhEA6^P=Vj_6JcAF!wbj#h3A_y=bBX6OGnblUu+EY$vQLUh;V6%5$Wa+`(=w>-d6FXD|-?>>DR zMi(SmnIAxK0w6wsZL>=V;nSV(}!hvDXZ;%TWqX zVT(1M(T%`NXIA@gJlXRW3tdbDOsGhny^fAZzujaYwj&qn?5@=r_33lO((7HthlyTZ zPoL{t<;OGm-8s>^t9(V^LRxBUMf&p<6YVa!#3ZcqksDPNv&y-v7+& z5$)K!LBZ2gz!jq2hcQrOL{8=FO<{e7B=0w&Zbtbp)kP@5)*?Yy#OAO%aDt1=;=(@q zI&IMdl$P#VR#8DdX17Fl_uao`Sq=WMdaD^}W ziCK4C@T?I3;;a&Ha<4~`ZQI5Y*Z>uC8O)m%J&~P=Od-Zk7#vsIFf6~loxOuYL#&p!=j;u<5cJ?j&-~3u6zJCJg1Tke z;8QG9f0QbHr{8R=xX4nN1+1H^>Il?8mEv@EC+ZYIJ?bpxLv<(Eh8w$P`gJDmM*V@l ze*cU*PiDJGy9?P#X&2mO=EMQ)Vb6h9rj7usbpCc2IZ6H+bimJ<-gEwT{no7@Mz+}> z^6DBdNw;<}u;3Nc@cVflG z=L-&nhEkY%o<9i<*1=++QV{$Vie)OGDqRu&1%`C1GA>Opl@BE~3hSAgfPORQWRQO0`?%w1vLWyK|jQj}g~18p=>3~^PUXxMYo z1jSujs>@GwOLdn;6&TzznX``62E@{khXFaMO-#U5v$E(zaN$3CmwjSQmo)00bCJDX zTij>fVE&SC>0)LTB7?s8=ZYt_VgGC8pBC_)#?;PHeVhcIC@*s=pjXxLK0k;PfJJuW zHNQ0km4{|aPpN&|wz4D-^GAbg5SOSSK2$;BN0Y7?6TVIhda^p1%e7$IK1mdef}={ zD!`^KYwyW^a9IUvXNUYh=i&V9CW_)NwaBRj1z~;~FJ~2=kC?JYM|*8NCRP{l7bC&# zkq@kgy9)DNVK^bf=3uD!?SsQfV8y?IP%C~k$p>6)kG}+or6CbRlcOw@t-1l2)EK{H za}abAHs1nh$?UVoPX7AL6BhdNRNg|CmEw+rY2Ce7 zrNFLcoEFYkC*AqcCM%U$csXy|w?PaxqSudk+!iV_a@O6qs^G$rk#5_VU?+L|kR!v ztXFH+vA^p%8~ZAqO$69h|Ak=e`j@lAnZjJV(KMZu*Js}y*+5COs9qIux{Jv+TyD1L zDm;4a2nneWRic%~LmJrY6v9W%m)(oNA9DK^V`_G$%u zi8%0cZr=r%YbGx{{gt?tbfdiv(?)j6UruGlCv=xfKq2C>sBh&asG3O^R!5z@wT&?m z$VYHpA2D$egi(Kp2xH#8 zYfSuUcWNU&k3fTXb{h-Ag{IM)7a=J`TH$2tO(3M)!@EiD%d4}NzTNrgg9$BMR^Ae0 zG@KT}hrWKx*#=eUo})SR=>f(uEmLzZ|F;-;QO}KuvA0DJQFqdd$K^iL`3@r^F23D7 z=7v@`fqTa^ZRF6`)zzc*hY$6pjLPt}0oL_-GA5?0t-n?P=v?Bq!iit56m2s4?x=gG zU4!-JI~421hdC?fFo2>}{VsFe+-fFV;<l%8$v#qn0msj+nzEut+Ql*SpHeak9sR=FKTigOxWS7Xp(#~5%(gx-f*J|s#>x-Pj zdQHesC0p@x5eH4ke*Dj{VF%oOoV~oV?|v+TDtm2j z8H8$dVg0r$WMVdBIlVrOHnFH|cFzFua`pK4RYgTP!fQX{H{3=das28kR`J9zrHtf_ z41)wVKO)-h*SUv3ec1p?IvN|^D zGHl=RbEsouhMo0OV}cbG#(xsh;p+z7hRmBea})aooU3YOLZw68X)pVwNojYVNBxBK5X5zxE{%t6G+XfDF z8{vhPy({C5=%~j!`g~!cQgnmR%@^roJ_5?8mZsW23>SS_5<4|IiSrmd$dXiW!EvA&@DHiWXDd_0Qy$*4mf{-0 zbkuBh`ccqh*`i?{c4sQREzV{bQof+;W2|&TQqqhgPm>TAqP^&s%k!j7+wGbC)O!R3 z7gK#QOg8Nr;tg9(?@j$*?ocR%C7p2O-UTtzAU$O$_b@g0w6=5riQlf-0vSj~v+{K| zBb7&(KBu6wORjtvtrtG9>)ukTwfkFC9>Y|EI`7Y~&kkjFA(Vx( z^^0Kp-fcd-UE+e+`^0Kkt}ow>nW7W9Q?=ngh3+}o?C+UpI)j54`OMkXz(4Rnh6=Do z(Vx{!uKc{ZbJ0;FNb9nlA&mBOwd`k2*Qm`~Fo0i{l z%D@Lr&@K6MvGQF9NP7WoY2`IpwLhvm!CQG+98b(*8(}Z{vrU1=-86y^qzEjyKfBMtk{v&hjO5YsW#dG znxTcDgeXq~Ad~OBYe}E^WAv!bseVORMaC2VZ%T)DP&Bed0Sq5K_vl)K&iE)%!#4tD z<4=hZk9Z9bTnNiU1u=rql+AwtAeTpW@e7n$NO43M>*W_jGKi}y4C*wfG^-@+s@o6wS@+7==YOyWEIOf2vS%^p~d7?;rBQ>RgA zlaTLY=ZX1`8cKcM+LkWEJM)tRQOt-V5F@_Q#UrnSZsSomfZ$Xx7$#ISP_&=lVnr2aUdTM>fFra$Cbd~PnNux)HzB5{;0oQ#qdUzLR1rj_C zQBsJly!2N!Io+St$UFitJv_+cSA5mM3^APYVrB)AU2W6wt5{Z;VNH0dO*e)q8N;WN zP&WUG@hx@4QAd~hJz4b)@Vu?z4-l52yJB#$stbyT> zwW&%9)1*%ZFPu;%;ohQGdL|GkPJNrOK) z`SJ#lBk)or(J}%eHb?-5&&o3AtYDz~7&kP33;@w{_^>NLbjW{#=V$+J%{|5TsmsMF z$K*50UM_}{_>7m3_9+wsi--dK@6YVNmqk0;zP&mSf}9|79F0Uh0DBg(D=DDf%<%ga znhFj`mUYrliHjMj884T|Z$2zLirJ4%YST2mO`R`ZOuTU6&);LqUr%<5{P1^elN$={ zq1P{{s%|of3plQ)zjMy(oztRb8D`B%%!-(EFw4g;|K_6!hbJ9(UfgE%BqvoD4Od4E zE1##Olh>^MSiZW`3^TI`^V@IFoHJbcx>v!zs38?ApA`6If3UN>adzojU3HUzF%UM5 z+x1H*%9~BDg%(*F`uT^KE5QAOb1N4|D*FR?kmc8;xQ2wdDuxa{Tj5-Gv>(eC>c@J5 zfoXIb;rj63&$QC|ewq_9XImqXs5+C{$E4NmpWEWoYadZwwl!H{q!}E@KgPZ1v~AHM zzTfP7j~|~O(`{G#4v~qUL%#jJHhTS5F#vx?tM7LG#wyHHBod`O`T#S#7R@LJegmf4^t2f~hEL<(}d*SqpJZ}LzDWYNmNHO6BTG+=I7OB7_j zwN;779Z24CWddCKUu6EpoOl?teFc`RfYCY;qh>!m*_*)s3>;X$n?UqArx%t3;j?j| zZ!lt?R~$d^u>SB4&ujTBVyKQqreQ=`6jcmCM3LXH8_58cQY*}+vLv+)OevkT-nmn3 zcwdiVB0AP`qxxK6kKCM`08)JUyLUH1?a)I^sVt1eMqoR4zbIpt%br1VLukVIG%;NB zNY4{(_UAU4QPm>Y%K1pWIbliVI2%B*^~^+(%kaKeGt=4kfo9=^ayk457ZqWcdWAf~ z7id5XwA=qf#VpI{A+F@@gZ6kL(n@v>IdH%;w9~if4G4L#V0N2k6%J*2Cke9 znAg_&?r3%yHGo=^Ca(yI>ea10RT1S8G(K__G+VZ`qTnu0U*g~wKStXh=wNsM`)0Tm z9v;vp12x8!tYZ_LH9CC*@OATT_J_k_J7&yuMsSv%+=2YX)6@4&cN93{A68hn9fA>R zmB|1YJ{$9+{DIEkKr_GyP}!(zivU*sGo&e{ZHetueHcD1j8PdavHSd2iA(k7Y4%^2 zRiU^Oss8B+W`Zo=zh1+p-jgS<1BxKVk)4L!U3LGix`Ha$Lj6)aP`P_*(IsSjm3Nbx z0b5wYmvMP$qHyiOhhaT}|6LrvlTMFwyKAa}QT1Sh^P5aQVy1_;T-@Nzn^AQ|5perW z%a2GheB7QXhhkRY^>*L8LcGhNULEz%PGtOme?nX9S$lSD|K-qZG@7zaRRCiW45x$& zVcPZWT5j)WFoJ%x>X)A64oct2D3meps0UL4YoS|goW3QcLG#SSGtJDiCT$(1%aoqy ztbjj{mp_d~<}ymxW%usV)={I}XJzZBn~!d2*DvaDehIm%Uu15CjgI=Yv6%yB9Y1-} zUDHNNyXO<~UoApfL#^$hpUuDur{DT-K=xDNHJKwIPYM-Ow_r!z*y-Y*`o3s~ndiL(!VI5_&tdH6uiqP-| zzf~*F)+MNU3!RtVxC;3T=ncK0XQgCDv4SnFiq{j)*aRkORmxW@3jS5l??oZf7CL;R3CxYCZ`y zk#Nk^ga5Mu?|{?`Ari0F>9i~`Z-JK!^nZ>O8=hqGd{D|j2TK@Va@fi#7nbsn+8QsJ zxqt6Bw@K^O*FOcZ&_v$?Opb_+Ag}<<8NES1#40UY>o^qfUYbtFELNA>G16*xYK*nEk(h<)~R$~0YbxdP>J3C5K8KtCy zDk5sv@1qel>KX-oP*D8HyzAGQU~t(q^E5Gul8f`WfUdph?%gg9Pw)JHEdZZUqjg8B z5P6>Da9&AyRn>&IstpjC(+KmI4_N#pni5%37wXSOeViCuyEK@o$@9LoFUWqPJzKu~ z+XTNOF*P4{rs%nc?J4JETWLGBKXUEr)sm>fo<&Dz7JhOE^P_iGe|{arT6Vf}+uzzo zArB{02jqE8n9yGQ+Z_LV#GodYf&uN(POfVBu3fo|CZ{w`#UiUGT$IRCmp+Cw-3<&j6Q-q6M%|ETRM?;T2#A*M=}_a( zUu$cpQGe5?p=lqvdbNoRBSSr>WzHIlyV%}Ab6-%W^B&>*Zd2>#5%=%j4d*8gZfLUMn=|_(G!IY7dLX;sdU%vc^$KG)!fF*I* z+fRksl;(=(O&NO&?NF=E?#NZ(FOUr+xEuZ`SkFXO7_k*@ag2xr@#F(=iU}{=hwD%DWEiLXS_s@vWNtX z)>)b#Z0intWgh^~{7l5))O&R6fA5T@0^MuGq<3OJm9l??bKl^xL9Y6*Hut&U*!&Ow zYByVtncm2lQ`%Gzxy;$J{t@89{r+EBPYmY>wSy+5^8T@I5FXO=Sg4Ewdw^)xzhT9G z`%-nMk(}}wIe}`FCC}f#A48l*nn;(pT`+VcI(R_g*L#|k>T~Db+BW>pxU{!1>TX&e z7G<3)%3HV;@LAi)=;(yM6tdUYLXhy~gKgM0o=c9^Z~pY5+QF5duEwZaX~fJETXLR% zvZ>Wd&fy>%2(UJbA9T5@9qcy4%axd6c9;Qk#dTu|at<_|-q=G*~!4;pJ91Ks2 z_y_C#4S0gnMqcMUi?$H&0D@#+?~97=ZaAj9bjqQp@c%_`CngThPqDXYUp^6>Ub-voQ_M`=z|=eHkP#rz4C+{E zhc$2A`Wo$Y&)&UTsl?Dse#X&wGC(zxM1}9Gs`9zu0O`xpp3DdEWFVq~|H9$RCUP2( za}nRiw{LzC#{ferCIq?grwNu=aafd@AuI*yc!^OZP%pJqOD=Va$?Lnm3KKhL=N)!l z!Fxs(omuimZ24CJ-?Y5exs}Om&&ID>eCCZDqpuQc3dS}lGGEgoMl*cbl#ngc^fjBFzxbDr)F*L%NqEpH`7p{;}N9cruk4B{EDIAbleNU&o)CC)4f( z^u@SBFd2Mx=!bLbxfkr)Oa7Dvg)(H#uhY(}$a`s98@}qP*DCVBfmXDabo%0nKsd~W zX1`4*=~3SDR!HCb@hHws+*Gz~lI?YNFXj+)neaecQ{r;Os;W^Q+p%6ccGe%vFQ|L( zkOnf5M2sDieUY$70CoN0-%fw_KXB%28%5>GT z$QEg5S}GLGFWv$ujV#;PxSezLlI!p-cTUasqGFs$+T(#Ej}}o46(a(x6pJo?IM5zF z>izf6Z}nVe(yu*vasWg!l1qPd#iuFQj^>fIBek0_qML^rMj#~muK`4KqE^oYC1qU6 zBN&Gq)%=vlq)7zC7tAZEhxMl%YuwpnoUJRl33HA;SYH^p_D?aS%|sg0(|R)?X@45h z_MP71%|hCf0#g>5C>4u zcrz<0HtPzEDR#kDB<4-Ny3#{~I#?+6`E&(J)OG!XFAXI}_`tX4Cx0Rfj z;SlpE=Jav3t(!MDqOcfPHMRaWhjRwbyI{%kVRqf#e;!a^O-}8uAxmD6JsKN4{n4x4 z;00Y78SLJ_e>fFLeT}WsYvfNdP2$ki7&5?Y^g*g zH#=yQZmRq4>dzJ}l{^~*-{+^#iV|WiR(GT{JSZ#A2zd} z7P|_&>**aDqkF9&oH-fNFc%?xNlAM8D1}?B{*1G_;TgO``P>udpHD0*kb}r~7F3Mw z&m#~Ljove0GCBeo?|IeN;KD?z=*W<<3{PM@G2H3!q1)fiYrl9$h31WBUH{a|J;%4Y zr4UF zQ9|J`GCP^@I|GkOGN3_C+FJi8x#%tro=>X3T6TiophSAW1b}1kiq2M7I<* zV3zax777L4L;f|9bKRnEoMJ-oarTZ)`EXdv>RiSERcp^uiq;p=-d2 z6DNwYaampX{o`b@8VAgA&DwL05d_5DVK-joEVhXBj!7ByrX1i!{mqV)I`$-G4~rb~ zar05PugSjGmWIq9O6Ve#Ea$dC4Ly#q0+0)%8)(I`6qbg-dOR{ z9w`;3P5cKx3~>l=c@pm@nFm@@S*XO%A(hR#ceowpo@?`g;4%bNhBv5+mo-Ro!Nr^8=lXVF%tK@#4;?rj`Rh z>h$Q*A9vjPiyz`jizHV@*1TDRi9u}u_3v>^FiEiTuy4v~I=lQxS%O2#nS+tRM%sM_ z#i=?r!Q~(|vH5U28Wu9L{{AIyV$MtuS^4pq`P?(#bHuDQIeAv(%KiLY@uLd1!hvYQ z{(Yq-C2p}+4!*v1Ep8oeZxE;2)p=JXJ3-d>)TlM*l2LmJ1}$C!6Hd+h?YgE3p~hlIR1Q7}vtORH(YB=<7Uh85*Ss1h<^+Sir(Rq+K(jl+;s zWNmzWZy*BKSZJ?ct2iAWKwoj>z1^*o{@JIc#a+K6nHSU#4+&~V>FcOVt}wQUxE4Fn zs~j_x_{TKS;!aJ3Bj+Zu%x}rtdreqO1*n}*fw``x`Fm0X1wt@0UEo$a>;fJ|kCkaL;A&zbOHGR~>ueFREtyzHF~;x1_ipg>rO`4K{?v~rJ0 z2*dPt%|bT}vb|ee>_c;m0x3K)@~Q|eUww@{pIxV^1oj)G_7_vGzWw`8g#^Yz)@ye& zaDq4%UNR-NuI9SJt%2x0hk=dG?v@au?Qc^*u7}w`(Uz@1nl^iYIhKV!bkV2JoN=GC zitmT^@w01|PajRDFA_T}sJ|#{ANt;pZ<3;GsQgWjxi4Cpck`y}^~GN700G$Zrmb4K z=vN!HrJ72(7P{k4+s(t3a&2#^4Gv5-}2K(73IzS!$}PhwiN$_Uq&2_N6_? z&ftNst2z2@q{me^H3dm;>6$-h_9SG^d%TCyYZh3EAsSc$E7xU}kyL>AHW4y%zJhD# z==<@3D6t_}B2GQ=-Hc82=;m6~&akUSfP*q9FCIxGb-oi#{Gosa{g7883mSqh1#lhm z6kq43IDaQO4x39?t>0~=@zN?C*Zv@4IQi}7I7x5An#+=;GuzxuZggIIVbB%ZJ=hfC zi!D^;FIx8{Z;I+O6c_o>y|tQSmp3*Xy4)*QfVv%hzrM>8ZO*4pvDA=)M4=@nYy;6> zWs11%DhU6b6ag*Tw+{jI#=RAm96hKx;qgF}`Rvh7wR>CLRcha(iRXVv7?o->0`W#u~&crcXcN7YHYD_&g@Lvw%z8)?Jpssc11 zppaq>#DiPnvf?xh8xUg9Y6GqlotE@sxOq7CYpM^9$JL|ZSx*38`0c$1&Oeo9nW;JX zV;F6MEag*+gQZYnYk-Y+FdYlULRShGvJpyc>Xa!KG~1Z|AvJ)_NLUaL;Q9)DhGu9A zU2Sx9bigw_4htA(hmDTsNx1FIp}`%5CKun5dN2f}q{@3~9r!)~LBfvHHPKDPkOl)* zEd|)7u~VNd9TYkZR*2d>Z!ZKz=^#i0VgSdmS8=R^y}e8&Q$qlCn)cNz})d`EsZs8WXM|)4mcm`U-_FG9PWSUzDxaqEY3>`XgLDKn^ zpLOB(km`skg4;t(B6~`mPoWhu$*{-Z!MjoG7ZHz;C#`eU?`~||o+wFkV(Z{gLCF@7 z^62dH`Oi0$COLEgtrRF2%48DkB=iks-6mXGXtuvpm565i1tSa*8w-c8_~?&-$79;9 zI!4lnENV@g>M{Vpq#woE@ChgX%^Uvr*LsjY;(a1>tpdi)nPU$*j<78r4 z7lV&K{4b!-p+ex0YE0ipbX#AJ<58OvY1{SW?mxkpJO& z=TzwNuD*PENltdtKL~C-11W@A*3?w~B9R0cXFpm8e%?rW9Q5!n;1EPHCFnofTDh%K zJ1jWN-)zyb}{rP279 z{BCo0UCfv;MV}oj$4^aw7n*&-PTRTv?Bkl}CEw@a5{urQW6bv%DLRJ zy1FH$Kbyi|0|?4Vfvc50j1fQY{rdgwDPNyy^==7AAz5TT5@AJsmn-Vj;G5y@!EyCd zrVQdB zQQ0v>o+i?AXZoBcU0d@(6 z^`wOb>J#(N0aekVHTuXzH=vxXs8uwN1GtK zMSf8+>Hi##eh!P5Ac7Z2t)~0-3w2cns3LBLv@!^sOF+%zT+KO`&urHWo@CVUwHKU? zWw>h`t0M6~XkNy|>m@!bwxNEZx9>VSovQJVQ!QK|bsnQE;8m^Kn2?3cC?IYJ*bh zcLb^3H=yz?4ygl>-Mc$B|NZ+nskAANlas=`ZD_9WuQ__0+tFyCi4s08hQAaHIuMyt zj|Von$f?OCmO*YM07QU^QMnf18j^Q(Uxcf2ER3BE7BR<%|uB(yL_^Bv*{_^0{m!2tKd zwWE{6pH)wF5IvHxT`&_cDBXAa$^ICjz3SC_`|7;O)|3ysDwB)lX%bM2>#;HGsk>evFT6vZ5Ov}nB=}j zMy#5Sq|Fj|nI2PYJ#urC^4A?sPCPKQ^d}Z zw;?+9FHazYjpX`6AB|nvzjv=*uH&!8>&iF+83$*EK(z%{R#z7HH{8R|m+wn|1XH&i zZ)zrjL8Kg(KEmN!wpKwex=zqNN8nZc&2!|g1t|d`Ohe~XaW4`^*?3*{k@F>M(z3hKE_oi>$;6l9$-TM zo?89Iu;zu!q)Crrbd3u(Lp-al|4Q?R;$a;)6-J}J`*$fFR$tnvbWNDkK*L!!VG8Q( zuBN7)002;RxuyB(w^)xW$=l;|2EKsCcYUyiDnGKC#4h0e_p@>NdF9l;N%@DK&#>iG z<}Y*FGJoHInLTtHHf%_laj0-7-64XoB#n>KT|gi%ki_SBJZ4ZMKT^rJ!_!wlZO6A!T38xrix2 zYL(%Xg^pS6J)*TQ-i_P3xkaQ$LDiZu+I?C#@qPIVo2a7rkU$SMhAx2Gqk&?_2O2_C7vi_2(Y=|5^Z_(3)G!bkG|6$Q07qv;83qp+)k^ zTabo{97o1WH&Y6@I68i8{Pfe`h1iRT_a&XIB|#R+ffTB;6PJ}zAq*`}=yZxU2fokx zV>fA_WOYbdx5liAXb1nvwW~-w^@MTcoyf(IL)@f`Y<3YcA+XgY%AZ950PRP126ih- zaWeqGybRz7&)ba$Ohc{OeXWSGk?+0o0@FUGsJHjN4kbE=*SJtqu4uQ|)NHl=ygjDPt?k?Kk?%toX6fZCWKBNOVqqw$IB0_$IRTG5v{It&=-N1}idcFSVNWeZWkO ziwIjd%AYB*rL|xX7(v${h<-{kQB^VQU%*;%D|$6V-Ya~4k7IbKwR{zwB_+#<=cnmP z)rYHs2LT{lL?aT+ij#zdK*oA$LvC}jMcjS+_Ew14qfB0CHJb^90+^v>1ey^W;Z^_1 zlP5VZufhPKG*&(0$A0*n3$4CXKOCz!bvX(t84m(=h_b6!f*NjQHv4Xu>ZB?1d6eY(cn2xFPslJ=53wbd94}9v~BaI7k<^)Qy7axg1#0; zQ3^KRsotayv{pz|n~ImsqD3!YoFX?&G0)N;#xJ>KkIl27+;Vc@d`Yzj!C$B+*-CAs zn2<5keB8LU!+(9OCqf}+e&}w+ee3yRhF$hJo>YH^oIVD4gFk)gsW*oK-_gB%+6BCI zEPTdi%nY+=pR;-EnIQj=Fh!Gwl%Uybez%MZwQApm4}J-%8P7}@npq_&tpF|l*MQqV zP{Oo@PEcV|JN;;pXP2IeZBwRC-+&}$Ps}}^#APTh#UYIjqCfuEBwYBr*VKgau-LPO zomi`VFJaL~bEGN4?84Uc(QdLb5jEsSTw0W$RaAVl3a`pNcJ!#Drfiq^pBC}x?YalM zp^@EZhui4vj*2R=oNrat;s03K7bgF)vfFG1{vb;1# zX4alQ>0a4mFc$DzZW%+j9(OEs&k1UNahJe}i_o0@;r*s!4H1$+#mA6KM6K;l#1moQBx9l|rBDI#r{CIh z71a4Oh>$RbRQCjik5K*^40s_}MMI1Pj#ekNs}3*eD9glng}JFv)V=GiF%(-}*(Tn_K%g*n&O`h%uG&d4NUdf9wy>KQKVi z%BdMz5YO`FP8wm?woqb5U}@V5qGf z8{vetu36T?ebDenuQLOi%Xbk&Y=RxYc4u$}YJiV8z|uL8C10@cl+>fl!wA}atnl%G#qDgy#U2+g)_QSCLQxsYf^ z5iv5k*OH}<)866Ik#_v%qNVs>JN5HSZ$gifQnc$Cn_@{UkZG0t*|gh8BsT)i6j=>4 zG)#BTZQ+z~{H-1=Ya1sOq0IWWs@H$1`4$z&wGbSL`;vKZCNr3)JP>svE5)}|yI^a+ zZXHquhn7kT=}B2c%GbS$%$c}CC>3NK4SBsqF2#XTsON8ZRhq(nqsHEl&ipEDR!-Uaedh~pDj z6}SgRC1Y$%+YOl6oI$Qv)Q1DN`sNoDR3L`1s|M1|95dGzpi$Vgk_+3u#rD&9Mmrhc z4@xuXZN)JXBNv};Q!gVaDJguRl*2B+06E< zH$&UkLwI)Q;xUaHbTXyO+gMd?%1=>we8F$;#fukvy#I^g40@$pzMd3tOwU^hvzL4*yK1yRQ`8rBJ7~V`I$UBN1wOF;OuyyURta}vFrN@6`vP2$B+u0xn!pvdrH6pP+&{;xp=XULEdCcw4J(%Ig z)KPNH(D6^F$7|QxukRe`wmZjUPxLtmKj0Cq2!(4yWUJ$uEB*ZX)~eZ8tGOP0lA0&0 zK9o3pfO6k(CQ(^xbM302$jFk#OZTo>66F5!0gpaTN13y{0Kh(|Xw5dl&tew%TXA|LJ6^?@6bUpi&U#=4u)fVPF%H)x56%&To(Q8LCDY7bNbfWjpO(5NR|NILk-lVAK!qqNLVJz?VOO zMmgvSPaOZzFxx^faOwjGbilafcq>zQRHs=3FdiKL>WV22l1%9cFG+TAo9FV}U_1U7 zZ~p*kFr7aB*p#56Ij~I@nd|7cc$pX_xa0?K1-_{LF~@$=q<#6{01^^TI=ND-VPqpC zHs~GqcPhPc!`@a!aeBq4I6dX!0Gj4Qhm9vsof<#rAg|DJy{EE@;m+1!!vv_rB2h;{V>~{1;6W6Ti7G8 zKc9PC*L7bvKYcm?q*K<(v9NUg^1cH_9YqylL#5lO83^4ec?2sGsbx4V@vIKU|&wBPqoYCyrS1X-yd zC`m0H_8zgYb*G-7J{PFbK`uSnslFqKVO1wmVRNjYX{2uyNyZ8vfN3A;#5% zE$Sj?kM-!(v?pv$+2+-*u2VGqHRGp{$O?X2$($;yV*pl9S9BKOlIFC%P3gc%_SRvK ztccp{>7plTdPjsWYgV-VEQWR`C z?K5oA`laZfjo-dcMgn(e$~LcF(S-&*4VApKzD<=fueP>&l|s@!wxndnTgW1j#go4L zf576tr-5I9SBey0$XZsHzMIUI+n({A+tO4+h1rm|l)9o(0@@J*Oi}?^9!KA|@Om;I z%q*M?VAG_{0(zxf6oW`1-l&F%{jjGuaHt1a;@W{Hv;q!r1U@0T0+%H}L&u5+!LKYR zKx?T1jz1W4^dX(wC%QGAK^ZdW4HKygc?|@t1BVXXqsSzBy+!nDvFVF=4I&gEm)%AR zfghy!SpxCN057&N(lN|KmV*)r?C&l?Vj~}|3il7xa+aO{bVU~h*=a<%DFYO?arTZN zW1vL17N?*pO-oN-2-JqLz;O}lft3zlbYB&Pf^?&VjSqMPy=xX15VG=sVu4SvmzUdl zN^e+W^Dkf6f%1ey1~4KMH@8NJEQyC={Ml=-jy{ki^@2sfMKrB0fH9ErkuLfeLdoZ6 zZ}K!gkqrKvJAd9_%9LFo-@qoRP_CUvtvvqstP>0aBdV0aH?A!vYBR%H!N!NqgdhiL z@wQOZ&Z! zzj)D!4oZCxYXT5HO3VRCZBjYvmC)>9tPKxA-#!a&>1r_(s6r{;fY{fcOu*U61%)-C#bC6|&_YS_Tg`B{p+jN>_m& z!mSMoo`ERIz>@o3=uFv;ti}xaD`lRTa@|_SLt8`=YZlcSGatTyc~}#I>Rm#L^t9c^ zu2X$oUS3|sDA7?45_H|>inJ*v^u8N&0Y4~pY=5*KAPd+jphCaRLc%7#C^tA?_&c2b zyYvxOqO^N&pz=eEqrzX@`!3yxy)iwTH0zTV5u?lPdq z8(R}q7KpT;^o9pjP6u+HWGvH!pTBt3xL?11-RjJo6BtsjT2*4aBTFWRsRX5^Cc*D` zwwZ6sxCt(p-MG3lUZtR72fw=DQeaG`)#XV1^I(zKTr6LHdR z%5a+1JqA744P@iID(ifh@x)ud!eI=ksFj|yg2wZ04_ukM##JoSpzP3FG zgc-fO5-vZ{YLb1|*1=aHc}2+tj3U3BqQL~IyePx4AA+hK>dIV}Zx5yxNw zwx~yupg^AvyEUvw4?nu=10cwb`uw^SsxPExZHS~d*}lyPBW__1@7sR^@e6YqP0!nh za|pK)*0=z`iwJztIm7tm7T)x&Q|`=WNyUJa%@;Ko$N}9$+=i*${qh$PB~$p)Y)HKW z&!p4<^Ot>SJ<ymdoL7+mWh>6ls;Z`OVjKhGxmVdEz`XVAx{WPm)Q5SsGtbv-CQdbr+U|0tW_RT` z)TSfo^>(b_M?d75S+6Yl{P`j0_Qb{-?D1v4pntaR)n{b4rT*11sk2>IuQne({d6eiEG;x{fvaabgi7^yiEqC8e5xZr7pBiaqE!%a@~nv zZayM|Yu$Q3f{=GmtJe{CV&Ms8SR+o0|+SRs4kGe-ss(WFwevhWr%5dc+ zhHKikJ?Qq)-|K4H$6iXoa~eujBBmQ;>nJN@24-ZLHMtcR9;JftZE*67933^bFWRwd zm;U-5f6l#%)0z@e-;S@LfY1&X@wBN=Y^!Gi=o>HAXm5NGCC&36=#VI;2|8ilei82k zUJ}J8wZk}AX3Ize;;&|n15JVB%8fg+d|-E>T;|K^I?x2c-FpTM3IqiPW2f1WdS%DL z8X7aONbBm~d$m^9w{NM>c)ay38LTi5bcgQd&0}o09aN9#Kpz^T^c_1ec_J14LiZ|P+2a*zM6nM z@nqL|2wt~C9gDAhIoGQ}lfFy&?AyEcN9ICBw~cvvyqbitJ$~GT$g#|?+;QH#8~@3d z$MJMG(~^iYeEp7+*|X6zc_UomjWG&w*?4_?NW+t8V5qGiNdsk+3V8#h8TY>5m@%E< z+-2&)KZQ#31D~OYR%|h~2IF4`eSPs#^B)>jhl6IPVG9~kDV%~xfj>=;u^mEX$x%6p z@z!R%LI6u;3=sW4$z(?4+g}jJ!|7pUTbqmsnVC&tPkh@dBB~3TEtF$o-_5)?Gp7Ro zGp~6c@&;~E{A#e66SA5I!F=ifDOLC%DDvkmTxj{_slkU&GZOq=*MHtGyG}7+GK^Y5 zaPF$Nd1k>fvu48*0GEeeX}?L2JR#nQ%Dnb9^An9BrHShcMF8ke)16$ZNl)CiO zi>QMJ*+?snP`iO!q584CTEZNA3MEhbTdiUB!PIBmpHjy&ktmDOh*L=!BLnsL{tp<{ za`T+9it=*EA(N9U_`29+mf|xYGyv)i(O6+$*@wS()Wi_T;6&uJETlyQ3)(}FYQ(AO zNn8G+rN9fI4`u|AEc|$@m$PDnX&JfsID?@D9t++GH}*%{Xh;=a?=7k!nZH5Ej8G6~ zmch#}V5=qA8uivN&;-y|x+ZnMwbYjtCHW`l^BHFmHV&!6#>-G9E|3^>+K3d!^MZFy zY#&FNwSaYmH_*ELne&SI42C_dXQ^16TBFW{bFbnQ#&VYRIi%kLIRPT)R?=+|vm=i` z3POg2gga{8w~iY751CuHrkI);dF14D9p~YdEbq~^JrF`)A{Uhge8&bdG&lIjaK}BV zk(u{E8>h4j@#ztU%GY_;3WHO%RNNlOv(V(#!*OPFy2)B*&cewrr8Re&apo|NY+L&h zThHbdn*Ad8BjJfS+sht<*9)p^%w?p+iCV{h%a*Q?i+z{4lS?@g&ZoSL!z^&97`SCF z-Q&`E-#6Cbw%UIC-YIcyJuu%Bs(-ltx6*}Hs18o9PMQ)I5AJEI=$DS{P386vTH7ajoXqx*|B)J1)7cru5AiBo2`zO5!!~}!&HahMv z9(zskua4!P-C$xO+MTnt6^WH5`@e#ESVYz9jhH43%j77H;r538S>k;Fep3uD{No_& ztY_Ju(~I)j`h}`9(d1J0#ie2u$NqCZL!2DY-7~CkwPW=~S(tSDdDTWoWs8vGj_%NA;(tufZ2evmC4T_>8S> zJ{K0E1)r7}=zhaP$=~ovkiNV9$-k`^_5yoi>V8H+rE#wV><>A+q=R?g=Vx0_RQfa!j!oUl#w` z`LN!~W@7_=;2Ny2E$`y@^sl8mk(-n6{!t|6`t3%1zSFOL>9YI~T4qmhs|0^oCZzkzmdQ z;~T8kKuhr=?hT#*rp=1m8-5y=0b|@|bc0nEh6e?hLxHOcT3%e17SJ1K{8-~0DGkZ` z&xWKk(jg-a2gyUYB7j_r(ofbHGPAsES7Q#L_|p@**~a^zK`R{(Fhc&+=+UFa<$h(( z<(qf}92<168F}P%sY(V@`7f@qIY&iG-T7cM*kt#aA4OK%N$FN#l;3?1# z`~(g%4*nX=A7v)9&W>C&5dCs|Rm!M7$|0DBuKQ>XfeBQ-{Oh;LE$Vri$C;dOse5C# zDCc+jZ>Zw}qpy_I&z!UnJS!JGd|37K=Ky~NrV4MjHSR7}3pD4TZa+VU?)Pi6mM22_ z5}>8WS!^N$f?xFDYPxUw(Ax8tNi2%&d$f^{CbrUj@vk+9^w+Q9#8l_XrSW!jvUA?M zgvL&GcGetdb2@UEk_;>^+^@TMweIol^ADV8sXi&O^K(Cik-UGV?vx7(5+N_J6I0O6 z{x|hJCCq|%?E&D%i9?zJ=ldz^Ld2XGYM06P$@lyZq4ua^1SeonYmvS2!DTrD{Wpp# zegrz~-Xlh|^)~cmZ6INcE=80YVjqChJS@lZ{G>qo6PZQiXT#5^>**yKEr?l7Atk;b zU-aVb9`ouc9ZU}fU5JXb(gZ8+j85(5;P0J)J+Q!8#_&YlRw~GK+2O8Q5#S+b8A#Qf z*3Smar~p#KuRw8kaA%vjajGGc@eq~y+AFseeVX>1G)?wGF>C5qFqd+)w5+Tb7S4gw zQ*ZVZRU~p{63Hb zVlx?eAVE0gC+PxoQ|aMjcekyX&WwW5Aj~|3cmK_fs) z&qG$yP3QssIv-!W28>>n%@mYYPnF=FNyx7NjFU#G0@ua9I-oQlb}y>C3R{YK1(AkS2z}p=y$*PJt8!Xo zIqF5b!P1?yF_&r)AwUhdrp~t;4L~fhRo+cZkV&QV^b2{qe^5gHWElyyL*$x$)LuaG zqduw}ymfYJoAFI%tkPazw4x;!*`Ueo1iJ zi;=^h7f&`c92x0%9kNFJUuo3UQe=>s|GT%nf2}?z5$Y2pG5TDq@$4?H`(5G=X0RAo zjwP}$KX;`sgw<<_a|;F3W%TI)K{CF)YSn(!#?WK85VwE?No@-@EV&C54A;efu#Rmr z;6#ipp&EN)c0@Y1@sH_o5WB~%ISxiCr{7p(#*pDxrt{r)UNjiL?09+q?W%(V(cZ(! zj#l#yfBlz6Az?0 z$8X=U<9`lYwj~i4+e-%yLEt>+-gJ%^kR2#+u!#}j*vixRPMvW~h6~=5=wh6I>ojZG za`7Fn)+$%pj9<3;scxmPm!Nn4?R(X-$z8vHrcFLdvi4gYrH0y#o*So=sp#hgItj~`%(*Irg02na|e^pEC4#6B42Z#0rRi*-()6iYxs|`LfsDUr%uSugqlEX-VY15rI)PD&GDH%+DFN*De!90 zmLIdEIfH?U?#2-6EuQ~qwivh4tx%=lJCivEAse9DYF zaXwl+2RPy@z72Qgz{}}jt%KdFR|Fj@lx4nq8q634Q7oe-;(8~fq?dbdET5=NJtR%h%}ZU0{comkvdQIMgq zXxV?#Lm4AyhA#^&i8dNjK1&7;i9)n+sXBIPV+jal_`05_Acmt{c74-y9B-H%#Eb9% zib`_&%2@_n_m2FN-<=82N%vDzLm&x+CZ(EDX`wa=R1^^4Ho!9@ITq&T=5b-Us5Hb> z8Pp2!>BZQWxF00{{<3QH*s(9GeugY1J)-wF;7ww_ID!uo@AH&_8H^XG#K=etcj4kw ze(6UvnRy|4to3IWQ+N%gdei5b3=f;6)%5mN-;M?so9wiz|F-qD5VOsTysMe;-rTr% zYu7yp{N;twf+27{_p)!T_&m|G?qcE+S=}jUb?uRzUpU9ReZI@#IZ1PHEIB!^q0OMV zKQo8d0_j>+S8af;`5zba*=h@Be<|=T&A(nKTPcG;mS(z>L1xGoG3RWVj*fF!0y&6L znM0iB8~PReZ!#`Va+yD0ojIqIJU8Q`TZut14v`x+LqZ0&Q8>p3AUy!@9yV%Ja=}LR zVq;&0ftTBei+>#BXnXE8YN9^rJERq!aN^@#$QW(B&u_{(*^17;2*WtdCf8+5N%a3tp3^2U4*9olIZ8}5+26&a(n!rTgcyYKS1kobzB_g+YyQ6JTJ z@TX{9aoJ>^?9K{xBZZW1uUoj@)iF~i33zhwfCyz4j>0GGUih~5c;eB6HKceQADSjc zX9*6WXi7RX zG4&0Dg3ZG<@?#4ZH&YLo!X{{@UlIyl`PMA!M#by{UIoxrKr_Dn*B1LZb2evhJri8h zboJb}G9IeKHkQ$2#^hewI4K=#1at z(FAr7ET&{bGMxSO+VRhFcRtG}_xRbWo@(Z>ePuy*bO0J!XR;&*uj5?wF}o~SnxMLm`8FCWEXbz z>V%??FQVE4#>Z7^s@xiiG9?WN4C(k}27CB*(p{8jMr5D z)5k+KWJ2>#p3^jywhtWyF_pBi&SB)bSl9WNLHDHJ#K=cDa6FS}1hU5V-|SsKP#Svi zq8|r_m?s;;8BmY4*-OPCs@B)9uTD?-{On`{GC>$(n(x!QdL0t|3O6*JtEXvgLM(84 z(YBh{pyBXvk739aBMOkTp8m%MXiG6np*U(;TDup{+LWB3Xxl|_4#`0MvF_pe{Bi4x zPi_A4=8d^yG6i;gcAeWke)Pb#H+QIpXb(Fcvr&E0-d_F+gC^=<+kx>zt52jCRlK6= zUNP=4l`3W3*>y`gYI76CF<>Ke)F|CK^1u_PA|eE8{cpY%TT*{&;Imh5w-0F+HMzBc zmX~^8rBiLjdmUPesgW#86(O2*L<$Cy?*Tg=8=*D-O>tT0by(zcU|71*8zBc3@Id`l z23m#?7+hk46K;({L&1%m{KrQB>rJV4-m2$;x{U*)Lp>2Mn8oU<$y5~k>XL&IwNvtr;xVN27C^HA~A)-owM z8U2A2E}UcZ2h!z(BNI|S5M@CTN4Z`$u$oqXRu2U65$^2)=1bCJXL8whs*wP7wY1k% zttT^_(>|?>%y9O!%P_n+r+rLQh0tdO1=fxxJX2cHqQI7>USmi6_dXU(^;i7YrxIrZ z#dPt8C_+r`i6=uS#7A#CV{@-@ zZ2pj^GjgP1n8nHTPyEE-&Bh*5@4fpPn&vc`I)zTDg&z1u`03m~iw83jOBKw1)xV9y z3}P~*NT9p+>@NY^lj$0B#!PbND>|8Um2)!)@gNonnK|>lu9+iwW=xsA*t@uoAPr`; zd24s|y)(G})Xt;zR9RcTV!)ave3f@!QG^&F%2Z-y+sZDpcDUl+(kHHe$c7!mq#4}?z>Pxks|i$;6kv}>{Ui2<_J66>+T z=Cd#ML?J;aIdd~EnLePcVed)rF9!4(55`0~j&=E+x#s;nVO$gxoq}yfE7pze#{Z;H zDb1tJ0718vH4!MM9(QX=pHlDZ4X2C*CH~6orRyo{?&Ln^-Lt2O7~h0b!`kivkPzyO zW_cUlMoH=a8xSdTSxqLeg^|K*?C11|{WaIUY{D`qX=6}D4Q%Rx_PTX7}$RJEm1ZlH#OlHaLBHlZqw>Drqn1$Q8|N-DfH zXb1`lZ!=W^8%|vVXzczOX}&9&!K1<#hUn&d2Z2A>fY}eTsILIjoa< zIX#0`mzaUusHyk4TXo@ms4nIXu}4xMQzGYhym!;m&b?mCZ^B?^J2eVu;&&fiY(9_n zLdvA#SNE5#PsFA2y;nyN%BDwzo;r0WctIPUPBloFOj#i1P}{r@J4`ygPaLtfhW+dg z@`G`1oy45FNNH127CJgkX69GwBMu^QcA$|5x)3iKnsnOs#XfVqqV3kVxsjbM)0Hw` z0{Zm*$Exg0-n)8i?KB|yfVgDxOIAICGZjf+XJmFXSr(U2Z|p#Rb&N92dQ2PzG$FKz z7SQrg^QBE_?U+3{Q}de>YusS`Pltu$J!lfpgp*F%VxhS7+ZZLLnx7zPV9j96d9yGJ zrkQV{VfJ%aZLZhiEn&oMVbP44J;c(|E(wQ_DroxGS+I)h;G7NV=C78vmUcTLU8Wy(EqPGExP5S0RX{Mn~< zq5w+JSpuGnXjof80frtZ>gKRVf#VK?3n}!fKC}%hxyJ*YN_oU!;%3On7J5mSx7e*{ z6HHkmR1$a6_Ep23-mo{^;e<3vJnkHzg(m{AU`|QIMA5 zKs(4&fU&UdXbke!Z|vBs(+iw30Ci+p69--v8`#BCx>;o9ANhJpy9#T{O^jUly?4b# zhN_Yf1N9=ehSG!Ma|dmjpNa-upi{hEu+BkyMsuk;Ddeqv<_>ceilm4tuosku*i*}v z&>=hN+UX!n_*9!90lQS_q2$5XR3&wwLUU`=_*MD#oqHF|GQIteoAUUoWLHb;+YA9>tEIKkd`~81Nh1znuP>beS*6Up z31%=L?jxw%ne=L>mIz4^==6XohK!Pd1pq|UI>bQ2NCVO+EE(UGCJ$aE?@+PWQc^ME z?XoBD$JL5tW3WBsO9~z4Uc8N!arUt~dbK8PN)HWv%V~!O5$d}!+-juUX~6f`UF7aj zCGE`~4IGE)Q(>l4+VETQsqs6Y;GtVWM@1#1HD?{h6&YYWQt*{NCLp0{7z+zKZ z!1b1?q--S)BJBV9)V;QW-_sQj@837Ct>!6r+5B%YGa+S6Uo{wtngWai_n`#@E19~X z>}8eedEWR<8ykG%dx%*C)f3Y|wr373 zD;H7z!i5uQ06gDc;_n=o(tSp4P(T0`Q;Q+jzZrP$-!!g~ii*r(U`FvN=gJ5m8nF~Y z)^Z>)(3ISc?1sW%7cY?1v@*NG7ZJ&TrV4-K9kjkQR>-&kHEl{kw3Od?bS+%2egNjsDRaN*cvBSa1lV$u{R(4!Gb`&TwXD@&Yl{#+BA0_nlX2)4eJD%L#I+88p+yGP;dA&+3W&Ls@Bz=KriSq)rmBfL}9=N0xIQ@ zq&e{^Hfg=BEULe(6rk9YUqdl+hYn{7KrAC)rzcETAGU}Wfd_Ibno)6ulxaC%Mf*`T z)PJ0CaTO)l_*rcI>Ck2#l7!S!&B6x`msf8C{V%)I){M4d2Od-SJh&Cb>hwtJ8#zJY_0pZXJ@yw|q?8r!Bn8-zlI%}o)YLQYGKIR(77R^C>;A~E{V@s>cINvlttgXV zD5gSsdY;L^yB*`APB10fK3U{oGNqWQR9ATwxd(O4R_7(S7O^$=ZrvX8YD!#oo9;4mo+QuPA?h(^WMGtmWs4-8@8rtHII5X zIlKYc*J-80mhbIRLiX?7dt#hMDUH5BO^+X&#vQ)~C&DQjjykGu)1mIQoAZE;ob@x= zAt4nUM_EAyE3Y7C-h@k}z zb-xbV=X*A*%vsxtxOz7)FUfw5Rez#6Br+4HQk@h3=UiT`#99l8RbWgNLM)PK!xJ%o z8-~tM^R*rHFqc_+&~@|Ld4+HpZcPitIyZW(Ve{ z6H8^y7_b<~CEBH}^Xaa?`)nZt@&kYlApm8hosJNZkj(x<%KZUoGBg>30(<3P0sSGjuYU zc@aDqi}i-3YdXCECd2PzpYQ4q7cH8vif$CZ|4mk`(%|t_5ycK&6RWEh!Oc zDB3a@0}Y4mlEn|mMUmakxe$cKH)g$b@?}HM=!y9g`bpLw_h1g_ExN`&{ra`(-u(&xGzJ_dPpe+;j+hcc zP$aX+7YJdi5r*62+|B!9Z2LCvdbgLC%xa2)P{jBsHe`%k24{Jh&pteypG9{G?G~RR6=3qM#U;9FXSsMMd)A!~v1WA~=L} z2v|FQ%1yUQ*tc;m!z6R6exac4MNY>SfyG-g5%|5$%=WDo4(#88dECcjb#b7iO*@Y0 zXQ^{b4EV07++CmG{M}#1oG1^zQD3y_(PKZJetbo2+Xi-iv8PJ6eR@O9HY)IE8Gruu zjx9+b=F!WOxgH$FdBDENg|^9Cq~adA@sr=UsF0&3lV@#R0Tp6QLL|Ai`11=>-BxF|xZGs6f&*5Z$jV$Cl?HbrFql?!YOP$pKYpluo{@fR+~$AtF@Sa^C62kLOfvGxcu?d$g?<8MAGLmi$z^4 zvmC-Np!2Y~l)y9taOFR&P?9lH!nRG^=XV^=*6`y{Y$25w^FcJ>71nZAM2X88r4lKk z0+j34|(J0YKCidIa!Zgx4XnGCQw^f!q zq94sIH#L11`8$kQaK}qCj)eo~%M$B8d(NJ5&E`Zy86co_l{p?btO2H9G!GBM;(=M| zj_^AOAgp|`mQrabtLtQWGv5&*uWYT z>LCjvr2s%eBZ7iOi?$y@6K*DrxhqmNfaW>6tz1umK1PBW<^!Q_?bem#1p=1aUR#CjKnuN< zmXRO-P*_zbp1IsHdJv{tn9q+L+$zhwy|;=|;yw3_yZ(m{H~!dPNz*Jg>J1CjD2mhk z=I3cQ|6KfgBon>^@LPDp9Zo&p)jjZ`7IM6;EUuyDcQ#QLpIl5mF~Ny3Rkot*o*Zjq zJFepc^Y34Cy9{`0n0crh-&=Ob$lO*`YVDp@XNn6~Sj)0$sDVbQhqVRgMzSjIIRZ}9 zAnRB{{{;S~Rjh06Go^4(zFs{WYN;$luxiNFV>hXW^L~^^XE@VyWx?}bH35$iE*%WWJyJQ^5)ILHEGN8dRe+EXJlbZ`S6MR1PW~}U#^+4wz zWnUs4bYyM6HjzJ?y4u;P%;LD?jzJ{t-^CLcV0Tp-ionN&Wzq!W!$%f2oYvww#18}Et zST9sO2pF!sUW@dOWh#GAhf%kRYp&_<4J-Fj8gXRr$Q%l4@aVZ^vD8aIPb~&Kb+JvD zG<9;QKM&;P<>fh)`jg;v0flt%O-}tmgl)hDq)y&M7jf*}3XL8Xw2Uo+ZufCs;svbE z+ZZERmrMt>Z%E_?w9Z&Ib?&)2bC|V8b?VkC2(yXtG^~`ZV!F;-KPRJDbRV1wW(}qU z76ud*7M2O&D*G5?Dn0%8gs;_(-S9p0&wtVI2;xM<+>iK|eg&t~g^VwWJOPu$llDb% zm{&P`UT-*Ad%<1r6-Gu6x~*`Td-C0bc=gB{zr?E_uzqy$U*UhOQ7t)=EG+ndFyDOO zpUgGqomyjkrdi}azP=%w=N{M`U9)P|Cifk@8X2zUCGoMBuiNK(@LEV4Y>Zk_xyf`B z*fz}T7Jrk~lN~&$F_a4eZR@UXI4yc0yOriiP#9A==$7t9f82olYb zGVn?LE@KHapNr|fQS){4kQDv+j|)ug(T0m*p=e8iP;IlfT+)MDq8-MEHXTVvf$TRf zWfz)u@vD&ICn3FxC&G*9(MEe4|9}hy3dvqnYPD72$S6N%WA<&txE~s6fN4&x-4=N0 zOwGr2v?0i_3VFCoa6nF&Gh-=d8VK?moY&t5Ty}xpMnGpe0m7UD=jLZE? zGrm8M-n*w{uBqm`m;vqS*apMQYy0S0FhN8o&`KBt_gWo>Fwc|)q?+Z_{qn1&%G%6aU4~EWe$a6Zhaq^O zp|b*<+fSUJP;^^kZBiFm6ToL`4$1-?HzOt^=kglQAxS?CvK)rR&wBBA?tzAY@Vy2M z@S^*+fWc!sN_5VfYB;hqC%;EU4(^?8XC}I7^Fc)dhGu5Ks2YFp!QuEdsvTZB%u1F_ z;chc%=2;KMdlR3;w5+Z`Q|uUG_>Oub^BKI~$U!b0MtYex_!)(ry`wb0w? z@86yeXWGG%-u5hGRm5|uuVAzxddAY9fWdIw0M*SMwW9?pM~sDL>ZGd)C!VTS2q~n+ zy+(|<@VY8j!4DO;@g+fbW6N2W`wz;#{#928oKHHP@Jrd{?>$X7tllXd#roZu( zr=3PDZeCYYq>tE598@XRGB?(6V&W#O$&Dq+CAOyfKn!5-?LD3XIaN$WgDVu+UdCOptokd7#LqtA8yBX!*6 z4jnswcC1x1K$MB!lFXhGQlyyUl+$qw&-&9iT~dNpY`>=Fv)if;IN^{10&ABd zg4wFgYTi5HVsd{J48X%r>_gX^Y^UdE0!|mFI5=s^h(^(G$rAyE5NMGt+Ti!!f1Xvl;G5Z5Ee&e&Y!2+1N zA1b1d+$bwKY0fz~{%SpZ3ECroEihMhd$=q=08f2y1j6UszB`KpA-@8Um2Tt0vdllp zAQgqj_V>^a68elXSse9$)u1B@KG!=Bv91F3cPd(v!OS(ConxD&#)@-TF zl`Xd((VtJCyKLLK^-X@C)S|$-5olwP%Rj^RT0F7VKGlubw~9+idQW|v1r?7SU}XC9 zr4aOpFs#R&a08nW^8vcN1JdaYi2G2(T8octs-v2+K9u!2EwnMvSP_6zM`)CH+o3$=LX3+R$h=2uy1%JL))tIXR^l zjRgk=e=efwlqNh80bYecI4LNb`KL)1M{Q_+3&hx3B7?KEet zFJc+!||G#nP&WCWr&<7;52gCUf1y!cD+T-;M zKCfH2@O>9G?|y898$CNT?E_K1=x9Jd2XX3OnPpFU{LYLe!J;8$_9 z4JjVjVv?!Ec_%I5iIJwP3`Jzuy#dT?X0>ILiT%=*wyS!-eC62nSingwjdp~izep(> z%hE^1V=o@IDNr?@YKN*sQC~Rz*4VB-;`G2uw>>^ShxTqsTaG%S%k_%s%Xo+$O)rz=+pFDU1z&C z<9$61nxtJFGj{AdHrnUR=cDiKqbnb8v6GQP#v|&#tJ~nK=)~rCY98Bv{4_IVa9ddc zfniU&^WpoO0c@W+$5UdR?;NsBkHa5^k0QKo!j*}w`RS?14S+jVK0Ft;V20MH+gDwX z(oTgvK*My=ZpGSN$`@-|WilWt7HL6Se=QXsZuAD{SK-14#I%$B!;ANw-6S9o*+fJs z>UZV_ldW*{uDH}S8xEJ>aDH<60a4Y7!%C+|E$pVnHB=nYch?h#67mcgM%4qhPcnYq z=5kXwD8F;?#!|z;mGhp(3jp;)qn?8Yd-DfHgj~v;Dw!YSTu;N$s2?@|S(N!Oz(-Ll zJ5Z>{+!m6)?*XboCrb)-d;AaVm=RPeQScqNMIZ>`N4`t(RC*1P-DC!c7$ziMFYD$` zETsIFeG3G6$emAL1W@B=jj!su08E)*^{07=`mlgiV7e1)=x>GC`lZr+0{RCH`r(%X}}x-YWwblF%vOFA&#*|NL`< z>fr(ERqycTg{uL`mW>dEoSo=!8i?}>&I3)^N!;a)$D5d%D$PvVJcjAk z1t1Kk!oo_ii#Ue5!*TEzP&bl%y;>swrpO#|#%5~=dM$CG1t61AbL%IwV0tLepOPd* z{Apgh>SIB{U5-uD7A-QmB$HP0=br}Ci4aTa4cyTiB2>YNx|;r+Vfhh)vr)7*Kv0m%l7kfZ{*InIWsq*?(Zk~a#O0@eM``DE^( z&aaQ5-oNtXlN(%ISFciRIx(i9(_kY7wJ%GNy1|^WJJu&J2_3K?E7=K|*((A0Xc#=N zsYQf`+h}B=175&OH$Hd^#X&nJkf@Ha*7m14L)JvUZ5vkV%T%rJ+4^XC zxl8Alq2q|7eUY?9@GzXT)DrubE2sn`t)ew!)Jf%`HZd{#;;z@(6jguj1R=_KMUU`7 z7$Nvxd=x*KCcA9daOP?D^R=kuM6AUc!M#|WpeyxY^1)_Y9uJYul-A6EsX_RpzP)<= z4e-u{j_1*%v*JrGL`F8D^i@gGkd&16+z3WI#Hf>9o8Yh^ZD)4Gp6-9NMB*1B%e|X7 zmE!HZsmXXFZq=-eo$-0ixOE?IP^f;tbT=hs;A3UNAb#f=(-bflR%6VzP}siz^vOsN zmxkjJ@j}^V_&8kOIBdV}k52r2G_4pjKFY7FbtPk60gXm!z(d7&;dJFyYFoCvym~Ww zhdegBv65`Gntp2fOowV@n4t1RZBO0=AiTJ)@j)7>Qi{8{3}*(Vr!StQxnvR-}iw6p5jP zW{iij-2B1PGo9uL!7w?KJu5C5WItOQ)Wj+ ze0YSI1|)A?avAXcbZNe5!ZCw5Dwu_A(EwM0(w)Ii+RiFn1q~rnpzUOS;2a}56vKB& z0X%&fC80+*A5#K4CwnRSn*|AYJbK(XSq6v%WCj?$yv0c|A#R^z6V@rf#kEjryt{X8FR1y32?e=$o2~q~hz)b~Ja0okzNMs(*wAF94FO zq4yfdp10RXOAkk76kAZywdvhEv={$hnF{Y1)m`SDJAEGVpNXMqb7)#J0l1&DseKi? zu;%=+<=%z|@%=fz#M#--Y2`}$QyI?FwA4(GR@9%miN{*9`N?91?IwvhWR1oD#T-_J zn(tNwPLJ^O`QyL;CAD69yr_BXkQ=$ryPDTWD6gx&Qg}S5ALf(4e|z!h_-h7U9iBe( zRm3jc;c+M$9UW+{%{8;oG|q5NA0fPY2;hyG{gXJjj$RD=lWc*6*F7xd3c`Kz2lp9< zE;YFv&$t^2a~q{_&ZV{TE8l(XEAr`s!!C+QT`L*oB{MxssVMw|TBBWn*h?~cA`PZ& zmE&yx;n%+rh%2z!$=#%jA&)wqm#6{B&rsA z0^h*E+&)F}V75n^gg1DxfPn;Bu-n0hbeCyT6Up_Y=Soj@7mrv$rIny}W#FAZ<;l4k zx%N~@-(jcjdGs_=Ogz7~XgWP&MeVZahU3?ZD2!v4c`D^Pw~4u<+Ys^(d^Rz4poi5- z;tJq=9S+>`^Y!1{z-sYK+kaIG_3Nry@pTt6w+N*jhjQ71@_Gs6o?AAfmd#}uv#EQ8n-iEaBv^k94h;K5MlzDF|qtibLP$`lX>`NGR<4)bgABu?*JwztQeHM zN)o_~9ahRYJ3w8+`Y2=#xCn{CH|m#$f)w3){aTF#PNmglOA=EF9JA8ON_4Cve{H&Kth=-=TQveW&TzmTTw=d#@Vq>imjKiU1(xxvM2y1T3Pu$ zzq1mZ4A-o-rreCq=M_S>lI!Iyp@%Jf1W%z3a^4q(z8A!9C`_nhHq?rU$UslElc)+d zQR;kL(S=zrdX~Pud%v$c=UTMJI-}}+ibJLHVbk$Hx=ngKx3%kcD>p6@bJM8 zJ1n~w_UqE<43k6N+F5=!J`eqN9}V~`V8O~OzT<*>MS3kiyye>Jx0Q`sJ$c%tW4pFr z8|6Js2~D|Eb-ZB9nR_|qdL>V*Z{uOK5fO<0IZ72K9`B=%`dT|7SDkTxv^T*S&R3|x zaUqRND@EC&MyR`9ww59vxJZ0?RI0IsIgI8Qzx}vA$s*q1MIkN`v4wQTkRg9V5EP82 zQIyv!`!_lant6i@{R%5Y|21^k%%a@}?rHA3oKr1b0!VFxf{eMYdKI&0&OA#n=I720 zt?nrK`}Pw1{8y6$(L<|5R_vJLrT;KTQ;BH{Al%8ZXHHBuBX6ka@7lio8+Tpl8?d0r zc`y;cP^B*{HoP43JSL=b)XB1AkE6YZGJAA`%1T?P}|PCsSw8a+rtJU6Q?}EFCUe z3kcNw9<~=_Hvjyl>o7%FnpGrn=J1Bn3n$t?rNIE!UEv*9N%uKm)g_=5zb^nE=7o_eDk|p@H&kEkF+b?h zU`CU-D0RPcv4bT}V8ec9F?m9Bq~P7(LpRq++qoUo11x zr7h(NFXmrrt;#ztX#8fNMq$9%7a++67?YECxB8sbm0&s~QERo$~7_bW*gG($B&eBa`D9>r#7z5%ynEbM?3H1dC@1iG+AC11mYVrK0@Oxi2oVeHF?dT%`4ZhoS(!OF^|buoKZa?B0VF!&-lAJzndXe zOUmtM=EDd;1og{6oOwqswm+~^d0T-*SyHdsC^wGPr>58n_&&OS|NhXK(}#lN3qvoK9F^<3@eab=K2L{T_HUC`UtCv)Y<+n@ zzzdNVMM~qLSJ&B3E|0{>dIo?C@`UF1u&MQL{GNZKkxg%8ienM@Rsr6Xvho}~7H!gH z7WsfP82%?>vewj1v_@@q6cmKE&!%9!UH3b`E;sXv_ow{iWS2ad`N%@Z zx6-kitJUMx_w7|f6Ot6)H|-GSUUTcq;_Bnlvef0(bu?TfL} z+_Pto-=udSTn{jfX#Rw8#Ap*O8x!rzBeuC>hJYTgWLzmTekMGXn~BuB=aIe^9H+HE zuCvJ^YQgi*-(7$I7HyERaq5=4>xLkTxIrOH?Q;BlEHjHw1-+o~P%Eb1Xg(_mQxRfG)>*5`O8-UEq6MLSMhoFdrVI^XYvU{*@2nsJLR>8kQ zpiY@P7hiCS_S47L(uYU~&6Zg&QUqoI;e+SGvyj>-6FDba;u41L$Mqm^jxW_T_f*ru^4 zn!3|HAKX^fUD^G3-Cq&76Nr@VuYkV>Zr3u4WR(Vedth z0t#XmICHm+Da=p7>!<38_lpEOBz07wZ-Ad6!Tf7A1*3y$@A(xTZ#X$xQ-7_zFD-lD zhLI;Jd*1Pmk@n*85R7Z#jk*)fp5ZGX>0NvuH~f2K!jiH*eQpF=DpA;7lTTstqwxe({f8>|&gG%nKny#^2T2wkJw~%rx@Frfjf(G0~^y5btbG0HEG{sxc{HP;WN| zuoLGB8Zk@T1dTgeh9&eFzvV>B|LD3qo_+ikl_$Y!X}?&q{fI2?<>RALTj%M1Hx`OVy1xokp)(>I|4rF7*tB8>D3NTheOH`R# zdxw!YszR!`&8wWz@$0@yP}F|=CcS91Hbz)Z^FT)44kAQ+zwHD(?uY9o`?3AC znYDLH3uy#y=w7Tt6XQsas({`kmXzK&I86k2MC~oXMW?4jBT!zg-=HfG=}6=9zZ`AN ztokUCx1q(&^J?;=`1_~lUOR-rlV(cIxodSywqSeFo4HZME);o&6r(J|NMU%2A1YdZ zX{&=be<}Kf(aax6$|xN>Gw%)qpanO8%yT%?4lILMP^@~l!6F|ck6&||Vk0yjSXm_3 zGl$0+@Ui&xpquY$C@Q-0R%K2J!%V}_VV&R~V$K`%A2@JY)$heLEuoj==3Xa$ZtH_g(zjEbQ-Mh2e@~N1KA{sPzdyY#$5SLj0+h@6v zx2_xYy|IO`Bl0AWywLPd9|_@ML)HN@s-z~rQc7+2_c%OmMa98b`CTYEQCT0=+cH+9 zk>p}3ospfCpf+?a-+imV0TG9E2cXZ0!p;W|Z_=X5EZCEPI| zAS?rg6cj7N*OMSB`4Kc`X&-fAl>-qGH}#E0)p-r-6%$6L}%!6-=vp^S8nZ#QtIa#qM1LLxGKx5Nj zu9eqLGhao<#;;e3gc2lxj%2w^b;$*kJCdOR_8gX8=jXtWn`bRyoWk&FIy}5^+B9cU zx$p)B=ORPO;vta;i{b=oGG=qSZCf&i$R~Lc)>ocFlge-5qPhQaQy{qH=k*qC7a)Z^ zp_wy}SSe|l7uvKi?-9}9QGoVd+=*G9GMOt!4@LAXWA(1$8*08X*wD4mg4Fl}1`U#_ z>PN@N90W%x(BXN>?orwznE<8y9L=gM*@g-DD&tH*nNWfZ9uGFJUEQ4x=QJ)*+d0=a zNz>vuy=F>}Et9CCz>TNGWy-Q&F`=LkNFkH$rT3yn2DL-9!4BC9-Q04HL}%=}Q9aW` zlyNp$)p%Mn|DA|jd6R4CHTZ=HBAFfaM~$dlpgSAOoQ5}uTPP#^4>|29Gu}-BDQ9km zxp{ETT0RmxFt0Al0Xm&b^~wGzs$`r}PZ3UeFw?S_NZSLT2=)%C*Rkn(0?&K+(GV* z&9$dOfj8co%Mlou(K=-QL1Pbn9^_i|mx3#Yoz7vRIl1LzBUgbjQuZKvFeLo9%Ol2i?lWHW1SEcG-t{r4ic#{;6IAOsDmM`Z z^6S#DgB6wg!u`62bLMpIIK=)G|5ms)qd7Pw-~kg>Q^_i%2c%o98InHhN^lQ(J3MYx z@w=c{`T|ZzZh0-J{(J67Qrt4|e0HoJSL=2G+H#g}Y-@QLc!D%aw2$*UZ~Kv1erfJg zi#}hwa;5V=3RD!%^c^#N74A7Hsj1PgpE7RP&4akw*<{Ug=Xho*2I@bBwsHUc*+C@G z)FhahXIEdgoJel+U$7&(t_E>qRdQXmKIN3BP0Zwo^aDqaM)lGCY7I?76!Pz$bh~~i zFXqQ9v?!D}GcT_`Iib}yt}I27@Ak+~iPnw`7K!08X-ejmgy7)&-$fWEqCu>}Y{G-+ z==M@frk|NRj^+=bC+v0G+z|?(}1ZJL#*c2n75+Nujm2h;yuqe$*D^;g@TtPtrzD)kxjjj3N8=0dQ z&{E6hK&Or7$!#0AP`g77iqcsG?9>z@gyn0k*|0%&)TU~kk;}qj{xnSk|}x9$IK5g|)i zDqE5*B$TBrAyFc0)@<35y;8!|jHRNOBq|dsQc_vlXk;rp5s@SsN>M`g<^Q?zKL6)< zj$__uUh4O|@9+0o&hxy^%h>KjMFT2QNq{VmA3A$GXna(-OErBj-hFDXT2r z=y(26Y2OLyO4sIfJUjgoSXx>`B`k_F`xP{3>X1>=T?$JM zx_>Q&I#%~dYQ|I!Lg-+{bF3wsTbmOUpAmB=w@q+NAk$~#DnuGFevI-Etwtl%wiCxJ zf0eX<8m3@rV6Tu&vVvg20x`xCmk9udabH!4adhQhINu_Y1Wc)O?eOYJW=6Gdyk!2Y zr+J&3X#JHwSxRhXiL`c)?6Zh0&jWprrF}KM=(Ez&k(@*V>;#MR82$g#a+cSher>(| zfxd+u;&!~85u|AnT{d28 zOprtI0-D^B2yh7dpoT;pp?8bJlUFX3v}7r4E|q~S5tC6%f!&~s zzToJourZ*%5Ka(gYQPk8P~D&m6EQF+k}E<_d3wT%?cjN+c$2;lWMQ-DAt)E5z)*PL zWJ;53r(1TPYQ^FB3?TrRFdtpE)YR8nf0go+I}X)3w}}t)(+-1bnxU95_1+<%kKG%r zc!^*^=hFZ)Y2y-41V159Y>$j=BU3oC<%nq$p-w@IjD3nQ*pq1Hho>}4vA3O?9OutUbVFjXW3zk&ha`yVBz^|-NY_QAWX~z4h zT^v40`|M&}?=9IP1pY$AV_dDEY|R&$^{Iesk-DExAEP0XBS`mZn%0>zP|7M<-1zwE zPa7JhQ0qUjAra@!cNVokV%Q|`WN*D)o?1y$lhgkd4L!SIdp&H?tl6ZJF9&>fMMmBP zIsSS0R{I+cix-z|2#sGffBrF?rtKcrZK#_?=hx19u@;*6Mr0i`4_ytg&N+9|YPGDx z>bdDKC`@u!$g?wC?Ck?*B|7e*S!w}A)C>V$3l{LaSYj5@n&@f|d6#GtV|#D0nF~l# zJiO{F{U94x7nkruxrTSKXENm(&(*zuMxrW|l843WpxYpaIV;Fm%mmd!`otZ=w|}UUR1}6vnF8 zdVENKD`Jg2ZCh2d?lde6Ipuxv*tT^mD0tla3jJ*{(M=P_9)>~Ph%KPSju^zL43Suz zOR5D@8ol3}=9&%lEnD&I+iXeOhCA}f3j3$JfOq)77oGu=!X@5X@TX-|yX=*|Rc5Ex z*bXu0{|ygJOxeI`BEf*d@IM! zm+uNgB6j#RVsn{HrBKoGrDC9gDVEi*Fvr3)f=g;h#1V{$dBICR z$sE1$I>J!@8f~t)|8T(t1(FZP8Bg~#oskNQu0hs~B5i76GIJC|mNJkF--Ykjv#P4wBtl~T z#9K1(EmOcW`$Qc9#Z}Za6j4Kp@Dq&!@rx)ZjbpEvTIR&#ATUZR%BBIB(oU)Fd-DnOas{JJ?^xukir=Q zs$2rs;eFnA1F9er#9XSYu`$CMGSDP2DZK_H3ywWo>9zPI*n2k<#z{0Mlxy{TftX}B z4he7s%qwS5`Z7#(l$EqWm^Iv{m>>iXB|<62pJ=0#C$z0+4p&u zcSWo^{ly~L2PA$Yr1_BuY(?i5s;e-qd5g-t(XLN*DMQTID~~vqADUz5L1-j9s&p*1$@WAWLd{bPPa;z{W&Xo(s4$j zY!!(|(RMQH7uWo*PVsH=N)u5Z0Mw}yZx|V!NAjS-YoI^{2(LfzEmsfh#p^GO8oK3( zyhz4M;0(usV9+IC$<{aQdePBoeSk1-63F$KE8Np}ge!E5 zFdzz{_X{=TReocAD_#`1kl^(r+pax$cR)UyB?CuTTTlA-2%7iT9NKh6S`-pmFbxnz zt|AbG%t!IM7qPAY*6ldD$rqpHkMMloliylJ-up%2bAqcV)w_b4MVB#<)4ejQvs;~g zd!d0cGs8Uq1Z5Sr*5DkW8*GB~FO$kexqX2WT1I_pmC@DDF8aNvjXl0N*N~|tS84c8 zE^-LnpTjj;i)!EzV;^_>iJj8@PW=gE_1a6YY!ZFmG}X?REB(QH5aOBGMlX_#i>^)C zwPlJ_BuJ&l|ItWG%iODE9d}KDT6*wZ%bG8EO#>{g#7vx(%E}gtDf0O7O@Tg%I9(&F zsxG4_L2?;!K85I*d(c(~Mr_x=t!b(qv&n0yU?eSaSU!J{s6^}L=FLrc% zs@H~uAdt~p-)Y>wgXs3+cB$W~s4+4!GUfa(*lTxa9xh9-p&71)0k6b<|HexfhNol4 z%f)}NWh!9Dj=GR+|K8nSMTC?@f@b{w*vWD1u<!CQ2>mFS>&7>p-vTQKP625^$|x0P=*NmjCp(jdL^}NSy$8{7s%G&l2^|#O zm@Zu-UzO!2w}YHBxA3bCcrB$8Sh6|2lM3a;m^Rr?lh5A2b@QgV*TpvN+T8|#z6g}) z`k_C44@+&Yqj6}MGW*OLEmTJsy!eyyO-ybT-#!e^ZN4>`^3bOABj1bH8KNJVkdmI3 z_Lkb!_(y%?-$LeTEzx~0iW?oU!oiH z3ZlFZ-PvTa3y3#aa}g6Oy_>VrVN;V&*7|Do<>S{-J)g9nGvd{E=&6Rark9*9$F+sS z8xOifj9+@J2ii`G+mPVkp{N##2E9fpe57t2%bPRcND4}LXMs|NQ#)BKQ`mmH=N#?HwZT3EO9kVg3EO2o`SSjW9zHFU+XLS>6dn$?&unVf+HZA1_x-os zCYu&FVeFL)N2fE(17sUxRUQ+OYkXM@Zs6lS*Mmi(dQ*nU|yBS3x?=3yEOeCBY0Efm~-YMEj)%L z=S#WEIcOO1@retGN6IK(A2PhFfZVhmXG>Gxi}4-`>h>&yKoSiKdY)${IhQ@#>epIn zZg16ZJ0D-CS+h-!2@6oc3xpazoxQ`XL8?mw&R6U!2gD|MO0L05E+Ig8QO@Do?kd|_ ze3Yl-uF9CeH#4`F_L6S+<+fwTLaGlIRV8mq_3fT>-w#c&{evqe##H#X71PE6Etx`I z^MBRdb#4O?^Fp+%#4ge02`!J|&XRHZvbvn%)f-UKp|9!*lvVT&>DEfDSj2)xTs=`n ziB3gGf~=ezKZ4Peh=gCX(7C|P##N87h5&gyiA)3W4-@L5Ii)kw?NT-1*!nN4|A~y$ zs{DeTn`wUsu-yq`ga(kZ43%fU<%Qf9hOCd;jrmg9tZmz|4ADMB_6!>-&l@0S!P;}2 z`)*ftk@#Tcy4-Y`+8oA4BwWuG1|8y%t=z>^{vG~4U22eJNLONm}sV@%^WZ{7?5 zR!4YYgarpLpAR)H!#)1|X*{E-ZA6AVxhOvV-4;Da#O#<>S9`s&9av8ZYxf-CpTB*o%9LpJ)834QQYm zwz2r|@4ThmaiAFIQgpH_3#Xo!mM$tc-Q;D!Q(Fug$X6zTR&&*E=d~9|@3{kmkMptX zR;0T$>(t36*)d@>w|!fW?%lWY&jw5zt~S>nvpqC)axC%<$C%uME@lyC^k0)kkG}4X z^FFJvZ`@sM_J~4xEwcfeDa%KYEH2ZF^%M*9>CVeM0Tq4@AJdN6jEdTO< zQg^d8we5sHv>*!4+CLV3JjBR1{Q9k17&^*=j+hea0#I-wf0xkRM_z7}vn}H~OF_#0We9(?WPCe1YzsSTGuxQnu%}-%$G&}AQ2Q}I0i}BMaCn%TU-JFqdQ`b`V@yC^cA8EVcHd2$Wqj$g6RG*)=q^9C%$u!odz2 z?Hba|+slhW12N(YVvFbm1iNB?#%2n%{CAyul<(x_L$^icSMaq>J-Ylp8DX0ysfLAP z%fN3J=RpE9>*f9?t@GHW8Bq~=J9+?(oXjsT_X^Yv1WI!zMva(<8DN%!2QhL5#9>3I z8KiTtN#5|bcqjoPhgi=uux85r`-+Po(tz5@sao0m~CjdSc)_MwkmfZlT-oJSkYHwjGWF`OsWaujPDUq${ zajEFP6sw#a~qr(>Cg zIx;X75KIB_x5*)IEp=bFa^nq%6EO3jAWX*8MVM@D=)*>&2xIkC-FlqajnF zz^vk?aG-p3*;cn-!OX|KtMYWzER2sYz%QTqBZz`~&9K4Oi7fMi(+Cd<>j^i9g^nu-l@J=Aq9zlvG4$ZjE-M5zUM;Jm7AGxs}+uC zZ1+K3^xL^rXfo|0akE}-80fuDtji#*?$`fnmR!3W}JS;|TYT4q2d9jFcJF{F%dkH$YgNbh}B*#pDMHJqN&6aQolhkv~xmHDWf zA=7a}9Fdq~RPH#rxj`%|PGV8L$U^Z@V_BntSjp2!b6gHLdLx9OjJ;g@$d}{}BCi>F zI>&(xi8RgknDDZD?5EW#o2EyEc(hgktGVP6WLXzG>=^i0OiTwp)Il&xBK0A^ESOU6 zZhJGcyfX8|#6)Qb70$cOr+AZ}dVLm}Vzq!=Muu%jkKDTwz6RAN_xmt#)%~K>xN|q& zL_IEi?h**#B4SeTlSY&av5jiQ?a||djjY;K;Ng(l`yq@^E+oL2wolf*Hr=#{(mYZKFW%Vlr6X?E?i@)xVcVx z_;48mj|h9hEyOiqn7_^N-&ON+O@(Nb9$(g&i!{G{oc#Fq`gLl{lQ9Ul|aYLbsvQ|I!l@q>(Q6vd8HQwRCoocaI#?(^J~CeaVVoVBftRc_?dssT3wlh@uF zEjD>}*%W8~vj1(&1}@~a_cxyOp{{URKzcmLyc0weQXe}4tqfZ+&sDh;7`V=uHe1t1O2;>1ge(hUwsVa3Z~#&Kj|8WH z+@+}&sUhh3sTEJ#2H808Op{mUW?1_fqX7kBh9~-s51@=_$&>`Q?NEFNuuV3Fy=pw? zB~+JKh)Dsl;=h}lXC;?X4~ZWHjV_{~R!D0W-#-#+rrDfeyZAQ}!rwvO+{Z&V6rNx$ z)rz28Kp*LM!)Vt?z%(HvcCRt(!^ad;AHp8O_a)^kE4gr*rMLH&qLyV+s;R!d-Hx_{ z4q8x_TF3l;s)jv#QpitYzp#g zta3x!BZCsmd%fEMu0rd6%~;_C@$aefIGdz6J~b+1+F-UT9x>B9yWeFbWs8{gL%HIi zU`O$B=()9gl=ig`&v3|)r+kzN)pOe4fVOu|qoSg+4$TG%4j{h)sC4qTSL9()?xLKZ zUE)m3BpL-Cp3E|{@w0A3;PtClpAnU2o>>zFy~z+?Rl0@PwbL4|rVNwyG+^fQUk&Bh zYVG^Y!EmG^wRX}Fo9Z57s&LS4W`5|MGx0%p7!{dm=Q+(>Xi1XRvEv`;gaSK;5r{}P`M ztY}ZSo_n9`B7!nv+%r6=rRJ40jNgH~h12PrmoHvaBbO7PO(HvnhHXZOq$;lsRFk1h zmm&&dI`2YWl)r{azkd1M_inb;&iYQ$3_>bq{7nr#y^J~PSU>Or(2?B@G=!BI$*`1U zMd;ak-P?stHg1j^JH(_Y6Uh>y*s(=r_%V$FSIRipaj*Y^M;=_uLIr;fwwVQ80X$`6 z$sQvW>qM4e_x7k~Lxu5&c&c%lZQ2d}1 z)E>>A$s&|7)QM#Ur@PT1zJ8p#gVAH-Pd(8BpxqLu7a}+`e}(CE30NPm7^V;NuWQn$ z&%M0%x*fI7mHQE7Im)5gJZtfHn>Myz{A~tlWJ-~N)}+2FvX}{YBpiQzh?wMln!c8- zy_1Y5GlUGqgQq60`32L*x4lJiQr=~l{H`^&9jykPn0rwJxjhm{6I!VMo0_GVlYNfe zGW9H(R>WKmPG!>CTl6xbhvi&jpM$8m7X^ad`vKIVkIwlFfyH3jUgp)P&I4m&oD&NZ z;?AKjyYWutCWF{z!w;D{K%?Vh7=dK)_}!^kW(%VYVG;UMX>0`+k7U7f*@67CYu)5T zoH?_u%?QUc#ydq<_YwucB97POpOwZYCJTXEq|{+N%XV@w@6CJ6PNhcdySRlfsA*8? zn|gm(EL;@-@)tUAFBF&!Kh9>po>VSder;~20=(e4Va3)=a7ceU2?cvBEc_XCaKOTsBIZCx(uDjfYp(A@6%R3Q$>vmdH&?! z&Bg%G{zHZ{7~Y3oZVoR-Y!txEz71wftQ0yfmWCNss!q$6Ib3k@9-~SVhTz)2G{2Cb z|K#OOl4(!sJD_=y^E$v{3@zNf*b42%m^OcnN8i8SW=Go~yh(G9^GVUkjLT_i-jL%h z_Qa6>lfPsoOo*3FrgXf^j&aIF?+Sjl8G$Lt*n}5<5EwH~AmdM5#05A4-Tzl>MVWj)P?yB%r{~c&$q-h-VSa#+YG7IBTkQnL z(qcAJKYnZKX%S<5-Mt8M18h<`25KYCTGQsuFH`eMP69B;KBXFIY#*1q2Q7k}!Va_3 z;$&ofxOJn({xviI58>n=N6cF2=v?IQK?v;EG)x#m$+FWG%PMNT6=Cu=z7ne> zihMEfqjEg3zD~f_b3I?$=zEzrq&a^Exx&JS$@0LjO4*Rj#fRO4~r~J3*EL}oBWEJ^$5QK zLK2p%=};+FZk(i==LU$#&d)uN^O&-XBK?Y!vZ%p3cH9hFravfY-q>HvEZQScCtaRr zxRgFc1e|wR0=Is{yiP7A|I-3&$gQX$|JCk%0D&Pgv2z~OYqt+!j^51a+R-}HSPXuJ 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%0D-#xH%e5 z@o5M3Z;n;Tc_wGJ0j*xRe7O!t8&BC#J}P{7OPSsPmE8hrA6C_GZ(wEq)vm|E1zTFE z-@S-GI7CcKi-s9$-~$Njtauo3{m5T863IRsQ7xlhMt=3zB;(DKjKyYNDW(+2#=JJZ z>+RGNUte_C2IWoV?~77`Bvn&pK{}Ly6QnXgzAJN9p{uTG4$QWThDE3l+Toir=E2%L z@fs5u4ibiYcB({1H7zYIaNkROVt4&Mn9Dq8;@)pqloh`j_D|Ae#msM*?&mP( z^+9*~*b?pr($e!>2oX)({Ei$#w2*=)Qi6-e1tg=Q2+Yih#$IxV@K3v(S*%kc4htkd zSwy}brxoh;{^U9i%C^d@-`?o&4K~Fb@tVo&7B`UDNM5BA1{snXUl?p2_aN^LC`f3f z8Wt~{T@R**CK;h@TXb4^M!U{z4`&vGry<@5aBFkfJvb<1EFvm8ocwK`qljs#rkVy5 zfc6eLsunxSh7WN*;4;L(3=$X=g=2toaZ9xP8kT)V8)+j+PzPiImC3bLMS=4ivx&QF zBY$^vfrO0qCMILMsoX)J*}ABxNQB46ji1nMDYE)dBj1^yA@$h96AK!gIC0`b+u^%0 zi=XChs~nneb(!jjY*bg&sl)t++5kU@_~tiFtq(3g$oolRra{KFuRf9f8VAzkih?aTCAFz;-Dw&;fy_ZYHa#dRx^?)LAuY4e z^PLs|@%!KK_nc;U-{WGUgJ-)iY4;%~F!PF{Rzv_QurqAV^y$-yO9gK}j(rk2<7vi? zePu`Li%TfwN5i(B6&be(I=M;R4(~fIV48X+(Q*gBdwGb|JJ$2p%lBHbFEDh^9`O)h z+0%n{gC(W1T$GfOhHH4Q3$KHd7BXG2tfJbLx*}Zt7!>xJVSWduIOKN?ae4Ic;jvG3 zpE#nZW%-(MpWeO8sCX}+H-cGua!D`e7tTO}Z(1=y zQCOmUfksODr((v>?sRYb8R?Q44#!qe;})+OXmDMGeNO_w>6AMKNBRyPJS%P`2kNVl zBlC=u+wU)ZV*`R|!CD<19Ti1FDb&WF$h?$(sdd6A>gq>kl3aYJ;Tc6Kj6jbCsp zCOt(#e}11()o76hN<(L>9TtIfRSFVD|3ynl^{BA}vySsj6)xSKcI89E$s6j~!kxE4 zEXa$V!wL4aHXKU0s#U1Dnjp1=lNDIuvp3UBH!D_TUfsHVdp6CSh_j`=0$3%W$?GLp zQ%hIl4Jdw1Fs*;l&76Hev4!06iOCotgn6H-gX$sz!?W+8&M(ZFuqmh`IZsCKAjNX? z^3EN`W1Ns%9Ru03^u7tZAH*ExJPbFcm(bcnhDG+e2nbo;@}Ul_ z^;Y_fa)4wh9n4)H;3rs@iw?-T5lsM-I=*L8+hP)N^Ls3P1X6!|Hn|n|D2wV9|KI4_^sGIbX)RpOJfTGlfU9hHOK(U5ByS zo5unAv2D48fxL-H5hf#S?;yz{^TX8(Yb@~E{ zl~rwM&a&7#vV~wIPW{u9^#-g)T-mp;qwD&+2Wv5kmYKMAg{7?Q9&mjyAYzS1156N;C-f)@xC@_ zNS8HXUV?ftKV~ig4X+F>&kwR$@Hf^(98XOqz~Cu%rH#`Lxv&Dj+1o9(RUB2DXvSn_ zwgI+Vct%uzkCN^`eCQ9rtfnAqk)=N;oxV9jETTLb2{9wJ8)8rtI_IX8TF`X>tk;DO z@t5V^iUDXULyszom^SAQv!4H_bWkDMGqimNsrYZ&vvcRX6X&+cyN4ICy|ru<)Hgw{ zZt=q8zc^kIHD8stJAA&Y0aKoR@Q^a;E@BpNKVMb^s47T0j@YVx=Z${8KKrMtB0g4p zdFvMb(&g$MuTfL@b=n(owFxnQZ;9OKQHU~6=9KG6T$xr+p85QY6h%jei%peo*!u|O z4g(BoiZoOZiq6a=czWE*X}hi=@-H<7XO5y}{?^t;hBD}K)xVc!mK`TO5izAGql61H z4n?zip19AxjcB*mV3Kc>eSS1h-l7&gPfaU@8;nG5QBfmwci=YSp-Db^Z$b0JXou|a zMhYOWTj=G=%0_@ED23)Q7zYkiSNZ<**N=8bjvO&du6q6Y5}lQbLKBe<^{=A9JBnUa z*bQ(5YFHthku#H_E-*=8*729J67iHYGKw!CnQ2oi>pVYG%{#Y+=cJqB))Y<&w@-?R z8D7@Jed@I8oVLLar8X1|4Q`sfu*nvc0~`qIz{_%@m<%5pKS>V0*fq3TarRG8^2P`c zMDoEewQpO3LU7ZNAFmuNO6Y3ymag+kpdX(Hm8JL!ip03D_nuK35NETMQJ2OOu@YvX z-Ng^{@l}R~ax(Js7mE3i9HE}ss5IieD`AHMzIM(5UnYVwfP z|J9?EA>qr<1i8C8bHj!~pw?=NNcW5sUa^4X;PeJega8`c`TkufV<@$!C7;DfcZ_Nl z1uXKj9AMR62oyyvtQ?>*&u+Ei!{>hp{^_4b1^V0DaDT(?H3F;+-F2W&e?Sb?w6zz1@IIDAd~rhFn|1Ter;M|_`Oh-Y;;~O)#m{W8 z&`=^Si8v7!(|*71oBwG6nzU%4p&)?0i2O{knpi!B{fX%_8^urB3Q!HC;2PPF6c6y2 z&18SoThA@LJ!TbK96f!yIftC1b>I8Qof%>*3j)Kz#ChB0Z5op|P=`p<&tJb@k(4}o z!=8t`)mC;@f*ma6H7>rR>6xbLV;Jjtp#mL(7j1+`#cC0EnfDKUJzN&)Io8^e9!s4Y%H&NvL z)?#euc}1tC>0-VRQG%jXMm)cqro$1jQO&)(cX^#`IG0W?CMl^Ax~sU_nY2TlzMvdg z-}zh*-g4CEfQJ{(BH5PxI_zr`02D;E4Zxi2qhddgBWQ|k#b=%%i9j}bPj6?nyar!` z=QR1l$Bz$Q*d5WJ$m78>&7DQxSdG_S40D-%V#jrPOMmJNRA{qde_lTxW7P0F7mRpx zVvbdj@6_g1XZx@NpFYEa^6s6NnWQGApEFmvbLh;a0m_)aN*urb(e??mFJyVqg;H_{ zM@A;P1u{U$98@(h)T_eRtxh=SG#dExa|t1?EVo+v#p9iQ>lkIa7{CL>EQ9} zHY8EsN|BJpsS`R1RvF>e#bwcLmIB{zA)+!#N+HNDy&&6cpL+mbMY&VI2{K6 z1P8LcV(V{nwNM7+| zd-Cvbw^=)xt6gNDf~$Cfd7=1D4AaS3GmkW!YYeW#R=FMx|;K#4BfgGgF&p)-X~ zq^S>j*A}Gg`&7+2e z|KsXSz;a%@_W!#9$&_)MiVPw1Oe#r++9*^cGnsZulqM94Ol2r@$&e;QgN(@-84@KD zB1utHWJvmdR`!10-|=_6&#~Wa*L{D7>sr@Z=Q`JUQdAsn1-?DT&25O#<6C_w>bPte zKe|6g*rysAp+PkycaXtt8U~!g>T5cjHM-Sf@hOfIT1Kbwp154j*m|vHag85=k(8p^ zGphXR^*eX!GF>C$SD(qA+Vs>Z8g}DsTLJH#7#bSMUrt;W6R5&rCQ@;N zW^jha-3r>fR}F>ue~Gn{-i3}>-#*9;<@5#dot=_Mh`ALZq zHHd*;IDmNySGRyE;NNPa*Y;C zDIgJOxrzc|2_^1?FHJ_Pm@u)xT$y0^8i-cTe^8FKz}xpLd=&z7z+V`D?{W~fU$mZ? zz8T5j+Tg)cJ~=Hv-aFGdczd)~Agnx+htogB&t&Cz$$*`In@KS?Eb96Y#{xxu6SIH&`& zJhDvS63?b6fFPyx-R=kCUkBeEg#D3z@E>8Wm(onR_+67)?=YFv7<@PDb1o$Vb__>z zS&gs6QA8Lo7goQ(ncy?qzp?NhNlON{J4L=xO4C$=hr*#m^Vgy3Uv(I1yUr}mfEYOP z8W1QjF2f*b_;ZE3&4 zMv!i#!uwTKiK|R;pw`s@gbB@^tCWJgDrqHA@7^yRbZ4F4Np*$9K>5>di_P9T?N(WQ z+IE@a5l>GUOO)5oJuuSK40O8>e9!T5hw1hTFv%Zt%pPp7iN@^yP+JOb+du!QcyU{1BI^FlY$(vCeb%l!^A}uf0pij5 zb@<#4{py~vQkLxHG&9ei$$bisOGy%nhbB=bVoXxeK4}M;^Ghnk!gMq&D@;!mGqe(dLGJp!Z$ z?L0SHSs^qt{;1Uynnw0j3aK>ZeJjbu)|DKbKVuKpG}xLlGR$xOcPn+}0qz(p|A{}! zu65dXXsTgruFz5V`Jlqm7zH=A)*~q(L$kWjWo)yipH7FPO>H|XDwQZ^DP){YM^Lx_ z_LqCqJJVT-oZF}2+K5@Lz@xy@eHxCuOLLvS5*A<06>tF&UTyTxTxtb=n!xfuMuKoLQ)dAa- zF7`!LbE0A9v6nQtn(Fx&n%jFV+^eX0KtHL0UjWv&&{OTOrQ_L73K_cLPt`iXEh7GX zj7?y1$hSXf`rj?AxhjLf%~><@=f)O!TDttu|MPD=yMJHg`@iH;(?#y$&ocP;bylsD zUu%74U@g_Xs-e{>FIT5n+58S@=M}87@$z8xi1xjj4Qw{TqS=jr$o%A`6;A(5^Y53q z;N8c`d&kGM-M8R;zl6h6_cfh-eU!t#b+@-~yFKK}@b6Au2FfKPD%Kck8EQGb$h%N- z{k3z+x2mLRNe!t9~YVG&^YkBZ~=l^{g z|522c{{6JA8UOzK5s$}S*(w^197%@IWC}hD8r8T(3+w#8qRKB?U=Izc_V9G*Zh%j1 z0QjYPG2~5=^FN<9am&JqE_YSsqH8|=LMOG)^&x_;^lfj1?q^9$RR|VcU`tl(#$Q1c z(yF!yhVPRfsK80dYMny)f4`d7eB}yoB&z9;8K4vWW;V05> zXct+RHLy`D9c!5wsn}VoJ$HvN(5RZ{&_tfYS4GWV`9zFWS20u}shY0c0Cn_A{}g<$ zPd%!L+N`X+cmMt}&U))bjnvf6Rkpv`-+bM_PtVe;iK<&|&cpXf0b;{OhcGE-9!l?S za9}=N>|OflfA1q|_`Ze+x^|jx_wNge8eUgfO9C}4jEtTzP-(s{U!*^ieJ`03?>fK=@LXDc(V2$D=%L@}*rn!&ca7thzkmA< z^8XAP-D9oMVd4c2Zlm>6A4VzY)Ks~Kg*$6*0tIRx+Du%A?|k0Ljl6*%FH9Ge#c!M# z$&rjs<)Ml`yn$(do}T4@PcNqg%s31}S!$Y4!EW8!fNo6JrP0AXK*)6KR0*NS}cN^J#=I1XYRk8;ZiSjK zO_Cv4bwjuoC{o0tq5rG}-llh~E~vJc!HW|QX&f0?2s_#E&8u}9#+L1Bf<<7FWiyRV zO$nq9Q=+YVGD3PC8KN4?0}}ntJ$sI?TVJ$=;q<83b^FTT6oOEqVWh0AEc^l(*_XqA z0}(V5KR%>CXyGK^y}JcCPj|Hvw4*q;(z*KwJNl!gE{_11wt&u7D6ux7!CVEI|5SVRpwFMlep4)!^qvwfJM%GjSrzS^Q*W44p|tXsqI2 zNh3xkpXou-kq+%)um)5dW_$>YBf7o!i4~&3B39R*B8RW8s;u0MddlLbr?s*8dbs!# zH=1Vftt~|g=tI9h_Ezf;AJ&H1F3KUU297`69U3Sr%*Lw*nOWsK8LO4{s5xs7TZR`Z zJUl#bK{qI#!)cTtZj*R&!<|y)Wtt#P&*f41a(9-;m65FJJNJef1e8(4mB2i3xnw|; zPpwrSK7K5g%Up2l!44{8r6@y>8t*4#TR8teF%PvBC zc*ee+`FeWd%Vbul%0mR^c>#yx$BY^!t$F0${jrPpZC(pOs#Pf;ni>0f^@|ia@~)ZP zni?G^M4IF;d2(VCP%1pHt01}FT%HrW*fp5ZbXJ?~;P3!}E78LSd3X!tLaU^lHmK#; zeKB|jsLkF)~Q2Y3tUhM1%+IBk_-5H`0|o$oN71I(6zGfyrpX zYy3CGfMw@SW8fIz0llk>5Qv4&B#lzSL~=$(GvXAtoWeFiX*>_{#s%c^Y)K{Yp9Z+N z$|a13RmYTy9Zc^=<;&~wCjJ~XkrPHJ_NlWAtUM*UY};nFTRHyBnZxkT035_@RDnnv zHXTB@m)JXR-bk!Ic;rH2S4l&L40(vr2NrSO2?<}1qQtCmWdFqR z=w#Q+egFP8fj6YWt>iA|yU4AiFJ9r~beP{VUu^QmMvRw5&hxMVx~)89L*K?$y&;{R z=y$o?luR8Jn7qY}M*1zZ1`wy!GuqrdfX44Dr&rvTC|rudJ6*Y^tzREK<6gdi9P3`J z-Cg9EtgMLBJd9x-&gIJtxP^Gyr$}^1c_w z05^tXUgAjxub9oD8%A-`9sR1CM2=BxD_{OutMxXWtmNeOc&g0D)49Hi%K8EFzip#; zMa9G%a+p1P`(gfR$3IW<&xMN?xgl464nN@d+sVnHZ}&yl-M)A4ZL){z_>I~(u8ekx zs@wjtl8@UZq-mj0CWU9Wsn?=MG7LV`{?%O=Xnjo=0x-TX{tDVn3|JlH3f~kK!X_WD z_5N3W`F+RWi&_YEzAijRR#ZAfe}&{JyN+fqiMEoXRevbRoA`09SW({P(JMroS;ugZ zAZQt(98_}g=Q%ewB-{ZF3QtvXIQes+zzIlIZ~m-0QnV}4Mvw^;{FK(@mQ%vy4-8D} zLDp!#e%1OW#`>pe!7oYJx^up={!oTF#qkPF7K6`2g@z`rSOy%Ta=P^Dg=kqF+FqOfNKNnl&cIE2~YVq%x?hQlaYFckk9s$jx+%X4~5%Tc4+yHNW?( z;Q-m}B$^=Ids_U}rcLxgP#-xsI1^0qI0Q)=9d}ej| zA^CN#pl};X6E0Uss(0>e5)&LEzKmUVJ~i-JNH<|ePj z&Q5nJOA{b-EBj|T-=F{OH*H=~RN{L#5OUcVjCPK6&u*=$c^`y#47e;sCD~ay3c7jh zMfgIHGwf0WyXiH*I)x*dmAEMDlqRqKC<~H~t`C5eq(`jzXE^YYdUSw}#xY9=7z6I- zP2E#%4PUJxbw$2@)?&dzLFEDUmc4(dEzjH@6t&&JB^jak3mDnhePL#18~hYeyu?+5 z90=0r9=7^H9@Gj}pr_Vjas{Vl%S1AU^~bmc;a7YtzkJAQM3#?MDbVISR1!k*-88#Z zCmD>AytAQ_k`gw22VnH0sFTK){EnPDZv;+%6R_~G0QqVX(f(vN@FbWe6GKOFuHz}K zhm$pK{CFiHZZL`xhR8Vj>VL7hpc{#aF9Fix0YVWqhsyo?cAy9GOENceo+(6#STWP9 z%0*ysk(lRW`wkdzjOD=w7q@Z#f^+wB_%!tZTSj`IW}tm&szW~h>+hlI|N&}>KNG}Gk2TtD>`;WOj^NW5z4aL3`tE=YkJ+1wNl^v(~FZ~ zIkIEP_2>>C<$NCC`0^m0va~MK=%kP%o{UZ7X{KLr`9}&S&V8vB5%Pjq zqDp{cYKu3DY+w8YjoFZqq~sx3i&Lb3yWtazjD&Z_P}ONl1|HUJ<|=6&1GRS-;hn*+ zR_($#D<><#&<|6aiE#_Y%b@XNtyZl}QG%d&mINNzY6boOp`H~db{;>pXU`atPY4&M zEG!dwlT76MqW#4qi0SVVsw*|ow1mx+Eml(-t$_=SjoTUg!GaIG=9osC;Wh&lVu?nECfeq5YI%5W6&P-^A;ZzV67Y4E>N{kw9< zSEra%m0r+0%r7~D9CZ0UrjAmlpb38A(Ry~uiw5jpcwF)9sCXSQRT0(S)sS;iDk!-A zVv8+o&A{+=Uk|iDYWp7-peQpBBh5F#t}jK+gXmMn%kKUh8;OYdO)TG010$zD-e zUwg~KkLR2Fkw>)}w(`Wz1vBtmfA{dryfK_okyB!{xGG8IBPMpVyS%JxJ!P4AV{4la zeS&B=?mhyWicKU%rL+2lZAcYzR*3&4BOWD%U#X;rA=#c#R?e^|x<{Q+zP8L}Kg*I2 z8LOd4ja8BqQsm$`nefOF&N?krRBkBoLt{S?XwsJ?nAILZ^qY3F1rDudX_tBGG{d{+ zJe-nGy96zUbzt(=Pj??Uutm(R%&(KwnNu{LiHlRoB^yQCIvC(1;gRxoIlwY90$J+8 z6}20*ey^%e2yng(g=t4SD?QTqm*2&k0j!%-m>V2D{YpvDV{AjZ5~ zuq%^Myhj5-%(oypozZ!xzsR!-o&4(r%Uy4@>Ktfa9h zy-i+3k@l7X21zPE`Wcm4SE#_*FH&^VT&G4Qk(&*sBK{O?u(`Mqu|R31&1U_jo}s;i z2gl*eCH$DhI<5SzTep5^p+wrmy)*dh+?Vq5$-gTpWXL@z>p~wpGNjAoh>f%d2JH;b#yyjL=ApYZ#SF|dYw#w4H)y9d8d-c*8ZqYynO+GD5Uhoef5+UW#a zt5G_4U&Z7fvZ0Jm{W|4%?A$f3fMwUItp)U;$Vsg<c8am_Sn2|u_!EWeq; z+r{QiryRpA1X~@>XqB8x?oELOro}HBv90w$?^y2;>*$-w$=={Jt5&Vzus{6ZJdf=z zXT4zfxiCHmj-#K2?Aen-giqz~omQ;qhz?H|4QE`SAsnSqk}$D)m_i640&Dl4tSt~C zA#@Xb02gi{RD(GUmn~y=`U*Ah#&5RSoJ2M^w3*l=y^y|A*vNuVrH zra!1UOJa%aJ%nE}T|sat)f7lPch=S2OsffY<4Dp)syV@NSn~`wZi$TSMh=oxaHS&_ zJxyv5(%G4d0ku^kaN`Wbf0Mk+oIuY3W_Gj8_Qm4J%PdS5hjX^2Zl>mBtVe$=L{M6C z58?wu@mL0Hy>AWk2YP%LdfnldA-<6#$`LEG-c&C5`9$=2lAAjl$}8N`Qx;z}L&+?X zt6w<3ynpiQ_OgL*DQ;%IuF9gsC65ZZ-S)HX2W9aN;fax`lH@{uG(W%C11BGe0X`2bWwQc2OQDEO3p@7`8o*k`z0IWBF5k;Fbm=ga!SYMhEGPS9q&hQ8#u5hK>d zjz4ML-KGVZ8T4jlyTL(}xhKD@%J1Ghr)Xx}+SK)RtS$$98a#dtrzh4%#-=0S3Zx__ zizf{JjQ8o$JI^Zc%;1bmp{(?d&92Xv0g#m6>2jzK@)Il^u(tL@Y_9P%L>&?_p%W5` z+xP4#11{)4PtsQVOnTgHU`HAB*|e!H+g>%b-*|*;n36P^HR}*r<|DFZVS;SU$K)pk z)Pt;!)buvc|Ul@rY!DWy?o6T=Jq+Ej+bSe zItb#-5|9KJfiPC5kX0GsoLqsqPG_=6S}}y5pf-1HFGK9R^!?420ZX%+MSPF1m{53+ z=J)##AIgP7m7#|9$UBM$b9)anDeh)mJX;o6%`*Y!#@l&O&bht|7A%k;OCp594X8k2 zn0iW#ZDPZ&w*I|`4&4V#&y@WQ&N#R7`-AH?Z1|*GFSm;bK#SlA5p+s^gLvRM5;?1v zf00E4vo~qehNIb5L<<&U-pFw|DI|wtr$1oW#x>gbC_nf`*J7c}jRFAuUdI`<0lxjlKEw+wWXNr9m?>IF{21tm#mdcJ$X~8tkrW(D3 zFJp|z2!O>ZE|+z|gycT1R%9~mel9?ocKrSU6V;7KM1vq^cK2;@*#5#p*n83aUBag` zgotvBHezZvNwJ}!-sE|5g=F$3Vt%LZwk+(il0R$`4MpYu9$Y{A>wTEBvpp*mtYXcO2s{ z;+Alsn6U>RK5e`n4cZKv&nD9w{1rKC8FR#mG%Tz$_AQWa+oe`eku7I* zO*iFuc=#B$CN8jJNzXD^0q`a8V)5MAJ#RO3xv1aXnrO*jkfTt?n?)K+nLs zUmc+-U8T$&;_)Q{diR!kWHAdMj)?l*No(6Vn=U?I{Uv=2@{G`SzndlQ*}Yr*YOGI9 zkBo=kM$OtET=fABk-iY-Ul!ySes}fof?{61wqVts@B@2#?{d3H8R%&U_FYvgu&2Ab zr$S*dDL?uEbU6;0_fO9po!|+1%6a$L`gQBN=Z@2&Vh;W}o)QGMbj}j9TAGt1A zz(f;IYyr6&dt^DMs35CcQ&>|A=Vi+*po{V%!$~~NG#l`wqoe=vjqENf!c>Pg;##Zl z_Q`Pv>q>DVI6A*5nnJ*Rb`%6~W$>pm0c_G;z2qGo39=;?I;qu0czg^W%I+^YKYI!| z2Q$Aw_2K~r@sBj?Qr^KAWbS>LXp&K4>UDC}mTlSqq7gl;-#uT6hZTt#!Kx{3lbaN8 zx|b`YKw(rGOE|2lD9o_cO9qJ^M;fs;$3Q!OpAu&mKkK6Q#77fAcb$@-s7 z7rja{033NkTnLMZ7#qHFEigBICv9f!CRX%xg`6mJgrK04&Xro{U)?jTYBh7+vCPE6 z!KXWnIxuh<9yob(hPW%Hi_0Raoax1}tv+f*m# zbxDSB<%>jyl!2)<^pJ5DOeF?J|gntf-Ceq*#NQ(1wLibmcAO9+x|U@ zYAJ=}kMpLe>pJVHfq?;_PRY@B5uiYra z@(a&SJNb@Lrand}vI$uRGZ} zB{5)Xb9^Kx6`q&ln3X^VQ@^yd6ebQ=K3b})%@=CbsUr&r%@4VfeAA>%@(I}cZJ!%D38JHg&vIAJ? z&4&+v(;{V(^)M#g;Fdyy3Jg0xT#XLQZ+IH9cz5Wn{3sX=ro*|w4q}ATr99t(!vz+C zv=d&^$ z|3(dO%-ILzJ(oP<+d!8a*RCmpVZrN)%8@0`oWOq2@$O6Eiqu1SIose{M>3inHOuH2 z0?d)t7n5EPf0ljN7R48^IxW_m`dC!oP07_XMb7-%_lAWwA;g$?t8FZ zxzV?}&Oh8ivR0>*8$FvGPXtLP+z%^R=->e4Vifc|bICwLlHP~ZR}V1rC@8Exd396N z%zxN5RIQ(eoJ~1->Dq5X-J(awHa)oXtL&!&8Q;nMx}>&h+43|Xqv)DZr$;w^`Zy~q zoXsoJVphl3zdGl%9$B$N6iqJ&+O48%B-qY^`>i{7KYWlDE-kk7$SE>R4&L^IDpp3M z9{eUtv?Fo>BfmV8HjGhW^F9Lxy!{Y!#oF2x9Y#ppqL)u!ak+Uxq*ZhaL6lLhm`&^2 z?BcYOI$$z@UFk5Rb;Gsvds5G&s<%q4?M|?ne%S5(3(|DXR@T*}f_VU3Gz0RXQKs&4 zl{uwY2+d))Zk{CT9s`tVYG!6^ZZ2RW(}@Jl9S`pRy1X@vT#d1sZ8Ru@@2yXK>9K`T zfO5QPIrpc(?q4=xvJV8EL&n0ys52=zR+0Oxp|YA&Zy^{^qUg@QNm9k3ycQ120E3I* zp`7CD$(N<`i&R@qPTMhKQp^g@9ny0#Gj)8jXuvO&w1P@phcOK*tO1h2z%{&gIL{ci zoVoU!SWbMDfiJRMQ-;0hu)KYHEY8PPM2d8$%o9n1JJ^=EUt4N#e@|!uKo{@}!WmU& zt^^pNYp-6%StWW|c8-qdhm8*FRzNg9LcvEJ?}UYF{RRyHW0L_yP?bU*#o7AQ5OQ(f z3#|zz=JN+`T26L>(8p#usxYUOrY7N=#Gg**ucQZ7S`lrqIi|V~=X+cY1S)}%*|bR$ zV-6WOaMCqJwsiv>k#mpck-GKi+gF=2p9b0NIdiTuTJj7DtqGwK)OIqHo-l1Z$a(kR zev??~KP!s2fH;z+rKG3tAh(zFFR7}64)`+3iwh7Z(je(@(GZWPF zosrG7saAK-0P7cnQ64^#Fhi4bGxgHnr7;U;&-OlZ#wkpxFLG&Hw{81$uI>CE4bIaI zf_q|B`w1Tz*k%rN%`<08SHHS6ZR%8EvjzvhFsP-$ssJEGG@ZsreE;);T1*}87Hz(&H4Y@F= z#s$Mk9I&fJC8jozq>zQ+fz;|+uPh^GR`scbzM=LP#sDibp*vvFLj`?TS`k>oWG@u0>a)^Q4q_M-!on;fG2xUKmiehTM zdGyi4O8N5|`1tdwQ!#Cu*sO#|7)KNkLJWMUxVy%{XEm zz2)ndFAl$}y#}-B)%jo9-Rj89B4q=E%a}6EhzJj#62TAg1zQHT9>2*tx@YF&$B(0! zNk3H!LCg7!7npxt=c`fOmZ3LshlgTiWRqPMJn0f%bbj> zWBK=TZqAVu?k{q)7KF*b+fCNi#DYiKhw_hj%U449GMfbNrqn2E@_28rks4@#Zsvil z-~j;m3EDwl8i=yG`>ASE5!Mhcp^UdNA!zP7q~^J4ja5WNSO-|h%$A;}pvR%1xrGhH(NyD2U(d5w zhSt;8IspI9?a3jZ7`&GetEYn>@mQ-_GZPK~=m(;9-8DKB$D>T$G^?po{YD=hakAGI zB^WX&)KRL0Jz9B@%n9CL$<$vxnPv!2mM_E4X<=3Au=AJ;qw3(=b_@-6B958T?Xr19 zqNpC~0BoB;TYXpX{3KHk{^mp#ONp|`cLn_sX>tXxo1563m<5EKdc>vXX=MI+8h#n7 zZp+EhH8OKYdwLuW+{+kxm^D;57#HOUqR4XcTE0hQ{#Xzqo$5{1 z6~t)$I&Q8hZqbOdPzcOJ@mp^mxLF=x64blAq9QX!O-O$`!oC2Sd~j%Z8ohnp%cp=V z;AC~B!8;l(fV>S&%T3aBgc33H*(ZYDLOxJn=EaLm4;iioq3U307$P-X+o9JGm~>-W zP)Yc7(s6?cz`EFZ=#V)lm%w>sS}jI}9X0fpqJAA2F^VdHUW%%f@=d4ZjiAa-7G|9>}fecfW`V5>~PlFwg7XS|>-Z|VqFVDxO&cc8-ML?>3U0+@Y1 z+60$CzZ6WyY~)~=cxBD%Q2U-=Y0dXT0w=$lL7+hc3}9-9O5^R4+Ya&^rH7~Ij3k?e zu@L>`0vXv>KxLRhn;*4k*6aqbm`g~g^tLFcl|YKq$cW+M-FWn#IoxpesR%swg~=@==>1>rndwni zL2^rjG<2(#U(wr&LKAcRTTeeIsFMsNKv_ucX&5%K>Ja#WFnf@q{Sm*h1HAPb_Ie`| z;kDqrEIleZ;-U60y=Z;V7h1?8VcqHuerd(wYV~^q;B6=R`d#F=w#&+p~=&r}jGRxQpyInVs>zehqp67$B7 zES`w1FETTOfO7jVcTJ>YK#-}z^QqHRg1Q}&d79A2B_BVY*wq0gVh(kfCGKfeeqP6! z&XL3xZn0n!uU=Irr8TB|N=Syck@_VN$Pej_ksu`PzHa})d=>b^0`h7hfRdIAy8_(D zlnaMvC*%!4=KQ_#l<15?UfKe7AVMRQIg`$Mp?)H>wK9NC-U@M}#*KyJ7=1FS(4@yn zx=pZaiHIQsN#aw7ZA>sNRhd5{8%9EK)_Za~U;B>UY(BaGGQ9#*LWs_FKURId-U#Sp z9+e^co$CF1YHHNAp)_M}6Uf z!0mx7Vwqf}i2;LP92~MA_SqON5gH8Xd}W-l*`=gXTfgkpAvwE+i7Olgdhy#3JA(AOI+j-3EiBu?2jwt%T~zdQtnvn_DWyAVy#q0kH!8K15FxxONPx$e zu9SWXoXyvwx`i2A`NO#9R6$LmB z^1ZM;WeD-*n#!egH&6hJ-s$dqk)&0|rDwY5H-EXRd^|{_45R&kxxzHXAV?<68J}79 z+L$OG(?2*O2di>qY?=v?jba7-Jgmf&B`2aD^u&j8bo2*zwKOyrt%7UUue*yF+?Ow% z0Fy;r4<$rz(BPeW_m1US-I)XwNk5nx*puZZ9oMEz*i~WgwW5Wwev8a*^%Nmh?UR9> zhfVE2EULUSl0;>Du5S;j|XWQeZJKpULZVY|F{5fTJf=$ zDcA`Owi2L)&PbSB8*B8EGxfxYwsKt9y`mQmpsZq8`LRDp_ovp!K4eDk=@(WL(zr(#KLdY-IU%e{P_!zbGRjT{DICRkfUJp>}`gibf&?}h(q9lVjbLrX-pryly4+~Di&XE*@?k8m1v&+kw z)4Yeyi4jRO`Lqb26&6ga`n`VLI)TjyOGla1C3$Poy!lNoorp6sEJd`_=qLk!itaYC z9IR}Ud~!iS_}0}VA)-QMXD1jlN&oH#=MaJE+ppgn1n_85&I|=9)2jk~6dA)(lpQ2H z%^xUa0AXWwJin$ity$BiBMHT{O+JqdF4)pL$!&m&hmn{wKO0070iyPf0|%nxU$pMz z6Pvb&)J0(z#Q4|n2P~SP;(VnyWz7drK)UR1xVmLx0F=pn5ZrdK&f<~Fn8@&O;pR@# z0}}OPA-K?_2bYVZ70F&NdCL3hM_ibAs%~m*5G4&Ur2tT^dB2vBXsYkk38x^lFRRI{MY;i)Pcot&1SJFcD#e~@7;q-2~9 zvxKIFo@>cHe#1NV%L}eT0}3H!hZO2Ri=v4h-YD;aA%M^cBT7a(P`~seG}5`{DyFP6 zV+9M2CB08FJ0ZzZjRab$QHki@tM1+V;rC;}wqh_q?lf+}0v*aG&NnGCfbx8+U^5V^ z>+saIkud3{JDZPFw5ndd3cxv)uF(lhl%dvmI+IK5$Aufh-A!xGDMDT zIOU)-jXLke`}7uhaT?kqRZ0G{7@voFP4{%RXb%NwL1Bz2u=u5yUbk`z4KCDxHh+)Y;(h0LbF;`#3q z0UkuV4TXTajIhA;(;=IJIm>26AcqpoWZ_RCs?Z8*%i(4D=+mKNoY zwdGzgO(V-3f6vJ={CfQK>Ftn%%qnB-v&EkX;;Rhuk>qO9&84+jlKm<8Cu#3%STD^T zzGp7^+P~ew7RJBgWK_uMRn%mST$@IUK+nRkJ%PGkTmj-mbHOE>W^}lE<x9Ur22)?DnvC=Brc+eIeP!%?<57EFp8}NZ3Vdj zWM)ROUTNyly_>bLmMf~Y&t)Mp-;VN# zFR`~j>cnB6z=D8a+flx;t*%0K`GYy_8?>~wFo~tP%z@9ED%yHcKe?7vy42Q^nIX5! zF-?mkapKge5%&s8vJ<+~6drLjy^m*wJ-MBC?18GXazXW>e9#(P^!#j3PDx@pMcW;Y zOw;k>g_ViOhfICsFW@c{P^sO=@oN~=KKc4`XXj(!nqP`C|6bf(S68HsnydR5Hsman zpu)b_UCMdSxKxty$z4GHR0X4@f9U-NrKoQMRxhFb?Oc>$x)^DWT#)HoPoK7gGeI)w z><=z-^z`Y^b9$MBFGhQ%Brarn&nkF{^6kehN*xDs3;B11YRqGS;?1dTME8V-RcEr= z)ZZ*v)Fb`K4TAwr$alem-vHGLGf)BsuO#P88etFoTR9n|bnG9vPk;k>71{BNMIQF{ z@2W}{|K~tjWYtpWr8Zat#==p4jWeeefab8{@j>R*Qu|U2zb518M7Bqr!F!VI z)T{cpVB6paDt6s1_@&v7jse(lFF#dwJ{N*U7m90PPSXm8kIq z26dthQ&abSJ6S_4G5Tf8Vo#5<>dskkWLM+7H*cP-Lp}?KD=T&d;bR@47A9QoqAP&C1o8>O}{#53PP= z6}RCm0e7Be(i<|Q6Qh9z^VRQeRM$3f>A(n!25+a9((j)9zvqHky{ry!wn-OPE)8Bv z>-~}GtX{9GSuQj)WGpp!DT;MT;hmeM9UQ6>8n^q`NzMkru!X@p!IQ3l?nm3CekN9T z84ghC+WXgn#fxq7$2)^e@7x(o))cqg#ERw}-0>5!UZ4q*C#k2sFtxk;Xv8yhEi7b} z-Fp08{UW+7R6Uv0D3D|iHg?}$ zGaN~prI+IA=7tyY;kXXQ%pZyv1_+VWgpOUWyiN+D>kqY)Lrz9tSzbm0$!ByR{J9G2oq5>|5Sq>BjkrShO4 zcHcsd4xkc%A>?*ExUieXpQ5*DfF?7~Z(c0{?x1h59eR#zYc2|Cnr1;d2`=Y@bI53* zjt?^I1^D*n{riZxD+o%`Rhr}wQl~-dV>zGqJV!m21INhbYD((feftXUz3%Pm=`kp< zc{f#N!7P1;=6v?LddoJ;wwfNl@W^DkjzSH6#C)BSifc};lV4VoR5FqI1)yH{h- zE03A;=H;npR)2c(>0}BUG{%^g;;Dywpu2JSp6K)7dCF8au=?8Ai`&wHZNgtB=XLe( z3N*A?I<+;6FzWiAf3!n30C!Q{-j^7SfE@=EB$(4oHuE^;)qqA@S$A)Vhdtp9t;a2N z6PYkLx9qht)vykyIp9~*=FNTSHNlLPK`gy0REY2}RktV{Us;7ksUnoMY-M=(HaeR!#$fM`V5) z*4rQM8a@3R(EUES+k>m$$m=9CU8^tdu?xC!)aB1il8b{iY`?z!`$zX{V548zdf<{{ zJ+`<;Gv>)y;4S)#$0s+hK3@=0iS@PXRLiW2;lIB%Tk!s}-+;#U-WnRUOd6aGeLC^X zjh!tAp1pD4&G>PbOp^xZFS&=y#Ji}z6X!h)HO=sTT5q(rv3;m_zxJa%KG`i;o2`KdQu- zaD7UiSU+sd1H-7Lpbo>|JUF<4R=`H4a1v(}L?7+Cae}$|!nSGm?%fcXRv;e3uLHZ9 z-NxswWeP(la~3b&1k+bp!L*A)L13`cpEYBg`exnQwcv|>cDpoaRve9->=31ZyJ=~4 z6ba31WoHlCNmpxeBQs<)^giBc^w_?r(A1l#FSZ(Nha0R8Y24@kw8PBB{!0+eJxZdE z6b0hC!pMOPkSGEwT&n55OFzK+xx11Pu%SSgqPoVANU&MmA+L2nu4E>gqGRi}53p|j zQg}n1@gDP{94R2&Yki3W)&;5g%b_?%Wd0};|2#@hp(a{+)W++%>)lesDxZZXZD6Ez zNcjZTOB8 zG3UUcl?D>2wvzsmm1luPb1u3zA|ZuxluWqzjC9*I)DFq;H&Va?uswOV0{z{2Bo3TG zKEzeH3{;%;>32yc%zl?)S|GaejPK}T)<{uPh=`~)n7imc(NvbnCK0#d{q?0RPy{^5 zVX83iQ1!1aAT>hG5T!iXGJWQ(TORxS?VychN3{Y{u5-YM+9}_L!IX0H(NiV(wEu8% zV~9!`65JEmr!tnQR{?6uGqTTQl7u$0Vt6QWtbUNyD^e5lHKmPoe+{LziRwlC2 zK&9J(P_%v?*`6jGDA}ITr$#ZCJuIS&Li^arb1S<Bmtn2-Vq%7}~`eP^0w+W4n3hAeZ}{LP1#e~rFiPx>$7ryy2a zq0)#Cb=PKdN$1=^pT))jvPQQwFEY=@c(1Wca;|u_gA1jx$pky+>m)t$LlBz{zq&IO zULP_OLlW(n9Dq`>ftbn`5aS9o<3^lcy`S8KH0titM5EHyz_1in4Rc|2LqqXJPlFjR zKW`S3SCoO73*(mKwsiENUiR>Cu{gIg~xX1PwJd<}A)89dG zHt=F|`9Yd<(%J?~rl6>YovpcGH&1qjV4onEa$x zKpiR?+3OsFw;-TTTfG`UE4iTDcIiNTR;Su^Oey)C{ZGtm;fw>hPAhKlusQtC zbaJ;s_5?`%v~35RXBruK$9k^u)UW&)SFD@q)!L;&?L!$?yu9)s`J9?rPXRNhlzEwG z%_-le6Fy~WwMqfm$gD7%9m{adt-QHsT9T!Tfk?}g=2pYh={jym9SY%Z&c(dI8mPox6`LjTj*He5#Ur=v6KKVEpF1P)Eg$~-H{7V>uij`J}wpbwPjhGK1H+= z$V)tR@ZQ6Y`(akrlwLuL92`i?2Xj|-z>xrf6U;q+-Z zZu%i*y^3~W5vQbJUQBmhz^9((YU!(G2v0`l70C>T@ytteud0ZeCi9tn`uAT?hl0Xd zyTz8qZQ9hMUx&{4U$~UqqLPZbwA-Y^Rg?tMA3h8{5uwofI-TQAhfsl#S}y(*)XZX( zN%<*U0(#!FIbk>(Bu@mhPp!QJYC`-*4>>!0b}9_k&z)643Cy3a)#O)EFSPtMjvSCp z1UReWmQg>RCkJLE$dX7{u!R7RJ8+gzOACfNO%zO@&3a3%c!S#6 zpF~!?GH$1(r2vM0M!MGgXv{7R1ZRaj?l!cUXuC&VqnW9IvE8T+NQyotWCd>$(RiQ9Uhdk^22%hB9UwuAFD zat69X-mp)F8kVnDExMA_bqa6tI>ewaWX{9#`$XF*GWi>58!5VZe8Ei)JtkWlv9{!k z#6!q!l#j-sJNT|u|0)*@__Y1Ael+)06k-}DuWj}86)RS3Jk-5MkNQ-vGz_JLL>`wU zS(-eFMT3!mF&Wmiu8~^$;>(@uDim0&CL@3tSlzBklOw+>SyFx7KId8&^mkc1>)f(A z(beDZhP-m+$^wth@gT3aODSx|S;>6QI?Wx>Daq!#_GECWQj!X~U6sZro4>4Yc1lqJ};+cF&A+ z%aouw)>gsKbs3Gk$pU%{R5tk{G>j+>;(nHXU2FdloZX&ULL=sPc7>)y z_i^?+(%)dpL&L|!2>v#{U1udVZB1iS#Uq<9muZk2tIhfIR~V(-aSy1kDNchuh^pIt~`3yoD?YF9*g6piq^o{>ot;F zg$c4a3;Uevth8vO;>FJG+tCtrjMc2o)ftbCF)>vbkKI_;*ZAznMZQr=&S``Mf6kQu ze%s~GZ}+lNRs^a(97Q)Jqun2QuUa*C)-p?137yF2+S@0PP?^9Ucs@tNc*v=+FyCSg zHSJ?#4$IoSZqlLgbM1KJb{Z}+&frVamc8@U2A)Y99d#{?!b3LMoxAR769uQOi{1Dh$Q6qNuj2kCg zyy6qvYpC&mLmmemBD|*nilUUFMh3`T}esQO+GOxZHT7hx|H zFZ0`gT@{?1zaY-TX`1+({<(6$eJ8GG<(0bi89Z2IpJ;UiRwK^%c6wNobbTbo>5__> zFvO|(!`gC)4y}1`>U(x7xIFufMgt;vBGT&z1G~Ah>#3 zaSAw!CNmAb$yx>FKaj}X2x37p^7`Y)ad(bsMG+floLnWdP0lNQ+HfNgT3r@v@U^ga z-rSBmNfbiz$`I^%RK>{D`YS~OgsA6x#(3y ze(U+jg+xsnf^fZ_HH3Hg@2Ah5Jv(`&ni)5P|BmzEv11}X^mc;&KmfZ2d(SswtmhwZ zmptC+IhPMDTDNKQtYKsj%tFaTzkPa@LZgP*Je$#;xggWI<&lGzo6B4gZw4jiO~n>| z8#1%9#M6m3*U6t72+(Scx726Fq$c(kHtW?{iBL0V zPG9RhoXE{})zw{++1;cx{OI3)L{na~097oz{8xwt7nUn&n}^B{n|v-%RiU+dd+4mP z3wMMY(Pe@OzCfu{8GK$-Sv;7t;Iu|7_enS|FfUAd|9h{ms*TlDC373}wZF_D-GThM zo^?94$LPtEoAS8Qk<`YDQC2nf!b9iaO7$V5S7(fU833zK3jsGfKN2J05|^J}HC9?# zTfbr4LQK`He4M7cR@7s#PNu|JSGJm7u~XnL)hq60>|yZpFG7;6_{gQok-fbg+E82lsmXdcE#R@6KD3&Qw5Fb-oYxFSx97~r| zl-8;b_#9%cNJ?M2*y46mv9$T{ zq$j6X9dNa2uhI+d%+w~OShjrmI_f^Ey2y1tU(9Ou(0<-LKmV+uiegA&i+#@Z15!o; z+j5f=@#pKehS3jBY1D#4eBXQYW_5G+iNzgOX~k;}GEDkJuU@_XxB&Y4`q&EACM|ZT z+av1-t$|pg$^wh0lzQf9>!x~?BqJdFwhPBydz-?k7d;?oyV|mhwM^) ze_Pde*)9r;cWJ=L!(5|Q&9=wTojr#jQl742d4IG?*DS#%oDGZ#FPpm4^Z*Gto=Y0>>P| z=wyQ~Jloh|%Q&5p@TB0$YiMdVKy?IWygHOn`;DW=Ce}pi$LBKs@|Faf+!8De6423p z*5nH$Fq(YjJnh(*VlMz*Yr?qf#nd8jO?giBHT42l)NM_HMrKJ@dUn~{JLpGTWkkmE zN&VrG$BwB=GhQ$XtP}SAto43-YN{Dh6jD@Xv@_ZQ)ktIvb1t~lBliBC1;cbbffqP< zHi^%UvBy3(JrWbs==}6kIXy!GVc5K4Wkvx+3Y=|Kb^TaUk`{QTVA6!QK1goBLvSuk z(70w*v#webn=dR&SsR}Q{(-0F&8O{h1$w~l9BgE&--&{|2-NXDTJ4#ye+MyY=66Ih ze^YVAjk$ecO6C?6Y@~-IYmG&`ByG>#eBoyxzAcs-bUlo=r0=Yt0N?f*jEG{2fR9UAY%**~Gwt1qBf@ewZPL z%@sP2aK!OE?;>rSZmkQQYVw8wyYoo4~FiA!EmL!lQ3S4yE})u*e6uYR!$XCM8F*FYpK2RpQ7BB@)evCbj0iGb}C zjArzOJ~)-L`p7?E9z)`^USZNSIkWDu1bokc(9HACF%?3G+|vKR{{6;1TJ$$O&gzA~ zLgXmgJ=Jpy!0%joFmB&JAI@I!eU%~KAY?L1wy%3tlk9UgbgGb1xo8~3*Sb3}3!Qv|N%EDS0ov4yC9EhQy<%heb&|X-W)Cfv~xPLN;S=ZCklhevDK`%5ctQINDbx1El;=fR6bYa`v zyS8FTvxiaKRCoQ5t!V{!zpqLPOe;uKQ(bqwy4rlbQTvF$)KpzI4_{??WoCPgjPf79 zMsvX2E+{`h=D&ppY}sqiT~+0^2X#qsX3XV)tti=dHsRYT)pSh=+0xoKGuxc{6l4=8 zRDt(zBkS0=??k&Ea5-eNU>|zdc)r1U3kBN+&Gfef! z9DS`u6!7TZ%?I=N<#xdJOx-vjZgFi|s-qz0m(tt(wwd?Lw9;wj|G@i47jLXQeq2W| zJQ~2${QV>PL-I`+9xZHdYwO)BRf@FHr5BM}RF7isZ|Zv}O=KR$@0rl^!9+RNl%X@3 zl!vky6h27bsz>8&L?srUHPboPu_l}}fqZjzqy-=Iq3nr?k7u(grM>$N&&J2+Qf4om zu)y>muj;D7GNyoZUmyQ1H|L63FlwP|d3C#w=G8Vl6hMPps{JKx_S~7@PsC~ogO8Ux z`)so4dINrBt4g2S^ZOx!u7Sf@50m2;DfVR^%FZTM55o6#Xmju>K5Cr_3t{4zJu8!W zB#epfCA0@Vqh9cu9X@TdzsCKV!}V{HwuSrSNTgG5f3qO$Nb@&uDs{hPWj)6nJ0Qsk z<$1*T-CqkI*P#TlTA5K&3{hbnctzCZX#6X{tF}PFUo^Onut(IztGR9TsZ+P;X&Y~P zv+@GXFKYJ33*OwgeOpZ`W=>QHCgC^V$BStJ><4jo$hPlggH;`uImvkY`({!wUf8-@ zRbwfnZ}@J;xkxLx~CMlk=_>6y zJ^tDc{W3eOpTQ1@8E~jdp%EnhFmwm^rm~Kj;V?>VihvxC?51b;KR~{5U}}$BvOcn+ zCVMFsz(5jQ9M6MRDOJCIoknwT=EdJvE)xlT?=OGy(s*L4iBqPe3@Jfz z`1I*MJ;!ABABUwFGQeBskph3G8AM@mB0u8xF1hiQM|3#iNvwK~xnTg>NCApy!MwKA zn$qv33qaK!-&WHVi~^pbCM`j$=S`t))gdT`hbj5&lF*Q@MgayM{H)>HMOPuDWLDJS zye#}$rIh`%wV>kc4}%Mbr??*IXSX?fbP!-35^d*pckD2ZZ^)>q!-S)KOi82Asn?D; zcn(`@gnfY;gc{?!I|}`AdKI~orRz*O?1+CB;Hz(*0b45f&;k8`+)wL(% zd0#WCf-l*Hs8uLDPCoK~5XH$TEd=dgvJ zOefKX9p&zRKK1+mAtQX7I+JJunA0G(x<$AaZ_k;TZSp9zM1DDMFS`oH42;D(T=zv1 zzRz#A^qvd3ZtH3VwKCGd{&c)fYiMdmd8A#`)IRpyDYCV9p~}$0eWWnFH~{<-tIEW? z`OC@GBXdeswO*VLL1`F>UQ*_Mefo%oRZFy(_V15S(j3E3OJs4Lq?NSfi)-IF0`iWd ziNDjh_8PNaU-J!AyjNu+UM3}$9(~Jdi=5#x!td-v0X+K>k!ZH0x4txUJ|jWUK<2g` z=JduV`}h=t@oe?H#41<9kO$oQq7yX9#&RK9+llW^e?~%fzDff zyWmJ=M&~UjFVX)5NGFl5Wy((!*6bo)*fZ8eax}Z`FhVrhU3}Zd?mPc?xOM%h^5yNP zU6ffE>11mP;Y38hc#&GPxP;E;wDoLwr|BcW&-`xrnRJ*C)cT(bjWu5nqOX-;`_c;U zBf`DG1w9$q!XD9TDEhhH(8Rt)eSKh0<)GH6(L(z^SvYC}1h+WS!5oP71~o~`PnZ`z zsd!&En^tt@pe>qAH8ax`-*#eJa~!iOK0JHA`;dmikz3wA8r%8}9=!0N-|54bE*)H1 zceW@;iMnoHR(|;pvZmHo9L9)|Gp&Sk?&Zf*r@|?RY3KR2&I<|?`Y8SUeK%}at~)eq z7gMAHe3PzPx4OvWBqAv3JY*JRKpV~v($-dO^6VBYctdO#I$pgUE{6aSXqD`6x<@er zj*_w5#NZV-D<zTdjmWDUuG_M_zu|w=iS`tBAtV>K5`cYh_aD zrSH3)pkvaX@1E9q*PWJ$R-V&cKkD^g{OH)AE{jM>*3)*ob!blmPEkaI7p@8bb~GZC zSgE_H5XWlOYmp22eWH!O&aOM3*`;$p1-~S8IU(tZ$x*gR`zD)OCf=SilBvMXN*=9t zjP>DnL`zwBR~-&b4tV($1D(blc8qO#K&i}4e;g`A zkByGPMlOPilT5Es13;oYJjOb_ammq)rrIWXl-W-kj)*nA?peqKIcuxp=Q zwz@aQjbFO7rVVB#cK5@J4=z!NY#G^_kXzoiUPupvXyN#tG(%Nh9+7^6SH`1%|9$gUT{8z$tzN13yPlpo zEHt!U9VI&94z$j-r|{_u7pC<{3Y=bWNQrap-lIo`kDl+hIk|qjqpQk|`9?b@1URR3 z*sqd2fGH7O)?p{tjbUXV}k==bhJUO8gOwY!ob>g{EJ zjU^t>aB27PFNXs?i(|pDf4_c)L6vpSht%o7ZRVOpc5Y@&o{w2o%+z^VYg*M2Lig;k zFYCrg4BUmLamWrYD7jt6N6D%?|56)}EMNTkV$tCEnh$c(POY$Mk zWomZ820&(B9VWqLE8M2c;`@ni04T!2`6ied_ge}_-=TLkI5LrP@3D^yOa1$FJ)KtQYFA(mJm%N=Er0~hv=m$VqdHF!> z@#9VZv}3`#Hpq{FxVHb*%ew!_2Ag50*k;j1tXZ;kM4UG?;|^n85x4^q30g(}ME}!d z&!Z81GS;bWqrnb|HK(?s*gfbQ!P;mbrM{11pv1*6&u{VDHbZ_t7FMpCWI)ll()lhQ zR$dN~vnTsyph@u4mE+Q15W1ucT)D@Zr|Ni7i`B?P5(YRDVmWH|iS%O`FJBHGSl`ah z&Lk$Zhx$={U5>@4{diqwFa^XKm& z^AOu~3tT?~2?i-e@aS6k({ld&ZtZrPZG3$=%CW~QggrwTsw5~;^U(-~3PAG2BhKY{ zd3k%9H3OZE`Bgn$D+z}Z$e`x*1#CIwuvs25J2|u#MRH*$i%^d|Sg=N){8tRJ!Ffy< z@D3-vrZtR&*REX>78LDNG5ZBfkMaEZ7uUSPX?pps)s%}1VpYYgO-jmMV#8(I2`KEx ztZRdq+r^I)>3%lx{{1&-5@miB(~sXb2{#u?2ju9^rs{89Nw|>Eg@^TSL-Lwws>r`5 zRz8;)XaJsquNspz{bZZS98rwqiZ%n%MRsAo0r@js{|aFxdp*60bOzZagYv(D6+^x%gTs*V_pp@~odAsd z8+5))`wmU+G;;=;fNNKyqVn%IJllJzjm_FyjXHl?@cQ*@DYcyqF(l3p%7X=Tjmd(ov|Q%7zKY;E5(e2r|bh!=P8;9Fr54Kz+Q&r zrDKdz6|Y9vKI;}ay^Ib`vebbR{>rxa8aA+P_v|Uzdk4Z8IgPA6{M7&*QS)b6orjw# z{JO&}po;q60Ngm?GM8YS;)x*=LvSn zkGq6a4ixKRYPrj3KAF7M)Oc-z9dAoQ6?j$Gs9IaQr7|ek0lZY&MoZk@WHtyEbi$P1L zS+F`Cirnt==%&q@k+SZ^J@UKE(N3a!V-Ebpd8=YQ(F4}`5%<7x{P^3Z;o)=US(=*G zRXFrgrk&C45JLS#6 z$2Tw-on`3RCZ_uak~nAR&bEx7>RyVe`_qdlc~9fIw>&-2c*6BNj~_SXcE%IG1)3m% z=>5jMD7avdVs=WU_+w67+?u(`xnP?fBh<6EgT<+Yl1`O7zm-D48HP|vucvS9ED2Oe zb5Mw>c!EZ&<)gbV;~Ux9+Rhvuwli=9c_{=4bjRz`@!CZ9*?t&T?!8!4LM!yxTxxr+<>oel~DVrdwfsHdI4RLj$WxH)vM zX}C)Ai9UIMDL+?j(q#8Q*TE$N(QeDOd3ddMI4}BCcyBt6l_E&hZitzZ;@Q-%4-prj z46R?k{`rd+H`sONi=r`^W%RzSYbVHsl(EHZme|Zpx~9>c%}R9@5x*ylgaF2hXxyt8 zeV3xF^>3QD<`t{ae+hxHa%EWNS}s9-V7g$Z@{*>`2A!O97T(oGNjEb_|06KRedy>2 z)fr52pq*xW`}OkQmPOg^;C`k}+qRB&?n{%e)(X;w!`oOEuFR1Bb8f|gJ_O-0 zeuX;<(BqlrhS?g%t^E{ye9179T1F&KUxBR{0pZNiz1HzJfKQXZfX(FjVX*dzdo?f$D&wV<; zr{W9QjYE2Ey zCN;I=KKlSG+Zm#7V9km5XRTzl!!FGaJj%0+ySB}#ZD7Mj>K2^RJ8<{#aL^SP)5tQ~ zF-ToeYyA9g`jR}$Prd1kqcS2-Hp`xiOp%E&9_oAbk1tlp0?3F};gA8en8H?jVYm=N0I zj#V;+D3ibZY}zJ;b4jzKD>_^#l+0K(cGma3TGDwh(&^l`U}FwHu3yMG<>wkwEF#eN z-6ea;SEs&W-=X>>5hSlvioJ~~v!kKyr0xg477zA6->*sPtdU=Fg1&{K6}{;fROh+e zN6im1$I?*$NRO*dwTscBN&~09t@#~Svje zP3cJN_-@Z^Pc>s`B$P%Co5U0mxjuYICmHzaLU`!5tuQVmzWuQZ~8Tmm%%z55fNX*e=YksZe-}GPvfJ8Mbj#PuR$j@JvSHZrV z(^Opht9Q;&;6j$0rAy;c)HdN7ys)S!es$wEOdb8e3AYurwg-K`mS4Gct>jC)4S(%3{ygg+NR3S0 z10PD)fg%=^2X+(P-^!d@PYx?+3l2k4m@i&bX=&%+@Z^TRi-W@e4l5A-i#|6m))Ee$ zGyBXkSb!Sn3{{b9!-*Q2055vr$SE| z*;zhhz{mpIi4*VM;({O7cHZUqI439Wo5cufG(Dj= zaIki~*5Nm!mr(rhl_u*yLr%gtiX0L!7L`B?!ry3!t??}*S8)rm2YhYGzza2IS#fhz zvqcvUQ)&Y$8YB;pJ7DFBMv1v9qxr-EG_Le4Yp-lk|1^fbCbKLdun(NS2vM3CN45aZ zY<_NO^BISfS{KJ41j~Kej*Eqw;>EP41wN@KLf?Hd;-#$r#kNk(b)xtoLi$zJ2M&%> z-M4$Uec2DT52%BM$f|oNi&Av+lHMGTIcF=vxA`cEsZ!(T&OOp@fnWY$k0jJ1eAYQ$ z+rK-#x|uye`BPhFsFdQ0C-s4bs3D@6$~vvm?1p3R_BBaA6PI6gx_0$&aRcL4<3|oL zJ2vyK@wHjz<`@22))pEeJhJS^Uk@g{F%CFk4^sXQ2Jqu4{iri_6|$Cq>=YGRg@t*!#k@(wyW<}R5AHIuGlw2`))1dDjSMa)mL<;`CVZLs-J;{(ML{Ag*? zXhZC8emZmxb!2jyrLH~=01=n>Mvd6;<4f~!s}FSsj!4%yJCYQndPp42_RgC-mx$4s z_KxQb>p0oO?SGm~)jH+8@x%9XaoQ+E ziLxh2qRAGa+M*RGOqhLU{fu&*nc&i&nhW%C=^-M_wNG}RgmPhxpBqS}r4zkg!o${- zTM1wC^wQq`X<}@2BgNYh=aM%$eC|C%OO&f{Ld!a{$m)W5oPR;u?zNHArWz;LtQ$Ta z0j5x6xNiAXwC7#M%_tqEz**Hmu>so>{p$V)OF~cH!%Zb#9LA35B4?+D&huKos2cOX zPem4hZ?ipJdiy@ufAXYJ9<4KS+)dR#d*{AHf06Qf%iC6Vz0%hXj`d$1soryWXy~o( zcwzQ<7e)JujQWCy5~tz*Lx;{?Jjr`-7st!Nov!CJZlkw<^ZxxdFI;iVA7`l>GtD>TE zTTfqYil0Kaq3P0=vwJ(7jbvOGF-~WjkZ`Z)3PqTC9pO+o86H0HAVJ{$nj1qKiK3IY z8=OaJ-NAaIE#{&7s>)d#&v7a^$4zqP#C-wq!rhiiLzamZW7&0>nDT{-+Ve=vd@(aw ztxwTk%2p>3$^x$e;Jj=eIGv-OaM~?+)U!_SZ;mZOiF5Lv0M_S*Eq(cyum1GebwJ(P z;|IG>x9~hAr5>j()C#jPYv`u-*6ih^^y1LU`LAM*N2I|pQQ?Q~r4=Qw)BI7(;KbCW zE*y3MO{l@N=oS46Yr2M`i!E!!wM2!|PO?qEj^zUFAt~zo{J6`PTS^eJ1Z1(Rq^-zw zM#go2VqBqn=JlYnI?`3%WqCw%JZbqGGO`d=FS4~gANe%ttUdFO7!-e~+rcDQ49YHQ zd``z50viB=dQ+Gj8FJymB?8_$>$=S<8qIf<(*8vvhxP`Mpu@S%KyA42T#|oN+gPyii-8p8W?B-NlC++9FLqS@0 zir??G>x1_%HrYgXNBBxa=JYK|A9|qe<9yrmTd{dc+z$4SdedVh6!z1M1K5u4@oVLo z;$F%b4pWB*+xv642w)%i*yc-z#PEmstfM0Sf@=g<*`BJygCi)*LS?7p68nq zKhMM@Ik2ZDGRYqZ?T}R0rnYQceG;#{2(CE0tdSbdxw+0U=v4SM(`$L>IlvF~P*-co zF2KXTB9XzPVWHXwgtglI$Y8T@1IW0kMpMkp{2m_Kh2BBp)X2ZABYIvn?TFML5Yemg zTZ*O?%a6=Iv?>5h>IbHNVXsRa1^I^OL;cUTEVyMeYwo1zy21|~zmr?~j3~^=43B}q z06Ys8oV+ssz-kG3Obv_O`1PsJz?uH_W{wPA5zZ;gAWVCF>xqudu5&iEqWwoiV^b29 z#^3n87_k@?SxJE$N(7z^+bC_{6c#r5&m9J#3XyOhU*f@Z`#*y9E@Reh=IT))L_5q| zIoo~YMQAv5G>HGy3knLPEd_s4@78U6;EoBv#Y{S^CsaT_Va`XnsRsbWI|*1*|I0@s zR+D!pQLs7GBDsKzpb}JkiOW_y}{~^FG~6;Qg(YfHIYt!R6IjI z9ffLN$KsVVI$#LfG52!_^`8q zrD3S!fANXlW&X=9;7;cEt*PdwEhY*|o_PUy1ZQCNkN=vgFj-yTs}OC?xSF3cFj0hz zxyHFiNX~XnPxC}>&F)RVa=SjPcR!c(kW$1%5^?{~dZ9;ITUpXnYoTHhYlzx7a3}!? z|MS(2!e}2-cq2Oc9cUo|d@H^ce%HdAGXMfu=tgTae-H1soR>17;TyL}sB)?>95j+5 zw{rLh&IeE^g@XRctjnX^(l2TAR=ve4cAqCi_-)FpKr)EN_>boFazvGcPBk^E_!b-z zVm-!)HdsxXu(!v#=J<%=sfB2JptYYoe##_-k5_BQdnYi`zmh4IJ~)Gw(L(42+s)Ky1uYQjb9U~PC5<4yMCmD<*F%ll zIK$+nm2%J33hgoss1jkgHTrlmdS@HdfuvRD&@`=<-HZ@6yP4wyWbIhVYX@i7uf*?d z21;Ux-_EIFw5bmY%sul?Tg;nR_&sUq46}s`!%bQS42CrzzQ%TRcQfpZPUU|=0EiN2Bz4hnn@Q>+Y>*sw7e&KtH zQV^n{;FpRvl5>2PgC7Ubs0A!hn;*B)ay{IRqc|619&HV{d2)HOE(U!+>s?E>2L%O9 zTYrVyDOyfG9?5@B+Ks+^c{?$oLd)`H$H0*!z_hX683iSRn&_UM{$l`f62{XD=FIN5 z&C5mHSBDN==p3~D^x2p{Uz#(B-ca^lzREq(4{a$oHag{mWtQ*^Q4<%v&&_?2ry+fA zuG(N8IKul}K4s2-Q&8}5&fb9srbg4$jTn&t<5vp3p3DEU&~y?ZkSGki(0)UtA)k4N zzcP{GkI+Izj~-{5k4y6PwSQyW=psWMT1?Q;++1dkZF*KAku{v`%FUZkhJ+PwlclBi z(W9!U5l;sM=pA{y$fDidS=%qpNj|gE;a0#z*V(W4rNoX6^Y2^1Zpxp$C%@X&Ietk^N} z%lWHc$+_*2c-DiPRvY}o2esS%mJ-KS7{ALz3680Fwf4G4)d&=U zTk((v-b=T!7TKp>7d$;>G(^lhM0m}LvTQ>G7 zsxIUO{q@f-n5VM?D~auB)#Q#TgAdwvs;$@gZ{7%^h|%qm+Abd;7Yt~L4}2r7g4%@6LFVDuR3z zf3<1-gJ#2uPv>y5>POrS5!TYabs!Q4{cF?NvuA^1V9A<5)kV>8{6h8qX@L(dTME_` z|5EA1rQX1zH_GyIInxMJzk8#4P{Fi>Z{NQ4ZS+qMOiUg3y;$=f*zr~?{>o-_`Dw0A z1`i!7Tr0~N=6Y{EkMVm7N~PQm>C;?e9uh^-vk?Ly+L*yK_01O!f(e$j3zr$^Wv+5K z8S>Hn^vg`c)@=$4i;9X)9j!ML?2xPbHw}NiHmAmfheq|DvxRk3LIVfp4d}}y z>H$FzX3KtMYaEz5D%*6&nC^^+etv;#kTl+$(%-trD}9-?Pb>nb1z$Dyz7u^cEWD~k z)285_4dJ60Jb&Ov9_|v$1sA(Z=MQ$DR?fZ=6EkdOBbSO|OHyB8(&8qj^Cdb{zeQps zW8pfS^=46LVS;5mpf_)F_Q|I}JDA81hdPK>+M^pOkkU4IzL&`j5fhshvUCUB}qOo@z>9Y1rSL!=qYIJLPDYR=nFO22=gHyGLR~x0HQ}{i4 z6ED3{SntmtPrO6KAJL6qOvlF%s=U~$?gPUFwgbqiCZ@tXah`>R)bplY$KITnK8%=k zG7=q}i7$}?M+L6g7pt=` z^_WiL|ps(qn z;NStpo$~+wyRTQPfnNXo?bZKEN!HKbZ+CxN_ipo|)y+Rv{NA^EVTDI_PTe(cDqp9U z#WEAJ2|!lF7O3es9T~OaDaTzz^?|M`D$nxIdXFX6^0KA>-x2LOP^dOvW2)G!cPg#K zG`A-2>0{h92CWn;lN#*T82_PH{fVAqr?x^ey_7=&_$>+TW|nie^}Xj-f@MFAq$V5h|a-{V{~%N0~l-w)y)Ziwd84#rQ4u_?5a2E zTEmnK?qEaC%tgx>^W0yY0pAD!5~r^B?_`b%*$(sU(x+47rUkY_l*&L8nSkhIC++pL zrCGC0MqFz%K5Jmp6LUGC(4$l~KhtQ~u&X&I>OrkD;2PU!(Kts|pZfIIQFpuJM~`NH zYTcnlG_z%BBFC7v$%loO z>w0&0YkT{w_kAmHYfww$Gcs;G@xbzVzF`hiFExKAo{JMFEJIG3LyBSDP{q775h@EB z5dWXz5+W!Ofxj!Gq2XX}cDv~AR)}2w9qW5emu;XdkRJa4_B>U`3kBGPl15r{vtn`G z00IU^jsra{bMed+h5mqqoZ~bap(V2!cCNJf$CpH4GSUnSE7y1Jda9l4laKwyuyggQ zy-%Cz1a7h)>(<6`pC57{MHH*Pd;eaeMGyTQK6f|kc@1PA(B*8+e9bnEvAj&i3iv54 z^q7VsdOzHSouw-KgmVU(Zq*s)sW*Xtd93s7;8{<4P0swYg-Lc*mn@HtX2_x%KWYA^ zgqYiN)6=tFz9jxA?1189f13CU&iN**SAWrcqN!3;LWqh*!^P7AePELc)C1hlIJoX- z?hJiYPyd5(`k@bkAc=JKdvwwGnl(lFdC$nigB}PyDXu&G{b&34|5efL(c{M}Tr9p4 zzoGp*CA*xLJz)59XP&`!r)-;Klj-w3dPUup=@(ThXV07Whzy~KDA@*Q=2fbh_3o) z%mh}#rbJiq>eXdTb@Q6~%bXYl1TfS0ve?q_a+Hy{qAhk$IeO%X#QEy#JC&&VNBlM? zN`zRkl!^KQJ!wnR&(BTf0h(S|VeD1zR5MPqB|-VjPXzgo{E&1i2-S+&2U=-0)aggc zb3A*pjgdaQSEApvo)|rnC+b(WCMlb@`Iv@2J^XY8-WU6(oME!RYdOT9vreb-LazWDyNK`_9)jat~H@4VBwN^i z;+kqx!eZfoP?&*wQKuJ+kP{T5-w`iI)5wQXD<+Jb-Z?iz&dBv>lnT>RSr zM+;iCj0`8L@75iT_y#rxhKZiAV9mk)T@KwP+?b%&jvhh6}E*i8F*%uv*M z?Y-x%Au8;2Hxd$rj)CuLJIlgi+Wh&))1vTs6^v3X?dHpm)AKS4J$-r$8qwtrO_Y^y zCne2DZ0T$S334edTS0-$xbE14&<$5^=Z?XWUk?rnS4cJ z;hLjbtli}K^`WpqYrnjiKt+;p-pS)?N@{+OJJG^PQgiL>E~G{AQFJd2@2BkxM6)dD z-oB2*&RM#4c{b8h@A+r*gP?dOTC-Z*9OVz?6*{So5}0Q4=WdZ_C{e-)$oD`Z2{tAGG1+v3SsKIRn)0D}$D!L$;tWL# z>m8f*=+UDac;C??_ksw(7~#uywFb>QGX*vUg!fK3!&dT7a(zmP%Ed#0)GV1y^I=wR;+CnWC? zi*9n}2;h-W&*3rJo_co>Xh+_Pq9^Lx>ik5>6a|-f;0TMw0M@;vrQV0)IM*?J#0pQj zOV^B50m3|nJ73d98LOr9rT?HovP2~L@b(;I+MUbnFJv1kd+H>K9@#walr(O0=VmO4 z8N-9=z3HvX<)nfFJK0eUAWQL;{Cl!1f#uc#QXX5Owj64im*?5raQ?VMvXLR<{zE$C zqx~IJqGvB$m;{Ov8C3?Tj*41s%2^#LAN&p; z1gi5U*$UaSh}lJ)j<5@L9f&FV8I$ZJi59mHk3DzN_-qrxQ}}@fh2>GqmKA10rah08 zW}LvbwNRU(rnpbUb96A+H&hZLfal4Ju<(r{PEeL?o+Qz``H==5U=_rM`j4=D@oJGa z5KTr$b%#%hk00;peR5sE^dZC9WLXM0Jz}2qozzsbUFI&WXepnh*>_-Jm5Ymu_TH%# zs=K%2^1We@#TOB2FRf|v+%deFlJAd&qcP1Dp}S(sAa@9k$&c0|_w8GyS4LmVX3suj z5{$#riu}&oMV2$&E#{3zTdEfGj%)GEUz-=zZ$*v$^d8%4EeHH^4WS za$ca6x3zY~*7em}&~--|WXTv-_(0I$12{Ac2_*QJ{ z?#@Rvy@udZ8aL`8GM}}qz6&ja#~t(g`wNqX|M;Q^@1?Fj!9EK*y36&TON>$kw9YH6 zDnuDTNkOwbqxa=Le$#ls$&-?0ha6s#$3bEWC^JM)WPIU?UME~p0tua{#GyEQWQYL4f;6A!UQ_)Gm%fYbj)n7>ze9C=>MsV-h@R`kS<0JVEZ1A zRdxfXuC$9{%B_9a_}&IpT>ifO`sD@(owTcPzC%yqws5Tnzrw|!4rvjWmp*DoE=Ock zrw$#yq?pcFp6xUJV6Z+Pxq&^Q4=>sPyL>FdZ$l5k_J8xc|CzW&?8^+aB`Z3F*1(Zm@A z7Z@3(>&3x8k8bM7(4~#3)U7rBE*Q8&$8)OX^LCy^ji}aYA|eDTy=~b~oGG%h;K$FO z>}o$(dN3A4S??@;F8vj&dkxBNzq_W|(9b(YUHNwi>*k}v{+-xDS08Z1xwG+yRs?C& zy~AeMC7Ul;@RaEld2M^Vx_0SR?8+tWxZ0)YTg8>gNQWy`|Hf+e?fVvrt_A0#MOMS6 z9iE-57^kjnQsrN-9Zg;F1S6xpX?KEYLL{_AghSh@vstPh*a3S#vBy*_u2$Eo0i zIz^E%bG+j>Ev@ZmF;nwG9vz@iKA+yFVg35fQ=7hfjT}Lip@%w`$92{o(oI{+WnX2BGD4a8!{3iCF*Yvh+JSAviu!2hvz}XXa$p*Ff2n z0pqil=hOS|rI6t;gId9+&v<_TF0z~ltU8lWZ<1jn1+xLE!~Gg7e%yOOgNe%Zf#Ro;gW-$+Qm#5jU5C^HXvUHld4QWvtHdWwYOw-Qdivn-&M@g(Q+lBww1MZk!ebpI&#t9_SV%sF{R7;v)QNY z2C*`VV?DC+7p`vF;X5F=*y7UW=tXe7<(&#E{cX<4MmJ$U;%&Waap!oYFRrlfr#;}$ zY3)Rl9r*I-Ue?Tgd1<{*wmUHpOt-W=k@k(@9KOH(A3%bf>y&dAaz-!ZEOOXYM4X|6 z_QoLjB=MSGxM*CMzkKmYmSg)(q=8o3t}VepLS2K2)he5bgYX!?n6RZ(DBl*a zHaI-|1FCt8EJ8E$8u@yZP+o!{-EpGK8v9eJC9yd z59u)IAkmJ^kahu5mp+@=V)=0$+F?|XxZ9uo7~PdVmfBggzutJpdRf%S!Qe2$xG@=M ziM}(&_8qR!59+DP$ zuxwa7Ie3=K#}N)t!7tqA2b#3x6aXn) zTkXLUXj!#c@WlS@oXxv-J)zYY&b{vVx z&M!y!R1Bltkq(4wB}+lBj!TlA-wSIh+oKGzLH%FxD-!fatFh8zuOmd1Z~7tz0>1^XPFR*{%YWwQ7j^0-&b$Gt=p7IiI4osly zg=r%If(3iMM~ynn>CH+QNlQ}zcm?5qzpk5i%h7y1^@%jWdMiuTB_F=de)crCajRC9 z#Dt|1m-UvwoVPp=;QSHm!q`SlueUDd@pctG|LFWx%Vnfj!!C=ACb(qqeYG}?>&tiq z(r-K?FfOZW{P^AW%XE5BW{4o_ICP2Etm?QKq~#c&TY7CPH}f0E+BccwV#X-`xp;Ap z6fF)AlrI*)uS%0ip!mykhmVFl%rS|qo{W;#encZU_$QJK#kUE0{Q=Y1J)mn8*&luW zt3y!55lwGv_k~$N3631;4Mm`{j>{f&Brb(DoCFlE9l!@nn+8n851=*v{a2DcQ5nm? zfEAKjL_W|{SP8Vf8eBf0&YTw>IK=q#x{0T=wXci2u3jAHG=$j;*A5ll32OR4W)IL_ zSaj|-d)BNky#0jX%KQW+d;jUv;;@RDecGsL9}c^CaYa-S&>Lbv!V-3xr?#OJUc^bk za~)yhrS~5~_3;FpG#bBT*ADLn($sgVONy@%BMgq%s&nVZPz9x5 zzQ}b1SB-Wpc}ghODE3tn(IRocTwGHes1S*uFScu2-DZ#>J%JM}<-%g?fI{0>PmLo6 zf#z_qHEP;)MXL5srU2%e$53Hxq6?z4LwX(K_6z3MPdK(BX^%M z>rIQMoSylsxU!+1Q#&7N(oVaIggkgwflkxs)9AU8Y;ed-!`VV_$N^$uc|BwRy!@7| zt9X~2qHlb|9Re=&!7Ka5Wypj;lbx(UfDGe7+uowNHCu?v$(l6}#sQ`f_%HR26#gDXsmIbe&G{<~Z=7dn|d_W~y zz4n!KYulkiA5+(u!5}+iFFxXtXI)$#&k16EvcI31Sz24QE1iM`kpZ0?@aGLOxu?t)7 zD|L1Gwd!!on91O1$VDF?9lo2yAcWS+&6*)A+=KhyngAS=VEsUoA(SX)yClf)BP_oK zWvJM&3PA>U1E*k2O8CQFAS>ut>atL3>ye1YNk{1@s0{jw$#m?_2>vrRQki;C60iA0X3i-MVeYN`|Zd z5xp3h_t!s+Wi~^;nFoF$^$oY~ZXSJwTSf771_mZ0x;#(O3Bo2ICL+ObMVT&H#S-OA zbH3lL)w?bKJxD`Xf{}4(dPEhwM42hUneh6=AGgft5>hlhrZ!{+h;q)=mv zMwd~4UbD44(N_|$*akROhI7f7e&}5mSzAwJwuXcv9pR)zOERF9%$(HQiniN%lJ*c! zy)DQ``1jncOFV7nmK6Z<_8Y44W7+AJ5ZR-&h^|{9(oct7Nt_q06z{gA{46iv)ppGB z4UW;1xq##S2I>s>hk9>#KM{_dV2~^G9j~rB37dw!J}P)>+2k6Iyh`ZhK9f+JPeqS(IZ1i0I#=_H892+dHd9w=Bif zZLhvleHy-dyaWIJ3gO528T$VG1X=K0rnddr7H}qxDA3M8MpsmpCUfT+&@6C~Kr{+; z^wpy~ACV!3-x%GLBajm)FznyDi>WxUcgALBvI3K_{U%nQS!QOExd|o1Ay zXBI!Y_B~h8vtcm@d=H12iseDlOi5NrbM2tF<4+saQjCA7`S_er!8ECems_i-U|G0& z>s}i!vd~FPH^%|-jDiX^{Y=U~Zq#DA0&w4Vu7*0>V&0UmRPiqEuiUqhLOs){_NCqS zaWw&k{pViM&$03v_!O!(M_sOC@8xT#^ZbF^RNg76*N&v}*KVfNVLTn$XIJ@6OI82f z__?2fAidjEv_%CVreE_@aoEQh2e$CqG81pBT*qYuy7Y~G=Xt#aPdP6=pGc*}|9^3Q zu}Eb*(x%8V8|wVf|5nohHN%w3%OjS$UyM|PnDJ(}Z)pErhEqUgN$Nz>SypPYO(o8k zd|imB)QsOq2%TI8scR4W@8Sl5=l{iZr!24w@Evn3J*Dgn2c|3d#x?3dl^t~ROC6Ng zIY)?5jCR2AN#wO*o$+1+$z|G$9r6<=TbEHL9ctGTXb&fsZUi-g;p=6zb3X*AV}8E( zB}bza?Qz6~7KjMwKO0Wb`G z`$2rXCuoa=PhNfLsiM|{skpvHJCVE67E%BS~L`+0OghZ-65wE&&-JhF- z1V}0^2kx)14`}B1&%L@##8g}V%}hrYlR&EhlAJyYjOA{>@SAsun&^m?f@|zhT*a{} zbww;G`z&v)@#OcC8nQh{EhbEGCB7Uc0hYW9uEZ$|TX&b1h7r%?)I0)&#j;Naz{{%o z8yAZoTnub?K%sv(I_lv{@@$@NE%0F^m{)W!vIh%Gd2p`87s9SgA{qWzaZe`@;$!fn zGQz~1tm2T*#fwD0(7e0-LgriYQe@$YHIeJDy4iKl#f7lg*jS_D9+?AK)Jw4?hW6FF^~_s6fXo>PKJ~e> zmz3`*&`a`y)KtaQxF`Lt*Py`_WcyVYGGpl;U}T3uH@@XYh(;X6U90x(gNzkCCv7O% zWhSR}%06fKUb!;VIeC)u=@Yfwgz{-q&J48?>u$h5Ag)wPzGmB%a5Tw4an&t3;riMN zKXFCsp1qvz3SP%ev&SJG46Rgk=?Qh8%hUdzmr(}{ZUoOHXJP9uU7m8k=B4iN^J|OZ z!Uks2iF>fMN4tPRq1icCoHY5GFc8f@#gNwTqj1o|0w5zSfGMYcK`!Z#i$GT?QL?_k z+rG>C_bp+LYE4jqK8%^KH&!_ah(`~j09``BbZ)W_LwY~`tW(}-_Y1m zQ&*GX;+-onEDL012QW|^nBib8t^4We{-Vf25oZM(IyUast&=<#S4o)xp2wep$EOX9 zp$xXf_J@tFVJkWl&4HTA@EUo3#q>bW*pf4rRDF(*2DHj|DC60iSXBT3p9`j?fpv$< zOT>o!a;iqbH-wE3`J+0jOW@J+u%Dx0KVgOh~AIy2^2qcL|B%$l+jME4Irv<3~(hz0D zIyPu4sL(xibz|cfZ^F(_u;D@ADErO}(dx4fs0*#uA{^&)=FY_pA?q{AAy5YgT#7=g z;M>CWd2Opp_iYl0gurHbb3t)wvA!a&b7ZW9H`s0xe3ocfI$TLU!3cbqJ{DcWIff>v zrmJwD{6}0iTe2GMgu83S{6?z;AU+{@7Al0h0D!><`r{&!KAN|Rr$SO@DhpYF(eyS1 zGe_z&@B|^csLQBi#>4-!TdV;e=4MTG)$OA9lil1ZJq~<9+hdY4u^G{(UdF6wkhXUBIm*BA_`G)=6E}2&?Cbm1&8aP zRX`R<-icVe&CZm#zFyxD5uKQB_m<7(=u;fVOWxx~W{4Cv=O4_zj{e87mMPZ4jM%P~}UeWi*cOcrWr#u`3WP z1#pE4_)(KVH*eGK4zC=$;m4%}7k{wwMI0pZ<|TG<-vd99Bn7jeoEt;^k9K_b~Bh>=%TNCqvuEd>pI*jFxx`r?4kK(++HFN=fQ&_KNKR1 zWw+aDGdaaYm_e0gQ`SC^8DghXTz^G) zUStS=8M5Fi4Ix=DA210(i|kSWp@$^~ zo53c%t@0PRD}v-t0C)=Gv}oRiBgZ!;tF<6G=zXnMtauDXYoW&HZUyEb+ZLxcsN}P; zlI990DiEbOgvs_t>p|m%&!X3;QFA;t0uCr3vcWmDZp_XVGR9Lik(wBp;PPR_CfD*3 z$l0=A;B^t&jh=x8@T32t7$VW>K5pD8J~HnRk_a2_D(^((h43&t=obiW*Qq%<8>CQ7} ztdE@>+N4O{45S4FwaI2kR$l(ifW)-}YNb;;&J4-l2zpCujd4kQmku5N6|n?bU_pvg zJy4&bpO=190>J<>T)lGv4dU5ojqb(XVIjOBgwN9F0h3e{arMf)$u_@eH-m|}Z>o3p zK51Ke(tB&=WbgQj;&Ydi<9Phi%A;18&PCtCk_A?O48fZSBzw~$~`z{|n3dyL_*4B=yEOZJ=IHJS{ zE6_+g!Ek4hoz9s!H`Z-9Z}gN zZmM74c(nG`{a%pTV+wk0KD4RE0QYoo9s>p82!FGnsuLr-d6Q3k45_mW$gopWH7 zPTThFb4>SGW)qN%utB!X{+Z)9qD$$B+!ds^HyQ@k$+l|U`pB5|Lm>zR31xyA{&Q2G zZ9m3c*=+P@vJ0BoNAfu-?nnwdGqKp(_F3&7?ao!Aw9qt>12mO+IyGI|f3z~9c#SMc zm{7hdC_Cp9$GdRarGurK`u;l4qVDQ{s{>9Tbhc$ z3OREc3bt{REsL@v3#fz!hVRcT(_rMtYrWc5lzfMQBDCN>7=8NZ(P&q>ykD@f-I zTpV3o&e8LMk$t-s_q*9<1Xv2du)S!&YRVSYP_FAE$0a6PRzVJ2aPwbM_h>R#L{;C; zmMrSHUwMQ2TSm75Am84s(`2X~m?I)gd5<2NSF~-_O2UKgq4!*06q$}?Ndc4}uFchzuT8HJ-Ji+mO4yur#ge}E06pHd zV;*-mk)tBUQR${A6Gy$-SiJ`aEv)kasAt7@)wcf~_z<*Ol zZ~6 z_n=$v5XjwF0o+}DZ^lZ{$J*T;U`YHV& zHnAo$$0*IS@Cg++RL zP0^}N)-Hmy1Ms%@LfwIGW8N@}j9#|l&{1@HC`=m^II0KyEvg{Q`J z!2+~TN-*@mn}q6RydMrx>ca_1NtZsI)uEgd3|hmVR+N^?&wWz7crfD;m!Ca#$0m<~ zj?E)-mQIw7ak7Du+CyXbMNqs~)=XQSN39-zCcpkGqtzTTYY8CW3nD}k7cgBRFBngZ z6*{v5jh(Tvx~xIHjiN4l3W}l8Bm&Z%UN20)eAWJ9mFzQCyml)b@TS~-+v&GOZw;-d z@2ACVyLsI2Pcv>8sZFtnxwloNh321mA;1*2S_B!iShQuLCB;6#?B@+EL&Z4r8kBS# z{)2&!f6N1VVO3dld?8EUWNIjJ>&iRfeT(X-)gaB)+SYa|xfIdMCfL`jUw?SVbv1_q z1DEa&e~y`I+_<=2iFghpZmnc4W9AyZ_r~?>5kEBKwYT?qL{28PyzB$8>h#5tSFS`C zR-6y9|4R{}-%9aBfPjn}YkMogW6O^wB+Uef@9OcrC6X5GXn=M1#NA%@^=Om@f)Ri^ z1?^bP%$m4OypP1))O$n6G^^x_x|895FH;)|KE#};Lcp|9yW&gF=VqZLCMfa6XRSrl zo&h@UD($)80xVuqHdO2Aby8)z#@Xf)ZXEVdEFQN^nu0Fmf(kG9Twd?jT6 zpII9a_QeJ4Z7*MTxURcM4KxjLE!6+{npA%>br?zDyH=E$z|u58--F^0183ByjR4@x znV`pM@7BZglfH&X>N29E(pLZ_Wr?Wd@^IX)D*cu4ZV%$NCj+0`K5BPFuR>!$k3Zny z$Ag?RbII(GxKEIP-VEk!>lV;X-f6keD6O4TUvL2=xEz{9ej-^m^t-?S)D#hWNph37 zJ&o`>sky8{CrOiToXH8z1x0)}eo=2sLS;Xt%O=E)L8f*4_K84qXr#zHYrtHK(E+rp zDGiWn#m;^EY&bL|p^2Zx*u~G1;cdFz1zGmPpZ$7WZnLt>tf!dgk;Bwn=bGy>(GLNd zlhU}@%4!Sm4e~@>-Lk>9?1s0Xcf}uoF^j%Bw=bHqtd3Mzy&%>nq|PYI%vzNm(O5nD z76_Ol6Bd%9?fd~W7}A39AKFg()AVTjNmHcmVR8t7!84c#bjn?re`~`L&;$vp8;?$j zw_SDXFXB{paR-EtDy2OT#U!_<@1Q}mPmM#Y4ws-6)^ET7IgOayPcmh3So4%EWe6j? zVdTz2a6vY;+jb5|N72f3(j?F5cH@cVQZN;af|*XOEE72ni`(wU$2)=&!Yiki4lfTa zvhVr*zi0nhaL(8vt@OO|dDd0hwVO=;KmlY}w_3bd503_?9O#z)ijf)5MN?PyPdOiV zDXLO#v+=xnhLomL9_1YYcM<&q@cqrbpahw>@FE}gFaeX;DS(V=DCLc1R~P!h?Qk;^ zDeCQh=-@#jS&fi!;ja6@jKe|NU^8A)*@MCAh$QO71tSGd!#5fVkrE>GkOUJELVQer z{@ggWXqk1(I9MdEsgkr}0AK}$%uaJiLFSzXzTnupM^*aCsR7?^#i$_gYRNz0H*IJ9 zH>6`Ln1*(`i3DGN|Dft0*f9eb233o|4h!-c(Y-487L&7YZK~PG z0?^@MKVebVm!;0$lJ(-}repQi(Nd9Auroo@&_y9rN7l*mb;2D_(K@%nK(3&B~ojF@9G56xpge|j4HtLEFdnipp`zoCSu zcD2tsvGNE} z{-|C~XHpAZb$Z;5wT&_vTsOy?+ zJ~8iFVb$9jpJtHE7OpKWMMbSFeVxfkJeZtD(DRgh`$-@EYyNp57Zkm^(c0AXMe|Qp zbQncx{`>Z|fDJ{N?N3q~y3QM{)8G-nSs>ROco5~I5JF_4&&#dkIEaZ4t=HA<<7xN3 zp^k4B&YnGm{%u-d{^Zq}t(v-i7@B8K8AWLfeeLp?tBd@Rj@CxgU4@8P=aK zr_>B4j{(eY8jA24x@B!BnM)Y3e!Xq6X%Q0PKXh?p^~|~M%~N!e*&vO1Ym9<*@Rq*4 zzj8Hmi8ii3vwc>~w?@CZ*8G?P%Q!r2G!M6IFIUjER&+kbY*?8K)Q&|$D|6V;p_#92 za_#HWIy4m1mF=MZ{SRu4Z?Ewm!KTTpTM!v2|63Nuu~YF~!%+G8dT8VZe$xVd-I*hP z7msDA5Pgn<&few^g5f7#ahEHYvxIb?2;Qer&3fX!yR9Mr^v84MW`JCyIy=r%Z zs7X*9B2kd~t18Q(XyfSGB(@WnFfD&<$^2a+qsT2R3_0mY9@$fNrw6S}PpvTiwef## z9PT(63-e94Xb;O00o|WZnX2d2{CigKM<*g5-ZrBV#AP0aW`ccr&6vGo> zIE;7dIDsbKtLbz!7KBm;qRr*nN&>qhui2a*MK?Nd2~ZY%namvk$+AcRCjnsBRSwu* z>AV!j;B4x=dHeRXW7j~F2h1~bZfzJXQ8IKGWUX2+Teh873`Fn)Kos+>okrK%6X>x5 z6J%K_JclVkKCiM?)(`NgRaoEm2)b}#7j3fO2vkK%Brp?|OF?*stoA|;PrLPp{F2K>#=HohKv?i(E!j}hr@@szx>@@S~b3A0dw{}G!mWlkp4TI5EC;Ur{z9T{$a z$jF+|x8x45qPBw#!t2=zG`PKaG=+UwP)Py61 zu?q%<6TxZxccwE7QJJEFr`J%h#mPw5p_;*@$mGimuZBBo&krX9z*;cvHS|SL(vGWF z-+uAp>Vrd5L(8(Z#4!(u6Y{X`vpJU+@X!_mh)C%^mGe{U2J(?gWdpB)(`$Rz=xxlX zfG)C&nzMqs{gzY}F5kTV&r*DJ8dh_i$*Hq%`m2OXt5MiKs}EQkllQ0L1>nwmD+M?yW@A6u7{8EPERP!nsWaxg6&bln^%ziu;*v z?cnlJYoktl4k6MlTI_4r@MEYMx1KfJ+}TWS*9lO*~AVHbuO6Y zvE%gHrx&vHHo-a>;*nEuXinEWpA*6rTCPDfhMv}pjXl_h{_GfT5nMDkxX!@QBn;&; zPE%?#18WktY(ka5!y!M$%If*Ku_XJaZf#;vC&I{Hb9$5KC&{o-f}@eed(@R*VfSYM z)iJawR+i*&H7i=zeurmA5Ik_vQcQn&@7aU0B@k&x(TLk=<@e)4>(=NDe_BUTe4~8x z$4Xq@iAZ2mYFtrAU%qxNkz&tSD5e~e5fg^fA`8GGvnsAtM8R&m!@yldHSZkxElp-e z%7^G!{QWsQ@ABK}n1%Toz4n~jz7l4NcKzolUcJt=2hIW!Xg~kPnn}89n>b_-A3X{K zB@Ya_Ui@QE97PHmd6xdxVq%jfEx&I@nn6l zldmqL#AY!6I@kY?r!N7gvhBWq%tR3tO{feNMFT~0q>`ahDs!epMQB2Xb54fJ6cLip z+*@W6l6gwf;qA>3g(S&L=Hs0Idi4GN*X4S@@BKc`d4~Jm_u6Z(y>?*?jQXCI44Cne zWHEY35$1qY0uU3B+K?PNn5H|p@fW8Q)~~lAyJ|>P+p1Mc}VkE7? zAkuT4xQBZbMc4AaeHAB9q3@{!6w)(j4qGl^)Lj|QT2Ex%XW{6cZsGx%X=U(I0H-te z0bLCdyFlEZ0(Vn4F$+d^8-^{TeJ8od1*arPlYd&ANZVpeKCVME3R?U>zj0@gc`>aG z+Bh<}B8erJLlxs|0@?QicUf|B2Wm$0AmqrT;`apB$#@|Uu-Ti-8+h1B(CFPt))?Yr zCHQ{Y`fsSB+3Oth_)WF1-`ecrwvgb@6p%UcKtT54!?U`__a+HJSHJc6TE#C!LQqcD@o!C9v%0N^$J1%6Nl`1^^OV+vhGvqm)ZDKFQIZD# zc3oD7-*=FBztr9)2!{4{e|QHkl_=^1okbY^FZz83HMzjcWXw z*xC!2BA<4yBePnv9F>VMfH~5vsY8@dPgsO_7}(;Bnrc98cNsFs1(>)&J{`{=w-3bl zo=-WmJ$QDoAl!gJ+IF|j;n!t#j7C8MyIjj>+2p09*;QmOn_kZxYqFRjOOO+j(87yf z9Q3|~6m#F>qdwgV)}>s+8bpryrmG+Jy}|L6!lq;xwfxrGqnr5<6W;9WY$SLge9ACY z%xG~21)#hl>}+)F=nH(~!Dj&hd!$85aAm<-(nM5E03z#^;t91?i*U?~Lj2*DZ+Rs7 zGqzF9xgbidOD?<{Iq`&xb;%WxiE)NT(2;YU)9 z20m4GnX)}o?+$4C70(tFcSSDN@)0Z~o98EsCvws|AKsAsPIZ0UuwHX4j^Wm-QG{*@ zQpXP(mmGIQl;jqTZvvLvEzmUc(W9t*(|*$05Ql5t$+b{vh9jjVMzUzC7oLCWRo=Pt zCI|u!;!QyTX;Q!0l#d)kMY<-J+K3?Nt))*zUe}fJgVC&MsxjUanoxH{WUna`HwRH8gk;^lXrpTwxPFf*}1ui zP>ZFoNPybZ6xy54<+MpPT+Gi%fa&zJw779a-N23!C! zQe~E!nyMDJ=M)#MxIG-l89FCql(Ki=^$3;!V5-|+IhOpn{>*lMUVn+zt1H)qYxtol zr_6pU+1e`?C4jP>KwZ}#uiZe1@UTKoI2@?tV_UPOyu2LBqVKoVVC|Z#w7VTgL5A%D#iwW%@9>}A~;q}P3@#ldB?H~&Zx$Z_)9UhF7MKu@Q@%NNx#`XH|QZ?-6OBo z(nB4MN~(~jOzV-m``oz&q*SBxvO0cjb6ZC!$dKE%;F{5+_#d~a=Msa922ljGHxKX(*g`_zkl=2z!n z;92L~&9x>V6yk5F-xJOKoSK|7^BBC$Ua&vVOdpfD>28Fri{$Y7m zZxT!I&(%YR4o#H`Q|Z|MT2GBS8LWQBFsO=hhwM%T>*?TMTQG0Kvp=)i4ctW+>e^G) zG-kCdW4hmw5}(0bZ{|nVEDq-}tdA9=p{IeHh%gNrMtW=dN3HCVd8%=nd+T{K*TE{O zT2$@~(zaN?9MPTjpkazDglh`9Dr<1N9^~z&cnOtvp!4WgUtjt6?`vVxhq!@(ye7XM zUO?3s?VcPr%C9BO^*jFh{ksfRXu;hnp@G_KNKFoQ{P46-{ka^3-F0YkO30ROcFDb@ zcb!~bnm!WXl+^MYFFtDc=gg_BGu!oN>(cjqmX2+2&Y57@fEkd~FM*J>;Yn*~^x~;5-tmp?#$|`qH5wkF9%g>UwhmWcL}2Q2vY!1Cd5SdK8yGC3 zQ8)IRLMk#08S^8|OjA#|H9JFLmQzTZ$*i<`>#YG1C(64<9^mwZtQ?Ml!1w+w&YRy? zc_UzvzPk|rWZ-RJ4ok|Ltry+ikzS^UWgCMO?$SE)|FqRPF-45eDcyr_Nw;jx`?z(24 z`tz0=$lgTX2{X)RCw~JLlelmsT~HBq-6B;v6N6tB)DfgPbIikztPda!W1&1CrILA~ z?D>B~Y;7I5Zn-)3)vQ2BJ2xrcE^TMlwYvqS;VcHd*E;oYY!SC~(cV%_?YQDnWtD1t z3Y8uKjw?G?Rngd!H2FfwV%PW3@Oigk09hMG+3*fdK+x%jif(|FAh2~_=k=8sXhFU? zd##O`rb3-=5`@jxxO%jcDDyu56olq-YRj02_B(UZ*iv^7Is0u{2#;~{QkV<__TZM1 zH`{y+FnUpe)02#n2qaxxQd7h$^Yf)u zKPMf@u#ytJ2h|4eMn;MbdR!auvo<%sSD$GeiYvL&bn*sf#Vx}9G@bNVO+0w}cGbfp z>uuxqczEoLsBL`4^?`K!svA3}>3aS|^1-OC0?_#{1v_L;_967tp5 z=#gqZDB$)3GhS9-&7{(_mvZll>Bf>Fa|9osRitS@DHJ?$XWB>e&%}hBGtb8HSsng0 zm7(Mq^|!&5c6aaJujuHI?swmXOi9(bnGOx0w(urL#Ks4odWXl7*sG9w)moh9Dz0dE z$wl~jgb^A5_Xb~N6ypP~vGKS+-Fv8b$42??WfOvR?{pT`r`N!`OkQ(DfEcNeU0EVH zH`mVIEyT-3bO>5caZ36O?;%S1`xSFfODAC{pLp@qe!ZGfSL#?ixtmDyP%5;8XRyQt1zpY5B6ef{*u-tHu!O~v`)-L`nn6U_O*q025$vjmD$&$;P zUb!@DLL}(~ZL**}jPzPSMsRSa&f^ABLNw&vK8sEZs@|zHuCCR1Rf%4|H@qGDxGN70 z6lI;tCRfO{gB(c=FqBh7_#X=3AEBkKR~Uh#S&2F#=z}6;HCZBumm~=sa3^6bFE1~* zuCN^!m+mFkFIg@B4xK_ZP>f%x^nd46u%Hk>LZGEyN=j815C-ld(-rcX*IvJ#FLwbe z_}6x8Z(mV~uuN2Vue^_OnueOwGC&~Mqu5aoKc6GR99DJP)t&?cuhcdgdv4gP@KM-8 zSSM3o<>q#g@djrD=QV8QO{loLVNX0LC|F6Et}!Gkk`;&tkkihxM&jS9?$~iD++eO{ zvG%)j>t@?}G^>dbUz--i4LIljL)BYxnIH;)(or=w+gBX5vMQ2$&onuQ9e{H%xmf+<%Y_dnu{=M5Iq?{D;J#{#`Gkn zU;)90v-7Idfg;^r7DHKR@)G&k{2S&6y*^nIQi;DJ! z4j%f*k*~ElA8xU|XMg?c+7VQus|&u3Z~o`=Z@*BWVwfLss>YxH%ER(8iXs4Q`jqEY zPeupHkK!N@ogbyA3uACMZ@Dsg_`@sfpAQsa1WlV9^UiUvv3uNP{&(*l;I}`vISz%~ z!e+0fLHlGVv0q<@&cCU*-~T3F@5GkPu_092{8KxQTYa~}F}D>R zRsp@eXK^l}^m__90MFT-2aHXDv+3BWo5(0zDACuU7l&4bV9Y_nTn+!Z%5Vt0*A zHg%-?@5?k*eB1@Jdcyec0-ygNX(Z*BFE8=;_eV&n?;A&s<_A3Xr(X9SI%`Pk4N0@^ zzhf;W?dNi|lRrO7P7dK@3!TndMcgzIf!8zmD*LPZ{%-RF03N}2zPcQs(I}9c!eyP@ zUqEvk$CNIDe3?%oWfuO}Fw6)$sK7z@bj9*AET)lvZ8nYvrF$E+!lzH4NLrzF0JH*n z@%AC5#C>Ibuu(2?$(2_Wz`Da}`=o?&!#I-rW~H6m&Q;4dbM8vH zKY<5^Qv6f@ZsYB<&%KO1U2<1?6-vV6rhf1I1~>Bq`1lco$bhTEaj}@6n{?ed%?e1d zW9r|(oXib00w@wOux5T;r%2!qYZhO(C5PQ1-jq3H?|FCx+BQzK_?%60x^Q7J*wG^! zdrjO6Z6xHnRj*g+v<~QC0Ueb`cYg)T}= z%Nq+w<0D^&UXJBf7UC-SieJA!@NoX~>`8cLZ$qU@`uh6fq~(f8a$#W|!mJ>m(vEC+ z!^s+#?R2~BvDM;fd1hj^9ziUZ=fu|c(Ukh*<=a@LM{eRQQKZ28{4jI~Xc0ppfM8at zI-6dIqrE{Q3}e7+ot?HgIuMk9j?c)@{t3`vS44U`i)uYQf(gU2fA}MU=XUsu?wVid z3(40lYLzaIScUUJYyA?0c(cY@<~D5I`fuNE;c&$R1!#HrpleNwc+kExKl6wRzssyh zg7q)`GNxVbT(#)sxA|A_QVV;|6A&9K4-IyqXSOeR+;9_S2`BP33y|tyGeIq*ZDG;+ za@D$;(625G?`Q!%D_@+Az}X^UI@{8CZDP64_&Ms=FQtd^*N`DlRi95G8IZjUkM^ zD&QlZ&4S=ZJXxD@iI{LE3?q72p@Rnk(62L(0C8~xi6zuJ4{=s2^c*Co38Jz^T9%_B zWpAo+kFSu^!h-#);)QIQ{Cd>4bhz#OXTbxlsc6DEfz$9=Ud`# z%vSCoZ&gC(wJMly`tLuo1r8f?_3G7EmE_^2406V=(hgmb zT#%`bdCl2XutJ*|%;n}RhM}VJhu45GIO@(xnrK0SPiB~+oW86`dbG1Re}#u6StUF# z4f7KbBau7Y>y3oU5s}N!<$OoV02Tv*89xGyV=s;)t=|h3?m;;*$bB0B6UzL2ZojLm z5@KVivQVhbI-D)X>#HmrvX^7L3^pff>j%D7KRU9${`2QRJUMRvJ?NlXlip-~-l(oW zySXGOVW5YW(PKkF7@jnJ4dG$O^_4E~X08TZhW_1vlL!hTIwOgR!ide+Z9CixUaXjx zBJ=Fgqp!`%%Ogj6fji|z{JN%v$<~IWQjZn{a`O6ftO(=9n?StAqtQNgOblw%TL+R> zBO(1Cy=|WQ7ftY-eHR;CWA6tC5{y8=Q7~4-GLegVn4K*Kjs-9Uy35+WaT7sm21EGQ zG)35!lfFryN1lU_;r7kfFW;?17$yu@Y$3GEu+S`A&2AnsCaLhW+UPfuj@c=B!z`)~sC-mUgB< z3lDtUOE4>EJ-HMcF%dh36Z6$@84{~j1pp05i)bk>+q-_rcfZAm3Oqgi{m1a{GNPDi z-085PMfkR=ImL6wlmp!Lwo5A3{(0_{ggs!}}gd!fVivtDj_A2OHhwz0|>WrVfF zREY0SsoI!p2Oc-bKJ9e=_dLn211nxY@|pHaLuS_<{nOexH*GrMPhe6pchAn`_zco%V*=h9iIh7spc$7Hv-dZVPcZt7Klot(x zNjwLrBRt4ozkZc0+|d^C`2w&19wA|2atbY0`}$3r0x`4ID_ap0GFR_%C(r+fNB)sM zJ%Zu`;tfd@qW~HEK~?lZ@AmOi#hWcZDa8;Sd~?i8{IgucG?V7#Hq;XY?O@yrDXD4z z-ZQG6OOXcx2NP+Ed>u*xx-tCkUag?x499Jd(C$YAv}>fY4s|s|wx6eUOy#2XJpY8B zHOoRud&Xq{EHhnHAXtjlIAsluQ1qj9z)NU3pCXPHKwL1UI#`TYL5M$h#>Phxd@xCt z%+`T61dZ0F19_t;v3appYsu4?lov@EXOonr#d+tP0~b;RN@y-w-Q3JksQhRX%>J%8 zUK&BpGDIqWjyLZ;s%;H2L_A?9rj4?L#jQ%~tr53C=j0TLk~gr%=!mGaFmOfU)t}38 zD!I{iF7w051sxtvvn~-Hc1TjheYd? zFIqQ?4K-S&BUaPoF!Bd4n|wnJBQhRS(Z~B|ueGnFv#k*A1gs4v=Sqy78j5-5AH6sp zeKX*|FdRGAVb8xzeSiuNewb7WK4bDxkM&OONQkl5K~nxgbG@s?47a^Yon_cFW82hf$D+~IGL_QE=g&`ii-F)u0QzLGw{ zsU`74Pi=D?&LtezKEwV}cYK6uq^OUKO$8!e?$CM`y@sq#-~`k>Dk^=0oDWFivy)Fu z)&W@pw*b8)G32k-Dgbh$O_!`RdVIYi4sr$r0lYZ_k@^8J;pq2s4v{Czs$jYPf{t5n z**>UZ0p4*Gd@XW`B5GB}xGHu{2{z5j$B&E8-cR{Wk5=>)1LKih*1P?BNTnTF5(DkL z=g?Y{4V}dnLgj82oExLx%NBAppChQ8(h2*BfH&B~?TG;rlZyY`C3rM|w((Uwr{-Gl)hW>uf zy>WOl>KSYdKJn(zT*bZdrwjfZQyCW%jbT2YRmTb6$}F)yCyO{-jxBWI)1e)ytv?L6 zbQCL1@8ZrtkVzCPTR^DBZB$uYVr+NRdcH;FNBQsj&o;wL` zvDv>=8tV^~^uI;VP;f^zWoCBPT-X#K&RnHve#m2D>rlLl(Ak>ZJ5ugwpUXC$k8{zF^y!M;GriA2es(`HATlsa z6MO4H!x@|0RwNTLtHt@bNr(ql9z9Y|t{jT0;l`1a+Q66;zVy|5gWJmh#*Yv-zGse4Hn6)Ap)``sh5tO=F# zhA-Si5{gcEk_haJ7X-?z78Bw{2P85^KP-_~X^z`hkSRiIYY24FZ{<13)d}}ta6A7W zFDc2@Mo)+E4A|}2P2)`}tkX2PyWPfBzCezh8C|5xQk&wStR%8_ozorQl?vLYtgar6 zwqZ$x4TTj_*jJ+TB!0VOj;TVcsoGNPILx0Pv;%;0SMZ;bUl3v80T` zm|^2T;hRPrDcMraE!(}5idWHh8{d`bu#PI+w8}!=sIEDyG+ueiaWbIC!{1OApauj* zZrepcSt2;pIQe8`eORTPzz|ob3kUN&SIcD1f2TPDO&5{k(1`J~1N%~VevD1Kp|wUO zn&{XTckrw%Cn6CnA2Rat?oQ;8r|g$6!8m1W3>IhU0l__e%7fGvAns~0>ztg>pKA(E z&!?rBS7x1U7{XI69XEY9d#_sgC%cxjB1Xi1EJr3D3)F`?EVbx{m?&YysfyTwDu3t4 zT|)s4XFhys)}y|&&kFb%#w;TGz5RTZWDK}Tq7Q2{x#3Hw`B*>nu%LWTeo9CHy$!ZT zmeM{nNmiyYpVVO19Do!X91{)i|9HyZf{C>J35RbW9rUxLsfZ{H^)NojJM~v5^%|;n zF{u2G%*wQd_DWjcV~58IipE^W9KFjsmBsrX&3ugIB5lDi|Y?M<%QVU`f#`rRxaMI@#Ejgtv zCzWCj+I0V(-FUwj6Z*j07)XlC5djvZnMsu^ID%#60IRUdNsb=#IDY)dxy`&iU#JCY z;&YQ-zBEi{@uC~CGVkb5^|rl;CYE zsjPEtCs7}6TPwZEajSFLx@C8U4H5&l-LX+SvtIH9R{9mb47Vc>@%mIZgYG!=Y6{p+eqyWsR%V`y!<&3%=2ny83%s zxkze6#=6n)&pj>}hD^M9!P#+a{Sp$-ed@jQhtEY>VjmKmwEUm`Rn%6_A5}v7a zn5}%x5)))WPJ=#7{z9wpR+oY>(c?~caSpUNSD_CsaSravYnxy<8J2cO|do7+WCn=QJPgV8(s6M>Gtn!lzQ>_5pm5Mlv*X@<#4X z5&t`7Lan4WY(AH>0!3wLn+!xb`n`kZc6ZVar99eqvsjRW428OBsSJKqL715p3_7}m z>OB6zBCyYpQ-StlplN2l^biEC4=P!hS-AG`Sjy?Li#`*X_8b(-J8{j|Z8Ovjr&+x+ zL`9;4(4Wc`GqMJpGOYr1wg&4;)Fy=vzAKhM1Z23voN;opm@J;{i$fXj?}-(w$VZ6Ml%6mPFiz@?{YvfmcWC)YMvE8k z{-)c`w=S`q!@ZZ)JqxV@v>%>Ms#O+3sR#w^%tsWj(_5D#r{1PnWEvDboqbK6o!R|< zw(|X4rKah$;+S}RuXtLg;feQ3Z|f+utkxQ<1M8QRq4LZC|l)eCPaA`gU|lJfea2wjCN!oZ!_)-s7I}(S!`>G0uJAbr!oS z-VawgOh=`5Il6}Iw)SM%H+382exRHXqjdHcnbs>Q<}Qox#{YLxsl_v}X5n>P>}dXi zueYEq#yIXJ4%ud-PO^PBEH~c(Pr&FwVK4HP#RAkPQO0@S@N51MjeLyf0Ul(7KnX4u zJruGhxWMSaN5M$cW_itfW=m_$>tAB-!-ml^HjGO4{Y_HBcvtW&<%PeH_`e`{`g$kBBtFQ+DjuEtE*qFA}#7{TygWI zN{4PN6~}^Pd5a;X#t(*5b7HEa1`{i$(p9h+kSRjU212yN``ef#iW>%A0|CP|^KuG& z1$b>-DE^6`!QC&8tbc&pZt6R`VLAC$76h|I^*#ZU0-l|TIii*PS^KGx-aVeN`G98L z^!0NTPiNV{Y;$#F^t7NqwR6m@j9V*9KjxqqVfU29ETOb~C^8kL)10%e%-UIt7ddR9 z7AFZZ>m0U$J3DB>yqy9^yFY9$^2>}>^f{l@*k#r$-r@&#d1|x)K5V4nPTy7mX`v65 z4!yWdFgB6C!~S-*O{3AqnKDjQfaUv|hO-%`cD)Em9XI@}cqG_9J;+v~dB7b!EI}e) zRDsVVP{^;~H_L@p_e$Wl-Mhn(u_4iu7U6fhc1&3UYo3nHf^r^YM;TyG^DNWuZ{k6f zL%=D2y7ZWgXieTq?;<=hJTJX2`=s1uu_qKwek#G>(P5;8QD(-rKg}wmTj!lB(YFpC zE^#BUu+~!-%$H~#`tcpE$CdZuAyJ1M!EAd_P*S5y=h8_`L zcOC8BHmH?>f|d+FU}WNmX90kLb&+qmC|aKfnG>pE4Lh5;{Q=dXk?||EhiFMg^jiDS zjrO4)zm(4bzN?Ljl0Xnri)nQ{4o0=iX-22VpktDP5UZs+O68B3+={92)E`%5T8)&< z&K8^cQ;6D+Qz0k!zI59u6kmsWW8D?!c1(RiCjLq;>LB^(P=l^`qsIwmxD(wLrk0ig z)m?hCo}ib;rilv29WBxra-|LB#FHm7-Rehh)j8%1!*oDT$4^9ZqE3;j0)0>*E|T1M zo2)hU4sk*{)a?9PC7N4z88h2yI8b($8RwhXS{A_Jz4^syRxQuJFZ_I{vcVZIr04;0 zEO6JERdl;O)Hh2pc9a{06sj&l<)pk1oCZu%ALKOuy;Q|hb@CiwXcMV3XR!-QhbA4z z+mP_Bet^U%RtOSF%Om6l|I`cpN7n1q2M6W4UO&CKbCntGq{2hvgM+Atnz93o2 z81GF8`H+y|3bFsdy5Qzf7=ia-?XTH+M?md&UO8Z@k-)(Sz9NbBM;;*jzBMM-u3566 z6e^Td2k)PhUwtme{NnPNbNW^?**L5wwh#vICo0uv zO@GPH(Sfy7(ZPWml zyk{E^%m+aJ4FM`~++ZlDU>X&QEmHIKcXpty1X38BE@ho=572nrBl{kt9;#4}PcLeD zW}J+2h3vTEyGe%J$(qK=km%l!)OK-Rrkw!6nhw~yY0NSFc2-)_ociq8cfQG*#%VzX z?&gym6-6|oDx5Ol>`>Q3y%%RFCN4L$wF&u`X7oE@Pzt%~baQ`365zyOGcMua=qUK* z5Jfbor28UzxcEs`8j2IW!-y64f zc};tIs)w(m%#1p*jlIrHoVEcI=^SUDA{vvc84FYAF$qz~6ASgf6d&QgPh`#a#^a(T z0GXt26}r=>+QNb5#yqI5VgvVV?@(D0hUdl8uBP={6!qm`>{P7zuEm=S6-7+eFKKHE z;9y_eL(4kP3~2g6`&cz~t%67@RPxdI>|ER&O3AofLvJ3y7QP1lvAmNYj+>Ztp-VyM z%9Zh#2RUyuSAu{OGt}UaW))1rLusk!-+Hdor+a$XKo3vE5;m16Iwc&2hRP0oj}ULG zLf<&qzpadL(;+rfli}=PRziC%z!<`!xF6g=2nH1?Tl(k z1))*1GC5ynM`HWeq`5b4Va3Bf{at0VHPmm|Y@i#ll)=YCf&8nt*KDbtRMrgAYO-g7 zSH#+QA33iXIbNHom>zN6b~q}D$qi0;^PeM;c6X22I6+5xc!%t4Ru z@g{Va@^k0y(@JyLSBo{n&%G}`ryJsh>rH*pf7&eN6)GHFRK6ZDQ0*&j`$FxU&QhsW zl2PSSQv58gFe(0#HCFslvf8d`LNI;9)66939`Mote34;6f~J4%?F{@|R#7JM# zLHoI5;g4D!PU#aHirfq|Ss$n`JFJ^OC(%A$t_E_<%*Y^eTf;zYk^)q;V)>#h{51HPq z`y&`Xo0%Rar6nIf@NqjwgtG-DGu*zLWp{#uxka{bjr4xSWnB()80I!I=ux~9A?b0G z{@>kEQ~c;KCqk^PyZh_<@^^P3?X0Na#y-xby5PV{HMWTOMmXDS+W$;%K_=bWGl^X~ z^oL>Hq-4n}&9w2qNEIt`b|2@9;bpzhp9>6|i@Y-BSX`B8*spH1|M5|1P|CV5?m;9h zEL=TwmEry1__A?|)c?*SgZ*jPa2WMu@ED*hYg$N|Z+8`y1#UP!A&XzIeK*5pIX+PL(*s5B@V7nij9 za??!25D*rnXSO@|I-E!~-uv)~?#5b%>We*>vPzDhi=$9<#d)Xg!ZR65ExH)rKK@jt z+NEz;7IL9>fl>5~VD4y_JZE!tK>OazK^C*=wmzUZG~wX8!2AKkBiip<$kHvXV=%hl z+p&}G`LqEIgh!2yigSqu{r~eSWM1VkPLXY4p((MP0Eg z#G1Lbh&?w{J~XMc3yFe*&qQ`oCHy%QdR6Aj`#%gC z;eiCl&qX|MRi-}Cd5}^pLuq+4XMb`oP?r7T{dCmsB8a<(o9*jnBF}eMC(ZFiMAR?- zI5XyIa54)>0|YgxJHWVS^r@1WL0_~mfC)OMz$1zX@j@7K0fS@T_Us;7>^lg58f{ME zCga=W__!@3(vPZ{y@s^!q6A6{@D|sbdh_{QB?LJ2?d?ieKY(MJN-myJAje)!VVx^X z@BEu2DSVNE#>A%dbxAD`DC^>OVMr!Ek1g9M5OG*m>*ZD&)kaurdx^Nhkl~3f5g}&O zPAAcC;ub@Uv`)V79EEOzlupOj!8Z9$na3%=Q4}Ma%MYbfC!Uu#xU*KNk*RdTpVFCQRL9&V#0A+1^v-TOLrITTe34%53jwn*U~sfyK{Fls=PK?+ z-DCDx(##STM3*bHG}PSCwI3u&4nB~#yx|I3owO;TdvcOpRi>k>iiCZC?IruCNa-Y5 z$|8mzOU>Q@cBfbCiYPZw`Wg+hw-@j zZHdD+5gm}pp_?9i#Cd;y;_@N$z%l$K06+qcXf@`_=XMG^`9QWRl_hl_~AdT}8LOtCGKjzI4%z zsF-|*b1JSQa*C5C$)5!#r=vNT6$GuCu<7obofhEEl%odz#-dTz>dG`H`_EFx-UImlNJmCb7C_yC0S z241(?C`;70v;?8af$Zskb3`c$gL$p6W%*M;3a%nfB>##efaj2HD*aKu_gei-yLBP2x7mr{P$I<{2JomTQAb zlV$b~k~V`)5`!$YU!3E>F$dZ&1cH*_Tj+&*1f4Yo=T^a8FC3k44wEbQ%%8ZN$+?F$ z&_9hv)ipg?g;bgfL$~+xn}AJh!anCi(r!Kj=kvvG#z~u69VyLORF>m}JLC`>iK(Zo zl2MDg)SMP^3bV(IMBEov@FQ?dj*W7N-5MFVJb$ikR?i@Ujno( z45?h}SA6Zulc&eDGYyN7YXK#x|u-+*)t8v7EPR^=~WAOv*4U(MKMd%EaSDNpQu= zl@~Aw?brBBsMU@&PA3fwg~^U2V&o@1iTOjGLuNCNhyf?Fi8d!r_iU#p?DF6=rEVas zL7Wu9iLa~HnzfbgDb|EZUu3TrNo1q12^IM*kUOJ_2)cj(U6%*3KB*l0@?su~CTlmy zax~5u5rkz&Tq>{Yw2NJ|GsSxi8bhD}j7nn}anWq+mD>Idmzo-LoS5!m$P9bzTm`i# zs;)?t=bxn(WPSE^9F_MtgTDgjHeJ9mu}O`ZFGD{91{GDz>*!0|G;J;;T53p}Io5`b zD(EUmo$lfLJFmf%SS{6Q9vJ`7J}S%MqiNl^t0!Ft;vp22)Dt!<^jMr#^L_I~ZuNiX zuKYXNdRZWL;Y}5$7%$7Nv{-pV32k@T*mJR|1Ak#?ryE2KfP_oorL_rvU~ENM(^rXJ zI&8L1x1Gw{w)sOEi0b4;Jpu~=g?5=$*<=r8EHV3bdipBF8JDVuW0wynU_R6=4Z8N- zwVQc}?=a#Vy&c{`b{3Kaa$;maa0B$$*k_*~{1Zv2#xK04^#I5^A2^KEE68XSDR4Aj z8LfpWq{2pTao*0dTlfwDV1Me1O zEM!t)Z_IU*uNTR4n>ib`N?CRqWYc8KCp)LGra@zmz&F^fxE$I+kkvuI##y6EY*7Ft zf(~Q*WoTuK)o6V7Om4FPYPX-fAI<}EHKXHt#EtUX;>rd*J$d|OYk<3U4rj|f}gxrsEo=~9Rebv;rj^H80mmR zdLWJ)E#Ayyvs%Mb1ef{UeR0H_B{r~GuoShyD9h9f=$9OH$32->|An9Wc;)Dp7`6Ih zwZ0|AGh(Yk(jlXCM`a0_-Qf$77ff)OI806Fe%dtd$WUPzU!eR4wSU_j9s`^Tw_lv{WlED%NUY^ z29#}+KLjAxSJhJpmq5~Gv^$kxih+HOt)CM6wcD>57DlOtbQ&2?O6%8djL)0UT>?=h+jW1wWh=m-u1>cP6Yx<}RM7sBOqK$ql+5S>>oj4?r3?Dx3e`Bq8xh!mTHAf*}b zXn*H>5<;01hYml#r1$R$xv0*S?Nd7cCUVU$uW4f}FZa40uZYx^Ssxl>>gn{0Ux?X> zd@o-A5u5GcV=?JTQh!2J1eRDisX2F`08Dn4wc%@#c}4kXtdZFP7&;86GdYc_j}!9b z40Sa0P;0Knj3o^D@R3Iy$?=p!s^qh2$pYB{e>=1}*SS)~$dN&@g}h`K)-76cLR7ll zskO<^$AlBSm>%UhRGCB&2Zi>`O5#IE>VUXYf9}6OsnDEty18v5Jz_}Dy1MU+BTwNJ z&BM49j*8r7i;rPDzP;O>bOnmKXBt1z2VpH*VbJp05Y4l<4@j0i*BswKVuYQ*l&Fup zp=AubG0XyfjeDV01T+zu6qC`&rD)nge+9Yh?LTjLi2%{`THNS$443Y}e@UB+V1U+r zF-V`D%)`T|Dh2s~lzk>9;-n8j4Z{^) zJAKoH8;nX`y`B<-z@&WlWShVDV7`3UrTO5x#2h=VG0Itn!!FbGTP&CE3r@0CAvsxW z;UKn|U@{l|Y2938>a?NCM<}O2RN?Ah<>Zj4<6MsVnD{(I!^J1BlH~x0+-LrD0k6NA zM9}5iy8AAQBI>Rc4buJc-q3kB?d890`}TsrBsDTI#MzG@55Ic-8a^Q@KTeCy!%%JA zhV^&|s+?WpGVKNk`|Vi6~R{fuZS${KWJ#oU=4 zbIm@@uHn3z#Nfm3g(eEEcVve-`l`DYSg$764x;)J3U-{4Lc)thf!bHU9@_KUh@yKLttz$Yii{$jOL^X$sVnfB#w}%ZBNq|9@J57_3B_-B+Bf&tgHI zASA;bTb`2ILHMT_yk|}SD?sj7ykc;xWP^TUqU3zCdFRhbF9q+OjjciwFS9+0w9QxX zY9~&eFI>JpU8&#Gw1}tV>d5=Km*?q5vF%$b)|Ry8D@-muXH$NQdCN8@JB--V6g~S) zRqK$&mH9}Ua-4kspR5K@8{S{tvr9k(PucetxMdiy>{H;4yz-}qkA=<9eG#lSI{F`^ zr7gk<0#WzbpIp`(x#=~{j)A{IBivt^IoSvZ-JL?(E$QU8_;#MdOxLCR&Tbm^*cP~2xaO7tjgxh% zJ$hC+lyhm_|J{MQ2{C1llQ%bvpCQXKSuAVJ3qs|7n=- z6wy^(a#B<))mYq1LJeQB?cTV91n=SJ+xXV$e;jaEDo`Ms?VX(ZBCGderz~3r8ipib zpxZ#_qNYOYI?=3`XW!FXlh*%PZ=CDIDym;M-|u4<6}*vb|1f!FTx7aFI&RL?a-2>>mr>fOKA~P)n0r)3@H6EeQ)2|#sAwesCK^lw7zM*94~i*R>|UatHV$E zw(HO%H%yC-Rur?hUiERHw6`|xXVTjjy^E%&aYi_1I_lIfb^T9bw1ScP-%r}gN@xBz z-;3q@hiB$U1fdJy`C6gLplQ`k;&J1y`;k zWzmPCrNxB<40^IujAjgb+NtB;){)keG>%oC%7sl^FR2#stV;5@<>9@@r>`=sU@ZG{ z$J1Ood)kxvx{=>!s&Z;zq@BZ+CUw_qq1$0O$zxfIn=kS=&&8HBo~o6%r(O|Ob`5GD zd?UDXxc5Isk|vjs#&RkDE5F_!UZ8kI;7I<`GjA3(&saTpc)-i(j4d(s=~PLj2|bYI zIjr<#bC~PXW-qafvGS3hVcHEM!~T1N!UKJSCZ%Y!xAK1V*2Qt2?V~$~zwBU5ez`ui z?AiG?|EI2W*a{=`jNdQ$WOP78E;H)i$Khrnzx^6lK} za%HqN@SMG~{|~|9do}yg(j2UE{;hw1^=2g z8$G2FOD~o0lCo%DDZFAjY#<e`9D#rnH{M)2h^4>P-RTq|gUxh$DP z34OU0p+oP6t2~U7R^BWYer^>;yU&vExb8}LYbH*ul8c$?SzxK>qgcJmqucV{Y0;Z= z#YEy9w@Aiws+A1!p=deVv#Y@~tACDikjgS}wH6qi3n}Sii+hf2GZ1r2iCB5pa|7$b z&-jwnhE-zos-`u`x(!!sFdZF`J+anhO!skvuDKM1gb+fQW+aGOZWhN0{k{jt;TWgQ zQwiRw%JT+dg!w6ryyU@PhI7n$EAv}}5`0uI4OX1}=KgSb+W-N=cj*x$F(no86~2;F zLzHkf)40r$hk7}|lT+)YXu9V5mi1OYHGO%f7#>`MEkAl_qnpvdZn;$He3S7_lc)fV zlI%&2bl;ORPBqbZg6Vq|IUXFbzPftrZT8@G>QXkVO6HHz)j2kYyk^2(;z(>2ZL%Wr z*z2Pm&xa1BxXmA$W<0@ZqUbE%lino$gt@y3U0s-hnH?oO;N52TIsAp?Eo7?U8C9UR_!l72Pyl(vs%uth; zVczrtLpe>=DVgD)#g(po2TPK67yZdQzO7HKyrTHI*4q!>L%v#H3%Z;}%mlecdhSpE zj5eCd6f1e>`n`KBZf3xL)L zM83qXO>>@X;mTN1`?WuADIKz9O}4L#9LPt+!Z|Qldf0bbCdz%qp>w>bC3>w(HQx@~%9_u2LH9 zzzL7X1svP;BBW)5m+W6H=Uj8~$4ID#yM2rC_twU=)O{aAcTe<-89MZM$+djgc~xgL zn=u#__d%xMYE@KDb$q$I#=rkQ+hpOswq}8>S%d8{(G3Di_6I%jye3~ytnfYld8nE4 zk{bBCY7f0auP~{nm+!Nd$KyA8@2Txx;qq)^Dw<+-)5CxyIkKdUPhu7f8WS%-BHFDP z#uHoHjYMPH0K;~EtH>^X8CuiCf2i2@X%kJfQ?C$F~h^pSYW4xz!U@wi6SxDP5$Cz;^a=)(RtEaIN z^ZHlaJ-5>M*B(zg`n@IEohtBC7$?jIEKC9@Zm#~ zt{JZudsb7zqSn$T2J^mR9tKmP;}+%7!vqo*nr$&Yxr-pkL`Othaq_HUUhiwpeMbXO zsfUj;WEkgL#E3cvv7<}sX6|0h4-KdO5ly3}Ify;~uK6=0KR@|~nd8=LBNjB@32v>% z9I1O6X_9gIH{w3jy%zp(pLqA>vY=ZR<=$J`XiEq?flu=8D(5EO(>^L!pK)u&ypxTV z(yM>L)iG??Ds^mk8`Y(lDdljOxcp^ePsfbm!EZx815fYFeYJ3nSL3LEks+6Owj;FY zLZ=z;^tYWgZVzexfhrfY-<`eBr6bH3cuOtQ@je^?r>6knahsKr?`)$mWNCJYSlWVf_suCe|8q3i@@9?n=kIuXZ>Tp8wIMJbU)(a>I} zFc=uD6EgXEqSdRATKc2{Zh_z4o*+UxkF~$e>j_(RuGrNf{hPFShVAv`LZ52nERJuJ zRNv9G;8sd!lU#VyNea6sy})*>K)u?kt-Br;zun-nE-qZ9wKaE<>FUWYrKfI>d?jq! zOPGla+4{+tntgr>?MXEUFYSC5mHw(d$)$TL1z8kk){49{|`wiS3q{@6642!aD>xl0c+5brLtrUBHEs0got@*gN*5~E=&2k+> z_J`i~eCy3W$4YO=aT(3~d|P=nMeXWahgqhzcPk&AcJ)_TxW&PQW0SjbPkq=w9bD5@ zHQge$E2)_4(OB`dWH#+Nxd<*!o95`zJ&MK>rYe=FnUA=7@oYsl^Dlo&?XWm_^l_nA zR~%cgc`|jnuqw_ss(Mc~P5$xBkC7~AOH*P`>Rb`!%Cq-8r<24Q9jU8`A2Cxy^J43F zYt3*e*f=npJ(0w16AHb{rpdD(UbZ-|<@Ym_%BIeF`HV)5_1DOXI~;!-&lG2$zo^@0 z=@xEI7;noxS)w+Y8$02Z;J+rDBi$tLRg=}`XX`ffp4_+g#8g!E(XM|#-XK?peKhWv zAUs=Jzg@@RPQ}>@ra`INf&8}@)0NGf(0k=@o(sy0(vu!v_n*fC>7=z5y^`yd{#fI3Wyji2;*Wf7)h-u3&v!oj z>&e!dx{#}yq(PQcvdkzgq{tE?q|_-5g|TFt78A-+j*%rqH7&9r=Sz`m9nB9UGK$Ai2O@@? z=u=O(y#0Hddq|R!1CKta+8=w;b@p4xT*R2Z=V*RN#OM#U?+q zb8tBa#Au3fkJL9+8eR3$Xw4c~HZeB1B+{nzLsjtUS>H2(Ij2uW@(kQkpL}iE!G%{m z_{f7#pW7l3o{Xmrbf4VxX0G@bA?d}6!lv4yTfrOMLI-=YEBDY#>ms4F{OAhPmaNFGEz2e?O0r)v@(}am- z#aD4F`%>S8O?@igS+zBz9z|gvTB?jEI+o1})vr4`%6jhVdDo2G+T$2Xt9Za7FI$$Shhv+(fQHm4ScQc( zySJ3cxfljyw8WNQ?TGT8EB_tV<`U5)ypcCfm^tY>$)asx4-0fBg45$m8>96U{L2U1 zl3rX`CcGe=KHRc#MkZkPOT&y)U&kE3CTbi_zg|l?=;vRk6o+e>>r0v_6EqIRj|{Pt zBRu?Ty>$u%lOM*Sl+lZ<%x-=her|kXT zzIkEbg(r{H^E2L?uDsEyE8i?~x^m2J^4w@?B`!Tao*C0Ov5!t#*Su43>K0>=E)qWD z5Y-{@`Y}^B`{|98p&FbP>3~M+&W#g`9h{?J0`5I@XEAp%ka=tWDrWgX$gC+^>%Xh8 z0jE**i+QZ>h56jr;?Ac5on2#JChu2@muJnbWoHRQ-ku8Xsm&aTIh&s&=jO7p_*hU^ zsEbyE~Ts^e6gH$&B&^3VjaR{jcd#v)@N>-+J+~GXpFi=HC9H{tx}E@U?rK zr6ksl*0P#LuDDgMSLibzJv(XtHQs4S`I6e~%9=jc=E#aeODF#+V;r0PZ5(rJOaB-1 z*kg6S0t0T0#B>N)e+@Rqj4k@UXav{qASjPe&*4wZnLHF!vLD?p5xm;ePY+)+XW$mL zG2z=4!Vve!Y(>ZUJ2m5y+4zF=E$VFU1aAAX%Oly{QsKX^O}0G#M>*R`S9tarU8-mH z+*HJ0?=qq$evhzM)Gq3iqOn&9oWj3#$_T0(COGu6XECSdHuJ(X{e*gdSMq26N6VD| z)-wrA7IcaSCjo2(yc3}kCQcR=&i-{xI(w{dQkl(;H~=)v_nnR29dDD#mWMQV6W^tO zgECQpH#oBGmw2k#rKO_{wP@~>+infq{p|xXqq|PdE^(hd9Coi_J-cGF`{PUZ&av1o zl>?OHHxy$a-8fS>|7tBOdOsaKc_76Jm#YL%!TiZS215VM8{Xs_2!<` zUOqefV%SFzW^iI%O_SF<$+14(!1Se=ci3H0y>#TxPQTPx!XD%`L~z>)Tp&>Qw(m(f zp|T4B<6wf)NQ?>zMu*M(@D%G93}1r1CBV{#{E)O)#$U&orKn=WguaN5VqO5q9+&tdeqpQ}jy1IHE5d_Gzy;B0~eTuPRKhBO# ze!bhVcp{t^7B#%OJFIZ+`J)_%$#1*?mG;$$R{A39qpiV0-C1gQ-G-yjt#F0XD~;}~ zKIXO)>|C(m!|XY!In{t~O9eBuomIJy?1)s4K+ov0}^j>~d zux;bPzKQL(lRaui;&*6$t8gv=IRw0i&4-zqYY2~AQn#ohL{i0ARml^5baREvoO9U^ z>#+nADB%u*$lfGqGRBXD^EN<3-?8-9X=^ROX)ce=)%vLZF-RUJMmaAwjq4phx%N$p zYmiT4#+`yNC(9z_>!_Nd+;eH=TkpGX3r}3;2f9sPqPK5iJX#mupE_o&SL|r5xYju& zNQ-p3*rHKtcs@a^AYkI%UcPZA$Hibfp4g~xj|`+=s=EE4cxz^}c?Jx;qbSJMKFF2K7%4 z)Z6F3=(mo2$JVG``UKvrMKCcw5-3$ZJ^s-|87o{$7v&xv{GsBQdB9PIt;^8fE2|ot z`_k)oH_SK26h?ffL0&ssG&={g1<+G(18wdd-4o}eC;z#-=^S8320)(3C2^eL1r6Mo zn9?r-@Xr4mtmTLR3B_WgLPmm-h;WrafEpdvO#H8llCW6Csj1i3aP2zzR(;MIbTVU6 z16lDz)WKV?%YDy00q=m3=aqwY;k9rljK2eDWQPwF-gkpx@bXXBX&9;QAYkJz<{o+C zBm@{_`162O&*MWXr73sGvGRm=@7R@-?yz^OgDx&tP1V*J?EU#e!@X@S&WNtJtYqFl zTadbv5YwLa_`=&Og<71n5ToX)I4hhFbK}Qhm}+n_1m}%Ok#8D{+1(!{vdl4YD}xvM z7AU}AIsTvoEWXK=6orM5BM~EEV;E^9D0Xcx?u^#^l)DID(9t&$f#u-XiubIMgLYc+ z0C$nhk30OU0=d5VFqD+edFxm;upxGN37GFor3M=4(-yqt60P_vR|f6_S88&HQy|8u z3AhcQdZX=iB48cMD<`W6z&<*|d&gUw_ncYQ8;da(0)@w07}3D6G+xD`dHYS5o(axs zUZ~4qlL;Jhv~+?kFt)e@SP-MP(#b!(0E^^TPf0Ro^NpE=!F49f2FB$oiG9_1(=Tl1OA2;USB{4dyP!KQy#ukF3Qo;C{X z*K4cIfyNGKs-d5{40y@4vH3TQvxQDK2QyCm{lAX}_Ag)$JbvCuLlhksnrzs{`+}!u z_=%={nXqi(yN2Y8099@97w;O2#bU&HKq;j5S3n(>+|Vj>PQP>=|&o9PooI>X%% zKXvCjaCgH{6DyFty zXLtH`m55?k%!AB2V8Fm2z%Z7!?)wu5>%8jmnh_6BRw)O0Vqj$Bgig%<+sh=W7Mp~u zy3rXA`djJTxdTXtoh>szUqg2k1>FSflWgx;3;B!#T_oJ|a1aTP#np$>4! zOZe4H%{V=vyT4UiORv~{Zhq}pke$Gi!{oOarwlMYg`Pc=zWQvhV@fe7>7i|7i40U& zps~XGty2RY#*wBR+-Dp)xgRZo9OFMu-}&=Y0tib>^6h&bE0pSLkubdC8K` zTCKI1BQwB}1ah(+RMbx(5aiGU)^5bm)A+va&&{x?A86q8A0!XFN;j}9m@R7}27H{e zJTvzpUpPnJql-$5)BB5bknG{Jm@zWrvmPrjtPvRyjY20Xl>s3`Z|K$ivy>lRAppZD zQ4j#gRhRRsM65MsrgF7FA;}MSJ-FbU^z~r>+sWsH{hgTCm>u6r9oKXLUtc9~T$U># zl&d+d$Iw7kKi}*Cs}|F%|KD%@R00w-KPSQ586L3eE1hfEIpZDo<+d1Q<%`(hf<$XZ zi2|GKQNq>8Zc#*_xx00G!y7edk}I&dn}pD2X%HYH?BHMd@1h#r)Rkznp4E&U?V=Up zD7@3`y7) zk3L93#-ORVVb@u~hp%+%+=v${&lh9{6DhboR_crsc2LpE@GADF?G*B}wa
|4D<=g-j3Y(_cfA2+sKNF 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 literal 0 HcmV?d00001 diff --git a/include/libwebsockets/lws-adopt.h b/include/libwebsockets/lws-adopt.h index a503327b1..94a1818d2 100644 --- a/include/libwebsockets/lws-adopt.h +++ b/include/libwebsockets/lws-adopt.h @@ -152,6 +152,7 @@ typedef struct lws_adopt_desc { const char *vh_prot_name; /**< NULL or vh protocol name to bind raw connection to */ struct lws *parent; /**< NULL or struct lws to attach new_wsi to as a child */ void *opaque; /**< opaque pointer to set on created wsi */ + const char *fi_wsi_name; /**< NULL, or Fault Injection inheritence filter for wsi=string/ context faults */ } lws_adopt_desc_t; /** @@ -249,6 +250,11 @@ lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, * \param parent_wsi: NULL or parent wsi new wsi will be a child of * \param opaque: set created wsi opaque ptr to this * \param retry_policy: NULL for vhost default policy else wsi specific policy + * \param fi_wsi_name: NULL, or string to inherit Fault Injection rules in + * form "wsi=string/rule". "wsi/rule" faults will be + * automatically applied as well. It's done at creation + * time so the rules can, eg, inject faults related to + * creation. * * Either returns new wsi bound to accept_fd, or closes accept_fd and * returns NULL, having cleaned up any new wsi pieces. @@ -257,7 +263,7 @@ LWS_VISIBLE LWS_EXTERN struct lws * lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, int flags, const char *protocol_name, const char *ifname, struct lws *parent_wsi, void *opaque, - const lws_retry_bo_t *retry_policy); + const lws_retry_bo_t *retry_policy, const char *fi_wsi_name); #endif diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 679a7e31f..38de89762 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -206,10 +206,15 @@ struct lws_client_connect_info { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t *fi; + lws_fi_ctx_t fic; /**< Attach external Fault Injection context to the client wsi, * hierarchy is wsi -> vhost -> context */ #endif + /* for convenience, available when FI disabled in build */ + const char *fi_wsi_name; + /**< specific Fault Injection namespace name for wsi created for this + * connection, allows targeting by "wsi=XXX/..." if you give XXX here. + */ uint16_t keep_warm_secs; /**< 0 means 5s. If the client connection to the endpoint becomes idle, diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 3e0057154..ee7d57dae 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -810,17 +810,9 @@ struct lws_context_creation_info { */ #endif /* PEER_LIMITS */ -#if defined(LWS_WITH_UDP) - uint8_t udp_loss_sim_tx_pc; - /**< CONTEXT: percentage of udp writes we could have performed - * to instead not do, in order to simulate and test udp retry flow */ - uint8_t udp_loss_sim_rx_pc; - /**< CONTEXT: percentage of udp reads we actually received - * to make disappear, in order to simulate and test udp retry flow */ -#endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t *fi; + lws_fi_ctx_t fic; /**< CONTEXT | VHOST: attach external Fault Injection context to the * lws_context or vhost. If creating the context + default vhost in * one step, only the context binds to \p fi. When creating a vhost diff --git a/include/libwebsockets/lws-fault-injection.h b/include/libwebsockets/lws-fault-injection.h index 8f46f0efe..6f8e1aa81 100644 --- a/include/libwebsockets/lws-fault-injection.h +++ b/include/libwebsockets/lws-fault-injection.h @@ -24,13 +24,54 @@ * Fault injection api if built with LWS_WITH_SYS_FAULT_INJECTION */ +typedef struct lws_xos { + uint64_t s[4]; +} lws_xos_t; + +/** + * lws_xos_init() - seed xoshiro256 PRNG + * + * \param xos: the prng state object to initialize + * \param seed: the 64-bit seed + * + * Initialize PRNG \xos with the starting state represented by \p seed + */ +LWS_VISIBLE LWS_EXTERN void +lws_xos_init(struct lws_xos *xos, uint64_t seed); + +/** + * lws_xos() - get next xoshiro256 PRNG result and update state + * + * \param xos: the PRNG state to use + * + * Returns next 64-bit PRNG result. These are cheap to get, + * quite a white noise sequence, and completely deterministic + * according to the seed it was initialized with. + */ +LWS_VISIBLE LWS_EXTERN uint64_t LWS_WARN_UNUSED_RESULT +lws_xos(struct lws_xos *xos); + +/** + * lws_xos_percent() - return 1 a given percent of the time on average + * + * \param xos: the PRNG state to use + * \param percent: chance in 100 of returning 1 + * + * Returns 1 if next random % 100 is < \p percent, such that + * 100 always returns 1, 0 never returns 1, and the chance linearly scales + * inbetween + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_xos_percent(struct lws_xos *xos, int percent); + #if defined(LWS_WITH_SYS_FAULT_INJECTION) enum { LWSFI_ALWAYS, LWSFI_DETERMINISTIC, /* do .count injections after .pre then stop */ - LWSFI_PROBABILISTIC, /* .prob1 / .prob2 chance of injection */ + LWSFI_PROBABILISTIC, /* .pre % chance of injection */ LWSFI_PATTERN, /* use .count bits in .pattern after .pre */ + LWSFI_PATTERN_ALLOC, /* as _PATTERN, but .pattern is malloc'd */ }; typedef struct lws_fi { @@ -44,8 +85,8 @@ typedef struct lws_fi { typedef struct lws_fi_ctx { lws_dll2_owner_t fi_owner; + struct lws_xos xos; const char *name; - struct lws_fi_ctx *parent; } lws_fi_ctx_t; /** @@ -65,7 +106,7 @@ typedef struct lws_fi_ctx { * If LWS_WITH_SYS_FAULT_INJECTION is not defined, then this always return 0. */ LWS_VISIBLE LWS_EXTERN int -lws_fi(lws_fi_ctx_t *fic, const char *fi_name); +lws_fi(const lws_fi_ctx_t *fic, const char *fi_name); /** * lws_fi_add() - add an allocated copy of fault injection to a context @@ -74,7 +115,7 @@ lws_fi(lws_fi_ctx_t *fic, const char *fi_name); * \param fi: the fault injection details * * This allocates a copy of \p fi and attaches it to the fault injection context - * \p fic. + * \p fic. \p fi can go out of scope after this safely. */ LWS_VISIBLE LWS_EXTERN int lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi); @@ -91,6 +132,35 @@ lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi); LWS_VISIBLE LWS_EXTERN void lws_fi_remove(lws_fi_ctx_t *fic, const char *name); +/** + * lws_fi_import() - transfers all the faults from one context to another + * + * \param fic_dest: the fault context to receive the faults + * \param fic_src: the fault context that will be emptied out into \p fic_dest + * + * This is used to initialize created object fault injection contexts from + * the caller. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src); + +/** + * lws_fi_inherit_copy() - attach copies of matching fault injection objects to dest + * + * \param fic_dest: destination Fault Injection context + * \param fic_src: parent fault context that may contain matching rules + * \param scope: the name of the path match required, eg, "vh" + * \param value: the dynamic name of our match, eg, "myvhost" + * + * If called with scope "vh" and value "myvhost", then matches faults starting + * "vh=myvhost/", strips that part of the name if it matches and makes a copy + * of the rule with the modified name attached to the destination Fault Injection + * context. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src, + const char *scope, const char *value); + /** * lws_fi_destroy() - removes all allocated fault injection entries * @@ -101,7 +171,44 @@ lws_fi_remove(lws_fi_ctx_t *fic, const char *name); * not usually directly allocated. */ LWS_VISIBLE LWS_EXTERN void -lws_fi_destroy(lws_fi_ctx_t *fic); +lws_fi_destroy(const lws_fi_ctx_t *fic); + +/** + * lws_fi_deserialize() - adds fault in string form to Fault Injection Context + * + * \p fic: the fault injection context + * \p sers: the string serializing the desired fault details + * + * This turns a string like "ss=captive_portal_detect/wsi/dnsfail(10%)" into + * a fault injection struct added to the fault injection context \p fic + * + * You can prepare the context creation info .fic with these before creating + * the context, and use namespace paths on those to target other objects. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers); + +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_wsi_fi(struct lws *wsi, const char *name); +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_context_fi(struct lws_context *ctx, const char *name); + +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_ss_handle; +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name); +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) +struct lws_sspc_handle; +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name); +#endif +#endif + +#define lws_fi_user_wsi_fi(_wsi, _name) _lws_fi_user_wsi_fi(_wsi, _name) +#define lws_fi_user_context_fi(_ctx, _name) _lws_fi_user_context_fi(_ctx, _name) +#define lws_fi_user_ss_fi(_h, _name) _lws_fi_user_ss_fi(_h, _name) +#define lws_fi_user_sspc_fi(_h, _name) _lws_fi_user_sspc_fi(_h, _name) #else @@ -111,5 +218,12 @@ lws_fi_destroy(lws_fi_ctx_t *fic); */ #define lws_fi(_fi_name, _fic) (0) +#define lws_fi_destroy(_x) +#define lws_fi_inherit_copy(_a, _b, _c, _d) +#define lws_fi_deserialize(_x, _y) +#define lws_fi_user_wsi_fi(_wsi, _name) (0) +#define lws_fi_user_context_fi(_wsi, _name) (0) +#define lws_fi_user_ss_fi(_h, _name) (0) +#define lws_fi_user_sspc_fi(_h, _name) (0) #endif diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index b853a2c45..17a4b3bd6 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index fa12014f3..eac12e79a 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -61,6 +61,7 @@ #define lws_ss_change_handlers lws_sspc_change_handlers #define lws_smd_ss_rx_forward lws_smd_sspc_rx_forward #define lws_ss_tag lws_sspc_tag +#define _lws_fi_user_ss_fi _lws_fi_user_sspc_fi #endif diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index d00cc00f3..718c5cda9 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -354,7 +354,7 @@ typedef struct lws_ss_info { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t *fi; + lws_fi_ctx_t fic; /**< Attach external Fault Injection context to the stream, hierarchy * is ss->context */ #endif diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 98c92d348..fc3f205ba 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -115,7 +115,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi, const char *de static struct lws * lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, const char *vh_prot_name, struct lws *parent, - void *opaque) + void *opaque, const char *fi_wsi_name) { struct lws_context *context = vh->context; struct lws_context_per_thread *pt; @@ -139,6 +139,15 @@ lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, return NULL; } + /* bring in specific fault injection rules early */ + lws_fi_inherit_copy(&new_wsi->fic, &context->fic, "wsi", fi_wsi_name); + + if (lws_fi(&new_wsi->fic, "createfail")) { + lws_fi_destroy(&new_wsi->fic); + lws_context_unlock(vh->context); + return NULL; + } + new_wsi->a.opaque_user_data = opaque; pt = &context->pt[(int)new_wsi->tsi]; @@ -201,6 +210,8 @@ bail: if (new_wsi->user_space) lws_free(new_wsi->user_space); + lws_fi_destroy(&new_wsi->fic); + lws_vhost_unbind_wsi(new_wsi); lws_free(new_wsi); @@ -509,7 +520,7 @@ lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info) new_wsi = lws_adopt_descriptor_vhost1(info->vh, info->type, info->vh_prot_name, info->parent, - info->opaque); + info->opaque, info->fi_wsi_name); if (!new_wsi) { if (info->type & LWS_ADOPT_SOCKET) compatible_close(info->fd.sockfd); @@ -772,7 +783,7 @@ struct lws * lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, int flags, const char *protocol_name, const char *ifname, struct lws *parent_wsi, void *opaque, - const lws_retry_bo_t *retry_policy) + const lws_retry_bo_t *retry_policy, const char *fi_wsi_name) { #if !defined(LWS_PLAT_OPTEE) struct lws *wsi; @@ -782,8 +793,10 @@ lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, /* create the logical wsi without any valid fd */ - wsi = lws_adopt_descriptor_vhost1(vhost, LWS_ADOPT_SOCKET | LWS_ADOPT_RAW_SOCKET_UDP, - protocol_name, parent_wsi, opaque); + wsi = lws_adopt_descriptor_vhost1(vhost, LWS_ADOPT_SOCKET | + LWS_ADOPT_RAW_SOCKET_UDP, + protocol_name, parent_wsi, opaque, + fi_wsi_name); if (!wsi) { lwsl_err("%s: udp wsi creation failed\n", __func__); goto bail; diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c index edc4b9a5b..4c632b504 100644 --- a/lib/core-net/client/connect.c +++ b/lib/core-net/client/connect.c @@ -86,7 +86,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) struct lws *wsi, *safe = NULL; const struct lws_protocols *p; const char *cisin[CIS_COUNT]; - struct lws_vhost *vh; + struct lws_vhost *vh, *v; int #if LWS_MAX_SMP > 1 tid = 0, @@ -151,15 +151,41 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) vh = vh->vhost_next; } +#if defined(LWS_WITH_SECURE_STREAMS) + /* any of these imply we are a client wsi bound to an SS, which + * implies our opaque user ptr is the ss (or sspc if PROXY_LINK) handle + */ + wsi->for_ss = !!(i->ssl_connection & (LCCSCF_SECSTREAM_CLIENT | LCCSCF_SECSTREAM_PROXY_LINK | LCCSCF_SECSTREAM_PROXY_ONWARD)); + wsi->client_bound_sspc = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_LINK); /* so wsi close understands need to remove sspc ptr to wsi */ + wsi->client_proxy_onward = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_ONWARD); +#endif + #if defined(LWS_WITH_SYS_FAULT_INJECTION) - wsi->fi.name = "wsi"; - wsi->fi.parent = &vh->fi; - if (i->fi) + wsi->fic.name = "wsi"; + if (i->fic.fi_owner.count) /* - * This moves all the lws_fi_t from info->fi to the vhost fi, + * This moves all the lws_fi_t from i->fi to the vhost fi, * leaving it empty */ - lws_fi_import(&wsi->fi, i->fi); + lws_fi_import(&wsi->fic, &i->fic); + + lws_fi_inherit_copy(&wsi->fic, &i->context->fic, "wsi", i->fi_wsi_name); + + if (lws_fi(&wsi->fic, "createfail")) + goto bail; + +#if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + if (wsi->client_bound_sspc) { + lws_sspc_handle_t *fih = (lws_sspc_handle_t *)i->opaque_user_data; + lws_fi_inherit_copy(&wsi->fic, &fih->fic, "wsi", NULL); + } +#endif + if (wsi->for_ss) { + lws_ss_handle_t *fih = (lws_ss_handle_t *)i->opaque_user_data; + lws_fi_inherit_copy(&wsi->fic, &fih->fic, "wsi", NULL); + } +#endif #endif /* @@ -187,7 +213,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) wsi->conn_validity_wakesuspend = 1; if (!i->vhost) { - struct lws_vhost *v = i->context->vhost_list; + v = i->context->vhost_list; if (!v) { /* coverity */ lwsl_err("%s: no vhost\n", __func__); @@ -195,9 +221,15 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) } if (!strcmp(v->name, "system")) v = v->vhost_next; - lws_vhost_bind_wsi(v, wsi); } else - lws_vhost_bind_wsi(i->vhost, wsi); + v = i->vhost; + + lws_vhost_bind_wsi(v, wsi); + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + /* additionally inerit from vhost we bound to */ + lws_fi_inherit_copy(&wsi->fic, &v->fic, "wsi", i->fi_wsi_name); +#endif if (!wsi->a.vhost) { lwsl_err("%s: No vhost in the context\n", __func__); @@ -332,12 +364,6 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) i->opaque_user_data; #if defined(LWS_WITH_SECURE_STREAMS) - /* any of these imply we are a client wsi bound to an SS, which - * implies our opaque user ptr is the ss (or sspc if PROXY_LINK) handle - */ - wsi->for_ss = !!(i->ssl_connection & (LCCSCF_SECSTREAM_CLIENT | LCCSCF_SECSTREAM_PROXY_LINK | LCCSCF_SECSTREAM_PROXY_ONWARD)); - wsi->client_bound_sspc = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_LINK); /* so wsi close understands need to remove sspc ptr to wsi */ - wsi->client_proxy_onward = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_ONWARD); if (wsi->for_ss) { /* it's related to ss... the options are @@ -515,6 +541,7 @@ bail1: lws_free_set_NULL(wsi->stash); bail: + lws_fi_destroy(&wsi->fic); lws_free(wsi); #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) bail2: diff --git a/lib/core-net/client/connect2.c b/lib/core-net/client/connect2.c index 97d619c0b..f1526551d 100644 --- a/lib/core-net/client/connect2.c +++ b/lib/core-net/client/connect2.c @@ -64,7 +64,10 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result) #endif wsi->dns_reachability = 0; - n = getaddrinfo(ads, NULL, &hints, result); + if (lws_fi(&wsi->fic, "dnsfail")) + n = EAI_FAIL; + else + n = getaddrinfo(ads, NULL, &hints, result); #if defined(LWS_WITH_CONMON) wsi->conmon.ciu_dns = (lws_conmon_interval_us_t) @@ -99,7 +102,7 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result) lws_snprintf(buckname, sizeof(buckname), "dns=\"unreachable %d\"", n); lws_metrics_hist_bump_priv_wsi(wsi, mth_conn_failures, buckname); #endif - lwsl_notice("%s: asking to recheck CPD in 1s\n", __func__); + lwsl_debug("%s: asking to recheck CPD in 1s\n", __func__); lws_system_cpd_start_defer(wsi->a.context, LWS_US_PER_SEC); } @@ -340,7 +343,10 @@ solo: #else /* this is either FAILED, CONTINUING, or already called connect_4 */ - n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads, + if (lws_fi(&wsi->fic, "dnsfail")) + return lws_client_connect_3_connect(wsi, NULL, NULL, -4, NULL); + else + n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads, LWS_ADNS_RECORD_A, lws_client_connect_3_connect, wsi, NULL); diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index 38d127b13..0236510fa 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -151,6 +151,9 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, lws_dns_sort_t *curr; ssize_t plen = 0; lws_dll2_t *d; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + int cfail; +#endif int m; /* @@ -433,7 +436,14 @@ ads_known: #endif wsi->socket_is_permanently_unusable = 0; - m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, (unsigned int)n); + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + cfail = lws_fi(&wsi->fic, "connfail"); + if (cfail) + m = -1; + else +#endif + m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, (unsigned int)n); #if defined(LWS_WITH_CONMON) wsi->conmon_datum = lws_now_usecs(); @@ -450,6 +460,12 @@ ads_known: int errno_copy = LWS_ERRNO; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + if (cfail) + /* fake an abnormal, fatal situation */ + errno_copy = 999; +#endif + lwsl_debug("%s: connect: errno: %d\n", __func__, errno_copy); if (errno_copy && @@ -481,10 +497,10 @@ ads_known: lws_sa46_write_numeric_address(&wsi->sa46_peer, nads, sizeof(nads)); - lwsl_info("%s: Connect failed: %s port %d\n", __func__, - nads, port); wsi->sa46_peer.sa4.sin_family = 0; + lwsl_info("%s: Connect failed: %s port %d (errno %d)\n", + __func__, nads, port, errno_copy); #if defined(LWS_WITH_UNIX_SOCK) } #endif diff --git a/lib/core-net/close.c b/lib/core-net/close.c index c58f6e3c3..a86c3b589 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -831,7 +831,7 @@ __lws_close_free_wsi_final(struct lws *wsi) #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_destroy(&wsi->fi); + lws_fi_destroy(&wsi->fic); #endif __lws_wsi_remove_from_sul(wsi); diff --git a/lib/core-net/output.c b/lib/core-net/output.c index 72d1de0dc..a8ff396ad 100644 --- a/lib/core-net/output.c +++ b/lib/core-net/output.c @@ -114,7 +114,11 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) /* nope, send it on the socket directly */ - m = (unsigned int)lws_ssl_capable_write(wsi, buf, n); + if (lws_fi(&wsi->fic, "sendfail")) + m = (unsigned int)LWS_SSL_CAPABLE_ERROR; + else + m = (unsigned int)lws_ssl_capable_write(wsi, buf, n); + lwsl_info("%s: ssl_capable_write (%d) says %d\n", __func__, n, m); /* something got written, it can have been truncated now */ @@ -329,20 +333,11 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, size_t len) #if defined(LWS_WITH_UDP) if (lws_wsi_is_udp(wsi)) { - if (wsi->a.context->udp_loss_sim_tx_pc) { - uint16_t u16; - /* - * We should randomly drop some of these - */ - if (lws_get_random(wsi->a.context, &u16, 2) == 2 && - ((u16 * 100) / 0xffff) <= - wsi->a.context->udp_loss_sim_tx_pc) { - lwsl_warn("%s: dropping udp tx\n", __func__); - /* pretend it was sent */ - n = (int)(ssize_t)len; - goto post_send; - } + if (lws_fi(&wsi->fic, "udp_tx_loss")) { + /* pretend it was sent */ + n = (int)(ssize_t)len; + goto post_send; } if (lws_has_buffered_out(wsi)) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 126f6baa0..d933f0e86 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -469,7 +469,7 @@ struct lws_vhost { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fi; + lws_fi_ctx_t fic; /**< Fault Injection ctx for the vhost, hierarchy vhost->context */ #endif @@ -693,7 +693,7 @@ struct lws { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fi; + lws_fi_ctx_t fic; /**< Fault Injection ctx for the wsi, hierarchy wsi->vhost->context */ #endif diff --git a/lib/core-net/route.c b/lib/core-net/route.c index dd44d2fcb..efe08ba1b 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -159,9 +159,14 @@ _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flag void _lws_route_table_empty(struct lws_context_per_thread *pt) { + + if (!pt->context) + return; + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, lws_dll2_get_head(&pt->context->routing_table)) { lws_route_t *rou = lws_container_of(d, lws_route_t, list); + lws_dll2_remove(&rou->list); lws_free(rou); diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index 529cc95f3..be48f1324 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -559,14 +559,16 @@ lws_create_vhost(struct lws_context *context, #endif int n; - - vh = lws_zalloc(sizeof(*vh) + if (lws_fi(&info->fic, "vh_create_oom")) + vh = NULL; + else + vh = lws_zalloc(sizeof(*vh) #if defined(LWS_WITH_EVENT_LIBS) + context->event_loop_ops->evlib_size_vh #endif , __func__); if (!vh) - return NULL; + goto early_bail; #if defined(LWS_WITH_EVENT_LIBS) vh->evlib_vh = (void *)&vh[1]; @@ -599,14 +601,17 @@ lws_create_vhost(struct lws_context *context, info->iface ? info->iface : "", info->port); #if defined(LWS_WITH_SYS_FAULT_INJECTION) - vh->fi.name = "vh"; - vh->fi.parent = &context->fi; - if (info->fi) + vh->fic.name = "vh"; + if (info->fic.fi_owner.count) /* * This moves all the lws_fi_t from info->fi to the vhost fi, * leaving it empty */ - lws_fi_import(&vh->fi, info->fi); + lws_fi_import(&vh->fic, &info->fic); + + lws_fi_inherit_copy(&vh->fic, &context->fic, "vh", vh->name); + if (lws_fi(&vh->fic, "vh_create_oom")) + goto bail; #endif #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) @@ -725,16 +730,19 @@ lws_create_vhost(struct lws_context *context, * - the ones that came from plugins * - his user protocols */ - lwsp = lws_zalloc(sizeof(struct lws_protocols) * + + if (lws_fi(&vh->fic, "vh_create_pcols_oom")) + lwsp = NULL; + else + lwsp = lws_zalloc(sizeof(struct lws_protocols) * ((unsigned int)vh->count_protocols + (unsigned int)abs_pcol_count + (unsigned int)sec_pcol_count + (unsigned int)context->plugin_protocol_count + - (unsigned int)fx + 1), - "vhost-specific plugin table"); + (unsigned int)fx + 1), "vh plugin table"); if (!lwsp) { lwsl_err("OOM\n"); - return NULL; + goto bail; } /* @@ -923,7 +931,10 @@ lws_create_vhost(struct lws_context *context, #ifdef LWS_WITH_ACCESS_LOG if (info->log_filepath) { - vh->log_fd = lws_open(info->log_filepath, + if (lws_fi(&vh->fic, "vh_create_access_log_open_fail")) + vh->log_fd = (int)LWS_INVALID_FILE; + else + vh->log_fd = lws_open(info->log_filepath, O_CREAT | O_APPEND | O_RDWR, 0600); if (vh->log_fd == (int)LWS_INVALID_FILE) { lwsl_err("unable to open log filepath %s\n", @@ -940,17 +951,22 @@ lws_create_vhost(struct lws_context *context, } else vh->log_fd = (int)LWS_INVALID_FILE; #endif - if (lws_context_init_server_ssl(info, vh)) { + if (lws_fi(&vh->fic, "vh_create_ssl_srv") || + lws_context_init_server_ssl(info, vh)) { lwsl_err("%s: lws_context_init_server_ssl failed\n", __func__); goto bail1; } - if (lws_context_init_client_ssl(info, vh)) { + if (lws_fi(&vh->fic, "vh_create_ssl_cli") || + lws_context_init_client_ssl(info, vh)) { lwsl_err("%s: lws_context_init_client_ssl failed\n", __func__); goto bail1; } #if defined(LWS_WITH_SERVER) lws_context_lock(context, __func__); - n = _lws_vhost_init_server(info, vh); + if (lws_fi(&vh->fic, "vh_create_srv_init")) + n = -1; + else + n = _lws_vhost_init_server(info, vh); lws_context_unlock(context); if (n < 0) { lwsl_err("init server failed\n"); @@ -978,7 +994,8 @@ lws_create_vhost(struct lws_context *context, /* for the case we are adding a vhost much later, after server init */ if (context->protocol_init_done) - if (lws_protocol_init(context)) { + if (lws_fi(&vh->fic, "vh_create_protocol_init") || + lws_protocol_init(context)) { lwsl_err("%s: lws_protocol_init failed\n", __func__); goto bail1; } @@ -990,10 +1007,13 @@ bail1: return NULL; -#ifdef LWS_WITH_ACCESS_LOG bail: + __lws_lc_untag(&vh->lc); + lws_fi_destroy(&vh->fic); lws_free(vh); -#endif + +early_bail: + lws_fi_destroy(&info->fic); return NULL; } @@ -1449,7 +1469,7 @@ __lws_vhost_destroy2(struct lws_vhost *vh) lws_dll2_remove(&vh->vh_being_destroyed_list); #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_destroy(&vh->fi); + lws_fi_destroy(&vh->fic); #endif __lws_lc_untag(&vh->lc); diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index ec1d5abfc..5bd30aaa7 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -240,6 +240,18 @@ __lws_wsi_create_with_role(struct lws_context *context, int tsi, // lwsl_debug("%s: tsi %d: role: %s\n", __func__, tsi, // ops ? ops->name : "none"); +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_xos_init(&wsi->fic.xos, lws_xos(&context->fic.xos)); +#endif + + lws_fi_inherit_copy(&wsi->fic, &context->fic, "wsi", NULL); + + if (lws_fi(&wsi->fic, "createfail")) { + lws_fi_destroy(&wsi->fic); + lws_free(wsi); + return NULL; + } + return wsi; } diff --git a/lib/core/context.c b/lib/core/context.c index 3ca945f56..78ab969c5 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -323,6 +323,9 @@ static const char * const opts_str = #if defined(LWS_WITH_MBEDTLS) "MbedTLS " #endif +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + "FLTINJ " +#endif #if defined(LWS_WITH_SYS_ASYNC_DNS) "ASYNC_DNS " #endif @@ -399,6 +402,9 @@ lws_create_context(const struct lws_context_creation_info *info) char fatal_exit_defer = 0; #endif + if (lws_fi(&info->fic, "ctx_createfail1")) + goto early_bail; + if (lpf) { lpf+= 2; #if defined(LWS_WITH_SYS_ASYNC_DNS) @@ -424,7 +430,7 @@ lws_create_context(const struct lws_context_creation_info *info) lwsl_notice("%s%s\n", opts_str, s); if (lws_plat_context_early_init()) - return NULL; + goto early_bail; #if defined(LWS_WITH_NETWORK) if (info->count_threads) @@ -482,7 +488,7 @@ lws_create_context(const struct lws_context_creation_info *info) map[n].name, NULL, NULL)) ok = 1; - if (!ok) { + if (!ok || lws_fi(&info->fic, "ctx_createfail_plugin_init")) { lwsl_err("%s: failed to load %s\n", __func__, map[n].name); goto bail; @@ -493,7 +499,8 @@ lws_create_context(const struct lws_context_creation_info *info) fatal_exit_defer = !!info->foreign_loops; #endif - if (!evlib_plugin_list) { + if (!evlib_plugin_list || + lws_fi(&info->fic, "ctx_createfail_evlib_plugin")) { lwsl_err("%s: unable to load evlib plugin %s\n", __func__, map[n].name); @@ -570,7 +577,7 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* not with ev plugins */ - if (!plev) + if (!plev || lws_fi(&info->fic, "ctx_createfail_evlib_sel")) goto fail_event_libs; #if defined(LWS_WITH_NETWORK) @@ -581,9 +588,12 @@ lws_create_context(const struct lws_context_creation_info *info) #endif context = lws_zalloc(size, "context"); - if (!context) { - lwsl_err("No memory for websocket context\n"); - return NULL; + if (!context || lws_fi(&info->fic, "ctx_createfail_oom_ctx")) { +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_free(context); +#endif + lwsl_err("No memory for lws_context\n"); + goto early_bail; } #if defined(LWS_WITH_NETWORK) @@ -609,13 +619,13 @@ lws_create_context(const struct lws_context_creation_info *info) context->pt_serv_buf_size = (unsigned int)s1; #if defined(LWS_WITH_SYS_FAULT_INJECTION) - context->fi.name = "ctx"; - if (info->fi) + context->fic.name = "ctx"; + if (info->fic.fi_owner.count) /* * This moves all the lws_fi_t from info->fi to the context fi, * leaving it empty, so no injection added to default vhost */ - lws_fi_import(&context->fi, info->fi); + lws_fi_import(&context->fic, &info->fic); #endif @@ -635,16 +645,6 @@ lws_create_context(const struct lws_context_creation_info *info) #endif #endif -#if defined(LWS_WITH_UDP) - context->udp_loss_sim_tx_pc = info->udp_loss_sim_tx_pc; - context->udp_loss_sim_rx_pc = info->udp_loss_sim_rx_pc; - - if (context->udp_loss_sim_tx_pc || context->udp_loss_sim_rx_pc) - lwsl_warn("%s: simulating udp loss tx: %d%%, rx: %d%%\n", - __func__, context->udp_loss_sim_tx_pc, - context->udp_loss_sim_rx_pc); -#endif - #if defined(LWS_WITH_NETWORK) context->lcg[LWSLCG_WSI].tag_prefix = "wsi"; context->lcg[LWSLCG_VHOST].tag_prefix = "vh"; @@ -800,8 +800,9 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* if he gave us names, set the uid / gid */ - if (lws_plat_drop_app_privileges(context, 0)) - goto bail; + if (lws_plat_drop_app_privileges(context, 0) || + lws_fi(&context->fic, "ctx_createfail_privdrop")) + goto free_context_fail2; #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) #if defined(LWS_WITH_MBEDTLS) @@ -900,7 +901,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (n == -1) { lwsl_err("Get RLIMIT_NOFILE failed!\n"); - goto free_context_fail; + goto free_context_fail2; } context->max_fds = (unsigned int)rt.rlim_cur; #else @@ -920,11 +921,12 @@ lws_create_context(const struct lws_context_creation_info *info) context->max_fds = (unsigned int)l; } #endif - if ((int)context->max_fds < 0) { + if ((int)context->max_fds < 0 || + lws_fi(&context->fic, "ctx_createfail_maxfds")) { lwsl_err("%s: problem getting process max files\n", __func__); - goto free_context_fail; + goto free_context_fail2; } #endif @@ -1094,7 +1096,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (!info->ka_interval && info->ka_time > 0) { lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); - return NULL; + goto free_context_fail; } #if defined(LWS_WITH_PEER_LIMITS) @@ -1120,9 +1122,13 @@ lws_create_context(const struct lws_context_creation_info *info) n = (int)(sizeof(struct lws_pollfd) * context->count_threads * context->fd_limit_per_thread); context->pt[0].fds = lws_zalloc((unsigned int)n, "fds table"); - if (context->pt[0].fds == NULL) { + if (context->pt[0].fds == NULL || + lws_fi(&context->fic, "ctx_createfail_oom_fds")) { +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_free(context->pt[0].fds); +#endif lwsl_err("OOM allocating %d fds\n", context->max_fds); - goto bail; + goto free_context_fail; } #endif @@ -1163,14 +1169,21 @@ lws_create_context(const struct lws_context_creation_info *info) * loop and if libuv, have to take care about how to unpick them... */ - if (lws_plat_init(context, info)) + if (lws_plat_init(context, info) || + lws_fi(&context->fic, "ctx_createfail_plat_init")) goto bail_libuv_aware; #if defined(LWS_WITH_NETWORK) + + if (lws_fi(&context->fic, "ctx_createfail_evlib_init")) + goto bail_libuv_aware; + if (context->event_loop_ops->init_context) if (context->event_loop_ops->init_context(context, info)) goto bail_libuv_aware; + if (lws_fi(&context->fic, "ctx_createfail_evlib_pt")) + goto bail_libuv_aware; if (context->event_loop_ops->init_pt) for (n = 0; n < context->count_threads; n++) { @@ -1255,7 +1268,10 @@ lws_create_context(const struct lws_context_creation_info *info) ii.pprotocols = pp; ii.port = CONTEXT_PORT_NO_LISTEN; - vh = lws_create_vhost(context, &ii); + if (lws_fi(&context->fic, "ctx_createfail_sys_vh")) + vh = NULL; + else + vh = lws_create_vhost(context, &ii); if (!vh) { lwsl_err("%s: failed to create system vhost\n", __func__); @@ -1264,7 +1280,8 @@ lws_create_context(const struct lws_context_creation_info *info) context->vhost_system = vh; - if (lws_protocol_init_vhost(vh, NULL)) { + if (lws_protocol_init_vhost(vh, NULL) || + lws_fi(&context->fic, "ctx_createfail_sys_vh_init")) { lwsl_err("%s: failed to init system vhost\n", __func__); goto bail_libuv_aware; } @@ -1309,15 +1326,17 @@ lws_create_context(const struct lws_context_creation_info *info) * if he's not saying he'll make his own vhosts later then act * compatibly and make a default vhost using the data in the info */ - if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) - if (!lws_create_vhost(context, info)) { + if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) { + if (!lws_create_vhost(context, info) || + lws_fi(&context->fic, "ctx_createfail_def_vh")) { lwsl_err("Failed to create default vhost\n"); #if defined(LWS_WITH_PEER_LIMITS) lws_free_set_NULL(context->pl_hash_table); #endif - goto fail_clean_pipes; + goto bail; } + } #if defined(LWS_WITH_SECURE_STREAMS) @@ -1330,16 +1349,25 @@ lws_create_context(const struct lws_context_creation_info *info) assert(lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)); - if (lws_ss_policy_parse_begin(context, 0)) + if (lws_ss_policy_parse_begin(context, 0) || + lws_fi(&context->fic, "ctx_createfail_ss_pol1")) { +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_ss_policy_parse_abandon(context); +#endif goto bail_libuv_aware; + } n = lws_ss_policy_parse(context, (uint8_t *)context->pss_policies_json, strlen(context->pss_policies_json)); - if (n != LEJP_CONTINUE && n < 0) + if ((n != LEJP_CONTINUE && n < 0) || + lws_fi(&context->fic, "ctx_createfail_ss_pol2")) { + lws_ss_policy_parse_abandon(context); goto bail_libuv_aware; + } - if (lws_ss_policy_set(context, "hardcoded")) { + if (lws_ss_policy_set(context, "hardcoded") || + lws_fi(&context->fic, "ctx_createfail_ss_pol3")) { lwsl_err("%s: policy set failed\n", __func__); goto bail_libuv_aware; } @@ -1348,7 +1376,8 @@ lws_create_context(const struct lws_context_creation_info *info) if (context->pss_policies) { /* user code set the policy objects directly, no parsing step */ - if (lws_ss_policy_set(context, "hardcoded")) { + if (lws_ss_policy_set(context, "hardcoded") || + lws_fi(&context->fic, "ctx_createfail_ss_pol3")) { lwsl_err("%s: policy set failed\n", __func__); goto bail_libuv_aware; } @@ -1368,7 +1397,8 @@ lws_create_context(const struct lws_context_creation_info *info) * listening, we don't want the power for anything else */ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) - if (lws_plat_drop_app_privileges(context, 1)) + if (lws_plat_drop_app_privileges(context, 1) || + lws_fi(&context->fic, "ctx_createfail_privdrop")) goto bail_libuv_aware; #if defined(LWS_WITH_SYS_STATE) @@ -1391,6 +1421,12 @@ lws_create_context(const struct lws_context_creation_info *info) return context; +early_bail: + lws_fi_destroy(&info->fic); + + return NULL; + +#if 0 #if defined(LWS_WITH_NETWORK) fail_clean_pipes: @@ -1410,11 +1446,15 @@ fail_clean_pipes: return NULL; #endif +#endif +#if defined(LWS_WITH_NETWORK) bail: + lws_fi_destroy(&info->fic); lws_context_destroy(context); return NULL; +#endif bail_libuv_aware: lws_context_destroy(context); @@ -1429,7 +1469,22 @@ fail_event_libs: lwsl_err("Requested event library support not configured\n"); #endif +#if defined(LWS_WITH_NETWORK) free_context_fail: + if (context) { +#if defined(LWS_WITH_SYS_SMD) + _lws_smd_destroy(context); +#endif + } +#endif +free_context_fail2: + if (context) { +#if defined(LWS_WITH_SYS_METRICS) + lws_metrics_destroy(context); +#endif + lws_fi_destroy(&context->fic); + } + lws_fi_destroy(&info->fic); lws_free(context); return NULL; @@ -1912,6 +1967,7 @@ next: for (n = 0; n < context->count_threads; n++) { struct lws_context_per_thread *pt = &context->pt[n]; + (void)pt; #if defined(LWS_WITH_SEQUENCER) lws_seq_destroy_all_on_pt(pt); @@ -2074,7 +2130,7 @@ next: #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_destroy(&context->fi); + lws_fi_destroy(&context->fic); #endif lws_free(context); diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 935f30d16..c46408590 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -1335,13 +1335,18 @@ lws_cmdline_option(int argc, const char **argv, const char *val) static const char * const builtins[] = { "-d", -#if defined(LWS_WITH_UDP) - "--udp-tx-loss", - "--udp-rx-loss", -#endif + "--fault-injection", + "--fault-seed", "--ignore-sigterm" }; +enum opts { + OPT_DEBUGLEVEL, + OPT_FAULTINJECTION, + OPT_FAULT_SEED, + OPT_IGNORE_SIGTERM, +}; + #if !defined(LWS_PLAT_FREERTOS) static void lws_sigterm_catch(int sig) @@ -1355,6 +1360,9 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, { const char *p; int n, m, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + uint64_t seed = (uint64_t)lws_now_usecs(); +#endif for (n = 0; n < (int)LWS_ARRAY_SIZE(builtins); n++) { p = lws_cmdline_option(argc, argv, builtins[n]); @@ -1364,20 +1372,24 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, m = atoi(p); switch (n) { - case 0: + case OPT_DEBUGLEVEL: logs = m; break; -#if defined(LWS_WITH_UDP) - case 1: - info->udp_loss_sim_tx_pc = (uint8_t)m; - break; - case 2: - info->udp_loss_sim_rx_pc = (uint8_t)m; - break; - case 3: -#else - case 1: + + case OPT_FAULTINJECTION: +#if !defined(LWS_WITH_SYS_FAULT_INJECTION) + lwsl_err("%s: FAULT_INJECTION not built\n", __func__); #endif + lws_fi_deserialize(&info->fic, p); + break; + + case OPT_FAULT_SEED: +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + seed = (uint64_t)atoll(p); +#endif + break; + + case OPT_IGNORE_SIGTERM: #if !defined(LWS_PLAT_FREERTOS) signal(SIGTERM, lws_sigterm_catch); #endif @@ -1385,7 +1397,16 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, } } +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_xos_init(&info->fic.xos, seed); +#endif lws_set_log_level(logs, NULL); + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + if (info->fic.fi_owner.count) + lwsl_notice("%s: Fault Injection seed %llu\n", __func__, + (unsigned long long)seed); +#endif } diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 2539d7826..d993d746c 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -524,7 +524,7 @@ struct lws_context { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fi; + lws_fi_ctx_t fic; /**< Toplevel Fault Injection ctx */ #endif @@ -729,8 +729,6 @@ struct lws_context { uint16_t us_wait_resolution; uint8_t max_fi; - uint8_t udp_loss_sim_tx_pc; - uint8_t udp_loss_sim_rx_pc; uint8_t captive_portal_detect; uint8_t captive_portal_detect_type; diff --git a/lib/misc/CMakeLists.txt b/lib/misc/CMakeLists.txt index d8979f918..cd040aa58 100644 --- a/lib/misc/CMakeLists.txt +++ b/lib/misc/CMakeLists.txt @@ -33,6 +33,7 @@ include_directories(.) list(APPEND SOURCES misc/base64-decode.c + misc/prng.c misc/lws-ring.c) if (LWS_WITH_FTS) diff --git a/lib/misc/prng.c b/lib/misc/prng.c new file mode 100644 index 000000000..8f05fadb9 --- /dev/null +++ b/lib/misc/prng.c @@ -0,0 +1,80 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * After Public Domain implementations + * + * https://github.com/svaarala/duktape/tree/master/misc + */ + +#include + +static inline uint64_t rol64(uint64_t x, int k) +{ + return (x << k) | (x >> (64 - k)); +} + +uint64_t +lws_xos(struct lws_xos *xos) +{ + uint64_t *s = &xos->s[0]; + uint64_t const result = rol64(s[1] * 5, 7) * 9; + uint64_t const c = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= c; + s[3] = rol64(s[3], 45); + + return result; +} + +static uint64_t +splitmix64(uint64_t *s) +{ + uint64_t r = *s; + + *s = r + 0x9E3779B97F4A7C15ull; + + r = (r ^ (r >> 30)) * 0xBF58476D1CE4E5B9ull; + r = (r ^ (r >> 27)) * 0x94D049BB133111EBull; + + return r ^ (r >> 31); +} + +void +lws_xos_init(struct lws_xos *xos, uint64_t seed) +{ + int n; + + for (n = 0; n < 4; n++) + xos->s[n] = splitmix64(&seed); +} + +int +lws_xos_percent(struct lws_xos *xos, int percent) +{ + return (int)(lws_xos(xos) % 100) < percent; +} diff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c index d5288de18..7a3808952 100644 --- a/lib/plat/unix/unix-service.c +++ b/lib/plat/unix/unix-service.c @@ -54,6 +54,7 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) __func__, m); return -1; } + /* if something closed, retry this slot since may have been * swapped with end fd */ if (m && pt->fds[n].fd != fd) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 02b8d6a1b..e3d9dc5b1 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -1459,6 +1459,9 @@ lws_h2_parse_end_of_frame(struct lws *wsi) /* pass on the initial headers to SID 1 */ h2n->swsi->http.ah = wsi->http.ah; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_fi_import(&h2n->swsi->fic, &wsi->fic); +#endif h2n->swsi->client_mux_substream = 1; h2n->swsi->client_h2_alpn = 1; #if defined(LWS_WITH_CLIENT) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index c6b4bf632..6c635c5a3 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -175,17 +175,23 @@ done_list: #endif for (m = 0; m < limit; m++) { + + if (lws_fi(&vhost->fic, "listenskt")) { + sockfd = LWS_SOCK_INVALID; + } else { + #ifdef LWS_WITH_UNIX_SOCK - if (LWS_UNIX_SOCK_ENABLED(vhost)) - sockfd = socket(AF_UNIX, SOCK_STREAM, 0); - else + if (LWS_UNIX_SOCK_ENABLED(vhost)) + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + else #endif #ifdef LWS_WITH_IPV6 - if (LWS_IPV6_ENABLED(vhost)) - sockfd = socket(AF_INET6, SOCK_STREAM, 0); - else + if (LWS_IPV6_ENABLED(vhost)) + sockfd = socket(AF_INET6, SOCK_STREAM, 0); + else #endif - sockfd = socket(AF_INET, SOCK_STREAM, 0); + sockfd = socket(AF_INET, SOCK_STREAM, 0); + } if (sockfd == LWS_SOCK_INVALID) { lwsl_err("ERROR opening socket\n"); diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index cbe927cf4..ff01fd3ff 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -142,20 +142,9 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, } #if defined(LWS_WITH_UDP) - if (wsi->a.context->udp_loss_sim_rx_pc) { - uint16_t u16; - /* - * We should randomly drop some of these - */ - - if (lws_get_random(wsi->a.context, &u16, 2) == 2 && - ((u16 * 100) / 0xffff) <= - wsi->a.context->udp_loss_sim_rx_pc) { - lwsl_warn("%s: dropping udp rx\n", __func__); - /* pretend it was handled */ - n = ebuf.len; - goto post_rx; - } + if (lws_fi(&wsi->fic, "udp_rx_loss")) { + n = ebuf.len; + goto post_rx; } #endif diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 180de3207..c2fd361ce 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -1115,6 +1115,21 @@ int lws_ss_policy_parse_abandon(struct lws_context *context) { struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + lws_ss_x509_t *x; + + x = args->heads[LTY_X509].x; + while (x) { + /* + * Free all the client DER buffers now they have been parsed + * into tls library X.509 objects + */ + if (!x->keep) { /* used for server */ + lws_free((void *)x->ca_der); + x->ca_der = NULL; + } + + x = x->next; + } lejp_destruct(&args->jctx); lwsac_free(&args->ac); diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 7fe4ff055..2ce42146d 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -59,7 +59,7 @@ typedef struct lws_ss_handle { struct lws_dll2 cli_list; /**< same server clients list */ #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fi; /**< Fault Injection context */ + lws_fi_ctx_t fic; /**< Fault Injection context */ #endif struct lws_dll2_owner src_list; /**< sink's list of bound sources */ @@ -285,7 +285,7 @@ typedef struct lws_sspc_handle { struct lws_ss_serialization_parser parser; #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fi; /**< Fault Injection context */ + lws_fi_ctx_t fic; /**< Fault Injection context */ #endif lws_dll2_owner_t metadata_owner; @@ -402,7 +402,7 @@ lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, int *flags); int -lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state, +lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); void diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 2edfc18b3..9c877fad4 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -174,7 +174,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_RAW_CONNECTED: - if (!h) + if (!h || lws_fi(&h->fic, "sspc_fail_on_linkup")) return -1; lwsl_info("%s: CONNECTED (%s)\n", __func__, h->ssi.streamtype); @@ -234,9 +234,18 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, return -1; } - n = lws_ss_deserialize_parse(&h->parser, lws_get_context(wsi), - h->dsh, in, len, &h->state, h, - (lws_ss_handle_t **)m, &h->ssi, 1); + if (lws_fi(&h->fic, "sspc_fake_rxparse_disconnect_me")) + n = LWSSSSRET_DISCONNECT_ME; + else + if (lws_fi(&h->fic, "sspc_fake_rxparse_destroy_me")) + n = LWSSSSRET_DESTROY_ME; + else + n = lws_ss_deserialize_parse(&h->parser, + lws_get_context(wsi), + h->dsh, in, len, + &h->state, h, + (lws_ss_handle_t **)m, + &h->ssi, 1); switch (n) { case LWSSSSRET_OK: break; @@ -476,7 +485,10 @@ do_write_nz: break; do_write: - n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW); + if (lws_fi(&h->fic, "sspc_link_write_fail")) + n = -1; + else + n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW); if (n < 0) { lwsl_notice("%s: WRITEABLE: %d\n", __func__, n); @@ -530,20 +542,32 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, * and the streamname */ h = malloc(sizeof(lws_sspc_handle_t) + ssi->user_alloc + - strlen(ssi->streamtype) + 1); + strlen(ssi->streamtype) + 1); if (!h) return 1; memset(h, 0, sizeof(*h)); - __lws_lc_tag(&context->lcg[LWSLCG_SSP_CLIENT], &h->lc, ssi->streamtype); - #if defined(LWS_WITH_SYS_FAULT_INJECTION) - h->fi.name = "sspc"; - h->fi.parent = &context->fi; - if (ssi->fi) - lws_fi_import(&h->fi, ssi->fi); + h->fic.name = "sspc"; + lws_xos_init(&h->fic.xos, lws_xos(&context->fic.xos)); + if (ssi->fic.fi_owner.count) + lws_fi_import(&h->fic, &ssi->fic); + + lws_fi_inherit_copy(&h->fic, &context->fic, "ss", ssi->streamtype); #endif + if (lws_fi(&h->fic, "sspc_create_oom")) { + /* + * We have to do this a litte later, so we can cleanly inherit + * the OOM pieces and drain the info fic + */ + lws_fi_destroy(&h->fic); + free(h); + return 1; + } + + __lws_lc_tag(&context->lcg[LWSLCG_SSP_CLIENT], &h->lc, ssi->streamtype); + memcpy(&h->ssi, ssi, sizeof(*ssi)); ua = (uint8_t *)&h[1]; memset(ua, 0, ssi->user_alloc); @@ -633,7 +657,7 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) } #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_destroy(&h->fi); + lws_fi_destroy(&h->fic); #endif lws_sul_cancel(&h->sul_retry); @@ -823,7 +847,10 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, * We have to stash the metadata and pass it to the proxy */ - md = lws_malloc(sizeof(*md) + len, "set metadata"); + if (lws_fi(&h->fic, "sspc_fail_metadata_set")) + md = NULL; + else + md = lws_malloc(sizeof(*md) + len, "set metadata"); if (!md) { lwsl_err("%s: OOM\n", __func__); diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index acd55b4e4..dc24a6657 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -91,6 +91,8 @@ __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size) pt = &conn->wsi->a.context->pt[(int)conn->wsi->tsi]; + if (lws_fi(&conn->ss->fic, "ssproxy_dsh_create_oom")) + return -1; conn->dsh = lws_dsh_create(&pt->ss_dsh_owner, dsh_size, 2); if (!conn->dsh) return -1; @@ -100,7 +102,7 @@ __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size) return 0; } -/* secure streams payload interface */ +/* Onward secure streams payload interface */ static lws_ss_state_return_t ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags) @@ -120,9 +122,22 @@ ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags) flags |= LWSSS_FLAG_RIDESHARE; } - n = lws_ss_serialize_rx_payload(m->conn->dsh, buf, len, flags, rsp); + /* + * Apply SSS framing around this chunk of RX and stash it in the dsh + * in ss -> proxy [ -> client] direction. This can fail... + */ + + if (lws_fi(&m->ss->fic, "ssproxy_dsh_rx_queue_oom")) + n = 1; + else + n = lws_ss_serialize_rx_payload(m->conn->dsh, buf, len, + flags, rsp); if (n) - return n; + /* + * We couldn't buffer this rx, eg due to OOM, let's escalate it + * to be a "loss of connection", which it basically is... + */ + return LWSSSSRET_DISCONNECT_ME; /* * Manage rx flow on the SS (onward) side according to our situation @@ -141,7 +156,7 @@ ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags) if (m->conn->wsi) /* if possible, request client conn write */ lws_callback_on_writable(m->conn->wsi); - return 0; + return LWSSSSRET_OK; } /* @@ -221,6 +236,8 @@ ss_proxy_onward_state(void *userobj, void *sh, __func__, lws_ss_tag(m->ss), (unsigned long)dsh_size); + /* this includes ssproxy_dsh_create_oom fault generation */ + if (__lws_ss_proxy_bind_ss_to_conn_wsi(m->conn, dsh_size)) { /* failed to allocate the dsh */ @@ -257,7 +274,12 @@ ss_proxy_onward_state(void *userobj, void *sh, return LWSSSSRET_OK; } - lws_ss_serialize_state(m->conn->dsh, state, ack); + if (lws_ss_serialize_state(m->conn->wsi, m->conn->dsh, state, ack)) + /* + * Failed to alloc state packet that we want to send in dsh, + * we will lose coherence and have to disconnect the link + */ + return LWSSSSRET_DISCONNECT_ME; if (m->conn->wsi) /* if possible, request client conn write */ lws_callback_on_writable(m->conn->wsi); @@ -280,7 +302,7 @@ ss_proxy_onward_txcr(void *userobj, int bump) } /* - * Client - Proxy connection on unix domain socket + * Client <-> Proxy connection, usually on Unix Domain Socket */ static int @@ -315,9 +337,14 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, lwsl_info("LWS_CALLBACK_RAW_ADOPT\n"); if (!pss) return -1; - pss->conn = malloc(sizeof(struct conn)); + + if (lws_fi(&wsi->fic, "ssproxy_client_adopt_oom")) + pss->conn = NULL; + else + pss->conn = malloc(sizeof(struct conn)); if (!pss->conn) return -1; + memset(pss->conn, 0, sizeof(*pss->conn)); /* dsh is allocated when the onward ss is done */ @@ -354,8 +381,8 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, assert(conn->wsi == wsi); conn->wsi = NULL; - lwsl_notice("%s: cli->prox link %s closing\n", - __func__, lws_wsi_tag(wsi)); + lwsl_notice("%s: cli->prox link %s closing\n", __func__, + lws_wsi_tag(wsi)); /* sever relationship with conn */ lws_set_opaque_user_data(wsi, NULL); @@ -518,9 +545,11 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, conn->state = LPCSPROX_OPERATIONAL; lws_set_timeout(wsi, 0, 0); break; + case LPCSPROX_OPERATIONAL: /* + * returning [onward -> ] proxy]-> client * rx metadata has priority */ @@ -546,7 +575,8 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, p[3] = (uint8_t)naml; memcpy(&p[4], md->name, naml); p += 4 + naml; - memcpy(p, md->value__may_own_heap, md->length); + memcpy(p, md->value__may_own_heap, + md->length); p += md->length; n = lws_ptr_diff(p, cp); @@ -607,7 +637,10 @@ again: if (!n) break; - n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW); + if (lws_fi(&wsi->fic, "ssproxy_client_write_fail")) + n = -1; + else + n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW); if (n < 0) { lwsl_info("%s: WRITEABLE: %d\n", __func__, n); diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index abd23bff1..ec70e0917 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -262,7 +262,7 @@ lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, */ int -lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state, +lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { uint8_t pre[12]; @@ -285,7 +285,8 @@ lws_ss_serialize_state(struct lws_dsh *dsh, lws_ss_constate_t state, lws_ser_wu32be(&pre[n], ack); - if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, (unsigned int)n + 4, NULL, 0)) { + if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, (unsigned int)n + 4, NULL, 0) || + (wsi && lws_fi(&wsi->fic, "sspc_dsh_ss2p_oom"))) { lwsl_err("%s: unable to alloc in dsh 2\n", __func__); return 1; @@ -428,7 +429,9 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, * We're going to try to do the onward connect */ - if (_lws_ss_client_connect(proxy_pss_to_ss_h(pss), + if ((proxy_pss_to_ss_h(pss) && + lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_onward_conn_fail")) || + _lws_ss_client_connect(proxy_pss_to_ss_h(pss), 0, parconn) == LWSSSSRET_DESTROY_ME) goto hangup; @@ -685,7 +688,9 @@ payload_ff: /* time used later to find proxy hold time */ lws_ser_wu64be(&p[15], (uint64_t)us); - if (lws_dsh_alloc_tail(dsh, KIND_C_TO_P, pre, + if ((proxy_pss_to_ss_h(pss) && + lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_dsh_c2p_pay_oom")) || + lws_dsh_alloc_tail(dsh, KIND_C_TO_P, pre, 23, cp, (unsigned int)n)) { lwsl_err("%s: unable to alloc in dsh 3\n", __func__); @@ -715,6 +720,11 @@ payload_ff: /* we still have an sspc handle */ int ret = ssi->rx(client_pss_to_userdata(pss), (uint8_t *)cp, (unsigned int)n, (int)flags); + + if (client_pss_to_sspc_h(pss, ssi) && + lws_fi(&client_pss_to_sspc_h(pss, ssi)->fic, "sspc_rx_fake_destroy_me")) + ret = LWSSSSRET_DESTROY_ME; + switch (ret) { case LWSSSSRET_OK: break; @@ -1005,7 +1015,10 @@ payload_ff: * Create the client's rx metadata entry */ - md = lws_malloc(sizeof(lws_sspc_metadata_t) + + if (h && lws_fi(&h->fic, "sspc_rx_metadata_oom")) + md = NULL; + else + md = lws_malloc(sizeof(lws_sspc_metadata_t) + par->rem + 1, "rxmeta"); if (!md) { lwsl_err("%s: OOM\n", __func__); @@ -1057,7 +1070,13 @@ payload_ff: lws_free_set_NULL(par->ssmd->value__may_own_heap); par->ssmd->value_on_lws_heap = 0; - par->ssmd->value__may_own_heap = lws_malloc((unsigned int)par->rem + 1, "metadata"); + if (proxy_pss_to_ss_h(pss) && + lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_rx_metadata_oom")) + par->ssmd->value__may_own_heap = NULL; + else + par->ssmd->value__may_own_heap = + lws_malloc((unsigned int)par->rem + 1, "metadata"); + if (!par->ssmd->value__may_own_heap) { lwsl_err("%s: OOM mdv\n", __func__); goto hangup; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 3e919d03b..8dd99f621 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -747,7 +747,29 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, pol = ssi->policy; if (!pol) { #endif + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_fi_ctx_t temp_fic; + + /* + * We have to do a temp inherit from context to find out + * early if we are supposed to inject a fault concealing + * the policy + */ + + memset(&temp_fic, 0, sizeof(temp_fic)); + lws_xos_init(&temp_fic.xos, lws_xos(&context->fic.xos)); + lws_fi_inherit_copy(&temp_fic, &context->fic, "ss", ssi->streamtype); + + if (lws_fi(&temp_fic, "ss_no_streamtype_policy")) + pol = NULL; + else + pol = lws_ss_policy_lookup(context, ssi->streamtype); + + lws_fi_destroy(&temp_fic); +#else pol = lws_ss_policy_lookup(context, ssi->streamtype); +#endif if (!pol) { lwsl_info("%s: unknown stream type %s\n", __func__, ssi->streamtype); @@ -821,10 +843,12 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, ssi->streamtype ? ssi->streamtype : "nostreamtype"); #if defined(LWS_WITH_SYS_FAULT_INJECTION) - h->fi.name = "ss"; - h->fi.parent = &context->fi; - if (ssi->fi) - lws_fi_import(&h->fi, ssi->fi); + h->fic.name = "ss"; + lws_xos_init(&h->fic.xos, lws_xos(&context->fic.xos)); + if (ssi->fic.fi_owner.count) + lws_fi_import(&h->fic, &ssi->fic); + + lws_fi_inherit_copy(&h->fic, &context->fic, "ss", ssi->streamtype); #endif h->info = *ssi; @@ -980,7 +1004,10 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, } #endif - vho = lws_create_vhost(context, &i); + if (lws_fi(&ssi->fic, "ss_srv_vh_fail")) + vho = NULL; + else + vho = lws_create_vhost(context, &i); if (!vho) { lwsl_err("%s: failed to create vh", __func__); goto late_bail; @@ -1037,6 +1064,7 @@ late_bail: lws_dll2_remove(&h->list); lws_pt_unlock(pt); + lws_fi_destroy(&h->fic); __lws_lc_untag(&h->lc); lws_free(h); @@ -1199,7 +1227,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_destroy(&h->fi); + lws_fi_destroy(&h->fic); #endif #if defined(LWS_WITH_SYS_METRICS) diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index ba1552980..c46c8f34c 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -28,7 +28,7 @@ static const uint32_t botable[] = { 300, 500, 700, 1250, 5000 /* in case everything just dog slow */ }; static const lws_retry_bo_t retry_policy = { - botable, LWS_ARRAY_SIZE(botable), LWS_ARRAY_SIZE(botable), + botable, LWS_ARRAY_SIZE(botable), LWS_RETRY_CONCEAL_ALWAYS, /* don't conceal after the last table entry */ 0, 0, 20 }; void @@ -371,7 +371,7 @@ ok: dns->wsi = lws_create_adopt_udp(context->vhost_list, ads, 53, 0, lws_async_dns_protocol.name, NULL, - NULL, NULL, &retry_policy); + NULL, NULL, &retry_policy, "asyncdns"); if (!dns->wsi) { lwsl_err("%s: foreign socket adoption failed\n", __func__); return 1; diff --git a/lib/system/dhcpclient/dhcpc4.c b/lib/system/dhcpclient/dhcpc4.c index c841d2bc9..33c8494fc 100644 --- a/lib/system/dhcpclient/dhcpc4.c +++ b/lib/system/dhcpclient/dhcpc4.c @@ -299,7 +299,7 @@ lws_dhcpc4_retry_conn(struct lws_sorted_usec_list *sul) 68, LWS_CAUDP_PF_PACKET | LWS_CAUDP_BROADCAST, "lws-dhcp4client", (const char *)&r[1], - NULL, NULL, &bo2); + NULL, NULL, &bo2, "dhcpc"); lwsl_debug("%s: created wsi_raw: %s\n", __func__, lws_wsi_tag(r->wsi_raw)); if (!r->wsi_raw) { lwsl_err("%s: unable to create udp skt\n", __func__); diff --git a/lib/system/fault-injection/fault-injection.c b/lib/system/fault-injection/fault-injection.c index c833c6d6c..57082cc50 100644 --- a/lib/system/fault-injection/fault-injection.c +++ b/lib/system/fault-injection/fault-injection.c @@ -26,9 +26,8 @@ #include - static lws_fi_priv_t * -lws_fi_lookup(lws_fi_ctx_t *fic, const char *name) +lws_fi_lookup(const lws_fi_ctx_t *fic, const char *name) { lws_start_foreach_dll(struct lws_dll2 *, p, fic->fi_owner.head) { lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list); @@ -42,58 +41,81 @@ lws_fi_lookup(lws_fi_ctx_t *fic, const char *name) } int -lws_fi(lws_fi_ctx_t *fic, const char *name) +lws_fi(const lws_fi_ctx_t *fic, const char *name) { - lws_fi_priv_t *pv = NULL; + lws_fi_priv_t *pv; + int n; - do { - pv = lws_fi_lookup(fic, name); + pv = lws_fi_lookup(fic, name); - if (pv) { - int n; + if (!pv) + return 0; - switch (pv->fi.type) { - case LWSFI_ALWAYS: + switch (pv->fi.type) { + case LWSFI_ALWAYS: + goto inject; + + case LWSFI_DETERMINISTIC: + pv->fi.times++; + if (pv->fi.times >= pv->fi.pre) + if (pv->fi.times < pv->fi.pre + pv->fi.count) goto inject; + return 0; - case LWSFI_DETERMINISTIC: - pv->fi.times++; - if (pv->fi.times >= pv->fi.pre) - if (pv->fi.times < pv->fi.pre + pv->fi.count) - goto inject; - return 0; + case LWSFI_PROBABILISTIC: + if (lws_xos_percent((lws_xos_t *)&fic->xos, (int)pv->fi.pre)) + goto inject; + return 0; - case LWSFI_PROBABILISTIC: - pv->fi.times = (unsigned long)(pv->fi.times * 3) ^ - (unsigned long)lws_now_usecs(); - if ((uint16_t)pv->fi.times % 101 >= pv->fi.pre) - goto inject; - return 0; + case LWSFI_PATTERN: + case LWSFI_PATTERN_ALLOC: + n = (int)((pv->fi.times++) % pv->fi.count); + if (pv->fi.pattern[n >> 3] & (1 << (n & 7))) + goto inject; - case LWSFI_PATTERN: - n = (int)(pv->fi.times % pv->fi.pre); - if (pv->fi.pattern[n >> 3] & (1 << (n & 7))) - goto inject; + return 0; - return 0; - - default: - return 0; - } - } - - fic = fic->parent; - } while (fic); + default: + return 0; + } return 0; inject: - lwsl_warn("%s: Injecting fault %s->%s\n", __func__, fic->name, - pv->fi.name); + lwsl_warn("%s: Injecting fault %s->%s\n", __func__, + fic->name ? fic->name : "unk", pv->fi.name); return 1; } +int +_lws_fi_user_wsi_fi(struct lws *wsi, const char *name) +{ + return lws_fi(&wsi->fic, name); +} + +int +_lws_fi_user_context_fi(struct lws_context *ctx, const char *name) +{ + return lws_fi(&ctx->fic, name); +} + +#if defined(LWS_WITH_SECURE_STREAMS) +int +_lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name) +{ + return lws_fi(&h->fic, name); +} + +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) +int +_lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name) +{ + return lws_fi(&h->fic, name); +} +#endif +#endif + int lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi) { @@ -130,7 +152,12 @@ lws_fi_remove(lws_fi_ctx_t *fic, const char *name) void lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src) { - lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, fic_src->fi_owner.head) { + + /* inherit the PRNG seed for our context from source guy too */ + lws_xos_init(&fic_dest->xos, lws_xos((lws_xos_t *)&fic_src->xos)); + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + fic_src->fi_owner.head) { lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list); lws_dll2_remove(&pv->list); @@ -139,14 +166,210 @@ lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src) } lws_end_foreach_dll_safe(p, p1); } -void -lws_fi_destroy(lws_fi_ctx_t *fic) +static void +do_inherit(lws_fi_ctx_t *fic_dest, lws_fi_t *pfi, size_t trim) { - lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, fic->fi_owner.head) { + lws_fi_t fi = *pfi; + + fi.name += trim; + + lwsl_info("%s: %s: %s inherited as %s\n", __func__, fic_dest->name, + pfi->name, fi.name); + + if (fi.type == LWSFI_PATTERN_ALLOC) { + fi.pattern = lws_malloc((size_t)((fi.count >> 3) + 1), __func__); + if (!fi.pattern) + return; + memcpy((uint8_t *)fi.pattern, pfi->pattern, + (size_t)((fi.count >> 3) + 1)); + } + + lws_fi_add(fic_dest, &fi); +} + +void +lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src, + const char *scope, const char *value) +{ + size_t sl = 0, vl = 0; + + if (scope) + sl = strlen(scope); + + if (value) + vl = strlen(value); + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + fic_src->fi_owner.head) { lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list); + size_t nl = strlen(pv->fi.name); + + if (!scope) + do_inherit(fic_dest, &pv->fi, 0); + else + if (nl > sl + 2 && + !strncmp(pv->fi.name, scope, sl) && + pv->fi.name[sl] == '/') + do_inherit(fic_dest, &pv->fi, sl + 1); + else { + if (value && nl > sl + vl + 2 && + pv->fi.name[sl] == '=' && + !strncmp(pv->fi.name + sl + 1, value, vl) && + pv->fi.name[sl + 1 + vl] == '/') + do_inherit(fic_dest, &pv->fi, sl + vl + 2); + } + + } lws_end_foreach_dll_safe(p, p1); +} + +void +lws_fi_destroy(const lws_fi_ctx_t *fic) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + fic->fi_owner.head) { + lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list); + + if (pv->fi.type == LWSFI_PATTERN_ALLOC && pv->fi.pattern) { + lws_free((void *)pv->fi.pattern); + pv->fi.pattern = NULL; + } lws_dll2_remove(&pv->list); lws_free(pv); } lws_end_foreach_dll_safe(p, p1); } + +enum { + PARSE_NAME, + PARSE_WHEN, + PARSE_PC, + PARSE_ENDBR +}; + +void +lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers) +{ + struct lws_tokenize ts; + lws_fi_t fi; + char nm[64]; + int state = PARSE_NAME; + + /* + * Go through the comma-separated list of faults + * creating them and adding to the lws_context info + */ + + lws_tokenize_init(&ts, sers, LWS_TOKENIZE_F_DOT_NONTERM | + LWS_TOKENIZE_F_NO_INTEGERS | + LWS_TOKENIZE_F_NO_FLOATS | + LWS_TOKENIZE_F_EQUALS_NONTERM | + LWS_TOKENIZE_F_SLASH_NONTERM | + LWS_TOKENIZE_F_MINUS_NONTERM); + ts.len = (unsigned int)strlen(sers); + if (ts.len < 1 || ts.len > 10240) + return; + + do { + ts.e = (int8_t)lws_tokenize(&ts); + switch (ts.e) { + case LWS_TOKZE_TOKEN: + + if (state == PARSE_NAME) { + /* + * One fault to inject looks like, eg, + * + * vh=xxx/listenskt + */ + + memset(&fi, 0, sizeof(fi)); + + lws_strnncpy(nm, ts.token, ts.token_len, sizeof(nm)); + fi.name = nm; + fi.type = LWSFI_ALWAYS; + + lwsl_notice("%s: name %.*s\n", __func__, (int)ts.token_len, ts.token); + + /* added later, potentially after (when) */ + break; + } + if (state == PARSE_WHEN) { + /* it's either numeric or a pattern */ + + lwsl_notice("%s: when\n", __func__); + + if (*ts.token == '.' || *ts.token == 'X') { + uint8_t *pat; + size_t n; + + /* + * pattern... we need to allocate it + */ + fi.type = LWSFI_PATTERN_ALLOC; + pat = lws_zalloc((ts.token_len >> 3) + 1, __func__); + if (!pat) + return; + fi.pattern = pat; + fi.count = (uint64_t)ts.token_len; + + for (n = 0; n < ts.token_len; n++) + if (ts.token[n] == 'X') + pat[n >> 3] = (uint8_t)( + pat[n >> 3] | (1 << (n & 7))); + + lwsl_hexdump_notice(pat, (ts.token_len >> 3) + 1); + + state = PARSE_ENDBR; + break; + } + + fi.pre = (uint64_t)atoi(ts.token); + lwsl_notice("%s: prob %d%%\n", __func__, (int)fi.pre); + fi.type = LWSFI_PROBABILISTIC; + state = PARSE_PC; + break; + } + break; + + case LWS_TOKZE_DELIMITER: + if (*ts.token == ',') { + lws_fi_add(fic, &fi); + state = PARSE_NAME; + break; + } + if (*ts.token == '(') { + lwsl_notice("%s: (\n", __func__); + if (state != PARSE_NAME) { + lwsl_err("%s: misplaced (\n", __func__); + return; + } + state = PARSE_WHEN; + break; + } + if (*ts.token == ')') { + if (state != PARSE_ENDBR) { + lwsl_err("%s: misplaced )\n", __func__); + return; + } + state = PARSE_NAME; + break; + } + if (*ts.token == '%') { + if (state != PARSE_PC) { + lwsl_err("%s: misplaced %%\n", __func__); + return; + } + state = PARSE_ENDBR; + break; + } + break; + + case LWS_TOKZE_ENDED: + lws_fi_add(fic, &fi); + return; + + default: + return; + } + } while (ts.e > 0); +} diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 86536c898..bc5a96158 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -83,7 +83,7 @@ lws_ntpc_retry_conn(struct lws_sorted_usec_list *sul) v->retry_count_write = 0; v->wsi_udp = lws_create_adopt_udp(v->vhost, v->ntp_server_ads, 123, 0, v->protocol->name, NULL, NULL, NULL, - &bo2); + &bo2, "ntpclient"); lwsl_debug("%s: created wsi_udp: %s\n", __func__, lws_wsi_tag(v->wsi_udp)); if (!v->wsi_udp) { lwsl_err("%s: unable to create udp skt\n", __func__); diff --git a/minimal-examples/api-tests/api-test-lws_dsh/main.c b/minimal-examples/api-tests/api-test-lws_dsh/main.c index dc0f7d710..69bd25042 100644 --- a/minimal-examples/api-tests/api-test-lws_dsh/main.c +++ b/minimal-examples/api-tests/api-test-lws_dsh/main.c @@ -1,7 +1,7 @@ /* * lws-api-test-lws_dsh * - * Written in 2010-2019 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -252,7 +252,7 @@ test4(void) memset(blob, 0, sizeof(blob)); /* - * test 1: use up whole free list, then recover and alloc something + * test 4: use up whole free list, then recover and alloc something * else */ @@ -327,6 +327,92 @@ bail: return 1; } +int +test5(void) +{ + struct lws_dsh *dsh; + unsigned int budget; + uint8_t blob[4096]; + lws_xos_t xos; + size_t size; + void *a1; + + memset(blob, 0, sizeof(blob)); + lws_xos_init(&xos, 0x123456789abcdef0ull); + + budget = (unsigned int)(lws_xos(&xos) % 4000) + 4000; + + lwsl_notice("%s: budget %u\n", __func__, budget); + + + /* + * test 5: PRNG-based spamming and erratic bidi draining + */ + + dsh = lws_dsh_create(NULL, 409600, 2); + if (!dsh) { + lwsl_err("%s: Failed to create dsh\n", __func__); + + return 1; + } + + do { + + if (lws_xos_percent(&xos, 60)) { + /* kind 0 is going to try to write */ + + size = (size_t)((lws_xos(&xos) & 127) + 1); + + if (!lws_dsh_alloc_tail(dsh, 0, blob, size, NULL, 0)) + lwsl_notice("%s: kind 0 alloc %d\n", __func__, (int)size); + } + + if (lws_xos_percent(&xos, 80)) { + /* kind 1 is going to try to write */ + + size = (size_t)((lws_xos(&xos) & 127) + 1); + + if (!lws_dsh_alloc_tail(dsh, 1, blob, size, NULL, 0)) + lwsl_notice("%s: kind 1 alloc %d\n", __func__, (int)size); + } + + if (lws_xos_percent(&xos, 40)) { + /* kind 0 is going to try to read */ + + while (!lws_dsh_get_head(dsh, 0, &a1, &size)) { + lwsl_notice("%s: kind 0 read %d\n", __func__, (int)size); + lws_dsh_free(&a1); + } + } + + if (lws_xos_percent(&xos, 30)) { + /* kind 1 is going to try to read */ + + while (!lws_dsh_get_head(dsh, 1, &a1, &size)) { + lwsl_notice("%s: kind 1 read %d\n", __func__, (int)size); + lws_dsh_free(&a1); + } + } + + } while (budget--); + + while (!lws_dsh_get_head(dsh, 0, &a1, &size)) { + lwsl_notice("%s: kind 0 read %d\n", __func__, (int)size); + lws_dsh_free(&a1); + } + + while (!lws_dsh_get_head(dsh, 1, &a1, &size)) { + lwsl_notice("%s: kind 1 read %d\n", __func__, (int)size); + lws_dsh_free(&a1); + } + + lws_dsh_describe(dsh, "test dsh end state"); + + lws_dsh_destroy(&dsh); + + return 0; +} + int main(int argc, const char **argv) { int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; @@ -355,6 +441,10 @@ int main(int argc, const char **argv) lwsl_user("%s: test4: %d\n", __func__, n); ret |= n; + n = test5(); + lwsl_user("%s: test5: %d\n", __func__, n); + ret |= n; + lwsl_user("Completed: %s\n", ret ? "FAIL" : "PASS"); return ret; diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 5f18af585..0aae74c2d 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -794,8 +794,7 @@ done: return 0; bail: -if (test2()) - return 1; + lwsl_user("Completed: FAIL\n"); return 1; diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c index d69dc2fee..073bdb0b2 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -1,7 +1,7 @@ /* * lws-api-test-lws_tokenize * - * Written in 2010-2020 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -173,6 +173,10 @@ struct expected expected1[] = { expected17[] = { { LWS_TOKZE_TOKEN, "hello", 5 }, { LWS_TOKZE_ENDED, "", 0 }, + }, + expected18[] = { + { LWS_TOKZE_TOKEN, "x=y", 3 }, + { LWS_TOKZE_ENDED, "", 0 }, } ; @@ -253,6 +257,10 @@ struct tests tests[] = { { "# comment1\r\nhello #comment2\r\n#comment3", expected17, LWS_ARRAY_SIZE(expected17), LWS_TOKENIZE_F_HASH_COMMENT + }, + { + "x=y", expected18, + LWS_ARRAY_SIZE(expected18), LWS_TOKENIZE_F_EQUALS_NONTERM } }; diff --git a/minimal-examples/http-client/minimal-http-client-fi/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-fi/CMakeLists.txt deleted file mode 100644 index 0e0d95792..000000000 --- a/minimal-examples/http-client/minimal-http-client-fi/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -project(lws-minimal-http-client-fi C) -cmake_minimum_required(VERSION 2.8.12) -find_package(libwebsockets CONFIG REQUIRED) -list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) -include(CheckCSourceCompiles) -include(LwsCheckRequirements) - -set(SAMP lws-minimal-http-client-fi) -set(SRCS minimal-http-client.c) - -set(requirements 1) -require_lws_config(LWS_ROLE_H1 1 requirements) -require_lws_config(LWS_WITH_CLIENT 1 requirements) -require_lws_config(LWS_WITH_SYS_STATE 1 requirements) -require_lws_config(LWS_WITH_SYS_FAULT_INJECTION 1 requirements) - -if (requirements) - add_executable(${SAMP} ${SRCS}) - - # if (LWS_CTEST_INTERNET_AVAILABLE) - # add_test(NAME http-client-warmcat COMMAND lws-minimal-http-client ) - # add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --h1) - # set_tests_properties(http-client-warmcat - # http-client-warmcat-h1 - # PROPERTIES - # WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client - # TIMEOUT 20) - # - #endif() - - if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) - add_dependencies(${SAMP} websockets_shared) - else() - target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) - endif() -endif() diff --git a/minimal-examples/http-client/minimal-http-client-fi/README.md b/minimal-examples/http-client/minimal-http-client-fi/README.md deleted file mode 100644 index 9387f8c75..000000000 --- a/minimal-examples/http-client/minimal-http-client-fi/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# lws minimal http client - -The application goes to either https://warmcat.com or -https://localhost:7681 (with `-l` option) and receives the page data. - -## build - -``` - $ cmake . && make -``` - -## usage - -Commandline option|Meaning ----|--- --d |Debug verbosity in decimal, eg, -d15 --l| Connect to https://localhost:7681 and accept selfsigned cert ---h1|Specify http/1.1 only using ALPN, rejects h2 even if server supports it ---server |set server name to connect to --k|Apply tls option LCCSCF_ALLOW_INSECURE --j|Apply tls option LCCSCF_ALLOW_SELFSIGNED --m|Apply tls option LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK --e|Apply tls option LCCSCF_ALLOW_EXPIRED --v|Connection validity use 3s / 10s instead of default 5m / 5m10s ---nossl| disable ssl connection ---user | Set Basic Auth username ---password | Set Basic Auth password - -``` - $ ./lws-minimal-http-client -[2018/03/04 14:43:20:8562] USER: LWS minimal http client -[2018/03/04 14:43:20:8571] NOTICE: Creating Vhost 'default' port -1, 1 protocols, IPv6 on -[2018/03/04 14:43:20:8616] NOTICE: created client ssl context for default -[2018/03/04 14:43:20:8617] NOTICE: lws_client_connect_2: 0x1814dc0: address warmcat.com -[2018/03/04 14:43:21:1496] NOTICE: lws_client_connect_2: 0x1814dc0: address warmcat.com -[2018/03/04 14:43:22:0154] NOTICE: lws_client_interpret_server_handshake: incoming content length 26520 -[2018/03/04 14:43:22:0154] NOTICE: lws_client_interpret_server_handshake: client connection up -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3022] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3022] USER: RECEIVE_CLIENT_HTTP_READ: read 974 -[2018/03/04 14:43:22:3022] NOTICE: lws_http_client_read: transaction completed says -1 -[2018/03/04 14:43:23:3042] USER: Completed -``` - -You can also test the client Basic Auth support against the http-server/minimal-http-server-basicauth -example. In one console window run the server and in the other - -``` -$ lws-minimal-http-client -l --nossl --path /secret/index.html --user user --password password -``` - -The Basic Auth credentials for the test server are literally username "user" and password "password". - diff --git a/minimal-examples/http-client/minimal-http-client-fi/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client-fi/minimal-http-client.c deleted file mode 100644 index 2027b83d4..000000000 --- a/minimal-examples/http-client/minimal-http-client-fi/minimal-http-client.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * lws-minimal-http-client - * - * Written in 2010-2021 by Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * This demonstrates the a minimal http client using lws. - * - * It visits https://warmcat.com/ and receives the html page there. You - * can dump the page data by changing the #if 0 below. - */ - -#include -#include -#include - -static int interrupted, bad = 1, status; -#if defined(LWS_WITH_HTTP2) -static int long_poll; -#endif -static struct lws *client_wsi; -static const char *ba_user, *ba_password; - -static const lws_retry_bo_t retry = { - .secs_since_valid_ping = 3, - .secs_since_valid_hangup = 10, -}; - -static int -callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - switch (reason) { - - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", - in ? (char *)in : "(null)"); - interrupted = 1; - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - { - char buf[128]; - - lws_get_peer_simple(wsi, buf, sizeof(buf)); - status = (int)lws_http_client_http_response(wsi); - - lwsl_user("Connected to %s, http response: %d\n", - buf, status); - } -#if defined(LWS_WITH_HTTP2) - if (long_poll) { - lwsl_user("%s: Client entering long poll mode\n", __func__); - lws_h2_client_stream_long_poll_rxonly(wsi); - } -#endif - break; - -#if defined(LWS_WITH_HTTP_BASIC_AUTH) - - /* you only need this if you need to do Basic Auth */ - case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: - { - unsigned char **p = (unsigned char **)in, *end = (*p) + len; - char b[128]; - - if (!ba_user || !ba_password) - break; - - if (lws_http_basic_auth_gen(ba_user, ba_password, b, sizeof(b))) - break; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_AUTHORIZATION, - (unsigned char *)b, (int)strlen(b), p, end)) - return -1; - - break; - } -#endif - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); -#if defined(LWS_WITH_HTTP2) - if (long_poll) { - char dotstar[128]; - lws_strnncpy(dotstar, (const char *)in, len, - sizeof(dotstar)); - lwsl_notice("long poll rx: %d '%s'\n", (int)len, - dotstar); - } -#endif -#if 0 /* enable to dump the html */ - { - const char *p = in; - - while (len--) - if (*p < 0x7f) - putchar(*p++); - else - putchar('.'); - } -#endif - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); - interrupted = 1; - bad = status != 200; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ - break; - - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - interrupted = 1; - bad = status != 200; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -static void -sigint_handler(int sig) -{ - interrupted = 1; -} - -struct args { - int argc; - const char **argv; -}; - -static const lws_fi_t fi = { - .name = "cliwsi.dnsfail", - .type = LWSFI_ALWAYS -}; - -static int -make_client_connection(struct lws_context *context) -{ - struct lws_client_connect_info i; - struct args *a = lws_context_user(context); - lws_fi_ctx_t fic; - const char *p; - - memset(&fic, 0, sizeof(fic)); - lws_fi_add(&fic, &fi); - - memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ - i.context = context; - i.fi = &fic; - - if (!lws_cmdline_option(a->argc, a->argv, "-n")) { - i.ssl_connection = LCCSCF_USE_SSL; -#if defined(LWS_WITH_HTTP2) - /* requires h2 */ - if (lws_cmdline_option(a->argc, a->argv, "--long-poll")) { - lwsl_user("%s: long poll mode\n", __func__); - long_poll = 1; - } -#endif - } - - if (lws_cmdline_option(a->argc, a->argv, "-l")) { - i.port = 7681; - i.address = "localhost"; - i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; - } else { - i.port = 443; - i.address = "warmcat.com"; - } - - if (lws_cmdline_option(a->argc, a->argv, "--nossl")) - i.ssl_connection = 0; - - i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | - LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; - - i.alpn = "h2"; - if (lws_cmdline_option(a->argc, a->argv, "--h1")) - i.alpn = "http/1.1"; - - if (lws_cmdline_option(a->argc, a->argv, "--h2-prior-knowledge")) - i.ssl_connection |= LCCSCF_H2_PRIOR_KNOWLEDGE; - - if ((p = lws_cmdline_option(a->argc, a->argv, "-p"))) - i.port = atoi(p); - - if ((p = lws_cmdline_option(a->argc, a->argv, "--user"))) - ba_user = p; - if ((p = lws_cmdline_option(a->argc, a->argv, "--password"))) - ba_password = p; - - if (lws_cmdline_option(a->argc, a->argv, "-j")) - i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; - - if (lws_cmdline_option(a->argc, a->argv, "-k")) - i.ssl_connection |= LCCSCF_ALLOW_INSECURE; - - if (lws_cmdline_option(a->argc, a->argv, "-m")) - i.ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; - - if (lws_cmdline_option(a->argc, a->argv, "-e")) - i.ssl_connection |= LCCSCF_ALLOW_EXPIRED; - - if ((p = lws_cmdline_option(a->argc, a->argv, "-f"))) { - i.ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW; - i.manual_initial_tx_credit = atoi(p); - lwsl_notice("%s: manual peer tx credit %d\n", __func__, - i.manual_initial_tx_credit); - } - - /* the default validity check is 5m / 5m10s... -v = 3s / 10s */ - - if (lws_cmdline_option(a->argc, a->argv, "-v")) - i.retry_and_idle_policy = &retry; - - if ((p = lws_cmdline_option(a->argc, a->argv, "--server"))) - i.address = p; - - if ((p = lws_cmdline_option(a->argc, a->argv, "--path"))) - i.path = p; - else - i.path = "/"; - - i.host = i.address; - i.origin = i.address; - i.method = "GET"; - - i.protocol = protocols[0].name; - i.pwsi = &client_wsi; - - return !lws_client_connect_via_info(&i); -} - -static int -system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, - int current, int target) -{ - struct lws_context *context = mgr->parent; - - if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL) - return 0; - - lwsl_info("%s: operational\n", __func__); - - make_client_connection(context); - - return 0; -} - -int main(int argc, const char **argv) -{ - lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; - lws_state_notify_link_t *na[] = { ¬ifier, NULL }; - struct lws_context_creation_info info; - struct lws_context *context; - struct args args; - int n = 0; - // uint8_t memcert[4096]; - - args.argc = argc; - args.argv = argv; - - signal(SIGINT, sigint_handler); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - lws_cmdline_option_handle_builtin(argc, argv, &info); - - lwsl_user("LWS minimal http client [-d] [-l] [--h1]\n"); - - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - info.protocols = protocols; - info.user = &args; - info.register_notifier_list = na; - info.connect_timeout_secs = 30; - - /* - * since we know this lws context is only ever going to be used with - * one client wsis / fds / sockets at a time, let lws know it doesn't - * have to use the default allocations for fd tables up to ulimit -n. - * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we - * will use. - */ - info.fd_limit_per_thread = 1 + 1 + 1; - -#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) - /* - * OpenSSL uses the system trust store. mbedTLS has to be told which - * CA to trust explicitly. - */ - info.client_ssl_ca_filepath = "./warmcat.com.cer"; -#endif -#if 0 - n = open("./warmcat.com.cer", O_RDONLY); - if (n >= 0) { - info.client_ssl_ca_mem_len = read(n, memcert, sizeof(memcert)); - info.client_ssl_ca_mem = memcert; - close(n); - n = 0; - memcert[info.client_ssl_ca_mem_len++] = '\0'; - } -#endif - context = lws_create_context(&info); - if (!context) { - lwsl_err("lws init failed\n"); - return 1; - } - - while (n >= 0 && !interrupted) - n = lws_service(context, 0); - - lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); - - return bad; -} diff --git a/minimal-examples/http-client/minimal-http-client-fi/warmcat.com.cer b/minimal-examples/http-client/minimal-http-client-fi/warmcat.com.cer deleted file mode 100644 index 8dc39efc5..000000000 --- a/minimal-examples/http-client/minimal-http-client-fi/warmcat.com.cer +++ /dev/null @@ -1,21 +0,0 @@ - -----BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- - diff --git a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index 23d5dc0d1..eeb26a904 100644 --- a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -8,16 +8,37 @@ include(LwsCheckRequirements) set(SAMP lws-minimal-http-client) set(SRCS minimal-http-client.c) +set(has_fault_injection 1) set(has_h2 1) +set(has_plugins 1) +set(has_ss_policy_parse 1) +set(has_no_system_vhost 1) +set(has_async_dns 1) + set(requirements 1) + require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) require_lws_config(LWS_WITH_SYS_STATE 1 requirements) require_lws_config(LWS_ROLE_H2 1 has_h2) +require_lws_config(LWS_WITH_SYS_FAULT_INJECTION 1 has_fault_injection) +require_lws_config(LWS_WITH_EVLIB_PLUGINS 1 has_plugins) +require_lws_config(LWS_WITH_EVENT_LIBS 1 has_plugins) + +require_lws_config(LWS_WITH_SECURE_STREAMS 1 has_ss_policy_parse) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 has_ss_policy_parse) + +require_lws_config(LWS_WITH_SYS_ASYNC_DNS 0 has_no_system_vhost) +require_lws_config(LWS_WITH_SYS_NTPCLIENT 0 has_no_system_vhost) +require_lws_config(LWS_WITH_SYS_DHCP_CLIENT 0 has_no_system_vhost) + +require_lws_config(LWS_WITH_SYS_ASYNC_DNS 1 has_async_dns) if (requirements) add_executable(${SAMP} ${SRCS}) + + find_program(VALGRIND "valgrind") sai_resource(warmcat_conns 1 40 http_client_warmcat) @@ -27,15 +48,102 @@ if (requirements) add_test(NAME http-client-warmcat COMMAND lws-minimal-http-client ) list(APPEND mytests http-client-warmcat) endif() + + add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --h1) set_tests_properties(${mytests} PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client TIMEOUT 20) + if (has_fault_injection) + + # creation related faults + + list(APPEND mytests http-client-fi-ctx1) + add_test(NAME http-client-fi-ctx1 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail1") + + # if (has_plugins) + # !!! need to actually select an available evlib plugin to trigger this + # list(APPEND mytests http-client-fi-pi) + # add_test(NAME http-client-fi-pi COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_plugin_init") + # endif() + + list(APPEND mytests http-client-fi-ctx2) + add_test(NAME http-client-fi-ctx2 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_sel") + + list(APPEND mytests http-client-fi-ctx3) + add_test(NAME http-client-fi-ctx3 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_oom_ctx") + + list(APPEND mytests http-client-fi-ctx4) + add_test(NAME http-client-fi-ctx4 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_privdrop") + + list(APPEND mytests http-client-fi-ctx5) + add_test(NAME http-client-fi-ctx5 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_maxfds") + + list(APPEND mytests http-client-fi-ctx6) + add_test(NAME http-client-fi-ctx6 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_oom_fds") + + list(APPEND mytests http-client-fi-ctx7) + add_test(NAME http-client-fi-ctx7 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_plat_init") + + list(APPEND mytests http-client-fi-ctx8) + add_test(NAME http-client-fi-ctx8 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_init") + + list(APPEND mytests http-client-fi-ctx9) + add_test(NAME http-client-fi-ctx9 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_pt") + + if (NOT has_no_system_vhost) + + list(APPEND mytests http-client-fi-ctx10) + add_test(NAME http-client-fi-ctx10 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_sys_vh") + + list(APPEND mytests http-client-fi-ctx11) + add_test(NAME http-client-fi-ctx11 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_sys_vh_init") + + endif() + + list(APPEND mytests http-client-fi-ctx12) + add_test(NAME http-client-fi-ctx12 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_def_vh") + + + list(APPEND mytests http-client-fi-vh1) + add_test(NAME http-client-fi-vh1 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_oom") + + list(APPEND mytests http-client-fi-vh2) + add_test(NAME http-client-fi-vh2 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_pcols_oom") + + list(APPEND mytests http-client-fi-vh3) + add_test(NAME http-client-fi-vh3 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_ssl_srv") + + list(APPEND mytests http-client-fi-vh4) + add_test(NAME http-client-fi-vh4 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_ssl_cli") + + list(APPEND mytests http-client-fi-vh5) + add_test(NAME http-client-fi-vh5 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_srv_init") + + + list(APPEND mytests http-client-fi-dnsfail) + add_test(NAME http-client-fi-dnsfail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi=user/dnsfail") + + if (has_async_dns) + list(APPEND mytests http-client-fi-connfail) + add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi=user/connfail") + else() + list(APPEND mytests http-client-fi-connfail) + add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 2 --fault-injection "wsi=user/connfail") + endif() + + list(APPEND mytests http-client-fi-user-est-fail) + add_test(NAME http-client-fi-user-est-fail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi/user_reject_at_est") + + + endif() + + if (DEFINED ENV{SAI_OVN}) set_tests_properties(${mytests} PROPERTIES FIXTURES_REQUIRED "res_http_client_warmcat") - endif() + endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c index 87d5a8e29..01243e5ad 100644 --- a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c @@ -73,6 +73,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); interrupted = 1; + bad = 3; /* connection failed before we could make connection */ lws_cancel_service(lws_get_context(wsi)); #if defined(LWS_WITH_CONMON) @@ -97,6 +98,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, lws_h2_client_stream_long_poll_rxonly(wsi); } #endif + + if (lws_fi_user_wsi_fi(wsi, "user_reject_at_est")) + return -1; + break; #if defined(LWS_WITH_HTTP_BASIC_AUTH) @@ -132,17 +137,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, dotstar); } #endif -#if 0 /* enable to dump the html */ - { - const char *p = in; - - while (len--) - if (*p < 0x7f) - putchar(*p++); - else - putchar('.'); - } +#if 0 + lwsl_hexdump_notice(in, len); #endif + return 0; /* don't passthru */ /* uninterpreted http content */ @@ -152,6 +150,9 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, char *px = buffer + LWS_PRE; int lenx = sizeof(buffer) - LWS_PRE; + if (lws_fi_user_wsi_fi(wsi, "user_reject_at_rx")) + return -1; + if (lws_http_client_read(wsi, &px, &lenx) < 0) return -1; } @@ -304,8 +305,18 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, i.protocol = protocols[0].name; i.pwsi = &client_wsi; + i.fi_wsi_name = "user"; - return !lws_client_connect_via_info(&i); + if (!lws_client_connect_via_info(&i)) { + lwsl_err("Client creation failed\n"); + interrupted = 1; + bad = 2; /* could not even start client connection */ + lws_cancel_service(context); + + return 1; + } + + return 0; } int main(int argc, const char **argv) @@ -314,8 +325,9 @@ int main(int argc, const char **argv) lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; struct lws_context *context; + int n = 0, expected = 0; struct args args; - int n = 0; + const char *p; // uint8_t memcert[4096]; args.argc = argc; @@ -334,7 +346,7 @@ int main(int argc, const char **argv) info.protocols = protocols; info.user = &args; info.register_notifier_list = na; - info.connect_timeout_secs = 30; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with @@ -365,14 +377,24 @@ int main(int argc, const char **argv) context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); - return 1; + bad = 5; + goto bail; } while (n >= 0 && !interrupted) n = lws_service(context, 0); lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); - return bad; +bail: + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); + + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } else + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); + + return 1; } diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c index 7be451c1d..35aaaab12 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c @@ -150,6 +150,9 @@ do_client_conn(void) i.origin = i.address; i.method = "GET"; i.local_protocol_name = protocols[0].name; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + i.fi_wsi_name = "user"; +#endif if (!lws_client_connect_via_info(&i)) { lwsl_err("Client creation failed\n"); diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index 9a9d11422..e93b54298 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -182,7 +182,8 @@ int main(int argc, const char **argv) * Create our own "foreign" UDP socket bound to 7681/udp */ if (!lws_create_adopt_udp(vhost, NULL, 7681, LWS_CAUDP_BIND, - protocols[0].name, NULL, NULL, NULL, NULL)) { + protocols[0].name, NULL, NULL, NULL, NULL, + "user")) { lwsl_err("%s: foreign socket adoption failed\n", __func__); goto bail; } diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c b/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c index 122cf7c96..773f11e6d 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c @@ -34,6 +34,7 @@ static int interrupted, bad = 1, port = 0 /* unix domain socket */; static const char *ibind = NULL; /* default to unix domain skt "proxy.ss.lws" */ static lws_state_notify_link_t nl; +static struct lws_context *context; /* * We just define enough policy so it can fetch the latest one securely @@ -233,41 +234,21 @@ static const lws_system_ops_t system_ops = { static void sigint_handler(int sig) { + lwsl_notice("%s\n", __func__); interrupted = 1; -} - -static void -assert_bt(int sig) -{ -#if defined(__APPLE__) || defined(__linux__) - void *array[20]; - char **strings; - int size, i; - - size = backtrace (array, 10); - strings = backtrace_symbols (array, size); - if (!strings) - return; - - for (i = 0; i < size; i++) - printf("%s\n", strings[i]); - - free (strings); -#endif + lws_cancel_service(context); } int main(int argc, const char **argv) { - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; struct lws_context_creation_info info; - struct lws_context *context; const char *p; + int n = 0; + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); signal(SIGINT, sigint_handler); - signal(SIGABRT, assert_bt); - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); /* connect to ssproxy via UDS by default, else via tcp with this port */ if ((p = lws_cmdline_option(argc, argv, "-p"))) @@ -278,11 +259,8 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "-i"))) ibind = p; - lws_set_log_level(logs, NULL); lwsl_user("LWS secure streams Proxy [-d]\n"); - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -311,8 +289,9 @@ int main(int argc, const char **argv) /* the event loop */ - while (n >= 0 && !interrupted) + do { n = lws_service(context, 0); + } while (n >= 0 && !interrupted); bad = 0; diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 36704fc6e..a53503939 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -248,13 +248,18 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ interrupted = 1; + bad = 2; break; + case LWSSSCS_QOS_ACK_REMOTE: lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); break; case LWSSSCS_TIMEOUT: lwsl_notice("%s: LWSSSCS_TIMEOUT\n", __func__); + /* if we're out of time */ + interrupted = 1; + bad = 3; break; case LWSSSCS_USER_BASE: @@ -405,8 +410,8 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; + int n = 0, expected = 0; const char *p; - int n = 0; signal(SIGINT, sigint_handler); @@ -475,7 +480,7 @@ int main(int argc, const char **argv) context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); - return 1; + goto bail; } #if !defined(LWS_SS_USE_SSPC) @@ -520,7 +525,15 @@ int main(int argc, const char **argv) lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); +bail: + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); - return bad; + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } else + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); + + return 1; }