From 736c159665ece271cefac388e33eb2368261b73c Mon Sep 17 00:00:00 2001 From: flub Date: Wed, 29 Apr 2026 10:27:25 +0000 Subject: [PATCH] deploy: 6c9469f4b115672405991b9796b490c444629de4 --- pr/619/docs/noq/enum.ClosePathError.html | 6 +- pr/619/docs/noq/enum.ConnectionError.html | 6 +- pr/619/docs/noq/enum.PathError.html | 6 +- pr/619/docs/noq/enum.SendDatagramError.html | 6 +- pr/619/docs/noq/struct.AcceptBi.html | 6 +- pr/619/docs/noq/struct.AcceptUni.html | 6 +- pr/619/docs/noq/struct.AddressDiscovery.html | 4 +- pr/619/docs/noq/struct.Connecting.html | 6 +- pr/619/docs/noq/struct.Connection.html | 98 +- pr/619/docs/noq/struct.OnClosed.html | 4 +- pr/619/docs/noq/struct.OpenBi.html | 6 +- pr/619/docs/noq/struct.OpenUni.html | 6 +- pr/619/docs/noq/struct.Path.html | 11 +- pr/619/docs/noq/struct.ReadDatagram.html | 6 +- pr/619/docs/noq/struct.SendDatagram.html | 6 +- .../docs/noq/struct.WeakConnectionHandle.html | 10 +- pr/619/docs/noq/struct.WeakPathHandle.html | 10 +- pr/619/docs/noq/struct.ZeroRttAccepted.html | 4 +- pr/619/docs/noq/trait.NetworkChangeHint.html | 4 +- .../docs/noq_proto/enum.ClosePathError.html | 6 +- .../docs/noq_proto/enum.ConnectionError.html | 6 +- pr/619/docs/noq_proto/enum.Event.html | 4 +- pr/619/docs/noq_proto/enum.PathError.html | 6 +- pr/619/docs/noq_proto/enum.PathEvent.html | 2 +- pr/619/docs/noq_proto/struct.Connection.html | 70 +- .../struct.MultipathNotNegotiated.html | 4 +- .../docs/noq_proto/struct.TransportError.html | 2 +- .../noq_proto/trait.NetworkChangeHint.html | 4 +- pr/619/docs/perf/server/index.html | 2 +- pr/619/docs/search.index/0007afbe4a1e.js | 1 - pr/619/docs/search.index/003d0358f65c.js | 1 + pr/619/docs/search.index/0072ff485b3d.js | 1 + pr/619/docs/search.index/0074467c55f3.js | 1 + pr/619/docs/search.index/0076e0f9ae1b.js | 1 - pr/619/docs/search.index/00e155de90d9.js | 1 - pr/619/docs/search.index/00ee301dfa9b.js | 1 - .../{16832093cb10.js => 00fda0fef97d.js} | 2 +- pr/619/docs/search.index/0113920737b2.js | 1 + pr/619/docs/search.index/01179ef58d64.js | 1 + pr/619/docs/search.index/02cb2f01921a.js | 1 + pr/619/docs/search.index/03098f8f36f0.js | 1 + pr/619/docs/search.index/03534d6a80b5.js | 1 + pr/619/docs/search.index/03ee76ce924c.js | 1 - pr/619/docs/search.index/03fef7854a4e.js | 1 + pr/619/docs/search.index/04280654882e.js | 1 + pr/619/docs/search.index/04460d3da660.js | 1 + pr/619/docs/search.index/044bd26a62da.js | 1 - pr/619/docs/search.index/04e46d976d32.js | 1 - pr/619/docs/search.index/04f13de54089.js | 1 - pr/619/docs/search.index/053d8e28fefb.js | 1 - pr/619/docs/search.index/05cdd3acb27b.js | 1 + pr/619/docs/search.index/05f9c5191180.js | 1 + pr/619/docs/search.index/069af7b6cfda.js | 1 + pr/619/docs/search.index/06e54bb1f956.js | 1 + pr/619/docs/search.index/072f914cace1.js | 1 - pr/619/docs/search.index/074bfcb6336f.js | 1 + pr/619/docs/search.index/084b410c630d.js | 1 + .../{724469503f12.js => 08613fa638dc.js} | 2 +- pr/619/docs/search.index/090f98468b1e.js | 1 - pr/619/docs/search.index/0922c28c8228.js | 1 - pr/619/docs/search.index/097f0b930929.js | 1 + pr/619/docs/search.index/0a07ec521ff0.js | 1 - pr/619/docs/search.index/0a8a212c9645.js | 1 + pr/619/docs/search.index/0ac376e86095.js | 1 + pr/619/docs/search.index/0b6366326bb6.js | 1 - pr/619/docs/search.index/0b86da30c91a.js | 1 - pr/619/docs/search.index/0c0a3ac3c3ab.js | 1 + pr/619/docs/search.index/0c270d347467.js | 1 + pr/619/docs/search.index/0c93807c54f2.js | 1 + pr/619/docs/search.index/0d1b75fe6868.js | 1 - pr/619/docs/search.index/0d4624154f2d.js | 1 - pr/619/docs/search.index/0d714d59fce3.js | 1 + pr/619/docs/search.index/0e1d5ce71b67.js | 1 - pr/619/docs/search.index/0e3272544c9f.js | 1 + pr/619/docs/search.index/0e58e1bb907a.js | 1 + pr/619/docs/search.index/0e7e85b355d2.js | 1 + pr/619/docs/search.index/0ef2ff5ecde1.js | 1 - pr/619/docs/search.index/0f010111b606.js | 1 + pr/619/docs/search.index/0ffd4bca177b.js | 1 - pr/619/docs/search.index/10205aeb3afc.js | 1 - pr/619/docs/search.index/1027029693c7.js | 1 - pr/619/docs/search.index/1054b7cef79e.js | 1 - pr/619/docs/search.index/11080eab78d7.js | 1 + pr/619/docs/search.index/113efc17a327.js | 1 - pr/619/docs/search.index/115969eb294f.js | 1 - pr/619/docs/search.index/116035aee40f.js | 1 - pr/619/docs/search.index/121b35b185ca.js | 1 - pr/619/docs/search.index/122997da0a01.js | 1 + pr/619/docs/search.index/12aea47c4523.js | 1 - pr/619/docs/search.index/12c0183bdd8b.js | 1 + pr/619/docs/search.index/12c236cb8009.js | 1 - pr/619/docs/search.index/135a83bd03db.js | 1 + pr/619/docs/search.index/138816621609.js | 1 - pr/619/docs/search.index/13948c9f9736.js | 1 - pr/619/docs/search.index/139d3d613348.js | 1 - pr/619/docs/search.index/13a818f01933.js | 1 - pr/619/docs/search.index/1411b24ac546.js | 1 - pr/619/docs/search.index/146d3be3d959.js | 1 + pr/619/docs/search.index/1472ccb432ba.js | 1 + pr/619/docs/search.index/147bf4a9aa00.js | 1 - pr/619/docs/search.index/158247ec2aa8.js | 1 + pr/619/docs/search.index/15a4e01e0b92.js | 1 - pr/619/docs/search.index/16f09b5de525.js | 1 - pr/619/docs/search.index/16f491f146e5.js | 1 + pr/619/docs/search.index/17184d64783b.js | 1 + pr/619/docs/search.index/179216a7d32e.js | 1 - pr/619/docs/search.index/17bd24afd385.js | 1 - pr/619/docs/search.index/180af5c927d2.js | 1 + pr/619/docs/search.index/183c7cb9c0b3.js | 1 - pr/619/docs/search.index/18c195f86148.js | 1 + pr/619/docs/search.index/1921a81b6ef5.js | 1 + pr/619/docs/search.index/1a644fbba3cb.js | 1 - pr/619/docs/search.index/1a800e9c8293.js | 1 - pr/619/docs/search.index/1a989f91d70f.js | 1 + pr/619/docs/search.index/1adf7d09a2d4.js | 1 - pr/619/docs/search.index/1ae8c9ceb124.js | 1 + pr/619/docs/search.index/1b2c46b17d90.js | 1 - pr/619/docs/search.index/1b75e1cecf5e.js | 1 + pr/619/docs/search.index/1b7f85a1565f.js | 1 - pr/619/docs/search.index/1bbdc0f8e5e9.js | 1 - pr/619/docs/search.index/1c47dbb0412a.js | 1 + pr/619/docs/search.index/1c6850fbc408.js | 1 - pr/619/docs/search.index/1c7dd0f38597.js | 1 + pr/619/docs/search.index/1ca4225d7479.js | 1 + pr/619/docs/search.index/1d8b2f1b629f.js | 1 - pr/619/docs/search.index/1f1ee380fec9.js | 1 - pr/619/docs/search.index/1fa35b1e6419.js | 1 - pr/619/docs/search.index/1fb996d7a506.js | 1 - pr/619/docs/search.index/20887c9c6a32.js | 1 - pr/619/docs/search.index/212a3b848bca.js | 1 - pr/619/docs/search.index/21ace249e57c.js | 1 + pr/619/docs/search.index/21b5a273209d.js | 1 - pr/619/docs/search.index/22d71b69fe53.js | 1 - pr/619/docs/search.index/23121bb3cfba.js | 1 + pr/619/docs/search.index/2341c468e163.js | 1 - pr/619/docs/search.index/2365407c51d1.js | 1 + pr/619/docs/search.index/24048c7d32ce.js | 1 - pr/619/docs/search.index/2457a8245b21.js | 1 - pr/619/docs/search.index/24eb37241fd9.js | 1 + pr/619/docs/search.index/253a1a2f3af2.js | 1 + pr/619/docs/search.index/258f74639e7e.js | 1 + pr/619/docs/search.index/261bd9c5a7ae.js | 1 + pr/619/docs/search.index/26c726b9a1ff.js | 1 - pr/619/docs/search.index/26c9d07115ed.js | 1 + pr/619/docs/search.index/26da58cfcc22.js | 1 + pr/619/docs/search.index/26f7810019b9.js | 1 + pr/619/docs/search.index/278e7db09dfe.js | 1 - pr/619/docs/search.index/2792eabda019.js | 1 + pr/619/docs/search.index/27986af38333.js | 1 + pr/619/docs/search.index/287bdd249076.js | 1 + pr/619/docs/search.index/293b0c0e4c00.js | 1 - pr/619/docs/search.index/2a0fddb4ea90.js | 1 + pr/619/docs/search.index/2a60d7315b5a.js | 1 - pr/619/docs/search.index/2acf06bb018a.js | 1 + pr/619/docs/search.index/2adcb0ce9ddb.js | 1 + pr/619/docs/search.index/2af0babf5073.js | 1 - pr/619/docs/search.index/2b7fd9f87c9b.js | 1 + pr/619/docs/search.index/2b9a15e4da70.js | 1 + pr/619/docs/search.index/2bc73e9cd7d3.js | 1 - pr/619/docs/search.index/2c07d4061000.js | 1 - pr/619/docs/search.index/2c3aac18c124.js | 1 - pr/619/docs/search.index/2c44f0df5c90.js | 1 + pr/619/docs/search.index/2c5286276032.js | 1 + pr/619/docs/search.index/2cd6064912c5.js | 1 + pr/619/docs/search.index/2d92946fc8de.js | 1 + pr/619/docs/search.index/2e19ea627523.js | 1 - pr/619/docs/search.index/2e309b1ddfc0.js | 1 + pr/619/docs/search.index/2e6ec339b5c9.js | 1 + pr/619/docs/search.index/2ecb7d9903c8.js | 1 + pr/619/docs/search.index/2f0bf8f46f74.js | 1 + pr/619/docs/search.index/2f3fbe34ef8f.js | 1 + pr/619/docs/search.index/2f967e9cee72.js | 1 - pr/619/docs/search.index/300566ec33f3.js | 1 + pr/619/docs/search.index/301e73fffc4a.js | 1 + pr/619/docs/search.index/30471f8f48c9.js | 1 + pr/619/docs/search.index/30996967e28a.js | 1 + pr/619/docs/search.index/30af5de71430.js | 1 + pr/619/docs/search.index/30ca63111c0a.js | 1 - pr/619/docs/search.index/3116216cb50c.js | 1 - pr/619/docs/search.index/31359e89bbb9.js | 1 - pr/619/docs/search.index/31aec0400f56.js | 1 - pr/619/docs/search.index/31dcc78b2786.js | 1 - pr/619/docs/search.index/31e4b5cbd2f8.js | 1 + pr/619/docs/search.index/3201f7aa10ec.js | 1 - pr/619/docs/search.index/320512d77248.js | 1 - pr/619/docs/search.index/3235335929a9.js | 1 - pr/619/docs/search.index/327cc382d02d.js | 1 + pr/619/docs/search.index/3470e377b8a5.js | 1 - pr/619/docs/search.index/348eb4db4131.js | 1 - pr/619/docs/search.index/34e21c1eff8a.js | 1 + pr/619/docs/search.index/3580a7a1ae5a.js | 1 + pr/619/docs/search.index/35f4ee3323ca.js | 1 - pr/619/docs/search.index/36168b037bdf.js | 1 - pr/619/docs/search.index/364e0899e234.js | 1 + pr/619/docs/search.index/364efa71ab66.js | 1 - pr/619/docs/search.index/367dd0ec2281.js | 1 - pr/619/docs/search.index/36a6df1413de.js | 1 - pr/619/docs/search.index/36ab74947c62.js | 1 + pr/619/docs/search.index/36e93ebda724.js | 1 + pr/619/docs/search.index/375a6b7ea5ac.js | 1 + pr/619/docs/search.index/37820096d35f.js | 1 - pr/619/docs/search.index/37a8671a9e5c.js | 1 + pr/619/docs/search.index/37d677adaca5.js | 1 + pr/619/docs/search.index/37dd659620c0.js | 1 + pr/619/docs/search.index/37e014765119.js | 1 - pr/619/docs/search.index/37fb467cac9a.js | 1 - pr/619/docs/search.index/381627e07c4a.js | 1 - pr/619/docs/search.index/384db2e965f3.js | 1 + pr/619/docs/search.index/386d9b10bedf.js | 1 - pr/619/docs/search.index/3888f1592d5b.js | 1 + pr/619/docs/search.index/38a288884c49.js | 1 + .../{5d7054075c79.js => 38ac6f2b5ca2.js} | 2 +- pr/619/docs/search.index/39c7b725e6d9.js | 1 - pr/619/docs/search.index/3b4ebba34e4d.js | 1 + pr/619/docs/search.index/3b59728b3fd9.js | 1 + pr/619/docs/search.index/3b9071c6bff0.js | 1 + pr/619/docs/search.index/3b9c1d6496c7.js | 1 + pr/619/docs/search.index/3bef9f9517c5.js | 1 + pr/619/docs/search.index/3c0adaab5c9d.js | 1 - pr/619/docs/search.index/3c3e3a203317.js | 1 + pr/619/docs/search.index/3c458307b0c9.js | 1 + pr/619/docs/search.index/3c9ab60377f1.js | 1 - pr/619/docs/search.index/3c9e08c1699f.js | 1 - pr/619/docs/search.index/3ca1ec2ec8ab.js | 1 + pr/619/docs/search.index/3cca7897888d.js | 1 - pr/619/docs/search.index/3cce4c537167.js | 1 + pr/619/docs/search.index/3cda01bca1f3.js | 1 + pr/619/docs/search.index/3d39c2a0de50.js | 1 + pr/619/docs/search.index/3dbbea9c55d9.js | 1 - pr/619/docs/search.index/3dfa50f90aec.js | 1 + pr/619/docs/search.index/3e0f6f7169fa.js | 1 - pr/619/docs/search.index/3e7117b77bc1.js | 1 + pr/619/docs/search.index/3e9a4fcd7329.js | 1 - pr/619/docs/search.index/3ea4023c697d.js | 1 - pr/619/docs/search.index/3f4f2cfa5535.js | 1 + pr/619/docs/search.index/3f7ffddc1a36.js | 1 + pr/619/docs/search.index/3fc46817fb62.js | 1 - pr/619/docs/search.index/3fee3aae2f7c.js | 1 + pr/619/docs/search.index/407ac64d24ca.js | 1 - pr/619/docs/search.index/409350de5974.js | 1 + pr/619/docs/search.index/409dcc2e7d00.js | 1 - pr/619/docs/search.index/40b97f872728.js | 1 - pr/619/docs/search.index/417b64643f1d.js | 1 - pr/619/docs/search.index/417d23b5a9d5.js | 1 + pr/619/docs/search.index/4188d8b1473d.js | 1 + pr/619/docs/search.index/41ad038f4378.js | 1 + pr/619/docs/search.index/41ca5c735a3c.js | 1 - pr/619/docs/search.index/41f859c3ca08.js | 1 - pr/619/docs/search.index/421c90d42076.js | 1 + pr/619/docs/search.index/4263fb6aabb3.js | 1 - pr/619/docs/search.index/42941d28362c.js | 1 + pr/619/docs/search.index/436b7e10f3f4.js | 1 - pr/619/docs/search.index/4382781d434c.js | 1 - pr/619/docs/search.index/438c1338380f.js | 1 - pr/619/docs/search.index/43a2e1b577ea.js | 1 + pr/619/docs/search.index/43be24b30c96.js | 1 - pr/619/docs/search.index/43d088068252.js | 1 - pr/619/docs/search.index/44a641e102e9.js | 1 + pr/619/docs/search.index/44b1e0e589da.js | 1 + pr/619/docs/search.index/4532c887319b.js | 1 - pr/619/docs/search.index/45772a0772e0.js | 1 - pr/619/docs/search.index/46067659099a.js | 1 - pr/619/docs/search.index/461a6040991a.js | 1 - pr/619/docs/search.index/469b0802b939.js | 1 - pr/619/docs/search.index/46d5566d7ae7.js | 1 - pr/619/docs/search.index/46e4d0320e64.js | 1 + pr/619/docs/search.index/4725f9698340.js | 1 + pr/619/docs/search.index/473725894482.js | 1 + pr/619/docs/search.index/476898cf4863.js | 1 - pr/619/docs/search.index/4804538c1395.js | 1 - pr/619/docs/search.index/48106c3c5c2c.js | 1 + pr/619/docs/search.index/48408a05a41d.js | 1 + pr/619/docs/search.index/486fe095d42b.js | 1 + pr/619/docs/search.index/4889d2edc856.js | 1 + pr/619/docs/search.index/48a29e008e15.js | 1 - pr/619/docs/search.index/48f90631aab7.js | 1 - pr/619/docs/search.index/490b10876df2.js | 1 - pr/619/docs/search.index/491b60251375.js | 1 + pr/619/docs/search.index/4937adcdd97b.js | 1 - pr/619/docs/search.index/494dbd5577e9.js | 1 - pr/619/docs/search.index/49e136f13e32.js | 1 + pr/619/docs/search.index/4a10cfb0683a.js | 1 + pr/619/docs/search.index/4a62d4a1af3d.js | 1 + .../{2e78c3c6420b.js => 4b13a43f6772.js} | 2 +- pr/619/docs/search.index/4b54ee0900f5.js | 1 - pr/619/docs/search.index/4b5ec50dbde7.js | 1 - pr/619/docs/search.index/4b6c25da1b8d.js | 1 + pr/619/docs/search.index/4b92a5eb1142.js | 1 + pr/619/docs/search.index/4bcb9b25f02d.js | 1 - pr/619/docs/search.index/4c7306736acb.js | 1 - pr/619/docs/search.index/4c8a317f35fe.js | 1 + pr/619/docs/search.index/4c8ba4ecb3a3.js | 1 - pr/619/docs/search.index/4ca1c3eded1f.js | 1 + pr/619/docs/search.index/4cc106c9c096.js | 1 - pr/619/docs/search.index/4cdfa2c543b7.js | 1 + pr/619/docs/search.index/4d8196dbc1e6.js | 1 + pr/619/docs/search.index/4e123559303b.js | 1 + pr/619/docs/search.index/4e9e267b2057.js | 1 + pr/619/docs/search.index/4f24054bf4c8.js | 1 - pr/619/docs/search.index/4f47720a4a70.js | 1 - pr/619/docs/search.index/4f50d5ca1278.js | 1 + pr/619/docs/search.index/502e82d4852b.js | 1 + pr/619/docs/search.index/5068939f60c0.js | 1 + .../{48ae650d1123.js => 506b2673d878.js} | 2 +- pr/619/docs/search.index/5070f1f10ee5.js | 1 + pr/619/docs/search.index/50aedf89c3d4.js | 1 + pr/619/docs/search.index/50b1f19bd128.js | 1 + .../{36f982cb06b4.js => 50c240033502.js} | 2 +- pr/619/docs/search.index/50d909c780ea.js | 1 - pr/619/docs/search.index/512d730914d8.js | 1 + pr/619/docs/search.index/5151488331bc.js | 1 + pr/619/docs/search.index/51515dbbfc1a.js | 1 + pr/619/docs/search.index/51550cc23ebb.js | 1 - pr/619/docs/search.index/517058123e73.js | 1 - pr/619/docs/search.index/51b113a9243a.js | 1 + pr/619/docs/search.index/522ac7ec74f9.js | 1 + pr/619/docs/search.index/52559e834367.js | 1 - pr/619/docs/search.index/5282edab2506.js | 1 + pr/619/docs/search.index/530be4a20340.js | 1 - pr/619/docs/search.index/537f1365d973.js | 1 - pr/619/docs/search.index/53bc60c79808.js | 1 - pr/619/docs/search.index/54011c82d16e.js | 1 + pr/619/docs/search.index/5495b5bb307e.js | 1 - pr/619/docs/search.index/54a96814a8d9.js | 1 + pr/619/docs/search.index/54cd2264c9fa.js | 1 + pr/619/docs/search.index/54f8e1b1ce55.js | 1 + pr/619/docs/search.index/55717c6a00ad.js | 1 + pr/619/docs/search.index/558a6ec98792.js | 1 - pr/619/docs/search.index/55c799f52241.js | 1 + pr/619/docs/search.index/55f99a25ee95.js | 1 + pr/619/docs/search.index/560456bf6138.js | 1 - pr/619/docs/search.index/56e3f5148932.js | 1 + pr/619/docs/search.index/573145d855d3.js | 1 - pr/619/docs/search.index/575a77072d0b.js | 1 + pr/619/docs/search.index/575b5c18cfe6.js | 1 - pr/619/docs/search.index/576a19df7354.js | 1 + pr/619/docs/search.index/57920d8b3eb8.js | 1 - pr/619/docs/search.index/58f342d8c6f8.js | 1 - pr/619/docs/search.index/597646fd02a2.js | 1 - pr/619/docs/search.index/59a86ab4d1f5.js | 1 + pr/619/docs/search.index/5a1a09f0a2a3.js | 1 + pr/619/docs/search.index/5a9b2df043b7.js | 1 - pr/619/docs/search.index/5b33e7b2e8ac.js | 1 - pr/619/docs/search.index/5b499f990c5c.js | 1 - pr/619/docs/search.index/5b5f9cd06395.js | 1 - pr/619/docs/search.index/5b6614ab60f9.js | 1 - pr/619/docs/search.index/5b7f3b18b806.js | 1 - .../{006efa80c79b.js => 5b87a2dfb37f.js} | 2 +- pr/619/docs/search.index/5c081caa8d23.js | 1 - pr/619/docs/search.index/5c4b51f4875f.js | 1 - pr/619/docs/search.index/5c7d0b0c55d0.js | 1 - pr/619/docs/search.index/5cad8e1cb609.js | 1 - pr/619/docs/search.index/5cf9082a3bd3.js | 1 + pr/619/docs/search.index/5d5311cd5bf9.js | 1 - pr/619/docs/search.index/5e57b15a881e.js | 1 + pr/619/docs/search.index/5edc2ab10d4f.js | 1 + pr/619/docs/search.index/5ee13d39262b.js | 1 + pr/619/docs/search.index/5ef0351c7da4.js | 1 - pr/619/docs/search.index/5f168d03cb64.js | 1 - pr/619/docs/search.index/5fb00a88a718.js | 1 - pr/619/docs/search.index/604e2f19f907.js | 1 - pr/619/docs/search.index/6126cb0a3314.js | 1 + pr/619/docs/search.index/612b1c20b390.js | 1 + pr/619/docs/search.index/61e642656581.js | 1 + pr/619/docs/search.index/6204ff5bc229.js | 1 - pr/619/docs/search.index/62357ed0a8f2.js | 1 + pr/619/docs/search.index/623acef83daa.js | 1 + pr/619/docs/search.index/624d4fcb2468.js | 1 + pr/619/docs/search.index/6270a92ca42a.js | 1 - pr/619/docs/search.index/62eae10a92b2.js | 1 + pr/619/docs/search.index/63db0133e5a7.js | 1 - pr/619/docs/search.index/642b84d73e0d.js | 1 + pr/619/docs/search.index/64336b5290b0.js | 1 - pr/619/docs/search.index/6495a83641f9.js | 1 - pr/619/docs/search.index/64a6287ecae1.js | 1 + pr/619/docs/search.index/652b221c4360.js | 1 + pr/619/docs/search.index/65463ff680b5.js | 1 + pr/619/docs/search.index/6547187e7e81.js | 1 - pr/619/docs/search.index/657095ac6c20.js | 1 + pr/619/docs/search.index/65d7f0f56d36.js | 1 + pr/619/docs/search.index/65fced5fb18c.js | 1 + pr/619/docs/search.index/6635658ace13.js | 1 - pr/619/docs/search.index/664a448ebb15.js | 1 - pr/619/docs/search.index/665c853e8913.js | 1 - pr/619/docs/search.index/66c8d3a8ed30.js | 1 - pr/619/docs/search.index/66d062150add.js | 1 - pr/619/docs/search.index/6707166781ac.js | 1 + pr/619/docs/search.index/6733f8336dde.js | 1 + pr/619/docs/search.index/67b1ae83fd68.js | 1 - pr/619/docs/search.index/68884d4c1398.js | 1 - pr/619/docs/search.index/68ece63de0b2.js | 1 + pr/619/docs/search.index/69477c6171ff.js | 1 - pr/619/docs/search.index/6a8b122a8833.js | 1 - pr/619/docs/search.index/6af725c39cbd.js | 1 + pr/619/docs/search.index/6b3f760f828d.js | 1 - pr/619/docs/search.index/6b4af5b9cce5.js | 1 - pr/619/docs/search.index/6b9ac143a49f.js | 1 - pr/619/docs/search.index/6b9afa46ea73.js | 1 + pr/619/docs/search.index/6b9f939265d9.js | 1 - pr/619/docs/search.index/6c3a7ed9893f.js | 1 - pr/619/docs/search.index/6c65d8f022b6.js | 1 + pr/619/docs/search.index/6c6fd1c60881.js | 1 + pr/619/docs/search.index/6ce4893b3d85.js | 1 - pr/619/docs/search.index/6d4789e20b5d.js | 1 - pr/619/docs/search.index/6d907d4f4ecd.js | 1 - pr/619/docs/search.index/6e0237fddaf9.js | 1 - pr/619/docs/search.index/6e36418a6b2a.js | 1 - pr/619/docs/search.index/6e756b7be8af.js | 1 - pr/619/docs/search.index/6e951ec52a5e.js | 1 - pr/619/docs/search.index/6ef33c9e5294.js | 1 + pr/619/docs/search.index/6efd68c23a2e.js | 1 + pr/619/docs/search.index/6f0652676cb6.js | 1 - pr/619/docs/search.index/6f4ddc2fa0ef.js | 1 - pr/619/docs/search.index/6fe4512f74c9.js | 1 + pr/619/docs/search.index/6ff2473e7df7.js | 1 - pr/619/docs/search.index/701d23b5721f.js | 1 - pr/619/docs/search.index/704723e7598f.js | 1 - pr/619/docs/search.index/7081024babaf.js | 1 - pr/619/docs/search.index/70a80acda88a.js | 1 - pr/619/docs/search.index/70abc9bdb948.js | 1 + pr/619/docs/search.index/7105bb415f63.js | 1 - pr/619/docs/search.index/71878b673d60.js | 1 + pr/619/docs/search.index/7191e94af5e0.js | 1 - pr/619/docs/search.index/71afe78ac6d4.js | 1 + pr/619/docs/search.index/71c746032e91.js | 1 - pr/619/docs/search.index/723df646870e.js | 1 + pr/619/docs/search.index/730acf77735f.js | 1 - pr/619/docs/search.index/73730d6f0681.js | 1 + pr/619/docs/search.index/738b1982f2f2.js | 1 - pr/619/docs/search.index/73f291f4a740.js | 1 + pr/619/docs/search.index/7481844ee2d2.js | 1 - pr/619/docs/search.index/74e1dac109d2.js | 1 - .../{01c8144aed81.js => 74f0801909fc.js} | 2 +- pr/619/docs/search.index/7531d92ef543.js | 1 + pr/619/docs/search.index/75a09cbe7feb.js | 1 + pr/619/docs/search.index/75a21333679c.js | 1 - pr/619/docs/search.index/75a90aa8afcb.js | 1 - pr/619/docs/search.index/75f58c5acd34.js | 1 - pr/619/docs/search.index/7669f28e496a.js | 1 + pr/619/docs/search.index/76dd52dd2d8c.js | 1 - pr/619/docs/search.index/76ed19bd7d71.js | 1 - pr/619/docs/search.index/770c52750c29.js | 1 - pr/619/docs/search.index/772fadcc62b0.js | 1 + pr/619/docs/search.index/7770a1a6381d.js | 1 - pr/619/docs/search.index/77856163ad0a.js | 1 - pr/619/docs/search.index/77a0ffd5dec4.js | 1 + pr/619/docs/search.index/77f54ff580e6.js | 1 - pr/619/docs/search.index/7818197cf8d8.js | 1 + pr/619/docs/search.index/785eb7a99207.js | 1 - pr/619/docs/search.index/7886dc8c4f27.js | 1 + pr/619/docs/search.index/78ba03951c35.js | 1 + pr/619/docs/search.index/78c30f0b3daa.js | 1 - pr/619/docs/search.index/78fd5b73bd69.js | 1 + pr/619/docs/search.index/7918c5103edf.js | 1 + pr/619/docs/search.index/791b5f37fbfa.js | 1 + pr/619/docs/search.index/794532fecbad.js | 1 + pr/619/docs/search.index/7a0147b1d120.js | 1 + pr/619/docs/search.index/7a8eed6dec67.js | 1 - pr/619/docs/search.index/7a9b6af3ec35.js | 1 - pr/619/docs/search.index/7aa67d35b328.js | 1 + pr/619/docs/search.index/7abf8916b235.js | 1 + pr/619/docs/search.index/7b27a3c761b1.js | 1 + pr/619/docs/search.index/7b4cfcfcb707.js | 1 + pr/619/docs/search.index/7b564533bf45.js | 1 + pr/619/docs/search.index/7bf37cdcde98.js | 1 - pr/619/docs/search.index/7c17a1e91f1c.js | 1 - .../{1528e494c297.js => 7c302d99a047.js} | 2 +- pr/619/docs/search.index/7d45cf1ad0f1.js | 1 - pr/619/docs/search.index/7d953c34eb92.js | 1 + pr/619/docs/search.index/7dcbe350cea7.js | 1 + pr/619/docs/search.index/7e02f86b18de.js | 1 + pr/619/docs/search.index/7e20fbd5e7ea.js | 1 + pr/619/docs/search.index/7e5f97ab36a0.js | 1 + pr/619/docs/search.index/7e7a3cefa593.js | 1 + pr/619/docs/search.index/7ee6a3493b01.js | 1 - pr/619/docs/search.index/7eed9b0d8ac9.js | 1 + pr/619/docs/search.index/7f4f82681f3d.js | 1 - pr/619/docs/search.index/7f56256940f4.js | 1 + pr/619/docs/search.index/desc/900a316ca624.js | 1 + pr/619/docs/search.index/desc/b4a947a8a2ee.js | 1 - .../docs/search.index/entry/76669476e13c.js | 1 + .../docs/search.index/entry/969c3a537ad9.js | 1 - .../search.index/function/af7dc08aa70a.js | 1 - .../search.index/function/c7020792e5cc.js | 1 + .../generic_inverted_index/4d33a67ed87f.js | 1 - .../generic_inverted_index/828b7994c50d.js | 1 + .../name/{3b16bb0727a1.js => 13e9ded8cacd.js} | 2 +- .../{5a08d7469d41.js => 9a8f39ae04e1.js} | 2 +- pr/619/docs/search.index/root.js | 2 +- pr/619/docs/search.index/type/6b2dbcbd3853.js | 1 + pr/619/docs/search.index/type/9ea587c05e74.js | 1 - pr/619/docs/src/noq/connection.rs.html | 3288 ++-- pr/619/docs/src/noq/path.rs.html | 273 +- .../docs/src/noq_proto/connection/mod.rs.html | 12415 ++++++++-------- pr/619/docs/src/perf/server.rs.html | 197 +- 495 files changed, 8470 insertions(+), 8494 deletions(-) delete mode 100644 pr/619/docs/search.index/0007afbe4a1e.js create mode 100644 pr/619/docs/search.index/003d0358f65c.js create mode 100644 pr/619/docs/search.index/0072ff485b3d.js create mode 100644 pr/619/docs/search.index/0074467c55f3.js delete mode 100644 pr/619/docs/search.index/0076e0f9ae1b.js delete mode 100644 pr/619/docs/search.index/00e155de90d9.js delete mode 100644 pr/619/docs/search.index/00ee301dfa9b.js rename pr/619/docs/search.index/{16832093cb10.js => 00fda0fef97d.js} (53%) create mode 100644 pr/619/docs/search.index/0113920737b2.js create mode 100644 pr/619/docs/search.index/01179ef58d64.js create mode 100644 pr/619/docs/search.index/02cb2f01921a.js create mode 100644 pr/619/docs/search.index/03098f8f36f0.js create mode 100644 pr/619/docs/search.index/03534d6a80b5.js delete mode 100644 pr/619/docs/search.index/03ee76ce924c.js create mode 100644 pr/619/docs/search.index/03fef7854a4e.js create mode 100644 pr/619/docs/search.index/04280654882e.js create mode 100644 pr/619/docs/search.index/04460d3da660.js delete mode 100644 pr/619/docs/search.index/044bd26a62da.js delete mode 100644 pr/619/docs/search.index/04e46d976d32.js delete mode 100644 pr/619/docs/search.index/04f13de54089.js delete mode 100644 pr/619/docs/search.index/053d8e28fefb.js create mode 100644 pr/619/docs/search.index/05cdd3acb27b.js create mode 100644 pr/619/docs/search.index/05f9c5191180.js create mode 100644 pr/619/docs/search.index/069af7b6cfda.js create mode 100644 pr/619/docs/search.index/06e54bb1f956.js delete mode 100644 pr/619/docs/search.index/072f914cace1.js create mode 100644 pr/619/docs/search.index/074bfcb6336f.js create mode 100644 pr/619/docs/search.index/084b410c630d.js rename pr/619/docs/search.index/{724469503f12.js => 08613fa638dc.js} (53%) delete mode 100644 pr/619/docs/search.index/090f98468b1e.js delete mode 100644 pr/619/docs/search.index/0922c28c8228.js create mode 100644 pr/619/docs/search.index/097f0b930929.js delete mode 100644 pr/619/docs/search.index/0a07ec521ff0.js create mode 100644 pr/619/docs/search.index/0a8a212c9645.js create mode 100644 pr/619/docs/search.index/0ac376e86095.js delete mode 100644 pr/619/docs/search.index/0b6366326bb6.js delete mode 100644 pr/619/docs/search.index/0b86da30c91a.js create mode 100644 pr/619/docs/search.index/0c0a3ac3c3ab.js create mode 100644 pr/619/docs/search.index/0c270d347467.js create mode 100644 pr/619/docs/search.index/0c93807c54f2.js delete mode 100644 pr/619/docs/search.index/0d1b75fe6868.js delete mode 100644 pr/619/docs/search.index/0d4624154f2d.js create mode 100644 pr/619/docs/search.index/0d714d59fce3.js delete mode 100644 pr/619/docs/search.index/0e1d5ce71b67.js create mode 100644 pr/619/docs/search.index/0e3272544c9f.js create mode 100644 pr/619/docs/search.index/0e58e1bb907a.js create mode 100644 pr/619/docs/search.index/0e7e85b355d2.js delete mode 100644 pr/619/docs/search.index/0ef2ff5ecde1.js create mode 100644 pr/619/docs/search.index/0f010111b606.js delete mode 100644 pr/619/docs/search.index/0ffd4bca177b.js delete mode 100644 pr/619/docs/search.index/10205aeb3afc.js delete mode 100644 pr/619/docs/search.index/1027029693c7.js delete mode 100644 pr/619/docs/search.index/1054b7cef79e.js create mode 100644 pr/619/docs/search.index/11080eab78d7.js delete mode 100644 pr/619/docs/search.index/113efc17a327.js delete mode 100644 pr/619/docs/search.index/115969eb294f.js delete mode 100644 pr/619/docs/search.index/116035aee40f.js delete mode 100644 pr/619/docs/search.index/121b35b185ca.js create mode 100644 pr/619/docs/search.index/122997da0a01.js delete mode 100644 pr/619/docs/search.index/12aea47c4523.js create mode 100644 pr/619/docs/search.index/12c0183bdd8b.js delete mode 100644 pr/619/docs/search.index/12c236cb8009.js create mode 100644 pr/619/docs/search.index/135a83bd03db.js delete mode 100644 pr/619/docs/search.index/138816621609.js delete mode 100644 pr/619/docs/search.index/13948c9f9736.js delete mode 100644 pr/619/docs/search.index/139d3d613348.js delete mode 100644 pr/619/docs/search.index/13a818f01933.js delete mode 100644 pr/619/docs/search.index/1411b24ac546.js create mode 100644 pr/619/docs/search.index/146d3be3d959.js create mode 100644 pr/619/docs/search.index/1472ccb432ba.js delete mode 100644 pr/619/docs/search.index/147bf4a9aa00.js create mode 100644 pr/619/docs/search.index/158247ec2aa8.js delete mode 100644 pr/619/docs/search.index/15a4e01e0b92.js delete mode 100644 pr/619/docs/search.index/16f09b5de525.js create mode 100644 pr/619/docs/search.index/16f491f146e5.js create mode 100644 pr/619/docs/search.index/17184d64783b.js delete mode 100644 pr/619/docs/search.index/179216a7d32e.js delete mode 100644 pr/619/docs/search.index/17bd24afd385.js create mode 100644 pr/619/docs/search.index/180af5c927d2.js delete mode 100644 pr/619/docs/search.index/183c7cb9c0b3.js create mode 100644 pr/619/docs/search.index/18c195f86148.js create mode 100644 pr/619/docs/search.index/1921a81b6ef5.js delete mode 100644 pr/619/docs/search.index/1a644fbba3cb.js delete mode 100644 pr/619/docs/search.index/1a800e9c8293.js create mode 100644 pr/619/docs/search.index/1a989f91d70f.js delete mode 100644 pr/619/docs/search.index/1adf7d09a2d4.js create mode 100644 pr/619/docs/search.index/1ae8c9ceb124.js delete mode 100644 pr/619/docs/search.index/1b2c46b17d90.js create mode 100644 pr/619/docs/search.index/1b75e1cecf5e.js delete mode 100644 pr/619/docs/search.index/1b7f85a1565f.js delete mode 100644 pr/619/docs/search.index/1bbdc0f8e5e9.js create mode 100644 pr/619/docs/search.index/1c47dbb0412a.js delete mode 100644 pr/619/docs/search.index/1c6850fbc408.js create mode 100644 pr/619/docs/search.index/1c7dd0f38597.js create mode 100644 pr/619/docs/search.index/1ca4225d7479.js delete mode 100644 pr/619/docs/search.index/1d8b2f1b629f.js delete mode 100644 pr/619/docs/search.index/1f1ee380fec9.js delete mode 100644 pr/619/docs/search.index/1fa35b1e6419.js delete mode 100644 pr/619/docs/search.index/1fb996d7a506.js delete mode 100644 pr/619/docs/search.index/20887c9c6a32.js delete mode 100644 pr/619/docs/search.index/212a3b848bca.js create mode 100644 pr/619/docs/search.index/21ace249e57c.js delete mode 100644 pr/619/docs/search.index/21b5a273209d.js delete mode 100644 pr/619/docs/search.index/22d71b69fe53.js create mode 100644 pr/619/docs/search.index/23121bb3cfba.js delete mode 100644 pr/619/docs/search.index/2341c468e163.js create mode 100644 pr/619/docs/search.index/2365407c51d1.js delete mode 100644 pr/619/docs/search.index/24048c7d32ce.js delete mode 100644 pr/619/docs/search.index/2457a8245b21.js create mode 100644 pr/619/docs/search.index/24eb37241fd9.js create mode 100644 pr/619/docs/search.index/253a1a2f3af2.js create mode 100644 pr/619/docs/search.index/258f74639e7e.js create mode 100644 pr/619/docs/search.index/261bd9c5a7ae.js delete mode 100644 pr/619/docs/search.index/26c726b9a1ff.js create mode 100644 pr/619/docs/search.index/26c9d07115ed.js create mode 100644 pr/619/docs/search.index/26da58cfcc22.js create mode 100644 pr/619/docs/search.index/26f7810019b9.js delete mode 100644 pr/619/docs/search.index/278e7db09dfe.js create mode 100644 pr/619/docs/search.index/2792eabda019.js create mode 100644 pr/619/docs/search.index/27986af38333.js create mode 100644 pr/619/docs/search.index/287bdd249076.js delete mode 100644 pr/619/docs/search.index/293b0c0e4c00.js create mode 100644 pr/619/docs/search.index/2a0fddb4ea90.js delete mode 100644 pr/619/docs/search.index/2a60d7315b5a.js create mode 100644 pr/619/docs/search.index/2acf06bb018a.js create mode 100644 pr/619/docs/search.index/2adcb0ce9ddb.js delete mode 100644 pr/619/docs/search.index/2af0babf5073.js create mode 100644 pr/619/docs/search.index/2b7fd9f87c9b.js create mode 100644 pr/619/docs/search.index/2b9a15e4da70.js delete mode 100644 pr/619/docs/search.index/2bc73e9cd7d3.js delete mode 100644 pr/619/docs/search.index/2c07d4061000.js delete mode 100644 pr/619/docs/search.index/2c3aac18c124.js create mode 100644 pr/619/docs/search.index/2c44f0df5c90.js create mode 100644 pr/619/docs/search.index/2c5286276032.js create mode 100644 pr/619/docs/search.index/2cd6064912c5.js create mode 100644 pr/619/docs/search.index/2d92946fc8de.js delete mode 100644 pr/619/docs/search.index/2e19ea627523.js create mode 100644 pr/619/docs/search.index/2e309b1ddfc0.js create mode 100644 pr/619/docs/search.index/2e6ec339b5c9.js create mode 100644 pr/619/docs/search.index/2ecb7d9903c8.js create mode 100644 pr/619/docs/search.index/2f0bf8f46f74.js create mode 100644 pr/619/docs/search.index/2f3fbe34ef8f.js delete mode 100644 pr/619/docs/search.index/2f967e9cee72.js create mode 100644 pr/619/docs/search.index/300566ec33f3.js create mode 100644 pr/619/docs/search.index/301e73fffc4a.js create mode 100644 pr/619/docs/search.index/30471f8f48c9.js create mode 100644 pr/619/docs/search.index/30996967e28a.js create mode 100644 pr/619/docs/search.index/30af5de71430.js delete mode 100644 pr/619/docs/search.index/30ca63111c0a.js delete mode 100644 pr/619/docs/search.index/3116216cb50c.js delete mode 100644 pr/619/docs/search.index/31359e89bbb9.js delete mode 100644 pr/619/docs/search.index/31aec0400f56.js delete mode 100644 pr/619/docs/search.index/31dcc78b2786.js create mode 100644 pr/619/docs/search.index/31e4b5cbd2f8.js delete mode 100644 pr/619/docs/search.index/3201f7aa10ec.js delete mode 100644 pr/619/docs/search.index/320512d77248.js delete mode 100644 pr/619/docs/search.index/3235335929a9.js create mode 100644 pr/619/docs/search.index/327cc382d02d.js delete mode 100644 pr/619/docs/search.index/3470e377b8a5.js delete mode 100644 pr/619/docs/search.index/348eb4db4131.js create mode 100644 pr/619/docs/search.index/34e21c1eff8a.js create mode 100644 pr/619/docs/search.index/3580a7a1ae5a.js delete mode 100644 pr/619/docs/search.index/35f4ee3323ca.js delete mode 100644 pr/619/docs/search.index/36168b037bdf.js create mode 100644 pr/619/docs/search.index/364e0899e234.js delete mode 100644 pr/619/docs/search.index/364efa71ab66.js delete mode 100644 pr/619/docs/search.index/367dd0ec2281.js delete mode 100644 pr/619/docs/search.index/36a6df1413de.js create mode 100644 pr/619/docs/search.index/36ab74947c62.js create mode 100644 pr/619/docs/search.index/36e93ebda724.js create mode 100644 pr/619/docs/search.index/375a6b7ea5ac.js delete mode 100644 pr/619/docs/search.index/37820096d35f.js create mode 100644 pr/619/docs/search.index/37a8671a9e5c.js create mode 100644 pr/619/docs/search.index/37d677adaca5.js create mode 100644 pr/619/docs/search.index/37dd659620c0.js delete mode 100644 pr/619/docs/search.index/37e014765119.js delete mode 100644 pr/619/docs/search.index/37fb467cac9a.js delete mode 100644 pr/619/docs/search.index/381627e07c4a.js create mode 100644 pr/619/docs/search.index/384db2e965f3.js delete mode 100644 pr/619/docs/search.index/386d9b10bedf.js create mode 100644 pr/619/docs/search.index/3888f1592d5b.js create mode 100644 pr/619/docs/search.index/38a288884c49.js rename pr/619/docs/search.index/{5d7054075c79.js => 38ac6f2b5ca2.js} (52%) delete mode 100644 pr/619/docs/search.index/39c7b725e6d9.js create mode 100644 pr/619/docs/search.index/3b4ebba34e4d.js create mode 100644 pr/619/docs/search.index/3b59728b3fd9.js create mode 100644 pr/619/docs/search.index/3b9071c6bff0.js create mode 100644 pr/619/docs/search.index/3b9c1d6496c7.js create mode 100644 pr/619/docs/search.index/3bef9f9517c5.js delete mode 100644 pr/619/docs/search.index/3c0adaab5c9d.js create mode 100644 pr/619/docs/search.index/3c3e3a203317.js create mode 100644 pr/619/docs/search.index/3c458307b0c9.js delete mode 100644 pr/619/docs/search.index/3c9ab60377f1.js delete mode 100644 pr/619/docs/search.index/3c9e08c1699f.js create mode 100644 pr/619/docs/search.index/3ca1ec2ec8ab.js delete mode 100644 pr/619/docs/search.index/3cca7897888d.js create mode 100644 pr/619/docs/search.index/3cce4c537167.js create mode 100644 pr/619/docs/search.index/3cda01bca1f3.js create mode 100644 pr/619/docs/search.index/3d39c2a0de50.js delete mode 100644 pr/619/docs/search.index/3dbbea9c55d9.js create mode 100644 pr/619/docs/search.index/3dfa50f90aec.js delete mode 100644 pr/619/docs/search.index/3e0f6f7169fa.js create mode 100644 pr/619/docs/search.index/3e7117b77bc1.js delete mode 100644 pr/619/docs/search.index/3e9a4fcd7329.js delete mode 100644 pr/619/docs/search.index/3ea4023c697d.js create mode 100644 pr/619/docs/search.index/3f4f2cfa5535.js create mode 100644 pr/619/docs/search.index/3f7ffddc1a36.js delete mode 100644 pr/619/docs/search.index/3fc46817fb62.js create mode 100644 pr/619/docs/search.index/3fee3aae2f7c.js delete mode 100644 pr/619/docs/search.index/407ac64d24ca.js create mode 100644 pr/619/docs/search.index/409350de5974.js delete mode 100644 pr/619/docs/search.index/409dcc2e7d00.js delete mode 100644 pr/619/docs/search.index/40b97f872728.js delete mode 100644 pr/619/docs/search.index/417b64643f1d.js create mode 100644 pr/619/docs/search.index/417d23b5a9d5.js create mode 100644 pr/619/docs/search.index/4188d8b1473d.js create mode 100644 pr/619/docs/search.index/41ad038f4378.js delete mode 100644 pr/619/docs/search.index/41ca5c735a3c.js delete mode 100644 pr/619/docs/search.index/41f859c3ca08.js create mode 100644 pr/619/docs/search.index/421c90d42076.js delete mode 100644 pr/619/docs/search.index/4263fb6aabb3.js create mode 100644 pr/619/docs/search.index/42941d28362c.js delete mode 100644 pr/619/docs/search.index/436b7e10f3f4.js delete mode 100644 pr/619/docs/search.index/4382781d434c.js delete mode 100644 pr/619/docs/search.index/438c1338380f.js create mode 100644 pr/619/docs/search.index/43a2e1b577ea.js delete mode 100644 pr/619/docs/search.index/43be24b30c96.js delete mode 100644 pr/619/docs/search.index/43d088068252.js create mode 100644 pr/619/docs/search.index/44a641e102e9.js create mode 100644 pr/619/docs/search.index/44b1e0e589da.js delete mode 100644 pr/619/docs/search.index/4532c887319b.js delete mode 100644 pr/619/docs/search.index/45772a0772e0.js delete mode 100644 pr/619/docs/search.index/46067659099a.js delete mode 100644 pr/619/docs/search.index/461a6040991a.js delete mode 100644 pr/619/docs/search.index/469b0802b939.js delete mode 100644 pr/619/docs/search.index/46d5566d7ae7.js create mode 100644 pr/619/docs/search.index/46e4d0320e64.js create mode 100644 pr/619/docs/search.index/4725f9698340.js create mode 100644 pr/619/docs/search.index/473725894482.js delete mode 100644 pr/619/docs/search.index/476898cf4863.js delete mode 100644 pr/619/docs/search.index/4804538c1395.js create mode 100644 pr/619/docs/search.index/48106c3c5c2c.js create mode 100644 pr/619/docs/search.index/48408a05a41d.js create mode 100644 pr/619/docs/search.index/486fe095d42b.js create mode 100644 pr/619/docs/search.index/4889d2edc856.js delete mode 100644 pr/619/docs/search.index/48a29e008e15.js delete mode 100644 pr/619/docs/search.index/48f90631aab7.js delete mode 100644 pr/619/docs/search.index/490b10876df2.js create mode 100644 pr/619/docs/search.index/491b60251375.js delete mode 100644 pr/619/docs/search.index/4937adcdd97b.js delete mode 100644 pr/619/docs/search.index/494dbd5577e9.js create mode 100644 pr/619/docs/search.index/49e136f13e32.js create mode 100644 pr/619/docs/search.index/4a10cfb0683a.js create mode 100644 pr/619/docs/search.index/4a62d4a1af3d.js rename pr/619/docs/search.index/{2e78c3c6420b.js => 4b13a43f6772.js} (57%) delete mode 100644 pr/619/docs/search.index/4b54ee0900f5.js delete mode 100644 pr/619/docs/search.index/4b5ec50dbde7.js create mode 100644 pr/619/docs/search.index/4b6c25da1b8d.js create mode 100644 pr/619/docs/search.index/4b92a5eb1142.js delete mode 100644 pr/619/docs/search.index/4bcb9b25f02d.js delete mode 100644 pr/619/docs/search.index/4c7306736acb.js create mode 100644 pr/619/docs/search.index/4c8a317f35fe.js delete mode 100644 pr/619/docs/search.index/4c8ba4ecb3a3.js create mode 100644 pr/619/docs/search.index/4ca1c3eded1f.js delete mode 100644 pr/619/docs/search.index/4cc106c9c096.js create mode 100644 pr/619/docs/search.index/4cdfa2c543b7.js create mode 100644 pr/619/docs/search.index/4d8196dbc1e6.js create mode 100644 pr/619/docs/search.index/4e123559303b.js create mode 100644 pr/619/docs/search.index/4e9e267b2057.js delete mode 100644 pr/619/docs/search.index/4f24054bf4c8.js delete mode 100644 pr/619/docs/search.index/4f47720a4a70.js create mode 100644 pr/619/docs/search.index/4f50d5ca1278.js create mode 100644 pr/619/docs/search.index/502e82d4852b.js create mode 100644 pr/619/docs/search.index/5068939f60c0.js rename pr/619/docs/search.index/{48ae650d1123.js => 506b2673d878.js} (67%) create mode 100644 pr/619/docs/search.index/5070f1f10ee5.js create mode 100644 pr/619/docs/search.index/50aedf89c3d4.js create mode 100644 pr/619/docs/search.index/50b1f19bd128.js rename pr/619/docs/search.index/{36f982cb06b4.js => 50c240033502.js} (53%) delete mode 100644 pr/619/docs/search.index/50d909c780ea.js create mode 100644 pr/619/docs/search.index/512d730914d8.js create mode 100644 pr/619/docs/search.index/5151488331bc.js create mode 100644 pr/619/docs/search.index/51515dbbfc1a.js delete mode 100644 pr/619/docs/search.index/51550cc23ebb.js delete mode 100644 pr/619/docs/search.index/517058123e73.js create mode 100644 pr/619/docs/search.index/51b113a9243a.js create mode 100644 pr/619/docs/search.index/522ac7ec74f9.js delete mode 100644 pr/619/docs/search.index/52559e834367.js create mode 100644 pr/619/docs/search.index/5282edab2506.js delete mode 100644 pr/619/docs/search.index/530be4a20340.js delete mode 100644 pr/619/docs/search.index/537f1365d973.js delete mode 100644 pr/619/docs/search.index/53bc60c79808.js create mode 100644 pr/619/docs/search.index/54011c82d16e.js delete mode 100644 pr/619/docs/search.index/5495b5bb307e.js create mode 100644 pr/619/docs/search.index/54a96814a8d9.js create mode 100644 pr/619/docs/search.index/54cd2264c9fa.js create mode 100644 pr/619/docs/search.index/54f8e1b1ce55.js create mode 100644 pr/619/docs/search.index/55717c6a00ad.js delete mode 100644 pr/619/docs/search.index/558a6ec98792.js create mode 100644 pr/619/docs/search.index/55c799f52241.js create mode 100644 pr/619/docs/search.index/55f99a25ee95.js delete mode 100644 pr/619/docs/search.index/560456bf6138.js create mode 100644 pr/619/docs/search.index/56e3f5148932.js delete mode 100644 pr/619/docs/search.index/573145d855d3.js create mode 100644 pr/619/docs/search.index/575a77072d0b.js delete mode 100644 pr/619/docs/search.index/575b5c18cfe6.js create mode 100644 pr/619/docs/search.index/576a19df7354.js delete mode 100644 pr/619/docs/search.index/57920d8b3eb8.js delete mode 100644 pr/619/docs/search.index/58f342d8c6f8.js delete mode 100644 pr/619/docs/search.index/597646fd02a2.js create mode 100644 pr/619/docs/search.index/59a86ab4d1f5.js create mode 100644 pr/619/docs/search.index/5a1a09f0a2a3.js delete mode 100644 pr/619/docs/search.index/5a9b2df043b7.js delete mode 100644 pr/619/docs/search.index/5b33e7b2e8ac.js delete mode 100644 pr/619/docs/search.index/5b499f990c5c.js delete mode 100644 pr/619/docs/search.index/5b5f9cd06395.js delete mode 100644 pr/619/docs/search.index/5b6614ab60f9.js delete mode 100644 pr/619/docs/search.index/5b7f3b18b806.js rename pr/619/docs/search.index/{006efa80c79b.js => 5b87a2dfb37f.js} (55%) delete mode 100644 pr/619/docs/search.index/5c081caa8d23.js delete mode 100644 pr/619/docs/search.index/5c4b51f4875f.js delete mode 100644 pr/619/docs/search.index/5c7d0b0c55d0.js delete mode 100644 pr/619/docs/search.index/5cad8e1cb609.js create mode 100644 pr/619/docs/search.index/5cf9082a3bd3.js delete mode 100644 pr/619/docs/search.index/5d5311cd5bf9.js create mode 100644 pr/619/docs/search.index/5e57b15a881e.js create mode 100644 pr/619/docs/search.index/5edc2ab10d4f.js create mode 100644 pr/619/docs/search.index/5ee13d39262b.js delete mode 100644 pr/619/docs/search.index/5ef0351c7da4.js delete mode 100644 pr/619/docs/search.index/5f168d03cb64.js delete mode 100644 pr/619/docs/search.index/5fb00a88a718.js delete mode 100644 pr/619/docs/search.index/604e2f19f907.js create mode 100644 pr/619/docs/search.index/6126cb0a3314.js create mode 100644 pr/619/docs/search.index/612b1c20b390.js create mode 100644 pr/619/docs/search.index/61e642656581.js delete mode 100644 pr/619/docs/search.index/6204ff5bc229.js create mode 100644 pr/619/docs/search.index/62357ed0a8f2.js create mode 100644 pr/619/docs/search.index/623acef83daa.js create mode 100644 pr/619/docs/search.index/624d4fcb2468.js delete mode 100644 pr/619/docs/search.index/6270a92ca42a.js create mode 100644 pr/619/docs/search.index/62eae10a92b2.js delete mode 100644 pr/619/docs/search.index/63db0133e5a7.js create mode 100644 pr/619/docs/search.index/642b84d73e0d.js delete mode 100644 pr/619/docs/search.index/64336b5290b0.js delete mode 100644 pr/619/docs/search.index/6495a83641f9.js create mode 100644 pr/619/docs/search.index/64a6287ecae1.js create mode 100644 pr/619/docs/search.index/652b221c4360.js create mode 100644 pr/619/docs/search.index/65463ff680b5.js delete mode 100644 pr/619/docs/search.index/6547187e7e81.js create mode 100644 pr/619/docs/search.index/657095ac6c20.js create mode 100644 pr/619/docs/search.index/65d7f0f56d36.js create mode 100644 pr/619/docs/search.index/65fced5fb18c.js delete mode 100644 pr/619/docs/search.index/6635658ace13.js delete mode 100644 pr/619/docs/search.index/664a448ebb15.js delete mode 100644 pr/619/docs/search.index/665c853e8913.js delete mode 100644 pr/619/docs/search.index/66c8d3a8ed30.js delete mode 100644 pr/619/docs/search.index/66d062150add.js create mode 100644 pr/619/docs/search.index/6707166781ac.js create mode 100644 pr/619/docs/search.index/6733f8336dde.js delete mode 100644 pr/619/docs/search.index/67b1ae83fd68.js delete mode 100644 pr/619/docs/search.index/68884d4c1398.js create mode 100644 pr/619/docs/search.index/68ece63de0b2.js delete mode 100644 pr/619/docs/search.index/69477c6171ff.js delete mode 100644 pr/619/docs/search.index/6a8b122a8833.js create mode 100644 pr/619/docs/search.index/6af725c39cbd.js delete mode 100644 pr/619/docs/search.index/6b3f760f828d.js delete mode 100644 pr/619/docs/search.index/6b4af5b9cce5.js delete mode 100644 pr/619/docs/search.index/6b9ac143a49f.js create mode 100644 pr/619/docs/search.index/6b9afa46ea73.js delete mode 100644 pr/619/docs/search.index/6b9f939265d9.js delete mode 100644 pr/619/docs/search.index/6c3a7ed9893f.js create mode 100644 pr/619/docs/search.index/6c65d8f022b6.js create mode 100644 pr/619/docs/search.index/6c6fd1c60881.js delete mode 100644 pr/619/docs/search.index/6ce4893b3d85.js delete mode 100644 pr/619/docs/search.index/6d4789e20b5d.js delete mode 100644 pr/619/docs/search.index/6d907d4f4ecd.js delete mode 100644 pr/619/docs/search.index/6e0237fddaf9.js delete mode 100644 pr/619/docs/search.index/6e36418a6b2a.js delete mode 100644 pr/619/docs/search.index/6e756b7be8af.js delete mode 100644 pr/619/docs/search.index/6e951ec52a5e.js create mode 100644 pr/619/docs/search.index/6ef33c9e5294.js create mode 100644 pr/619/docs/search.index/6efd68c23a2e.js delete mode 100644 pr/619/docs/search.index/6f0652676cb6.js delete mode 100644 pr/619/docs/search.index/6f4ddc2fa0ef.js create mode 100644 pr/619/docs/search.index/6fe4512f74c9.js delete mode 100644 pr/619/docs/search.index/6ff2473e7df7.js delete mode 100644 pr/619/docs/search.index/701d23b5721f.js delete mode 100644 pr/619/docs/search.index/704723e7598f.js delete mode 100644 pr/619/docs/search.index/7081024babaf.js delete mode 100644 pr/619/docs/search.index/70a80acda88a.js create mode 100644 pr/619/docs/search.index/70abc9bdb948.js delete mode 100644 pr/619/docs/search.index/7105bb415f63.js create mode 100644 pr/619/docs/search.index/71878b673d60.js delete mode 100644 pr/619/docs/search.index/7191e94af5e0.js create mode 100644 pr/619/docs/search.index/71afe78ac6d4.js delete mode 100644 pr/619/docs/search.index/71c746032e91.js create mode 100644 pr/619/docs/search.index/723df646870e.js delete mode 100644 pr/619/docs/search.index/730acf77735f.js create mode 100644 pr/619/docs/search.index/73730d6f0681.js delete mode 100644 pr/619/docs/search.index/738b1982f2f2.js create mode 100644 pr/619/docs/search.index/73f291f4a740.js delete mode 100644 pr/619/docs/search.index/7481844ee2d2.js delete mode 100644 pr/619/docs/search.index/74e1dac109d2.js rename pr/619/docs/search.index/{01c8144aed81.js => 74f0801909fc.js} (55%) create mode 100644 pr/619/docs/search.index/7531d92ef543.js create mode 100644 pr/619/docs/search.index/75a09cbe7feb.js delete mode 100644 pr/619/docs/search.index/75a21333679c.js delete mode 100644 pr/619/docs/search.index/75a90aa8afcb.js delete mode 100644 pr/619/docs/search.index/75f58c5acd34.js create mode 100644 pr/619/docs/search.index/7669f28e496a.js delete mode 100644 pr/619/docs/search.index/76dd52dd2d8c.js delete mode 100644 pr/619/docs/search.index/76ed19bd7d71.js delete mode 100644 pr/619/docs/search.index/770c52750c29.js create mode 100644 pr/619/docs/search.index/772fadcc62b0.js delete mode 100644 pr/619/docs/search.index/7770a1a6381d.js delete mode 100644 pr/619/docs/search.index/77856163ad0a.js create mode 100644 pr/619/docs/search.index/77a0ffd5dec4.js delete mode 100644 pr/619/docs/search.index/77f54ff580e6.js create mode 100644 pr/619/docs/search.index/7818197cf8d8.js delete mode 100644 pr/619/docs/search.index/785eb7a99207.js create mode 100644 pr/619/docs/search.index/7886dc8c4f27.js create mode 100644 pr/619/docs/search.index/78ba03951c35.js delete mode 100644 pr/619/docs/search.index/78c30f0b3daa.js create mode 100644 pr/619/docs/search.index/78fd5b73bd69.js create mode 100644 pr/619/docs/search.index/7918c5103edf.js create mode 100644 pr/619/docs/search.index/791b5f37fbfa.js create mode 100644 pr/619/docs/search.index/794532fecbad.js create mode 100644 pr/619/docs/search.index/7a0147b1d120.js delete mode 100644 pr/619/docs/search.index/7a8eed6dec67.js delete mode 100644 pr/619/docs/search.index/7a9b6af3ec35.js create mode 100644 pr/619/docs/search.index/7aa67d35b328.js create mode 100644 pr/619/docs/search.index/7abf8916b235.js create mode 100644 pr/619/docs/search.index/7b27a3c761b1.js create mode 100644 pr/619/docs/search.index/7b4cfcfcb707.js create mode 100644 pr/619/docs/search.index/7b564533bf45.js delete mode 100644 pr/619/docs/search.index/7bf37cdcde98.js delete mode 100644 pr/619/docs/search.index/7c17a1e91f1c.js rename pr/619/docs/search.index/{1528e494c297.js => 7c302d99a047.js} (62%) delete mode 100644 pr/619/docs/search.index/7d45cf1ad0f1.js create mode 100644 pr/619/docs/search.index/7d953c34eb92.js create mode 100644 pr/619/docs/search.index/7dcbe350cea7.js create mode 100644 pr/619/docs/search.index/7e02f86b18de.js create mode 100644 pr/619/docs/search.index/7e20fbd5e7ea.js create mode 100644 pr/619/docs/search.index/7e5f97ab36a0.js create mode 100644 pr/619/docs/search.index/7e7a3cefa593.js delete mode 100644 pr/619/docs/search.index/7ee6a3493b01.js create mode 100644 pr/619/docs/search.index/7eed9b0d8ac9.js delete mode 100644 pr/619/docs/search.index/7f4f82681f3d.js create mode 100644 pr/619/docs/search.index/7f56256940f4.js create mode 100644 pr/619/docs/search.index/desc/900a316ca624.js delete mode 100644 pr/619/docs/search.index/desc/b4a947a8a2ee.js create mode 100644 pr/619/docs/search.index/entry/76669476e13c.js delete mode 100644 pr/619/docs/search.index/entry/969c3a537ad9.js delete mode 100644 pr/619/docs/search.index/function/af7dc08aa70a.js create mode 100644 pr/619/docs/search.index/function/c7020792e5cc.js delete mode 100644 pr/619/docs/search.index/generic_inverted_index/4d33a67ed87f.js create mode 100644 pr/619/docs/search.index/generic_inverted_index/828b7994c50d.js rename pr/619/docs/search.index/name/{3b16bb0727a1.js => 13e9ded8cacd.js} (59%) rename pr/619/docs/search.index/normalizedName/{5a08d7469d41.js => 9a8f39ae04e1.js} (60%) create mode 100644 pr/619/docs/search.index/type/6b2dbcbd3853.js delete mode 100644 pr/619/docs/search.index/type/9ea587c05e74.js diff --git a/pr/619/docs/noq/enum.ClosePathError.html b/pr/619/docs/noq/enum.ClosePathError.html index 51c091460..83eaa250a 100644 --- a/pr/619/docs/noq/enum.ClosePathError.html +++ b/pr/619/docs/noq/enum.ClosePathError.html @@ -1,4 +1,4 @@ -ClosePathError in noq - Rust

ClosePathError

Enum ClosePathError 

Source
pub enum ClosePathError {
+ClosePathError in noq - Rust

ClosePathError

Enum ClosePathError 

Source
pub enum ClosePathError {
     MultipathNotNegotiated,
     ClosedPath,
     LastOpenPath,
@@ -7,8 +7,8 @@
 
§

ClosedPath

The path is already closed or was never opened

§

LastOpenPath

Cannot close the last remaining open path via the local API.

Use Connection::close to end the connection instead.

-

Trait Implementations§

Source§

impl Clone for ClosePathError

Source§

fn clone(&self) -> ClosePathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosePathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ClosePathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ClosePathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for ClosePathError

Source§

fn eq(&self, other: &ClosePathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ClosePathError

Source§

impl StructuralPartialEq for ClosePathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ClosePathError

Source§

fn clone(&self) -> ClosePathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosePathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ClosePathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ClosePathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for ClosePathError

Source§

fn eq(&self, other: &ClosePathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ClosePathError

Source§

impl StructuralPartialEq for ClosePathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/enum.ConnectionError.html b/pr/619/docs/noq/enum.ConnectionError.html index 24ddfba5f..54ee1a8b6 100644 --- a/pr/619/docs/noq/enum.ConnectionError.html +++ b/pr/619/docs/noq/enum.ConnectionError.html @@ -1,4 +1,4 @@ -ConnectionError in noq - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
+ConnectionError in noq - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
     VersionMismatch,
     TransportError(Error),
     ConnectionClosed(ConnectionClose),
@@ -20,8 +20,8 @@ and §

LocallyClosed

The local application closed the connection

§

CidsExhausted

The connection could not be created because not enough of the CID space is available

Try using longer connection IDs.

-

Trait Implementations§

Source§

impl Clone for ConnectionError

Source§

fn clone(&self) -> ConnectionError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Close> for ConnectionError

Source§

fn from(x: Close) -> ConnectionError

Converts to this type from the input type.
Source§

impl From<CloseReason> for ConnectionError

Source§

fn from(value: CloseReason) -> ConnectionError

Converts to this type from the input type.
Source§

impl From<ConnectionError> for ReadError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for ResetError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for StoppedError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for WriteError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: Error) -> ConnectionError

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionError

Source§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ConnectionError

Source§

impl StructuralPartialEq for ConnectionError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ConnectionError

Source§

fn clone(&self) -> ConnectionError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Close> for ConnectionError

Source§

fn from(x: Close) -> ConnectionError

Converts to this type from the input type.
Source§

impl From<CloseReason> for ConnectionError

Source§

fn from(value: CloseReason) -> ConnectionError

Converts to this type from the input type.
Source§

impl From<ConnectionError> for ReadError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for ResetError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for StoppedError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<ConnectionError> for WriteError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: Error) -> ConnectionError

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionError

Source§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ConnectionError

Source§

impl StructuralPartialEq for ConnectionError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/enum.PathError.html b/pr/619/docs/noq/enum.PathError.html index ffb3c02fd..27ef28aa2 100644 --- a/pr/619/docs/noq/enum.PathError.html +++ b/pr/619/docs/noq/enum.PathError.html @@ -1,4 +1,4 @@ -PathError in noq - Rust

PathError

Enum PathError 

Source
pub enum PathError {
+PathError in noq - Rust

PathError

Enum PathError 

Source
pub enum PathError {
     MultipathNotNegotiated,
     ServerSideNotAllowed,
     MaxPathIdReached,
@@ -12,8 +12,8 @@
 
§

RemoteCidsExhausted

No remote CIDs available to open a new path

§

ValidationFailed

Path could not be validated and will be abandoned

§

InvalidRemoteAddress(SocketAddr)

The remote address for the path is not supported by the endpoint

-

Trait Implementations§

Source§

impl Clone for PathError

Source§

fn clone(&self) -> PathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for PathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for PathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for PathError

Source§

fn eq(&self, other: &PathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Copy for PathError

Source§

impl Eq for PathError

Source§

impl StructuralPartialEq for PathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for PathError

Source§

fn clone(&self) -> PathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for PathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for PathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for PathError

Source§

fn eq(&self, other: &PathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Copy for PathError

Source§

impl Eq for PathError

Source§

impl StructuralPartialEq for PathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/enum.SendDatagramError.html b/pr/619/docs/noq/enum.SendDatagramError.html index 9064f2075..ccdd02d4d 100644 --- a/pr/619/docs/noq/enum.SendDatagramError.html +++ b/pr/619/docs/noq/enum.SendDatagramError.html @@ -1,4 +1,4 @@ -SendDatagramError in noq - Rust

SendDatagramError

Enum SendDatagramError 

Source
pub enum SendDatagramError {
+SendDatagramError in noq - Rust

SendDatagramError

Enum SendDatagramError 

Source
pub enum SendDatagramError {
     UnsupportedByPeer,
     Disabled,
     TooLarge,
@@ -10,8 +10,8 @@
 

Indicates that the path MTU minus overhead or the limit advertised by the peer has been exceeded.

§

ConnectionLost(ConnectionError)

The connection was lost

-

Trait Implementations§

Source§

impl Clone for SendDatagramError

Source§

fn clone(&self) -> SendDatagramError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SendDatagramError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for SendDatagramError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for SendDatagramError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for SendDatagramError

Source§

fn eq(&self, other: &SendDatagramError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for SendDatagramError

Source§

impl StructuralPartialEq for SendDatagramError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for SendDatagramError

Source§

fn clone(&self) -> SendDatagramError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SendDatagramError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for SendDatagramError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for SendDatagramError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for SendDatagramError

Source§

fn eq(&self, other: &SendDatagramError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for SendDatagramError

Source§

impl StructuralPartialEq for SendDatagramError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/struct.AcceptBi.html b/pr/619/docs/noq/struct.AcceptBi.html index 22392f301..e18841308 100644 --- a/pr/619/docs/noq/struct.AcceptBi.html +++ b/pr/619/docs/noq/struct.AcceptBi.html @@ -1,6 +1,6 @@ -AcceptBi in noq - Rust

AcceptBi

Struct AcceptBi 

Source
pub struct AcceptBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_bi

-

Trait Implementations§

Source§

impl Future for AcceptBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptBi<'a>
where +AcceptBi in noq - Rust

AcceptBi

Struct AcceptBi 

Source
pub struct AcceptBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_bi

+

Trait Implementations§

Source§

impl Future for AcceptBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptBi<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for AcceptBi<'a>

§

impl<'a> !RefUnwindSafe for AcceptBi<'a>

§

impl<'a> Send for AcceptBi<'a>

§

impl<'a> Sync for AcceptBi<'a>

§

impl<'a> !UnwindSafe for AcceptBi<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.AcceptUni.html b/pr/619/docs/noq/struct.AcceptUni.html index 5a259a576..03d1f46d4 100644 --- a/pr/619/docs/noq/struct.AcceptUni.html +++ b/pr/619/docs/noq/struct.AcceptUni.html @@ -1,6 +1,6 @@ -AcceptUni in noq - Rust

AcceptUni

Struct AcceptUni 

Source
pub struct AcceptUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_uni

-

Trait Implementations§

Source§

impl Future for AcceptUni<'_>

Source§

type Output = Result<RecvStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptUni<'a>
where +AcceptUni in noq - Rust

AcceptUni

Struct AcceptUni 

Source
pub struct AcceptUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_uni

+

Trait Implementations§

Source§

impl Future for AcceptUni<'_>

Source§

type Output = Result<RecvStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptUni<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for AcceptUni<'a>

§

impl<'a> !RefUnwindSafe for AcceptUni<'a>

§

impl<'a> Send for AcceptUni<'a>

§

impl<'a> Sync for AcceptUni<'a>

§

impl<'a> !UnwindSafe for AcceptUni<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.AddressDiscovery.html b/pr/619/docs/noq/struct.AddressDiscovery.html index b14c5a0cd..22a2d8d82 100644 --- a/pr/619/docs/noq/struct.AddressDiscovery.html +++ b/pr/619/docs/noq/struct.AddressDiscovery.html @@ -1,7 +1,7 @@ -AddressDiscovery in noq - Rust

AddressDiscovery

Struct AddressDiscovery 

Source
pub struct AddressDiscovery { /* private fields */ }
Expand description

Stream produced by Path::observed_external_addr

+AddressDiscovery in noq - Rust

AddressDiscovery

Struct AddressDiscovery 

Source
pub struct AddressDiscovery { /* private fields */ }
Expand description

Stream produced by Path::observed_external_addr

This will always return the external address most recently reported by the remote over this path. If the extension is not negotiated, this stream will never return.

-

Trait Implementations§

Source§

impl Stream for AddressDiscovery

Source§

type Item = SocketAddr

Values yielded by the stream.
Source§

fn poll_next( +

Trait Implementations§

Source§

impl Stream for AddressDiscovery

Source§

type Item = SocketAddr

Values yielded by the stream.
Source§

fn poll_next( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Option<Self::Item>>

Attempt to pull out the next value of this stream, registering the diff --git a/pr/619/docs/noq/struct.Connecting.html b/pr/619/docs/noq/struct.Connecting.html index a8723b1c8..5c1eda8bb 100644 --- a/pr/619/docs/noq/struct.Connecting.html +++ b/pr/619/docs/noq/struct.Connecting.html @@ -1,5 +1,5 @@ Connecting in noq - Rust

Connecting

Struct Connecting 

Source
pub struct Connecting { /* private fields */ }
Expand description

In-progress connection attempt future

-

Implementations§

Source§

impl Connecting

Source

pub fn into_0rtt(self) -> Result<(Connection, ZeroRttAccepted), Self>

Convert into a 0-RTT or 0.5-RTT connection at the cost of weakened security

+

Implementations§

Source§

impl Connecting

Source

pub fn into_0rtt(self) -> Result<(Connection, ZeroRttAccepted), Self>

Convert into a 0-RTT or 0.5-RTT connection at the cost of weakened security

Returns Ok immediately if the local endpoint is able to attempt sending 0/0.5-RTT data. If so, the returned Connection can be used to send application data without waiting for the rest of the handshake to complete, at the cost of weakened cryptographic security @@ -45,9 +45,9 @@ the endpoint is bound to a wildcard address like 0.0.0.0 or : information. See noq_udp::RecvMeta::dst_ip for a list of supported platforms when using noq_udp for I/O, which is the default.

Will panic if called after poll has returned Ready.

-
Source

pub fn remote_address(&self) -> SocketAddr

The peer’s UDP addresses

+
Source

pub fn remote_address(&self) -> SocketAddr

The peer’s UDP addresses

Will panic if called after poll has returned Ready.

-

Trait Implementations§

Source§

impl Debug for Connecting

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Future for Connecting

Source§

type Output = Result<Connection, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +

Trait Implementations§

Source§

impl Debug for Connecting

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Future for Connecting

Source§

type Output = Result<Connection, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.Connection.html b/pr/619/docs/noq/struct.Connection.html index 35e909b72..8c04b9738 100644 --- a/pr/619/docs/noq/struct.Connection.html +++ b/pr/619/docs/noq/struct.Connection.html @@ -1,4 +1,4 @@ -Connection in noq - Rust

Connection

Struct Connection 

Source
pub struct Connection(/* private fields */);
Expand description

A QUIC connection.

+Connection in noq - Rust

Connection

Struct Connection 

Source
pub struct Connection(/* private fields */);
Expand description

A QUIC connection.

If all references to a connection (including every clone of the Connection handle, streams of incoming streams, and the various stream types) have been dropped, then the connection will be automatically closed with an error_code of 0 and an empty reason. You can also close the @@ -8,29 +8,29 @@ receiving CONNECTION_CLOSE the peer may drop any stream data not yet de application. Connection::close() describes in more detail how to gracefully close a connection without losing application data.

May be cloned to obtain another handle to the same connection.

-

Implementations§

Source§

impl Connection

Source

pub fn weak_handle(&self) -> WeakConnectionHandle

Returns a weak reference to the inner connection struct.

-
Source

pub fn open_uni(&self) -> OpenUni<'_> ⓘ

Initiate a new outgoing unidirectional stream.

+

Implementations§

Source§

impl Connection

Source

pub fn weak_handle(&self) -> WeakConnectionHandle

Returns a weak reference to the inner connection struct.

+
Source

pub fn open_uni(&self) -> OpenUni<'_> ⓘ

Initiate a new outgoing unidirectional stream.

Streams are cheap and instantaneous to open unless blocked by flow control. As a consequence, the peer won’t be notified that a stream has been opened until the stream is actually used.

-
Source

pub fn open_bi(&self) -> OpenBi<'_> ⓘ

Initiate a new outgoing bidirectional stream.

+
Source

pub fn open_bi(&self) -> OpenBi<'_> ⓘ

Initiate a new outgoing bidirectional stream.

Streams are cheap and instantaneous to open unless blocked by flow control. As a consequence, the peer won’t be notified that a stream has been opened until the stream is actually used. Calling open_bi() then waiting on the RecvStream without writing anything to SendStream will never succeed.

-
Source

pub fn accept_uni(&self) -> AcceptUni<'_> ⓘ

Accept the next incoming uni-directional stream

-
Source

pub fn accept_bi(&self) -> AcceptBi<'_> ⓘ

Accept the next incoming bidirectional stream

+
Source

pub fn accept_uni(&self) -> AcceptUni<'_> ⓘ

Accept the next incoming uni-directional stream

+
Source

pub fn accept_bi(&self) -> AcceptBi<'_> ⓘ

Accept the next incoming bidirectional stream

Important Note: The Connection that calls open_bi() must write to its SendStream before the other Connection is able to accept_bi(). Calling open_bi() then waiting on the RecvStream without writing anything to SendStream will never succeed.

-
Source

pub fn read_datagram(&self) -> ReadDatagram<'_> ⓘ

Receive an application datagram

-
Source

pub fn open_path_ensure( +

Source

pub fn read_datagram(&self) -> ReadDatagram<'_> ⓘ

Receive an application datagram

+
Source

pub fn open_path_ensure( &self, addr: SocketAddr, initial_status: PathStatus, ) -> OpenPath ⓘ

Opens a new path if no path exists yet for the remote address.

Otherwise behaves exactly as open_path.

-
Source

pub fn open_path( +

Source

pub fn open_path( &self, addr: SocketAddr, initial_status: PathStatus, @@ -45,34 +45,34 @@ path opens. The P future, or at a later time. If the failure is immediate OpenPath::path_id will return None and the future will be ready immediately. If the failure happens later, a PathEvent will be emitted.

-

Source

pub fn path(&self, id: PathId) -> Option<Path>

Returns the Path structure of an open path

-
Source

pub fn path_events(&self) -> PathEvents

A stream of PathEvents for all paths in this connection.

+
Source

pub fn path(&self, id: PathId) -> Option<Path>

Returns the Path structure of an open path

+
Source

pub fn path_events(&self) -> PathEvents

A stream of PathEvents for all paths in this connection.

The stream will yield a PathEvent whenever there is a change in the state of any path in this connection. The events need to be processed immediately, since there isn’t an unbounded buffer for them.

If processing of events lags behind too much, you will get an error of type crate::Lagged indicating how many events were lost. The stream continues after a lag, delivering the oldest retained message next.

-
Source

pub fn nat_traversal_updates(&self) -> NatTraversalUpdates

A stream of NAT traversal updates for this connection.

+
Source

pub fn nat_traversal_updates(&self) -> NatTraversalUpdates

A stream of NAT traversal updates for this connection.

The events need to be processed immediately, since there isn’t an unbounded buffer for them.

If processing of events lags behind too much, you will get an error of type crate::Lagged indicating how many events were lost. The stream continues after a lag, delivering the oldest retained message next.

-
Source

pub async fn closed(&self) -> ConnectionError

Wait for the connection to be closed for any reason

+
Source

pub async fn closed(&self) -> ConnectionError

Wait for the connection to be closed for any reason

Despite the return type’s name, closed connections are often not an error condition at the application layer. Cases that might be routine include ConnectionError::LocallyClosed and ConnectionError::ApplicationClosed.

-
Source

pub fn on_closed(&self) -> OnClosed ⓘ

Wait for the connection to be closed without keeping a strong reference to the connection

+
Source

pub fn on_closed(&self) -> OnClosed ⓘ

Wait for the connection to be closed without keeping a strong reference to the connection

Returns a future that resolves, once the connection is closed, to a tuple of (ConnectionError, ConnectionStats).

Calling Self::closed keeps the connection alive until it is either closed locally via Connection::close or closed by the remote peer. This function instead does not keep the connection itself alive, so if all other clones of the connection are dropped, the connection will be closed implicitly even if there are futures returned from this function still being awaited.

-
Source

pub fn close_reason(&self) -> Option<ConnectionError>

Whether the connection is closed, and why.

+
Source

pub fn close_reason(&self) -> Option<ConnectionError>

Whether the connection is closed, and why.

The close_reason is always set to Some(ConnectionError) when a socket is closed; whether it was closed manually by calling Connection::close() or due to an internal error (such as an idle timeout or the peer closing the connection).

Note: when the connection is closed, connection.close_reason().is_some() will always be true.

-
Source

pub fn close(&self, error_code: VarInt, reason: &[u8])

Close the connection immediately.

+
Source

pub fn close(&self, error_code: VarInt, reason: &[u8])

Close the connection immediately.

Pending operations will fail immediately with ConnectionError::LocallyClosed. No more data is sent to the peer and the peer may drop buffered data upon receiving the CONNECTION_CLOSE frame.

@@ -93,7 +93,7 @@ endpoint. Once the local side sends a CONNECTION_CLOSE frame in response to call close() the remote endpoint may drop any data it received but is as yet undelivered to the application, including data that was acknowledged as received to the local endpoint.

-
Source

pub async fn handshake_confirmed(&self) -> Result<(), ConnectionError>

Wait for the handshake to be confirmed.

+
Source

pub async fn handshake_confirmed(&self) -> Result<(), ConnectionError>

Wait for the handshake to be confirmed.

As a server, who must be authenticated by clients, this happens when the handshake completes upon receiving a TLS Finished message from the client. @@ -101,56 +101,44 @@ In return, the server send a HANDSHAKE_DONE frame.

As a client, this happens when receiving a HANDSHAKE_DONE frame. At this point, the server has either accepted our authentication, or, if client authentication is not required, accepted our lack of authentication.

-
Source

pub fn send_datagram(&self, data: Bytes) -> Result<(), SendDatagramError>

Transmit data as an unreliable, unordered application datagram

+
Source

pub fn send_datagram(&self, data: Bytes) -> Result<(), SendDatagramError>

Transmit data as an unreliable, unordered application datagram

Application datagrams are a low-level primitive. They may be lost or delivered out of order, and data must both fit inside a single QUIC packet and be smaller than the maximum dictated by the peer.

Previously queued datagrams which are still unsent may be discarded to make space for this datagram, in order of oldest to newest.

-
Source

pub fn send_datagram_wait(&self, data: Bytes) -> SendDatagram<'_> ⓘ

Transmit data as an unreliable, unordered application datagram

+
Source

pub fn send_datagram_wait(&self, data: Bytes) -> SendDatagram<'_> ⓘ

Transmit data as an unreliable, unordered application datagram

Unlike send_datagram(), this method will wait for buffer space during congestion conditions, which effectively prioritizes old datagrams over new datagrams.

See send_datagram() for details.

-
Source

pub fn max_datagram_size(&self) -> Option<usize>

Compute the maximum size of datagrams that may be passed to send_datagram().

+
Source

pub fn max_datagram_size(&self) -> Option<usize>

Compute the maximum size of datagrams that may be passed to send_datagram().

Returns None if datagrams are unsupported by the peer or disabled locally.

This may change over the lifetime of a connection according to variation in the path MTU estimate. The peer can also enforce an arbitrarily small fixed limit, but if the peer’s limit is large this is guaranteed to be a little over a kilobyte at minimum.

Not necessarily the maximum size of received datagrams.

-
Source

pub fn datagram_send_buffer_space(&self) -> usize

Bytes available in the outgoing datagram buffer

+
Source

pub fn datagram_send_buffer_space(&self) -> usize

Bytes available in the outgoing datagram buffer

When greater than zero, calling send_datagram() with a datagram of at most this size is guaranteed not to cause older datagrams to be dropped.

-
Source

pub fn side(&self) -> Side

The side of the connection (client or server)

-
Source

pub fn remote_address(&self) -> SocketAddr

The peer’s UDP address

-

If ServerConfig::migration is true, clients may change addresses at will, -e.g. when switching to a cellular internet connection.

-

If multipath is enabled this will return the address of any -path, and may not be consistent. Prefer Path::remote_address instead.

-
Source

pub fn local_ip(&self) -> Option<IpAddr>

The local IP address which was used when the peer established -the connection

-

This can be different from the address the endpoint is bound to, in case -the endpoint is bound to a wildcard address like 0.0.0.0 or ::.

-

This will return None for clients, or when the platform does not expose this -information. See noq_udp::RecvMeta::dst_ip for a list of -supported platforms when using noq_udp for I/O, which is the default.

-
Source

pub fn rtt(&self, path_id: PathId) -> Option<Duration>

Current best estimate of this connection’s latency (round-trip-time)

-
Source

pub fn stats(&self) -> ConnectionStats

Returns connection statistics

-
Source

pub fn path_stats(&self, path_id: PathId) -> Option<PathStats>

Returns path statistics

-
Source

pub fn congestion_state(&self, path_id: PathId) -> Option<Box<dyn Controller>>

Current state of the congestion control algorithm, for debugging purposes

-
Source

pub fn handshake_data(&self) -> Option<Box<dyn Any>>

Parameters negotiated during the handshake

+
Source

pub fn side(&self) -> Side

The side of the connection (client or server)

+
Source

pub fn rtt(&self, path_id: PathId) -> Option<Duration>

Current best estimate of this connection’s latency (round-trip-time)

+
Source

pub fn stats(&self) -> ConnectionStats

Returns connection statistics

+
Source

pub fn path_stats(&self, path_id: PathId) -> Option<PathStats>

Returns path statistics

+
Source

pub fn congestion_state(&self, path_id: PathId) -> Option<Box<dyn Controller>>

Current state of the congestion control algorithm, for debugging purposes

+
Source

pub fn handshake_data(&self) -> Option<Box<dyn Any>>

Parameters negotiated during the handshake

Guaranteed to return Some on fully established connections or after Connecting::handshake_data() succeeds. See that method’s documentations for details on the returned value.

-
Source

pub fn peer_identity(&self) -> Option<Box<dyn Any>>

Cryptographic identity of the peer

+
Source

pub fn peer_identity(&self) -> Option<Box<dyn Any>>

Cryptographic identity of the peer

The dynamic type returned is determined by the configured Session. For the default rustls session, the return value can be downcast to a Vec<[rustls::pki_types::CertificateDer]>

-
Source

pub fn stable_id(&self) -> usize

A stable identifier for this connection

+
Source

pub fn stable_id(&self) -> usize

A stable identifier for this connection

Peer addresses and connection IDs can change, but this value will remain fixed for the lifetime of the connection.

-
Source

pub fn force_key_update(&self)

Update traffic keys spontaneously

+
Source

pub fn force_key_update(&self)

Update traffic keys spontaneously

This primarily exists for testing purposes.

-
Source

pub fn export_keying_material( +

Source

pub fn export_keying_material( &self, output: &mut [u8], label: &[u8], @@ -161,17 +149,17 @@ arguments and output buffers of equal length, they will get the same sequence of bytes in output. These bytes are cryptographically strong and pseudorandom, and are suitable for use as keying material.

See RFC5705 for more information.

-

Source

pub fn set_max_concurrent_uni_streams(&self, count: VarInt)

Modify the number of remotely initiated unidirectional streams that may be concurrently open

+
Source

pub fn set_max_concurrent_uni_streams(&self, count: VarInt)

Modify the number of remotely initiated unidirectional streams that may be concurrently open

No streams may be opened by the peer unless fewer than count are already open. Large counts increase both minimum and worst-case memory consumption.

-
Source

pub fn set_send_window(&self, send_window: u64)

Source

pub fn set_receive_window(&self, receive_window: VarInt)

Source

pub fn set_max_concurrent_bi_streams(&self, count: VarInt)

Modify the number of remotely initiated bidirectional streams that may be concurrently open

+
Source

pub fn set_send_window(&self, send_window: u64)

Source

pub fn set_receive_window(&self, receive_window: VarInt)

Source

pub fn set_max_concurrent_bi_streams(&self, count: VarInt)

Modify the number of remotely initiated bidirectional streams that may be concurrently open

No streams may be opened by the peer unless fewer than count are already open. Large counts increase both minimum and worst-case memory consumption.

-
Source

pub fn observed_external_addr(&self) -> ObservedExternalAddr

Track changes on our external address as reported by the peer.

-
Source

pub fn is_multipath_enabled(&self) -> bool

Is multipath enabled?

-
Source

pub fn add_nat_traversal_address( +

Source

pub fn observed_external_addr(&self) -> ObservedExternalAddr

Track changes on our external address as reported by the peer.

+
Source

pub fn is_multipath_enabled(&self) -> bool

Is multipath enabled?

+
Source

pub fn add_nat_traversal_address( &self, address: SocketAddr, ) -> Result<(), Error>

Registers one address at which this endpoint might be reachable

@@ -179,7 +167,7 @@ strong and pseudorandom, and are suitable for use as keying material.

ADD_ADDRESS frames. This allows clients to obtain server address candidates to initiate NAT traversal attempts. Clients provide their own reachable addresses in REACH_OUT frames when Self::initiate_nat_traversal_round is called.

-
Source

pub fn remove_nat_traversal_address( +

Source

pub fn remove_nat_traversal_address( &self, address: SocketAddr, ) -> Result<(), Error>

Removes one or more addresses from the set of addresses at which this endpoint is reachable

@@ -188,18 +176,18 @@ clients in REMOVE_ADDRESS frames. This allows clients to stop using server address candidates that are no longer valid for NAT traversal.

For clients, removed addresses will no longer be advertised in REACH_OUT frames.

Addresses not present in the set will be silently ignored.

-
Source

pub fn get_local_nat_traversal_addresses( +

Source

pub fn get_local_nat_traversal_addresses( &self, ) -> Result<Vec<SocketAddr>, Error>

Get the current local nat traversal addresses

-
Source

pub fn get_remote_nat_traversal_addresses( +

Source

pub fn get_remote_nat_traversal_addresses( &self, ) -> Result<Vec<SocketAddr>, Error>

Get the currently advertised nat traversal addresses by the server

-
Source

pub fn initiate_nat_traversal_round(&self) -> Result<Vec<SocketAddr>, Error>

Initiates a new nat traversal round

+
Source

pub fn initiate_nat_traversal_round(&self) -> Result<Vec<SocketAddr>, Error>

Initiates a new nat traversal round

A nat traversal round involves advertising the client’s local addresses in REACH_OUT frames, and initiating probing of the known remote addresses. When a new round is initiated, the previous one is cancelled, and paths that have not been opened are closed.

Returns the server addresses that are now being probed.

-

Trait Implementations§

Source§

impl Clone for Connection

Source§

fn clone(&self) -> Connection

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for Connection

Source§

fn clone(&self) -> Connection

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/struct.OnClosed.html b/pr/619/docs/noq/struct.OnClosed.html index fcc150193..a7bb35c6f 100644 --- a/pr/619/docs/noq/struct.OnClosed.html +++ b/pr/619/docs/noq/struct.OnClosed.html @@ -1,6 +1,6 @@ -OnClosed in noq - Rust

OnClosed

Struct OnClosed 

Source
pub struct OnClosed { /* private fields */ }
Expand description

Future returned by Connection::on_closed

+OnClosed in noq - Rust

OnClosed

Struct OnClosed 

Source
pub struct OnClosed { /* private fields */ }
Expand description

Future returned by Connection::on_closed

Resolves to a tuple of (ConnectionError, ConnectionStats).

-

Trait Implementations§

Source§

impl Drop for OnClosed

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Future for OnClosed

Source§

type Output = (ConnectionError, ConnectionStats)

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +

Trait Implementations§

Source§

impl Drop for OnClosed

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Future for OnClosed

Source§

type Output = (ConnectionError, ConnectionStats)

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.OpenBi.html b/pr/619/docs/noq/struct.OpenBi.html index a098d55ad..0debf2eca 100644 --- a/pr/619/docs/noq/struct.OpenBi.html +++ b/pr/619/docs/noq/struct.OpenBi.html @@ -1,6 +1,6 @@ -OpenBi in noq - Rust

OpenBi

Struct OpenBi 

Source
pub struct OpenBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_bi

-

Trait Implementations§

Source§

impl Future for OpenBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenBi<'a>
where +OpenBi in noq - Rust

OpenBi

Struct OpenBi 

Source
pub struct OpenBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_bi

+

Trait Implementations§

Source§

impl Future for OpenBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenBi<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for OpenBi<'a>

§

impl<'a> !RefUnwindSafe for OpenBi<'a>

§

impl<'a> Send for OpenBi<'a>

§

impl<'a> Sync for OpenBi<'a>

§

impl<'a> !UnwindSafe for OpenBi<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.OpenUni.html b/pr/619/docs/noq/struct.OpenUni.html index 54f7cedbe..324de9c42 100644 --- a/pr/619/docs/noq/struct.OpenUni.html +++ b/pr/619/docs/noq/struct.OpenUni.html @@ -1,6 +1,6 @@ -OpenUni in noq - Rust

OpenUni

Struct OpenUni 

Source
pub struct OpenUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_uni

-

Trait Implementations§

Source§

impl Future for OpenUni<'_>

Source§

type Output = Result<SendStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenUni<'a>
where +OpenUni in noq - Rust

OpenUni

Struct OpenUni 

Source
pub struct OpenUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_uni

+

Trait Implementations§

Source§

impl Future for OpenUni<'_>

Source§

type Output = Result<SendStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenUni<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for OpenUni<'a>

§

impl<'a> !RefUnwindSafe for OpenUni<'a>

§

impl<'a> Send for OpenUni<'a>

§

impl<'a> Sync for OpenUni<'a>

§

impl<'a> !UnwindSafe for OpenUni<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.Path.html b/pr/619/docs/noq/struct.Path.html index ace476fdb..93edafae5 100644 --- a/pr/619/docs/noq/struct.Path.html +++ b/pr/619/docs/noq/struct.Path.html @@ -1,7 +1,7 @@ -Path in noq - Rust

Path

Struct Path 

Source
pub struct Path { /* private fields */ }
Expand description

An open network transmission within a multipath-enabled connection.

+Path in noq - Rust

Path

Struct Path 

Source
pub struct Path { /* private fields */ }
Expand description

An open network transmission within a multipath-enabled connection.

As long as a Path or WeakPathHandle is alive, it is ensured that the PathStats for this path are not dropped even after the path is abandoned.

-

Implementations§

Source§

impl Path

Source

pub fn weak_handle(&self) -> WeakPathHandle

Returns a WeakPathHandle for this path.

+

Implementations§

Source§

impl Path

Source

pub fn weak_handle(&self) -> WeakPathHandle

Returns a WeakPathHandle for this path.

Holding a WeakPathHandle does not keep a connection alive, but ensures that the path’s stats are not dropped until the underlying connection is dropped, even if the path is abandoned.

@@ -28,8 +28,11 @@ returned.

Source

pub fn observed_external_addr(&self) -> Result<AddressDiscovery, ClosedPath>

Track changes on our external address as reported by the peer.

If the address-discovery extension is not negotiated, the stream will never return.

Source

pub fn remote_address(&self) -> Result<SocketAddr, ClosedPath>

The peer’s UDP address for this path.

-
Source

pub fn ping(&self) -> Result<(), ClosedPath>

Ping the remote endpoint over this path.

-

Trait Implementations§

Source§

impl Clone for Path

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Path

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Path

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for Path

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +
Source

pub fn local_ip(&self) -> Result<Option<IpAddr>, ClosedPath>

The local IP used for this path, if known.

+

Returns Ok(None) for clients or when the platform does not expose this information; see +noq_udp::RecvMeta::dst_ip for supported platforms.

+
Source

pub fn ping(&self) -> Result<(), ClosedPath>

Ping the remote endpoint over this path.

+

Trait Implementations§

Source§

impl Clone for Path

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Path

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Path

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for Path

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

§

impl Freeze for Path

§

impl RefUnwindSafe for Path

§

impl Send for Path

§

impl Sync for Path

§

impl Unpin for Path

§

impl UnwindSafe for Path

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.ReadDatagram.html b/pr/619/docs/noq/struct.ReadDatagram.html index 4ce3655a4..aba7eb3cb 100644 --- a/pr/619/docs/noq/struct.ReadDatagram.html +++ b/pr/619/docs/noq/struct.ReadDatagram.html @@ -1,6 +1,6 @@ -ReadDatagram in noq - Rust

ReadDatagram

Struct ReadDatagram 

Source
pub struct ReadDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::read_datagram

-

Trait Implementations§

Source§

impl Future for ReadDatagram<'_>

Source§

type Output = Result<Bytes, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for ReadDatagram<'a>
where +ReadDatagram in noq - Rust

ReadDatagram

Struct ReadDatagram 

Source
pub struct ReadDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::read_datagram

+

Trait Implementations§

Source§

impl Future for ReadDatagram<'_>

Source§

type Output = Result<Bytes, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for ReadDatagram<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for ReadDatagram<'a>

§

impl<'a> !RefUnwindSafe for ReadDatagram<'a>

§

impl<'a> Send for ReadDatagram<'a>

§

impl<'a> Sync for ReadDatagram<'a>

§

impl<'a> !UnwindSafe for ReadDatagram<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.SendDatagram.html b/pr/619/docs/noq/struct.SendDatagram.html index e29a91ed8..6f0cfcf49 100644 --- a/pr/619/docs/noq/struct.SendDatagram.html +++ b/pr/619/docs/noq/struct.SendDatagram.html @@ -1,6 +1,6 @@ -SendDatagram in noq - Rust

SendDatagram

Struct SendDatagram 

Source
pub struct SendDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::send_datagram_wait

-

Trait Implementations§

Source§

impl Future for SendDatagram<'_>

Source§

type Output = Result<(), SendDatagramError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering -the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for SendDatagram<'a>
where +SendDatagram in noq - Rust

SendDatagram

Struct SendDatagram 

Source
pub struct SendDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::send_datagram_wait

+

Trait Implementations§

Source§

impl Future for SendDatagram<'_>

Source§

type Output = Result<(), SendDatagramError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for SendDatagram<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for SendDatagram<'a>

§

impl<'a> !RefUnwindSafe for SendDatagram<'a>

§

impl<'a> Send for SendDatagram<'a>

§

impl<'a> Sync for SendDatagram<'a>

§

impl<'a> !UnwindSafe for SendDatagram<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/struct.WeakConnectionHandle.html b/pr/619/docs/noq/struct.WeakConnectionHandle.html index 6969cb307..3e05c3c97 100644 --- a/pr/619/docs/noq/struct.WeakConnectionHandle.html +++ b/pr/619/docs/noq/struct.WeakConnectionHandle.html @@ -1,10 +1,10 @@ -WeakConnectionHandle in noq - Rust

WeakConnectionHandle

Struct WeakConnectionHandle 

Source
pub struct WeakConnectionHandle(/* private fields */);
Expand description

A handle to some connection internals, use with care.

+WeakConnectionHandle in noq - Rust

WeakConnectionHandle

Struct WeakConnectionHandle 

Source
pub struct WeakConnectionHandle(/* private fields */);
Expand description

A handle to some connection internals, use with care.

This contains a weak reference to the connection so will not itself keep the connection alive.

-

Implementations§

Source§

impl WeakConnectionHandle

Source

pub fn is_alive(&self) -> bool

Returns true if the Connection associated with this handle is still alive.

-
Source

pub fn upgrade(&self) -> Option<Connection>

Upgrade the handle to a full Connection

-
Source

pub fn is_same_connection(&self, other: &Self) -> bool

Returns true if the two WeakConnectionHandle point at the same connection.

-

Trait Implementations§

Source§

impl Clone for WeakConnectionHandle

Source§

fn clone(&self) -> WeakConnectionHandle

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for WeakConnectionHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Implementations§

Source§

impl WeakConnectionHandle

Source

pub fn is_alive(&self) -> bool

Returns true if the Connection associated with this handle is still alive.

+
Source

pub fn upgrade(&self) -> Option<Connection>

Upgrade the handle to a full Connection

+
Source

pub fn is_same_connection(&self, other: &Self) -> bool

Returns true if the two WeakConnectionHandle point at the same connection.

+

Trait Implementations§

Source§

impl Clone for WeakConnectionHandle

Source§

fn clone(&self) -> WeakConnectionHandle

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for WeakConnectionHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/struct.WeakPathHandle.html b/pr/619/docs/noq/struct.WeakPathHandle.html index 967321d0a..9e6d5a2bd 100644 --- a/pr/619/docs/noq/struct.WeakPathHandle.html +++ b/pr/619/docs/noq/struct.WeakPathHandle.html @@ -1,12 +1,12 @@ -WeakPathHandle in noq - Rust

WeakPathHandle

Struct WeakPathHandle 

Source
pub struct WeakPathHandle { /* private fields */ }
Expand description

Weak handle for a Path that does not keep the connection alive.

+WeakPathHandle in noq - Rust

WeakPathHandle

Struct WeakPathHandle 

Source
pub struct WeakPathHandle { /* private fields */ }
Expand description

Weak handle for a Path that does not keep the connection alive.

As long as a WeakPathHandle for a path exists, that path’s final stats will not be dropped even if the path was abandoned.

The WeakPathHandle can be upgraded to a Path as long as its Connection has not been dropped.

-

Implementations§

Source§

impl WeakPathHandle

Source

pub fn id(&self) -> PathId

Returns the PathId of this path.

-
Source

pub fn upgrade(&self) -> Option<Path>

Upgrades to a Path.

+

Implementations§

Source§

impl WeakPathHandle

Source

pub fn id(&self) -> PathId

Returns the PathId of this path.

+
Source

pub fn upgrade(&self) -> Option<Path>

Upgrades to a Path.

Returns None if the connection was dropped.

-

Trait Implementations§

Source§

impl Clone for WeakPathHandle

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for WeakPathHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for WeakPathHandle

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for WeakPathHandle

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for WeakPathHandle

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for WeakPathHandle

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for WeakPathHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for WeakPathHandle

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for WeakPathHandle

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for WeakPathHandle

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq/struct.ZeroRttAccepted.html b/pr/619/docs/noq/struct.ZeroRttAccepted.html index f6332f3cd..d6f96d145 100644 --- a/pr/619/docs/noq/struct.ZeroRttAccepted.html +++ b/pr/619/docs/noq/struct.ZeroRttAccepted.html @@ -1,7 +1,7 @@ -ZeroRttAccepted in noq - Rust

ZeroRttAccepted

Struct ZeroRttAccepted 

Source
pub struct ZeroRttAccepted(/* private fields */);
Expand description

Future that completes when a connection is fully established

+ZeroRttAccepted in noq - Rust

ZeroRttAccepted

Struct ZeroRttAccepted 

Source
pub struct ZeroRttAccepted(/* private fields */);
Expand description

Future that completes when a connection is fully established

For clients, the resulting value indicates if 0-RTT was accepted. For servers, the resulting value is meaningless.

-

Trait Implementations§

Source§

impl Future for ZeroRttAccepted

Source§

type Output = bool

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +

Trait Implementations§

Source§

impl Future for ZeroRttAccepted

Source§

type Output = bool

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq/trait.NetworkChangeHint.html b/pr/619/docs/noq/trait.NetworkChangeHint.html index 2fb715fa0..63d289ea2 100644 --- a/pr/619/docs/noq/trait.NetworkChangeHint.html +++ b/pr/619/docs/noq/trait.NetworkChangeHint.html @@ -1,4 +1,4 @@ -NetworkChangeHint in noq - Rust

NetworkChangeHint

Trait NetworkChangeHint 

Source
pub trait NetworkChangeHint: Debug + 'static {
+NetworkChangeHint in noq - Rust

NetworkChangeHint

Trait NetworkChangeHint 

Source
pub trait NetworkChangeHint: Debug + 'static {
     // Required method
     fn is_path_recoverable(
         &self,
@@ -6,7 +6,7 @@
         network_path: FourTuple,
     ) -> bool;
 }
Expand description

Hints when the caller identifies a network change.

-

Required Methods§

Source

fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool

Inform the connection if a path may recover after a network change.

+

Required Methods§

Source

fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool

Inform the connection if a path may recover after a network change.

After network changes, paths may not be recoverable. In this case, waiting for the path to become idle may take longer than what is desirable. If Self::is_path_recoverable returns false, a multipath-enabled, client-side connection will establish a new path to diff --git a/pr/619/docs/noq_proto/enum.ClosePathError.html b/pr/619/docs/noq_proto/enum.ClosePathError.html index d035a5e2d..1b194ffe1 100644 --- a/pr/619/docs/noq_proto/enum.ClosePathError.html +++ b/pr/619/docs/noq_proto/enum.ClosePathError.html @@ -1,4 +1,4 @@ -ClosePathError in noq_proto - Rust

ClosePathError

Enum ClosePathError 

Source
pub enum ClosePathError {
+ClosePathError in noq_proto - Rust

ClosePathError

Enum ClosePathError 

Source
pub enum ClosePathError {
     MultipathNotNegotiated,
     ClosedPath,
     LastOpenPath,
@@ -7,8 +7,8 @@
 
§

ClosedPath

The path is already closed or was never opened

§

LastOpenPath

Cannot close the last remaining open path via the local API.

Use Connection::close to end the connection instead.

-

Trait Implementations§

Source§

impl Clone for ClosePathError

Source§

fn clone(&self) -> ClosePathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosePathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for ClosePathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for ClosePathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for ClosePathError

Source§

fn eq(&self, other: &ClosePathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ClosePathError

Source§

impl StructuralPartialEq for ClosePathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ClosePathError

Source§

fn clone(&self) -> ClosePathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosePathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for ClosePathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for ClosePathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for ClosePathError

Source§

fn eq(&self, other: &ClosePathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ClosePathError

Source§

impl StructuralPartialEq for ClosePathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq_proto/enum.ConnectionError.html b/pr/619/docs/noq_proto/enum.ConnectionError.html index 47854a92a..b552f735c 100644 --- a/pr/619/docs/noq_proto/enum.ConnectionError.html +++ b/pr/619/docs/noq_proto/enum.ConnectionError.html @@ -1,4 +1,4 @@ -ConnectionError in noq_proto - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
+ConnectionError in noq_proto - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
     VersionMismatch,
     TransportError(TransportError),
     ConnectionClosed(ConnectionClose),
@@ -20,8 +20,8 @@ and §

LocallyClosed

The local application closed the connection

§

CidsExhausted

The connection could not be created because not enough of the CID space is available

Try using longer connection IDs.

-

Trait Implementations§

Source§

impl Clone for ConnectionError

Source§

fn clone(&self) -> ConnectionError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for Error

Source§

fn from(x: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: TransportError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionError

Source§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ConnectionError

Source§

impl StructuralPartialEq for ConnectionError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ConnectionError

Source§

fn clone(&self) -> ConnectionError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for Error

Source§

fn from(x: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: TransportError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionError

Source§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ConnectionError

Source§

impl StructuralPartialEq for ConnectionError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq_proto/enum.Event.html b/pr/619/docs/noq_proto/enum.Event.html index d73f08102..6a9617fbb 100644 --- a/pr/619/docs/noq_proto/enum.Event.html +++ b/pr/619/docs/noq_proto/enum.Event.html @@ -1,4 +1,4 @@ -Event in noq_proto - Rust

Event

Enum Event 

Source
pub enum Event {
+Event in noq_proto - Rust

Event

Enum Event 

Source
pub enum Event {
     HandshakeDataReady,
     Connected,
     HandshakeConfirmed,
@@ -25,7 +25,7 @@ fail with §

DatagramsUnblocked

One or more application datagrams have been sent after blocking

§

Path(PathEvent)

(Multi)Path events

§

NatTraversal(Event)

n0’s nat traversal events

-

Trait Implementations§

Source§

impl Debug for Event

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<PathEvent> for Event

Source§

fn from(source: PathEvent) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Debug for Event

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<PathEvent> for Event

Source§

fn from(source: PathEvent) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/pr/619/docs/noq_proto/enum.PathError.html b/pr/619/docs/noq_proto/enum.PathError.html index 4547f04c2..fb0f14f23 100644 --- a/pr/619/docs/noq_proto/enum.PathError.html +++ b/pr/619/docs/noq_proto/enum.PathError.html @@ -1,4 +1,4 @@ -PathError in noq_proto - Rust

PathError

Enum PathError 

Source
pub enum PathError {
+PathError in noq_proto - Rust

PathError

Enum PathError 

Source
pub enum PathError {
     MultipathNotNegotiated,
     ServerSideNotAllowed,
     MaxPathIdReached,
@@ -12,8 +12,8 @@
 
§

RemoteCidsExhausted

No remote CIDs available to open a new path

§

ValidationFailed

Path could not be validated and will be abandoned

§

InvalidRemoteAddress(SocketAddr)

The remote address for the path is not supported by the endpoint

-

Trait Implementations§

Source§

impl Clone for PathError

Source§

fn clone(&self) -> PathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for PathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for PathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for PathError

Source§

fn eq(&self, other: &PathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Copy for PathError

Source§

impl Eq for PathError

Source§

impl StructuralPartialEq for PathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for PathError

Source§

fn clone(&self) -> PathError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for PathError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for PathError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for PathError

Source§

fn eq(&self, other: &PathError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Copy for PathError

Source§

impl Eq for PathError

Source§

impl StructuralPartialEq for PathError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq_proto/enum.PathEvent.html b/pr/619/docs/noq_proto/enum.PathEvent.html index 884e2e2bd..82f845b5a 100644 --- a/pr/619/docs/noq_proto/enum.PathEvent.html +++ b/pr/619/docs/noq_proto/enum.PathEvent.html @@ -39,7 +39,7 @@ changes the status.

Fields

§id: PathId

Path over which the observed address was reported, PathId::ZERO when multipath is not negotiated

§addr: SocketAddr

The address observed by the remote over this path

-

Trait Implementations§

Source§

impl Clone for PathEvent

Source§

fn clone(&self) -> PathEvent

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathEvent

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<PathEvent> for Event

Source§

fn from(source: PathEvent) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for PathEvent

Source§

fn eq(&self, other: &PathEvent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +

Trait Implementations§

Source§

impl Clone for PathEvent

Source§

fn clone(&self) -> PathEvent

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PathEvent

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<PathEvent> for Event

Source§

fn from(source: PathEvent) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for PathEvent

Source§

fn eq(&self, other: &PathEvent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for PathEvent

Source§

impl StructuralPartialEq for PathEvent

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq_proto/struct.Connection.html b/pr/619/docs/noq_proto/struct.Connection.html index cdf6be909..cb52e6048 100644 --- a/pr/619/docs/noq_proto/struct.Connection.html +++ b/pr/619/docs/noq_proto/struct.Connection.html @@ -33,7 +33,7 @@ increasing time. Specifically, calling Instant may be interleaved in any order with a call to handle_event at that same instant; however events or timeouts with different instants must not be interleaved.

-

Implementations§

Source§

impl Connection

Source

pub fn poll_timeout(&mut self) -> Option<Instant>

Returns the next time at which handle_timeout should be called

+

Implementations§

Source§

impl Connection

Source

pub fn poll_timeout(&mut self) -> Option<Instant>

Returns the next time at which handle_timeout should be called

The value returned may change after:

  • the application performed some I/O on the connection
  • @@ -124,42 +124,42 @@ idle time. Setting None disables the timeout and stops the timer.

    max_datagrams specifies how many datagrams can be returned inside a single Transmit using GSO. This must be at least 1.

    -
Source

pub fn handle_event(&mut self, event: ConnectionEvent)

Process ConnectionEvents generated by the associated Endpoint

+
Source

pub fn handle_event(&mut self, event: ConnectionEvent)

Process ConnectionEvents generated by the associated Endpoint

Will execute protocol logic upon receipt of a connection event, in turn preparing signals (including application Events, EndpointEvents and outgoing datagrams) that should be extracted through the relevant methods.

-
Source

pub fn handle_timeout(&mut self, now: Instant)

Process timer expirations

+
Source

pub fn handle_timeout(&mut self, now: Instant)

Process timer expirations

Executes protocol logic, potentially preparing signals (including application Events, EndpointEvents and outgoing datagrams) that should be extracted through the relevant methods.

It is most efficient to call this immediately after the system clock reaches the latest Instant that was output by poll_timeout; however spurious extra calls will simply no-op and therefore are safe.

-
Source

pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes)

Close a connection immediately

+
Source

pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes)

Close a connection immediately

This does not ensure delivery of outstanding data. It is the application’s responsibility to call this only when all important communications have been completed, e.g. by calling SendStream::finish on outstanding streams and waiting for the corresponding StreamEvent::Finished event.

If Streams::send_streams returns 0, all outstanding stream data has been delivered. There may still be data from the peer that has not been received.

-
Source

pub fn datagrams(&mut self) -> Datagrams<'_>

Control datagrams

-
Source

pub fn stats(&mut self) -> ConnectionStats

Returns connection statistics

-
Source

pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats>

Returns path statistics

-
Source

pub fn ping(&mut self)

Ping the remote endpoint

+
Source

pub fn datagrams(&mut self) -> Datagrams<'_>

Control datagrams

+
Source

pub fn stats(&mut self) -> ConnectionStats

Returns connection statistics

+
Source

pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats>

Returns path statistics

+
Source

pub fn ping(&mut self)

Ping the remote endpoint

Causes an ACK-eliciting packet to be transmitted on the connection.

-
Source

pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath>

Ping the remote endpoint over a specific path

+
Source

pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath>

Ping the remote endpoint over a specific path

Causes an ACK-eliciting packet to be transmitted on the path.

-
Source

pub fn force_key_update(&mut self)

Update traffic keys spontaneously

+
Source

pub fn force_key_update(&mut self)

Update traffic keys spontaneously

This can be useful for testing key updates, as they otherwise only happen infrequently.

-
Source

pub fn crypto_session(&self) -> &dyn Session

Get a session reference

-
Source

pub fn is_handshaking(&self) -> bool

Whether the connection is in the process of being established

+
Source

pub fn crypto_session(&self) -> &dyn Session

Get a session reference

+
Source

pub fn is_handshaking(&self) -> bool

Whether the connection is in the process of being established

If this returns false, the connection may be either established or closed, signaled by the emission of a Connected or ConnectionLost event respectively. Note that locally-initiated closes via close() do not emit a ConnectionLost event.

For an established connection this essentially means the handshake is completed, but not necessarily yet confirmed.

-
Source

pub fn is_closed(&self) -> bool

Whether the connection is closed

+
Source

pub fn is_closed(&self) -> bool

Whether the connection is closed

Closed connections cannot transport any further data. A connection becomes closed when either peer application intentionally closes it, or when either transport layer detects an error such as a time-out or certificate validation failure.

@@ -167,24 +167,24 @@ error such as a time-out or certificate validation failure.

connection is closed by the peer or due to an error. When the local application closes the connection via close(), no ConnectionLost event is emitted; instead, pending operations fail with ConnectionError::LocallyClosed.

-
Source

pub fn is_drained(&self) -> bool

Whether there is no longer any need to keep the connection around

+
Source

pub fn is_drained(&self) -> bool

Whether there is no longer any need to keep the connection around

Closed connections become drained after a brief timeout to absorb any remaining in-flight packets from the peer. All drained connections have been closed.

-
Source

pub fn accepted_0rtt(&self) -> bool

For clients, if the peer accepted the 0-RTT data packets

+
Source

pub fn accepted_0rtt(&self) -> bool

For clients, if the peer accepted the 0-RTT data packets

The value is meaningless until after the handshake completes.

-
Source

pub fn has_0rtt(&self) -> bool

Whether 0-RTT is/was possible during the handshake

-
Source

pub fn has_pending_retransmits(&self) -> bool

Whether there are any pending retransmits

-
Source

pub fn side(&self) -> Side

Look up whether we’re the client or server of this Connection

-
Source

pub fn path_observed_address( +

Source

pub fn has_0rtt(&self) -> bool

Whether 0-RTT is/was possible during the handshake

+
Source

pub fn has_pending_retransmits(&self) -> bool

Whether there are any pending retransmits

+
Source

pub fn side(&self) -> Side

Look up whether we’re the client or server of this Connection

+
Source

pub fn path_observed_address( &self, path_id: PathId, ) -> Result<Option<SocketAddr>, ClosedPath>

Get the address observed by the remote over the given path

-
Source

pub fn rtt(&self, path_id: PathId) -> Option<Duration>

Current best estimate of this connection’s latency (round-trip-time)

-
Source

pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller>

Current state of this connection’s congestion controller, for debugging purposes

-
Source

pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt)

Modify the number of remotely initiated streams that may be concurrently open

+
Source

pub fn rtt(&self, path_id: PathId) -> Option<Duration>

Current best estimate of this connection’s latency (round-trip-time)

+
Source

pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller>

Current state of this connection’s congestion controller, for debugging purposes

+
Source

pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt)

Modify the number of remotely initiated streams that may be concurrently open

No streams may be opened by the peer unless fewer than count are already open. Large counts increase both minimum and worst-case memory consumption.

-
Source

pub fn set_max_concurrent_paths( +

Source

pub fn set_max_concurrent_paths( &mut self, now: Instant, count: NonZeroU32, @@ -195,16 +195,16 @@ actively reduce paths they must be closed using TransportConfig) this can not enable multipath and will fail.

-

Source

pub fn max_concurrent_streams(&self, dir: Dir) -> u64

Current number of remotely initiated streams that may be concurrently open

+
Source

pub fn max_concurrent_streams(&self, dir: Dir) -> u64

Current number of remotely initiated streams that may be concurrently open

If the target for this limit is reduced using set_max_concurrent_streams, it will not change immediately, even if fewer streams are open. Instead, it will decrement by one for each time a remotely initiated stream of matching directionality is closed.

-
Source

pub fn set_send_window(&mut self, send_window: u64)

Source

pub fn set_receive_window(&mut self, receive_window: VarInt)

Source

pub fn is_multipath_negotiated(&self) -> bool

Whether the Multipath for QUIC extension is enabled.

+
Source

pub fn set_send_window(&mut self, send_window: u64)

Source

pub fn set_receive_window(&mut self, receive_window: VarInt)

Source

pub fn is_multipath_negotiated(&self) -> bool

Whether the Multipath for QUIC extension is enabled.

Multipath is only enabled after the handshake is completed and if it was enabled by both peers.

-
Source

pub fn handle_network_change( +

Source

pub fn handle_network_change( &mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant, @@ -219,26 +219,26 @@ paths as non recoverable when necessary accelerates connectivity re-establishmen allow it altogether.

The optional hint allows callers to indicate when paths are non-recoverable and should be migrated to new a PathId.

-

Source

pub fn current_mtu(&self) -> u16

Storage size required for the largest packet that can be transmitted on all currently +

Source

pub fn current_mtu(&self) -> u16

Storage size required for the largest packet that can be transmitted on all currently available paths

Buffers passed to Connection::poll_transmit should be at least this large.

When multipath is enabled, this value is the minimum MTU across all available paths.

-
Source

pub fn add_nat_traversal_address( +

Source

pub fn add_nat_traversal_address( &mut self, address: SocketAddr, ) -> Result<(), Error>

Add addresses the local endpoint considers are reachable for nat traversal.

-
Source

pub fn remove_nat_traversal_address( +

Source

pub fn remove_nat_traversal_address( &mut self, address: SocketAddr, ) -> Result<(), Error>

Removes an address the endpoing no longer considers reachable for nat traversal

Addresses not present in the set will be silently ignored.

-
Source

pub fn get_local_nat_traversal_addresses( +

Source

pub fn get_local_nat_traversal_addresses( &self, ) -> Result<Vec<SocketAddr>, Error>

Get the current local nat traversal addresses

-
Source

pub fn get_remote_nat_traversal_addresses( +

Source

pub fn get_remote_nat_traversal_addresses( &self, ) -> Result<Vec<SocketAddr>, Error>

Get the currently advertised nat traversal addresses by the server

-
Source

pub fn initiate_nat_traversal_round( +

Source

pub fn initiate_nat_traversal_round( &mut self, now: Instant, ) -> Result<Vec<SocketAddr>, Error>

Initiates a new nat traversal round

@@ -249,7 +249,7 @@ round is initiated, the previous one is cancelled.

4-tuple.

Returns the server addresses that are now being probed. If addresses fail due to spurious errors, these might succeed later and not be returned in this set.

-

Trait Implementations§

Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/pr/619/docs/noq_proto/struct.MultipathNotNegotiated.html b/pr/619/docs/noq_proto/struct.MultipathNotNegotiated.html index d03d466d5..1f150efd7 100644 --- a/pr/619/docs/noq_proto/struct.MultipathNotNegotiated.html +++ b/pr/619/docs/noq_proto/struct.MultipathNotNegotiated.html @@ -1,5 +1,5 @@ -MultipathNotNegotiated in noq_proto - Rust

MultipathNotNegotiated

Struct MultipathNotNegotiated 

Source
pub struct MultipathNotNegotiated { /* private fields */ }
Expand description

Error when the multipath extension was not negotiated, but attempted to be used.

-

Trait Implementations§

Source§

impl Clone for MultipathNotNegotiated

Source§

fn clone(&self) -> MultipathNotNegotiated

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MultipathNotNegotiated

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for MultipathNotNegotiated

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for MultipathNotNegotiated

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl Copy for MultipathNotNegotiated

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +MultipathNotNegotiated in noq_proto - Rust

MultipathNotNegotiated

Struct MultipathNotNegotiated 

Source
pub struct MultipathNotNegotiated { /* private fields */ }
Expand description

Error when the multipath extension was not negotiated, but attempted to be used.

+

Trait Implementations§

Source§

impl Clone for MultipathNotNegotiated

Source§

fn clone(&self) -> MultipathNotNegotiated

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MultipathNotNegotiated

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for MultipathNotNegotiated

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for MultipathNotNegotiated

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl Copy for MultipathNotNegotiated

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/619/docs/noq_proto/struct.TransportError.html b/pr/619/docs/noq_proto/struct.TransportError.html index ec0380a29..2ec284f78 100644 --- a/pr/619/docs/noq_proto/struct.TransportError.html +++ b/pr/619/docs/noq_proto/struct.TransportError.html @@ -11,7 +11,7 @@
§reason: String

Human-readable explanation of the reason

§crypto: Option<Arc<dyn Error + Send + Sync>>

An underlying crypto (e.g. TLS) layer error

Implementations§

Source§

impl Error

Source

pub fn new(code: Code, reason: String) -> Self

Construct an error with a code and a reason

-

Trait Implementations§

Source§

impl Clone for Error

Source§

fn clone(&self) -> Error

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for Error

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Error> for ConnectionClose

Source§

fn from(x: TransportError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: TransportError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for TransportError

Source§

fn from(e: Error) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for Error

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +

Trait Implementations§

Source§

impl Clone for Error

Source§

fn clone(&self) -> Error

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for Error

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Error> for ConnectionClose

Source§

fn from(x: TransportError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for ConnectionError

Source§

fn from(source: TransportError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for TransportError

Source§

fn from(e: Error) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for Error

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Error

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/619/docs/noq_proto/trait.NetworkChangeHint.html b/pr/619/docs/noq_proto/trait.NetworkChangeHint.html index e948a5b14..0b3000bd7 100644 --- a/pr/619/docs/noq_proto/trait.NetworkChangeHint.html +++ b/pr/619/docs/noq_proto/trait.NetworkChangeHint.html @@ -1,4 +1,4 @@ -NetworkChangeHint in noq_proto - Rust

NetworkChangeHint

Trait NetworkChangeHint 

Source
pub trait NetworkChangeHint: Debug + 'static {
+NetworkChangeHint in noq_proto - Rust

NetworkChangeHint

Trait NetworkChangeHint 

Source
pub trait NetworkChangeHint: Debug + 'static {
     // Required method
     fn is_path_recoverable(
         &self,
@@ -6,7 +6,7 @@
         network_path: FourTuple,
     ) -> bool;
 }
Expand description

Hints when the caller identifies a network change.

-

Required Methods§

Source

fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool

Inform the connection if a path may recover after a network change.

+

Required Methods§

Source

fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool

Inform the connection if a path may recover after a network change.

After network changes, paths may not be recoverable. In this case, waiting for the path to become idle may take longer than what is desirable. If Self::is_path_recoverable returns false, a multipath-enabled, client-side connection will establish a new path to diff --git a/pr/619/docs/perf/server/index.html b/pr/619/docs/perf/server/index.html index de30e6257..4aa8e181b 100644 --- a/pr/619/docs/perf/server/index.html +++ b/pr/619/docs/perf/server/index.html @@ -1 +1 @@ -perf::server - Rust

Module server

Module server 

Source

Structs§

Opt

Functions§

run
\ No newline at end of file +perf::server - Rust

Module server

Module server 

Source

Structs§

Opt

Functions§

run
\ No newline at end of file diff --git a/pr/619/docs/search.index/0007afbe4a1e.js b/pr/619/docs/search.index/0007afbe4a1e.js deleted file mode 100644 index 0e55ee68c..000000000 --- a/pr/619/docs/search.index/0007afbe4a1e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9EkUAAABAAEAAQABBQD0ORMAAAEAlAABAPMAAmN19VYQAAABAMYAAQABAAEJAPN+FAAAAQA7AAENAaCgAAAUyHfyuBQAAAEAAYECsIAUjgABoGAAABS2ZHM3AQCEhaBAAAAUYbBgFDEAUAKQCiOAAqBwAAARX2RyAQsBoEAAABRlZfKHFAAAAQATgAKwMBByAAFkcvMCAWX04wcAAAEAAQABACOAArAgDAsAAWV5AQoA88ESAAABAAEAAQsAOzAAAAEAAAcAAQCkEwcAAQIA9AMUAAABAFAAAQC3AACAhbBwEvcAAbDQFKsAAWAgBgEGAPPOEgAAAQABAAEDAbBAFHwAAXTy2RMAAAEAI4UCoEAAABQJYnMjAgOwQBEDAAGgUAAAEXBhYmb3DQkAAAEASAByBwEAYgABAPOAAmlwAQQA828QAAABAAEA8wABcDswAAABAAAMAAEA4wYMACOAA6AwAAAMG7BwE7gAAWFlafOAA2RtbgEAADowAAABAAAAAAAHABAAAAAYCWoMtxK4Eg4TDxMQExET8wIBZDswAAABAAAJAAMA4xEDALISAwDmEgEAI4ACoJAAABRYaW8BgAOwMBNrAAGAE64AEAGwUBEgAAFjc3jzAAFlAcoEAADnFQCAiaAAAAAMe6BAAAAM1LBADNUAAZBIXQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/003d0358f65c.js b/pr/619/docs/search.index/003d0358f65c.js new file mode 100644 index 000000000..080180597 --- /dev/null +++ b/pr/619/docs/search.index/003d0358f65c.js @@ -0,0 +1 @@ +rn_("AQMBsDATWwABY/OGEQAAAQABAAEDAYATfQAQ+nM7MAAAAQAABQABAF0TBQAjggKgkAAAFGFpcwcBAIDFsFATJgABoKAAABPIsHATjQABoNAAABRtgAEYCPOAAmRy") \ No newline at end of file diff --git a/pr/619/docs/search.index/0072ff485b3d.js b/pr/619/docs/search.index/0072ff485b3d.js new file mode 100644 index 000000000..966ef9bdf --- /dev/null +++ b/pr/619/docs/search.index/0072ff485b3d.js @@ -0,0 +1 @@ +rn_("AQAAOjAAAAEAAAAAAAoAEAAAAOYP5w/WENcQYxH0EfURERMSE6oUqxQBBADz4Q8AAOEAAQDzAAFx9w4NAAABADsDAQDNAGEAAQDzAAJleTowAAABAAAAAAAOABAAAAAPCVcMWAx3EIwQjRAiESMRJBH5E/oTChQLFIUUihQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0074467c55f3.js b/pr/619/docs/search.index/0074467c55f3.js new file mode 100644 index 000000000..39e569f4d --- /dev/null +++ b/pr/619/docs/search.index/0074467c55f3.js @@ -0,0 +1 @@ +rn_("AQUA9MsSAAABAKYAAQABCAD0hxMAAAEAiAABADMBA7BAE1YAAWFiZfX4DAAAAQBAA2oC0gABAAA7MAAAAQAABQACADEMAQC9DwMA84ACc3UjgQKwgBOBAAFydAGAArBwEwgAAaAQAAAM1256AQYA9IUQAAABALcAAQBzAISgoAAAFMcCART1egUAAAEA5Q5XAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/0076e0f9ae1b.js b/pr/619/docs/search.index/0076e0f9ae1b.js deleted file mode 100644 index 7c0ef4131..000000000 --- a/pr/619/docs/search.index/0076e0f9ae1b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsCARRgABsDARxAABZXABBQD05g8AAAEA7wABAFOAA7CQEfUAAWFpcgGBArCgFBkAAbCgFBsAAWNyxwAAAIWwUAz6AAGgIAAACXSgIAAADCM8AAE6MAAAAQAAAAAACgAQAAAAtQG2AXkE/gYlCSYJfRB+EPEQ8hAIEg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/00e155de90d9.js b/pr/619/docs/search.index/00e155de90d9.js deleted file mode 100644 index c073775da..000000000 --- a/pr/619/docs/search.index/00e155de90d9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQoA9KITAAABAA8AAQABgwKgIAAAEEygMAAAEOhpdAEAAPQOEwAAAQABAAEA8wQBZPSyEgAAAQABAAEAI4aEsKAUVgABsEATDAABsHAT/QABFYAAAQACsDAQPgABsBATugABc3TylgUAAIcGAYACsMAUhAABoAAAAAdSdHnzgIURwQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/00ee301dfa9b.js b/pr/619/docs/search.index/00ee301dfa9b.js deleted file mode 100644 index f1237eb43..000000000 --- a/pr/619/docs/search.index/00ee301dfa9b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9WQJAAABAAEAAQABACOAAqCgAAAUlmZwRwAAAIWwMA+0AAGgUAAAEHiwcBEGAAGxQBTBAAGBKQDydgUAAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/16832093cb10.js b/pr/619/docs/search.index/00fda0fef97d.js similarity index 53% rename from pr/619/docs/search.index/16832093cb10.js rename to pr/619/docs/search.index/00fda0fef97d.js index e2cc57266..1799bf795 100644 --- a/pr/619/docs/search.index/16832093cb10.js +++ b/pr/619/docs/search.index/00fda0fef97d.js @@ -1 +1 @@ -rn_("AYQCoCAAABEnoDAAABGNaXQBAQA7MAAAAQAAjQACAHUHAAB6CYwAYwADsAACGQABZGVsOjAAAAEAAAAAAAcAEAAAALUEhQWGBYcFeQdEEZcTmBM=") \ No newline at end of file +rn_("AYQCoCAAABEnoDAAABGNaXQBAQA7MAAAAQAAjQACAHUHAAB6CYwAYwADsAACGQABZGVsOjAAAAEAAAAAAAcAEAAAALUEhQWGBYcFeQdEEZYTlxM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0113920737b2.js b/pr/619/docs/search.index/0113920737b2.js new file mode 100644 index 000000000..566ce1024 --- /dev/null +++ b/pr/619/docs/search.index/0113920737b2.js @@ -0,0 +1 @@ +rn_("AYACsHAS2gABoLAAABQXZW8jAQOwcBIAAAGAE30AEPptbnM7MAAAAQAAGgAGAGwHAQD3CAUADA0BAE4RCQCMEQAAXRMFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/01179ef58d64.js b/pr/619/docs/search.index/01179ef58d64.js new file mode 100644 index 000000000..cb86b2fd4 --- /dev/null +++ b/pr/619/docs/search.index/01179ef58d64.js @@ -0,0 +1 @@ +rn_("AQcA9p8TAAABAKwAWAAYAAEA8wEBaQFhCQAAAQAA9WQJAAABAAEAAQABAEcBAIDGP+46ri98oKAAABSVsGAUBAABoBAAAAk4AAogig==") \ No newline at end of file diff --git a/pr/619/docs/search.index/02cb2f01921a.js b/pr/619/docs/search.index/02cb2f01921a.js new file mode 100644 index 000000000..38f8b3fe5 --- /dev/null +++ b/pr/619/docs/search.index/02cb2f01921a.js @@ -0,0 +1 @@ +rn_("AQAA9AoRAAABAJIBAQAjgQKgYAAAEz9iaQEAAPTyDwAAAQD0AAgBI4ECsFATUgABZXMTgAKAB1MfMAFhcgGJArAgFHAAAaAwAAAUemlwAQIA9CQTAAABAJAAAQABAwD0WBMAAAEAmAABAPOFAmJ1AQIA9HURAAABAHwBAQDzgAJpbLcBAACFoCAAABMsEgEMOjAAAAEAAAAAABYAEAAAAHQHAQgCCAMIBAgVDE4MTwxQDFEMGhDgEHATcROsEzAUfRR+FIAUjRSOFLUUuRQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/03098f8f36f0.js b/pr/619/docs/search.index/03098f8f36f0.js new file mode 100644 index 000000000..443147599 --- /dev/null +++ b/pr/619/docs/search.index/03098f8f36f0.js @@ -0,0 +1 @@ +rn_("AQACoCAAABOPsDAR6gABaXTy9hIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PkTAAABAIsABQATAQOwkBRiAAGwUBM+AWdnbHA7MAAAAQAAEgAJAGkQAgDtEQEALRMBAE4TAQCFEwEA6hMBACQUAQAzFAEAdBQBAAGAArAwEeYAAbAwEegAAXJ2AQQBsAAStgABZDswAAABAAAFAAIA4hEDAOUSAQC3BQABh7BQErgBFLBgEzwAAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETQTbRMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwGEoFAAABGLoDAAABCkFAEQ8pwHAAABABOAA7BgEtoAAbAAD7AAAWNnchOAA6CwAAAUF6BAAAAOnGVvcw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/03534d6a80b5.js b/pr/619/docs/search.index/03534d6a80b5.js new file mode 100644 index 000000000..8c25384c6 --- /dev/null +++ b/pr/619/docs/search.index/03534d6a80b5.js @@ -0,0 +1 @@ +rn_("AQECsCAM9QABsAAMbQABZXPyZQcAAAEAAQUA8x0TAAABAAEA8wQBcvTkDwAAAQDuAAEAE4ACoLAAABRdYXPzgAJiYw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/03ee76ce924c.js b/pr/619/docs/search.index/03ee76ce924c.js deleted file mode 100644 index f6a75d934..000000000 --- a/pr/619/docs/search.index/03ee76ce924c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA884RAAABAAEAAYICsEASyAABsEASygABNDYBCwDzxhMAAGwAAQABBgD0tBQAAAEACgABAPMCAXIBEBQAAPMCAWU7MAAAAQAABQACAH8QAwAwEQEAE4ACoFAAABL9ZHTzAIQRAQH37xAAAAEAbgAdAAEAAQA9AQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/03fef7854a4e.js b/pr/619/docs/search.index/03fef7854a4e.js new file mode 100644 index 000000000..deda23a8b --- /dev/null +++ b/pr/619/docs/search.index/03fef7854a4e.js @@ -0,0 +1 @@ +rn_("AQUA9AIUAAABAFAAAQDzAwFj8gYTAAABACOAArBwFLoAAWhvAYICsAAS4wABsAAR6gABZXNDAAOgoAAAFFigIAAAE49laXTy9hIAAAEAAQIAOzAAAAEAAAYAAQBkEQYAAQIBoEAAABQ5ZfJnFAAAAQDzgAJpbwEIAPT5EwAAAQCLAAUAEwEDsJAUYgABsFATPgFnZ2xwOzAAAAEAABIACQBpEAIA7REBAC0TAQBOEwEAhRMBAOoTAQAkFAEAMxQBAHQUAQABgAKwQBK4ARSgIAAAEShhaQEDAPPXEgAAAQABACOBArAwFAoAAWNpAQAA9CgTAAABAFgBAQDzAwFzOzAAAAEAAA8AAwDoEQEAoxMHAJsUBQABAwD15hEAAAEAJAEBAGEB84ACcnYBAAA7MAAAAQAABQACALYSAQANEwMA8wIBZDswAAABAAAJAAMA4hEDALESAwDlEgEAI4ACoJAAABRXaW8TgAKw8BSqAAFsbwEFAPRzFAAADAAiABEAI4ACoGAAABODZ3MjgAKwkBRVAAFibPfHAACNsGAUiwABsHAT/AABsGATPAABsFATKgABtckXOjAAAAEAAAAAACAAEAAAALcFBwk1CWIMYwziDOMM5AyYDpkOmg6bDp0Ong79D/4P/w8AEAEQzxDQEAwRLxGOEY8RkBGREeARNBNLE0wTbRMnFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/04280654882e.js b/pr/619/docs/search.index/04280654882e.js new file mode 100644 index 000000000..30f9e5144 --- /dev/null +++ b/pr/619/docs/search.index/04280654882e.js @@ -0,0 +1 @@ +rn_("AQUA9MsSAAABAKYAAQABCAD0hxMAAAEAiAABADMBA7BAE1YAAWFiZfX4DAAAAQBAA2oC0gABAAA7MAAAAQAABQACADEMAQC9DwMA84ACc3UjgQKwgBOBAAFydAEGAPSFEAAAAQC3AAEAUwCEsIATCAABoKAAABTHAgEU9XoFAAABAOUOVwABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/04460d3da660.js b/pr/619/docs/search.index/04460d3da660.js new file mode 100644 index 000000000..577eee742 --- /dev/null +++ b/pr/619/docs/search.index/04460d3da660.js @@ -0,0 +1 @@ +rn_("AQEA9D0HAAABAAEAAQABAQGgQAAAEYlz9TkMAAAmBUoBAQABABOCAqAgAAANEGVyI4ADoEAAAAw4sDAJLAABZW90AQAA9DkHAAABAAEAAQABAgD0oRMAAAEADwABABOAArBAFFsAAWJ284ACb3gBCgD13RMAAAEAAQB6AAEAAYECoCAAABD6sFASvAABYW8BBAGgAAAAE+JzAfkQAABjAwOwUBFrAAFjZXP2CAkAAAEAAQAsAAEAawkBAQA7MAAAAQAABQABANoMBQAjgAKwMBM+AWdydPMAhgHAB/LwAQAAAwY=") \ No newline at end of file diff --git a/pr/619/docs/search.index/044bd26a62da.js b/pr/619/docs/search.index/044bd26a62da.js deleted file mode 100644 index 2b9313ad8..000000000 --- a/pr/619/docs/search.index/044bd26a62da.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCAUcQABoDAAABR7aXATAAOgIAAAEy2ggAAAE0BlaXX1FQwAADkAAQABAAEAAYYCsJAUmAABoAAAABK6YmQBgAKwMBMhAAGgMAAAEPhydtcAAAKFoDAAABBsoDAAABN3EAETOjAAAAEAAAAAAAkAEAAAAAEJAgkDCTMJNAmHEI4QSBFJEf0SAQMBsDATOwABc/PKEAAAAQABAAEAADswAAABAAAKAAMAchECALwTAwCnFAMAlwEAAIWgIAAABa+wIAgFAAFQGAH1fgwAAAEAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/04e46d976d32.js b/pr/619/docs/search.index/04e46d976d32.js deleted file mode 100644 index 46e7523fa..000000000 --- a/pr/619/docs/search.index/04e46d976d32.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCAUcQABoDAAABR7aXATAAOgIAAAEy2ggAAAE0BlaXX1FQwAADkAAQABAAEAAYYCsJAUmAABoAAAABK6YmQBgAKwMBMhAAGgMAAAEPhydtcAAACFoDAAABBsoDAAABN3EAETOjAAAAEAAAAAAAkAEAAAAAEJAgkDCTMJNAmHEI4QSBFJEf0S") \ No newline at end of file diff --git a/pr/619/docs/search.index/04f13de54089.js b/pr/619/docs/search.index/04f13de54089.js deleted file mode 100644 index 78fe2d334..000000000 --- a/pr/619/docs/search.index/04f13de54089.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9IMMAAABAAEAAQABAAGwUBQ+AAFyAcEEAABTAYSwQBK/AAGwQBR8AAGYAAQ6MAAAAQAAAAAAKAAQAAAAiwSMBI0ElwUSCRMJOAlrCdcMzw8+ED8QTBB8ENsQ3BDdECcRoBL+Ev8SABMBEy0TOxM8E2kTahPZE9oT3hPfE+AT8BPxE1oUWxRxFHIUmBSZFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/053d8e28fefb.js b/pr/619/docs/search.index/053d8e28fefb.js deleted file mode 100644 index baadeba17..000000000 --- a/pr/619/docs/search.index/053d8e28fefb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHASmQABsCAUsQABaW8BAAGw8BSxAAFrOzAAAAEAAAgAAwAYFAAAHRQGAEgUAADzBQFk8tsSAAABAAECAPPbEAAAAQABAPMAAWk6MAAAAQAAAAAABwAQAAAAthDwEtwT3RMNFA4ULxQwFCODArCwFIwAAWFzAYECoKAAABNFoEAAABB0b3bzgIQBUAE=") \ No newline at end of file diff --git a/pr/619/docs/search.index/05cdd3acb27b.js b/pr/619/docs/search.index/05cdd3acb27b.js new file mode 100644 index 000000000..596f5b11e --- /dev/null +++ b/pr/619/docs/search.index/05cdd3acb27b.js @@ -0,0 +1 @@ +rn_("AQUA9JETAAABAAEAAQABAAD1fgwAAAEAAQABAAEA84ACZ2sTgAKwsBPsAAFhbwGAAqAgAAAL/6BAAAAMN2V0AYUCsHAUFQABsDATaAABZXMTAAOwQA/YAAGgYAAAEYxiZXM7MAAAAQAAEgAEAKkFAQDKBgoAURABAKkQAwABAwD0bRAAAAEABAABAAEKAaBAAAAUZGXyhhQAAAEAE4ACsGASugABY2nzgAJkcvMAAmVvOzAAAAEAAAkAAgCeBwUA4wcDAAECAbAwEVgAAW47MAAAAQAACQABAPULCQDzgAJvdAEDADswAAABAADuAAIAeAcAAAcL7QABAgGgcAAAEf9pOzAAAAEAAAABAgB3BwAABwr/ABOAAqBAAAAMNnJ1AQQA9EcTAAABAJgAAQABAwDz1BIAAAEAqgDzgAJhb9cHAACIsEANAAABsTAUgwABNIEWOzAAAAEAAB4ADQC9BAEAggUBAAoMAAA8DAcAYAwBAOYPAQDWEAEAYxEAALARAwD0EQEAsBIAABETAQCqFAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/05f9c5191180.js b/pr/619/docs/search.index/05f9c5191180.js new file mode 100644 index 000000000..975008342 --- /dev/null +++ b/pr/619/docs/search.index/05f9c5191180.js @@ -0,0 +1 @@ +rn_("AQQA9HMUAAAMACIAEQABAgGwQBK+AAFlAc8PAAABgAKgkAAAFDWgkAAAFDYyM5cCAADGoCAAAAx4oGAAABFEsGANDAABAWQAAzswAAABAAAKAAMAGwcFAEQMAAB3EwMA") \ No newline at end of file diff --git a/pr/619/docs/search.index/069af7b6cfda.js b/pr/619/docs/search.index/069af7b6cfda.js new file mode 100644 index 000000000..20cf8158a --- /dev/null +++ b/pr/619/docs/search.index/069af7b6cfda.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwDLEQIAexMBABIUAgABBwD2nxMAAAEArABYABgAAQABBADzzhEAAAEAAQAjAAKgYAAAEvxhcvPvEAAAAQDJAQGAAqEQAAAUobCAFJcAAWl1dwgAAIixUBS+AAGgAAAAEM6wcBPbAAGhMAAAFLIKQRvyYQkAAEQHAYECoFAAABEUoKAAABNNa3ABAwA7MAAAAQAACQECAOcMAQCfDgcB84ACbHTzgAJhZQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/06e54bb1f956.js b/pr/619/docs/search.index/06e54bb1f956.js new file mode 100644 index 000000000..6e18f81ef --- /dev/null +++ b/pr/619/docs/search.index/06e54bb1f956.js @@ -0,0 +1 @@ +rn_("AQAEoAAAABCZsCARTAABoFAAABH4oEAAABQ6ZGxzdjswAAABAAATAAYArAUAADYMAADrDAAAChANAHARAAA1FAEAAQIA9NcRAAABAAEAAQAThAKwIBHbAAFhc/OAAmFl") \ No newline at end of file diff --git a/pr/619/docs/search.index/072f914cace1.js b/pr/619/docs/search.index/072f914cace1.js deleted file mode 100644 index a5eeeb323..000000000 --- a/pr/619/docs/search.index/072f914cace1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDLEQIAfBMBABMUAgABBADzzhEAAAEAAQAjAAKgYAAAEv1hcvPvEAAAAQDKAQGAAqEQAAAUorCAFJgAAWl1NwQAgYexUBS/AAGgAAAAEM6wcBPcAAGhMAAAFLMKQBsjgAKgMAAAEptudg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/074bfcb6336f.js b/pr/619/docs/search.index/074bfcb6336f.js new file mode 100644 index 000000000..ab503165a --- /dev/null +++ b/pr/619/docs/search.index/074bfcb6336f.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAAUAAQDcEgUAAQQBoFAAABQmaPK6EgAAAQABAAKwQBO3AAGgoAAAFEZlcjowAAABAAAAAAAHABAAAADGBscGYwdkB+4P7w/lEOYQ84ADZ2lz") \ No newline at end of file diff --git a/pr/619/docs/search.index/084b410c630d.js b/pr/619/docs/search.index/084b410c630d.js new file mode 100644 index 000000000..1eb2d255b --- /dev/null +++ b/pr/619/docs/search.index/084b410c630d.js @@ -0,0 +1 @@ +rn_("AQYA9OgTAAABAFYAAQAjgAKhEAAAFKVjchOAAqAgAAAJEWh5AQEBoGAAABSWc/LbEQAAAQAjgAKwIAl2AAFldQGAArAgECIAAaCQAAAURmFlAQcBsEAUZQABZfUpFAAAAQABAAEAAQABAAD0KBMAAAEAWAEBAPMEAXM7MAAAAQAADQACAKMTBwCbFAUARwAABIaggAAAE4OxABSqAAGwQBLjAAGwgBS6AAGwUBMqAAEVABb0mA4AAAEAAQABAIMAhLBAFLAAAbAwExkAAbAwE7cAAcAAAzowAAABAAAAAAAJABAAAAC4BBEREhG0EbURwhHDEQYUBxR5FAEDAbBAFHsAAXTy2BMAAAEAI4QCoEAAABQIYnMTgAKwwBSuAAF1eQGAAqAAAAAJMbAgEQMAAWdwAQEA9NcRAAABAAEAAQDzgAJkbLfoAACMoNAAABOPoFAAABFwoJAAABOrsFATCAABoDAAAAxvt5gHOzAAAAEAAGUAEwACAgEACAIBAGYEAwDHBQAAxgYBAGMHAQB2BwAADQkBABoJAAAkCQAAVgkAAIgMQgDhDAAA7g8BAMgQAQDlEAEAKxEBAKsRBAC8EgEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/724469503f12.js b/pr/619/docs/search.index/08613fa638dc.js similarity index 53% rename from pr/619/docs/search.index/724469503f12.js rename to pr/619/docs/search.index/08613fa638dc.js index b2f7581ce..b67796b4c 100644 --- a/pr/619/docs/search.index/724469503f12.js +++ b/pr/619/docs/search.index/08613fa638dc.js @@ -1 +1 @@ -rn_("AYACoIAAABLXsHAULwABYXMBAAGggAAAFLdm8gAJAACWCgEHAPVkEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MAAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAA84ACZHk=") \ No newline at end of file +rn_("AYACoIAAABLWsHAULgABYXMBAAGggAAAFLZm8gAJAACVCgEHAPVjEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MAAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAA84ACZHk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/090f98468b1e.js b/pr/619/docs/search.index/090f98468b1e.js deleted file mode 100644 index a960b353e..000000000 --- a/pr/619/docs/search.index/090f98468b1e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECoCAAABSXsEAP/QABYnABBQD0SBMAAAEAmAABAPMDAWMBsRIAAAEMAbAAFIIAAXM7MAAAAQAABQABAJwUBQDzgAJudgGAArAwDFsAAaAwAAAMXWlvAQMBoAAAABRicwH5EQAAAQQA9BcMAAABAAEAAQDXAwCAhrAABXQAAZFIAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/0922c28c8228.js b/pr/619/docs/search.index/0922c28c8228.js deleted file mode 100644 index baaa321fc..000000000 --- a/pr/619/docs/search.index/0922c28c8228.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoAAAABCVoAAAABCWNDYBgAOwABPkAAGwABPmAAGwcBRfAAE0NmEBBAD0tBQAAAEACgABACOBAqBAAAARXm1wAQEAOzAAAAEAAAgAAwDXEgAAShMAAMEUBgDHAQACxaBAAAAQWKCAAAASsUAGgAg7MAAAAQAAFwAIAPYPAQAWEQEAWhEDANERBgDAEwMAEBQAAG8UAQCjFAEA8wACZXY6MAAAAQAAAAAAFQAQAAAAEgITAhQCrgUGDbQPtQ/RD+sPfxCAEIEQghAwETERyBLJEsoSyxLGEzIUMxQBgQKwcBFaAAGwcBFcAAE0NiOAArAQB2MAAW5wAQMCsEATIQABoDAAABN3ZXf0hxAAAAcAugABABOBAqBwAAATsWdvAQQAOzAAAAEAAAYAAgAJDAAAFA0FAGOAA7BQD/YAAWRzdFcBAACFoBAAABBYsSAUbwABESEBOzAAAAEAAAoAAwB/AAAAlQAFANgRAwA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/097f0b930929.js b/pr/619/docs/search.index/097f0b930929.js new file mode 100644 index 000000000..46f1f9f45 --- /dev/null +++ b/pr/619/docs/search.index/097f0b930929.js @@ -0,0 +1 @@ +rn_("AQcA9JETAAABAAEAAQDzBQF0OzAAAAEAAAgAAgAKDAAAPAwHAAEFAPOtEwAAAQABADcAAICFsDAQTQABoKAAABPLoDAAABQIEEFI") \ No newline at end of file diff --git a/pr/619/docs/search.index/0a07ec521ff0.js b/pr/619/docs/search.index/0a07ec521ff0.js deleted file mode 100644 index 8aaa4f32f..000000000 --- a/pr/619/docs/search.index/0a07ec521ff0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsPAUsQABazswAAABAAAIAAMAGBQAAB0UBgBIFAAAEwACsQAUmgABZG7y2xIAAAEAE4ACsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAAGAAqBAAAARELDAFFwAAWVzAQEAOzAAAAEAABMAAQAkEBMAI4ACsJATxAABaW03NgAAiqAQAAAMKqBQAAAUJ7BwFAUAAaAgAAAM9JxVETswAAABAAAGAAMAWAcAAOkQAwC7EgEA84ACbHQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0a8a212c9645.js b/pr/619/docs/search.index/0a8a212c9645.js new file mode 100644 index 000000000..3ef4e3055 --- /dev/null +++ b/pr/619/docs/search.index/0a8a212c9645.js @@ -0,0 +1 @@ +rn_("AQYAOzAAAAEAAAkAAQBOEQkAI4ADsGATgQABsDAPzAABaXN0AQgA9UEUAAABAAEAAQABAPMBAWb1mhAAAAEAAQABAAEAY4ADoDAAABNDZWd0") \ No newline at end of file diff --git a/pr/619/docs/search.index/0ac376e86095.js b/pr/619/docs/search.index/0ac376e86095.js new file mode 100644 index 000000000..30c8da7aa --- /dev/null +++ b/pr/619/docs/search.index/0ac376e86095.js @@ -0,0 +1 @@ +rn_("AQMA82YQAAABAAEAAYACoLAAABQmsDATcAABbnRDAAOgIAAAERuwUBHyAAFlaGk7MAAAAQAABgADABMMAAADEgMAzxMBAPOAAmRy") \ No newline at end of file diff --git a/pr/619/docs/search.index/0b6366326bb6.js b/pr/619/docs/search.index/0b6366326bb6.js deleted file mode 100644 index f3e7dde10..000000000 --- a/pr/619/docs/search.index/0b6366326bb6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDLEQIAfBMBABMUAgABBADzzhEAAAEAAQAjAAKgYAAAEv1hcvPvEAAAAQDKAQGAAqEQAAAUorCAFJgAAWl1NwQAgYexUBS/AAGgAAAAEM6wcBPcAAGhMAAAFLMKQBsBAAA7MAAAAQAAjAABAAoOjAABAgD2oBMAAAEArABYABgAAQAjgQKgIAAAEQ9ydvOAAmVvI4ACoCAAABKbZHQBAAA7MAAAAQAA8AAEAMgFAAAHCO0AhwwAAHERAADzgANkbnY=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0b86da30c91a.js b/pr/619/docs/search.index/0b86da30c91a.js deleted file mode 100644 index d7356c90a..000000000 --- a/pr/619/docs/search.index/0b86da30c91a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOjAAAAEAAAAAAAcAEAAAAE8TUBPrE+wTJRQmFHUUdhTzBgFpAW4TAABDgAOwABSvAAGwUBNDAFpkZm4BAAGwQBMcAAFlOzAAAAEAAA0AAgDVBgwAEBEAACOAAqAwAAAMFmFlNwAAgMWwUBOXAAGwEBQ+AAGwYBOeAAEAApgI") \ No newline at end of file diff --git a/pr/619/docs/search.index/0c0a3ac3c3ab.js b/pr/619/docs/search.index/0c0a3ac3c3ab.js new file mode 100644 index 000000000..418920772 --- /dev/null +++ b/pr/619/docs/search.index/0c0a3ac3c3ab.js @@ -0,0 +1 @@ +rn_("AQAA9HcTAAABAAEAAQATAAKwgBNLAAFzdvRyCQAAAQCJCgEAE4ACsDARDQABbG4BgAKgAAAAEJWgAAAAEJY0NvMDAXYBBg0AABMAAqBAAAARiWFz9zkMAAC/A2cBSgEBAAEAsgEBAgD0JBMAAAEAkAABAAEDAPRYEwAAAQCYAAEA8wACYnU6MAAAAQAAAAAAEwAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfAR8REiEyMTLxMwEz8TsxO0E/OAAmR0E4ACoCAAAA0QZXIBBwGgQAAAFDll8mcUAAABAAEAAPVkCQAAAQABAAEAAQAjgAKgoAAAFJVmcEcAAACFsDAPtAABoFAAABB4sHARBgABsUAUwAABgSkA8nYFAAABAPOAAmx0lwEAgIaxMBQ7AAGxEBRpAAGgsAAAE1oRRQg=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0c270d347467.js b/pr/619/docs/search.index/0c270d347467.js new file mode 100644 index 000000000..d4285dfcd --- /dev/null +++ b/pr/619/docs/search.index/0c270d347467.js @@ -0,0 +1 @@ +rn_("AQIA9CQTAAABAJAAAQABAwD0WBMAAAEAmAABAPMCAmJ1OjAAAAEAAAAAABMAEAAAAEwHTQdOB9wP3Q+FEIYQphCnED0RPhHwEfERIhMjEy8TMBM/E7MTtBM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0c93807c54f2.js b/pr/619/docs/search.index/0c93807c54f2.js new file mode 100644 index 000000000..d193b8b40 --- /dev/null +++ b/pr/619/docs/search.index/0c93807c54f2.js @@ -0,0 +1 @@ +rn_("AYMCsQAUvAABsNAUrAABa20BCgDz/hMAAAEAdwATgAKiEAAAFMdsbzMBhKBgAAASlaEAAAAUeASAAzswAAABAAA2AAIAUQcAAKQHNQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0d1b75fe6868.js b/pr/619/docs/search.index/0d1b75fe6868.js deleted file mode 100644 index c69e8b7d9..000000000 --- a/pr/619/docs/search.index/0d1b75fe6868.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9iARAAABAJMDAQAKAAEAAQAAOzAAAAEAAAYAAgCMEwAA9BMFACOIArBAFGwAAWVzAQ0BsEAUZgABZfUqFAAAAQABAAEAAQABBQA7MAAAAQAACAADAP0RAgACEwQAKRQAANcBAACFVzFF2FXTFIQC884MAAABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/0d4624154f2d.js b/pr/619/docs/search.index/0d4624154f2d.js deleted file mode 100644 index 6ed3b5827..000000000 --- a/pr/619/docs/search.index/0d4624154f2d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsGAUDQABZQFHFAAAAQYA9DcTAAABAFEBAQABBAD0URMAAAEAEQEBAPMAA2VyczowAAABAAAAAAAJABAAAAApCSoJKwlFEYQRmRKaEqcSBRQGFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/0d714d59fce3.js b/pr/619/docs/search.index/0d714d59fce3.js new file mode 100644 index 000000000..dc2acd883 --- /dev/null +++ b/pr/619/docs/search.index/0d714d59fce3.js @@ -0,0 +1 @@ +rn_("AQUA9AIUAAABAFAAAQDzBAFj8gYTAAABAAEFAPPXEgAAAQABAPOCAmZ0AQABsAAUXgABZPQADAAAAQABAAEA84ACZWkTgAKw4BRpAAF0dg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/0e1d5ce71b67.js b/pr/619/docs/search.index/0e1d5ce71b67.js deleted file mode 100644 index 853c867d5..000000000 --- a/pr/619/docs/search.index/0e1d5ce71b67.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsAAQIgABsCAMYgABZWkBiQKwIBRxAAGgMAAAFHtpcBMAA6AgAAATLaCAAAATQGVpdfUVDAAAOQABAAEAAQABhgKwkBSYAAGgAAAAErpiZAGAArAwEyEAAaAwAAAQ+HJ21wAAAIWgMAAAEGygMAAAE3cQARM6MAAAAQAAAAAACgAQAAAAAQkCCQMJMwk0CSMMhxCOEEgRSRH9EmOAA7AQCPUAAWRtdA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/0e3272544c9f.js b/pr/619/docs/search.index/0e3272544c9f.js new file mode 100644 index 000000000..33e4830c9 --- /dev/null +++ b/pr/619/docs/search.index/0e3272544c9f.js @@ -0,0 +1 @@ +rn_("AQcA9AMSAAABAAEAAQAjAQKgcAAAEgJhcgF8BwAAAQMAOzAAAAEAAAgAAgCnDwYAWxMBAPMAAmN0OzAAAAEAAFcAJwCmBAsAbwUAABQJAQArDAEAMwwCAPMMAAD/DAIAEQ0BANAPAADVDwEA2A8BAN4PAABmEAIAbRABAHIQAQCXEAAADxEAABURAABhEQEAbhEBAIIRAQCGEQIA5hEBAPkRAgD/EQAAtRIAAL4SAQDDEgEACxMBABsTAQAgEwEAQBMBAFATAwBWEwEAtxMBAMsTAAA5FAAAYhQEAGsUAgA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0e58e1bb907a.js b/pr/619/docs/search.index/0e58e1bb907a.js new file mode 100644 index 000000000..2ac461dfa --- /dev/null +++ b/pr/619/docs/search.index/0e58e1bb907a.js @@ -0,0 +1 @@ +rn_("AYECoCAAABSWsEAP/QABYnABBQD0RxMAAAEAmAABAPMDAWMBsBIAAAEMAbAAFIEAAXM7MAAAAQAABQABAJsUBQDzgAJudgGAArAwDFsAAaAwAAAMXWlvAQMBoAAAABRhcwH4EQAAAQQA9BcMAAABAAEAAQDXAwCAhrAABXQAAZFIAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/0e7e85b355d2.js b/pr/619/docs/search.index/0e7e85b355d2.js new file mode 100644 index 000000000..e192fa528 --- /dev/null +++ b/pr/619/docs/search.index/0e7e85b355d2.js @@ -0,0 +1 @@ +rn_("AQIA9asRAAABAAEAAQABAAGAArBgExUAAaAgAAARAG95AQABoMAAABQ6afRsEwAACAAcABsAAQYA9KYUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATQ3I7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0IAWrCgE7kAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCsEgMA84ACZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0ef2ff5ecde1.js b/pr/619/docs/search.index/0ef2ff5ecde1.js deleted file mode 100644 index 24676eac4..000000000 --- a/pr/619/docs/search.index/0ef2ff5ecde1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOjAAAAEAAAAAAAoAEAAAAOYP5w/WENcQYxH1EfYREhMTE6sUrBTzAQF58gsUAAABACMAA6BAAAARgqBQAAAUXmVvc/LKDwAA1wI=") \ No newline at end of file diff --git a/pr/619/docs/search.index/0f010111b606.js b/pr/619/docs/search.index/0f010111b606.js new file mode 100644 index 000000000..0faadb983 --- /dev/null +++ b/pr/619/docs/search.index/0f010111b606.js @@ -0,0 +1 @@ +rn_("AQIA9CQTAAABAJAAAQABAwD0WBMAAAEAmAABAPMFAmJ1OjAAAAEAAAAAAAcAEAAAAIUQhhA9ET4R8BHxES8TMBMBAgD0dREAAAEAfAEBAAEFAPN7EQAAAQABAAEEAPTLEgAAAQCmAAEA84CEEQkA") \ No newline at end of file diff --git a/pr/619/docs/search.index/0ffd4bca177b.js b/pr/619/docs/search.index/0ffd4bca177b.js deleted file mode 100644 index 5aa0197cd..000000000 --- a/pr/619/docs/search.index/0ffd4bca177b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHAUmAABoAAAAASkZmcBAQA7MAAAAQAABwABAEYMBwABAQGgcAAAEqFhARUHAAAjgAKhAAAAFKJkbnOAhKBgAAASoABBSA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/10205aeb3afc.js b/pr/619/docs/search.index/10205aeb3afc.js deleted file mode 100644 index 9173b5786..000000000 --- a/pr/619/docs/search.index/10205aeb3afc.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBoKAAABNtZPL2BgAAAQABgQKgMAAAFHOgUAAAE/xjcwEEA7AgEUwAAaBQAAAR+aBAAAAUO2xzdvI2FAAAAQDzAANhZW87MAAAAQAACAADAIkEAQAJDAAAFA0FAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1027029693c7.js b/pr/619/docs/search.index/1027029693c7.js deleted file mode 100644 index 396955139..000000000 --- a/pr/619/docs/search.index/1027029693c7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9asRAAABAAEAAQABAAGAArBgExYAAaAgAAARAG95AQABoMAAABQ7afRtEwAACAAcABsAAQYA9KcUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATRHI7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0MAWrCgE7oAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCtEgMA84ACZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1054b7cef79e.js b/pr/619/docs/search.index/1054b7cef79e.js deleted file mode 100644 index 006e46242..000000000 --- a/pr/619/docs/search.index/1054b7cef79e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOzAAAAEAAAYAAQBkEQYAAQAA9yUJAAABAFcHAQBzAAEAFgEBggKgIAAAESegMAAAEY1pdPOAA2FncwEBAaBAAAAUOmXyaBQAAAEAI4ACsFAT7QABZnPzgAJpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/11080eab78d7.js b/pr/619/docs/search.index/11080eab78d7.js new file mode 100644 index 000000000..3b33d8115 --- /dev/null +++ b/pr/619/docs/search.index/11080eab78d7.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAI0AAgD3EAAACBKMAAEAAbBwE8kAAWXy4g8AAAEAIwACoEAAABQjZXP0TRAAAAEASwQBADOAA6BgAAARqmRpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/113efc17a327.js b/pr/619/docs/search.index/113efc17a327.js deleted file mode 100644 index 5df05c5ea..000000000 --- a/pr/619/docs/search.index/113efc17a327.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOjAAAAEAAAAAAAgAEAAAAA8JdxAiESMRJBH6E/sThhSLFAECAPSyEAAAAQABAAEAE4ACoNAAABRzY3NTgAOgcAAAFG5laW+DgISwIBOeAAGgIAAAD+uwAAdUAAEKCAQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/115969eb294f.js b/pr/619/docs/search.index/115969eb294f.js deleted file mode 100644 index 868949639..000000000 --- a/pr/619/docs/search.index/115969eb294f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsFARBgABoLAAABP8Y3MBBADzxA8AAAEAAQABgAKgUAAAENWgYAAAEUVpcgGAAqAgAAAMeKBgAAARRGVoAQEA83QMAAABAAEAE4ECoBAAAAx3YWMBgAKwEBPHAAGwMA0aAAFlcyMAAqBAAAAUZWV38ocUAAABAAEDADswAAABAAAFAAIAcAwDAFgRAQABBgD0EhMAAAEAmAEBABMAArBgExQAAWZt8uUMAAABAAEBAPQREQAAAQCwAAEAI4ACoLAAABPjZGcBggKgoAAAE0WgQAAAEHRvdvOAA2ducgGAAqBAAAATC6AwAAAPwWhstz8AAIqwQA/CAAE0YFc7MAAAAQAAGgAEAAoCAABqBA4A9QsJANIMAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/116035aee40f.js b/pr/619/docs/search.index/116035aee40f.js deleted file mode 100644 index d94fd0756..000000000 --- a/pr/619/docs/search.index/116035aee40f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA88ESAAABAAEAI4ECsSAUuwABY2sBBAGgQAAAEfpl8wkNAAAQBAEAAQAAOzAAAAEAAAUAAgDzEAMAihMBAHOAhKAwAAAUOggwAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/121b35b185ca.js b/pr/619/docs/search.index/121b35b185ca.js deleted file mode 100644 index d5b5ef0af..000000000 --- a/pr/619/docs/search.index/121b35b185ca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQsA9HQUAAAMACIAEQABCgA6MAAAAQAAAAAABwAQAAAATxNQE+sT7BMlFCYUdRR2FPOBAm90EwCEsCATQwBasDARSgABoFAAABEyEDACOzAAAAEAAAgABACFAAEArwADAFoHAQB0CQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/122997da0a01.js b/pr/619/docs/search.index/122997da0a01.js new file mode 100644 index 000000000..4a75a9bac --- /dev/null +++ b/pr/619/docs/search.index/122997da0a01.js @@ -0,0 +1 @@ +rn_("AQEA9GkHAAB4COEAAQABBQD0SBQAAAEAAQABAAEFAPQ4EwAAAQCUAAEA8wICY3X1VhAAAAEAxgABAAEA84ACbnM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/12aea47c4523.js b/pr/619/docs/search.index/12aea47c4523.js deleted file mode 100644 index 9791f3664..000000000 --- a/pr/619/docs/search.index/12aea47c4523.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9asRAAABAAEAAQABAAGAArBgExYAAaAgAAARAG95AQABoMAAABQ7afRtEwAACAAcABsAAQYA9KcUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATRHI7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0MAWrCgE7oAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCtEgMA84ICZWkjAAKggAAAFLdmaPIACQAAlgoBBQDzHhMAAAEAAQABAQA7MAAAAQAABQACAAQMAwD3EQEAUwADsDAUVgABZXBy9OQPAAABAO4AAQABAAOwQBQbAAGhQAAAFIugUAAAEe1iY2YBDAcAAPOAAm1uAQGEoLAAABPYsEAQtwABsMAUBwABoGAAABGSFCAE9vMGAABcCQEAOgEvARQBAQUAOzAAAAEAAAUAAQDdEgUAAQcA9WQTAAABAAEAAQABACOAAqBQAAARY2Fv8wCFIEkCOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/12c0183bdd8b.js b/pr/619/docs/search.index/12c0183bdd8b.js new file mode 100644 index 000000000..0647b009f --- /dev/null +++ b/pr/619/docs/search.index/12c0183bdd8b.js @@ -0,0 +1 @@ +rn_("AQYA9LsTAAABAAEAAQABDwD0phQAAAEAAQABAAEAAbDwFLAAAWs7MAAAAQAACAADABcUAAAcFAYARxQAAAECAPR1EAAAAQCzAAEA9wAAAIWxABSZAAGJMADy2hIAAAEAE4ACsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAAGAAqAAAAAMKrAwFGUAAXFyAYACoEAAABEQsMAUWwABZXMBAQA7MAAAAQAAEwABACQQEwAjgAKwkBPDAAFpbXc2AACKoFAAABQmsHAUBAABoCAAAAz0nFUROzAAAAEAAAsABABYBwAA6RADALoSAQApFAQAAQIBsDARdwABcAGhEgAAs4CEoCAAABHhAigE") \ No newline at end of file diff --git a/pr/619/docs/search.index/12c236cb8009.js b/pr/619/docs/search.index/12c236cb8009.js deleted file mode 100644 index 1419f48ef..000000000 --- a/pr/619/docs/search.index/12c236cb8009.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9UIUAAABAAEAAQABAPMAAWY7MAAAAQAABQACAPEBAACaEAQAAQIAOzAAAAEAAAsAAgDSEwUAkBQFAPMGAW07MAAAAQAADQAEANMMAABtEQAA6hIFAE4UBQBjgAOwAAknAAFlbXM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/135a83bd03db.js b/pr/619/docs/search.index/135a83bd03db.js new file mode 100644 index 000000000..9152fbcd2 --- /dev/null +++ b/pr/619/docs/search.index/135a83bd03db.js @@ -0,0 +1 @@ +rn_("AQEBoGAAABSWc/LbEQAAAQABCAD1QRQAAAEAAQABAAEAowCEsCAJdgABoIAAABLvMEAIOzAAAAEAAAUAAgDxAQAAmhAEAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/138816621609.js b/pr/619/docs/search.index/138816621609.js deleted file mode 100644 index 9bf9c1bd1..000000000 --- a/pr/619/docs/search.index/138816621609.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsCATQwBaoFAAABEybXNDgAOw4BQFAAE+D29xafpkZ3IBAwDz2BIAAAEAAQAjgAKwMBQLAAFjaTOAA7AADQcDZWFpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/13948c9f9736.js b/pr/619/docs/search.index/13948c9f9736.js deleted file mode 100644 index 4f76d97b2..000000000 --- a/pr/619/docs/search.index/13948c9f9736.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9QATAAABAPAAgAABABOAArAwEzIBSWlwAQYA864TAAABAAEA8wICYnMBQBAAAPMBAWYBaAcAAAECAPRZEwAAAQCYAAEAM4ADsEATJwABaXV5") \ No newline at end of file diff --git a/pr/619/docs/search.index/139d3d613348.js b/pr/619/docs/search.index/139d3d613348.js deleted file mode 100644 index d17811266..000000000 --- a/pr/619/docs/search.index/139d3d613348.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAABEABQCsBQAANgwAAOsMAAAKEA0AcBEAAAGEArDQFK8AAaCQAAATrGJoAYQCsAARfgABsAARgAABNDaXBAAAh6AgAAAR3qAwAAARRKAwAAASqbBwD+IAActACDswAAABAAARARQAuAEAAKMFAAD+CAAABAkAACEJAgARDAAAUgwBAHkMAQDuDAAAHA3tAM4PAADfDwEA1RAAAJIRAADxEgEA0hMFAO8TAAB4FAAAkBQFAK0UAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/13a818f01933.js b/pr/619/docs/search.index/13a818f01933.js deleted file mode 100644 index 139bc1e2d..000000000 --- a/pr/619/docs/search.index/13a818f01933.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYAOzAAAAEAAAkAAQBOEQkAI4ADsGATggABsDAPzAABaXN0AQgA9UIUAAABAAEAAQABAPMBAWb1mhAAAAEAAQABAAEAY4ADoDAAABNEZWd0") \ No newline at end of file diff --git a/pr/619/docs/search.index/1411b24ac546.js b/pr/619/docs/search.index/1411b24ac546.js deleted file mode 100644 index d4223438f..000000000 --- a/pr/619/docs/search.index/1411b24ac546.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9yIRAAABAAEA1gIBAIsABQABAgD0shAAAAEAAQABABOAAqDQAAAUc2Nz84ACZW8jgQKwAAdUAAFsdAEAADswAAABAAAFAAEAsQUFAFOAhKBQAAAUyLCgFAcAAQggBQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/146d3be3d959.js b/pr/619/docs/search.index/146d3be3d959.js new file mode 100644 index 000000000..f16708db8 --- /dev/null +++ b/pr/619/docs/search.index/146d3be3d959.js @@ -0,0 +1 @@ +rn_("AQMA9gUNAADnAloAAQDQAgEAAQQAOzAAAAEAAAoABACPEAUA0hIBADITAQBYFAAAAYYCoAAAABNUoAAAABNVZHLzAgF2AYATAADzgAJlbycBAADHoDAAAA/roHAAABKioIAAABQnsNATxgABoLAAABQnQEUICTswAAABAAAJAAMAwAUCACEHBABeDAEAI4ACf1YlaUD0ZHIBAAA6MAAAAQAAAAAACgAQAAAAVwlYCSEQbhNvE58ToBNMFKQUvBS9FBOAAqAwAAAQpWx084ACYWU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1472ccb432ba.js b/pr/619/docs/search.index/1472ccb432ba.js new file mode 100644 index 000000000..a5cb6f506 --- /dev/null +++ b/pr/619/docs/search.index/1472ccb432ba.js @@ -0,0 +1 @@ +rn_("AQgBoIAAABS2ZgGVEwAAE4ACoOAAABR4YnABAwGwABQwAFBz9ugPAAABAMQAKwABAP4CAYACsEASvAABoBAAABEYcHIBgQOgAAAAEYmwAA/TASegEAAAD8tlc3XzgANhb3IBAgD12xAAAAEAAQBdAgEAAQQAOzAAAAEAAAkAAQBOEQkAAQAA9L4RAAABAAEAAQABgAKgkAAAE/CwUBKkAAFid/OAAmR0o4CEsFAUDAABsJATMgABQCADVwMAAIagcAAAE+egQAAAFF0wQQw6MAAAAQAAAAAAQAAQAAAAwgTDBIgFiQWKBYsFjAWNBY4FjwWQBZEFgQcsCS0JMgkxDDIMVAxVDFYM6QzqDPcMnA69D74Pvw/AD9MP8g/zDzgQthDEEMUQxhDHEOcQ6BD6ECARIRGNEeER6hHrEe8R7xIoEykT2xPcE+ITDBQNFC4ULxRGFIEUghSzFLQUvhS/FA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/147bf4a9aa00.js b/pr/619/docs/search.index/147bf4a9aa00.js deleted file mode 100644 index d173ae2ff..000000000 --- a/pr/619/docs/search.index/147bf4a9aa00.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA82YQAAABAAEAAYACoLAAABQnsDATcQABbnRDAAOgIAAAERuwUBHzAAFlaGk7MAAAAQAABgADABMMAAAEEgMA0BMBAPOAAmRy") \ No newline at end of file diff --git a/pr/619/docs/search.index/158247ec2aa8.js b/pr/619/docs/search.index/158247ec2aa8.js new file mode 100644 index 000000000..b8e7866d6 --- /dev/null +++ b/pr/619/docs/search.index/158247ec2aa8.js @@ -0,0 +1 @@ +rn_("AQUBsEASwwABZTswAAABAAAFAAIA5xIBAEgUAwABggKgkAAAFDWgkAAAFDYyMwEAA6AgAAASn6AgAAAI/rCAFK4AAWltcDswAAABAAAOAAYAnAQAANQEBQBuCQAAtg8DAAgUAAAaFAEA8wABcwEyEQAAAQUA9JETAAABAAEAAQABAAD1fgwAAAEAAQABAAEA84ACZ2tzgISwsBPsAAERSAABBQGgQAAAEfll8wkNAAAQBAEAE4ACoDAAAAw3ZXIBgAOwUBQuAAGgEAAAC/+gcAAAE4BnbnJHAQAAhaBgAAAUCaBQAAAUYaCgAAAT+xUBBDswAAABAAARAAQAAAIBALkQCAC2EQMAwBICAAGFArBwFBUAAbAwE2gAAWVzEwADsEAP2AABoGAAABGMYmVzOzAAAAEAABIABACpBQEAygYKAFEQAQCpEAMAAQMA9G0QAAABAAQAAQABCgGgQAAAFGRl8oYUAAABABOAArBgEroAAWNp84ACZHLzAAJlbzswAAABAAAJAAIAngcFAOMHAwABAgGwMBFYAAFuOzAAAAEAAAkAAQD1CwkAAQAA9K4QAAABAAEAAQABAQA7MAAAAQAA7gACAMgFAAAHCO0AYwADsBATJgABZWlzOjAAAAEAAAAAAA4AEAAAABEJTAlNCU4JTwkeDB8Mrg+vD9cP6g/aEAARjROOE+OAhLAgB1oAARFABAGBhLAwDAsAAaBAAAAM1KCAAAARX7BADNUAAQAAHQEFAPXdEwAAAQABAHoAAQATgAKgAAAABv5hZwEDAPSYEgAAAQBrAQEA84ACaW8BAQA7MAAAAQAA7gACAHgHAAAHC+0AAQgBsEAUZQABZfUpFAAAAQABAAEAAQDzgQJndAEBAaBwAAAR/2k7MAAAAQAAAAECAHcHAAAHCv8AAQUA88oQAAABAAEA84ACYW8TgAKgQAAADDZydQGAAqAAAAAHXKAQAAAJEGR4EwACsCANAAABZXLyGxAAAAEAE4ACsLAUsAABcngBCgD0mBMAAAEAAQABABOAArAQERQCOWFlAQQA9KkQAAABAAEAAQABBAA6MAAAAQAAAAAABwAQAAAAOBM5E0cTSBPNE84T4BPhEwEDAPPUEgAAAQCqANOAhLBAEQYAAQFIAce/AwCPoIAAABLWsGAM7wABsEAMYAABsTAUgwABP6kfOzAAAAEAAEsAIgB7AAAAgAAAAL0EAQDJBAAAggUBAEIHAQBSBwAAVgcBAEUJAABZCQcAcAkBAAoMAAAhDAEAKAwBADwMBwBgDAEAfAwBAMsMAQDmDwEAVhABANYQAQDjEAEA+xAAAB0RAgAtEQEAPxEEAGMRAACwEQMA9BEBALASAAAREwEAFRMBAEMTAACqFAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/15a4e01e0b92.js b/pr/619/docs/search.index/15a4e01e0b92.js deleted file mode 100644 index fc7e010fe..000000000 --- a/pr/619/docs/search.index/15a4e01e0b92.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUBsEASxAABZfLoEgAAAQABAAA7MAAAAQAAEQAEAAACAQC5EAgAthEDAMESAgABCgGwQBRmAAFl9SoUAAABAAEAAQABAEcGAACHsCARFAI6sMAUsQABoCAAAAb+sDAHWgABGIkKOjAAAAEAAAAAAAwAEAAAAFYHVwdFCSEMIgwoDCkMfAx9DMsMzAwWExcT") \ No newline at end of file diff --git a/pr/619/docs/search.index/16f09b5de525.js b/pr/619/docs/search.index/16f09b5de525.js deleted file mode 100644 index c7c8db6f1..000000000 --- a/pr/619/docs/search.index/16f09b5de525.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9GkHAAB4COEAAQABBQD0SRQAAAEAAQABAAEFAPQ5EwAAAQCUAAEA8wICY3X1VhAAAAEAxgABAAEAYwAEoDAAAAw6oHAAABHiZW5zdvN0EAAAnwAjAg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/16f491f146e5.js b/pr/619/docs/search.index/16f491f146e5.js new file mode 100644 index 000000000..4305b86cb --- /dev/null +++ b/pr/619/docs/search.index/16f491f146e5.js @@ -0,0 +1 @@ +rn_("AYADsAAT4wABsAAT5QABsHAUXgABNDZhAQQA9LMUAAABAAoAAQAjgQKgQAAAEV5tcAEBADswAAABAAAIAAMA1hIAAEkTAADAFAYAxwEAAMWgQAAAEFiggAAAErBABoAIOzAAAAEAABYACAD2DwEAFhEBAFoRAwDREQUAvxMDAA8UAABuFAEAohQBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/17184d64783b.js b/pr/619/docs/search.index/17184d64783b.js new file mode 100644 index 000000000..10cda0ccb --- /dev/null +++ b/pr/619/docs/search.index/17184d64783b.js @@ -0,0 +1 @@ +rn_("AQIA9asRAAABAAEAAQABAAGAArBgExUAAaAgAAARAG95AQABoMAAABQ6afRsEwAACAAcABsAAQMA9JETAAABAAEAAQABBgD0phQAAAEAAQABAAECAPT+EAAAAQCaAAEAAQIBoEAAABNDcjswAAABAAAHAAIA/BABAJMRBQDzgAJhb2cHAACHsIATQgBasKATuQABDDAHOzAAAAEAAA4ABACTBAUAIAwAAMYRAwCsEgMApwAAgIWg8AAAE8ywUBBPAAGgkAAAEYqUgQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/179216a7d32e.js b/pr/619/docs/search.index/179216a7d32e.js deleted file mode 100644 index 2a506c73d..000000000 --- a/pr/619/docs/search.index/179216a7d32e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYADsAAT5AABsAAT5gABsHAUXwABNDZhAQQA9LQUAAABAAoAAQAjgQKgQAAAEV5tcAEBADswAAABAAAIAAMA1xIAAEoTAADBFAYAxwEAAMWgQAAAEFiggAAAErFABoAIOzAAAAEAABcACAD2DwEAFhEBAFoRAwDREQYAwBMDABAUAABvFAEAoxQBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/17bd24afd385.js b/pr/619/docs/search.index/17bd24afd385.js deleted file mode 100644 index c60dbebb5..000000000 --- a/pr/619/docs/search.index/17bd24afd385.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9UMQAAABAAEAYAIBAAEEAaAAAAAQ4HP1Ag0AAAEAAQA9AwEAAQIA9asRAAABAAEAAQABAAGAArBgExYAAaAgAAARAG95AQABoMAAABQ7afRtEwAACAAcABsAAQYA9KcUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATRHI7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0MAWrCgE7oAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCtEgMA84ICZWlHAQAAhbBwE8oAAaCAAAAUt6BAAAAP+LBABPQACQAA4gYBALMDAYECoCAAABD6sFASvQABYW8BBAGgAAAAE+NzAfkQAABjBAOwUBFrAAFjZXP2CAkAAAEAAQAsAAEAbAkBAAA7MAAAAQAAJAAIAEQHBwBDEAIAnBENAMsRAgClEgEAKxMBAHwTAQATFAIAAQUA8x4TAAABAAEAAQEAOzAAAAEAAAUAAgAEDAMA9xEBAFMAA7AwFFYAAWVwcvTkDwAAAQDuAAEAAQADsEAUGwABoUAAABSLoFAAABHtYmNmAQwHAADjgISxQBS0AAECMBABAYSgsAAAE9iwQBC3AAGwwBQHAAGgYAAAEZIUIAT28wYAAFwJAQA6AS8BFAEBAwA7MAAAAQAABQABAN0SBQABAAGgoAAAFEdy9O4PAAABAPYAAQDzgQJncwEHAPVkEwAAAQABAAEAAQABgAKgQAAAEWOwUBFKAAFjafOAAmFvAQABoCAAABGDcvM4DAAAggNrAUOAhKAAAAAUJKAwAAAUJIAFcgAdKAggIQEDArBAEyEAAaAwAAATd2V38o4QAAC7ABODAqBwAAATsWdvAQIA9QATAAABAPAAgAABABOAArAwEzIBSWlwAQYA864TAAABAAEA8wUCYnMBQBAAAAECAPQdEAAAAQABAAEAI4ACoGAAABKhYmP3XwEAzbBgEN4AAaCQAAASosBOchU6MAAAAQAAAAAAGAAQAAAAGQIaAoIEgwSEBBUHTweCB4MHhAeFB4YHhwf/C3gMCA07EE0QThAbEZsRmhSbFK8UsBQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/180af5c927d2.js b/pr/619/docs/search.index/180af5c927d2.js new file mode 100644 index 000000000..d66d3aa36 --- /dev/null +++ b/pr/619/docs/search.index/180af5c927d2.js @@ -0,0 +1 @@ +rn_("AQACoCAAABOPsDAR6gABaXTy9hIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PkTAAABAIsABQATAQOwkBRiAAGwUBM+AWdnbHA7MAAAAQAAEgAJAGkQAgDtEQEALRMBAE4TAQCFEwEA6hMBACQUAQAzFAEAdBQBAAGAArAwEeYAAbAwEegAAXJ2AQQBsAAStgABZDswAAABAAAFAAIA4hEDAOUSAQC3BQABh7BQErgBFLBgEzwAAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETQTbRMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwGEoFAAABGLoDAAABCkFAEQ8pwHAAABABOAArBgEtoAAWNnE4ADoLAAABQXoEAAAA6cZW9z") \ No newline at end of file diff --git a/pr/619/docs/search.index/183c7cb9c0b3.js b/pr/619/docs/search.index/183c7cb9c0b3.js deleted file mode 100644 index 1b05644ea..000000000 --- a/pr/619/docs/search.index/183c7cb9c0b3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsEAUYwABsGATNwABZXIBBQD0nxAAAAEAAQABAPOAAmZtAQYAOjAAAAEAAAAAAAgAEAAAAN8P4A+SEfES8hLvE3gUrRSuFAEAArCwFAcAAaFAAAAUpmVn9H0HAAABAAEAAQDDAISgsAAAE9iwQBC3AAEUIAT38wYAAN4FfgMBADoBLwEUAWOAA7AwEBsAAWFlaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/18c195f86148.js b/pr/619/docs/search.index/18c195f86148.js new file mode 100644 index 000000000..a744b1084 --- /dev/null +++ b/pr/619/docs/search.index/18c195f86148.js @@ -0,0 +1 @@ +rn_("AQcA9AMSAAABAAEAAQAjAAKgcAAAEgJhcgF8BwAAAQAA9iARAAABAJIDAQAKAAEAAQAAOzAAAAEAAAYAAgCLEwAA8xMFACOIArBAFGsAAWVzAQ0BsEAUZQABZfUpFAAAAQABAAEAAQABBQA7MAAAAQAACAADAPwRAgABEwQAKBQAANcDAACGAD0DWPZcFIQG9b8EAAABAA4IAQABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1921a81b6ef5.js b/pr/619/docs/search.index/1921a81b6ef5.js new file mode 100644 index 000000000..f50fa2823 --- /dev/null +++ b/pr/619/docs/search.index/1921a81b6ef5.js @@ -0,0 +1 @@ +rn_("AQEBsIATagABdfJKCQAAAQAjgAKwEAlIAAEzNgEGAPPxEAAAAQAVAROAArAAD7sAAW91AQIA81MHAADzAQEAAQMA880SAAABAAEAI4ACsAARxAABaGkBAAA7MAAAAQAAEwABAIgHEwAjgAKgMAAADOBhZfOAAnJ0E4ACsDATuQABYWwBAAGggAAAFLZm8gAJAACVCgEHAPVjEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MCAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAAE4ACoEAAAAwSYW8BAwGwQBR7AAF08tgTAAABACOFAqBAAAAUCGJzIwADsEARAwABoFAAABFwYWJm9w0JAAABAEgAcgcBAGIAAQATgQKgUAAAEf9ndAGAAqBAAAAR7KAgAAAT52FpAQIA9EMJAAABAAIIAQABAgDzVAwAAAEAAQATgAOwEAlBAAGwMBQaAAFpdXkBAgA7MAAAAQAACwACANETBQCPFAUA8wgBbTswAAABAAAMAAMAbREAAOkSBQBNFAUAAYECoIAAABLWoHAAABQuYXPzgAJucrfbAQCNoUAAABSKoCAAAAlFoFAAABACN5UPOzAAAAEAADUCBQD9AQAAIwIyAQwHAAB3BwAABwr/AA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1a644fbba3cb.js b/pr/619/docs/search.index/1a644fbba3cb.js deleted file mode 100644 index ad40814c6..000000000 --- a/pr/619/docs/search.index/1a644fbba3cb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9BITAAABAJgBAQATAgKwYBMUAAFmbfLlDAAAAQAjggKwQBNBAAFlbAEFAPQDFAAAAQBQAAEA8wMBY/IHEwAAAQABgQKgAAAACTKgMAAAD9dzdBOAAqAQAAAHUG5404CEsHAUuwABkEAB") \ No newline at end of file diff --git a/pr/619/docs/search.index/1a800e9c8293.js b/pr/619/docs/search.index/1a800e9c8293.js deleted file mode 100644 index 13b2e59d3..000000000 --- a/pr/619/docs/search.index/1a800e9c8293.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEATuAABZfLGBgAAAQABBADzbxAAAAEAAQBDAAOwQBMcAAGxABP/AAFlZnA7MAAAAQAAJAAGABgCAADVBgwA4wYMAKcPBgAQEQAAXBMBAGOAA7AwDBYABWFlaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1a989f91d70f.js b/pr/619/docs/search.index/1a989f91d70f.js new file mode 100644 index 000000000..81374a0e2 --- /dev/null +++ b/pr/619/docs/search.index/1a989f91d70f.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwDLEQIAexMBABIUAgABBADzzhEAAAEAAQAjAAKgYAAAEvxhcvPvEAAAAQDJAQGAAqEQAAAUobCAFJcAAWl1NwQAgoexUBS+AAGgAAAAEM6wcBPbAAGhMAAAFLIKQBsTgAKwEBMIAAFpcg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1adf7d09a2d4.js b/pr/619/docs/search.index/1adf7d09a2d4.js deleted file mode 100644 index e1a98a16e..000000000 --- a/pr/619/docs/search.index/1adf7d09a2d4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9L4RAAABAAEAAQATAAKgMAAAEYlldPTEEAAAAQABAAEAAQMA9LoRAAABAAEAAQABgAKgAAAAEJWgAAAAEJY0NvMDAXYBBg0AAJcCAACIsKATHAABsCAMKAABsGATFgABsIAS+wABoCAAABEACUxGOjAAAAEAAAAAAAkAEAAAAAkHCgcLBzkM+A9fEaoSqxKsEl4U") \ No newline at end of file diff --git a/pr/619/docs/search.index/1ae8c9ceb124.js b/pr/619/docs/search.index/1ae8c9ceb124.js new file mode 100644 index 000000000..8422fadc8 --- /dev/null +++ b/pr/619/docs/search.index/1ae8c9ceb124.js @@ -0,0 +1 @@ +rn_("AYACsEATbgABoMAAABQuZW8BAgD01xEAAAEAAQABABMAA7AgEdsAAbCAFD8AAWFzdAHhDAAAAQQA8/8PAAABAAEAs4CEsEATgQABQQAG") \ No newline at end of file diff --git a/pr/619/docs/search.index/1b2c46b17d90.js b/pr/619/docs/search.index/1b2c46b17d90.js deleted file mode 100644 index f5beafae5..000000000 --- a/pr/619/docs/search.index/1b2c46b17d90.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9AUJAAABANUK7QAnAAAAyqEQAAAUeqBAAAARFbBgFGoAAaAQAAAMh7BQFAEAAbAwEXcAAaAAAAAMRbEgFIwAAbBAERMCI0BOsAk6MAAAAQAAAAAAFAAQAAAAGwkcCS8JMAkNDA4MDwwQDBYMGwzgDKISzhLPEtASiBOJE54TnxMRFBIU") \ No newline at end of file diff --git a/pr/619/docs/search.index/1b75e1cecf5e.js b/pr/619/docs/search.index/1b75e1cecf5e.js new file mode 100644 index 000000000..2dd804cef --- /dev/null +++ b/pr/619/docs/search.index/1b75e1cecf5e.js @@ -0,0 +1 @@ +rn_("AQAA9HcTAAABAAEAAQDzBgFz8vwTAAABAAEBAbBQEvgAAWX3GQkAAFIDAQANBAEA2wMBAAEDAPS+EQAAAQABAAEAAQMA9LoRAAABAAEAAQDzgwJsc/OAAmN0U4ADoBAAAAzNYW9y") \ No newline at end of file diff --git a/pr/619/docs/search.index/1b7f85a1565f.js b/pr/619/docs/search.index/1b7f85a1565f.js deleted file mode 100644 index 01cd86978..000000000 --- a/pr/619/docs/search.index/1b7f85a1565f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoDAAAAzRaQF3EwAAAQABsDARSgABbvJaBwAAAQABAQDz2gcAANgHAQATAAKgUAAAEKhlc/VZBAAAAQABAAEAAQABhAKwoBQZAAGwoBQbAAFjcvMBAXT07REAAOsAAQABAAEDAbBgFGoAAWY7MAAAAQAABwADAA0MAwCIEwEAERQBAPOAAmFl84CEACgF") \ No newline at end of file diff --git a/pr/619/docs/search.index/1bbdc0f8e5e9.js b/pr/619/docs/search.index/1bbdc0f8e5e9.js deleted file mode 100644 index 05a1a48dc..000000000 --- a/pr/619/docs/search.index/1bbdc0f8e5e9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAEMAAgAkCQAAiAxCAAEFAPTEEAAAAQABAAEAE4ACsLATogABYWwBBAD0tg8AAAEAAQABAHMABKAQAAAQeGJwcnY7MAAAAQAACgACAGQRBgC6EQMAAYACsIAREwIjsOAUCwABaXIBAwGwQBFhAAFlAZcOAAABBQA7MAAAAQAABgABAF8QBgABAwA7MAAAAQAABQABANoMBQDzAAJwczowAAABAAAAAAAMABAAAACoBcUGGAldDGoMBhEHEbcSuBIOEw8TEBMRE1cAAACFsFAQtgI6sFAP1ADPoEAAABGMSIADOzAAAAEAAA8ABgCgBAAAaAUDAMEPAADjEQMAshIDAOYSAQDTAISgYAAADO4QCAbzrwEAAAEAHQs=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1c47dbb0412a.js b/pr/619/docs/search.index/1c47dbb0412a.js new file mode 100644 index 000000000..f445eb1a4 --- /dev/null +++ b/pr/619/docs/search.index/1c47dbb0412a.js @@ -0,0 +1 @@ +rn_("AQUA9MsSAAABAKYAAQABCAD0hxMAAAEAiAABADMBA7BAE1YAAWFiZTowAAABAAAAAAAMABAAAAAzBzQHNQf4DPkMyw85EIgQiRCKEIsQoxJ1EwEAADswAAABAAAgAA4AwgQBAIgFCQAsCQEAMQwBAOkMAQCcDgAAvQ8DANMPAADyDwEA5xABAPoQAACNEQAA6hEBAO8RAAABgQKwABF+AAGwABGAAAE0NiOAArCAFIsAAW9wAQABsEATUgABZfOJEQAAWgEBALcBAICFoGAAABEmEAEL") \ No newline at end of file diff --git a/pr/619/docs/search.index/1c6850fbc408.js b/pr/619/docs/search.index/1c6850fbc408.js deleted file mode 100644 index c895bf6b1..000000000 --- a/pr/619/docs/search.index/1c6850fbc408.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCoFAAABEUoKAAABNOa3ABAAGwQBKZAAFs9HAJAAABAHIHAQABCAD0rRIAAAEAAQABAAEEAbAAEO0AAXMBVRAAAAECAaBQAAATC2MB0gwAALcAAACFsEANEQABoDAAAAwUlQABOzAAAAEAAAgABADGBAAAmAUCANUMAQDEDwIAJwEAgIWwMAkvAAGgEAAAE4SwIAd6AAGRAEQBEAGwABSCAAFzOzAAAAEAAAUAAQCcFAUAAQMA9HAJAAABAHIHAQBjgAOgAAAADBRucnUBAAKw0BPKAAGgMAAAD8diavZ8BQAAAQABAEsAAQB3AQEAAbCAE+kAAXQ7MAAAAQAARQAEAMcFAAAaCQAAJAkAAIgMQgABCQDzzhIAAAEAAQDzgANjZ3QBgwKgkAAAFDagkAAAFDcyMwGAAqBQAAAUYqCAAAATgWNl8wACc3TyQgcAAAEAAQABoLAAABPMYvNWEwAALgEBACOAAqAAAAATVWRyI4ACoFAAABQoY2XzgAJpeQEEAPU/EQAAAQABAAEAAQDzAQFuATgHAAABAQA7MAAAAQAACQACAOkHBwAUEwEAAQYA9LwTAAABAAEAAQABDwD0pxQAAAEAAQABAPOBAmhtAQABsEAUZgABZfUqFAAAAQABAAEAAQBTgAOgIAAAEeJsbnTXbQCAy6AgAAAUl7BgENEAAbBAD/0AAcAbOAo=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1c7dd0f38597.js b/pr/619/docs/search.index/1c7dd0f38597.js new file mode 100644 index 000000000..63e359b42 --- /dev/null +++ b/pr/619/docs/search.index/1c7dd0f38597.js @@ -0,0 +1 @@ +rn_("AQwA9L8TAAABAAEAAQABBgDzchEAAAEAAQABggKwYBNFAAGw0BRnAAFpchOAArAQDOwAAWVpFwMAg4ixMBSGAAGgYAAAEXGgUAAAEQWwkBMXAAGwQBEBAAG0EAfzAAFh9EMJAAABAAIIAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1ca4225d7479.js b/pr/619/docs/search.index/1ca4225d7479.js new file mode 100644 index 000000000..186c8c059 --- /dev/null +++ b/pr/619/docs/search.index/1ca4225d7479.js @@ -0,0 +1 @@ +rn_("AQIA9f8SAAABAPAAgAABABOAArAwEzEBSWlwAQYA860TAAABAAEA8wICYnMBQBAAAPMBAWYBaAcAAAECAPRYEwAAAQCYAAEAM4ADsEATJgABaXV5") \ No newline at end of file diff --git a/pr/619/docs/search.index/1d8b2f1b629f.js b/pr/619/docs/search.index/1d8b2f1b629f.js deleted file mode 100644 index 13f29fec8..000000000 --- a/pr/619/docs/search.index/1d8b2f1b629f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsIAT6QABdAEaCQAAAYECoBAAABNFoHAAABONYWPzAQFy8qoRAAAgAPOAAmVpAQAA9BcMAAABAAEAAQDzgAJkcvMAAWX0kAAAAGQMSgcBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1f1ee380fec9.js b/pr/619/docs/search.index/1f1ee380fec9.js deleted file mode 100644 index 59b8c9cf3..000000000 --- a/pr/619/docs/search.index/1f1ee380fec9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoGAAABQKoKAAABP8YWkBCwD0mRMAAAEAAQABAAEEAPSpEAAAAQABAAEAI4ACsEARBgABbHLzAANjZHMB+xAAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1fa35b1e6419.js b/pr/619/docs/search.index/1fa35b1e6419.js deleted file mode 100644 index bf6292d01..000000000 --- a/pr/619/docs/search.index/1fa35b1e6419.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsKAS0wABZTswAAABAAAJAAIA6QcHABQTAQABAAGgIAAADO5tAYQFAAABgAKwoBLRAAGwQA/aAAFsbwEAAPQOEwAAAQABAAEA8wQBZPSyEgAAAQABAAEAIwKEsKAUVgABsEATDAABsHAT/QABFYAAASgUAAABAAGwgBQ8AAFw8jgUAAABAEMAA6AgAAARYKBAAAAStmRlc/P5DwAATQMBAPOBAmVp1wIAAIawIBKXAAGw0BRAAAEXAQL0oQQAAAEAAQDJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/1fb996d7a506.js b/pr/619/docs/search.index/1fb996d7a506.js deleted file mode 100644 index 188a244ad..000000000 --- a/pr/619/docs/search.index/1fb996d7a506.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABGDZQE7EAAAAQgA9MYRAAABAAEAAQABAwGgQAAAEYJlAcoPAAABAgDzMwwAAAEAAQAjAAKwIAwhAAFrcvb0BgAAAQAQCu4AAQAzAvOAAnJ4AQMBsIAUXwABdjswAAABAAAMAAMAFhEBANERBgDAEwMAI4ACsGAQhwDBYXIBAwGgAAAAEDpz8sgPAAABACOAAqCwAAAT6GVoAQMBoEAAABEVZfIbCQAAAQDXCwAAiqAgAAAHaLCwEzcAAaCAAAARyqAAAAATRJ8ITDowAAABAAAAAAAKABAAAAALAnoEewR8BAsMDAx0DHUMdgxFE1sT") \ No newline at end of file diff --git a/pr/619/docs/search.index/20887c9c6a32.js b/pr/619/docs/search.index/20887c9c6a32.js deleted file mode 100644 index 6b4d01db9..000000000 --- a/pr/619/docs/search.index/20887c9c6a32.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEAUfAABdDswAAABAAANAAYA/hIDAGkTAQDZEwEA8BMBAHEUAQCYFAEAE4ACsDATMgFJaXABBQDzrhMAAAEAAQATgAKgMAAAFAlleVMBA7BwFBYAAWJlcwFAEAAAE4ADsDAUjAABsCAG/wABZWxz") \ No newline at end of file diff --git a/pr/619/docs/search.index/212a3b848bca.js b/pr/619/docs/search.index/212a3b848bca.js deleted file mode 100644 index 373992134..000000000 --- a/pr/619/docs/search.index/212a3b848bca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9LwTAAABAAEAAQABDwD0pxQAAAEAAQABAPOHAmhtAQAA9A4TAAABAAEAAQDzBAFk9LISAAABAAEAAQAjh4SwoBRWAAGwQBMMAAGwcBP9AAEVgAABAAGgQAAAEJdlOzAAAAEAAAcAAgBuBwUA/wcBABOAArBQEE0AAWRyAQkA9d4TAAABAAEAegABALcCAICGsCASvQABQLl/hycoEUkB") \ No newline at end of file diff --git a/pr/619/docs/search.index/21ace249e57c.js b/pr/619/docs/search.index/21ace249e57c.js new file mode 100644 index 000000000..238f0651a --- /dev/null +++ b/pr/619/docs/search.index/21ace249e57c.js @@ -0,0 +1 @@ +rn_("AQgA9OgTAAABAFYAAQABAgGgYAAAFJZz8tsRAAABAAGAArAgECIAAaCQAAAURmFlAQcBsEAUZQABZfUpFAAAAQABAAEAAQABAwGwQBR7AAF08tgTAAABACOEAqBAAAAUCGJzE4ACsMAUrgABdXkBAQD01xEAAAEAAQABABOAArAwEQMAAWRsN3QAAIuwQBO3AAGgUAAAEXCgkAAAE6uwUBMIAAGgMAAADG+zmAc7MAAAAQAAYgARAAgCAQBmBAMAxwUAAMYGAQBjBwEADQkBABoJAAAkCQAAVgkAAIgMQgDhDAAA7g8BAMgQAQDlEAEAKxEBAKsRBAC8EgEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/21b5a273209d.js b/pr/619/docs/search.index/21b5a273209d.js deleted file mode 100644 index 512f2d332..000000000 --- a/pr/619/docs/search.index/21b5a273209d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgC2EQMAwRICAAEKAbBAFGYAAWX1KhQAAAEAAQABAAEA8wACaXP0KAwAAAEAUwABACOBAqDgAAAUTWV5") \ No newline at end of file diff --git a/pr/619/docs/search.index/22d71b69fe53.js b/pr/619/docs/search.index/22d71b69fe53.js deleted file mode 100644 index bfa202a70..000000000 --- a/pr/619/docs/search.index/22d71b69fe53.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9OkTAAABAFYAAQAjgAKhEAAAFKZjchOAAqAgAAAJEWh5AQEBoGAAABSXc/LcEQAAAQAjgAKwIAl2AAFldQGAArAgECIAAaCQAAAUR2FlAQcBsEAUZgABZfUqFAAAAQABAAEAAQABAAD0KRMAAAEAWAEBAPMEAXM7MAAAAQAADQACAKQTBwCcFAUARwAABIaggAAAE4SxABSrAAGwQBLkAAGwgBS7AAGwUBMrAAEVABb0mA4AAAEAAQABAIMAhLBAFLEAAbAwExoAAbAwE7gAAcAAAzowAAABAAAAAAAJABAAAAC4BBEREhG0EbURwhHDEQcUCBR6FAEDAbBAFHwAAXTy2RMAAAEAI4QCoEAAABQJYnMTgAKwwBSvAAF1eQGAAqAAAAAJMbAgEQMAAWdwAQEA9NgRAAABAAEAAQDzgAJkbLfoAACMoNAAABOQoFAAABFwoJAAABOssFATCQABoDAAAAxvt5gHOzAAAAEAAGUAEwACAgEACAIBAGYEAwDHBQAAxgYBAGMHAQB2BwAADQkBABoJAAAkCQAAVgkAAIgMQgDhDAAA7g8BAMgQAQDlEAEAKxEBAKsRBAC9EgEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/23121bb3cfba.js b/pr/619/docs/search.index/23121bb3cfba.js new file mode 100644 index 000000000..b9bedf5a8 --- /dev/null +++ b/pr/619/docs/search.index/23121bb3cfba.js @@ -0,0 +1 @@ +rn_("AYACsFARBgABoLAAABP7Y3MBBADzxA8AAAEAAQABgAKgUAAAENWgYAAAEUVpcgGAAqAgAAAMeKBgAAARRGVoAQEA83QMAAABAAEAE4ECoBAAAAx3YWMBgAKwEBPGAAGwMA0aAAFlcyMAAqBAAAAUZGV38oYUAAABAAEDADswAAABAAAFAAIAcAwDAFgRAQABBgD0ERMAAAEAmAEBABMAArBgExMAAWZt8uUMAAABAAEBAPQREQAAAQCwAAEAI4ACoLAAABPiZGcBggKgoAAAE0SgQAAAEHRvdvOAA2ducgGAAqBAAAATCqAwAAAPwWhstz8AAIqwQA/CAAE0YFc7MAAAAQAAGgAEAAoCAABqBA4A9QsJANIMAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2341c468e163.js b/pr/619/docs/search.index/2341c468e163.js deleted file mode 100644 index 21aebe75c..000000000 --- a/pr/619/docs/search.index/2341c468e163.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9MwSAAABAKYAAQABCAD0iBMAAAEAiAABADMBA7BAE1cAAWFiZfX4DAAAAQBAA2sC0gABAAA7MAAAAQAABQACADEMAQC9DwMA84ACc3UjgQKwgBOCAAFydAEGAPSFEAAAAQC3AAEAUwCEsIATCQABoKAAABTIAgEU9XoFAAABAOYOVwABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2365407c51d1.js b/pr/619/docs/search.index/2365407c51d1.js new file mode 100644 index 000000000..8f857f17e --- /dev/null +++ b/pr/619/docs/search.index/2365407c51d1.js @@ -0,0 +1 @@ +rn_("AQAA9AUJAAABANQK7QAnAAAAyqEQAAAUeaBAAAARFbBgFGkAAaAQAAAMh7BQFAAAAbAwEXcAAaAAAAAMRbEgFIsAAbBAERMCIkBOsAk6MAAAAQAAAAAAFAAQAAAAGwkcCS8JMAkNDA4MDwwQDBYMGwzgDKESzRLOEs8ShxOIE50TnhMQFBEU") \ No newline at end of file diff --git a/pr/619/docs/search.index/24048c7d32ce.js b/pr/619/docs/search.index/24048c7d32ce.js deleted file mode 100644 index 60758bdef..000000000 --- a/pr/619/docs/search.index/24048c7d32ce.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsCARhAEjoJAAABQpbXABggKwoBQZAAGwoBQbAAFjcgECAaBAAAARg2UBOxAAADOAhLAgEQEAAbAgD7sAAVAUAPOAAm9y") \ No newline at end of file diff --git a/pr/619/docs/search.index/2457a8245b21.js b/pr/619/docs/search.index/2457a8245b21.js deleted file mode 100644 index 217425d7c..000000000 --- a/pr/619/docs/search.index/2457a8245b21.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCAUcQABoDAAABR7aXATAAOgIAAAEy2ggAAAE0BlaXX1FQwAADkAAQABAAEAAYYCsJAUmAABoAAAABK6YmQBAgD0HgwAAAEAjwMBAAEAAPQ9CQAAAQABAAEAAQAAOzAAAAEAAAYAAgCMEwAA9BMFACOBArBAFGwAAWVz84ADZXh5AQAA9DkJAAABAAEAAQAjgAKwIBMhAAFyeEcBAADGsMATuAABoBAAABFxsEAM6QABoDAAABD4AESAC/RwBQAAAQB+BwEA1wAAAIWgMAAAEGygMAAAE3cQARM6MAAAAQAAAAAACgAQAAAAAQkCCQMJMwk0CSMMhxCOEEgRSRH9Eg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/24eb37241fd9.js b/pr/619/docs/search.index/24eb37241fd9.js new file mode 100644 index 000000000..8d3b05ba3 --- /dev/null +++ b/pr/619/docs/search.index/24eb37241fd9.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgC2EQMAwBICAAEKAbBAFGUAAWX1KRQAAAEAAQABAAEA8wACaXP0KAwAAAEAUwABACOBAqDgAAAUTGV5") \ No newline at end of file diff --git a/pr/619/docs/search.index/253a1a2f3af2.js b/pr/619/docs/search.index/253a1a2f3af2.js new file mode 100644 index 000000000..2a99a902e --- /dev/null +++ b/pr/619/docs/search.index/253a1a2f3af2.js @@ -0,0 +1 @@ +rn_("AYACsHASmAABsCAUsAABaW8BAAGw8BSwAAFrOzAAAAEAAAgAAwAXFAAAHBQGAEcUAADzBQFk8toSAAABAAECAPPbEAAAAQABAPMAAWk6MAAAAQAAAAAABwAQAAAAthDvEtsT3BMMFA0ULhQvFCODArCwFIsAAWFzAYECoKAAABNEoEAAABB0b3bzgIQBUAE=") \ No newline at end of file diff --git a/pr/619/docs/search.index/258f74639e7e.js b/pr/619/docs/search.index/258f74639e7e.js new file mode 100644 index 000000000..9dd707912 --- /dev/null +++ b/pr/619/docs/search.index/258f74639e7e.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgCLEwAA8xMFACOIArBAFGsAAWVzAQQBsDATWwABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/BECAAETBAAoFAAA8wEDY2Vw884MAAABAAEAAQIA9h4JAABXAA4HAQC3AAEA84ACbnI=") \ No newline at end of file diff --git a/pr/619/docs/search.index/261bd9c5a7ae.js b/pr/619/docs/search.index/261bd9c5a7ae.js new file mode 100644 index 000000000..e41436f16 --- /dev/null +++ b/pr/619/docs/search.index/261bd9c5a7ae.js @@ -0,0 +1 @@ +rn_("AQkBoEAAABRkZfKGFAAAAQABgAKwAAzsAAGggAAAE8hkcAEDAaAAAAAQOnPyyA8AAAEAAQIDsGATRQABsNAUZwABoIAAABPnaXJzAXIUAAD3AACAhaEwAAAUhZBJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/26c726b9a1ff.js b/pr/619/docs/search.index/26c726b9a1ff.js deleted file mode 100644 index f65cfa377..000000000 --- a/pr/619/docs/search.index/26c726b9a1ff.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9AoRAAABAJMBAQABAAD08g8AAAEA9AAJASOCArBQE1MAAWVzAQIA9CUTAAABAJAAAQABAwD0WRMAAAEAmAABAPOFAmJ1AQIA9HURAAABAH0BAQDzgAJpbPMAA2J0dTowAAABAAAAAAAPABAAAAB0BwEIAggDCAQIGhDgEK0TMRR+FH8UgRSOFI8UthS6FAEMAPMTFAAAAQABAAGAArAACR8AAaAgAAANB2RuAQYA9CMTAAABAJAAAQDzAwFi9AgRAAABAJMBAQCXBgAAh7BAD/AAAaBwAAASqLCQE1EAATgJAzowAAABAAAAAAAkABAAAADDBcQFxQXGBTYHNwc3DPwM/Qz+DAINAw0EDegP6Q88ED0QQRBCEF8QYBBhEGIQYxBkEGUQqBCtENgQ2RCNE7ET2BN0FIAUohSzFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/26c9d07115ed.js b/pr/619/docs/search.index/26c9d07115ed.js new file mode 100644 index 000000000..e3744fd99 --- /dev/null +++ b/pr/619/docs/search.index/26c9d07115ed.js @@ -0,0 +1 @@ +rn_("AQIBoKAAABNsZPL2BgAAAQABgQKgMAAAFHKgUAAAE/tjcwEEA7AgEUwAAaBQAAAR+KBAAAAUOmxzdvI1FAAAAQDzAANhZW87MAAAAQAACAADAIkEAQAJDAAAFA0FAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/26da58cfcc22.js b/pr/619/docs/search.index/26da58cfcc22.js new file mode 100644 index 000000000..33aebdc5c --- /dev/null +++ b/pr/619/docs/search.index/26da58cfcc22.js @@ -0,0 +1 @@ +rn_("AQABsIAUOwABcPI3FAAAAQBDBQOgIAAAEWCgQAAAErVkZXPz+Q8AAEwDAQABAgA7MAAAAQAAEwABACQQEwATgYSgUAAAERCgEAAADCqgIAAADPQcQAAzgAOwUBOBAAFhZm4=") \ No newline at end of file diff --git a/pr/619/docs/search.index/26f7810019b9.js b/pr/619/docs/search.index/26f7810019b9.js new file mode 100644 index 000000000..91ad8abc7 --- /dev/null +++ b/pr/619/docs/search.index/26f7810019b9.js @@ -0,0 +1 @@ +rn_("AQABoEAAABCtdPf3DAAAQQPwAgEAuQCfAAEA8wABczswAAABAAAcAAgAsgQCAC0MAwDwDwEAtxABAPgQAQDoEQEAoxMHAJsUBQAjgAKxEBSiAAFhdA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/278e7db09dfe.js b/pr/619/docs/search.index/278e7db09dfe.js deleted file mode 100644 index 0b7a8e4e2..000000000 --- a/pr/619/docs/search.index/278e7db09dfe.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoEAAABGJc/U5DAAAJgVLAQEAAQATggKgIAAADRBlcgECAPTuDwAAAQD2AAEAI4ECoBAAAAw4ZWkTgAKg8AAAFChucjMAA7AwCSwAAWVvdAHeEQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/2792eabda019.js b/pr/619/docs/search.index/2792eabda019.js new file mode 100644 index 000000000..8104deff5 --- /dev/null +++ b/pr/619/docs/search.index/2792eabda019.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABQjZfKZFAAAAQABAQA7MAAAAQAABgABAMAUBgDzBgFl9G4UAAABADMAAQAzBQOwYBOEAIphcnXzexAAAHkCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/27986af38333.js b/pr/619/docs/search.index/27986af38333.js new file mode 100644 index 000000000..7ebf9d3f8 --- /dev/null +++ b/pr/619/docs/search.index/27986af38333.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAUAAgCDDAMAGRMBAAECAPN7EQAAAQABAAEGAPSmFAAAAQABAAEA8wYBbfSsEgAAAQABAAEA84ACbnbzgAJhaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/287bdd249076.js b/pr/619/docs/search.index/287bdd249076.js new file mode 100644 index 000000000..a4754a774 --- /dev/null +++ b/pr/619/docs/search.index/287bdd249076.js @@ -0,0 +1 @@ +rn_("AYACsHAUlwABoAAAAASkZmcBAQA7MAAAAQAABwABAEYMBwABAQGgcAAAEqBhARUHAAAjgAKhAAAAFKFkbnOAhKBgAAASnwBBSA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/293b0c0e4c00.js b/pr/619/docs/search.index/293b0c0e4c00.js deleted file mode 100644 index 08f165560..000000000 --- a/pr/619/docs/search.index/293b0c0e4c00.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYYCoAAAABNVoAAAABNWZHIBgAKgcAAAE+igMAAAERhmdAELAaBAAAAUOmXyaBQAAAEAI4ECsFAQ7wABY3YBAAGwgBQ8AAFw8jgUAAABAEMGA6AgAAARYKBAAAAStmRlc/P5DwAATQMBAPMABGlyc3Y7MAAAAQAADwAFAPgGBQDdEgUACRMBAIETAABzFAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/2a0fddb4ea90.js b/pr/619/docs/search.index/2a0fddb4ea90.js new file mode 100644 index 000000000..134583b55 --- /dev/null +++ b/pr/619/docs/search.index/2a0fddb4ea90.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAUAAQCPFAUA8w0BbTswAAABAAAFAAEATRQFAEcAAACFsAAUXgABsEASwwABoQAAABSVsAAThACKOAgCOzAAAAEAABwABwAADAMAMxEHAOcSAQBjEwQAQRQEAEgUAwC2FAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/2a60d7315b5a.js b/pr/619/docs/search.index/2a60d7315b5a.js deleted file mode 100644 index 3c9c82fae..000000000 --- a/pr/619/docs/search.index/2a60d7315b5a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CUTAAABAJAAAQABAwD0WRMAAAEAmAABAPMFAmJ1OjAAAAEAAAAAAAcAEAAAAIUQhhA9ET4R8RHyETATMRMBAgD0dREAAAEAfQEBAAEFAPN7EQAAAQABAAEEAPTMEgAAAQCmAAEA84CEEQkA") \ No newline at end of file diff --git a/pr/619/docs/search.index/2acf06bb018a.js b/pr/619/docs/search.index/2acf06bb018a.js new file mode 100644 index 000000000..bfd95c4ee --- /dev/null +++ b/pr/619/docs/search.index/2acf06bb018a.js @@ -0,0 +1 @@ +rn_("AQMA9IMMAAABAAEAAQABAAGwUBQ9AAFyAcEEAABTAYSwQBK+AAGwQBR7AAGYAAQ6MAAAAQAAAAAAKAAQAAAAiwSMBI0ElwUSCRMJOAlrCdcMzw8+ED8QTBB8ENsQ3BDdECcRnxL9Ev4S/xIAEywTOhM7E2gTaRPYE9kT3RPeE98T7xPwE1kUWhRwFHEUlxSYFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2adcb0ce9ddb.js b/pr/619/docs/search.index/2adcb0ce9ddb.js new file mode 100644 index 000000000..de85bbe4c --- /dev/null +++ b/pr/619/docs/search.index/2adcb0ce9ddb.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABNKc/TSDwAA8QMBAAQAAQECsGAUPQABsEAUewABZHQ7MAAAAQAADQAGAP0SAwBoEwEA2BMBAO8TAQBwFAEAlxQBAAEBA7BwEgAAAbCAEtoAAYATfQAQ+m1uczswAAABAAALAAIA9wgFAF0TBQCjgISwsBPGAAGxcBS6AAEIQIIBgAKwMBSuAAGxABQ9AAFjbmcBAACFThI1WTA7sDATMQFJEYEIOzAAAAEAAAYAAgCLEwAA8xMFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2af0babf5073.js b/pr/619/docs/search.index/2af0babf5073.js deleted file mode 100644 index 25dd6a67f..000000000 --- a/pr/619/docs/search.index/2af0babf5073.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9n4UAAABAA8AAQAnAAQAAQMA88ESAAABAAEAI4ECsSAUuwABY2sTgAKgMAAAFDpuclMAA6BAAAAMI2VvcvQoEQAAgQG/AQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/2b7fd9f87c9b.js b/pr/619/docs/search.index/2b7fd9f87c9b.js new file mode 100644 index 000000000..9f1879466 --- /dev/null +++ b/pr/619/docs/search.index/2b7fd9f87c9b.js @@ -0,0 +1 @@ +rn_("AQAA9HcTAAABAAEAAQABBADzxA8AAAEAAQABgAKgUAAAENWgYAAAEUVpcgGAAqAgAAAMeKBgAAARRGVoAQEA83QMAAABAAEAE4ECoBAAAAx3YWMBAwA7MAAAAQAABQACAHAMAwBYEQEAAQYA9BETAAABAJgBAQATAAKwYBMTAAFmbfLlDAAAAQAjgAKgwAAAE+JucqcPAACIoEAAAA/BsEAPwgABNCAXOzAAAAEAABkAAwAKAgAAagQOAPULCQABgAOwcBOWAAGwMBNAAAGwgBPPAAFjcnMBAAGwIBOWAAFvOjAAAAEAAAAAAAkAEAAAAN4R3xH6EvsS6BPpEz8UQBS6FLsUAYACsCAJJwABsDATSwABcnT3BAAAyKAgAAAHdqBgAAAP7bCAE0sAAUAGkgn2FgIAAHgC5AQBAIkKAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2b9a15e4da70.js b/pr/619/docs/search.index/2b9a15e4da70.js new file mode 100644 index 000000000..1bc9ee500 --- /dev/null +++ b/pr/619/docs/search.index/2b9a15e4da70.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAABEABQCsBQAANgwAAOsMAAAKEA0AcBEAAAGEArDQFK4AAaCQAAATq2JoAYQCsAARfgABsAARgAABNDaXBAAAh6AgAAAR3aAwAAARRKAwAAASqLBwD+IAActACDswAAABAAARARQAuAEAAKMFAAD+CAAABAkAACEJAgARDAAAUgwBAHkMAQDuDAAAHA3tAM4PAADfDwEA1RAAAJIRAADwEgEA0RMFAO4TAAB3FAAAjxQFAKwUAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2bc73e9cd7d3.js b/pr/619/docs/search.index/2bc73e9cd7d3.js deleted file mode 100644 index 68c930094..000000000 --- a/pr/619/docs/search.index/2bc73e9cd7d3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA834UAAABADsAAQ0BoKAAABTId/K4FAAAAQABgQKwgBSOAAGgYAAAFLZkczcBAIWFoEAAABRhsGAUMQBQApAK") \ No newline at end of file diff --git a/pr/619/docs/search.index/2c07d4061000.js b/pr/619/docs/search.index/2c07d4061000.js deleted file mode 100644 index c0fbdbae2..000000000 --- a/pr/619/docs/search.index/2c07d4061000.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDLEQIAfBMBABMUAgABBwD2oBMAAAEArABYABgAAQABBADzzhEAAAEAAQAjAAKgYAAAEv1hcvPvEAAAAQDKAQGAAqEQAAAUorCAFJgAAWl1dwgAAIixUBS/AAGgAAAAEM6wcBPcAAGhMAAAFLMKQRvyYQkAAEQHAYECoFAAABEUoKAAABNOa3ABAwA7MAAAAQAACQECAOcMAQCfDgcB84ACbHTzgAJhZQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2c3aac18c124.js b/pr/619/docs/search.index/2c3aac18c124.js deleted file mode 100644 index 632d68dfb..000000000 --- a/pr/619/docs/search.index/2c3aac18c124.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9K4QAAABAAEAAQABAAA6MAAAAQAAAAAACgAQAAAA5g/nD9YQ1xBjEfUR9hESExMTqxSsFPMBAXnyCxQAAAEAAQADoKAAABRZoCAAABOQsDAR6wABZWl08vcSAAABAAEDADswAAABAAAGAAEAZBEGAAEIAPT6EwAAAQCLAAUAEwEDsJAUYwABsFATPwFnZ2xwOzAAAAEAABIACQBpEAIA7hEBAC4TAQBPEwEAhhMBAOsTAQAlFAEANBQBAHUUAQABgAKwMBHnAAGwMBHpAAFydgECAbAAErcAAWQ7MAAAAQAABQACAOMRAwDmEgEAI4ECoJAAABRYaW8BBwD0dBQAAAwAIgARAHcWAAGJsFAUCwABsFASuQEUsGATPQABtQkDOjAAAAEAAAAAAA4AEAAAAOIM4wzkDJ0Ong7PENAQDBEvEY4RjxGQEZERNRNuE0OAA6AgAAAM1KAQAAAM4W1ubwEDAPRmEAAAAQABABoBAYACoLAAABQnsDATcQABbnRDAAOgIAAAERuwUBHzAAFlaGk7MAAAAQAABgADABMMAAAEEgMA0BMBAPOAAmRyhwsAAAqAAfcAEAGAAfoAEAGgUAAAEYugUAAAFF6gMAAAEJmgMAAAEKQwMWNlaW9zdHV39ZwHAAABAC0I1wJbAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2c44f0df5c90.js b/pr/619/docs/search.index/2c44f0df5c90.js new file mode 100644 index 000000000..8a5659762 --- /dev/null +++ b/pr/619/docs/search.index/2c44f0df5c90.js @@ -0,0 +1 @@ +rn_("AQIAOjAAAAEAAAAAAAgAEAAAAB4MHwyuD68P6g/aEAARjROOEwEAAPQ9CQAAAQABAAEAAQUBsDATGQABaPMGFAAAAQByABODAqAwAAAQzWNwAQMA9OgPAAABAO8AAQABgQKgAAAAEYmgEAAAD8tldfOAAmFyAQAA9L4RAAABAAEAAQABgAKgkAAAE/CwUBKkAAFid/OAAmR0E4ACsJATMgABbnLzAAJldPTEEAAAAQABAAEAAQEA9X4MAAABAAEAAQABABOAArCwE+wAAWFvIwACsEANAAABZXQ7MAAAAQAACQAEAL0EAQCCBQEAYAwBALARAwABAgA7MAAAAQAACQACAOkHBwATEwEAAYACsJATewABoKAAABPvZXYTgAKxgBTCAAFjbQGCArBAFBoAAaBQAAAR7GJmE4ACoEAAABRGZHMjgAKg0AAAFJZjbvOAhBEBQAEFAbBAE1YAAWUBoxIAAEOCA6EAAAAUpKDQAAAUd2ttcxOAArBgEOMAAWFyAQUAOzAAAAEAAI0AAgD3EAAACBKMAAGCA7AgExUAAbAgEH0AAbBAEXkAAWtsc1OAA7AgFHsAAWt0dQGJhKCAAAAUtaBAAAAUYKBgAAAUgKCQAAAUuQKAChOChKCgAAAT7rGgFMUAAbDQFFkAAQQBCQEBAPS6EQAAAQABAAEAQ4ADsXAUwAABoNAAABQvY29zI4ACsGAQ4QABaW8BAAD0KAwAAAEAUwABACOBAqDgAAAUTGV5AQ0AOjAAAAEAAAAAAAcAEAAAAE4TTxPqE+sTJBQlFHQUdRQBgQKwQBNuAAGgwAAAFC5lbwECADowAAABAAAAAAAIABAAAADfD+APkhHwEvES7hN3FKwUrRTzAQFvOzAAAAEAAAkABABiCQEAnxADAOEQAQDsEwEA84ADbW5yAQAAOzAAAAEAAAYAAgCLEwAA8xMFAEOAA7BAFGsAAaAgAAAM/2VycyMAArAwE88AAWNy8rkTAAABAAGBArCAExsAAaEAAAAUdmNmAQsA9HcTAAABAAEAAQABgAKgAAAAEJWgAAAAEJY0NvMCAXYBBg0AAPMAAmRsAR0JAADX/jkAkrCgFBgAAbBwEd4AAbCAEvoAAaCwAAATNJ3dfzswAAABAAAXAAsAqwEBALkEAwB/BQIA/wYBAAkHAgA5DAAA+A8AAF8RAADOEQIAqRICAF0UAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2c5286276032.js b/pr/619/docs/search.index/2c5286276032.js new file mode 100644 index 000000000..c810b9c01 --- /dev/null +++ b/pr/619/docs/search.index/2c5286276032.js @@ -0,0 +1 @@ +rn_("AYACsCATQgBaoFAAABEybXNDgAOw4BQEAAFu/WjCOi5kZ3IBAwDz1xIAAAEAAQAjgAKwMBQKAAFjaTOAA7AADQcDZWFpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2cd6064912c5.js b/pr/619/docs/search.index/2cd6064912c5.js new file mode 100644 index 000000000..ff902de0c --- /dev/null +++ b/pr/619/docs/search.index/2cd6064912c5.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAEMAAgAkCQAAiAxCAAEFAPTEEAAAAQABAAEAE4ACsLAToQABYWwBBAD0tg8AAAEAAQABAHMABKAQAAAQeGJwcnY7MAAAAQAACgACAGQRBgC6EQMAAYACsIAREwIisOAUCgABaXIBAwGwQBFhAAFlAZcOAAABBQA7MAAAAQAABgABAF8QBgABAwA7MAAAAQAABQABANoMBQDzAAJwczowAAABAAAAAAAMABAAAACoBcUGGAldDGoMBhEHEbYStxINEw4TDxMQE1cAAACFsFAQtgI5sFAP1ADPoEAAABGMSIADOzAAAAEAAA8ABgCgBAAAaAUDAMEPAADiEQMAsRIDAOUSAQDTAISgYAAADO4QCAbzrwEAAAEAHQs=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2d92946fc8de.js b/pr/619/docs/search.index/2d92946fc8de.js new file mode 100644 index 000000000..475bf9c3a --- /dev/null +++ b/pr/619/docs/search.index/2d92946fc8de.js @@ -0,0 +1 @@ +rn_("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") \ No newline at end of file diff --git a/pr/619/docs/search.index/2e19ea627523.js b/pr/619/docs/search.index/2e19ea627523.js deleted file mode 100644 index 7edd940fc..000000000 --- a/pr/619/docs/search.index/2e19ea627523.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9AMUAAABAFAAAQDzBAFj8gcTAAABAAEFAPPYEgAAAQABAPOCAmZ0AQABsAAUXwABZPQADAAAAQABAAEA84ACZWkTgAKw4BRqAAF0dg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2e309b1ddfc0.js b/pr/619/docs/search.index/2e309b1ddfc0.js new file mode 100644 index 000000000..1a2992484 --- /dev/null +++ b/pr/619/docs/search.index/2e309b1ddfc0.js @@ -0,0 +1 @@ +rn_("AQEAOjAAAAEAAAAAAAgAEAAAAA8JdxAiESMRJBH5E/oThRSKFAECAPSyEAAAAQABAAEAE4ACoNAAABRyY3NTgAOgcAAAFG1laW+DgISwIBOdAAGgIAAAD+uwAAdUAAEKCAQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2e6ec339b5c9.js b/pr/619/docs/search.index/2e6ec339b5c9.js new file mode 100644 index 000000000..8e99913cd --- /dev/null +++ b/pr/619/docs/search.index/2e6ec339b5c9.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAAkABABiCQEAnxADAOEQAQDsEwEAAQIBsEAUewABdDswAAABAAANAAYA/RIDAGgTAQDYEwEA7xMBAHAUAQCXFAEAE4ACsDATMQFJaXABiAKwABPjAAGwABPlAAE0NhOBAqAwAAARhWRzAYACoCAAAAx7sGAUFQABbngBBQDzrRMAAAEAAQATgAKgMAAAFAhlefMAhBIAA/JAEAAA5gDzgAJydA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2ecb7d9903c8.js b/pr/619/docs/search.index/2ecb7d9903c8.js new file mode 100644 index 000000000..010120f39 --- /dev/null +++ b/pr/619/docs/search.index/2ecb7d9903c8.js @@ -0,0 +1 @@ +rn_("AQIA9CQTAAABAJAAAQABAgD0/hAAAAEAmgABAAEDAPRYEwAAAQCYAAEAAQIBoEAAABNDcjswAAABAAAHAAIA/BABAJMRBQDzAIQDQAg6MAAAAQAAAAAAFQAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfAR8REiEyMTLxMwEz8TahNrE7MTtBM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2f0bf8f46f74.js b/pr/619/docs/search.index/2f0bf8f46f74.js new file mode 100644 index 000000000..6ed236d5a --- /dev/null +++ b/pr/619/docs/search.index/2f0bf8f46f74.js @@ -0,0 +1 @@ +rn_("AYkCsCAUcAABoDAAABR6aXATAAOgIAAAEyyggAAAEz9laXX1FQwAADkAAQABAAEAAYYCsJAUlwABoAAAABK5YmQBAgD0HgwAAAEAjwMBAAEAAPQ9CQAAAQABAAEAAQAAOzAAAAEAAAYAAgCLEwAA8xMFACOBArBAFGsAAWVz84ADZXh5AQAA9DkJAAABAAEAAQAjgAKwIBMgAAFyeEcBAADGsMATtwABoBAAABFxsEAM6QABoDAAABD4AESAC/RwBQAAAQB+BwEA1wAAAIWgMAAAEGygMAAAE3YQARM6MAAAAQAAAAAACgAQAAAAAQkCCQMJMwk0CSMMhxCOEEgRSRH8Eg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2f3fbe34ef8f.js b/pr/619/docs/search.index/2f3fbe34ef8f.js new file mode 100644 index 000000000..16609d4be --- /dev/null +++ b/pr/619/docs/search.index/2f3fbe34ef8f.js @@ -0,0 +1 @@ +rn_("AQwBoKAAABTHd/K3FAAAAQABAQDz+g8AAAEAAQABiYSggAAAFLWgQAAAFGCgYAAAFICgkAAAFLkCgAoTgYSgoAAAE+6xoBTFAAGw0BRZAAEEAQnzgANhdHU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/2f967e9cee72.js b/pr/619/docs/search.index/2f967e9cee72.js deleted file mode 100644 index 1ed338f8e..000000000 --- a/pr/619/docs/search.index/2f967e9cee72.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBoQAAABSAZPJiBwAADQIBBgGgMAAAEfB0Aa0TAAABAwGwUBL5AAFl9RkJAABSAwEADQQBAAEBADswAAABAAAFAAEAsQUFAAEBAaEAAAAUdGTysAUAAEYClwcAAIewoBL3AAGg4AAAFEcegArzYAQAAAEAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/300566ec33f3.js b/pr/619/docs/search.index/300566ec33f3.js new file mode 100644 index 000000000..282f2eafb --- /dev/null +++ b/pr/619/docs/search.index/300566ec33f3.js @@ -0,0 +1 @@ +rn_("AYICsEAUYgABsGATNgABZXIBBQD0nxAAAAEAAQABAPOAAmZtAQYAOjAAAAEAAAAAAAgAEAAAAN8P4A+SEfAS8RLuE3cUrBStFAEAArCwFAYAAaFAAAAUpWVn9H0HAAABAAEAAQDDAISgsAAAE9ewQBC3AAEUIAT38wYAAN4FfgMBADoBLgEUAWOAA7AwEBsAAWFlaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/301e73fffc4a.js b/pr/619/docs/search.index/301e73fffc4a.js new file mode 100644 index 000000000..24c889899 --- /dev/null +++ b/pr/619/docs/search.index/301e73fffc4a.js @@ -0,0 +1 @@ +rn_("AQIA9LARAAABAAEAAQABAQDzzhEAAAEAAQATgAIW9JHxRuVlcwEKAPS/EwAAAQABAAEAAYACsCAUPQABoGAAABOMb3YBgAKwMBLFAAGgAAAAE0RjZPOAhQUQBg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/30471f8f48c9.js b/pr/619/docs/search.index/30471f8f48c9.js new file mode 100644 index 000000000..1658f8e11 --- /dev/null +++ b/pr/619/docs/search.index/30471f8f48c9.js @@ -0,0 +1 @@ +rn_("AQIA9asRAAABAAEAAQABAAGAArBgExUAAaAgAAARAG95AQABoMAAABQ6afRsEwAACAAcABsAAQYA9KYUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATQ3I7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0IAWrCgE7kAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCsEgMA84ICZWkjAAKggAAAFLZmaPIACQAAlQoBBQDzHRMAAAEAAQABAQA7MAAAAQAABQACAAQMAwD2EQEAUwADsDAUVQABZXBy9OQPAAABAO4AAQABAAOwQBQaAAGhQAAAFIqgUAAAEexiY2YBDAcAAPOAAm1uAQGEoLAAABPXsEAQtwABsMAUBgABoGAAABGSFCAE9vMGAABcCQEAOgEuARQBAQUAOzAAAAEAAAUAAQDcEgUAAQcA9WMTAAABAAEAAQABACOAAqBQAAARY2Fv8wCFIEkCOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/30996967e28a.js b/pr/619/docs/search.index/30996967e28a.js new file mode 100644 index 000000000..cfe18fc5f --- /dev/null +++ b/pr/619/docs/search.index/30996967e28a.js @@ -0,0 +1 @@ +rn_("AQQA884RAAABAAEAAYICsEASxwABsEASyQABNDYBCwDzxRMAAGwAAQABBgD0sxQAAAEACgABAPMCAXIBDxQAAPMCAWU7MAAAAQAABQACAH8QAwAwEQEAE4ACoFAAABL8ZHTzAIQRAQH37xAAAAEAbgAdAAEAAQA8AQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/30af5de71430.js b/pr/619/docs/search.index/30af5de71430.js new file mode 100644 index 000000000..46094e54d --- /dev/null +++ b/pr/619/docs/search.index/30af5de71430.js @@ -0,0 +1 @@ +rn_("AQAA9EMJAAABAAIIAQABCQGggAAAFLZmAZUTAAABAgD12xAAAAEAAQBdAgEA8wACaXU6MAAAAQAAAAAABwAQAAAAthDvEtsT3BMMFA0ULhQvFAEIAPVBFAAAAQABAAEAAQDzAgFm9ZoQAAABAAEAAQABABOAArCgFIsAAXJ08wACYXPzyhAAAAEAAQDzgAJ0dg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/30ca63111c0a.js b/pr/619/docs/search.index/30ca63111c0a.js deleted file mode 100644 index bbae7df53..000000000 --- a/pr/619/docs/search.index/30ca63111c0a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOzAAAAEAAAcAAQBZCQcAAQIA90wQAADbALcCAQABAHoAAQATgAKwMBDoAKVpdPMAAXPyjBQAAAEAM4ADsRAT/QABZG5w") \ No newline at end of file diff --git a/pr/619/docs/search.index/3116216cb50c.js b/pr/619/docs/search.index/3116216cb50c.js deleted file mode 100644 index 057e89787..000000000 --- a/pr/619/docs/search.index/3116216cb50c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9HQUAAAMACIAEQABAgGwQBK/AAFlAc8PAAABgAKgkAAAFDagkAAAFDcyM5cCAADGoCAAAAx4oGAAABFEsGANDAABAWQAAzswAAABAAAKAAMAGwcFAEQMAAB4EwMA") \ No newline at end of file diff --git a/pr/619/docs/search.index/31359e89bbb9.js b/pr/619/docs/search.index/31359e89bbb9.js deleted file mode 100644 index 0a1d062b4..000000000 --- a/pr/619/docs/search.index/31359e89bbb9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9BYJAAABAFADAQABAwDzZAwAAAEAAQDzgAJpbwEBAbBQEQ0AAWP0XwcAAAEAAQALAiOBAqBQAAAQzmNuAQQAOzAAAAEAAAcAAwDLEQIAfBMBABMUAgABAQA6MAAAAQAAAAAABwAQAAAA7hHvES4TLxOGE4cTNBQ1FPMJAWkBDBEAANcCAACHsMATcQABoFAAAA+6oRAAABReFAEXOzAAAAEAACIAAQC5ASIA") \ No newline at end of file diff --git a/pr/619/docs/search.index/31aec0400f56.js b/pr/619/docs/search.index/31aec0400f56.js deleted file mode 100644 index 3496fe770..000000000 --- a/pr/619/docs/search.index/31aec0400f56.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9AoRAAABAJMBAQAjgQKgYAAAE0BiaQEAAPTyDwAAAQD0AAkBI4ECsFATUwABZXMTgAKAB1MfMAFhcgGJArAgFHEAAaAwAAAUe2lwAQIA9CUTAAABAJAAAQABAwD0WRMAAAEAmAABAPOFAmJ1AQIA9HURAAABAH0BAQDzgAJpbLcBAACFoCAAABMtEgEMOjAAAAEAAAAAABYAEAAAAHQHAQgCCAMIBAgVDE4MTwxQDFEMGhDgEHETchOtEzEUfhR/FIEUjhSPFLYUuhQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/31dcc78b2786.js b/pr/619/docs/search.index/31dcc78b2786.js deleted file mode 100644 index c64b961f3..000000000 --- a/pr/619/docs/search.index/31dcc78b2786.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsRAUmgABsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAIcHAACHsKATxAABsNAUXAABoFAAABQnjBQROzAAAAEAAAYAAwBYBwAA6RADALsSAQDzgAJsdBOAA6AgAAAM0bCgFEAAAWFkbg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/31e4b5cbd2f8.js b/pr/619/docs/search.index/31e4b5cbd2f8.js new file mode 100644 index 000000000..27f5d91d0 --- /dev/null +++ b/pr/619/docs/search.index/31e4b5cbd2f8.js @@ -0,0 +1 @@ +rn_("AQkA830UAAABADsAAQ0BoKAAABTHd/K3FAAAAQABgQKwgBSNAAGgYAAAFLVkczcBAIaFoEAAABRgsGAUMABQApAK") \ No newline at end of file diff --git a/pr/619/docs/search.index/3201f7aa10ec.js b/pr/619/docs/search.index/3201f7aa10ec.js deleted file mode 100644 index 1d34b462d..000000000 --- a/pr/619/docs/search.index/3201f7aa10ec.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9GkHAAB4COEAAQABBQD0SRQAAAEAAQABAAEFAPQ5EwAAAQCUAAEA8wICY3X1VhAAAAEAxgABAAEA84ACbnM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/320512d77248.js b/pr/619/docs/search.index/320512d77248.js deleted file mode 100644 index 4c8998f60..000000000 --- a/pr/619/docs/search.index/320512d77248.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9qAFAAABACsNAQCmAAEAAQAAOzAAAAEAAAcAAwAQAgEAbQwBAB0QAwABgwKwcBOXAAGwgBPQAAFjcwEFAPRJFAAAAQABAAEAAQUA9DkTAAABAJQAAQDzCAJjdfVWEAAAAQDGAAEAAQABAgD0vhEAAAEAAQABABMAAqAwAAARiWV09MQQAAABAAEAAQABAwD0uhEAAAEAAQABAAGAAqAAAAAQlaAAAAAQljQ28wMBdgEGDQAAlwEAAIawoBMcAAGwIAwoAAGwgBL7AAEJDAY6MAAAAQAAAAAACQAQAAAACQcKBwsHOQz4D18RqhKrEqwSXhQBAgD0JRMAAAEAkAABAAEDAPRZEwAAAQCYAAEA8wACYnU6MAAAAQAAAAAAFQAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfER8hEjEyQTMBMxE0ATaxNsE7QTtRMBAQD0nAUAAAEAWAcBALcAAICFsQAUQAABsAAHVgABDAhEAQgAOzAAAAEAAAUAAQDdEgUA1w0AAIiwQBEtAAGgIAAADRC5AAs7MAAAAQAADwAFAH0AAQABBwcAZQcBAHUQAQApEQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/3235335929a9.js b/pr/619/docs/search.index/3235335929a9.js deleted file mode 100644 index 4a2396551..000000000 --- a/pr/619/docs/search.index/3235335929a9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgBoIAAABS3ZgGWEwAAE4ACoOAAABR5YnABAwGwABQxAFBz9ugPAAABAMQAKwABAP8CAYACsEASvQABoBAAABEYcHIBgQOgAAAAEYmwAA/TASegEAAAD8tlc3XzgANhb3IBAgD12xAAAAEAAQBeAgEAAQQAOzAAAAEAAAkAAQBOEQkAAQAA9L4RAAABAAEAAQABgAKgkAAAE/GwUBKlAAFid/OAAmR0o4CEsFAUDQABsJATMwABQCADVwMAAIagcAAAE+igQAAAFF4wQQw6MAAAAQAAAAAAQAAQAAAAwgTDBIgFiQWKBYsFjAWNBY4FjwWQBZEFgQcsCS0JMgkxDDIMVAxVDFYM6QzqDPcMnA69D74Pvw/AD9MP8g/zDzgQthDEEMUQxhDHEOcQ6BD6ECARIRGNEeIR6xHsEfAR8BIpEyoT3BPdE+MTDRQOFC8UMBRHFIIUgxS0FLUUvxTAFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/327cc382d02d.js b/pr/619/docs/search.index/327cc382d02d.js new file mode 100644 index 000000000..aee7903cd --- /dev/null +++ b/pr/619/docs/search.index/327cc382d02d.js @@ -0,0 +1 @@ +rn_("AQEA9qAFAAABACoNAQCmAAEAAQAAOzAAAAEAAAcAAwAQAgEAbQwBAB0QAwABgwKwcBOWAAGwgBPPAAFjcwEFAPRIFAAAAQABAAEAAQUA9DgTAAABAJQAAQDzCAJjdfVWEAAAAQDGAAEAAQABAgD0vhEAAAEAAQABABMAAqAwAAARiWV09MQQAAABAAEAAQABAwD0uhEAAAEAAQABAAGAAqAAAAAQlaAAAAAQljQ28wMBdgEGDQAAlwEAAIawoBMbAAGwIAwoAAGwgBL6AAEJDAY6MAAAAQAAAAAACQAQAAAACQcKBwsHOQz4D18RqRKqEqsSXRQBAgD0JBMAAAEAkAABAAEDAPRYEwAAAQCYAAEA8wACYnU6MAAAAQAAAAAAFQAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfAR8REiEyMTLxMwEz8TahNrE7MTtBMBAQD0nAUAAAEAWAcBALcAAICFsQAUPwABsAAHVgABDAhEAQgAOzAAAAEAAAUAAQDcEgUA1w0AAIiwQBEtAAGgIAAADRC5AAs7MAAAAQAADwAFAH0AAQABBwcAZQcBAHUQAQApEQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/3470e377b8a5.js b/pr/619/docs/search.index/3470e377b8a5.js deleted file mode 100644 index 60b3690d7..000000000 --- a/pr/619/docs/search.index/3470e377b8a5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQsBoEAAABQ6ZfJoFAAAAQABBQD0BBIAAAEAAQABAAGDArAAEO8AAbBQE3wAAWR3E4ACoKAAABPwZXYBAgD0ChEAAAEAkwEBAAEAAPTyDwAAAQD0AAkBI4ICsFATUwABZXMBAgD0JRMAAAEAkAABAAEDAPRZEwAAAQCYAAEA84UCYnUBAgD0dREAAAEAfQEBAPOAAmls8wADYnR1OjAAAAEAAAAAAA8AEAAAAHQHAQgCCAMIBAgaEOAQrRMxFH4UfxSBFI4UjxS2FLoUAQwA8xMUAAABAAEAAYACsAAJHwABoCAAAA0HZG4BBgD0IxMAAAEAkAABAPMDAWL0CBEAAAEAkwEBAJcGAACHsEAP8AABoHAAABKosJATUQABOAkDOjAAAAEAAAAAACQAEAAAAMMFxAXFBcYFNgc3BzcM/Az9DP4MAg0DDQQN6A/pDzwQPRBBEEIQXxBgEGEQYhBjEGQQZRCoEK0Q2BDZEI0TsRPYE3QUgBSiFLMUAQMA9DcTAAABAFEBAQDzgAJjbXcBAIDFsYAUwwABQIEECA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/348eb4db4131.js b/pr/619/docs/search.index/348eb4db4131.js deleted file mode 100644 index b1857d42e..000000000 --- a/pr/619/docs/search.index/348eb4db4131.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQAUvQABsNAUrQABa20BCgDz/xMAAAEAdwATgAKiEAAAFMhsbzMChKBgAAASlqEAAAAUeQSAAzswAAABAAA2AAIAUQcAAKQHNQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/34e21c1eff8a.js b/pr/619/docs/search.index/34e21c1eff8a.js new file mode 100644 index 000000000..7e771d889 --- /dev/null +++ b/pr/619/docs/search.index/34e21c1eff8a.js @@ -0,0 +1 @@ +rn_("AYQCsAARfgABsAARgAABNDbzAAFh8nkMAAABACOAArCQEYQBImx0AYACsHATlgABsIATzwABY3MBAAA6MAAAAQAAAAAACQAQAAAA3hHfEfoS+xLoE+kTPxRAFLoUuxTzgAJkZScBAICFoNAAABQPsBAEvwABoDAAABB4AggL") \ No newline at end of file diff --git a/pr/619/docs/search.index/3580a7a1ae5a.js b/pr/619/docs/search.index/3580a7a1ae5a.js new file mode 100644 index 000000000..23c174bd6 --- /dev/null +++ b/pr/619/docs/search.index/3580a7a1ae5a.js @@ -0,0 +1 @@ +rn_("AQ8A9CQUAAABAE8AAQABBAD0gxAAAAEAtwABAAECADowAAABAAAAAAAJABAAAADeEd8R+hL7EugT6RM/FEAUuhS7FPMAAW/yeAkAAAEAU4ADsQAUiAABaG9ww4CEoBAAABNasIATnQABBQAG") \ No newline at end of file diff --git a/pr/619/docs/search.index/35f4ee3323ca.js b/pr/619/docs/search.index/35f4ee3323ca.js deleted file mode 100644 index ae80710b9..000000000 --- a/pr/619/docs/search.index/35f4ee3323ca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAkBAgDnDAEAnw4HAQEBAaAAAAATS3P1xAQAAA4L8gMBAAQAAQECoGAAABPMoOAAABQpZXQ7MAAAAQAACAABAMsECAABgAOwIBKXAAGwsBLRAAGwsBLTAAFiY3PzgARjbHR2") \ No newline at end of file diff --git a/pr/619/docs/search.index/36168b037bdf.js b/pr/619/docs/search.index/36168b037bdf.js deleted file mode 100644 index 6694eed5f..000000000 --- a/pr/619/docs/search.index/36168b037bdf.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsAAT5AABsAAT5gABNDYBBgD0tBQAAAEACgABAPMCAnJ28/YPAAABABkE8wIBZTswAAABAAAFAAIAfxADADARAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/364e0899e234.js b/pr/619/docs/search.index/364e0899e234.js new file mode 100644 index 000000000..483d09dc4 --- /dev/null +++ b/pr/619/docs/search.index/364e0899e234.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAI0AAgB1BwAAegmMAAGEArBwFDcAAaBAAAARGGlzAQcA8/EQAAABABUBI4ACoLAAABLWYXQBAAOwMAknAAGwMBOWAAGgIAAAB3ZhZG8BFgIAADcDAICGoMAAABQvsAAUAAABAJgV") \ No newline at end of file diff --git a/pr/619/docs/search.index/364efa71ab66.js b/pr/619/docs/search.index/364efa71ab66.js deleted file mode 100644 index d14c0d3a3..000000000 --- a/pr/619/docs/search.index/364efa71ab66.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQwBoKAAABTId/K4FAAAAQABAQDz+g8AAAEAAQABiYSggAAAFLagQAAAFGGgYAAAFIGgkAAAFLoCgAoTgYSgoAAAE++xoBTGAAGw0BRaAAEEAQnzgANhdHU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/367dd0ec2281.js b/pr/619/docs/search.index/367dd0ec2281.js deleted file mode 100644 index 084f815d9..000000000 --- a/pr/619/docs/search.index/367dd0ec2281.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHARdwABsCAUXAABYWQBBQD0SBMAAAEAmAABAPMAAWMBsRIAAEOAA7AwE54AAbCgFD4AAWFzeQEGAPQWEQAAAQC/AAEAk4CEoAAAABFesSAUowABCSAB84ACZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/36a6df1413de.js b/pr/619/docs/search.index/36a6df1413de.js deleted file mode 100644 index b35fca876..000000000 --- a/pr/619/docs/search.index/36a6df1413de.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9T8RAAABAAEAAQABACOBArCQFAUAAWF0Q4ADsRAUhwABsIATxwABY290EwACsAAUXAABbnL2DAIAAAEAegIBALACWAw=") \ No newline at end of file diff --git a/pr/619/docs/search.index/36ab74947c62.js b/pr/619/docs/search.index/36ab74947c62.js new file mode 100644 index 000000000..0487f1a01 --- /dev/null +++ b/pr/619/docs/search.index/36ab74947c62.js @@ -0,0 +1 @@ +rn_("AQEAOzAAAAEAAAYAAQBkEQYAAQAA9yUJAAABAFcHAQBzAAEAFQEBggKgIAAAESegMAAAEY1pdPOAA2FncwEBAaBAAAAUOWXyZxQAAAEAI4ACsFAT7AABZnPzgAJpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/36e93ebda724.js b/pr/619/docs/search.index/36e93ebda724.js new file mode 100644 index 000000000..032950f18 --- /dev/null +++ b/pr/619/docs/search.index/36e93ebda724.js @@ -0,0 +1 @@ +rn_("AYACsAARfgABsAARgAABNDYBBAGgoAAAFMd38rcUAAABAAELADswAAABAAAGAAEAHBQGACOAAqCAAAAUR2VvYwIDoGAAABPaZW5wAScMAADzAAJhdgHiBgAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/375a6b7ea5ac.js b/pr/619/docs/search.index/375a6b7ea5ac.js new file mode 100644 index 000000000..dcd082edb --- /dev/null +++ b/pr/619/docs/search.index/375a6b7ea5ac.js @@ -0,0 +1 @@ +rn_("AQAA9CgTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCjEwcAmxQFAEcAAAWGoIAAABODsQAUqgABsEAS4wABsIAUugABsFATKgABFQAW9JgOAAABAAEAAQBDAISgIAAACTGg0AAAE4+gMAAACREVAATzAgIAAAEAcwU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/37820096d35f.js b/pr/619/docs/search.index/37820096d35f.js deleted file mode 100644 index e676f9892..000000000 --- a/pr/619/docs/search.index/37820096d35f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9HgTAAABAAEAAQDzBgFz8v0TAAABAAEBAbBQEvkAAWX3GQkAAFIDAQANBAEA3AMBAAEDAPS+EQAAAQABAAEAAQMA9LoRAAABAAEAAQDzgwJsc/OAAmN0U4ADoBAAAAzNYW9y") \ No newline at end of file diff --git a/pr/619/docs/search.index/37a8671a9e5c.js b/pr/619/docs/search.index/37a8671a9e5c.js new file mode 100644 index 000000000..95b395453 --- /dev/null +++ b/pr/619/docs/search.index/37a8671a9e5c.js @@ -0,0 +1 @@ +rn_("AQEAOjAAAAEAAAAAAAcAEAAAAE4TTxPqE+sTJBQlFHQUdRTzBgFpAW0TAABDgAOwABSuAAGwUBNCAFpkZm4BAAGwQBMbAAFlOzAAAAEAAA0AAgDVBgwAEBEAACOAAqAwAAAMFmFlNwAAgMWwUBOWAAGwEBQ9AAGwYBOdAAEAApgI") \ No newline at end of file diff --git a/pr/619/docs/search.index/37d677adaca5.js b/pr/619/docs/search.index/37d677adaca5.js new file mode 100644 index 000000000..f45fa3c20 --- /dev/null +++ b/pr/619/docs/search.index/37d677adaca5.js @@ -0,0 +1 @@ +rn_("AYYCoAAAABNUoAAAABNVZHIBgAKgcAAAE+egMAAAERhmdAELAaBAAAAUOWXyZxQAAAEAI4ECsFAQ7wABY3YBAAGwgBQ7AAFw8jcUAAABAEMGA6AgAAARYKBAAAAStWRlc/P5DwAATAMBAPMABGlyc3Y7MAAAAQAADwAFAPgGBQDcEgUACBMBAIATAAByFAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/37dd659620c0.js b/pr/619/docs/search.index/37dd659620c0.js new file mode 100644 index 000000000..46e8767d1 --- /dev/null +++ b/pr/619/docs/search.index/37dd659620c0.js @@ -0,0 +1 @@ +rn_("AQ0A9d0TAAABAAEAegABAAEHAPPFEwAAbAABACOAAqEQAAAUF25yAQcA9LYRAAABAAEAAQAzAASgIAAACS6w4BQMAAExZWlyOjAAAAEAAAAAAAkAEAAAAF4EXwRQBxAJcAxxDHIMcwxYEVkRAQIA9AoRAAABAJIBAQABAwD0dREAAAEAfAEBAPMAAmJ1ARoQAAABAwD0CBEAAAEAkgEBAPOEAmRzAQIA8xIJAAABAFgA84ACaXQBGADzxBQAAAEAAQAjgQKwwBPbAAFjbQENAbBAFGUAAWX1KRQAAAEAAQABAAEAE4ICsAARIAABa3MBBAD0rhAAAAEAAQABAAGBAqAgAAARG7BAE3AAAWVp84ICZXQBBAGwYBLFAAFy9CUMAAABAPIDAQDzgANhZW8BCQD28BIAAAEA/QCJADUAAQATgAKwYBDIAAFkbgEGADswAAABAAAFAAIA8xADAIkTAQABAwGgcAAAEyxn9F0HAAABAAsCAQABCQDzfRQAAAEAOwABgQKwgBSNAAGgYAAAFLVkcxcBAIiFsNAUtwABoEAAABRgsGAUMABQApAKAQQA9MkTAAABAEsAAQBTgAOwkBSwAAFlaG8BAAGgQAAAEYJlAcoPAAAjgQKwUBEtAAFrdHfsAwCOoZAAABSlsLATOgABoKAAABLvsVAUrgAB/cEPOzAAAAEAACEACACCAAAAiAADAHIFAQA5BwcAOQkHAEYMBwBTEAEAmhIAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/37e014765119.js b/pr/619/docs/search.index/37e014765119.js deleted file mode 100644 index 8b25c4711..000000000 --- a/pr/619/docs/search.index/37e014765119.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9ecRAAABACQBAQBhAQEBAPciEQAAAQABANYCAQCLAAUAAQIA9LIQAAABAAEAAQATgAKg0AAAFHNjc/OAAmVvI4ACsAAHVAABbHTzAAJhcvKwDwAAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/37fb467cac9a.js b/pr/619/docs/search.index/37fb467cac9a.js deleted file mode 100644 index 9311bd060..000000000 --- a/pr/619/docs/search.index/37fb467cac9a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CUTAAABAJAAAQABAgD0/hAAAAEAmgABAAEDAPRZEwAAAQCYAAEAAQIBoEAAABNEcjswAAABAAAHAAIA/BABAJMRBQDzAIQDQAg6MAAAAQAAAAAAFQAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfER8hEjEyQTMBMxE0ATaxNsE7QTtRM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/381627e07c4a.js b/pr/619/docs/search.index/381627e07c4a.js deleted file mode 100644 index 03dceafb9..000000000 --- a/pr/619/docs/search.index/381627e07c4a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9AQSAAABAAEAAQAjAAKgcAAAEgNhcgF8BwAAAQAA9iARAAABAJMDAQAKAAEAAQAAOzAAAAEAAAYAAgCMEwAA9BMFACOIArBAFGwAAWVzAQ0BsEAUZgABZfUqFAAAAQABAAEAAQABBQA7MAAAAQAACAADAP0RAgACEwQAKRQAANcDAACGVzFF2FXTFIQG9b8EAAABAA4IAQABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/384db2e965f3.js b/pr/619/docs/search.index/384db2e965f3.js new file mode 100644 index 000000000..65ea4bc31 --- /dev/null +++ b/pr/619/docs/search.index/384db2e965f3.js @@ -0,0 +1 @@ +rn_("AQMA9BYJAAABAFADAQABAwDzZAwAAAEAAQDzgAJpbwEBAbBQEQ0AAWP0XwcAAAEAAQALAiOBAqBQAAAQzmNuAQQAOzAAAAEAAAcAAwDLEQIAexMBABIUAgABAQA6MAAAAQAAAAAABwAQAAAA7RHuES0TLhOFE4YTMxQ0FPMJAWkBDBEAANcCAACHsMATcAABoFAAAA+6oRAAABRdFAEXOzAAAAEAACIAAQC5ASIA") \ No newline at end of file diff --git a/pr/619/docs/search.index/386d9b10bedf.js b/pr/619/docs/search.index/386d9b10bedf.js deleted file mode 100644 index 73b5949f6..000000000 --- a/pr/619/docs/search.index/386d9b10bedf.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsRAUmgABsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAIcHAACHsKATxAABsNAUXAABoFAAABQnjBQROzAAAAEAAAYAAwBYBwAA6RADALsSAQDzgQJsdPMAAWk7MAAAAQAAjgADAJoEAAD3EAAACRKMAAEFAPN+FAAAAQA7AAEAAaBAAAAQ+2XzCwkAAAEAnAkTgAKgMAAAD95kcvMAAWXz8AYAAAEAAQDzgAJodAEBADswAAABAACNAAIA9xAAAAkSjAATgAKgUAAAECFpdAEIAPT6EwAAAQCLAAUAEwCEsPAUgAAzsJAUYwABsFATPwFnQIkAOzAAAAEAABIACQBpEAIA7hEBAC4TAQBPEwEAhhMBAOsTAQAlFAEANBQBAHUUAQDXAQAAhrCAEbQAAaBAAAAJLggwJjowAAABAAAAAAANABAAAACSAJMAYgdvCQgMEw0KEQsRnhKfEiUTJhO2E7cT") \ No newline at end of file diff --git a/pr/619/docs/search.index/3888f1592d5b.js b/pr/619/docs/search.index/3888f1592d5b.js new file mode 100644 index 000000000..322eff13f --- /dev/null +++ b/pr/619/docs/search.index/3888f1592d5b.js @@ -0,0 +1 @@ +rn_("AQYAOzAAAAEAAAUAAQBdEwUAg4YEsFATJgABsHATjQABoNAAABRtYm5vdhOAArAQEvgAAXByAQABoDAAABHvdAGsEwAA8wIBc/KoEAAACAMTgAKgYAAAEJlldQECAPYODQAAAQA7AwEALgEBAAGAArAAEuMAAYAOnDTgAWVzAQEA81kHAAAoDAEAY4ADsIAUAAABYm5084ADYW9yARQAOzAAAAEAAAUAAQCbFAUAAQAAOzAAAAEAAAYAAgCLEwAA8xMFACOIArBAFGsAAWVzAQQBsDATWwABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/BECAAETBAAoFAAA8wIDY2Vw884MAAABAAEAY4ADoGAAAA/0ZW91AQABsGAUDAABZQFGFAAA8wIBc/YpCQAAAQABABoIPwAiAQEIAPPAEgAAAQABAEOAA6AQAAATj6DgAAAUF2RvcwECAaBQAAARhXIBJhEAAAGAAqBAAAAQpaBwAAAUWGFlAQAAOzAAAAEAAAsAAgD4BgUA3BIFAPOAAnR2IwACsBAH9AABbnL2HgkAAFcADgcBALcAAQDzAIcwkQw6MAAAAQAAAAAACAAQAAAAxwTIBAMRBBH2EvcSfRN+E3gU") \ No newline at end of file diff --git a/pr/619/docs/search.index/38a288884c49.js b/pr/619/docs/search.index/38a288884c49.js new file mode 100644 index 000000000..d45d502c8 --- /dev/null +++ b/pr/619/docs/search.index/38a288884c49.js @@ -0,0 +1 @@ +rn_("AYACoGAAABQJoKAAABP7YWkBCwD0mBMAAAEAAQABAAEEAPSpEAAAAQABAAEAI4ACsEARBgABbHLzAANjZHMB+xAAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5d7054075c79.js b/pr/619/docs/search.index/38ac6f2b5ca2.js similarity index 52% rename from pr/619/docs/search.index/5d7054075c79.js rename to pr/619/docs/search.index/38ac6f2b5ca2.js index b6aca044b..8ebf4ae79 100644 --- a/pr/619/docs/search.index/5d7054075c79.js +++ b/pr/619/docs/search.index/38ac6f2b5ca2.js @@ -1 +1 @@ -rn_("AQMBsAAM9wNBc/QtDAAAAQABAAEAAQIA9CsMAAABADUFAQAjAAKgQAAADPNlcvK2BAAAAQABgAKgQAAAE9uwMBL5AAFhcwECAaBAAAAUZWXyhxQAAAEA84AEbG5ydg==") \ No newline at end of file +rn_("AQMBsAAM9wNBc/QtDAAAAQABAAEAAQIA9CsMAAABADUFAQAjAAKgQAAADPNlcvK2BAAAAQABgAKgQAAAE9qwMBL4AAFhcwECAaBAAAAUZGXyhhQAAAEA84AEbG5ydg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/39c7b725e6d9.js b/pr/619/docs/search.index/39c7b725e6d9.js deleted file mode 100644 index 7737c6e8b..000000000 --- a/pr/619/docs/search.index/39c7b725e6d9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQAOjAAAAEAAAAAAAcAEAAAANwP3Q+mEKcQIxMkE7QTtRMBAAD0BQkAAAEA1QrtACcAAACIoRAAABR6oEAAABEVsGAUagABoBAAAAyHsFAUAQABsDARdwABsSAUjAABOcECOjAAAAEAAAAAABEAEAAAABsJHAkvCTAJDQwODA8MEAwWDBsM4AyiEogTiROeE58TERQSFDOAA6CAAAAUCmVveQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3b4ebba34e4d.js b/pr/619/docs/search.index/3b4ebba34e4d.js new file mode 100644 index 000000000..d525eb086 --- /dev/null +++ b/pr/619/docs/search.index/3b4ebba34e4d.js @@ -0,0 +1 @@ +rn_("AQMBoEAAABQ5ZfJnFAAAAQABAAD0DRMAAAEAAQABAPMEAWT0sRIAAAEAAQABAKcAAAKFsKAUVQABsEATCwABsHAT/AABFYgAAScUAAABAAGwgBQ7AAFw8jcUAAABAEMAA6AgAAARYKBAAAAStWRlc/P5DwAATAMBAPOAAmVp") \ No newline at end of file diff --git a/pr/619/docs/search.index/3b59728b3fd9.js b/pr/619/docs/search.index/3b59728b3fd9.js new file mode 100644 index 000000000..7f1ed0ada --- /dev/null +++ b/pr/619/docs/search.index/3b59728b3fd9.js @@ -0,0 +1 @@ +rn_("AYACsHAR3gABsCAP6gDwaHkBBQD0Cg0AAAEAPQMBAAEAAPRkDAAAAQABAG4AAQIAOjAAAAEAAAAAAAkAEAAAAN8P4A/VEJIR8BLxEu4TdxSsFK0UAQMA8yEJAAABAAEA1wMAAIagQAAAEfkYQAc6MAAAAQAAAAAAFwAQAAAAagdrB/kHLgliCWMJCQ3MD80P7Q+YEJ8QoBChEKIQ4RDiEBkRGhGVEuwT7RMYFBkU") \ No newline at end of file diff --git a/pr/619/docs/search.index/3b9071c6bff0.js b/pr/619/docs/search.index/3b9071c6bff0.js new file mode 100644 index 000000000..3355cc7de --- /dev/null +++ b/pr/619/docs/search.index/3b9071c6bff0.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAYAAQBfEAYAAQMAOzAAAAEAAAUAAQDaDAUAYwADoJAAABN0aHBzOjAAAAEAAAAAAA4AEAAAAKgFxQYYCV0MagwGEQcRthK3Eg0TDhMPExATPBM9Ew==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3b9c1d6496c7.js b/pr/619/docs/search.index/3b9c1d6496c7.js new file mode 100644 index 000000000..1ef343e77 --- /dev/null +++ b/pr/619/docs/search.index/3b9c1d6496c7.js @@ -0,0 +1 @@ +rn_("AQQBsEAUZQABZfUpFAAAAQABAAEAAQABAgA7MAAAAQAACwACANETBQCPFAUA8wEBbTswAAABAAANAAQA0wwAAG0RAADpEgUATRQFAPMBAWXyABIAAAEAM4CEsBAQjAABoCAAAAwcFEAE") \ No newline at end of file diff --git a/pr/619/docs/search.index/3bef9f9517c5.js b/pr/619/docs/search.index/3bef9f9517c5.js new file mode 100644 index 000000000..281913498 --- /dev/null +++ b/pr/619/docs/search.index/3bef9f9517c5.js @@ -0,0 +1 @@ +rn_("AQkBoIAAABS2ZgGVEwAAAQIA9dsQAAABAAEAXQIBAPMAAml1OjAAAAEAAAAAAAcAEAAAALYQ7xLbE9wTDBQNFC4ULxQBCAD1QRQAAAEAAQABAAEA8wIBZvWaEAAAAQABAAEAAQATgAKwoBSLAAFydPMCAmFz88oQAAABAAEAAQQBsEAUZQABZfUpFAAAAQABAAEAAQABAgA7MAAAAQAACwACANETBQCPFAUA8wMBbTswAAABAAANAAQA0wwAAG0RAADpEgUATRQFAPOBAmNl84ACYWU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3c0adaab5c9d.js b/pr/619/docs/search.index/3c0adaab5c9d.js deleted file mode 100644 index 48ce3e86d..000000000 --- a/pr/619/docs/search.index/3c0adaab5c9d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9CkTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCkEwcAnBQFAEcAAAGGoIAAABOEsQAUqwABsEAS5AABsIAUuwABsFATKwABFQAW9JgOAAABAAEAAQABBQDz/w8AAAEAAQBjgISwQBCMAAGgAAAABuIA8AA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3c3e3a203317.js b/pr/619/docs/search.index/3c3e3a203317.js new file mode 100644 index 000000000..6fd319ce4 --- /dev/null +++ b/pr/619/docs/search.index/3c3e3a203317.js @@ -0,0 +1 @@ +rn_("AQABsPAUsAABazswAAABAAAIAAMAFxQAABwUBgBHFAAAEwACsQAUmQABZG7y2hIAAAEAE4ACsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAAGAAqBAAAARELDAFFsAAWVzAQEAOzAAAAEAABMAAQAkEBMAI4ACsJATwwABaW03NgAAiqAQAAAMKqBQAAAUJrBwFAQAAaAgAAAM9JxVETswAAABAAAGAAMAWAcAAOkQAwC6EgEA84ACbHQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3c458307b0c9.js b/pr/619/docs/search.index/3c458307b0c9.js new file mode 100644 index 000000000..a463ee00e --- /dev/null +++ b/pr/619/docs/search.index/3c458307b0c9.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAABYACQBZEAUAaxEBAPwRAgDQEgEAARMEAP4TAQAoFAAAVxQAAHYUAAAjgAOh8AAAFMew8BS6AAFjZmcjgAKwUBO5AAFtbgEFAPP+EwAAAQB3APMEAWMBixEAAAEBAbBwFFsAAXA7MAAAAQAACQACANsHBwDREAEAAQIAOzAAAAEAAAsAAgDREwUAjxQFAPMBAW07MAAAAQAADQAEANMMAABtEQAA6RIFAE0UBQATAAKgMAAADNdlc/IAEgAAAQABggKwcBQ3AAGgQAAAERhpc/cBAICGsJAUGAABkEkI") \ No newline at end of file diff --git a/pr/619/docs/search.index/3c9ab60377f1.js b/pr/619/docs/search.index/3c9ab60377f1.js deleted file mode 100644 index 0b8d3ece3..000000000 --- a/pr/619/docs/search.index/3c9ab60377f1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQBTAISgIAAACWGwYBOFAIoBAQnzexAAAHoCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3c9e08c1699f.js b/pr/619/docs/search.index/3c9e08c1699f.js deleted file mode 100644 index ab3b03f84..000000000 --- a/pr/619/docs/search.index/3c9e08c1699f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9HgTAAABAAEAAQABBADzxA8AAAEAAQABgAKgUAAAENWgYAAAEUVpcgGAAqAgAAAMeKBgAAARRGVoAQEA83QMAAABAAEAE4ECoBAAAAx3YWMBAwA7MAAAAQAABQACAHAMAwBYEQEAAQYA9BITAAABAJgBAQATAAKwYBMUAAFmbfLlDAAAAQAjgAKgwAAAE+NucqcPAACIoEAAAA/BsEAPwgABNCAXOzAAAAEAABkAAwAKAgAAagQOAPULCQABgAOwcBOXAAGwMBNBAAGwgBPQAAFjcnMBAAGwIBOXAAFvOjAAAAEAAAAAAAkAEAAAAN8R4BH7EvwS6RPqE0AUQRS7FLwUAYACsCAJJwABsDATTAABcnT3BAAAyKAgAAAHdqBgAAAP7bCAE0wAAUAGkgn2FgIAAHgC5AQBAIoKAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3ca1ec2ec8ab.js b/pr/619/docs/search.index/3ca1ec2ec8ab.js new file mode 100644 index 000000000..6330dddca --- /dev/null +++ b/pr/619/docs/search.index/3ca1ec2ec8ab.js @@ -0,0 +1 @@ +rn_("AQEBoEAAABRkZfKGFAAAAQABgAOgMAAAEqGw4BQ/AAGwkBSIAAFhY22HAQCAhrAQES0AAbAQEUwAAaCgAAAUcqDwAAAUlTFJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3cca7897888d.js b/pr/619/docs/search.index/3cca7897888d.js deleted file mode 100644 index 5e624f18f..000000000 --- a/pr/619/docs/search.index/3cca7897888d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9CkTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCkEwcAnBQFAEcAAASGoIAAABOEsQAUqwABsEAS5AABsIAUuwABsFATKwABFQAW9JgOAAABAAEAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3cce4c537167.js b/pr/619/docs/search.index/3cce4c537167.js new file mode 100644 index 000000000..b96bc24d9 --- /dev/null +++ b/pr/619/docs/search.index/3cce4c537167.js @@ -0,0 +1 @@ +rn_("AQACoCAAABHdoDAAABKoYmgBzg8AAAETAbAAFIEAAXM7MAAAAQAABQABAJsUBQABBwDzqRIAAAEAAQDzgANkcnQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3cda01bca1f3.js b/pr/619/docs/search.index/3cda01bca1f3.js new file mode 100644 index 000000000..5fdbb656f --- /dev/null +++ b/pr/619/docs/search.index/3cda01bca1f3.js @@ -0,0 +1 @@ +rn_("AQsA9HMUAAAMACIAEQABCgA6MAAAAQAAAAAABwAQAAAAThNPE+oT6xMkFCUUdBR1FPOBAm90EwCEsCATQgBasDARSgABoFAAABEyEDACOzAAAAEAAAgABACFAAEArwADAFoHAQB0CQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/3d39c2a0de50.js b/pr/619/docs/search.index/3d39c2a0de50.js new file mode 100644 index 000000000..2db28c94b --- /dev/null +++ b/pr/619/docs/search.index/3d39c2a0de50.js @@ -0,0 +1 @@ +rn_("AYMCoFAAABEUoKAAABNNa3ABAAGwQBKYAAFs9HAJAAABAHIHAQABCAD0rBIAAAEAAQABAAEEAbAAEO0AAXMBVRAAAAECAaBQAAATCmMB0gwAALcAAACFsEANEQABoDAAAAwUlQABOzAAAAEAAAgABADGBAAAmAUCANUMAQDEDwIAJwEAgIWwMAkvAAGgEAAAE4OwIAd6AAGRAEQBEAGwABSBAAFzOzAAAAEAAAUAAQCbFAUAAQMA9HAJAAABAHIHAQBjgAOgAAAADBRucnUBAAKw0BPJAAGgMAAAD8diavZ8BQAAAQABAEsAAQB3AQEAAbCAE+gAAXQ7MAAAAQAARQAEAMcFAAAaCQAAJAkAAIgMQgABCQDzzRIAAAEAAQDzgANjZ3QBgwKgkAAAFDWgkAAAFDYyMwGAAqBQAAAUYaCAAAATgGNl8wACc3TyQgcAAAEAAQABoLAAABPLYvNVEwAALgEBACOAAqAAAAATVGRyI4ACoFAAABQnY2XzgAJpeQEEAPU/EQAAAQABAAEAAQDzAQFuATgHAAABAQA7MAAAAQAACQACAOkHBwATEwEAAQYA9LsTAAABAAEAAQABDwD0phQAAAEAAQABAPOBAmhtAQABsEAUZQABZfUpFAAAAQABAAEAAQBTgAOgIAAAEeFsbnTXbQCAy6AgAAAUlrBgENEAAbBAD/0AAcAbOAo=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3dbbea9c55d9.js b/pr/619/docs/search.index/3dbbea9c55d9.js deleted file mode 100644 index 69674f3d3..000000000 --- a/pr/619/docs/search.index/3dbbea9c55d9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAUAAQCQFAUA8w0BbTswAAABAAAFAAEAThQFAEcAAACFsAAUXwABsEASxAABoQAAABSWsAAThQCKOAgCOzAAAAEAABwABwAADAMAMxEHAOgSAQBkEwQAQhQEAEkUAwC3FAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/3dfa50f90aec.js b/pr/619/docs/search.index/3dfa50f90aec.js new file mode 100644 index 000000000..d36611792 --- /dev/null +++ b/pr/619/docs/search.index/3dfa50f90aec.js @@ -0,0 +1 @@ +rn_("AQAA9CgTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCjEwcAmxQFAEcAAAGGoIAAABODsQAUqgABsEAS4wABsIAUugABsFATKgABFQAW9JgOAAABAAEAAQABBQDz/w8AAAEAAQBjgISwQBCMAAGgAAAABuIA8AA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3e0f6f7169fa.js b/pr/619/docs/search.index/3e0f6f7169fa.js deleted file mode 100644 index 53f568a8f..000000000 --- a/pr/619/docs/search.index/3e0f6f7169fa.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICoFAAABLjoQAAABSXY3QjAAKwQA/VAAFldTswAAABAAA3ABYAyAYBANgMAQD6DAEA2g8BAFkQBQCPEAUADREBAGsRAQD9EQIA0RIDAAITBAAzEwEAORMBAEgTAQDOEwEA4RMBAP8TAQADFAEAKRQAAFQUAQBYFAEAdxQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3e7117b77bc1.js b/pr/619/docs/search.index/3e7117b77bc1.js new file mode 100644 index 000000000..a29fd7434 --- /dev/null +++ b/pr/619/docs/search.index/3e7117b77bc1.js @@ -0,0 +1 @@ +rn_("AQcAOzAAAAEAAI0AAgD3EAAACBKMAAEDADswAAABAACMAAEACg6MAAECADswAAABAAAHAAEARgwHAPMAA2JpdDswAAABAACNAAIAnwQAANsEjAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/3e9a4fcd7329.js b/pr/619/docs/search.index/3e9a4fcd7329.js deleted file mode 100644 index c78a9769e..000000000 --- a/pr/619/docs/search.index/3e9a4fcd7329.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBgBN+ABD6czswAAABAAAFAAEAXhMFACOCAqCQAAAUYmlzAQEA9CUTAAABAJAAAQAjgAKwoBQLAAFjbgGEArCgFBkAAbCgFBsAAWNyAQIAOzAAAAEAAAYAAQBfEAYAE4ICoCAAABP8ZXUBAgDzzhEAAAEAAQABgAKwIBQ+AAGgYAAAE41vdmOBA6AQAAATRWFjcwEDADswAAABAAAFAAEA2gwFAAEBAPMhCQAAAQABAAEBAPT+EAAAAQCaAAEAU4ADoMAAABRubnB1AYACsDAQGwABoWAAABSmYWUBgQKwQBLIAAGwQBLKAAE0NgEFAaBQAAAUJ2jyuxIAAAEAAQUA9HUQAAABALMAAQBzgISwMBNxAAEBoAQBCADzbRMAAAgAHAATgAKwQBHzAAFhZQEKAPPGEwAAbAABAAEAAaAgAAAQl3IBYBEAAAEAAPTKEwAAAQBLAAEApwEAgIWgMAAAEPugEAAAERsJICEBCQGgQAAAFGVl8ocUAAABAEOAhKAgAAAUc6CQAAATyaEwAAAUhhBJAAECAPRZEwAAAQCYAAEAE4ACsEATJwABaXkBAQKgMAAAEv2gQAAAE0RncjswAAABAAAHAAIA/BABAJMRBQABgAKwABPkAAGwABPmAAE0NgEGAPS0FAAAAQAKAAEA8wICcnYBEBQAAPMCAWU7MAAAAQAABQACAH8QAwAwEQEA84ACZHTnrT8AEqAwAAARHKBAAAAM8bDwFLEAAbBwE44AATBhYmNlZ2hpa2xub3Byc3R1djswAAABAAAaAUYAwQQAAKgFAACvBQAAsQUFAMUGAAAmBwAATAcCAFwHAABuBwUAdQcAANoHAAD/BwEABQkBAAsJAQAYCQAAdgkBAHoJjAAEDAMAEwwAABcMAwAkDAAAXQwAAGoMAACyDwEA3A8BAPQPAABYEAAAhRABAJkQAACmEAEA7xABAPMQAwAGEQEAPREBAF4RAAB7EQIAqhEAAMoRAADtEQAA8REBAPcRAQADEgQAqBIAALcSAQC6EgAAxhIBANgSAgAOEwMAIxMBADATAQA3EwEAPRMBAEATAABDEwAAVRMAAGsTAQCKEwEAmRMEALQTAQDHEwEAyhMBANATAQDbEwAAFhQCAB0UBwA8FAEASBQAAF8UAQCJFAEAyBQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3ea4023c697d.js b/pr/619/docs/search.index/3ea4023c697d.js deleted file mode 100644 index 7fa247300..000000000 --- a/pr/619/docs/search.index/3ea4023c697d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAABYACQBZEAUAaxEBAP0RAgDREgEAAhMEAP8TAQApFAAAWBQAAHcUAAAjgAOh8AAAFMiw8BS7AAFjZmcjgAKwUBO6AAFtbgEFAPP/EwAAAQB3APMEAWMBixEAAAEBAbBwFFwAAXA7MAAAAQAACQACANsHBwDREAEAAQIAOzAAAAEAAAsAAgDSEwUAkBQFAPMBAW07MAAAAQAADQAEANMMAABtEQAA6hIFAE4UBQATAAKgMAAADNdlc/IBEgAAAQABggKwcBQ4AAGgQAAAERhpc/cBAICGsJAUGQABkEkI") \ No newline at end of file diff --git a/pr/619/docs/search.index/3f4f2cfa5535.js b/pr/619/docs/search.index/3f4f2cfa5535.js new file mode 100644 index 000000000..a825429b6 --- /dev/null +++ b/pr/619/docs/search.index/3f4f2cfa5535.js @@ -0,0 +1 @@ +rn_("AQEA9GkHAAB4COEAAQABBQD0SBQAAAEAAQABAAEFAPQ4EwAAAQCUAAEA8wICY3X1VhAAAAEAxgABAAEAYwAEoDAAAAw6oHAAABHhZW5zdvN0EAAAnwAiAg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3f7ffddc1a36.js b/pr/619/docs/search.index/3f7ffddc1a36.js new file mode 100644 index 000000000..f0729f2fb --- /dev/null +++ b/pr/619/docs/search.index/3f7ffddc1a36.js @@ -0,0 +1 @@ +rn_("AYACsIATCAABsKATgQABaXQBgAKw4BSDAAGwQBBTAAFscgEGAPTpEAAAAQABAAEARwUAAIeg0AAAFF2wUBBRAAGgAAAAE4Ow8BQ3AAEFkQPy9Q8AAK8A") \ No newline at end of file diff --git a/pr/619/docs/search.index/3fc46817fb62.js b/pr/619/docs/search.index/3fc46817fb62.js deleted file mode 100644 index 0dd675df3..000000000 --- a/pr/619/docs/search.index/3fc46817fb62.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCoCAAABEnoDAAABGNaXQBAQA7MAAAAQAAjQACAHUHAAB6CYwA8wACZWz1tQQAAMQCywlTAgEAAQIAOzAAAAEAAO4AAgARDAAAHA3tAMcAAACFsLATQQABsBATxwABsDANGgABFDACOzAAAAEAABoBCwDfAQYAogUAAM8F7QBEBwcAQxACAJwRDQDLEQIApRIBACsTAQB8EwEAExQCAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/3fee3aae2f7c.js b/pr/619/docs/search.index/3fee3aae2f7c.js new file mode 100644 index 000000000..cc374774c --- /dev/null +++ b/pr/619/docs/search.index/3fee3aae2f7c.js @@ -0,0 +1 @@ +rn_("AQIA9LARAAABAAEAAQABCgD0vxMAAAEAAQABAPOBAm10AQYA83IRAAABAAEAAYICsGATRQABsNAUZwABaXITgAKwEAzsAAFlaQEFAPQCFAAAAQBQAAEA8wQBY/IGEwAAAQABBQDz1xIAAAEAAQDzggJmdAEAAbAAFF4AAWT0AAwAAAEAAQABAPOBAmVpNwYAAImxMBSGAAGgYAAAEXGgUAAAEQWwkBMXAAGwQBEBAAG1EAcBOhQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/407ac64d24ca.js b/pr/619/docs/search.index/407ac64d24ca.js deleted file mode 100644 index 4ef20bd15..000000000 --- a/pr/619/docs/search.index/407ac64d24ca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoLAAABPMYvNWEwAALgEBAAGAAqAgAAAP06AwAAAT2GFy8wABdAGBBwAAAQQBoEAAABRlZfKHFAAAAQABBQA7MAAAAQAACwAFAFkQBQDREgEA/xMBAFgUAAB3FAAA4wGEoDAAAA/RhQACOzAAAAEAAAsABQClBQIAwAYEAFsMAQCLEQAA4xIAAGOAA7AAD/QDYWRucg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/409350de5974.js b/pr/619/docs/search.index/409350de5974.js new file mode 100644 index 000000000..2c0ba27ae --- /dev/null +++ b/pr/619/docs/search.index/409350de5974.js @@ -0,0 +1 @@ +rn_("AQQA9g4NAAABADsDAQAuAQEAAQoA89QSAAABAKoAAQEA9yUJAAABAFcHAQBzAAEAFQEjgAKwYBPsAAFpbwECAPTLDAAAAQBJBgEAAQUA9AIUAAABAFAAAQD3CAAAiLCQE7kAAaAgAAAMzbCQEfoAAQTcAzowAAABAAAAAAAIABAAAACUBRYJFwlnDGgMARECEQYTBxM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/409dcc2e7d00.js b/pr/619/docs/search.index/409dcc2e7d00.js deleted file mode 100644 index cce817021..000000000 --- a/pr/619/docs/search.index/409dcc2e7d00.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsIAUPAABcPI4FAAAAQBDBQOgIAAAEWCgQAAAErZkZXPz+Q8AAE0DAQABAgA7MAAAAQAAEwABACQQEwATgYSgUAAAERCgEAAADCqgIAAADPQcQAAzgAOwUBOCAAFhZm4=") \ No newline at end of file diff --git a/pr/619/docs/search.index/40b97f872728.js b/pr/619/docs/search.index/40b97f872728.js deleted file mode 100644 index 4e8f64d30..000000000 --- a/pr/619/docs/search.index/40b97f872728.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBgBN+ABD6czswAAABAAAFAAEAXhMFACOCAqCQAAAUYmlzBwEAhMWwUBMnAAGgoAAAE8mwcBOOAAGg0AAAFG6AARgI") \ No newline at end of file diff --git a/pr/619/docs/search.index/417b64643f1d.js b/pr/619/docs/search.index/417b64643f1d.js deleted file mode 100644 index 82063710f..000000000 --- a/pr/619/docs/search.index/417b64643f1d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBsEAUZgABZfUqFAAAAQABAAEAAQABAgA7MAAAAQAACwACANITBQCQFAUA8wEBbTswAAABAAANAAQA0wwAAG0RAADqEgUAThQFAPMBAWXyARIAAAEAM4CEsBAQjAABoCAAAAwcFEAE") \ No newline at end of file diff --git a/pr/619/docs/search.index/417d23b5a9d5.js b/pr/619/docs/search.index/417d23b5a9d5.js new file mode 100644 index 000000000..0d531cb16 --- /dev/null +++ b/pr/619/docs/search.index/417d23b5a9d5.js @@ -0,0 +1 @@ +rn_("AQYA9I4RAAABAAEAAQABAgA7MAAAAQAACgAEAI8QBQDSEgEAMhMBAFgUAADzgAJmbgEBADswAAABAAAIAAIApw8GAFsTAQDzgAJkbgEBAPMwBwAAAQABAAGGAqAAAAATVKAAAAATVWRy8wEBdgGAEwAAQwADsIAS5wABsLAUiAABa2xyOzAAAAEAAAwAAwAnBwgACg0BAEgQAQABAgD1+gcAAAEAAQABAAEA8wCEFEEAAYEAAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4188d8b1473d.js b/pr/619/docs/search.index/4188d8b1473d.js new file mode 100644 index 000000000..268339ba8 --- /dev/null +++ b/pr/619/docs/search.index/4188d8b1473d.js @@ -0,0 +1 @@ +rn_("AQIBoQAAABR/ZPJiBwAADQIBBgGgMAAAEe90AawTAAABAwGwUBL4AAFl9RkJAABSAwEADQQBAAEBADswAAABAAAFAAEAsQUFAAEBAaEAAAAUc2TysAUAAEYClwcAAIewoBL2AAGg4AAAFEYegArzYAQAAAEAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/41ad038f4378.js b/pr/619/docs/search.index/41ad038f4378.js new file mode 100644 index 000000000..193adb5a1 --- /dev/null +++ b/pr/619/docs/search.index/41ad038f4378.js @@ -0,0 +1 @@ +rn_("AQUA9MsSAAABAKYAAQABCAD0hxMAAAEAiAABADMAA7BAE1YAAWFiZTowAAABAAAAAAAMABAAAAAzBzQHNQf4DPkMyw85EIgQiRCKEIsQoxJ1Ew==") \ No newline at end of file diff --git a/pr/619/docs/search.index/41ca5c735a3c.js b/pr/619/docs/search.index/41ca5c735a3c.js deleted file mode 100644 index 3b8607bc3..000000000 --- a/pr/619/docs/search.index/41ca5c735a3c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUBsEASxAABZTswAAABAAAFAAIA6BIBAEkUAwABggKgkAAAFDagkAAAFDcyMwEAA6AgAAASoKAgAAAI/rCAFK8AAWltcDswAAABAAAOAAYAnAQAANQEBQBuCQAAtg8DAAkUAAAbFAEA8wABcwEyEQAAAQUA9JITAAABAAEAAQABAAD1fgwAAAEAAQABAAEA84ACZ2tzgISwsBPtAAERSAABBQGgQAAAEfpl8wkNAAAQBAEAE4ACoDAAAAw3ZXIBgAOwUBQvAAGgEAAAC/+gcAAAE4FnbnJHAQAAhaBgAAAUCqBQAAAUYqCgAAAT/BUBBDswAAABAAARAAQAAAIBALkQCAC2EQMAwRICAAGFArBwFBYAAbAwE2kAAWVzEwADsEAP2AABoGAAABGMYmVzOzAAAAEAABIABACpBQEAygYKAFEQAQCpEAMAAQMA9G0QAAABAAQAAQABCgGgQAAAFGVl8ocUAAABABOAArBgErsAAWNp84ACZHLzAAJlbzswAAABAAAJAAIAngcFAOMHAwABAgGwMBFYAAFuOzAAAAEAAAkAAQD1CwkAAQAA9K4QAAABAAEAAQABAQA7MAAAAQAA7gACAMgFAAAHCO0AYwADsBATJwABZWlzOjAAAAEAAAAAAA4AEAAAABEJTAlNCU4JTwkeDB8Mrg+vD9cP6g/aEAARjhOPE+OAhLAgB1oAARFABAGBhLAwDAsAAaBAAAAM1KCAAAARX7BADNUAAQAAHQEFAPXeEwAAAQABAHoAAQATgAKgAAAABv5hZwEDAPSZEgAAAQBrAQEA84ACaW8BAQA7MAAAAQAA7gACAHgHAAAHC+0AAQgBsEAUZgABZfUqFAAAAQABAAEAAQDzgQJndAEBAaBwAAASAGk7MAAAAQAAAAECAHcHAAAHCv8AAQUA88oQAAABAAEA84ACYW8TgAKgQAAADDZydQGAAqAAAAAHXKAQAAAJEGR4EwACsCANAAABZXLyGxAAAAEAE4ACsLAUsQABcngBCgD0mRMAAAEAAQABABOAArAQERQCOmFlAQQA9KkQAAABAAEAAQABBAA6MAAAAQAAAAAABwAQAAAAORM6E0gTSRPOE88T4RPiEwEDAPPVEgAAAQCqANOAhLBAEQYAAQFIAce/AwCPoIAAABLXsGAM7wABsEAMYAABsTAUhAABP6kfOzAAAAEAAEsAIgB7AAAAgAAAAL0EAQDJBAAAggUBAEIHAQBSBwAAVgcBAEUJAABZCQcAcAkBAAoMAAAhDAEAKAwBADwMBwBgDAEAfAwBAMsMAQDmDwEAVhABANYQAQDjEAEA+xAAAB0RAgAtEQEAPxEEAGMRAACwEQMA9REBALESAAASEwEAFhMBAEQTAACrFAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/41f859c3ca08.js b/pr/619/docs/search.index/41f859c3ca08.js deleted file mode 100644 index 14b80d2b6..000000000 --- a/pr/619/docs/search.index/41f859c3ca08.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCoJAAABQ2oJAAABQ3MjMBgAKgUAAAFGKggAAAE4FjZfMAAnN08kIHAAABAAEAAaCwAAATzGLzVhMAAC4BAQAjgAKwAA/0A2FkcgEAAbCAFDwAAXDyOBQAAAEAQwADoCAAABFgoEAAABK2ZGVz8/kPAABNAwEAE4ICoCAAABQoZWnzgAJjZQEEADswAAABAAAJAAQAYgkBAJ8QAwDhEAEA7RMBALOAhKCQAAAUlhABQg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/421c90d42076.js b/pr/619/docs/search.index/421c90d42076.js new file mode 100644 index 000000000..febb1e162 --- /dev/null +++ b/pr/619/docs/search.index/421c90d42076.js @@ -0,0 +1 @@ +rn_("AYACsAAT4wABsAAT5QABNDYBBgD0sxQAAAEACgABAPMCAnJ28/YPAAABABgE8wIBZTswAAABAAAFAAIAfxADADARAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4263fb6aabb3.js b/pr/619/docs/search.index/4263fb6aabb3.js deleted file mode 100644 index 5e82d7a76..000000000 --- a/pr/619/docs/search.index/4263fb6aabb3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsIATCQABsKATggABaXQBgAKw4BSEAAGwQBBTAAFscgEGAPTpEAAAAQABAAEARwUAAIeg0AAAFF6wUBBRAAGgAAAAE4Sw8BQ4AAEFkQPy9Q8AAK8A") \ No newline at end of file diff --git a/pr/619/docs/search.index/42941d28362c.js b/pr/619/docs/search.index/42941d28362c.js new file mode 100644 index 000000000..437ac7259 --- /dev/null +++ b/pr/619/docs/search.index/42941d28362c.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAkBAgDnDAEAnw4HAQEBAaAAAAATSnP1xAQAAA4L8QMBAAQAAQECoGAAABPLoOAAABQoZXQ7MAAAAQAACAABAMsECAABgAOwIBKWAAGwsBLQAAGwsBLSAAFiY3PzgARjbHR2") \ No newline at end of file diff --git a/pr/619/docs/search.index/436b7e10f3f4.js b/pr/619/docs/search.index/436b7e10f3f4.js deleted file mode 100644 index edb96b14d..000000000 --- a/pr/619/docs/search.index/436b7e10f3f4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoJAAABN1aPI9EwAAAQDzAgFk8hYHAAABAAECADswAAABAAAFAAEAkBQFAPMLAW07MAAAAQAABQABAE4UBQAjgAKwIAzvAAFhbwECAPMECQAATgMBAAGKArAAE+QAAbAAE+YAATQ2I4ECoDAAAAx7ZXIBgAKwQBH1AAE0jrTbQTFjdbcGAACHsBAQUwABsFAUagABEVEJ9ZsEAAAKAMgAAQCiBw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4382781d434c.js b/pr/619/docs/search.index/4382781d434c.js deleted file mode 100644 index 4aeb5f72c..000000000 --- a/pr/619/docs/search.index/4382781d434c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsIAT6QABdAEaCQAAAQkA884SAAABAAEA84ACY2cBgwKgkAAAFDagkAAAFDcyMwGAAqBQAAAUYqCAAAATgWNl8wACc3TyQgcAAAEAAQABoLAAABPMYvNWEwAALgEBACOAAqAAAAATVWRyI4ACoFAAABQoY2XzgAJpeQEGAPU/EQAAAQABAAEAAQABAQGwQBRmAAFl9SoUAAABAAEAAQABAPcAAICFoBAAAAwUKWAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/438c1338380f.js b/pr/619/docs/search.index/438c1338380f.js deleted file mode 100644 index 8a3a5b187..000000000 --- a/pr/619/docs/search.index/438c1338380f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsAARfgABsAARgAABNDbzAAFh8nkMAAABACOAArCQEYQBI2x0AYACsHATlwABsIAT0AABY3MBAAA6MAAAAQAAAAAACQAQAAAA3xHgEfsS/BLpE+oTQBRBFLsUvBTzgAJkZScBAICFoNAAABQQsBAEvwABoDAAABB4AggL") \ No newline at end of file diff --git a/pr/619/docs/search.index/43a2e1b577ea.js b/pr/619/docs/search.index/43a2e1b577ea.js new file mode 100644 index 000000000..c22c0e66b --- /dev/null +++ b/pr/619/docs/search.index/43a2e1b577ea.js @@ -0,0 +1 @@ +rn_("AQEA9T8RAAABAAEAAQABACOBArCQFAQAAWF0Q4ADsRAUhgABsIATxgABY290EwACsAAUWwABbnL2DAIAAAEAegIBALACVww=") \ No newline at end of file diff --git a/pr/619/docs/search.index/43be24b30c96.js b/pr/619/docs/search.index/43be24b30c96.js deleted file mode 100644 index 33cb5731d..000000000 --- a/pr/619/docs/search.index/43be24b30c96.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9AMUAAABAFAAAQDzAwFj8gcTAAABACOAArBwFLsAAWhvAYICsAAS5AABsAAR6wABZXNDAAOgoAAAFFmgIAAAE5BlaXT19xIAAAEAhgABAPoAAYACsHAS2wABoLAAABQYZW8BAgA7MAAAAQAABgABAGQRBgABAgGgQAAAFDpl8mgUAAABAPOAAmlvAQgA9PoTAAABAIsABQATAQOwkBRjAAGwUBM/AWdnbHA7MAAAAQAAEgAJAGkQAgDuEQEALhMBAE8TAQCGEwEA6xMBACUUAQA0FAEAdRQBAAGAArBAErkBFKAgAAARKGFpAQMA89gSAAABAAEAI4ECsDAUCwABY2kBAAD0KRMAAAEAWAEBAPMDAXM7MAAAAQAADwADAOkRAQCkEwcAnBQFAAEDAPXnEQAAAQAkAQEAYQHzgAJydgEAADswAAABAAAFAAIAtxIBAA4TAwDzAgFkOzAAAAEAAAkAAwDjEQMAshIDAOYSAQAjgAKgkAAAFFhpbxOAArDwFKsAAWxvAQUA9HQUAAAMACIAEQAjgAKgYAAAE4RncyOAArCQFFYAAWJs9xcDAI+wcBIBAAGwYBSMAAGwcBP9AAGwYBM9AAGwUBMrAAG1+Rc7MAAAAQAAPAAYALcFAABsBwEA9wgFAAcJAAA1CQAAFAwAAGIMAQDiDAIADA0BAJgOAwCdDgEA/Q8EAM8QAQAMEQAALxEAAE4RCQCMEQAAjhEDAOERAAA1EwAATBMBAF4TBQBuEwAAKBQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/43d088068252.js b/pr/619/docs/search.index/43d088068252.js deleted file mode 100644 index c8aefad7b..000000000 --- a/pr/619/docs/search.index/43d088068252.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA834UAAABADsAAYACoEAAABNbsCAUGQABaGkBDAGgoAAAFMh38rgUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjgABoGAAABS2ZHM3AwCAhqBAAAAUYbBgFDEAUAKQDgEAAbBQEQ0AAWP0XwcAAAEAAQALAsOAhKAQAAAMe6BQAAASowxABA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/44a641e102e9.js b/pr/619/docs/search.index/44a641e102e9.js new file mode 100644 index 000000000..7737cf85b --- /dev/null +++ b/pr/619/docs/search.index/44a641e102e9.js @@ -0,0 +1 @@ +rn_("AYACoAAAABCVoAAAABCWNDYBgAOwABPjAAGwABPlAAGwcBReAAE0NmEBBAD0sxQAAAEACgABACOBAqBAAAARXm1wAQEAOzAAAAEAAAgAAwDWEgAASRMAAMAUBgDHAQACxaBAAAAQWKCAAAASsEAGgAg7MAAAAQAAFgAIAPYPAQAWEQEAWhEDANERBQC/EwMADxQAAG4UAQCiFAEA8wACZXY6MAAAAQAAAAAAFQAQAAAAEgITAhQCrgUGDbQPtQ/RD+sPfxCAEIEQghAwETERxxLIEskSyhLFEzEUMhQBgQKwcBFaAAGwcBFcAAE0NiOAArAQB2MAAW5wAQMCsEATIAABoDAAABN2ZXf0hxAAAAcAugABABOBAqBwAAATsGdvAQQAOzAAAAEAAAYAAgAJDAAAFA0FAGOAA7BQD/YAAWRzdFcBAACFoBAAABBYsSAUbgABESEBOzAAAAEAAAoAAwB/AAAAlQAFANcRAwA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/44b1e0e589da.js b/pr/619/docs/search.index/44b1e0e589da.js new file mode 100644 index 000000000..54aad756b --- /dev/null +++ b/pr/619/docs/search.index/44b1e0e589da.js @@ -0,0 +1 @@ +rn_("AQgA9UEUAAABAAEAAQABAPMAAWY7MAAAAQAABQACAPEBAACaEAQAAQIAOzAAAAEAAAsAAgDREwUAjxQFAPMGAW07MAAAAQAADQAEANMMAABtEQAA6RIFAE0UBQBjgAOwAAknAAFlbXM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4532c887319b.js b/pr/619/docs/search.index/4532c887319b.js deleted file mode 100644 index b0ee73b03..000000000 --- a/pr/619/docs/search.index/4532c887319b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoEAAABQ6ZfJoFAAAAQABAAD0DhMAAAEAAQABAPMEAWT0shIAAAEAAQABAKcAAAKFsKAUVgABsEATDAABsHAT/QABFYgAASgUAAABAAGwgBQ8AAFw8jgUAAABAEMAA6AgAAARYKBAAAAStmRlc/P5DwAATQMBAPOAAmVp") \ No newline at end of file diff --git a/pr/619/docs/search.index/45772a0772e0.js b/pr/619/docs/search.index/45772a0772e0.js deleted file mode 100644 index a3df7cb08..000000000 --- a/pr/619/docs/search.index/45772a0772e0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9foHAAABAAEAAQABAAEAAqAwAAARHKCQAAATkTBo9QMSAACWAQEAAQABABOAAqAwAAAP0GRyIwKEsBAI/QM+sCAMCAELoDAAAA/1EgAY9ZsFAAAwAAEAAQABADOAhLCgEtEAAbBAD9oAARBJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/46067659099a.js b/pr/619/docs/search.index/46067659099a.js deleted file mode 100644 index ae5e01604..000000000 --- a/pr/619/docs/search.index/46067659099a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAUAAQCQFAUA8w0BbTswAAABAAAFAAEAThQFACMDhLBAEsQAAaEAAAAUlrAAE4UAijAIAjswAAABAAAYAAYAMxEHAOgSAQBkEwQAQhQEAEkUAwC3FAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/461a6040991a.js b/pr/619/docs/search.index/461a6040991a.js deleted file mode 100644 index ae619006a..000000000 --- a/pr/619/docs/search.index/461a6040991a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQAUvQABsNAUrQABa20BCgDz/xMAAAEAdwATgAKiEAAAFMhsbzMBhKBgAAASlqEAAAAUeQSAAzswAAABAAA2AAIAUQcAAKQHNQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/469b0802b939.js b/pr/619/docs/search.index/469b0802b939.js deleted file mode 100644 index 02df5f0dd..000000000 --- a/pr/619/docs/search.index/469b0802b939.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDLEQIAfBMBABMUAgABBADzzhEAAAEAAQAjAAKgYAAAEv1hcvPvEAAAAQDKAQGAAqEQAAAUorCAFJgAAWl1NwQAgoexUBS/AAGgAAAAEM6wcBPcAAGhMAAAFLMKQBsTgAKwEBMJAAFpcg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/46d5566d7ae7.js b/pr/619/docs/search.index/46d5566d7ae7.js deleted file mode 100644 index 1adae159f..000000000 --- a/pr/619/docs/search.index/46d5566d7ae7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsEASyAABsEASygABNDYBCwDzxhMAAGwAAQABBgD0tBQAAAEACgABAPMCAXIBEBQAAPMDAWU7MAAAAQAABQACAH8QAwAwEQEA84ADYWVp") \ No newline at end of file diff --git a/pr/619/docs/search.index/46e4d0320e64.js b/pr/619/docs/search.index/46e4d0320e64.js new file mode 100644 index 000000000..284512a27 --- /dev/null +++ b/pr/619/docs/search.index/46e4d0320e64.js @@ -0,0 +1 @@ +rn_("AQIA9AoRAAABAJIBAQABAAD08g8AAAEA9AAIASOCArBQE1IAAWVzAQIA9CQTAAABAJAAAQABAwD0WBMAAAEAmAABAPOFAmJ1AQIA9HURAAABAHwBAQDzgAJpbPMAA2J0dTowAAABAAAAAAAPABAAAAB0BwEIAggDCAQIGhDgEKwTMBR9FH4UgBSNFI4UtRS5FAEMAPMSFAAAAQABAAGAArAACR8AAaAgAAANB2RuAQYA9CITAAABAJAAAQDzAwFi9AgRAAABAJIBAQCXBgAAh7BAD/AAAaBwAAASp7CQE1AAATgJAzowAAABAAAAAAAkABAAAADDBcQFxQXGBTYHNwc3DPwM/Qz+DAINAw0EDegP6Q88ED0QQRBCEF8QYBBhEGIQYxBkEGUQqBCtENgQ2RCME7AT1xNzFH8UoRSyFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4725f9698340.js b/pr/619/docs/search.index/4725f9698340.js new file mode 100644 index 000000000..1c09b563e --- /dev/null +++ b/pr/619/docs/search.index/4725f9698340.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABQjZfKZFAAAAQABAQA7MAAAAQAABgABAMAUBgDzBgFl9G4UAAABADMAAQAzAwOwYBOEAIphcnXzexAAAHkCAQAjgAKAEXsAEAFkcg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/473725894482.js b/pr/619/docs/search.index/473725894482.js new file mode 100644 index 000000000..981a35d9e --- /dev/null +++ b/pr/619/docs/search.index/473725894482.js @@ -0,0 +1 @@ +rn_("AQACoDAAABEcoJAAABOQMGj1AhIAAJYBAQABAAEAE4ACoDAAAA/QZHIjAISwEAj9Az6wIAwIAQugMAAAD/USABj1mwUAADAAAQABAAEAAQIA9LMUAAABAAoAAQABAgDzbxAAAAEAAQDzgAJpcgEBArBAEWEAAaBQAAATdWVz9JcOAADgAgEAkQIBCwD2nxMAAAEArABYABgAAQDzgAJsdNOAhKCQAAATTQFEBA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/476898cf4863.js b/pr/619/docs/search.index/476898cf4863.js deleted file mode 100644 index 670df0671..000000000 --- a/pr/619/docs/search.index/476898cf4863.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA834UAAABADsAAQ0BoKAAABTId/K4FAAAAQABgQKwgBSOAAGgYAAAFLZkczcBAIaFoEAAABRhsGAUMQBQApAK") \ No newline at end of file diff --git a/pr/619/docs/search.index/4804538c1395.js b/pr/619/docs/search.index/4804538c1395.js deleted file mode 100644 index b4a473060..000000000 --- a/pr/619/docs/search.index/4804538c1395.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9JITAAABAAEAAQDzBQF0OzAAAAEAAAgAAgAKDAAAPAwHAAEFAPOuEwAAAQABADcAAICFsDAQTQABoKAAABPMoDAAABQJEEFI") \ No newline at end of file diff --git a/pr/619/docs/search.index/48106c3c5c2c.js b/pr/619/docs/search.index/48106c3c5c2c.js new file mode 100644 index 000000000..b8bcaefae --- /dev/null +++ b/pr/619/docs/search.index/48106c3c5c2c.js @@ -0,0 +1 @@ +rn_("AQEAOjAAAAEAAAAAAAgAEAAAAA8JdxAiESMRJBH5E/oThRSKFAEBAqBAAAAUbaAwAAARKGVo9QcJAAAuAC0DAQB9BQECAPTXEQAAAQABAAEAE4ECsCAR2wABYXPzgAJubwECAPSyEAAAAQABAAEAEwACoNAAABRyY3PyIhAAAAEA84ADZWlv") \ No newline at end of file diff --git a/pr/619/docs/search.index/48408a05a41d.js b/pr/619/docs/search.index/48408a05a41d.js new file mode 100644 index 000000000..061a08d9b --- /dev/null +++ b/pr/619/docs/search.index/48408a05a41d.js @@ -0,0 +1 @@ +rn_("AQAA9CgTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCjEwcAmxQFAEcAAASGoIAAABODsQAUqgABsEAS4wABsIAUugABsFATKgABFQAW9JgOAAABAAEAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/486fe095d42b.js b/pr/619/docs/search.index/486fe095d42b.js new file mode 100644 index 000000000..871735fb6 --- /dev/null +++ b/pr/619/docs/search.index/486fe095d42b.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABGDZQE7EAAAAQgA9MYRAAABAAEAAQABAwGgQAAAEYJlAcoPAAABAgDzMwwAAAEAAQAjAAKwIAwhAAFrcvb0BgAAAQAQCu0AAQAzAvOAAnJ4AQMBsIAUXgABdjswAAABAAALAAMAFhEBANERBQC/EwMAI4ACsGAQhwDBYXIBAwGgAAAAEDpz8sgPAAABACOAAqCwAAAT52VoAQMBoEAAABEVZfIbCQAAAQDXCwAAiqAgAAAHaLCwEzYAAaCAAAARyqAAAAATQ58ITDowAAABAAAAAAAKABAAAAALAnoEewR8BAsMDAx0DHUMdgxEE1oT") \ No newline at end of file diff --git a/pr/619/docs/search.index/4889d2edc856.js b/pr/619/docs/search.index/4889d2edc856.js new file mode 100644 index 000000000..4dd4b3484 --- /dev/null +++ b/pr/619/docs/search.index/4889d2edc856.js @@ -0,0 +1 @@ +rn_("AYACoCAAAA/ToDAAABPXYXLzAAF0AYEHAAABBAGgQAAAFGRl8oYUAAABAAEFADswAAABAAALAAUAWRAFANASAQD+EwEAVxQAAHYUAADjAISgMAAAD9GFAAI7MAAAAQAACwAFAKUFAgDABgQAWwwBAIsRAADiEgAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/48a29e008e15.js b/pr/619/docs/search.index/48a29e008e15.js deleted file mode 100644 index 573d1699d..000000000 --- a/pr/619/docs/search.index/48a29e008e15.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9LYPAAABAAEAAQDzAgFzATIRAAABAAKwgBSOAAGgYAAAFLZkc/L9CAAAPgOTgISwwBPKAAGgEAAAEd4AwUA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/48f90631aab7.js b/pr/619/docs/search.index/48f90631aab7.js deleted file mode 100644 index 1590bd9bb..000000000 --- a/pr/619/docs/search.index/48f90631aab7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAO4AAgARDAAAHA3tAPMAAW07MAAAAQAA7gACAKIFAADPBe0AAQMAOzAAAAEAAAgAAgCnDwYAXBMBAPMAAWM7MAAAAQAAVwAnAKYECwBvBQAAFAkBACsMAQAzDAIA8wwAAP8MAgARDQEA0A8AANUPAQDYDwEA3g8AAGYQAgBtEAEAchABAJcQAAAPEQAAFREAAGERAQBuEQEAghEBAIYRAgDnEQEA+hECAAASAAC2EgAAvxIBAMQSAQAMEwEAHBMBACETAQBBEwEAURMDAFcTAQC4EwEAzBMAADoUAABjFAQAbBQCAPOAAnJ3AQkA834UAAABADsAAYACoEAAABNbsCAUGQABaGkBDAGgoAAAFMh38rgUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjgABoGAAABS2ZHM3AwCBhqBAAAAUYbBgFDEAUAKQDgGIArAAE+QAAbAAE+YAATQ2M4ADoDAAABGFZG5zYwADoBAAAATJYWVvAYcAAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/490b10876df2.js b/pr/619/docs/search.index/490b10876df2.js deleted file mode 100644 index fe3bee0c3..000000000 --- a/pr/619/docs/search.index/490b10876df2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9I4RAAABAAEAAQABAgA7MAAAAQAACgAEAI8QBQDTEgEAMxMBAFkUAADzgAJmbgEBADswAAABAAAIAAIApw8GAFwTAQDzgAJkbgEBAPMwBwAAAQABAAGGAqAAAAATVaAAAAATVmRy8wEBdgGBEwAAQwADsIAS6AABsLAUiQABa2xyOzAAAAEAAAwAAwAnBwgACg0BAEgQAQABAgD1+gcAAAEAAQABAAEA8wCEFEEAAYEAAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/491b60251375.js b/pr/619/docs/search.index/491b60251375.js new file mode 100644 index 000000000..96eb9ae68 --- /dev/null +++ b/pr/619/docs/search.index/491b60251375.js @@ -0,0 +1 @@ +rn_("AYMCsQAUvAABsNAUrAABa20BCgDz/hMAAAEAdwATgAKiEAAAFMdsbzMChKBgAAASlaEAAAAUeASAAzswAAABAAA2AAIAUQcAAKQHNQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4937adcdd97b.js b/pr/619/docs/search.index/4937adcdd97b.js deleted file mode 100644 index 2d3784c47..000000000 --- a/pr/619/docs/search.index/4937adcdd97b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAYAAQBfEAYAAQMAOzAAAAEAAAUAAQDaDAUAYwADoJAAABN1aHBzOjAAAAEAAAAAAA4AEAAAAKgFxQYYCV0MagwGEQcRtxK4Eg4TDxMQExETPRM+Ew==") \ No newline at end of file diff --git a/pr/619/docs/search.index/494dbd5577e9.js b/pr/619/docs/search.index/494dbd5577e9.js deleted file mode 100644 index 26d6fed61..000000000 --- a/pr/619/docs/search.index/494dbd5577e9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOjAAAAEAAAAAAAgAEAAAAB4MHwyuD68P6g/aEAARjhOPEwEAAPQ9CQAAAQABAAEAAQUBsDATGgABaPMHFAAAAQByABODAqAwAAAQzWNwAQMA9OgPAAABAO8AAQABgQKgAAAAEYmgEAAAD8tldfOAAmFyAQAA9L4RAAABAAEAAQABgAKgkAAAE/GwUBKlAAFid/OAAmR0E4ACsJATMwABbnLzAAJldPTEEAAAAQABAAEAAQEA9X4MAAABAAEAAQABABOAArCwE+0AAWFvIwACsEANAAABZXQ7MAAAAQAACQAEAL0EAQCCBQEAYAwBALARAwABAgA7MAAAAQAACQACAOkHBwAUEwEAAYACsJATfAABoKAAABPwZXYTgAKxgBTDAAFjbQGCArBAFBsAAaBQAAAR7WJmE4ACoEAAABRHZHMjgAKg0AAAFJdjbvOAhBEBQAEFAbBAE1cAAWUBpBIAAEOCA6EAAAAUpaDQAAAUeGttcxOAArBgEOMAAWFyAQUAOzAAAAEAAI0AAgD3EAAACRKMAAGCA7AgExYAAbAgEH0AAbBAEXkAAWtsc1OAA7AgFHwAAWt0dQGJhKCAAAAUtqBAAAAUYaBgAAAUgaCQAAAUugKAChOChKCgAAAT77GgFMYAAbDQFFoAAQQBCQEBAPS6EQAAAQABAAEAQ4ADsXAUwQABoNAAABQwY29zI4ACsGAQ4QABaW8BAAD0KAwAAAEAUwABACOBAqDgAAAUTWV5AQ0AOjAAAAEAAAAAAAcAEAAAAE8TUBPrE+wTJRQmFHUUdhQBgQKwQBNvAAGgwAAAFC9lbwECADowAAABAAAAAAAIABAAAADfD+APkhHxEvIS7xN4FK0UrhTzAQFvOzAAAAEAAAkABABiCQEAnxADAOEQAQDtEwEA84ADbW5yAQAAOzAAAAEAAAYAAgCMEwAA9BMFAEOAA7BAFGwAAaAgAAAM/2VycyMAArAwE9AAAWNy8roTAAABAAGBArCAExwAAaEAAAAUd2NmAQsA9HgTAAABAAEAAQABgAKgAAAAEJWgAAAAEJY0NvMCAXYBBg0AAPMAAmRsAR0JAADX/jkAkrCgFBkAAbBwEd8AAbCAEvsAAaCwAAATNZ3dfzswAAABAAAXAAsAqwEBALkEAwB/BQIA/wYBAAkHAgA5DAAA+A8AAF8RAADOEQIAqhICAF4UAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/49e136f13e32.js b/pr/619/docs/search.index/49e136f13e32.js new file mode 100644 index 000000000..1b8637869 --- /dev/null +++ b/pr/619/docs/search.index/49e136f13e32.js @@ -0,0 +1 @@ +rn_("AQUA8x0TAAABAAEAAQAAOzAAAAEAAAUAAgAEDAMA9hEBAPMAAWT0/hAAAAEAmgABAFMAA7AwFFUAAWVwcvTkDwAAAQDuAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/4a10cfb0683a.js b/pr/619/docs/search.index/4a10cfb0683a.js new file mode 100644 index 000000000..fb96ddba5 --- /dev/null +++ b/pr/619/docs/search.index/4a10cfb0683a.js @@ -0,0 +1 @@ +rn_("AQkA830UAAABADsAAYACoEAAABNasCAUGAABaGkBDAGgoAAAFMd38rcUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjQABoGAAABS1ZHM3AwCAhqBAAAAUYLBgFDAAUAKQDgEAAbBQEQ0AAWP0XwcAAAEAAQALAsOAhKAQAAAMe6BQAAASogxABA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4a62d4a1af3d.js b/pr/619/docs/search.index/4a62d4a1af3d.js new file mode 100644 index 000000000..f1d47f662 --- /dev/null +++ b/pr/619/docs/search.index/4a62d4a1af3d.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgCLEwAA8xMFACOIArBAFGsAAWVzAQQBsDATWwABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/BECAAETBAAoFAAA8wMDY2Vw884MAAABAAEAAQABsGAUDAABZQFGFAAA8wIBc/YpCQAAAQABABoIPwAiAQECAaBQAAARhXIBJhEAAPOAA2ZtcA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/2e78c3c6420b.js b/pr/619/docs/search.index/4b13a43f6772.js similarity index 57% rename from pr/619/docs/search.index/2e78c3c6420b.js rename to pr/619/docs/search.index/4b13a43f6772.js index f0078c389..c488423ee 100644 --- a/pr/619/docs/search.index/2e78c3c6420b.js +++ b/pr/619/docs/search.index/4b13a43f6772.js @@ -1 +1 @@ -rn_("AQIA9L4RAAABAAEAAQDzAAFl9MQQAAABAAEAAQABAwD0uhEAAAEAAQABAMcAAACFsKATHAABsCAMKAABsIAS+wABCAwG8wkHAAABAAEA") \ No newline at end of file +rn_("AQIA9L4RAAABAAEAAQDzAAFl9MQQAAABAAEAAQABAwD0uhEAAAEAAQABAMcAAACFsKATGwABsCAMKAABsIAS+gABCAwG8wkHAAABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/4b54ee0900f5.js b/pr/619/docs/search.index/4b54ee0900f5.js deleted file mode 100644 index 481b648a9..000000000 --- a/pr/619/docs/search.index/4b54ee0900f5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9PoTAAABAIsABQATAAOwkBRjAAGwUBM/AWdnbHA7MAAAAQAAEgAJAGkQAgDuEQEALhMBAE8TAQCGEwEA6xMBACUUAQA0FAEAdRQBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4b5ec50dbde7.js b/pr/619/docs/search.index/4b5ec50dbde7.js deleted file mode 100644 index e6c5071c5..000000000 --- a/pr/619/docs/search.index/4b5ec50dbde7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9VAJAAABAAEAAQABAPMAAWnz8QwAAMAHAQABAQGgQAAAFCRl8poUAAABAAEEAqAgAAAR3qAwAAASqWJoAc4PAADnAACAxaAQAAAM8qAwAAAQfAQQKAE=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4b6c25da1b8d.js b/pr/619/docs/search.index/4b6c25da1b8d.js new file mode 100644 index 000000000..09914c174 --- /dev/null +++ b/pr/619/docs/search.index/4b6c25da1b8d.js @@ -0,0 +1 @@ +rn_("AQQA9g4NAAABADsDAQAuAQEAAQoA89QSAAABAKoAAQEA9yUJAAABAFcHAQBzAAEAFQEjgAKwYBPsAAFpbwECAPTLDAAAAQBJBgEAAQUA9AIUAAABAFAAAQD3BAAAh6AgAAAMzbCQEfoAAQScAzowAAABAAAAAAAIABAAAACUBRYJFwlnDGgMARECEQYTBxM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4b92a5eb1142.js b/pr/619/docs/search.index/4b92a5eb1142.js new file mode 100644 index 000000000..e77e92229 --- /dev/null +++ b/pr/619/docs/search.index/4b92a5eb1142.js @@ -0,0 +1 @@ +rn_("AQABoDAAAAzRaQF2EwAAAQABsDARSgABbvJaBwAAAQABAQDz2gcAANgHAQATAAKgUAAAEKhlc/VZBAAAAQABAAEAAQABhAKwoBQYAAGwoBQaAAFjcvMBAXT07BEAAOsAAQABAAEDAbBgFGkAAWY7MAAAAQAABwADAA0MAwCHEwEAEBQBAPOAAmFl84CEACgF") \ No newline at end of file diff --git a/pr/619/docs/search.index/4bcb9b25f02d.js b/pr/619/docs/search.index/4bcb9b25f02d.js deleted file mode 100644 index e21131397..000000000 --- a/pr/619/docs/search.index/4bcb9b25f02d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOjAAAAEAAAAAAAoAEAAAAOYP5w/WENcQYxH1EfYREhMTE6sUrBQBBADz4Q8AAOEAAQDzAAFx9w4NAAABADsDAQDNAGEAAQDzAAJleTowAAABAAAAAAAOABAAAAAPCVcMWAx3EIwQjRAiESMRJBH6E/sTCxQMFIYUixQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4c7306736acb.js b/pr/619/docs/search.index/4c7306736acb.js deleted file mode 100644 index bd6821d2c..000000000 --- a/pr/619/docs/search.index/4c7306736acb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQADoKAAABRZoCAAABOQsDAR6wABZWl08vcSAAABAAEDADswAAABAAAGAAEAZBEGAAEIAPT6EwAAAQCLAAUAEwEDsJAUYwABsFATPwFnZ2xwOzAAAAEAABIACQBpEAIA7hEBAC4TAQBPEwEAhhMBAOsTAQAlFAEANBQBAHUUAQABgAKwMBHnAAGwMBHpAAFydgECAbAAErcAAWQ7MAAAAQAABQACAOMRAwDmEgEAI4ECoJAAABRYaW8BBwD0dBQAAAwAIgARAHcLAAGIsFASuQEUsGATPQABlQkDOjAAAAEAAAAAAA4AEAAAAOIM4wzkDJ0Ong7PENAQDBEvEY4RjxGQEZERNRNuEyOAAqAQAAAM4W5v") \ No newline at end of file diff --git a/pr/619/docs/search.index/4c8a317f35fe.js b/pr/619/docs/search.index/4c8a317f35fe.js new file mode 100644 index 000000000..ef6b76b35 --- /dev/null +++ b/pr/619/docs/search.index/4c8a317f35fe.js @@ -0,0 +1 @@ +rn_("AQAA9AoRAAABAJIBAQAjgQKgYAAAEz9iaQEAAPTyDwAAAQD0AAgBI4ICsFATUgABZXMBiQKwIBRwAAGgMAAAFHppcAECAPQkEwAAAQCQAAEAAQMA9FgTAAABAJgAAQDzhQJidQECAPR1EQAAAQB8AQEA84ACaWy3AQAAhaAgAAATLBIBDDowAAABAAAAAAAUABAAAAB0BwEIAggDCAQIFQxODE8MUAxRDBoQ4BCsEzAUfRR+FIAUjRSOFLUUuRQBBQDzEhQAAAEAAQBDhgOwkBSXAAGgAAAAErliZHcBgAKwAAkfAAGwIA0HA2VkbgEDAPPwDwAAAQAHAQECAPYeDAAAAQCPAwEA3gMBAAEAAPQ9CQAAAQABAAEAAQAAOzAAAAEAAAYAAgCLEwAA8xMFACOBArBAFGsAAWVz84ADZXh5AQAA9DkJAAABAAEAAQBDgAOgQAAAFJWwIBMgAAFlcngBgAKgQAAADPGwQBAbAAFnbCcaAADJoJAAABNtsMATtwABoBAAABFxoDAAABQJsEAM6QABAEegCzowAAABAAAAAAAJABAAAABwBXEF7wzwDAUN7A9GEEcQFxMYEwEGAPQiEwAAAQCQAAEA8wMBYvQIEQAAAQCSAQEAtwwAAImgcAAAEqewkBNQAAGwYBA+AAGgMAAAE3Y4iRM6MAAAAQAAAAAALwAQAAAAwwXEBcUFxgU2BzcHAQkCCQMJMwk0CSMMNwz8DP0M/gwCDQMNBA3oD+kPPBA9EEEQQhBfEGAQYRBiEGMQZBBlEIcQjhCoEK0Q2BDZEEgRSRH8EowTsBPXE3MUfxShFLIU") \ No newline at end of file diff --git a/pr/619/docs/search.index/4c8ba4ecb3a3.js b/pr/619/docs/search.index/4c8ba4ecb3a3.js deleted file mode 100644 index 3e42f17cc..000000000 --- a/pr/619/docs/search.index/4c8ba4ecb3a3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgCMEwAA9BMFACOIArBAFGwAAWVzAQQBsDATXAABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/RECAAITBAApFAAA8wMDY2Vw884MAAABAAEAAQABsGAUDQABZQFHFAAA8wIBc/YpCQAAAQABABoIPwAjAQECAaBQAAARhXIBJhEAAPOAA2ZtcA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4ca1c3eded1f.js b/pr/619/docs/search.index/4ca1c3eded1f.js new file mode 100644 index 000000000..7f5787795 --- /dev/null +++ b/pr/619/docs/search.index/4ca1c3eded1f.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABNKc/TSDwAA8QMBAAQAAQECsGAUPQABsEAUewABZHQ7MAAAAQAADQAGAP0SAwBoEwEA2BMBAO8TAQBwFAEAlxQBAAEBA7BwEgAAAbCAEtoAAYATfQAQ+m1uczswAAABAAALAAIA9wgFAF0TBQCjgISwsBPGAAGxcBS6AAEIQIIBAIWgcAAAEp+wMBSuAAGgcAAAEQ+xABQ9AAGwABM+AWcGIQHyeAUAAAEAZwQAAIdOEjVZMDugEAAABauwMBMxAUmgQAAAETIRwQw7MAAAAQAABgACAIsTAADzEwUA") \ No newline at end of file diff --git a/pr/619/docs/search.index/4cc106c9c096.js b/pr/619/docs/search.index/4cc106c9c096.js deleted file mode 100644 index 6262c1f06..000000000 --- a/pr/619/docs/search.index/4cc106c9c096.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAI0AAgD3EAAACRKMAAEAAbBwE8oAAWXy4g8AAAEAIwACoEAAABQkZXP0TRAAAAEATAQBADOAA6BgAAARqmRpbw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4cdfa2c543b7.js b/pr/619/docs/search.index/4cdfa2c543b7.js new file mode 100644 index 000000000..bfae772b1 --- /dev/null +++ b/pr/619/docs/search.index/4cdfa2c543b7.js @@ -0,0 +1 @@ +rn_("AQIBsEATtwABZfLGBgAAAQABBADzbxAAAAEAAQBDAAOwQBMbAAGxABP+AAFlZnA7MAAAAQAAJAAGABgCAADVBgwA4wYMAKcPBgAQEQAAWxMBAGOAA7AwDBYABWFlaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4d8196dbc1e6.js b/pr/619/docs/search.index/4d8196dbc1e6.js new file mode 100644 index 000000000..05eb20fd7 --- /dev/null +++ b/pr/619/docs/search.index/4d8196dbc1e6.js @@ -0,0 +1 @@ +rn_("AYACsRAUmQABsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAIcHAACHsKATwwABsNAUWwABoFAAABQmjBQROzAAAAEAAAYAAwBYBwAA6RADALoSAQDzgQJsdPMAAWk7MAAAAQAAjgADAJoEAAD3EAAACBKMAAEFAPN9FAAAAQA7AAEAAaBAAAAQ+2XzCwkAAAEAmwkTgAKgMAAAD95kcvMAAWXz8AYAAAEAAQDzgAJodAEBADswAAABAACNAAIA9xAAAAgSjAATgAKgUAAAECFpdAEIAPT5EwAAAQCLAAUAEwCEsPAUfwAzsJAUYgABsFATPgFnQIkAOzAAAAEAABIACQBpEAIA7REBAC0TAQBOEwEAhRMBAOoTAQAkFAEAMxQBAHQUAQDXAQAAhrCAEbQAAaBAAAAJLggwJjowAAABAAAAAAANABAAAACSAJMAYgdvCQgMEw0KEQsRnRKeEiQTJRO1E7YT") \ No newline at end of file diff --git a/pr/619/docs/search.index/4e123559303b.js b/pr/619/docs/search.index/4e123559303b.js new file mode 100644 index 000000000..f0adcd3d9 --- /dev/null +++ b/pr/619/docs/search.index/4e123559303b.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABQjZfKZFAAAAQABAQA7MAAAAQAABgABAMAUBgDzBgFl9G4UAAABADMAAQAzAQOwYBOEAIphcnXzexAAAHkCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/4e9e267b2057.js b/pr/619/docs/search.index/4e9e267b2057.js new file mode 100644 index 000000000..b870f4a42 --- /dev/null +++ b/pr/619/docs/search.index/4e9e267b2057.js @@ -0,0 +1 @@ +rn_("AQIBoDAAABB3YQFaDAAAAYECoCAAABD6sFASvAABYW8BAwGgAAAAE+JzAfkQAAAjgAKgAAAAB/hydmMAA7BQEWsAAWNlczswAAABAAAIAAQACAkCADYJAQBvEAIAohIAAAGAArDQFK4AAaCQAAATq2JoJwEAgIWwUBErAAGw8BPDAAGwIA+wAAFEIQTzgAJudA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4f24054bf4c8.js b/pr/619/docs/search.index/4f24054bf4c8.js deleted file mode 100644 index 9c6bad7c2..000000000 --- a/pr/619/docs/search.index/4f24054bf4c8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9gUNAADnAloAAQDRAgEAAQQAOzAAAAEAAAoABACPEAUA0xIBADMTAQBZFAAAAYYCoAAAABNVoAAAABNWZHLzAgF2AYETAADzgAJlbycBAADHoDAAAA/roHAAABKjoIAAABQosNATxwABoLAAABQoQEUICTswAAABAAAJAAMAwAUCACEHBABeDAEAI4ACRtVWbXrnZHIBAAA6MAAAAQAAAAAACgAQAAAAVwlYCSEQbxNwE6AToRNNFKUUvRS+FBOAAqAwAAAQpWx0w4AEoAAAABCVoAAAABCWNDZhZQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4f47720a4a70.js b/pr/619/docs/search.index/4f47720a4a70.js deleted file mode 100644 index b51883552..000000000 --- a/pr/619/docs/search.index/4f47720a4a70.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkBoEAAABRlZfKHFAAAAQABgAKwAAzsAAGggAAAE8lkcAEDAaAAAAAQOnPyyA8AAAEAAQIDsGATRgABsNAUaAABoIAAABPoaXJzAXMUAAD3AACAhaEwAAAUhpBJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/4f50d5ca1278.js b/pr/619/docs/search.index/4f50d5ca1278.js new file mode 100644 index 000000000..9c2373910 --- /dev/null +++ b/pr/619/docs/search.index/4f50d5ca1278.js @@ -0,0 +1 @@ +rn_("AQQAOjAAAAEAAAAAAAcAEAAAANwP3Q+mEKcQIhMjE7MTtBMBAAD0BQkAAAEA1ArtACcAAACIoRAAABR5oEAAABEVsGAUaQABoBAAAAyHsFAUAAABsDARdwABsSAUiwABOcECOjAAAAEAAAAAABEAEAAAABsJHAkvCTAJDQwODA8MEAwWDBsM4AyhEocTiBOdE54TEBQRFDOAA6CAAAAUCWVveQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/502e82d4852b.js b/pr/619/docs/search.index/502e82d4852b.js new file mode 100644 index 000000000..d1d5ce920 --- /dev/null +++ b/pr/619/docs/search.index/502e82d4852b.js @@ -0,0 +1 @@ +rn_("AQAA9D0HAAABAAEAAQABhQKwcBQVAAGwMBNoAAFlcxMAA7BAD9gAAaBgAAARjGJlczswAAABAAASAAQAqQUBAMoGCgBREAEAqRADAAECAPO3BQAARgoBAAEDAPXQDwAAnQABAAQAAQABCgGgQAAAFGRl8oYUAAABACMABKAwAAARHKCQAAATkLBgEroAATBjaGn1AhIAAJYBAQABAAEA84ACZHLnBAAAh7AQCP0DPrAgDAgBC6AwAAAP9RJBODswAAABAAASAAYAjQACAJsFAADLBQMAngcFAOMHAwASDAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/5068939f60c0.js b/pr/619/docs/search.index/5068939f60c0.js new file mode 100644 index 000000000..8ef7ef8d6 --- /dev/null +++ b/pr/619/docs/search.index/5068939f60c0.js @@ -0,0 +1 @@ +rn_("AQgA9PkTAAABAIsABQATAAOwkBRiAAGwUBM+AWdnbHA7MAAAAQAAEgAJAGkQAgDtEQEALRMBAE4TAQCFEwEA6hMBACQUAQAzFAEAdBQBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/48ae650d1123.js b/pr/619/docs/search.index/506b2673d878.js similarity index 67% rename from pr/619/docs/search.index/48ae650d1123.js rename to pr/619/docs/search.index/506b2673d878.js index 3e413bbe8..9463e5ddf 100644 --- a/pr/619/docs/search.index/48ae650d1123.js +++ b/pr/619/docs/search.index/506b2673d878.js @@ -1 +1 @@ -rn_("AQMBoEAAABGCZQHKDwAAAQIA8zMMAAABAAEAIwACsCAMIQABa3L29AYAAAEAEAruAAEAMwLzAAJyePL1CAAAAQA=") \ No newline at end of file +rn_("AQMBoEAAABGCZQHKDwAAAQIA8zMMAAABAAEAIwACsCAMIQABa3L29AYAAAEAEArtAAEAMwLzAAJyePL1CAAAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5070f1f10ee5.js b/pr/619/docs/search.index/5070f1f10ee5.js new file mode 100644 index 000000000..847915de6 --- /dev/null +++ b/pr/619/docs/search.index/5070f1f10ee5.js @@ -0,0 +1 @@ +rn_("AQABoCAAAAzubQGEBQAAAQAA9A0TAAABAAEAAQDzBAFk9LESAAABAAEAAQAjhISwoBRVAAGwQBMLAAGwcBP8AAEVgAAzgAOw0BQ/AAFhZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/50aedf89c3d4.js b/pr/619/docs/search.index/50aedf89c3d4.js new file mode 100644 index 000000000..a33ffb12b --- /dev/null +++ b/pr/619/docs/search.index/50aedf89c3d4.js @@ -0,0 +1 @@ +rn_("AQQA9n0UAAABAA8AAQAnAAQAAQMA88ASAAABAAEAI4ECsSAUugABY2sTgAKgMAAAFDluclMAA6BAAAAMI2VvcvQoEQAAgAG/AQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/50b1f19bd128.js b/pr/619/docs/search.index/50b1f19bd128.js new file mode 100644 index 000000000..331427514 --- /dev/null +++ b/pr/619/docs/search.index/50b1f19bd128.js @@ -0,0 +1 @@ +rn_("AQABoJAAABN0aPI8EwAAAQDzAgFk8hYHAAABAAECADswAAABAAAFAAEAjxQFAPMLAW07MAAAAQAABQABAE0UBQAjgAKwIAzvAAFhbwECAPMECQAATgMBAAGKArAAE+MAAbAAE+UAATQ2I4ECoDAAAAx7ZXIBgAKwQBH0AAFJG2AlE3VjdbcGAACHsBAQUwABsFAUaQABEVEJ9ZsEAAAKAMgAAQCiBw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/36f982cb06b4.js b/pr/619/docs/search.index/50c240033502.js similarity index 53% rename from pr/619/docs/search.index/36f982cb06b4.js rename to pr/619/docs/search.index/50c240033502.js index 882ce4233..93a682e65 100644 --- a/pr/619/docs/search.index/36f982cb06b4.js +++ b/pr/619/docs/search.index/50c240033502.js @@ -1 +1 @@ -rn_("AQYAOzAAAAEAAAkAAQBOEQkAAQIAOzAAAAEAABMAAQAkEBMAE4GEoFAAABEQoBAAAAwqoCAAAAz0HEAAE4ACsFATggABYW4zgAOwMA/MAAFpc3Q=") \ No newline at end of file +rn_("AQYAOzAAAAEAAAkAAQBOEQkAAQIAOzAAAAEAABMAAQAkEBMAE4GEoFAAABEQoBAAAAwqoCAAAAz0HEAAE4ACsFATgQABYW4zgAOwMA/MAAFpc3Q=") \ No newline at end of file diff --git a/pr/619/docs/search.index/50d909c780ea.js b/pr/619/docs/search.index/50d909c780ea.js deleted file mode 100644 index 3cb10f281..000000000 --- a/pr/619/docs/search.index/50d909c780ea.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABPjcwH5EAAAAQMA9IgQAAABAAEAAQATgAKwUBCMAAFhaQGAArBwFK8AAbBwFDwAAWVyAYACoLAAABRzoDAAABElbG6XAQAAhaAgAAASoKAgAAAI/hCRBDowAAABAAAAAAATABAAAACcBNQE1QTWBNcE2ATZBG4Jtg+3D7gPuQ9LE4UTCRQPFBsUHBQ4FDkUAQIAOjAAAAEAAAAAAAoAEAAAAFcJWAkhEG8TcBOgE6ETTRSlFL0UvhQBAAA7MAAAAQAABgACAIwTAAD0EwUAAQIBsDATXAABYzowAAABAAAAAAATABAAAAD/DNAPZhBnEGgQbRBuEHIQcxAPEYIRhhGHEYgRABJRE1ITOhRjFGQUAQMA88YTAABsAAEAE4ECsEARbgABYWUTgAKgsAAAFHphZQEBAbBAFGYAAWX1KhQAAAEAAQABAAEAE4ACoBAAAAwUYW+HDwAAyLAwCQ8HaLBAFGwAAaCAAAASm0BMiAnz+AcAACQEPgABgAKggAAAE3agkAAAE05hawEDAPPBEgAAAQABACOAhLEgFLsAAaAAAAAJMqAwAAAP1wQEBgEIAPXDFAAAAQABAAEAAQATigKwQBSaAAFhcpMAhKDAAAATSqEAAAAUGAFABvJ6BwAAAQABAwGgQAAAEfpl8wkNAAAQBAEAAQUA9LwTAAABAAEAAQBTgAOwABNxAAFlc3QBBgD0pxQAAAEAAQABAPMIAW30rRIAAAEAAQABAAECADswAAABAAAFAAEAkBQFAPMNAW07MAAAAQAABQABAE4UBQABBAD3EQ0AAAEApAUOAAEAjgABAAEDAYATfgAQ+nM7MAAAAQAABQABAF4TBQAjggKgkAAAFGJpcwEFAaBQAAAUJ2jyuxIAAAEAE4ACsDATcQABbnQBgAKggAAAE5GwQBHzAAFhZQGAAqAQAAARG6AAAAARYG5yAQkBoEAAABRlZfKHFAAAAQAjgAKgkAAAE8lpbMcjAAAKoDAAABEcsFATJwABsPAUsQABsHATjgABoNAAABRuMGJjZWhpa25vdjswAAABAAAeAAsAEwwAAPMQAwADEgQAihMBAJkTAwDQEwEAGBQAAB0UBgA8FAEASBQAAF8UAQABAgKgsAAAFFigsAAAFFljc/PPEAAAAQBfAAEBArBQEfMAAaDAAAAUJ2hp8tATAAABAPOAAmVpAQEBsJATigABc/SyEAAAAQABAAEAAQMBsAAQ7QABcwFVEAAA84ADaGl0AQEBoFAAABMLYwHSDAAAAQUBsIAUXwABdjswAAABAAAIAAIA0REEAMATAwABAQD0dRAAAAEAswABAOOAhLBwEfcAAQ4IAPdlDwDRsJASmQABoFAAABEUoQAAABSWoKAAABOtoBAAAAdQQD+/KTswAAABAAA8ABkAxAQAAMYEAACYBQIAGAcCAAAMAwDVDAEAxA8CANIPAAD5DwAAAhAAACIQAQAyEQgAiREAANsSAQDkEgEA6BIBAEYTAQBkEwQAuhMBAMQTAQDJEwAAQhQEAEkUAwCWFAAAtxQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/512d730914d8.js b/pr/619/docs/search.index/512d730914d8.js new file mode 100644 index 000000000..29f2728bc --- /dev/null +++ b/pr/619/docs/search.index/512d730914d8.js @@ -0,0 +1 @@ +rn_("AQAAOjAAAAEAAAAAAAoAEAAAAOYP5w/WENcQYxH0EfURERMSE6oUqxTzAQF58goUAAABACMAA6BAAAARgqBQAAAUXWVvc/LKDwAA1gI=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5151488331bc.js b/pr/619/docs/search.index/5151488331bc.js new file mode 100644 index 000000000..ccf13d463 --- /dev/null +++ b/pr/619/docs/search.index/5151488331bc.js @@ -0,0 +1 @@ +rn_("AQEA9yIRAAABAAEA1QIBAIsABQABAgD0shAAAAEAAQABABOAAqDQAAAUcmNz84ACZW8jgQKwAAdUAAFsdAEAADswAAABAAAFAAEAsQUFAFOAhKBQAAAUx7CgFAYAAQggBQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/51515dbbfc1a.js b/pr/619/docs/search.index/51515dbbfc1a.js new file mode 100644 index 000000000..c8a1b766c --- /dev/null +++ b/pr/619/docs/search.index/51515dbbfc1a.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwDLEQIAexMBABIUAgABBADzzhEAAAEAAQAjAAKgYAAAEvxhcvPvEAAAAQDJAQGAAqEQAAAUobCAFJcAAWl1NwQAgYexUBS+AAGgAAAAEM6wcBPbAAGhMAAAFLIKQBsBAAA7MAAAAQAAjAABAAoOjAABAgD2nxMAAAEArABYABgAAQAjgQKgIAAAEQ9ydvOAAmVvI4ACoCAAABKaZHQBAAA7MAAAAQAA8AAEAMgFAAAHCO0AhwwAAHERAADzgANkbnY=") \ No newline at end of file diff --git a/pr/619/docs/search.index/51550cc23ebb.js b/pr/619/docs/search.index/51550cc23ebb.js deleted file mode 100644 index 30cc10829..000000000 --- a/pr/619/docs/search.index/51550cc23ebb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQoBoIAAABS3ZgGWEwAAAQgA9UIUAAABAAEAAQABAPMDAWb1mhAAAAEAAQABAAEA84MCYXMBAgKgIAAAEd6gMAAAEqliaAHODwAAI4ACoIAAABNKYXDzAAJobQGkBAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/517058123e73.js b/pr/619/docs/search.index/517058123e73.js deleted file mode 100644 index 1912741b4..000000000 --- a/pr/619/docs/search.index/517058123e73.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkBoIAAABS3ZgGWEwAAAQIA9dsQAAABAAEAXgIBAPMAAml1OjAAAAEAAAAAAAcAEAAAALYQ8BLcE90TDRQOFC8UMBQBCAD1QhQAAAEAAQABAAEA8wIBZvWaEAAAAQABAAEAAQATgAKwoBSMAAFydPMCAmFz88oQAAABAAEAAQQBsEAUZgABZfUqFAAAAQABAAEAAQABAgA7MAAAAQAACwACANITBQCQFAUA8wMBbTswAAABAAANAAQA0wwAAG0RAADqEgUAThQFAPOBAmNl84ACYWU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/51b113a9243a.js b/pr/619/docs/search.index/51b113a9243a.js new file mode 100644 index 000000000..e82bddb8b --- /dev/null +++ b/pr/619/docs/search.index/51b113a9243a.js @@ -0,0 +1 @@ +rn_("AQEAOjAAAAEAAAAAAAkAEAAAAN8P4A/VEJIR8BLxEu4TdxSsFK0UAYACsOAT6AABsDAUAAABZHDDgISxQBS+AAGgkAAAE6wCgAk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/522ac7ec74f9.js b/pr/619/docs/search.index/522ac7ec74f9.js new file mode 100644 index 000000000..730bd50fe --- /dev/null +++ b/pr/619/docs/search.index/522ac7ec74f9.js @@ -0,0 +1 @@ +rn_("AQMA88ASAAABAAEAI4ECsSAUugABY2sBBAGgQAAAEfll8wkNAAAQBAEAAQAAOzAAAAEAAAUAAgDzEAMAiRMBAHOAhKAwAAAUOQgwAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/52559e834367.js b/pr/619/docs/search.index/52559e834367.js deleted file mode 100644 index d7b158a12..000000000 --- a/pr/619/docs/search.index/52559e834367.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECoBAAABNFoHAAABONYWMBhwKwABPkAAGwABPmAAE0NlMAhKCQAAATbbCwFAsAAYEACfUmBwAANgA9CREBIAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5282edab2506.js b/pr/619/docs/search.index/5282edab2506.js new file mode 100644 index 000000000..2a954da80 --- /dev/null +++ b/pr/619/docs/search.index/5282edab2506.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABQjZfKZFAAAAQABAQA7MAAAAQAABgABAMAUBgDzBgFl9G4UAAABADMAAQBTAISgIAAACWGwYBOEAIoBAQnzexAAAHkCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/530be4a20340.js b/pr/619/docs/search.index/530be4a20340.js deleted file mode 100644 index 7b0f07e90..000000000 --- a/pr/619/docs/search.index/530be4a20340.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoCAAAAzubQGEBQAAAQAA9A4TAAABAAEAAQDzBAFk9LISAAABAAEAAQAjhISwoBRWAAGwQBMMAAGwcBP9AAEVgAAzgAOw0BRAAAFhZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/537f1365d973.js b/pr/619/docs/search.index/537f1365d973.js deleted file mode 100644 index d356ba9c6..000000000 --- a/pr/619/docs/search.index/537f1365d973.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoCAAAA/ToDAAABPYYXLzAAF0AYEHAAABBAGgQAAAFGVl8ocUAAABAAEFADswAAABAAALAAUAWRAFANESAQD/EwEAWBQAAHcUAADjAISgMAAAD9GFAAI7MAAAAQAACwAFAKUFAgDABgQAWwwBAIsRAADjEgAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/53bc60c79808.js b/pr/619/docs/search.index/53bc60c79808.js deleted file mode 100644 index b15aa009e..000000000 --- a/pr/619/docs/search.index/53bc60c79808.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoEAAABH6ZfMJDQAAEAQBAAEGAPQWEQAAAQC/AAEAE4EDoAAAABFesSAUowABYWRuAQUA9IgQAAABAAEAAQABFAD1wxQAAAEAAQABAAEAAQUBsIAUXwABdjswAAABAAAIAAIA0REEAMATAwAjgAKwcBH3AAFiZFcCAAGGsMATigABoKAAABOtoJAAABN2BeAC9RgHAAABAAEA6AiUBAEGAPPVEgAAAQCqAPOAA3J0dgEDADswAAABAAAHAAIAvBMDAKcUAwDzAAFzAWIUAADzAAFzAfkRAABnAQCAhqAwAAAMRbAAE3EAAaAQAAAM7hJADg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/54011c82d16e.js b/pr/619/docs/search.index/54011c82d16e.js new file mode 100644 index 000000000..99c637af9 --- /dev/null +++ b/pr/619/docs/search.index/54011c82d16e.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAUAAQCPFAUA8w0BbTswAAABAAAFAAEATRQFACMDhLBAEsMAAaEAAAAUlbAAE4QAijAIAjswAAABAAAYAAYAMxEHAOcSAQBjEwQAQRQEAEgUAwC2FAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/5495b5bb307e.js b/pr/619/docs/search.index/5495b5bb307e.js deleted file mode 100644 index 5f66f5563..000000000 --- a/pr/619/docs/search.index/5495b5bb307e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABHeoDAAABKpYmgBzg8AAAETAbAAFIIAAXM7MAAAAQAABQABAJwUBQABBwDzqhIAAAEAAQDzgANkcnQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/54a96814a8d9.js b/pr/619/docs/search.index/54a96814a8d9.js new file mode 100644 index 000000000..47f963360 --- /dev/null +++ b/pr/619/docs/search.index/54a96814a8d9.js @@ -0,0 +1 @@ +rn_("AQACoDAAABEcoJAAABOQMGj1AhIAAJYBAQABAAEAE4ACoDAAAA/QZHIjAYSwEAj9Az6wIAwIAQugMAAAD/USABj1mwUAADAAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/54cd2264c9fa.js b/pr/619/docs/search.index/54cd2264c9fa.js new file mode 100644 index 000000000..80b20b83b --- /dev/null +++ b/pr/619/docs/search.index/54cd2264c9fa.js @@ -0,0 +1 @@ +rn_("AYECoBAAABNEoHAAABOMYWMBhwKwABPjAAGwABPlAAE0NlMAhKCQAAATbLCwFAoAAYEACfUmBwAANgA9CREBIAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/54f8e1b1ce55.js b/pr/619/docs/search.index/54f8e1b1ce55.js new file mode 100644 index 000000000..1e07949b1 --- /dev/null +++ b/pr/619/docs/search.index/54f8e1b1ce55.js @@ -0,0 +1 @@ +rn_("AQIAOjAAAAEAAAAAAA4AEAAAABENEg0VEfkR+hH7EbUSvhK/EsMSxBIbExwTUhNTEwEJAPN7EQAAAQABAAEKAPPNEgAAAQABAAEGAPU/EQAAAQABAAEAAQDzgAJkbnMAhLEgFD0AAQARA/ImEwAAAQABDQD2nxMAAAEArABYABgAAQABgAKwoBO3AAGgEAAADDpjdQEBAPTJEwAAAQBLAAEA8wABZfJ2CQAAAQD3AACAxbAwELcAAQACqAg=") \ No newline at end of file diff --git a/pr/619/docs/search.index/55717c6a00ad.js b/pr/619/docs/search.index/55717c6a00ad.js new file mode 100644 index 000000000..139caaf68 --- /dev/null +++ b/pr/619/docs/search.index/55717c6a00ad.js @@ -0,0 +1 @@ +rn_("AQEBsIATagABdfJKCQAAAQAjgAKwEAlIAAEzNgECAPNTBwAA8wEBAAECAPRDCQAAAQACCAEAAQIA81QMAAABAAEAE4ACsBAJQQABaXUBAgA7MAAAAQAACwACANETBQCPFAUA8wkBbTswAAABAAAMAAMAbREAAOkSBQBNFAUAdzAAAIqgMAAAE+egcAAAEf+gIAAACUWwMBHEAAGgUAAAEAIzhQs7MAAAAQAANAIEAP0BAAAjAjIBdwcAAAcK/wA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/558a6ec98792.js b/pr/619/docs/search.index/558a6ec98792.js deleted file mode 100644 index c7eae847d..000000000 --- a/pr/619/docs/search.index/558a6ec98792.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9g4NAAABADsDAQAuAQEAAQoA89USAAABAKoAAQEA9yUJAAABAFcHAQBzAAEAFgEjgAKwYBPtAAFpbwECAPTLDAAAAQBKBgEAAQUA9AMUAAABAFAAAQD3BAAAh6AgAAAMzbCQEfsAAQScAzowAAABAAAAAAAIABAAAACUBRYJFwlnDGgMARECEQcTCBM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/55c799f52241.js b/pr/619/docs/search.index/55c799f52241.js new file mode 100644 index 000000000..19b191b41 --- /dev/null +++ b/pr/619/docs/search.index/55c799f52241.js @@ -0,0 +1 @@ +rn_("AQgA830UAAABADsAI4ACsAAQ3gABbW4BgAOgQAAAE1qwIBQYAAGgIAAAD9doaXkBCQGggAAAFLZmAZUTAAABAwGwABQwAFBz8q0QAAAqA0OAA7AgD9MBJ7BQErwAAWFvcgECAPXbEAAAAQABAF0CAQDzAANpdHU6MAAAAQAAAAAAEQAQAAAAgQcyCfcMOBC2EOER7xIoEykT2xPcE+ITDBQNFC4ULxSBFIIUAQYA9BETAAABAJgBAQATAgKwYBMTAAFmbfLlDAAAAQAjggKwQBNAAAFlbAGAAqAwAAAUYLCwE7EAAWFsAQYA8+EPAADhAAEAAQUA9AIUAAABAFAAAQDzAgFj8gYTAAABAAECAaAwAAAQd2EBWgwAAAGAArBQESsAAbAgD7AAAWNu84ACbnQBBQA7MAAAAQAADgACAOsMAAAKEA0AAQIAOzAAAAEAAAcAAQBZCQcA5wUAAAmgMAAADFmgsAAAFC6ggAAAEaqw0BQ9AAEwYWZpa21ydXY7MAAAAQAAagIFAP8BAABrA+0AeAcAAAcL7QAKDowAAQwBoKAAABTHd/K3FAAAAQABAQDz+g8AAAEAAQDzgAJ0dQEDAPPAEgAAAQABAAEBAPU/EQAAAQABAAEAAQABAQGwMA/qAPB09moHAAABAI4A9AerAP0BY4ADsJAUBAABYW10AQMBoEAAABRkZfKGFAAAAQATgAKwYBS6AAFlcgEDAaAAAAAT4nMB+RAAAAECADowAAABAAAAAAAKABAAAABXCVgJIRBuE28TnxOgE0wUpBS8FL0UgwAEoIAAABKasHARbgABsCARDwDwZm5ydgH4BwAAAYECoAAAAAkyoDAAAA/Xc3THAQCAxrAAFDsAAbCQEpgAAaAQAAAHUAASiCgBAgA7MAAAAQAADQAGAFkQBQBrEQEA0BIBAP4TAQBXFAAAdhQAABOCArDwFLoAAWZnAYACsIAUjQABoGAAABS1ZHMTgAKwwBPJAAFpbwEIAPVBFAAAAQABAAEAAQDzAgFm9ZoQAAABAAEAAQABACOAA6AgAAAP0bCgFIsAAWRydPf7BwCPoDAAAA/Hl9cPOzAAAAEAAFUBHgCFBAEAsgQCAHwFAgClBQIAyQUBAMAGBABBBwAAWQcAAPQHAQAICQIANgkBAC0MAwBbDAEAgwwDAOcMAQCfDgcB8A8BAG8QAgC3EAEAyhACAPgQAQCLEQAAvhEDAOgRAQCiEgAA4hIAABkTAQCBEwEAoxMHAJsUBQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/55f99a25ee95.js b/pr/619/docs/search.index/55f99a25ee95.js new file mode 100644 index 000000000..10d888c42 --- /dev/null +++ b/pr/619/docs/search.index/55f99a25ee95.js @@ -0,0 +1 @@ +rn_("AYACsAAQIgABsCAMYgABZWkBiQKwIBRwAAGgMAAAFHppcBMAA6AgAAATLKCAAAATP2VpdfUVDAAAOQABAAEAAQABhgKwkBSXAAGgAAAAErliZAGAArAwEyAAAaAwAAAQ+HJ21wAAAIWgMAAAEGygMAAAE3YQARM6MAAAAQAAAAAACgAQAAAAAQkCCQMJMwk0CSMMhxCOEEgRSRH8EmOAA7AQCPUAAWRtdA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/560456bf6138.js b/pr/619/docs/search.index/560456bf6138.js deleted file mode 100644 index 2baf8d4b4..000000000 --- a/pr/619/docs/search.index/560456bf6138.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9JITAAABAAEAAQABAAD1fgwAAAEAAQABAAEA84ACZ2sTgAKwsBPtAAFhbwGAAqAgAAAL/6BAAAAMN2V0AYUCsHAUFgABsDATaQABZXMTAAOwQA/YAAGgYAAAEYxiZXM7MAAAAQAAEgAEAKkFAQDKBgoAURABAKkQAwABAwD0bRAAAAEABAABAAEKAaBAAAAUZWXyhxQAAAEAE4ACsGASuwABY2nzgAJkcvMAAmVvOzAAAAEAAAkAAgCeBwUA4wcDAAECAbAwEVgAAW47MAAAAQAACQABAPULCQDzgAJvdAEDADswAAABAADuAAIAeAcAAAcL7QABAgGgcAAAEgBpOzAAAAEAAAABAgB3BwAABwr/ABOAAqBAAAAMNnJ1AQQA9EgTAAABAJgAAQABAwDz1RIAAAEAqgDzgAJhb9cHAACIsEANAAABsTAUhAABNIEWOzAAAAEAAB4ADQC9BAEAggUBAAoMAAA8DAcAYAwBAOYPAQDWEAEAYxEAALARAwD1EQEAsRIAABITAQCrFAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/56e3f5148932.js b/pr/619/docs/search.index/56e3f5148932.js new file mode 100644 index 000000000..183933eff --- /dev/null +++ b/pr/619/docs/search.index/56e3f5148932.js @@ -0,0 +1 @@ +rn_("AQoBoIAAABS2ZgGVEwAAAQgA9UEUAAABAAEAAQABAPMDAWb1mhAAAAEAAQABAAEA84MCYXMBAgKgIAAAEd2gMAAAEqhiaAHODwAAI4ACoIAAABNJYXDzAAJobQGkBAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/573145d855d3.js b/pr/619/docs/search.index/573145d855d3.js deleted file mode 100644 index a54e805c2..000000000 --- a/pr/619/docs/search.index/573145d855d3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBsDATXAABY/OGEQAAAQABAAEDAYATfgAQ+nM7MAAAAQAABQABAF4TBQAjggKgkAAAFGJpcwcBAIDFsFATJwABoKAAABPJsHATjgABoNAAABRugAEYCPOAAmRy") \ No newline at end of file diff --git a/pr/619/docs/search.index/575a77072d0b.js b/pr/619/docs/search.index/575a77072d0b.js new file mode 100644 index 000000000..b22ee1063 --- /dev/null +++ b/pr/619/docs/search.index/575a77072d0b.js @@ -0,0 +1 @@ +rn_("AQoA9KETAAABAA8AAQABgwKgIAAAEEygMAAAEOhpdAEAAPQNEwAAAQABAAEA8wQBZPSxEgAAAQABAAEAI4aEsKAUVQABsEATCwABsHAT/AABFYAAAQACsDAQPgABsBATuQABc3TylgUAAIcGAYACsMAUgwABoAAAAAdSdHnzgIURwQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/575b5c18cfe6.js b/pr/619/docs/search.index/575b5c18cfe6.js deleted file mode 100644 index c0ec99002..000000000 --- a/pr/619/docs/search.index/575b5c18cfe6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBoDAAABB3YQFaDAAAAYECoCAAABD6sFASvQABYW8BAwGgAAAAE+NzAfkQAAAjgAKgAAAAB/hydmMAA7BQEWsAAWNlczswAAABAAAIAAQACAkCADYJAQBvEAIAoxIAAAGAArDQFK8AAaCQAAATrGJoJwEAgIWwUBErAAGw8BPEAAGwIA+wAAFEIQTzgAJudA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/576a19df7354.js b/pr/619/docs/search.index/576a19df7354.js new file mode 100644 index 000000000..8a4139190 --- /dev/null +++ b/pr/619/docs/search.index/576a19df7354.js @@ -0,0 +1 @@ +rn_("AQABsGAUDAABZQFGFAAAAQYA9DYTAAABAFEBAQABBAD0UBMAAAEAEQEBAPMAA2VyczowAAABAAAAAAAJABAAAAApCSoJKwlFEYQRmBKZEqYSBBQFFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/57920d8b3eb8.js b/pr/619/docs/search.index/57920d8b3eb8.js deleted file mode 100644 index caf038524..000000000 --- a/pr/619/docs/search.index/57920d8b3eb8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAEoAAAABCZsCARTAABoFAAABH5oEAAABQ7ZGxzdjswAAABAAATAAYArAUAADYMAADrDAAAChANAHARAAA2FAEAAQIA9NgRAAABAAEAAQAThAKwIBHcAAFhc/OAAmFl") \ No newline at end of file diff --git a/pr/619/docs/search.index/58f342d8c6f8.js b/pr/619/docs/search.index/58f342d8c6f8.js deleted file mode 100644 index 3128583b2..000000000 --- a/pr/619/docs/search.index/58f342d8c6f8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsFAUFgABoAAAAAkQY3QBAQD0khMAAAEAAQABAAEDAPTzDAAA2QagAAEAAYACoBAAAAx7oFAAABKjY2QBAgDzBAkAAE4DAQDzAAFt86UEAADIAAEAAYECoBAAABNFoHAAABONYWPzAAFy81wHAABOCiAAZw8AgIiwMA/UAM+gMAAAFJYpMCM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/597646fd02a2.js b/pr/619/docs/search.index/597646fd02a2.js deleted file mode 100644 index d443fd34c..000000000 --- a/pr/619/docs/search.index/597646fd02a2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEAUfAABdDswAAABAAANAAYA/hIDAGkTAQDZEwEA8BMBAHEUAQCYFAEAE4ACsDATMgFJaXABBQDzrhMAAAEAAQATgAKgMAAAFAlleVMCA7BwFBYAAWJlcwFAEAAAEwACoCAAAAWjZm31gwAAAOQGAQDZAQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/59a86ab4d1f5.js b/pr/619/docs/search.index/59a86ab4d1f5.js new file mode 100644 index 000000000..d4bed6a79 --- /dev/null +++ b/pr/619/docs/search.index/59a86ab4d1f5.js @@ -0,0 +1 @@ +rn_("AQMBgBN9ABD6czswAAABAAAFAAEAXRMFACOCAqCQAAAUYWlzBwEAhMWwUBMmAAGgoAAAE8iwcBONAAGg0AAAFG2AARgI") \ No newline at end of file diff --git a/pr/619/docs/search.index/5a1a09f0a2a3.js b/pr/619/docs/search.index/5a1a09f0a2a3.js new file mode 100644 index 000000000..6a3f5928d --- /dev/null +++ b/pr/619/docs/search.index/5a1a09f0a2a3.js @@ -0,0 +1 @@ +rn_("AQUA9AIUAAABAFAAAQDzAwFj8gYTAAABACOAArBwFLoAAWhvAYICsAAS4wABsAAR6gABZXNDAAOgoAAAFFigIAAAE49laXT19hIAAAEAhgABAPoAAYACsHAS2gABoLAAABQXZW8BAgA7MAAAAQAABgABAGQRBgABAgGgQAAAFDll8mcUAAABAPOAAmlvAQgA9PkTAAABAIsABQATAQOwkBRiAAGwUBM+AWdnbHA7MAAAAQAAEgAJAGkQAgDtEQEALRMBAE4TAQCFEwEA6hMBACQUAQAzFAEAdBQBAAGAArBAErgBFKAgAAARKGFpAQMA89cSAAABAAEAI4ECsDAUCgABY2kBAAD0KBMAAAEAWAEBAPMDAXM7MAAAAQAADwADAOgRAQCjEwcAmxQFAAEDAPXmEQAAAQAkAQEAYQHzgAJydgEAADswAAABAAAFAAIAthIBAA0TAwDzAgFkOzAAAAEAAAkAAwDiEQMAsRIDAOUSAQAjgAKgkAAAFFdpbxOAArDwFKoAAWxvAQUA9HMUAAAMACIAEQAjgAKgYAAAE4NncyOAArCQFFUAAWJs9xcDAI+wcBIAAAGwYBSLAAGwcBP8AAGwYBM8AAGwUBMqAAG1+Rc7MAAAAQAAPAAYALcFAABsBwEA9wgFAAcJAAA1CQAAFAwAAGIMAQDiDAIADA0BAJgOAwCdDgEA/Q8EAM8QAQAMEQAALxEAAE4RCQCMEQAAjhEDAOARAAA0EwAASxMBAF0TBQBtEwAAJxQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5a9b2df043b7.js b/pr/619/docs/search.index/5a9b2df043b7.js deleted file mode 100644 index 0c90b3cac..000000000 --- a/pr/619/docs/search.index/5a9b2df043b7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9gUNAADnAloAAQDRAgEAAQQAOzAAAAEAAAoABACPEAUA0xIBADMTAQBZFAAAAYYCoAAAABNVoAAAABNWZHLzAgF2AYETAADzgAJlbycBAADHoDAAAA/roHAAABKjoIAAABQosNATxwABoLAAABQoQEUICTswAAABAAAJAAMAwAUCACEHBABeDAEAI4ACRtVWbXrnZHIBAAA6MAAAAQAAAAAACgAQAAAAVwlYCSEQbxNwE6AToRNNFKUUvRS+FBOAAqAwAAAQpWx084ACYWU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5b33e7b2e8ac.js b/pr/619/docs/search.index/5b33e7b2e8ac.js deleted file mode 100644 index 501baa1e6..000000000 --- a/pr/619/docs/search.index/5b33e7b2e8ac.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoEAAABCtdPf3DAAAQQPxAgEAuQCfAAEA8wABczswAAABAAAcAAgAsgQCAC0MAwDwDwEAtxABAPgQAQDpEQEApBMHAJwUBQAjgAKxEBSjAAFhdA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5b499f990c5c.js b/pr/619/docs/search.index/5b499f990c5c.js deleted file mode 100644 index 15abb7a99..000000000 --- a/pr/619/docs/search.index/5b499f990c5c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoFAAABRecwGhEgAAAYICsEASyAABsEASygABNDYBCwDzxhMAAGwAAQABBgD0tBQAAAEACgABAPMCAXIBEBQAAPMDAWU7MAAAAQAABQACAH8QAwAwEQEA84QDYWVpY4ADoFAAABSXY2V0") \ No newline at end of file diff --git a/pr/619/docs/search.index/5b5f9cd06395.js b/pr/619/docs/search.index/5b5f9cd06395.js deleted file mode 100644 index a687bdb86..000000000 --- a/pr/619/docs/search.index/5b5f9cd06395.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOjAAAAEAAAAAAAkAEAAAAN8P4A/VEJIR8RLyEu8TeBStFK4UAYACsOAT6QABsDAUAQABZHDDgISxQBS/AAGgkAAAE60CgAk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5b6614ab60f9.js b/pr/619/docs/search.index/5b6614ab60f9.js deleted file mode 100644 index a3c061e2b..000000000 --- a/pr/619/docs/search.index/5b6614ab60f9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOjAAAAEAAAAAAA4AEAAAABENEg0VEfoR+xH8EbYSvxLAEsQSxRIcEx0TUxNUEwEJAPN7EQAAAQABAAEKAPPOEgAAAQABAAEGAPU/EQAAAQABAAEAAQDzgAJkbnMAhLEgFD4AAQARA/InEwAAAQABDQD2oBMAAAEArABYABgAAQABgAKwoBO4AAGgEAAADDpjdQEBAPTKEwAAAQBLAAEA8wABZfJ2CQAAAQD3AACAxbAwELcAAQACqAg=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5b7f3b18b806.js b/pr/619/docs/search.index/5b7f3b18b806.js deleted file mode 100644 index d5b7eb6a4..000000000 --- a/pr/619/docs/search.index/5b7f3b18b806.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABOQsDAR6wABaXTy9xIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PoTAAABAIsABQATAQOwkBRjAAGwUBM/AWdnbHA7MAAAAQAAEgAJAGkQAgDuEQEALhMBAE8TAQCGEwEA6xMBACUUAQA0FAEAdRQBAAGAArAwEecAAbAwEekAAXJ2AQQBsAAStwABZDswAAABAAAFAAIA4xEDAOYSAQC3BQABh7BQErkBFLBgEz0AAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETUTbhMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwCEoFAAABGLoDAAABCkFAEQ8pwHAAABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/006efa80c79b.js b/pr/619/docs/search.index/5b87a2dfb37f.js similarity index 55% rename from pr/619/docs/search.index/006efa80c79b.js rename to pr/619/docs/search.index/5b87a2dfb37f.js index 5bbd172b6..7a77aef8b 100644 --- a/pr/619/docs/search.index/006efa80c79b.js +++ b/pr/619/docs/search.index/5b87a2dfb37f.js @@ -1 +1 @@ -rn_("AQgA9HUQAAABALMAAQABAAGggAAAFLdm8gAJAACWCgEHAPVkEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MCAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAAM4ADoEAAAAwSYWVv") \ No newline at end of file +rn_("AQgA9HUQAAABALMAAQABAAGggAAAFLZm8gAJAACVCgEHAPVjEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MCAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAAM4ADoEAAAAwSYWVv") \ No newline at end of file diff --git a/pr/619/docs/search.index/5c081caa8d23.js b/pr/619/docs/search.index/5c081caa8d23.js deleted file mode 100644 index 68e62856f..000000000 --- a/pr/619/docs/search.index/5c081caa8d23.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQAzAQOwYBOFAIphcnXzexAAAHoCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/5c4b51f4875f.js b/pr/619/docs/search.index/5c4b51f4875f.js deleted file mode 100644 index c22c3bc99..000000000 --- a/pr/619/docs/search.index/5c4b51f4875f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoDAAABEcoJAAABORMGj1AxIAAJYBAQABAAEAE4ACoDAAAA/QZHIjAISwEAj9Az6wIAwIAQugMAAAD/USABj1mwUAADAAAQABAAEAAQIA9LQUAAABAAoAAQABAgDzbxAAAAEAAQDzgAJpcgEBArBAEWEAAaBQAAATdmVz9JcOAADgAgEAkgIBCwD2oBMAAAEArABYABgAAQDzgAJsdNOAhKCQAAATTgFEBA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5c7d0b0c55d0.js b/pr/619/docs/search.index/5c7d0b0c55d0.js deleted file mode 100644 index 4ce1bfa1a..000000000 --- a/pr/619/docs/search.index/5c7d0b0c55d0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9OkTAAABAFYAAQABAgGgYAAAFJdz8twRAAABAAGAArAgECIAAaCQAAAUR2FlAQcBsEAUZgABZfUqFAAAAQABAAEAAQABAwGwQBR8AAF08tkTAAABACOEAqBAAAAUCWJzE4ACsMAUrwABdXkBAQD02BEAAAEAAQABABOAArAwEQMAAWRsN3QAAIuwQBO4AAGgUAAAEXCgkAAAE6ywUBMJAAGgMAAADG+zmAc7MAAAAQAAYgARAAgCAQBmBAMAxwUAAMYGAQBjBwEADQkBABoJAAAkCQAAVgkAAIgMQgDhDAAA7g8BAMgQAQDlEAEAKxEBAKsRBAC9EgEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/5cad8e1cb609.js b/pr/619/docs/search.index/5cad8e1cb609.js deleted file mode 100644 index 22ea9cb95..000000000 --- a/pr/619/docs/search.index/5cad8e1cb609.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAAkABABiCQEAnxADAOEQAQDtEwEAAQIBsEAUfAABdDswAAABAAANAAYA/hIDAGkTAQDZEwEA8BMBAHEUAQCYFAEAE4ACsDATMgFJaXABiAKwABPkAAGwABPmAAE0NhOBAqAwAAARhWRzAYACoCAAAAx7sGAUFgABbngBBQDzrhMAAAEAAQATgAKgMAAAFAllefMAhBIAA/JAEAAA5gDzgAJydA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5cf9082a3bd3.js b/pr/619/docs/search.index/5cf9082a3bd3.js new file mode 100644 index 000000000..617e30177 --- /dev/null +++ b/pr/619/docs/search.index/5cf9082a3bd3.js @@ -0,0 +1 @@ +rn_("AQAA9K4QAAABAAEAAQDzAgFz9UwJAAABAAEAAQCIBgEGAPQDEgAAAQABAAEAAQQBoEAAABQjZfKZFAAAAQABAQA7MAAAAQAABgABAMAUBgDzBgFl9G4UAAABADMAAQAzBgOwYBOEAIphcnXzexAAAHkCAQDzgAJhZQEDAPS2EQAAAQABAAEAAQIA9MwPAAABAEsEAQABggKgEAAAE1qwQBL6AAFhcwGAA7AAB3oAAaAAAAAMHLBwEIwAAW5yc+cHAACHoHAAABICkQVBOjAAAAEAAAAAAAwAEAAAAOYB5wHoAekBfAfnB+gHVQlZDAcQCBAJEBwR") \ No newline at end of file diff --git a/pr/619/docs/search.index/5d5311cd5bf9.js b/pr/619/docs/search.index/5d5311cd5bf9.js deleted file mode 100644 index 467fa66eb..000000000 --- a/pr/619/docs/search.index/5d5311cd5bf9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoGAAABSXc/LcEQAAAQABCAD1QhQAAAEAAQABAAEAowCEsCAJdgABoIAAABLwMEAIOzAAAAEAAAUAAgDxAQAAmhAEAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5e57b15a881e.js b/pr/619/docs/search.index/5e57b15a881e.js new file mode 100644 index 000000000..9d39ceab7 --- /dev/null +++ b/pr/619/docs/search.index/5e57b15a881e.js @@ -0,0 +1 @@ +rn_("AQMBoEAAABH5ZfMJDQAAEAQBAAEGAPQWEQAAAQC+AAEAE4EDoAAAABFesSAUogABYWRuAQUA9IgQAAABAAEAAQABFAD1whQAAAEAAQABAAEAAQUBsIAUXgABdjswAAABAAAHAAIA0REDAL8TAwAjgAKwcBH2AAFiZFcCAAGGsMATiQABoKAAABOsoJAAABN1BeAC9RgHAAABAAEA6AiTBAEGAPPUEgAAAQCqAPOAA3J0dgEDADswAAABAAAHAAIAuxMDAKYUAwDzAAFzAWEUAADzAAFzAfgRAABnAQCAhqAwAAAMRbAAE3AAAaAQAAAM7hJADg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5edc2ab10d4f.js b/pr/619/docs/search.index/5edc2ab10d4f.js new file mode 100644 index 000000000..fda5fc833 --- /dev/null +++ b/pr/619/docs/search.index/5edc2ab10d4f.js @@ -0,0 +1 @@ +rn_("AQkA830UAAABADsAAQ0BoKAAABTHd/K3FAAAAQABgQKwgBSNAAGgYAAAFLVkczcBAIWFoEAAABRgsGAUMABQApAK") \ No newline at end of file diff --git a/pr/619/docs/search.index/5ee13d39262b.js b/pr/619/docs/search.index/5ee13d39262b.js new file mode 100644 index 000000000..6e7d7025b --- /dev/null +++ b/pr/619/docs/search.index/5ee13d39262b.js @@ -0,0 +1 @@ +rn_("AQACoCAAABOPsDAR6gABaXTy9hIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PkTAAABAIsABQATAQOwkBRiAAGwUBM+AWdnbHA7MAAAAQAAEgAJAGkQAgDtEQEALRMBAE4TAQCFEwEA6hMBACQUAQAzFAEAdBQBAAGAArAwEeYAAbAwEegAAXJ2AQQBsAAStgABZDswAAABAAAFAAIA4hEDAOUSAQC3BQABh7BQErgBFLBgEzwAAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETQTbRMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwCEoFAAABGLoDAAABCkFAEQ8pwHAAABAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5ef0351c7da4.js b/pr/619/docs/search.index/5ef0351c7da4.js deleted file mode 100644 index 667219d9b..000000000 --- a/pr/619/docs/search.index/5ef0351c7da4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYAOzAAAAEAAAUAAQBeEwUAg4YEsFATJwABsHATjgABoNAAABRuYm5vdhOAArAQEvkAAXByAQABoDAAABHwdAGtEwAA8wIBc/KoEAAACQMTgAKgYAAAEJlldQECAPYODQAAAQA7AwEALgEBAAGAArAAEuQAAYAOnDTwAWVzAQEA81kHAAApDAEAY4ADsIAUAQABYm5084ADYW9yARQAOzAAAAEAAAUAAQCcFAUAAQAAOzAAAAEAAAYAAgCMEwAA9BMFACOIArBAFGwAAWVzAQQBsDATXAABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/RECAAITBAApFAAA8wIDY2Vw884MAAABAAEAY4ADoGAAAA/0ZW91AQABsGAUDQABZQFHFAAA8wIBc/YpCQAAAQABABoIPwAjAQEIAPPBEgAAAQABAEOAA6AQAAATkKDgAAAUGGRvcwECAaBQAAARhXIBJhEAAAGAAqBAAAAQpaBwAAAUWWFlAQAAOzAAAAEAAAsAAgD4BgUA3RIFAPOAAnR2IwACsBAH9AABbnL2HgkAAFcADgcBALcAAQDzAIcwkQw6MAAAAQAAAAAACAAQAAAAxwTIBAMRBBH3EvgSfhN/E3kU") \ No newline at end of file diff --git a/pr/619/docs/search.index/5f168d03cb64.js b/pr/619/docs/search.index/5f168d03cb64.js deleted file mode 100644 index 06ea6e31a..000000000 --- a/pr/619/docs/search.index/5f168d03cb64.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQECsCAM9QABsAAMbQABZXPyZQcAAAEAAQUA8x4TAAABAAEA8wQBcvTkDwAAAQDuAAEAE4ACoLAAABReYXPzgAJiYw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/5fb00a88a718.js b/pr/619/docs/search.index/5fb00a88a718.js deleted file mode 100644 index 2300cb1d0..000000000 --- a/pr/619/docs/search.index/5fb00a88a718.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9EMJAAABAAIIAQABCQGggAAAFLdmAZYTAAABAgD12xAAAAEAAQBeAgEA8wACaXU6MAAAAQAAAAAABwAQAAAAthDwEtwT3RMNFA4ULxQwFAEIAPVCFAAAAQABAAEAAQDzAgFm9ZoQAAABAAEAAQABABOAArCgFIwAAXJ08wACYXPzyhAAAAEAAQDzgAJ0dg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/604e2f19f907.js b/pr/619/docs/search.index/604e2f19f907.js deleted file mode 100644 index 3fa94e567..000000000 --- a/pr/619/docs/search.index/604e2f19f907.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoEAAABRlZfKHFAAAAQABgAOgMAAAEqKw4BRAAAGwkBSJAAFhY22HAQCAhrAQES0AAbAQEUwAAaCgAAAUc6DwAAAUljFJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6126cb0a3314.js b/pr/619/docs/search.index/6126cb0a3314.js new file mode 100644 index 000000000..0832d94d6 --- /dev/null +++ b/pr/619/docs/search.index/6126cb0a3314.js @@ -0,0 +1 @@ +rn_("AQABsIAT6AABdAEaCQAAAQkA880SAAABAAEA84ACY2cBgwKgkAAAFDWgkAAAFDYyMwGAAqBQAAAUYaCAAAATgGNl8wACc3TyQgcAAAEAAQABoLAAABPLYvNVEwAALgEBACOAAqAAAAATVGRyI4ACoFAAABQnY2XzgAJpeQEGAPU/EQAAAQABAAEAAQABAQGwQBRlAAFl9SkUAAABAAEAAQABAPcAAICFoBAAAAwUKWAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/612b1c20b390.js b/pr/619/docs/search.index/612b1c20b390.js new file mode 100644 index 000000000..635eab768 --- /dev/null +++ b/pr/619/docs/search.index/612b1c20b390.js @@ -0,0 +1 @@ +rn_("AQIBsEAUewABdDswAAABAAANAAYA/RIDAGgTAQDYEwEA7xMBAHAUAQCXFAEAE4ACsDATMQFJaXABBQDzrRMAAAEAAQATgAKgMAAAFAhleVMCA7BwFBUAAWJlcwFAEAAAEwACoCAAAAWjZm31gwAAAOQGAQDZAQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/61e642656581.js b/pr/619/docs/search.index/61e642656581.js new file mode 100644 index 000000000..5b31be5f5 --- /dev/null +++ b/pr/619/docs/search.index/61e642656581.js @@ -0,0 +1 @@ +rn_("AQABoLAAABPLYvNVEwAALgEBAAGAAqAgAAAP06AwAAAT12Fy8wABdAGBBwAAAQQBoEAAABRkZfKGFAAAAQABBQA7MAAAAQAACwAFAFkQBQDQEgEA/hMBAFcUAAB2FAAA4wGEoDAAAA/RhQACOzAAAAEAAAsABQClBQIAwAYEAFsMAQCLEQAA4hIAAGOAA7AAD/QDYGRucg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6204ff5bc229.js b/pr/619/docs/search.index/6204ff5bc229.js deleted file mode 100644 index 3a04b2351..000000000 --- a/pr/619/docs/search.index/6204ff5bc229.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsCARhAEjoJAAABQpbXABgAKgMAAAERCgUAAAE8xjcpcAAACFsCATlwABsMAUXAABoGAAABHhEEAOOzAAAAEAABIABgDLBAgA3xEBAPsSAQDpEwEAQBQBALsUAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/62357ed0a8f2.js b/pr/619/docs/search.index/62357ed0a8f2.js new file mode 100644 index 000000000..caf69ff01 --- /dev/null +++ b/pr/619/docs/search.index/62357ed0a8f2.js @@ -0,0 +1 @@ +rn_("AQADoKAAABRYoCAAABOPsDAR6gABZWl08vYSAAABAAEDADswAAABAAAGAAEAZBEGAAEIAPT5EwAAAQCLAAUAEwEDsJAUYgABsFATPgFnZ2xwOzAAAAEAABIACQBpEAIA7REBAC0TAQBOEwEAhRMBAOoTAQAkFAEAMxQBAHQUAQABgAKwMBHmAAGwMBHoAAFydgECAbAAErYAAWQ7MAAAAQAABQACAOIRAwDlEgEAI4ECoJAAABRXaW8BBwD0cxQAAAwAIgARAHcLAAGIsFASuAEUsGATPAABlQkDOjAAAAEAAAAAAA4AEAAAAOIM4wzkDJ0Ong7PENAQDBEvEY4RjxGQEZERNBNtEyOAAqAQAAAM4W5v") \ No newline at end of file diff --git a/pr/619/docs/search.index/623acef83daa.js b/pr/619/docs/search.index/623acef83daa.js new file mode 100644 index 000000000..853318b8d --- /dev/null +++ b/pr/619/docs/search.index/623acef83daa.js @@ -0,0 +1 @@ +rn_("AQsA9KETAAABAA8AAQABBAGwQBNWAAFlAaMSAADzAAF0AWAUAAABDQDzdxQAADUAAQABEADzpBQAABgAAQDzgQNrbXMBAAA7MAAAAQAABgACAIsTAADzEwUAI4YCsEAUawABZXMBBAD0xBAAAAEAAQABAPOAA2NydDOAA7BgEOMAAWFscg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/624d4fcb2468.js b/pr/619/docs/search.index/624d4fcb2468.js new file mode 100644 index 000000000..84995a655 --- /dev/null +++ b/pr/619/docs/search.index/624d4fcb2468.js @@ -0,0 +1 @@ +rn_("AYACoFAAABFFoFAAABKVYXUBgwKxABS8AAGw0BSsAAFrbQEEAaCgAAAUx3fytxQAAAEAAQsAOzAAAAEAAAYAAQAcFAYAI4ACoIAAABRHZW9jAwOgYAAAE9plbnABJwwAACOAAqBAAAAQ1W1wAQoA8/4TAAABAHcAE4ACohAAABTHbG/3AAAAhaEAAAAUeASBAzswAAABAAA9AAQAugUFAFEHAACkBzUAhREAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6270a92ca42a.js b/pr/619/docs/search.index/6270a92ca42a.js deleted file mode 100644 index 218309d34..000000000 --- a/pr/619/docs/search.index/6270a92ca42a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsFAP2gABY/ShBAAAAQABAMkAAQABoIAAABS3ZgGWEwAA8wYBc/IIDQAAkwQzAAOgYAAAFJdjaXPy3BEAAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/62eae10a92b2.js b/pr/619/docs/search.index/62eae10a92b2.js new file mode 100644 index 000000000..8eaf726bc --- /dev/null +++ b/pr/619/docs/search.index/62eae10a92b2.js @@ -0,0 +1 @@ +rn_("AQUA9UMQAAABAAEAXwIBAAEEAaAAAAAQ4HP1Ag0AAAEAAQA9AwEAAQIA9asRAAABAAEAAQABAAGAArBgExUAAaAgAAARAG95AQABoMAAABQ6afRsEwAACAAcABsAAQYA9KYUAAABAAEAAQABAgD0/hAAAAEAmgABAAECAaBAAAATQ3I7MAAAAQAABwACAPwQAQCTEQUA84ACYW9nAwAAhrCAE0IAWrCgE7kAAQwwBjswAAABAAAIAAMAIAwAAMYRAwCsEgMA84ICZWlHAQAAhbBwE8kAAaCAAAAUtqBAAAAP+LBABPQACQAA4gYBALIDAYECoCAAABD6sFASvAABYW8BBAGgAAAAE+JzAfkQAABjBAOwUBFrAAFjZXP2CAkAAAEAAQAsAAEAawkBAAA7MAAAAQAAJAAIAEQHBwBDEAIAnBENAMsRAgCkEgEAKhMBAHsTAQASFAIAAQUA8x0TAAABAAEAAQEAOzAAAAEAAAUAAgAEDAMA9hEBAFMAA7AwFFUAAWVwcvTkDwAAAQDuAAEAAQADsEAUGgABoUAAABSKoFAAABHsYmNmAQwHAADjgISxQBSzAAECMBABAYSgsAAAE9ewQBC3AAGwwBQGAAGgYAAAEZIUIAT28wYAAFwJAQA6AS4BFAEBAwA7MAAAAQAABQABANwSBQABAAGgoAAAFEZy9O4PAAABAPYAAQDzgQJncwEHAPVjEwAAAQABAAEAAQABgAKgQAAAEWOwUBFKAAFjafOAAmFvAQABoCAAABGDcvM4DAAAggNrAUOAhKAAAAAUI6AwAAAUI4AFcgAdJwggIQEDArBAEyAAAaAwAAATdmV38o4QAAC7ABODAqBwAAATsGdvAQIA9f8SAAABAPAAgAABABOAArAwEzEBSWlwAQYA860TAAABAAEA8wUCYnMBQBAAAAECAPQdEAAAAQABAAEAI4ACoGAAABKgYmP3XwEAzbBgEN4AAaCQAAASocBOchU6MAAAAQAAAAAAGAAQAAAAGQIaAoIEgwSEBBUHTweCB4MHhAeFB4YHhwf/C3gMCA07EE0QThAbEZsRmRSaFK4UrxQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/63db0133e5a7.js b/pr/619/docs/search.index/63db0133e5a7.js deleted file mode 100644 index c35ca7490..000000000 --- a/pr/619/docs/search.index/63db0133e5a7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcAOzAAAAEAAI0AAgD3EAAACRKMAAEDADswAAABAACMAAEACg6MAAECADswAAABAAAHAAEARgwHAPMAA2JpdDswAAABAACNAAIAnwQAANsEjAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/642b84d73e0d.js b/pr/619/docs/search.index/642b84d73e0d.js new file mode 100644 index 000000000..e08b1cf75 --- /dev/null +++ b/pr/619/docs/search.index/642b84d73e0d.js @@ -0,0 +1 @@ +rn_("AQQBoFAAABRdcwGgEgAAAYICsEASxwABsEASyQABNDYBCwDzxRMAAGwAAQABBgD0sxQAAAEACgABAPMCAXIBDxQAAPMDAWU7MAAAAQAABQACAH8QAwAwEQEA84QDYWVpY4ADoFAAABSWY2V0") \ No newline at end of file diff --git a/pr/619/docs/search.index/64336b5290b0.js b/pr/619/docs/search.index/64336b5290b0.js deleted file mode 100644 index 0fa503537..000000000 --- a/pr/619/docs/search.index/64336b5290b0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ8A9CUUAAABAE8AAQABBAD0gxAAAAEAtwABAAECADowAAABAAAAAAAJABAAAADfEeAR+xL8EukT6hNAFEEUuxS8FPMAAW/yeAkAAAEAU4ADsQAUiQABaG9ww4CEoBAAABNbsIATngABBQAG") \ No newline at end of file diff --git a/pr/619/docs/search.index/6495a83641f9.js b/pr/619/docs/search.index/6495a83641f9.js deleted file mode 100644 index acf34afc2..000000000 --- a/pr/619/docs/search.index/6495a83641f9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABOQsDAR6wABaXTy9xIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PoTAAABAIsABQATAQOwkBRjAAGwUBM/AWdnbHA7MAAAAQAAEgAJAGkQAgDuEQEALhMBAE8TAQCGEwEA6xMBACUUAQA0FAEAdRQBAAGAArAwEecAAbAwEekAAXJ2AQQBsAAStwABZDswAAABAAAFAAIA4xEDAOYSAQC3BQABh7BQErkBFLBgEz0AAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETUTbhMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwGEoFAAABGLoDAAABCkFAEQ8pwHAAABABOAArBgEtsAAWNnE4ADoLAAABQYoEAAAA6cZW9z") \ No newline at end of file diff --git a/pr/619/docs/search.index/64a6287ecae1.js b/pr/619/docs/search.index/64a6287ecae1.js new file mode 100644 index 000000000..a11af1375 --- /dev/null +++ b/pr/619/docs/search.index/64a6287ecae1.js @@ -0,0 +1 @@ +rn_("AQMBgBN9ABD6czswAAABAAAFAAEAXRMFACOCAqCQAAAUYWlzAQEA9CQTAAABAJAAAQAjgAKwoBQKAAFjbgGEArCgFBgAAbCgFBoAAWNyAQIAOzAAAAEAAAYAAQBfEAYAE4ICoCAAABP7ZXUBAgDzzhEAAAEAAQABgAKwIBQ9AAGgYAAAE4xvdmOBA6AQAAATRGFjcwEDADswAAABAAAFAAEA2gwFAAEBAPMhCQAAAQABAAEBAPT+EAAAAQCaAAEAU4ADoMAAABRtbnB1AYACsDAQGwABoWAAABSlYWUBgQKwQBLHAAGwQBLJAAE0NgEFAaBQAAAUJmjyuhIAAAEAAQUA9HUQAAABALMAAQBzgISwMBNwAAEBoAQBCADzbBMAAAgAHAATgAKwQBHyAAFhZQEKAPPFEwAAbAABAAEAAaAgAAAQl3IBYBEAAAEAAPTJEwAAAQBLAAEApwEAgIWgMAAAEPugEAAAERsJICEBCQGgQAAAFGRl8oYUAAABAEOAhKAgAAAUcqCQAAATyKEwAAAUhRBJAAECAPRYEwAAAQCYAAEAE4ACsEATJgABaXkBAQKgMAAAEvygQAAAE0NncjswAAABAAAHAAIA/BABAJMRBQABgAKwABPjAAGwABPlAAE0NgEGAPSzFAAAAQAKAAEA8wICcnYBDxQAAPMCAWU7MAAAAQAABQACAH8QAwAwEQEA84ACZHTnrT8AEqAwAAARHKBAAAAM8bDwFLAAAbBwE40AATBhYmNlZ2hpa2xub3Byc3R1djswAAABAAAaAUYAwQQAAKgFAACvBQAAsQUFAMUGAAAmBwAATAcCAFwHAABuBwUAdQcAANoHAAD/BwEABQkBAAsJAQAYCQAAdgkBAHoJjAAEDAMAEwwAABcMAwAkDAAAXQwAAGoMAACyDwEA3A8BAPQPAABYEAAAhRABAJkQAACmEAEA7xABAPMQAwAGEQEAPREBAF4RAAB7EQIAqhEAAMoRAADsEQAA8BEBAPYRAQACEgQApxIAALYSAQC5EgAAxRIBANcSAgANEwMAIhMBAC8TAQA2EwEAPBMBAD8TAABCEwAAVBMAAGoTAQCJEwEAmBMEALMTAQDGEwEAyRMBAM8TAQDaEwAAFRQCABwUBwA7FAEARxQAAF4UAQCIFAEAxxQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/652b221c4360.js b/pr/619/docs/search.index/652b221c4360.js new file mode 100644 index 000000000..059db9199 --- /dev/null +++ b/pr/619/docs/search.index/652b221c4360.js @@ -0,0 +1 @@ +rn_("AQEA9foHAAABAAEAAQABAAEAAqAwAAARHKCQAAATkDBo9QISAACWAQEAAQABABOAAqAwAAAP0GRyIwKEsBAI/QM+sCAMCAELoDAAAA/1EgAY9ZsFAAAwAAEAAQABADOAhLCgEtAAAbBAD9oAARBJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/65463ff680b5.js b/pr/619/docs/search.index/65463ff680b5.js new file mode 100644 index 000000000..3e55d274e --- /dev/null +++ b/pr/619/docs/search.index/65463ff680b5.js @@ -0,0 +1 @@ +rn_("AQMBsEARYQABZQGXDgAAAQUAOzAAAAEAAAYAAQBfEAYAAQMAOzAAAAEAAAUAAQDaDAUA8wACcHM6MAAAAQAAAAAADAAQAAAAqAXFBhgJXQxqDAYRBxG2ErcSDRMOEw8TEBMzAAOwUA/UAM9kcHI7MAAAAQAADwAGAKAEAABoBQMAwQ8AAOIRAwCxEgMA5RIBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6547187e7e81.js b/pr/619/docs/search.index/6547187e7e81.js deleted file mode 100644 index 762fe3f10..000000000 --- a/pr/619/docs/search.index/6547187e7e81.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHAR3wABsCAP6gDwaHkBBQD0Cg0AAAEAPQMBAAEAAPRkDAAAAQABAG4AAQIAOjAAAAEAAAAAAAkAEAAAAN8P4A/VEJIR8RLyEu8TeBStFK4UAQMA8yEJAAABAAEA1wMAAIagQAAAEfoYQAc6MAAAAQAAAAAAFwAQAAAAagdrB/kHLgliCWMJCQ3MD80P7Q+YEJ8QoBChEKIQ4RDiEBkRGhGWEu0T7hMZFBoU") \ No newline at end of file diff --git a/pr/619/docs/search.index/657095ac6c20.js b/pr/619/docs/search.index/657095ac6c20.js new file mode 100644 index 000000000..4b3ba6f3a --- /dev/null +++ b/pr/619/docs/search.index/657095ac6c20.js @@ -0,0 +1 @@ +rn_("AQsBoEAAABQ5ZfJnFAAAAQABBQD0AxIAAAEAAQABAAGDArAAEO8AAbBQE3sAAWR3E4ACoKAAABPvZXYBAgD0ChEAAAEAkgEBAAEAAPTyDwAAAQD0AAgBI4ICsFATUgABZXMBAgD0JBMAAAEAkAABAAEDAPRYEwAAAQCYAAEA84UCYnUBAgD0dREAAAEAfAEBAPOAAmls8wADYnR1OjAAAAEAAAAAAA8AEAAAAHQHAQgCCAMIBAgaEOAQrBMwFH0UfhSAFI0UjhS1FLkUAQwA8xIUAAABAAEAAYACsAAJHwABoCAAAA0HZG4BBgD0IhMAAAEAkAABAPMDAWL0CBEAAAEAkgEBAJcGAACHsEAP8AABoHAAABKnsJATUAABOAkDOjAAAAEAAAAAACQAEAAAAMMFxAXFBcYFNgc3BzcM/Az9DP4MAg0DDQQN6A/pDzwQPRBBEEIQXxBgEGEQYhBjEGQQZRCoEK0Q2BDZEIwTsBPXE3MUfxShFLIUAQMA9DYTAAABAFEBAQDzgAJjbXcBAIDFsYAUwgABQIEECA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/65d7f0f56d36.js b/pr/619/docs/search.index/65d7f0f56d36.js new file mode 100644 index 000000000..cf79710c8 --- /dev/null +++ b/pr/619/docs/search.index/65d7f0f56d36.js @@ -0,0 +1 @@ +rn_("AYACsFAUFQABoAAAAAkQY3QBAQD0kRMAAAEAAQABAAEDAPTzDAAA2AagAAEAAYACoBAAAAx7oFAAABKiY2QBAgDzBAkAAE4DAQDzAAFt86UEAADIAAEAAYECoBAAABNEoHAAABOMYWPzAAFy81wHAABOCiAAZw8AgIiwMA/UAM+gMAAAFJUpMCM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/65fced5fb18c.js b/pr/619/docs/search.index/65fced5fb18c.js new file mode 100644 index 000000000..fce820bb0 --- /dev/null +++ b/pr/619/docs/search.index/65fced5fb18c.js @@ -0,0 +1 @@ +rn_("AYQCsAARfgABsAARgAABNDbzAgFh8nkMAAABAAEAAPbFEgAAAQBwAAEAUQEBAPMAAWTz1BIAAAEAqgBjgAOgIAAACP9hZW8=") \ No newline at end of file diff --git a/pr/619/docs/search.index/6635658ace13.js b/pr/619/docs/search.index/6635658ace13.js deleted file mode 100644 index f13b98dbf..000000000 --- a/pr/619/docs/search.index/6635658ace13.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9asRAAABAAEAAQABAAGAArBgExYAAaAgAAARAG95AQABoMAAABQ7afRtEwAACAAcABsAAQMA9JITAAABAAEAAQABBgD0pxQAAAEAAQABAAECAPT+EAAAAQCaAAEAAQIBoEAAABNEcjswAAABAAAHAAIA/BABAJMRBQDzgAJhb2cHAACHsIATQwBasKATugABDDAHOzAAAAEAAA4ABACTBAUAIAwAAMYRAwCtEgMApwAAgIWg8AAAE82wUBBPAAGgkAAAEYqUgQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/664a448ebb15.js b/pr/619/docs/search.index/664a448ebb15.js deleted file mode 100644 index 94f81fb9c..000000000 --- a/pr/619/docs/search.index/664a448ebb15.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsEATbwABoMAAABQvZW8BAgD02BEAAAEAAQABABMAA7AgEdwAAbCAFEAAAWFzdAHhDAAAAQQA8/8PAAABAAEAs4CEsEATggABQQAG") \ No newline at end of file diff --git a/pr/619/docs/search.index/665c853e8913.js b/pr/619/docs/search.index/665c853e8913.js deleted file mode 100644 index 2f90e9176..000000000 --- a/pr/619/docs/search.index/665c853e8913.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgCMEwAA9BMFACOIArBAFGwAAWVzAQQBsDATXAABY/OGEQAAAQABAAEFADswAAABAAAIAAMA/RECAAITBAApFAAA8wEDY2Vw884MAAABAAEAAQIA9h4JAABXAA4HAQC3AAEA84ACbnI=") \ No newline at end of file diff --git a/pr/619/docs/search.index/66c8d3a8ed30.js b/pr/619/docs/search.index/66c8d3a8ed30.js deleted file mode 100644 index d231e5eaa..000000000 --- a/pr/619/docs/search.index/66c8d3a8ed30.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9AoRAAABAJMBAQAjgQKgYAAAE0BiaQEAAPTyDwAAAQD0AAkBI4ICsFATUwABZXMBiQKwIBRxAAGgMAAAFHtpcAECAPQlEwAAAQCQAAEAAQMA9FkTAAABAJgAAQDzhQJidQECAPR1EQAAAQB9AQEA84ACaWy3AQAAhaAgAAATLRIBDDowAAABAAAAAAAUABAAAAB0BwEIAggDCAQIFQxODE8MUAxRDBoQ4BCtEzEUfhR/FIEUjhSPFLYUuhQBBQDzExQAAAEAAQBDhgOwkBSYAAGgAAAAErpiZHcBgAKwAAkfAAGwIA0HA2VkbgEDAPPwDwAAAQAHAQECAPYeDAAAAQCPAwEA3wMBAAEAAPQ9CQAAAQABAAEAAQAAOzAAAAEAAAYAAgCMEwAA9BMFACOBArBAFGwAAWVz84ADZXh5AQAA9DkJAAABAAEAAQBDgAOgQAAAFJawIBMhAAFlcngBgAKgQAAADPGwQBAbAAFnbCcaAADJoJAAABNusMATuAABoBAAABFxoDAAABQKsEAM6QABAEegCzowAAABAAAAAAAJABAAAABwBXEF7wzwDAUN7A9GEEcQGBMZEwEGAPQjEwAAAQCQAAEA8wMBYvQIEQAAAQCTAQEAtwwAAImgcAAAEqiwkBNRAAGwYBA+AAGgMAAAE3c4iRM6MAAAAQAAAAAALwAQAAAAwwXEBcUFxgU2BzcHAQkCCQMJMwk0CSMMNwz8DP0M/gwCDQMNBA3oD+kPPBA9EEEQQhBfEGAQYRBiEGMQZBBlEIcQjhCoEK0Q2BDZEEgRSRH9Eo0TsRPYE3QUgBSiFLMU") \ No newline at end of file diff --git a/pr/619/docs/search.index/66d062150add.js b/pr/619/docs/search.index/66d062150add.js deleted file mode 100644 index 0a75a46fc..000000000 --- a/pr/619/docs/search.index/66d062150add.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoFAAABFFoFAAABKWYXUBgwKxABS9AAGw0BStAAFrbQEEAaCgAAAUyHfyuBQAAAEAAQsAOzAAAAEAAAYAAQAdFAYAI4ACoIAAABRIZW9jAwOgYAAAE9tlbnABJwwAACOAAqBAAAAQ1W1wAQoA8/8TAAABAHcAE4ACohAAABTIbG/3AAAAhaEAAAAUeQSBAzswAAABAAA9AAQAugUFAFEHAACkBzUAhREAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6707166781ac.js b/pr/619/docs/search.index/6707166781ac.js new file mode 100644 index 000000000..da36cc8df --- /dev/null +++ b/pr/619/docs/search.index/6707166781ac.js @@ -0,0 +1 @@ +rn_("AQcA9d0TAAABAAEAegABAAEHAPPKEAAAAQABAAGAAqAAAAAHXKAQAAAJEGR48wEBZfIbEAAAAQDnAAAAhbBgDO8AAbBADGAAATIIAfTJBAAAiQLbCQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6733f8336dde.js b/pr/619/docs/search.index/6733f8336dde.js new file mode 100644 index 000000000..7552094a6 --- /dev/null +++ b/pr/619/docs/search.index/6733f8336dde.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAYAAgC6BQUAhREAAAEAAPQoEwAAAQBYAQEA8wQBczswAAABAAANAAIAoxMHAJsUBQBHAAABhqCAAAATg7EAFKoAAbBAEuMAAbCAFLoAAbBQEyoAARUAFvSYDgAAAQABAAEAAQUA8/8PAAABAAEAY4ADsEAQjAABbW5vAQEA9IgQAAABAAEAAQAjgQKwAAzpAAFzdfMAAmFpOjAAAAEAAAAAAAcAEAAAAGkH4Q/CEMMQkROSE5MTlBMBgAOwABPjAAGwABPlAAGwcBReAAE0NmEBBAD0sxQAAAEACgABACOBAqBAAAARXm1wAQIAOzAAAAEAAA4ABABsBwEADA0BAE4RCQCMEQAAAQEAOzAAAAEAAAgAAwDWEgAASRMAAMAUBgABAQA7MAAAAQAACgADAHIRAgC7EwMAphQDACOAAqAwAAAQWGRn1wMAAMaggAAAErBARoAIOzAAAAEAABgACQD2DwEAFhEBAEoRAQBaEQMA0REFAL8TAwAPFAAAbhQBAKIUAQABAwD2HgkAAFcADgcBALcAAQAjgAOwcBSuAAGwcBQ7AAFlb3IBBAGwsBSIAAFs9AoNAAABAD0DAQABAgA7MAAAAQAADAADAP4IAADREwUAjxQFAAEBAPM+EAAAAQBgAiOAAqCwAAAUOmd6AQIAOjAAAAEAAAAAAAkAEAAAAN4R3xH6EvsS6BPpEz8UQBS6FLsU8wABb/J4CQAAAQABBQD06A8AAAEA7wABAIMAhKBAAAAM/7BwE24AAbAgDHwAARAFAjswAAABAAAJAAMAuQQDAH8FAgDOEQIAAYACoCAAABElsCAUOwABZHQBhAKwsBSLAAGwABPbAAFhc9OAhKCwAAAUckAoBAGAAqAwAAAR+LBgD/0AAWhyR/8BAM2gIAAABZ6gIAAABZ+wcBPPAAEDZzQHOzAAAAEAADoAGQCcBAAA1AQFAG4JAADTDAAAtg8DAK4QAwBtEQAA1hIAAOkSBQBJEwEAbBMAAHQTAACEEwAAkBMAAKETAQCrEwAArRMCALETAQAIFAAADhQAABoUAQA3FAEATRQFAGEUAADAFAYA") \ No newline at end of file diff --git a/pr/619/docs/search.index/67b1ae83fd68.js b/pr/619/docs/search.index/67b1ae83fd68.js deleted file mode 100644 index 492e5f3bc..000000000 --- a/pr/619/docs/search.index/67b1ae83fd68.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBsEARYQABZQGXDgAAAQUAOzAAAAEAAAYAAQBfEAYAAQMAOzAAAAEAAAUAAQDaDAUA8wACcHM6MAAAAQAAAAAADAAQAAAAqAXFBhgJXQxqDAYRBxG3ErgSDhMPExATERMzAAOwUA/UAM9kcHI7MAAAAQAADwAGAKAEAABoBQMAwQ8AAOMRAwCyEgMA5hIBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/68884d4c1398.js b/pr/619/docs/search.index/68884d4c1398.js deleted file mode 100644 index 00c26d002..000000000 --- a/pr/619/docs/search.index/68884d4c1398.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9BYRAAABAL8AAQATgQOgAAAAEV6xIBSjAAFhZG4BBQD0iBAAAAEAAQABAAEUAPXDFAAAAQABAAEAAQABBQGwgBRfAAF2OzAAAAEAAAgAAgDREQQAwBMDACOAArBwEfcAAWJkVwIAAYawwBOKAAGgoAAAE62gkAAAE3YF4AL1GAcAAAEAAQDoCJQEAQYA89USAAABAKoAAQABoGAAAA/tcgGOBAAA1wEAgMWgMAAADBIAAIoK") \ No newline at end of file diff --git a/pr/619/docs/search.index/68ece63de0b2.js b/pr/619/docs/search.index/68ece63de0b2.js new file mode 100644 index 000000000..76547c121 --- /dev/null +++ b/pr/619/docs/search.index/68ece63de0b2.js @@ -0,0 +1 @@ +rn_("AQMA9gUNAADnAloAAQDQAgEAAQQAOzAAAAEAAAoABACPEAUA0hIBADITAQBYFAAAAYYCoAAAABNUoAAAABNVZHLzAgF2AYATAADzgAJlbycBAADHoDAAAA/roHAAABKioIAAABQnsNATxgABoLAAABQnQEUICTswAAABAAAJAAMAwAUCACEHBABeDAEAI4ACf1YlaUD0ZHIBAAA6MAAAAQAAAAAACgAQAAAAVwlYCSEQbhNvE58ToBNMFKQUvBS9FBOAAqAwAAAQpWx0w4AEoAAAABCVoAAAABCWNDZhZQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/69477c6171ff.js b/pr/619/docs/search.index/69477c6171ff.js deleted file mode 100644 index 65d0013ab..000000000 --- a/pr/619/docs/search.index/69477c6171ff.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9MwSAAABAKYAAQABCAD0iBMAAAEAiAABADMBA7BAE1cAAWFiZTowAAABAAAAAAAMABAAAAAzBzQHNQf4DPkMyw85EIgQiRCKEIsQpBJ2EwEAADswAAABAAAgAA4AwgQBAIgFCQAsCQEAMQwBAOkMAQCcDgAAvQ8DANMPAADyDwEA5xABAPoQAACNEQAA6xEBAPARAAABgQKwABF+AAGwABGAAAE0NiOAArCAFIwAAW9wAQABsEATUwABZfOJEQAAWwEBALcBAICFoGAAABEmEAEL") \ No newline at end of file diff --git a/pr/619/docs/search.index/6a8b122a8833.js b/pr/619/docs/search.index/6a8b122a8833.js deleted file mode 100644 index 5b40cac47..000000000 --- a/pr/619/docs/search.index/6a8b122a8833.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQAUvQABsNAUrQABa20BBAGgoAAAFMh38rgUAAABAAELADswAAABAAAGAAEAHRQGACOAAqCAAAAUSGVvYwQDoGAAABPbZW5wAScMAAABCgDz/xMAAAEAdwATgAKiEAAAFMhsb3cAAACFoGAAABKWoQAAABR5BIEDOzAAAAEAAD0ABAC6BQUAUQcAAKQHNQCFEQAAQ4ADsIARhAEjoAAAAAIXZGt0") \ No newline at end of file diff --git a/pr/619/docs/search.index/6af725c39cbd.js b/pr/619/docs/search.index/6af725c39cbd.js new file mode 100644 index 000000000..d23e7504b --- /dev/null +++ b/pr/619/docs/search.index/6af725c39cbd.js @@ -0,0 +1 @@ +rn_("AYkCsCAUcAABoDAAABR6aXATAAOgIAAAEyyggAAAEz9laXX1FQwAADkAAQABAAEAAYYCsJAUlwABoAAAABK5YmQBgAKwMBMgAAGgMAAAEPhydtcAAAKFoDAAABBsoDAAABN2EAETOjAAAAEAAAAAAAkAEAAAAAEJAgkDCTMJNAmHEI4QSBFJEfwSAQMBsDATOgABc/PKEAAAAQABAAEAADswAAABAAAKAAMAchECALsTAwCmFAMAlwEAAIWgIAAABa+wIAgFAAFQGAH1fgwAAAEAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6b3f760f828d.js b/pr/619/docs/search.index/6b3f760f828d.js deleted file mode 100644 index 87968b526..000000000 --- a/pr/619/docs/search.index/6b3f760f828d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9IgQAAABAAEAAQABEwD1wxQAAAEAAQABAAEAE4ACoMAAABNKYW8BAgKgsAAAFFigsAAAFFljc/PPEAAAAQBfAAGBArBQEfMAAaDAAAAUJ2hp84ACZWkjgAKwsBOKAAFpdAEFAbCAFF8AAXY7MAAAAQAACAACANERBADAEwMAI4ACsHAR9wABYmR3AgAAhqCgAAATraCQAAATdgXgAvUYBwAAAQABAOgIlAQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/6b4af5b9cce5.js b/pr/619/docs/search.index/6b4af5b9cce5.js deleted file mode 100644 index 1a304fd0a..000000000 --- a/pr/619/docs/search.index/6b4af5b9cce5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA834UAAABADsAAYACoEAAABNbsCAUGQABaGkBDAGgoAAAFMh38rgUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjgABoGAAABS2ZHM3AwCDhqBAAAAUYbBgFDEAUAKQDgESAbAAFIIAAXM7MAAAAQAABQABAJwUBQABAMagUAAAEuOgAAAAEJmwIBFMAAGgUAAAEfmhAAAAFJegQAAAFDsAAwILOzAAAAEAABUABwCsBQAANgwAAOsMAAAKEA0AcBEAAPkSAQA2FAEAAQEBsLAUiQABbDswAAABAAAMAAMAJwcIAAoNAQBIEAEAAQEBoDAAABEoaPMHCQAALgCsCAECAPTYEQAAAQABAAEAE4ECsCAR3AABYXPzggJub/cBAICHoCAAAAWroEAAAAwdFQEH") \ No newline at end of file diff --git a/pr/619/docs/search.index/6b9ac143a49f.js b/pr/619/docs/search.index/6b9ac143a49f.js deleted file mode 100644 index bd336eb0c..000000000 --- a/pr/619/docs/search.index/6b9ac143a49f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQAzAwOwYBOFAIphcnXzexAAAHoCAQAjgAKAEXsAEAFkcg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6b9afa46ea73.js b/pr/619/docs/search.index/6b9afa46ea73.js new file mode 100644 index 000000000..2871f08eb --- /dev/null +++ b/pr/619/docs/search.index/6b9afa46ea73.js @@ -0,0 +1 @@ +rn_("AQIBsEAUewABdDswAAABAAANAAYA/RIDAGgTAQDYEwEA7xMBAHAUAQCXFAEAE4ACsDATMQFJaXABBQDzrRMAAAEAAQATgAKgMAAAFAhleVMBA7BwFBUAAWJlcwFAEAAAE4ADsDAUiwABsCAG/wABZWxz") \ No newline at end of file diff --git a/pr/619/docs/search.index/6b9f939265d9.js b/pr/619/docs/search.index/6b9f939265d9.js deleted file mode 100644 index 5e6d74298..000000000 --- a/pr/619/docs/search.index/6b9f939265d9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAUAAgCDDAMAGhMBAAECAPN7EQAAAQABAAEGAPSnFAAAAQABAAEA8wYBbfStEgAAAQABAAEA84ACbnbzgAJhaQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6c3a7ed9893f.js b/pr/619/docs/search.index/6c3a7ed9893f.js deleted file mode 100644 index 409b82f8f..000000000 --- a/pr/619/docs/search.index/6c3a7ed9893f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9qATAAABAKwAWAAYAAEA8wEBaQFhCQAAAQAA9WQJAAABAAEAAQABAEcBAIDGbZB9T07NoKAAABSWsGAUBQABoBAAAAk4AAogig==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6c65d8f022b6.js b/pr/619/docs/search.index/6c65d8f022b6.js new file mode 100644 index 000000000..28094628c --- /dev/null +++ b/pr/619/docs/search.index/6c65d8f022b6.js @@ -0,0 +1 @@ +rn_("AQEAOzAAAAEAAAcAAQBZCQcAAQIA90wQAADbALYCAQABAHoAAQATgAKwMBDoAKVpdPMAAXPyixQAAAEAM4ADsRAT/AABZG5w") \ No newline at end of file diff --git a/pr/619/docs/search.index/6c6fd1c60881.js b/pr/619/docs/search.index/6c6fd1c60881.js new file mode 100644 index 000000000..ae35567ec --- /dev/null +++ b/pr/619/docs/search.index/6c6fd1c60881.js @@ -0,0 +1 @@ +rn_("AQUA9EgUAAABAAEAAQABBQD0OBMAAAEAlAABAPMAAmN19VYQAAABAMYAAQABAAEJAPN9FAAAAQA7AAENAaCgAAAUx3fytxQAAAEAAYECsIAUjQABoGAAABS1ZHM3AQCEhaBAAAAUYLBgFDAAUAKQCiOAAqBwAAARX2RyAQsBoEAAABRkZfKGFAAAAQATgAKwMBByAAFkcvMCAWX04wcAAAEAAQABACOAArAgDAsAAWV5AQoA88ASAAABAAEAAQsAOzAAAAEAAAcAAQCjEwcAAQIA9AIUAAABAFAAAQC3AACAhbBwEvYAAbDQFKoAAWAgBgEGAPPNEgAAAQABAAEDAbBAFHsAAXTy2BMAAAEAI4UCoEAAABQIYnMjAgOwQBEDAAGgUAAAEXBhYmb3DQkAAAEASAByBwEAYgABAPOAAmlwAQQA828QAAABAAEA8wABcDswAAABAAAMAAEA4wYMACOAA6AwAAAMG7BwE7cAAWFlafOAA2RtbgEAADowAAABAAAAAAAHABAAAAAYCWoMthK3Eg0TDhMPExAT8wIBZDswAAABAAAJAAMA4hEDALESAwDlEgEAI4ACoJAAABRXaW8BgAOwMBNqAAGAE60AEAGwUBEgAAFjc3jzAAFlAcoEAADnFQCAiaAAAAAMe6BAAAAM1LBADNUAAZBIXQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6ce4893b3d85.js b/pr/619/docs/search.index/6ce4893b3d85.js deleted file mode 100644 index c9473713f..000000000 --- a/pr/619/docs/search.index/6ce4893b3d85.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABNLc/TSDwAA8gMBAAQAAQECsGAUPgABsEAUfAABZHQ7MAAAAQAADQAGAP4SAwBpEwEA2RMBAPATAQBxFAEAmBQBAAEBA7BwEgEAAbCAEtsAAYATfgAQ+m1uczswAAABAAALAAIA9wgFAF4TBQCjgISwsBPHAAGxcBS7AAEIQIIBgAKwMBSvAAGxABQ+AAFjbmcBAACFXAgcqo0jsDATMgFJEYEIOzAAAAEAAAYAAgCMEwAA9BMFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6d4789e20b5d.js b/pr/619/docs/search.index/6d4789e20b5d.js deleted file mode 100644 index ed02c1999..000000000 --- a/pr/619/docs/search.index/6d4789e20b5d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ0A9d4TAAABAAEAegABAAEHAPPGEwAAbAABACOAAqEQAAAUGG5yAQcA9LYRAAABAAEAAQAzAASgIAAACS6w4BQNAAExZWlyOjAAAAEAAAAAAAkAEAAAAF4EXwRQBxAJcAxxDHIMcwxYEVkRAQIA9AoRAAABAJMBAQABAwD0dREAAAEAfQEBAPMAAmJ1ARoQAAABAwD0CBEAAAEAkwEBAPOEAmRzAQIA8xIJAAABAFgA84ACaXQBGADzxRQAAAEAAQAjgQKwwBPcAAFjbQENAbBAFGYAAWX1KhQAAAEAAQABAAEAE4ICsAARIAABa3MBBAD0rhAAAAEAAQABAAGBAqAgAAARG7BAE3EAAWVp84ICZXQBBAGwYBLGAAFy9CUMAAABAPIDAQDzgANhZW8BCQD28RIAAAEA/QCJADUAAQATgAKwYBDIAAFkbgEGADswAAABAAAFAAIA8xADAIoTAQABAwGgcAAAEy1n9F0HAAABAAsCAQABCQDzfhQAAAEAOwABgQKwgBSOAAGgYAAAFLZkcxcBAIiFsNAUuAABoEAAABRhsGAUMQBQApAKAQQA9MoTAAABAEsAAQBTgAOwkBSxAAFlaG8BAAGgQAAAEYJlAcoPAAAjgQKwUBEtAAFrdHfsAwCOoZAAABSmsLATOwABoKAAABLwsVAUrwAB/cEPOzAAAAEAACEACACCAAAAiAADAHIFAQA5BwcAOQkHAEYMBwBTEAEAmxIAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6d907d4f4ecd.js b/pr/619/docs/search.index/6d907d4f4ecd.js deleted file mode 100644 index 1eb3ac99b..000000000 --- a/pr/619/docs/search.index/6d907d4f4ecd.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9LARAAABAAEAAQABCgD0wBMAAAEAAQABAPOBAm10AQYA83IRAAABAAEAAYICsGATRgABsNAUaAABaXITgAKwEAzsAAFlaQEFAPQDFAAAAQBQAAEA8wQBY/IHEwAAAQABBQDz2BIAAAEAAQDzggJmdAEAAbAAFF8AAWT0AAwAAAEAAQABAPOBAmVpNwYAAImxMBSHAAGgYAAAEXGgUAAAEQWwkBMYAAGwQBEBAAG1EAcBOxQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6e0237fddaf9.js b/pr/619/docs/search.index/6e0237fddaf9.js deleted file mode 100644 index 9384cdb15..000000000 --- a/pr/619/docs/search.index/6e0237fddaf9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9LARAAABAAEAAQABAQDzzhEAAAEAAQATgAIXkhan0y5lcwEKAPTAEwAAAQABAAEAAYACsCAUPgABoGAAABONb3YBgAKwMBLGAAGgAAAAE0VjZPOAhQUQBg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6e36418a6b2a.js b/pr/619/docs/search.index/6e36418a6b2a.js deleted file mode 100644 index 21f033c29..000000000 --- a/pr/619/docs/search.index/6e36418a6b2a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9g4NAAABADsDAQAuAQEAAQoA89USAAABAKoAAQEA9yUJAAABAFcHAQBzAAEAFgEjgAKwYBPtAAFpbwECAPTLDAAAAQBKBgEAAQUA9AMUAAABAFAAAQD3CAAAiLCQE7oAAaAgAAAMzbCQEfsAAQTcAzowAAABAAAAAAAIABAAAACUBRYJFwlnDGgMARECEQcTCBM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/6e756b7be8af.js b/pr/619/docs/search.index/6e756b7be8af.js deleted file mode 100644 index ee713d762..000000000 --- a/pr/619/docs/search.index/6e756b7be8af.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9AMUAAABAFAAAQDzAwFj8gcTAAABACOAArBwFLsAAWhvAYICsAAS5AABsAAR6wABZXNDAAOgoAAAFFmgIAAAE5BlaXTy9xIAAAEAAQIAOzAAAAEAAAYAAQBkEQYAAQIBoEAAABQ6ZfJoFAAAAQDzgAJpbwEIAPT6EwAAAQCLAAUAEwEDsJAUYwABsFATPwFnZ2xwOzAAAAEAABIACQBpEAIA7hEBAC4TAQBPEwEAhhMBAOsTAQAlFAEANBQBAHUUAQABgAKwQBK5ARSgIAAAEShhaQEDAPPYEgAAAQABACOBArAwFAsAAWNpAQAA9CkTAAABAFgBAQDzAwFzOzAAAAEAAA8AAwDpEQEApBMHAJwUBQABAwD15xEAAAEAJAEBAGEB84ACcnYBAAA7MAAAAQAABQACALcSAQAOEwMA8wIBZDswAAABAAAJAAMA4xEDALISAwDmEgEAI4ACoJAAABRYaW8TgAKw8BSrAAFsbwEFAPR0FAAADAAiABEAI4ACoGAAABOEZ3MjgAKwkBRWAAFibPfHAACNsGAUjAABsHAT/QABsGATPQABsFATKwABtckXOjAAAAEAAAAAACAAEAAAALcFBwk1CWIMYwziDOMM5AyYDpkOmg6bDp0Ong79D/4P/w8AEAEQzxDQEAwRLxGOEY8RkBGREeERNRNME00TbhMoFA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6e951ec52a5e.js b/pr/619/docs/search.index/6e951ec52a5e.js deleted file mode 100644 index 8af267a4e..000000000 --- a/pr/619/docs/search.index/6e951ec52a5e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9D0HAAABAAEAAQABAQGgQAAAEYlz9TkMAAAmBUsBAQABABOCAqAgAAANEGVyI4ADoEAAAAw4sDAJLAABZW90AQAA9DkHAAABAAEAAQABAgD0ohMAAAEADwABABOAArBAFFwAAWJ284ACb3gBCgD13hMAAAEAAQB6AAEAAYECoCAAABD6sFASvQABYW8BBAGgAAAAE+NzAfkQAABjAwOwUBFrAAFjZXP2CAkAAAEAAQAsAAEAbAkBAQA7MAAAAQAABQABANoMBQAjgAKwMBM/AWdydPMAhgHAB/LwAQAAAwY=") \ No newline at end of file diff --git a/pr/619/docs/search.index/6ef33c9e5294.js b/pr/619/docs/search.index/6ef33c9e5294.js new file mode 100644 index 000000000..fd2d14828 --- /dev/null +++ b/pr/619/docs/search.index/6ef33c9e5294.js @@ -0,0 +1 @@ +rn_("AQEBoEAAABGJc/U5DAAAJgVKAQEAAQATggKgIAAADRBlcgECAPTuDwAAAQD2AAEAI4ECoBAAAAw4ZWkTgAKg8AAAFCducjMAA7AwCSwAAWVvdAHdEQAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6efd68c23a2e.js b/pr/619/docs/search.index/6efd68c23a2e.js new file mode 100644 index 000000000..40758a3f4 --- /dev/null +++ b/pr/619/docs/search.index/6efd68c23a2e.js @@ -0,0 +1 @@ +rn_("AYICoFAAABLioQAAABSWY3QjAAKwQA/VAAFldTswAAABAAA3ABYAyAYBANgMAQD6DAEA2g8BAFkQBQCPEAUADREBAGsRAQD8EQIA0BIDAAETBAAyEwEAOBMBAEcTAQDNEwEA4BMBAP4TAQACFAEAKBQAAFMUAQBXFAEAdhQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/6f0652676cb6.js b/pr/619/docs/search.index/6f0652676cb6.js deleted file mode 100644 index bac86c78c..000000000 --- a/pr/619/docs/search.index/6f0652676cb6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ0A9d4TAAABAAEAegABAAECAPQKEQAAAQCTAQEAAQMA9HURAAABAH0BAQDzAAJidQEaEAAAAQMA9AgRAAABAJMBAQDzhAJkcwECAPMSCQAAAQBYAPOAAml0ARgA88UUAAABAAEAI4ECsMAT3AABY20BBQGwYBLGAAFy9CUMAAABAPIDAQABCQD28RIAAAEA/QCJADUAAQATgAKwYBDIAAFkbgEDAaBwAAATLWf0XQcAAAEACwIBAAEJAPN+FAAAAQA7AAGBArCAFI4AAaBgAAAUtmRzFwEAiYWw0BS4AAGgQAAAFGGwYBQxAFACkApnugAAjLBwES0AAbCwEzsAAaCgAAAS8LFQFK8AAbDwFA0AAW3BD/SIAAAAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6f4ddc2fa0ef.js b/pr/619/docs/search.index/6f4ddc2fa0ef.js deleted file mode 100644 index e9a38ea01..000000000 --- a/pr/619/docs/search.index/6f4ddc2fa0ef.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAYAAgC6BQUAhREAAAEAAPQpEwAAAQBYAQEA8wQBczswAAABAAANAAIApBMHAJwUBQBHAAABhqCAAAAThLEAFKsAAbBAEuQAAbCAFLsAAbBQEysAARUAFvSYDgAAAQABAAEAAQUA8/8PAAABAAEAY4ADsEAQjAABbW5vAQEA9IgQAAABAAEAAQAjgQKwAAzpAAFzdfMAAmFpOjAAAAEAAAAAAAcAEAAAAGkH4Q/CEMMQkhOTE5QTlRMBgAOwABPkAAGwABPmAAGwcBRfAAE0NmEBBAD0tBQAAAEACgABACOBAqBAAAARXm1wAQIAOzAAAAEAAA4ABABsBwEADA0BAE4RCQCMEQAAAQEAOzAAAAEAAAgAAwDXEgAAShMAAMEUBgABAQA7MAAAAQAACgADAHIRAgC8EwMApxQDACOAAqAwAAAQWGRn1wMAAMaggAAAErFARoAIOzAAAAEAABkACQD2DwEAFhEBAEoRAQBaEQMA0REGAMATAwAQFAAAbxQBAKMUAQABAwD2HgkAAFcADgcBALcAAQAjgAOwcBSvAAGwcBQ8AAFlb3IBBAGwsBSJAAFs9AoNAAABAD0DAQABAgA7MAAAAQAADAADAP4IAADSEwUAkBQFAAEBAPM+EAAAAQBhAiOAAqCwAAAUO2d6AQIAOjAAAAEAAAAAAAkAEAAAAN8R4BH7EvwS6RPqE0AUQRS7FLwU8wABb/J4CQAAAQABBQD06A8AAAEA7wABAIMAhKBAAAAM/7BwE28AAbAgDHwAARAFAjswAAABAAAJAAMAuQQDAH8FAgDOEQIAAYACoCAAABElsCAUPAABZHQBhAKwsBSMAAGwABPcAAFhc9OAhKCwAAAUc0AoBAGAAqAwAAAR+bBgD/0AAWhyR/8BAM2gIAAABZ6gIAAABZ+wcBPQAAEDZzQHOzAAAAEAADoAGQCcBAAA1AQFAG4JAADTDAAAtg8DAK4QAwBtEQAA1xIAAOoSBQBKEwEAbRMAAHUTAACFEwAAkRMAAKITAQCsEwAArhMCALITAQAJFAAADxQAABsUAQA4FAEAThQFAGIUAADBFAYA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6fe4512f74c9.js b/pr/619/docs/search.index/6fe4512f74c9.js new file mode 100644 index 000000000..62d359d36 --- /dev/null +++ b/pr/619/docs/search.index/6fe4512f74c9.js @@ -0,0 +1 @@ +rn_("AQAA9iARAAABAJIDAQAKAAEAAQAAOzAAAAEAAAYAAgCLEwAA8xMFACOIArBAFGsAAWVzAQ0BsEAUZQABZfUpFAAAAQABAAEAAQABBQA7MAAAAQAACAADAPwRAgABEwQAKBQAANcBAACFAD0DWPZcFIQC884MAAABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/6ff2473e7df7.js b/pr/619/docs/search.index/6ff2473e7df7.js deleted file mode 100644 index 7a9fe6025..000000000 --- a/pr/619/docs/search.index/6ff2473e7df7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9MwSAAABAKYAAQABCAD0iBMAAAEAiAABADMAA7BAE1cAAWFiZTowAAABAAAAAAAMABAAAAAzBzQHNQf4DPkMyw85EIgQiRCKEIsQpBJ2Ew==") \ No newline at end of file diff --git a/pr/619/docs/search.index/701d23b5721f.js b/pr/619/docs/search.index/701d23b5721f.js deleted file mode 100644 index 3dd24140f..000000000 --- a/pr/619/docs/search.index/701d23b5721f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9d4TAAABAAEAegABAAEHAPPKEAAAAQABAAGAAqAAAAAHXKAQAAAJEGR48wEBZfIbEAAAAQDnAAAAhbBgDO8AAbBADGAAATIIAfTJBAAAiQLbCQEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/704723e7598f.js b/pr/619/docs/search.index/704723e7598f.js deleted file mode 100644 index 9022ede47..000000000 --- a/pr/619/docs/search.index/704723e7598f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CUTAAABAJAAAQABAwD0WRMAAAEAmAABAPMCAmJ1OjAAAAEAAAAAABMAEAAAAEwHTQdOB9wP3Q+FEIYQphCnED0RPhHxEfIRIxMkEzATMRNAE7QTtRM=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7081024babaf.js b/pr/619/docs/search.index/7081024babaf.js deleted file mode 100644 index f68652e3f..000000000 --- a/pr/619/docs/search.index/7081024babaf.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9HgTAAABAAEAAQATAAKwgBNMAAFzdvRyCQAAAQCKCgEAE4ACsDARDQABbG4BgAKgAAAAEJWgAAAAEJY0NvMDAXYBBg0AABMAAqBAAAARiWFz9zkMAAC/A2cBSwEBAAEAsgEBAgD0JRMAAAEAkAABAAEDAPRZEwAAAQCYAAEA8wACYnU6MAAAAQAAAAAAEwAQAAAATAdNB04H3A/dD4UQhhCmEKcQPRE+EfER8hEjEyQTMBMxE0ATtBO1E/OAAmR0E4ACoCAAAA0QZXIBBwGgQAAAFDpl8mgUAAABAAEAAPVkCQAAAQABAAEAAQAjgAKgoAAAFJZmcEcAAACFsDAPtAABoFAAABB4sHARBgABsUAUwQABgSkA8nYFAAABAPOAAmx0lwEAgIaxMBQ8AAGxEBRqAAGgsAAAE1sRRQg=") \ No newline at end of file diff --git a/pr/619/docs/search.index/70a80acda88a.js b/pr/619/docs/search.index/70a80acda88a.js deleted file mode 100644 index 9d729f84f..000000000 --- a/pr/619/docs/search.index/70a80acda88a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9AQSAAABAAEAAQAjAQKgcAAAEgNhcgF8BwAAAQMAOzAAAAEAAAgAAgCnDwYAXBMBAPMAAmN0OzAAAAEAAFcAJwCmBAsAbwUAABQJAQArDAEAMwwCAPMMAAD/DAIAEQ0BANAPAADVDwEA2A8BAN4PAABmEAIAbRABAHIQAQCXEAAADxEAABURAABhEQEAbhEBAIIRAQCGEQIA5xEBAPoRAgAAEgAAthIAAL8SAQDEEgEADBMBABwTAQAhEwEAQRMBAFETAwBXEwEAuBMBAMwTAAA6FAAAYxQEAGwUAgA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/70abc9bdb948.js b/pr/619/docs/search.index/70abc9bdb948.js new file mode 100644 index 000000000..37de22c42 --- /dev/null +++ b/pr/619/docs/search.index/70abc9bdb948.js @@ -0,0 +1 @@ +rn_("AQYA9LsTAAABAAEAAQABDwD0phQAAAEAAQABAPOHAmhtAQAA9A0TAAABAAEAAQDzBAFk9LESAAABAAEAAQAjh4SwoBRVAAGwQBMLAAGwcBP8AAEVgAABAAGgQAAAEJdlOzAAAAEAAAcAAgBuBwUA/wcBABOAArBQEE0AAWRyAQkA9d0TAAABAAEAegABALcCAICGsCASvAABWahqtNH1EUkB") \ No newline at end of file diff --git a/pr/619/docs/search.index/7105bb415f63.js b/pr/619/docs/search.index/7105bb415f63.js deleted file mode 100644 index f204ebf90..000000000 --- a/pr/619/docs/search.index/7105bb415f63.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQsA9KITAAABAA8AAQABBAGwQBNXAAFlAaQSAADzAAF0AWEUAAABDQDzeBQAADUAAQABEADzpRQAABgAAQDzgQNrbXMBAAA7MAAAAQAABgACAIwTAAD0EwUAI4YCsEAUbAABZXMBBAD0xBAAAAEAAQABAPOAA2NydDOAA7BgEOMAAWFscg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/71878b673d60.js b/pr/619/docs/search.index/71878b673d60.js new file mode 100644 index 000000000..c79f5f77f --- /dev/null +++ b/pr/619/docs/search.index/71878b673d60.js @@ -0,0 +1 @@ +rn_("AQAA9HcTAAABAAEAAQATAgKwgBNLAAFzdvRyCQAAAQCJCgEA8wABYwFpDAAAAQICoLAAABRXoLAAABRYY3PzzxAAAAEAXwABgQKwUBHyAAGgwAAAFCZoafOCAmVp84ACZW8=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7191e94af5e0.js b/pr/619/docs/search.index/7191e94af5e0.js deleted file mode 100644 index edeed6b6c..000000000 --- a/pr/619/docs/search.index/7191e94af5e0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHAS2wABoLAAABQYZW8jAQOwcBIBAAGAE34AEPptbnM7MAAAAQAAGgAGAGwHAQD3CAUADA0BAE4RCQCMEQAAXhMFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/71afe78ac6d4.js b/pr/619/docs/search.index/71afe78ac6d4.js new file mode 100644 index 000000000..a78fe5ede --- /dev/null +++ b/pr/619/docs/search.index/71afe78ac6d4.js @@ -0,0 +1 @@ +rn_("AYMCsCARhAEioJAAABQobXABggKwoBQYAAGwoBQaAAFjcgECAaBAAAARg2UBOxAAADOAhLAgEQEAAbAgD7sAAVAUAPOAAm9y") \ No newline at end of file diff --git a/pr/619/docs/search.index/71c746032e91.js b/pr/619/docs/search.index/71c746032e91.js deleted file mode 100644 index 98ffb0234..000000000 --- a/pr/619/docs/search.index/71c746032e91.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA834UAAABADsAAYADoEAAABNbsCAUGQABoCAAAA/XaGl5AQkBoIAAABS3ZgGWEwAAAQMBsAAUMQBQc/KtEAAAKwMjgAKgIAAAD9NhcgECAPXbEAAAAQABAF4CAQDzAANpdHU6MAAAAQAAAAAAEAAQAAAAgQcyCfcMOBC2EPASKRMqE9wT3RPjEw0UDhQvFDAUghSDFAGAAqAwAAAUYbCwE7IAAWFsAQwBoKAAABTId/K4FAAAAQABAQDz+g8AAAEAAQDzgAJ0dQEDAPPBEgAAAQABAAEBAPU/EQAAAQABAAEAAQAjgAKwkBQFAAFhdAEEAaBAAAAUZWXyhxQAAAEAAQIAOzAAAAEAAAsABQBZEAUA0RIBAP8TAQBYFAAAdxQAABOCArDwFLsAAWZnAYECsIAUjgABoGAAABS2ZHMBCAD1QhQAAAEAAQABAAEA8wIBZvWaEAAAAQABAAEAAQAjgAOgIAAAD9GwoBSMAAFkcnR37wEAjbAQFDwAAbDgFD4AAZfVDjswAAABAAA9ARMAhQQBALIEAgClBQIAwAYEAPQHAQAtDAMAWwwBAOcMAQCfDgcB8A8BALcQAQDKEAIA+BABAIsRAAC+EQMA6REBAOMSAACkEwcAnBQFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/723df646870e.js b/pr/619/docs/search.index/723df646870e.js new file mode 100644 index 000000000..3b930c592 --- /dev/null +++ b/pr/619/docs/search.index/723df646870e.js @@ -0,0 +1 @@ +rn_("AQQA9K4QAAABAAEAAQABAAA6MAAAAQAAAAAACgAQAAAA5g/nD9YQ1xBjEfQR9RERExITqhSrFPMBAXnyChQAAAEAAQADoKAAABRYoCAAABOPsDAR6gABZWl08vYSAAABAAEDADswAAABAAAGAAEAZBEGAAEIAPT5EwAAAQCLAAUAEwEDsJAUYgABsFATPgFnZ2xwOzAAAAEAABIACQBpEAIA7REBAC0TAQBOEwEAhRMBAOoTAQAkFAEAMxQBAHQUAQABgAKwMBHmAAGwMBHoAAFydgECAbAAErYAAWQ7MAAAAQAABQACAOIRAwDlEgEAI4ECoJAAABRXaW8BBwD0cxQAAAwAIgARAHcWAAGJsFAUCgABsFASuAEUsGATPAABtQkDOjAAAAEAAAAAAA4AEAAAAOIM4wzkDJ0Ong7PENAQDBEvEY4RjxGQEZERNBNtE0OAA6AgAAAM1KAQAAAM4W1ubwEDAPRmEAAAAQABABoBAYACoLAAABQmsDATcAABbnRDAAOgIAAAERuwUBHyAAFlaGk7MAAAAQAABgADABMMAAADEgMAzxMBAPOAAmRyhwsAAAqAAfcAEAGAAfoAEAGgUAAAEYugUAAAFF2gMAAAEJmgMAAAEKQwMWNlaW9zdHV39ZwHAAABAC0I1gJbAQ==") \ No newline at end of file diff --git a/pr/619/docs/search.index/730acf77735f.js b/pr/619/docs/search.index/730acf77735f.js deleted file mode 100644 index 2ef990566..000000000 --- a/pr/619/docs/search.index/730acf77735f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoDAAABEcoJAAABORMGj1AxIAAJYBAQABAAEAE4ACoDAAAA/QZHIjAYSwEAj9Az6wIAwIAQugMAAAD/USABj1mwUAADAAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/73730d6f0681.js b/pr/619/docs/search.index/73730d6f0681.js new file mode 100644 index 000000000..dc298fd78 --- /dev/null +++ b/pr/619/docs/search.index/73730d6f0681.js @@ -0,0 +1 @@ +rn_("AQIA9eYRAAABACQBAQBhAQEBAPciEQAAAQABANUCAQCLAAUAAQIA9LIQAAABAAEAAQATgAKg0AAAFHJjc/OAAmVvI4ACsAAHVAABbHTzAAJhcvKwDwAAAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/738b1982f2f2.js b/pr/619/docs/search.index/738b1982f2f2.js deleted file mode 100644 index 17318de5e..000000000 --- a/pr/619/docs/search.index/738b1982f2f2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsAARfgABsAARgAABNDbzAgFh8nkMAAABAAEAAPbGEgAAAQBwAAEAUQEBAPMAAWTz1RIAAAEAqgBjgAOgIAAACP9hZW8=") \ No newline at end of file diff --git a/pr/619/docs/search.index/73f291f4a740.js b/pr/619/docs/search.index/73f291f4a740.js new file mode 100644 index 000000000..e49ae13af --- /dev/null +++ b/pr/619/docs/search.index/73f291f4a740.js @@ -0,0 +1 @@ +rn_("AQkA830UAAABADsAAYACoEAAABNasCAUGAABaGkBDAGgoAAAFMd38rcUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjQABoGAAABS1ZHM3AwCDhqBAAAAUYLBgFDAAUAKQDgESAbAAFIEAAXM7MAAAAQAABQABAJsUBQABAMagUAAAEuKgAAAAEJmwIBFMAAGgUAAAEfihAAAAFJagQAAAFDoAAwILOzAAAAEAABUABwCsBQAANgwAAOsMAAAKEA0AcBEAAPgSAQA1FAEAAQEBsLAUiAABbDswAAABAAAMAAMAJwcIAAoNAQBIEAEAAQEBoDAAABEoaPMHCQAALgCrCAECAPTXEQAAAQABAAEAE4ECsCAR2wABYXPzggJub/cBAICHoCAAAAWroEAAAAwdFQEH") \ No newline at end of file diff --git a/pr/619/docs/search.index/7481844ee2d2.js b/pr/619/docs/search.index/7481844ee2d2.js deleted file mode 100644 index b6c36dec1..000000000 --- a/pr/619/docs/search.index/7481844ee2d2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9K4QAAABAAEAAQDzAgFz9UwJAAABAAEAAQCIBgEGAPQEEgAAAQABAAEAAQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQAzBgOwYBOFAIphcnXzexAAAHoCAQDzgAJhZQEDAPS2EQAAAQABAAEAAQIA9MwPAAABAEwEAQABggKgEAAAE1uwQBL7AAFhcwGAA7AAB3oAAaAAAAAMHLBwEIwAAW5yc+cHAACHoHAAABIDkQVBOjAAAAEAAAAAAAwAEAAAAOYB5wHoAekBfAfnB+gHVQlZDAcQCBAJEBwR") \ No newline at end of file diff --git a/pr/619/docs/search.index/74e1dac109d2.js b/pr/619/docs/search.index/74e1dac109d2.js deleted file mode 100644 index 832b449e0..000000000 --- a/pr/619/docs/search.index/74e1dac109d2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA8x4TAAABAAEAAQAAOzAAAAEAAAUAAgAEDAMA9xEBAPMAAWT0/hAAAAEAmgABAFMAA7AwFFYAAWVwcvTkDwAAAQDuAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/01c8144aed81.js b/pr/619/docs/search.index/74f0801909fc.js similarity index 55% rename from pr/619/docs/search.index/01c8144aed81.js rename to pr/619/docs/search.index/74f0801909fc.js index e52ceafff..6e60c83b8 100644 --- a/pr/619/docs/search.index/01c8144aed81.js +++ b/pr/619/docs/search.index/74f0801909fc.js @@ -1 +1 @@ -rn_("AYECsDAQPgABsBATugABc3QBAwDzzhIAAAEAAQAjgAKwABHEAAFoaQEAADswAAABAAATAAEAiAcTACOAAqAwAAAM4GFl84ACcnTzAAJhbDswAAABAAAoAAMAmwATAK4BAAAkEBMA") \ No newline at end of file +rn_("AYECsDAQPgABsBATuQABc3QBAwDzzRIAAAEAAQAjgAKwABHEAAFoaQEAADswAAABAAATAAEAiAcTACOAAqAwAAAM4GFl84ACcnTzAAJhbDswAAABAAAoAAMAmwATAK4BAAAkEBMA") \ No newline at end of file diff --git a/pr/619/docs/search.index/7531d92ef543.js b/pr/619/docs/search.index/7531d92ef543.js new file mode 100644 index 000000000..13966fc58 --- /dev/null +++ b/pr/619/docs/search.index/7531d92ef543.js @@ -0,0 +1 @@ +rn_("AYICsCARRgABsDARxAABZXABBQD05g8AAAEA7wABAFOAA7CQEfQAAWFpcgGBArCgFBgAAbCgFBoAAWNyxwAAAIWwUAz6AAGgIAAACXSgIAAADCM8AAE6MAAAAQAAAAAACgAQAAAAtQG2AXkE/gYlCSYJfRB+EPEQ8hAHEg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/75a09cbe7feb.js b/pr/619/docs/search.index/75a09cbe7feb.js new file mode 100644 index 000000000..7639e47ae --- /dev/null +++ b/pr/619/docs/search.index/75a09cbe7feb.js @@ -0,0 +1 @@ +rn_("AQAA9LYPAAABAAEAAQDzAgFzATIRAAABAAKwgBSNAAGgYAAAFLVkc/L9CAAAPgOTgISwwBPJAAGgEAAAEd0AwUA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/75a21333679c.js b/pr/619/docs/search.index/75a21333679c.js deleted file mode 100644 index 560f05222..000000000 --- a/pr/619/docs/search.index/75a21333679c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABOQsDAR6wABaXTy9xIAAAEAAQMAOzAAAAEAAAYAAQBkEQYAAQgA9PoTAAABAIsABQATAQOwkBRjAAGwUBM/AWdnbHA7MAAAAQAAEgAJAGkQAgDuEQEALhMBAE8TAQCGEwEA6xMBACUUAQA0FAEAdRQBAAGAArAwEecAAbAwEekAAXJ2AQQBsAAStwABZDswAAABAAAFAAIA4xEDAOYSAQC3BQABh7BQErkBFLBgEz0AAZQJAzowAAABAAAAAAALABAAAADiDOMM5AydDp4ODBGOEY8RkBGRETUTbhMjgAKgEAAADOFubwEDAPNmEAAAAQABACOAAqAAAAAME2RyYwGEoFAAABGLoDAAABCkFAEQ8pwHAAABABOAA7BgEtsAAbAAD7AAAWNnchOAA6CwAAAUGKBAAAAOnGVvcw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/75a90aa8afcb.js b/pr/619/docs/search.index/75a90aa8afcb.js deleted file mode 100644 index 48a7f4d76..000000000 --- a/pr/619/docs/search.index/75a90aa8afcb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9MwSAAABAKYAAQABCAD0iBMAAAEAiAABADMBA7BAE1cAAWFiZfX4DAAAAQBAA2sC0gABAAA7MAAAAQAABQACADEMAQC9DwMA84ACc3UjgQKwgBOCAAFydAGAArBwEwkAAaAQAAAM1256AQYA9IUQAAABALcAAQBzAISgoAAAFMgCART1egUAAAEA5g5XAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/75f58c5acd34.js b/pr/619/docs/search.index/75f58c5acd34.js deleted file mode 100644 index bf329f396..000000000 --- a/pr/619/docs/search.index/75f58c5acd34.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9CkTAAABAFgBAQDzBAFzOzAAAAEAAA0AAgCkEwcAnBQFAEcAAAWGoIAAABOEsQAUqwABsEAS5AABsIAUuwABsFATKwABFQAW9JgOAAABAAEAAQBDAISgIAAACTGg0AAAE5CgMAAACREVAATzAgIAAAEAcwU=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7669f28e496a.js b/pr/619/docs/search.index/7669f28e496a.js new file mode 100644 index 000000000..25541c5a8 --- /dev/null +++ b/pr/619/docs/search.index/7669f28e496a.js @@ -0,0 +1 @@ +rn_("AQkA830UAAABADsAAYADoEAAABNasCAUGAABoCAAAA/XaGl5AQkBoIAAABS2ZgGVEwAAAQMBsAAUMABQc/KtEAAAKgMjgAKgIAAAD9NhcgECAPXbEAAAAQABAF0CAQDzAANpdHU6MAAAAQAAAAAAEAAQAAAAgQcyCfcMOBC2EO8SKBMpE9sT3BPiEwwUDRQuFC8UgRSCFAGAAqAwAAAUYLCwE7EAAWFsAQwBoKAAABTHd/K3FAAAAQABAQDz+g8AAAEAAQDzgAJ0dQEDAPPAEgAAAQABAAEBAPU/EQAAAQABAAEAAQAjgAKwkBQEAAFhdAEEAaBAAAAUZGXyhhQAAAEAAQIAOzAAAAEAAAsABQBZEAUA0BIBAP4TAQBXFAAAdhQAABOCArDwFLoAAWZnAYECsIAUjQABoGAAABS1ZHMBCAD1QRQAAAEAAQABAAEA8wIBZvWaEAAAAQABAAEAAQAjgAOgIAAAD9GwoBSLAAFkcnR37wEAjbAQFDsAAbDgFD0AAZfVDjswAAABAAA9ARMAhQQBALIEAgClBQIAwAYEAPQHAQAtDAMAWwwBAOcMAQCfDgcB8A8BALcQAQDKEAIA+BABAIsRAAC+EQMA6BEBAOISAACjEwcAmxQFAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/76dd52dd2d8c.js b/pr/619/docs/search.index/76dd52dd2d8c.js deleted file mode 100644 index cbf9deb80..000000000 --- a/pr/619/docs/search.index/76dd52dd2d8c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsIATawABdfJKCQAAAQAjgAKwEAlIAAEzNgECAPNTBwAA8wEBAAECAPRDCQAAAQACCAEAAQIA81QMAAABAAEAE4ACsBAJQQABaXUBAgA7MAAAAQAACwACANITBQCQFAUA8wkBbTswAAABAAAMAAMAbREAAOoSBQBOFAUAdzAAAIqgMAAAE+igcAAAEgCgIAAACUWwMBHEAAGgUAAAEAIzhQs7MAAAAQAANAIEAP0BAAAjAjIBdwcAAAcK/wA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/76ed19bd7d71.js b/pr/619/docs/search.index/76ed19bd7d71.js deleted file mode 100644 index d83dfa32b..000000000 --- a/pr/619/docs/search.index/76ed19bd7d71.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEAUfAABdDswAAABAAANAAYA/hIDAGkTAQDZEwEA8BMBAHEUAQCYFAEAE4ACsDATMgFJaXABBQDzrhMAAAEAAQATgAKgMAAAFAlleVMAA7BwFBYAAWJlcwFAEAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/770c52750c29.js b/pr/619/docs/search.index/770c52750c29.js deleted file mode 100644 index 77b7ca76a..000000000 --- a/pr/619/docs/search.index/770c52750c29.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsIATawABdfJKCQAAAQAjgAKwEAlIAAEzNgEGAPPxEAAAAQAWAROAArAAD7sAAW91AQIA81MHAADzAQEAAQMA884SAAABAAEAI4ACsAARxAABaGkBAAA7MAAAAQAAEwABAIgHEwAjgAKgMAAADOBhZfOAAnJ0E4ACsDATugABYWwBAAGggAAAFLdm8gAJAACWCgEHAPVkEwAAAQABAAEAAQAjgAKgUAAAEWNhb/MCAmZzOzAAAAEAAAgABABPBwAAggcFAAgNAACbEQAAE4ACoEAAAAwSYW8BAwGwQBR8AAF08tkTAAABACOFAqBAAAAUCWJzIwADsEARAwABoFAAABFwYWJm9w0JAAABAEgAcgcBAGIAAQATgQKgUAAAEgBndAGAAqBAAAAR7aAgAAAT6GFpAQIA9EMJAAABAAIIAQABAgDzVAwAAAEAAQATgAOwEAlBAAGwMBQbAAFpdXkBAgA7MAAAAQAACwACANITBQCQFAUA8wgBbTswAAABAAAMAAMAbREAAOoSBQBOFAUAAYECoIAAABLXoHAAABQvYXPzgAJucrfbAQCNoUAAABSLoCAAAAlFoFAAABACN5UPOzAAAAEAADUCBQD9AQAAIwIyAQwHAAB3BwAABwr/AA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/772fadcc62b0.js b/pr/619/docs/search.index/772fadcc62b0.js new file mode 100644 index 000000000..dee298926 --- /dev/null +++ b/pr/619/docs/search.index/772fadcc62b0.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABPicwH5EAAAAQMA9IgQAAABAAEAAQATgAKwUBCMAAFhaQGAArBwFK4AAbBwFDsAAWVyAYACoLAAABRyoDAAABElbG6XAQAAhaAgAAASn6AgAAAI/hCRBDowAAABAAAAAAATABAAAACcBNQE1QTWBNcE2ATZBG4Jtg+3D7gPuQ9KE4QTCBQOFBoUGxQ3FDgUAQIAOjAAAAEAAAAAAAoAEAAAAFcJWAkhEG4TbxOfE6ATTBSkFLwUvRQBAAA7MAAAAQAABgACAIsTAADzEwUAAQIBsDATWwABYzowAAABAAAAAAATABAAAAD/DNAPZhBnEGgQbRBuEHIQcxAPEYIRhhGHEYgR/xFQE1ETORRiFGMUAQMA88UTAABsAAEAE4ECsEARbgABYWUTgAKgsAAAFHlhZQEBAbBAFGUAAWX1KRQAAAEAAQABAAEAE4ACoBAAAAwUYW+HDwAAyLAwCQ8HaLBAFGsAAaCAAAASmkBMiAnz+AcAACQEPgABgAKggAAAE3WgkAAAE01hawEDAPPAEgAAAQABACOAhLEgFLoAAaAAAAAJMqAwAAAP1wQEBgEIAPXCFAAAAQABAAEAAQATigKwQBSZAAFhcpMAhKDAAAATSaEAAAAUFwFABvJ6BwAAAQABAwGgQAAAEfll8wkNAAAQBAEAAQUA9LsTAAABAAEAAQBTgAOwABNwAAFlc3QBBgD0phQAAAEAAQABAPMIAW30rBIAAAEAAQABAAECADswAAABAAAFAAEAjxQFAPMNAW07MAAAAQAABQABAE0UBQABBAD3EQ0AAAEAowUOAAEAjgABAAEDAYATfQAQ+nM7MAAAAQAABQABAF0TBQAjggKgkAAAFGFpcwEFAaBQAAAUJmjyuhIAAAEAE4ACsDATcAABbnQBgAKggAAAE5CwQBHyAAFhZQGAAqAQAAARG6AAAAARYG5yAQkBoEAAABRkZfKGFAAAAQAjgAKgkAAAE8hpbMcjAAAKoDAAABEcsFATJgABsPAUsAABsHATjQABoNAAABRtMGJjZWhpa25vdjswAAABAAAeAAsAEwwAAPMQAwACEgQAiRMBAJgTAwDPEwEAFxQAABwUBgA7FAEARxQAAF4UAQABAgKgsAAAFFegsAAAFFhjc/PPEAAAAQBfAAEBArBQEfIAAaDAAAAUJmhp8s8TAAABAPOAAmVpAQEBsJATiQABc/SyEAAAAQABAAEAAQMBsAAQ7QABcwFVEAAA84ADaGl0AQEBoFAAABMKYwHSDAAAAQUBsIAUXgABdjswAAABAAAHAAIA0REDAL8TAwABAQD0dRAAAAEAswABAOOAhLBwEfYAAQ4IAPdlDwDRsJASmAABoFAAABEUoQAAABSVoKAAABOsoBAAAAdQQD+/KTswAAABAAA8ABkAxAQAAMYEAACYBQIAGAcCAAAMAwDVDAEAxA8CANIPAAD5DwAAAhAAACIQAQAyEQgAiREAANoSAQDjEgEA5xIBAEUTAQBjEwQAuRMBAMMTAQDIEwAAQRQEAEgUAwCVFAAAthQAAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7770a1a6381d.js b/pr/619/docs/search.index/7770a1a6381d.js deleted file mode 100644 index 48b73bf22..000000000 --- a/pr/619/docs/search.index/7770a1a6381d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9LwTAAABAAEAAQABDwD0pxQAAAEAAQABAAEAAbDwFLEAAWs7MAAAAQAACAADABgUAAAdFAYASBQAAAECAPR1EAAAAQCzAAEA9wAAAIWxABSaAAGJMADy2xIAAAEAE4ACsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAAGAAqAAAAAMKrAwFGYAAXFyAYACoEAAABEQsMAUXAABZXMBAQA7MAAAAQAAEwABACQQEwAjgAKwkBPEAAFpbXc2AACKoFAAABQnsHAUBQABoCAAAAz0nFUROzAAAAEAAAsABABYBwAA6RADALsSAQAqFAQAAQIBsDARdwABcAGiEgAAs4CEoCAAABHiAigE") \ No newline at end of file diff --git a/pr/619/docs/search.index/77856163ad0a.js b/pr/619/docs/search.index/77856163ad0a.js deleted file mode 100644 index 644b5e459..000000000 --- a/pr/619/docs/search.index/77856163ad0a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQADsCARTAABoFAAABH5oEAAABQ7bHN28jYUAAABAAECAPTYEQAAAQABAAEAE4QCsCAR3AABYXPzgAJhZROAAm/yRz5993JzAQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQAzBwOwYBOFAIphcnXzexAAAHoCAQAjgAKgEAAADBxlcgEAADswAAABAAAgAA4AwgQBAIgFCQAsCQEAMQwBAOkMAQCcDgAAvQ8DANMPAADyDwEA5xABAPoQAACNEQAA6xEBAPARAAABAQA6MAAAAQAAAAAADAAQAAAADwlXDFgMdxCMEI0QIhEjESQR+hP7E4YUixQBgQKwABF+AAGwABGAAAE0NgEFAPQDFAAAAQBQAAEA8wQBY/IHEwAAAQABAwGgQAAAFDpl8mgUAAABAAEFAPPYEgAAAQABAAEEAPMMEwAAAQBhAQEAAPQOEwAAAQABAAEA8wQBZPSyEgAAAQABAAEA5xIAAYmwoBRWAAGgMAAAESiwYBSMAAGwcBP9AAG1yAQ6MAAAAQAAAAAACgAQAAAABwk1CWIMYwz/DwAQARDhEUwTTRMoFBGBAhOwIBHcAAFhcwECAPPOEgAAAQABAPcAAIDFoBAAABClgAA4CAEFAPTMEgAAAQCmAAEAAQgA9IgTAAABAIgAAQAzAQOwQBNXAAFhYmX1+AwAAAEAQANrAtIAAQAAOzAAAAEAAAUAAgAxDAEAvQ8DAPOCAnN1AQYA9IUQAAABALcAAQAzAAOgoAAAFMhidHf1egUAAAEA5g5XAAEAAQ8A9CUUAAABAE8AAQABBAD0gxAAAAEAtwABACOAArEAFIkAAW9wY4EDsIATngABY3N0AQQBoKAAABTId/K4FAAAAQABCwA7MAAAAQAABgABAB0UBgABDAD0hhMAAAEArQABACOAAqBwAAAUSGd384ACZW8BDQDzeBQAADUAAQABEADzpRQAABgAAQABAQGwYBLGAAFy97gFAAABAD4CLgQBAPIDAQABAwGwAAz3A0Fz9C0MAAABAAEAAQABAwD0KwwAAAEANQUBAAGAAqBAAAAT27AwEvkAAWFz84ADbnJ2AQkA9PERAAABAD4BAQABBwD0EREAAAEAsAABAPOAAmhpAQECsCAM9QABsAAMbQABZXPyZQcAAAEAAQUA8x4TAAABAAEA8wUBcvTkDwAAAQDuAAEA84ACYmPX3gEAjqAgAAAHZ6BQAAARiqDgAAAUELDQFAEAAZf1CzowAAABAAAAAAAcABAAAAAFAgYCBwJjBGQEGQknDGsMbAxvDNoM2wzcDN0M3gzfDJcOeRB6EM0QdxF4EcQRxREKFFYUVxRqFGsUAYACoLAAABRzoDAAABElbG4TAAKwgBQ8AAFlcPSFEwAAigApAAEAAQMBsEAUZgABZfUqFAAAAQABAAEAAQABBgD0vBMAAAEAAQABAAEPAPSnFAAAAQABAAEAAQIAOzAAAAEAAAUAAQCQFAUA8w0BbTswAAABAAAFAAEAThQFAAEEAPW2EgAADgABAI4AAQABAAKgEAAAEWCw8BSxAAFlazswAAABAAAKAAQAGBQAAB0UBgBIFAAAXxQBAAECAPSyEAAAAQABAAEAAQIA9HUQAAABALMAAQD3kwEAjaBQAAARFKEAAAAUlrEAFJoAAaCgAAATTr28AzswAAABAAAmAA0AAAwDAPkPAAAiEAEAMxEHAIkRAADbEgEA5BIBAOgSAQBGEwEAZBMEAEIUBABJFAMAtxQAAAECADswAAABAAALAAIA0hMFAJAUBQDzAQFtOzAAAAEAAA0ABADTDAAAbREAAOoSBQBOFAUAEwECoDAAAAzXZXPyARIAAAEAAYkCsCAUcQABoDAAABR7aXATAAOgIAAAEy2ggAAAE0BlaXX1FQwAADkAAQABAAEAAYYCsJAUmAABoAAAABK6YmQBgAKwMBMhAAGgMAAAEPhydtcAAAOFoDAAABBsoDAAABN3EAETOjAAAAEAAAAAAAkAEAAAAAEJAgkDCTMJNAmHEI4QSBFJEf0SAQYAOjAAAAEAAAAAAAcAEAAAANwP3Q+mEKcQIxMkE7QTtRMBBwD0mRMAAAEAAQABAHcAAACGoHAAABOxoEAAABNEoHAAABEmQ0AFOzAAAAEAABAABwAbAgAAXQcBAGkJAQD8EAEACBEBAJMRBQCcEgEAd3cAgIuwsBSEAAGgYAAAESa1QQ8=") \ No newline at end of file diff --git a/pr/619/docs/search.index/77a0ffd5dec4.js b/pr/619/docs/search.index/77a0ffd5dec4.js new file mode 100644 index 000000000..adc73cdf3 --- /dev/null +++ b/pr/619/docs/search.index/77a0ffd5dec4.js @@ -0,0 +1 @@ +rn_("AYkCsCAUcAABoDAAABR6aXATAAOgIAAAEyyggAAAEz9laXX1FQwAADkAAQABAAEAAYYCsJAUlwABoAAAABK5YmQBgAKwMBMgAAGgMAAAEPhydtcAAACFoDAAABBsoDAAABN2EAETOjAAAAEAAAAAAAkAEAAAAAEJAgkDCTMJNAmHEI4QSBFJEfwS") \ No newline at end of file diff --git a/pr/619/docs/search.index/77f54ff580e6.js b/pr/619/docs/search.index/77f54ff580e6.js deleted file mode 100644 index d1d430ea2..000000000 --- a/pr/619/docs/search.index/77f54ff580e6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOjAAAAEAAAAAAAgAEAAAAA8JdxAiESMRJBH6E/sThhSLFAEBAqBAAAAUbqAwAAARKGVo9QcJAAAuAC0DAQB+BQECAPTYEQAAAQABAAEAE4ECsCAR3AABYXPzgAJubwECAPSyEAAAAQABAAEAEwACoNAAABRzY3PyIhAAAAEA84ADZWlv") \ No newline at end of file diff --git a/pr/619/docs/search.index/7818197cf8d8.js b/pr/619/docs/search.index/7818197cf8d8.js new file mode 100644 index 000000000..f45822d6a --- /dev/null +++ b/pr/619/docs/search.index/7818197cf8d8.js @@ -0,0 +1 @@ +rn_("AQYA9BETAAABAJgBAQATAgKwYBMTAAFmbfLlDAAAAQAjggKwQBNAAAFlbAEFAPQCFAAAAQBQAAEA8wMBY/IGEwAAAQABgQKgAAAACTKgMAAAD9dzdBOAAqAQAAAHUG5404CEsHAUugABkEAB") \ No newline at end of file diff --git a/pr/619/docs/search.index/785eb7a99207.js b/pr/619/docs/search.index/785eb7a99207.js deleted file mode 100644 index 2b6b3d0f7..000000000 --- a/pr/619/docs/search.index/785eb7a99207.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABQkZfKaFAAAAQABAQA7MAAAAQAABgABAMEUBgDzBgFl9G8UAAABADMAAQAzBQOwYBOFAIphcnXzexAAAHoCAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7886dc8c4f27.js b/pr/619/docs/search.index/7886dc8c4f27.js new file mode 100644 index 000000000..054bbded5 --- /dev/null +++ b/pr/619/docs/search.index/7886dc8c4f27.js @@ -0,0 +1 @@ +rn_("AQAA9WQJAAABAAEAAQABACOAAqCgAAAUlWZwRwAAAIWwMA+0AAGgUAAAEHiwcBEGAAGxQBTAAAGBKQDydgUAAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/78ba03951c35.js b/pr/619/docs/search.index/78ba03951c35.js new file mode 100644 index 000000000..99335ff92 --- /dev/null +++ b/pr/619/docs/search.index/78ba03951c35.js @@ -0,0 +1 @@ +rn_("AQEBsFAP2gABY/ShBAAAAQABAMkAAQABoIAAABS2ZgGVEwAA8wYBc/IIDQAAkwQzAAOgYAAAFJZjaXPy2xEAAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/78c30f0b3daa.js b/pr/619/docs/search.index/78c30f0b3daa.js deleted file mode 100644 index be7c216bf..000000000 --- a/pr/619/docs/search.index/78c30f0b3daa.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsAARfgABsAARgAABNDYBBAGgoAAAFMh38rgUAAABAAELADswAAABAAAGAAEAHRQGACOAAqCAAAAUSGVvYwIDoGAAABPbZW5wAScMAADzAAJhdgHiBgAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/78fd5b73bd69.js b/pr/619/docs/search.index/78fd5b73bd69.js new file mode 100644 index 000000000..5bd9e342c --- /dev/null +++ b/pr/619/docs/search.index/78fd5b73bd69.js @@ -0,0 +1 @@ +rn_("AQYA9BYRAAABAL4AAQATgQOgAAAAEV6xIBSiAAFhZG4BBQD0iBAAAAEAAQABAAEUAPXCFAAAAQABAAEAAQABBQGwgBReAAF2OzAAAAEAAAcAAgDREQMAvxMDACOAArBwEfYAAWJkVwIAAYawwBOJAAGgoAAAE6ygkAAAE3UF4AL1GAcAAAEAAQDoCJMEAQYA89QSAAABAKoAAQABoGAAAA/tcgGOBAAA1wEAgMWgMAAADBIAAIoK") \ No newline at end of file diff --git a/pr/619/docs/search.index/7918c5103edf.js b/pr/619/docs/search.index/7918c5103edf.js new file mode 100644 index 000000000..c592832b2 --- /dev/null +++ b/pr/619/docs/search.index/7918c5103edf.js @@ -0,0 +1 @@ +rn_("AQIBsEAUewABdDswAAABAAANAAYA/RIDAGgTAQDYEwEA7xMBAHAUAQCXFAEAE4ACsDATMQFJaXABBQDzrRMAAAEAAQATgAKgMAAAFAhleVMAA7BwFBUAAWJlcwFAEAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/791b5f37fbfa.js b/pr/619/docs/search.index/791b5f37fbfa.js new file mode 100644 index 000000000..9ab2d5e7a --- /dev/null +++ b/pr/619/docs/search.index/791b5f37fbfa.js @@ -0,0 +1 @@ +rn_("AQUA9IgQAAABAAEAAQABEwD1whQAAAEAAQABAAEAE4ACoMAAABNJYW8BAgKgsAAAFFegsAAAFFhjc/PPEAAAAQBfAAGBArBQEfIAAaDAAAAUJmhp84ACZWkjgAKwsBOJAAFpdAEFAbCAFF4AAXY7MAAAAQAABwACANERAwC/EwMAI4ACsHAR9gABYmR3AgAAhqCgAAATrKCQAAATdQXgAvUYBwAAAQABAOgIkwQ=") \ No newline at end of file diff --git a/pr/619/docs/search.index/794532fecbad.js b/pr/619/docs/search.index/794532fecbad.js new file mode 100644 index 000000000..3fb602b16 --- /dev/null +++ b/pr/619/docs/search.index/794532fecbad.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwDLEQIAexMBABIUAgABBADzzhEAAAEAAQAjAAKgYAAAEvxhcvPvEAAAAQDJAQGAAqEQAAAUobCAFJcAAWl1NwQAgYexUBS+AAGgAAAAEM6wcBPbAAGhMAAAFLIKQBsjgAKgMAAAEppudg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7a0147b1d120.js b/pr/619/docs/search.index/7a0147b1d120.js new file mode 100644 index 000000000..b4409197d --- /dev/null +++ b/pr/619/docs/search.index/7a0147b1d120.js @@ -0,0 +1 @@ +rn_("AQIBsIAT6AABdAEaCQAAAYECoBAAABNEoHAAABOMYWPzAQFy8qoRAAAgAPOAAmVpAQAA9BcMAAABAAEAAQDzgAJkcvMAAWX0kAAAAGQMSQcBAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7a8eed6dec67.js b/pr/619/docs/search.index/7a8eed6dec67.js deleted file mode 100644 index 3d4f762ba..000000000 --- a/pr/619/docs/search.index/7a8eed6dec67.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAI0AAgB1BwAAegmMAAGEArBwFDgAAaBAAAARGGlzAQcA8/EQAAABABYBI4ACoLAAABLXYXQBAAOwMAknAAGwMBOXAAGgIAAAB3ZhZG8BFgIAADcDAICGoMAAABQwsAAUAQABAJgV") \ No newline at end of file diff --git a/pr/619/docs/search.index/7a9b6af3ec35.js b/pr/619/docs/search.index/7a9b6af3ec35.js deleted file mode 100644 index 8aac73310..000000000 --- a/pr/619/docs/search.index/7a9b6af3ec35.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9HgTAAABAAEAAQATAgKwgBNMAAFzdvRyCQAAAQCKCgEA8wABYwFpDAAAAQICoLAAABRYoLAAABRZY3PzzxAAAAEAXwABgQKwUBHzAAGgwAAAFCdoafOCAmVp84ACZW8=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7aa67d35b328.js b/pr/619/docs/search.index/7aa67d35b328.js new file mode 100644 index 000000000..0d5424f75 --- /dev/null +++ b/pr/619/docs/search.index/7aa67d35b328.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAO4AAgARDAAAHA3tAPMAAW07MAAAAQAA7gACAKIFAADPBe0AAQMAOzAAAAEAAAgAAgCnDwYAWxMBAPMAAWM7MAAAAQAAVwAnAKYECwBvBQAAFAkBACsMAQAzDAIA8wwAAP8MAgARDQEA0A8AANUPAQDYDwEA3g8AAGYQAgBtEAEAchABAJcQAAAPEQAAFREAAGERAQBuEQEAghEBAIYRAgDmEQEA+RECAP8RAAC1EgAAvhIBAMMSAQALEwEAGxMBACATAQBAEwEAUBMDAFYTAQC3EwEAyxMAADkUAABiFAQAaxQCAPOAAnJ3AQkA830UAAABADsAAYACoEAAABNasCAUGAABaGkBDAGgoAAAFMd38rcUAAABAAEBAPP6DwAAAQABAPOAAnR1AYECsIAUjQABoGAAABS1ZHM3AwCBhqBAAAAUYLBgFDAAUAKQDgGIArAAE+MAAbAAE+UAATQ2M4ADoDAAABGFZG5zYwADoBAAAATJYWVvAYcAAAA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7abf8916b235.js b/pr/619/docs/search.index/7abf8916b235.js new file mode 100644 index 000000000..aeabaee2b --- /dev/null +++ b/pr/619/docs/search.index/7abf8916b235.js @@ -0,0 +1 @@ +rn_("AYACsHARdwABsCAUWwABYWQBBQD0RxMAAAEAmAABAPMAAWMBsBIAAEOAA7AwE50AAbCgFD0AAWFzeQEGAPQWEQAAAQC+AAEAk4CEoAAAABFesSAUogABCSAB84ACZWk=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7b27a3c761b1.js b/pr/619/docs/search.index/7b27a3c761b1.js new file mode 100644 index 000000000..c311f4c0c --- /dev/null +++ b/pr/619/docs/search.index/7b27a3c761b1.js @@ -0,0 +1 @@ +rn_("AQ0A9d0TAAABAAEAegABAAECAPQKEQAAAQCSAQEAAQMA9HURAAABAHwBAQDzAAJidQEaEAAAAQMA9AgRAAABAJIBAQDzhAJkcwECAPMSCQAAAQBYAPOAAml0ARgA88QUAAABAAEAI4ECsMAT2wABY20BBQGwYBLFAAFy9CUMAAABAPIDAQABCQD28BIAAAEA/QCJADUAAQATgAKwYBDIAAFkbgEDAaBwAAATLGf0XQcAAAEACwIBAAEJAPN9FAAAAQA7AAGBArCAFI0AAaBgAAAUtWRzFwEAiYWw0BS3AAGgQAAAFGCwYBQwAFACkApnugAAjLBwES0AAbCwEzoAAaCgAAAS77FQFK4AAbDwFAwAAW3BD/SIAAAAAQABAAEA") \ No newline at end of file diff --git a/pr/619/docs/search.index/7b4cfcfcb707.js b/pr/619/docs/search.index/7b4cfcfcb707.js new file mode 100644 index 000000000..4f5764cc3 --- /dev/null +++ b/pr/619/docs/search.index/7b4cfcfcb707.js @@ -0,0 +1 @@ +rn_("AQEA9VAJAAABAAEAAQABAPMAAWnz8QwAAL8HAQABAQGgQAAAFCNl8pkUAAABAAEEAqAgAAAR3aAwAAASqGJoAc4PAADnAACAxaAQAAAM8qAwAAAQfAQQKAE=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7b564533bf45.js b/pr/619/docs/search.index/7b564533bf45.js new file mode 100644 index 000000000..1b841267e --- /dev/null +++ b/pr/619/docs/search.index/7b564533bf45.js @@ -0,0 +1 @@ +rn_("AYQCsCARhAEioJAAABQobXABgAKgMAAAERCgUAAAE8tjcpcAAACFsCATlgABsMAUWwABoGAAABHgEEAOOzAAAAEAABIABgDLBAgA3hEBAPoSAQDoEwEAPxQBALoUAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7bf37cdcde98.js b/pr/619/docs/search.index/7bf37cdcde98.js deleted file mode 100644 index b9797225e..000000000 --- a/pr/619/docs/search.index/7bf37cdcde98.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9D0HAAABAAEAAQABhQKwcBQWAAGwMBNpAAFlcxMAA7BAD9gAAaBgAAARjGJlczswAAABAAASAAQAqQUBAMoGCgBREAEAqRADAAECAPO3BQAARgoBAAEDAPXQDwAAnQABAAQAAQABCgGgQAAAFGVl8ocUAAABACMABKAwAAARHKCQAAATkbBgErsAATBjaGn1AxIAAJYBAQABAAEA84ACZHLnBAAAh7AQCP0DPrAgDAgBC6AwAAAP9RJBODswAAABAAASAAYAjQACAJsFAADLBQMAngcFAOMHAwASDAAA") \ No newline at end of file diff --git a/pr/619/docs/search.index/7c17a1e91f1c.js b/pr/619/docs/search.index/7c17a1e91f1c.js deleted file mode 100644 index 0978e6901..000000000 --- a/pr/619/docs/search.index/7c17a1e91f1c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQwA9MATAAABAAEAAQABBgDzchEAAAEAAQABggKwYBNGAAGw0BRoAAFpchOAArAQDOwAAWVpFwMAg4ixMBSHAAGgYAAAEXGgUAAAEQWwkBMYAAGwQBEBAAG0EAfzAAFh9EMJAAABAAIIAQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/1528e494c297.js b/pr/619/docs/search.index/7c302d99a047.js similarity index 62% rename from pr/619/docs/search.index/1528e494c297.js rename to pr/619/docs/search.index/7c302d99a047.js index d15f99c04..2ea3b1466 100644 --- a/pr/619/docs/search.index/1528e494c297.js +++ b/pr/619/docs/search.index/7c302d99a047.js @@ -1 +1 @@ -rn_("AQAA9HUQAAABALMAAQABhAKwABF+AAGwABGAAAE0NvMCAWHyeQwAAAEAAQEA9sYSAAABAHAAAQBRAQEA84ACZW/zgAJoaw==") \ No newline at end of file +rn_("AQAA9HUQAAABALMAAQABhAKwABF+AAGwABGAAAE0NvMCAWHyeQwAAAEAAQEA9sUSAAABAHAAAQBRAQEA84ACZW/zgAJoaw==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7d45cf1ad0f1.js b/pr/619/docs/search.index/7d45cf1ad0f1.js deleted file mode 100644 index b6e40dff4..000000000 --- a/pr/619/docs/search.index/7d45cf1ad0f1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAAUAAQDdEgUAAQQBoFAAABQnaPK7EgAAAQABAAKwQBO4AAGgoAAAFEdlcjowAAABAAAAAAAHABAAAADGBscGYwdkB+4P7w/lEOYQ84ADZ2lz") \ No newline at end of file diff --git a/pr/619/docs/search.index/7d953c34eb92.js b/pr/619/docs/search.index/7d953c34eb92.js new file mode 100644 index 000000000..63c1d837f --- /dev/null +++ b/pr/619/docs/search.index/7d953c34eb92.js @@ -0,0 +1 @@ +rn_("AQIA9L4RAAABAAEAAQATAAKgMAAAEYlldPTEEAAAAQABAAEAAQMA9LoRAAABAAEAAQABgAKgAAAAEJWgAAAAEJY0NvMDAXYBBg0AAJcCAACIsKATGwABsCAMKAABsGATFQABsIAS+gABoCAAABEACUxGOjAAAAEAAAAAAAkAEAAAAAkHCgcLBzkM+A9fEakSqhKrEl0U") \ No newline at end of file diff --git a/pr/619/docs/search.index/7dcbe350cea7.js b/pr/619/docs/search.index/7dcbe350cea7.js new file mode 100644 index 000000000..c4e29782d --- /dev/null +++ b/pr/619/docs/search.index/7dcbe350cea7.js @@ -0,0 +1 @@ +rn_("AYMCoJAAABQ1oJAAABQ2MjMBgAKgUAAAFGGggAAAE4BjZfMAAnN08kIHAAABAAEAAaCwAAATy2LzVRMAAC4BAQAjgAKwAA/0A2BkcgEAAbCAFDsAAXDyNxQAAAEAQwADoCAAABFgoEAAABK1ZGVz8/kPAABMAwEAE4ICoCAAABQnZWnzgAJjZQEEADswAAABAAAJAAQAYgkBAJ8QAwDhEAEA7BMBALOAhKCQAAAUlRABQg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7e02f86b18de.js b/pr/619/docs/search.index/7e02f86b18de.js new file mode 100644 index 000000000..cf5574bf5 --- /dev/null +++ b/pr/619/docs/search.index/7e02f86b18de.js @@ -0,0 +1 @@ +rn_("AYACsRAUmQABsBAMVwABZW8BBQA7MAAAAQAADQABAJwRDQABAgDzBxAAAAEAAQABAgD0AxAAAAEAAQABAAEDADswAAABAAAIAAEAuRAIAIcHAACHsKATwwABsNAUWwABoFAAABQmjBQROzAAAAEAAAYAAwBYBwAA6RADALoSAQDzgAJsdBOAA6AgAAAM0bCgFD8AAWFkbg==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7e20fbd5e7ea.js b/pr/619/docs/search.index/7e20fbd5e7ea.js new file mode 100644 index 000000000..faa58ba6a --- /dev/null +++ b/pr/619/docs/search.index/7e20fbd5e7ea.js @@ -0,0 +1 @@ +rn_("AQUBsEASwwABZfLnEgAAAQABAAA7MAAAAQAAEQAEAAACAQC5EAgAthEDAMASAgABCgGwQBRlAAFl9SkUAAABAAEAAQABAEcGAACHsCARFAI5sMAUsAABoCAAAAb+sDAHWgABGIkKOjAAAAEAAAAAAAwAEAAAAFYHVwdFCSEMIgwoDCkMfAx9DMsMzAwVExYT") \ No newline at end of file diff --git a/pr/619/docs/search.index/7e5f97ab36a0.js b/pr/619/docs/search.index/7e5f97ab36a0.js new file mode 100644 index 000000000..d96034970 --- /dev/null +++ b/pr/619/docs/search.index/7e5f97ab36a0.js @@ -0,0 +1 @@ +rn_("AYQCoCAAABEnoDAAABGNaXQBAQA7MAAAAQAAjQACAHUHAAB6CYwA8wACZWz1tQQAAMQCywlSAgEAAQIAOzAAAAEAAO4AAgARDAAAHA3tAMcAAACFsLATQAABsBATxgABsDANGgABFDACOzAAAAEAABoBCwDfAQYAogUAAM8F7QBEBwcAQxACAJwRDQDLEQIApBIBACoTAQB7EwEAEhQCAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7e7a3cefa593.js b/pr/619/docs/search.index/7e7a3cefa593.js new file mode 100644 index 000000000..dde30be79 --- /dev/null +++ b/pr/619/docs/search.index/7e7a3cefa593.js @@ -0,0 +1 @@ +rn_("AYMCsQAUvAABsNAUrAABa20BBAGgoAAAFMd38rcUAAABAAELADswAAABAAAGAAEAHBQGACOAAqCAAAAUR2VvYwQDoGAAABPaZW5wAScMAAABCgDz/hMAAAEAdwATgAKiEAAAFMdsb3cAAACFoGAAABKVoQAAABR4BIEDOzAAAAEAAD0ABAC6BQUAUQcAAKQHNQCFEQAAQ4ADsIARhAEioAAAAAIXZGt0") \ No newline at end of file diff --git a/pr/619/docs/search.index/7ee6a3493b01.js b/pr/619/docs/search.index/7ee6a3493b01.js deleted file mode 100644 index e09d1bcdd..000000000 --- a/pr/619/docs/search.index/7ee6a3493b01.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA834UAAABADsAI4ACsAAQ3gABbW4BgAOgQAAAE1uwIBQZAAGgIAAAD9doaXkBCQGggAAAFLdmAZYTAAABAwGwABQxAFBz8q0QAAArA0OAA7AgD9MBJ7BQEr0AAWFvcgECAPXbEAAAAQABAF4CAQDzAANpdHU6MAAAAQAAAAAAEQAQAAAAgQcyCfcMOBC2EOIR8BIpEyoT3BPdE+MTDRQOFC8UMBSCFIMUAQYA9BITAAABAJgBAQATAgKwYBMUAAFmbfLlDAAAAQAjggKwQBNBAAFlbAGAAqAwAAAUYbCwE7IAAWFsAQYA8+EPAADhAAEAAQUA9AMUAAABAFAAAQDzAgFj8gcTAAABAAECAaAwAAAQd2EBWgwAAAGAArBQESsAAbAgD7AAAWNu84ACbnQBBQA7MAAAAQAADgACAOsMAAAKEA0AAQIAOzAAAAEAAAcAAQBZCQcA5wUAAAmgMAAADFmgsAAAFC+ggAAAEaqw0BQ+AAEwYWZpa21ydXY7MAAAAQAAagIFAP8BAABrA+0AeAcAAAcL7QAKDowAAQwBoKAAABTId/K4FAAAAQABAQDz+g8AAAEAAQDzgAJ0dQEDAPPBEgAAAQABAAEBAPU/EQAAAQABAAEAAQABAQGwMA/qAPB09moHAAABAI4A9AerAP4BY4ADsJAUBQABYW10AQMBoEAAABRlZfKHFAAAAQATgAKwYBS7AAFlcgEDAaAAAAAT43MB+RAAAAECADowAAABAAAAAAAKABAAAABXCVgJIRBvE3AToBOhE00UpRS9FL4UgwAEoIAAABKbsHARbgABsCARDwDxZm5ydgH4BwAAAYECoAAAAAkyoDAAAA/Xc3THAQCAxrAAFDwAAbCQEpkAAaAQAAAHUAASiCgBAgA7MAAAAQAADQAGAFkQBQBrEQEA0RIBAP8TAQBYFAAAdxQAABOCArDwFLsAAWZnAYACsIAUjgABoGAAABS2ZHMTgAKwwBPKAAFpbwEIAPVCFAAAAQABAAEAAQDzAgFm9ZoQAAABAAEAAQABACOAA6AgAAAP0bCgFIwAAWRydPf7BwCPoDAAAA/Hl9cPOzAAAAEAAFUBHgCFBAEAsgQCAHwFAgClBQIAyQUBAMAGBABBBwAAWQcAAPQHAQAICQIANgkBAC0MAwBbDAEAgwwDAOcMAQCfDgcB8A8BAG8QAgC3EAEAyhACAPgQAQCLEQAAvhEDAOkRAQCjEgAA4xIAABoTAQCCEwEApBMHAJwUBQA=") \ No newline at end of file diff --git a/pr/619/docs/search.index/7eed9b0d8ac9.js b/pr/619/docs/search.index/7eed9b0d8ac9.js new file mode 100644 index 000000000..6979364fa --- /dev/null +++ b/pr/619/docs/search.index/7eed9b0d8ac9.js @@ -0,0 +1 @@ +rn_("AQABsKAS0gABZTswAAABAAAJAAIA6QcHABMTAQABAAGgIAAADO5tAYQFAAABgAKwoBLQAAGwQA/aAAFsbwEAAPQNEwAAAQABAAEA8wQBZPSxEgAAAQABAAEAIwKEsKAUVQABsEATCwABsHAT/AABFYAAAScUAAABAAGwgBQ7AAFw8jcUAAABAEMAA6AgAAARYKBAAAAStWRlc/P5DwAATAMBAPOBAmVp1wIAAIawIBKWAAGw0BQ/AAEXAQL0oQQAAAEAAQDJAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/7f4f82681f3d.js b/pr/619/docs/search.index/7f4f82681f3d.js deleted file mode 100644 index 95660cd32..000000000 --- a/pr/619/docs/search.index/7f4f82681f3d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABNLc/TSDwAA8gMBAAQAAQECsGAUPgABsEAUfAABZHQ7MAAAAQAADQAGAP4SAwBpEwEA2RMBAPATAQBxFAEAmBQBAAEBA7BwEgEAAbCAEtsAAYATfgAQ+m1uczswAAABAAALAAIA9wgFAF4TBQCjgISwsBPHAAGxcBS7AAEIQIIBAIWgcAAAEqCwMBSvAAGgcAAAEQ+xABQ+AAGwABM/AWcGIQHyeAUAAAEAZwQAAIdcCByqjSOgEAAABauwMBMyAUmgQAAAETIRwQw7MAAAAQAABgACAIwTAAD0EwUA") \ No newline at end of file diff --git a/pr/619/docs/search.index/7f56256940f4.js b/pr/619/docs/search.index/7f56256940f4.js new file mode 100644 index 000000000..1de085dfe --- /dev/null +++ b/pr/619/docs/search.index/7f56256940f4.js @@ -0,0 +1 @@ +rn_("AYICsEASxwABsEASyQABNDYBCwDzxRMAAGwAAQABBgD0sxQAAAEACgABAPMCAXIBDxQAAPMDAWU7MAAAAQAABQACAH8QAwAwEQEA84ADYWVp") \ No newline at end of file diff --git a/pr/619/docs/search.index/desc/900a316ca624.js b/pr/619/docs/search.index/desc/900a316ca624.js new file mode 100644 index 000000000..ddd97da2f --- /dev/null +++ b/pr/619/docs/search.index/desc/900a316ca624.js @@ -0,0 +1 @@ +rd_("AmData flows in both directions0CdThe CE codepoint, signalling that congestion was \xe2\x80\xa600AjContains the success valueBeThe PathId of this path.BmReturns the PathId of this path.AoGet the identity of this stream00AfWhich path is now openAhWith path was abandoned.B`Which path had its state droppedAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa643210AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetClWhether a stream communicates data in both directions or \xe2\x80\xa60AhContains the error valueAoThe largest representable valueAlThe maximum path ID allowed.10ClConnects to a QUIC perf server and maintains a specified \xe2\x80\xa6BmData flows only from the stream\xe2\x80\x99s initiator0AnWhich directions data flows in0CaDirectionality for which streams have been openedCdDirectionality for which streams are newly availableCjExplicit congestion notification bits to set on the packet0CeThe Explicit Congestion Notification bits for the \xe2\x80\xa61CdReturns the most recently observed external address.B`The current best RTT estimation.BfThe number of I/O operations executed.0BcLength of QUIC packet being decodedAlLength of the packet payload0BmThe number of bytes the associated buffer hasBbSet a custom TokenLog0CaMinimum RTT registered so far for this estimator.ClConstruct with an approximate maximum memory usage and a \xe2\x80\xa6CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6DiCreates a new QlogConfig that writes a qlog trace to the \xe2\x80\xa6CiCreates a new qlog factory that writes files into the \xe2\x80\xa6D`Create a default config with a particular reset_keyCmCreate a default config with a particular handshake token \xe2\x80\xa6CkCreate a default config with a particular cryptographic \xe2\x80\xa6AmConstruct cid from byte arrayoConstruct emptyAeCreate a new StreamIdDjConstruct a state using the given config and current time \xe2\x80\xa60:8AeCreate a new endpointDcCreate a new instance of FixedLengthConnectionIdParserBdCreate a generator with a random key:987DgBegin decoding a QUIC packet from bytes, returning any \xe2\x80\xa67BkConstruct an error with a code and a reasonCgInitialize Random CID generator with a fixed CID length87BeCreates a new FourTuple.77BfQUIC transport protocol implementationCkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000BcExperimental! Use at your own risk.0ChThe ECT(0) codepoint, indicating that an endpoint is \xe2\x80\xa600ChThe ECT(1) codepoint, indicating that an endpoint is \xe2\x80\xa600CaA complete set of keys for a certain packet space0CbA Long packet header, as used during the handshakeChNot attributed to any particular FrameType.CkAn open network transmission within a multipath-enabled \xe2\x80\xa6Ab(Multi)Path eventsB`An error occurred during readingCeWhether an endpoint was the initiator of a connection0nThe 0 path id.0CaThe address observed by the remote over this path0CjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBlCurrent congestion window of the connection.0gPayloadAoReturns the argument unchanged.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCoMethod for opening a sealed message data in-place.B`Open a single stream if possible1CgReturns the Path structure of an open pathBhPing the remote endpoint over this path.AhPing the remote endpointCkCheck whether the timer has expired, and register to be \xe2\x80\xa6BaReturns application-facing eventsBgRead data contiguously from the stream.AoRead from the given recv streamCcDecode TransportParameters from bufferBiReceive an unreliable, unordered datagramBdMethod for sealing a token in-place.0CiQueue an unreliable, unordered datagram for immediate \xe2\x80\xa6CbSends a Transmit on the given socket.CmNumber of address validation tokens sent to a client when \xe2\x80\xa60BmThe side of the connection (client or server)ChLook up whether we\xe2\x80\x99re the client or server of this \xe2\x80\xa6AlMethod for signing a message0CdAmount of data written to the caller-supplied buffer0hSpin bitAcStop accepting data0BoStop accepting data on the given receive streamCiTry to find and take a token that was stored with the \xe2\x80\xa60BgA chunk of data from the receive stream0CiThe RFC8312 congestion controller, as widely used for TCP0Borustls reports protocol errors using this type.0DbErrors encountered while decoding TransportParametersCdErrors that the nat traversal state might encounter.BeEvents of interest to the applicationCiEvent emitted when the client receives ADD_ADDRESS or \xe2\x80\xa6CjAttributed to a specific FrameType, never \xe2\x80\xa6A`Any other error.0CcThe peer abandoned transmitting data on this streamCnThe peer is unable to continue processing this connection, \xe2\x80\xa6CdThe peer abandoned transmitting data on this stream.1AeA Retry packet headerCdA short packet header, as used during the data phaseCmBest-effort extraction of the ALPN protocols from the TLS \xe2\x80\xa60BiConstruct a fresh Controller0AiThe contents of the chunkCiThe total amount of bytes which have been transferred \xe2\x80\xa6BjThe amount of bytes which had been written210BnUnderlying error describing reason for failureBaClose the connection immediately.CnClose all of this endpoint\xe2\x80\x99s connections immediately and \xe2\x80\xa6AaCloses this path.AnClose a connection immediatelyBcFrame type that triggered the errorCcDistinguishes streams of the same initiator and \xe2\x80\xa60CjReturns whether the codepoint is a CE, signalling that \xe2\x80\xa60AgKey for encrypting data0BgParse a connection id from given bufferAhReturns all known paths.BlUpdate the timer to expire at iBbClose the send stream immediately.BeAbandon transmitting data on a streamCnRespond with a retry packet, requiring the client to retry \xe2\x80\xa60CiDrive future to completion in the backgroundCeShow connection stats the at the end of the benchmarkAmReturns connection statisticsBiReturns relevant stats from this EndpointCaReturns the PathStats for this path.2BcTitle to record in the qlog capture0CmWrite a buffer into this stream, returning how many bytes \xe2\x80\xa6AmSend data on the given streamCcEncode TransportParameters into bufferC`Future produced by Endpoint::acceptClPaths marked as backup will only be used if there are no \xe2\x80\xa60CeChunks returned from RecvStream::read().AmThe initiator of a connectionAdRun as a perf client1CgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6BcThe receiver lagged too far behind.CcFuture produced by Connection::open_biAjA new path has been opened0ChOne or more new streams has been opened and might be \xe2\x80\xa6ChId representing different paths when using multipath \xe2\x80\xa60AbCoding result typeAlThe acceptor of a connectionAdRun as a perf server1mStream eventsAiAn integer less than 2^620CfGet the next incoming connection attempt from a clientClAttempt to accept this incoming connection (an error may \xe2\x80\xa6CcAccept a remotely initiated stream of a certain \xe2\x80\xa61C`The amount of full chunks which had been written0BlAllows to configure the desired cipher suiteCiHelper to construct an endpoint for use with outgoing \xe2\x80\xa6CcWait for the connection to be closed for any reasonAfCoding related traits.BnAccess the configuration used by this endpointChTraits and implementations for the QUIC cryptography \xe2\x80\xa6BjCreate QUIC error code from TLS alert codeBoTLS configuration used for incoming connections210BkAn underlying crypto (e.g. TLS) layer errorCgDecode a plain header from given buffer, with given \xe2\x80\xa6DiDecode a Self from the provided buffer, if the buffer is \xe2\x80\xa6ChThe destination IP address which was encoded in this \xe2\x80\xa6D`Append the encoding of self to the provided buffer.CmNotify the peer that no more data will ever be written to \xe2\x80\xa6CnFinish a send stream, signalling that no more data will be \xe2\x80\xa6B`Process an incoming UDP datagramAfHeader protection keys0ClIgnore this incoming connection attempt, not sending any \xe2\x80\xa60C`Potentially store a token for later one-time use0CfPerform NSS-compatible TLS key logging to the file \xe2\x80\xa6AhThe offset in the stream0B`Packet deliveries were confirmed0AfPacket protection keys0lRandom valueBcHuman-readable reason for the close0BcReason why this path was abandoned.11BhHuman-readable explanation of the reasonBeReason that the connection was closed2AjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataBoReturns the remote address of the network path.1AmTLS interface based on rustls0CnHelper to construct an endpoint for use with both incoming \xe2\x80\xa6BkOptional source IP address for the datagram00CgThe current local PathStatus of this path.B`The new status set by the remote0CfThe size of a single datagram in the associated bufferCkStatistics about datagrams and bytes received on this path.CjStatistics about UDP datagrams received on the connection.10CgStatistics about datagrams and bytes sent on this path.CeStatistics about UDP datagrams transmitted on the \xe2\x80\xa610AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0A`Send would blockCcNo more data is currently available on this stream.CjThe peer is not able to accept additional data, or the \xe2\x80\xa6BfA catch-all error for unlikely errors.0BlA key for signing with HMAC-based algorithms0AhAn Initial packet headerBnA pair of keys for bidirectional communication0BhA simple, standard congestion controller0CdFuture produced by Connection::open_uniCkAbstracts I/O and timer operations for runtime independenceBfA cryptographic session (commonly TLS)0CcThe peer is no longer accepting data on this streamCfFuture returned from SendStream::stopped.ClThe peer is no longer accepting data on this stream, and \xe2\x80\xa6CkThe peer is no longer accepting data on this stream. No \xe2\x80\xa6CgThe peer asked us to stop sending on an outgoing streamAaAccess to streamsCaThe stream is larger than the user-supplied limitCnAttributed to some frame type this implementation does not \xe2\x80\xa6ClIndicates how many bytes and chunks had been transferred \xe2\x80\xa60l0-RTT packetCjReturns the length of a CID for connections created by \xe2\x80\xa60CdProvide the length of dst_cid in short header packetCcThe total number of clients which should be createdAlConnect to a remote endpointAeInitiate a connectionBbDecrypt the Initial packet payloadCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header210ClConstructs a value with arbitrary fields, intended to be \xe2\x80\xa6DjConstruct an event that indicating that a Connection will \xe2\x80\xa6BkThe destination connection ID of the packetBkThe destination Connection ID of the packetAiDestination Connection ID00000CgEncrypt the packet payload with the given packet numberBcEncrypt the given packet\xe2\x80\x99s header10CbCheck if this stream has been opened during 0-RTT.0CmRetrieve implementation-specific metrics used to populate \xe2\x80\xa60CnThe maximum UDP payload size guaranteed to be supported by \xe2\x80\xa60CjUniform interface to send and receive UDP packets with \xe2\x80\xa6BbOne or more packets were just sent0BmInitiate a new outgoing bidirectional stream.CaReturns the path ID of the new path being opened.AdSource Connection ID0000CiCompletes when the peer stops the stream or reads the \xe2\x80\xa6CjCheck if this stream was stopped, get the reason if it wasCcThe total number of streams which should be createdAlProvide control over streamsCeThe length of the AEAD tag appended to packets on \xe2\x80\xa60CdUpgrade the handle to a full ConnectionB`Upgrades to a Path.AkSet the QUIC version to use0lQUIC versionB`The version that was unsupported11CeFuture produced by Connection::accept_biAfAn unreliable datagramBdDatagram support is disabled locally0A`A QUIC endpoint.BcThe main entry point to the libraryChA finished stream has been fully acknowledged or stoppedCkAn incoming connection for which the server has not yet \xe2\x80\xa60BoLong packet types with uniform header structureB`The largest encoded value length0Cmthe connection is being closed abruptly in the absence of \xe2\x80\xa60CeFuture returned by Connection::on_closedClFuture produced by crate::Connection::open_pathCmA currently open stream likely has data or errors waiting \xe2\x80\xa6CkMetadata for a single buffer filled with bytes received \xe2\x80\xa6BkResponse generated directly by the endpointCfIdentifier for a stream within a particular connection0CnCommunication with the peer has lapsed for longer than the \xe2\x80\xa6CkWe didn\xe2\x80\x99t receive any data from the remote within the \xe2\x80\xa61ChResponsible for limiting clients\xe2\x80\x99 ability to reuse \xe2\x80\xa60ClThe datagram is larger than the connection can currently \xe2\x80\xa60AbAn outgoing packet00CmStatistics about UDP datagrams transmitted or received on \xe2\x80\xa60CnA formerly write-blocked stream might be ready for a write \xe2\x80\xa6AkCongestion algorithm to useAhContents of the datagramBoMark the read data as consumed from the stream.BnStatistics about frames received on this path.CcStatistics about frames received on the connection.10CaStatistics about frames transmitted on this path.CfStatistics about frames transmitted on the connection.10DhConstructs cid by reading len bytes from a Buf0DkCreates a new qlog factory that writes files into QLOGDIR, \xe2\x80\xa60BfCreate a generator with a specific keyBjConstruct a VarInt infallibly0BeSucceeds iff x < 2^620AeWhat type we receivedAoWhat handshake type we received10CbWhether 0-RTT is/was possible during the handshakeCmSpecifies the time to wait after completing MTU discovery \xe2\x80\xa60CcReturns Self for use in down-casting to extract \xe2\x80\xa60EhReturns true if the Connection associated with this handle \xe2\x80\xa6CmDuration after an address validation token was issued for \xe2\x80\xa60CeThe local IP address which was used when the peer \xe2\x80\xa60BjThe local IP used for this path, if known.1BnReturns the local address of the network path.ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BnInitiate a new outgoing unidirectional stream.BcGet the priority of the send streamAlGet the priority of a streamCfThe negotiated application protocol, if ALPN is in use0Aeqlog output directoryBbOptional response to transmit backCiOptional seed to be used internally for random number \xe2\x80\xa60AlSlow start threshold (bytes)0BeSucceeds iff x < 2^6200000DaSends a Transmit on the given socket without any \xe2\x80\xa6DkQuickly determine whether cid could have been generated by \xe2\x80\xa600BmA path was abandoned and is no longer usable.0CfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa60CnAt least one new stream of a certain directionality may be \xe2\x80\xa6BkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.CkA path was discarded and all remaining state for it has \xe2\x80\xa60BgInfallible encoding of QUIC primitives.CnIdentifies a network path by the combination of remote and \xe2\x80\xa6A`Handshake packetBcKeys used to protect packet headers0CiCatch-all error for problems while decoding transport \xe2\x80\xa6CeNat traversal attempt failed due to a multipath errorBdKeys used to protect packet payloads0BmErrors that might trigger a path being closed0AnApplication events about paths0BjStatistics related to a transmission path.0AeA read error occurredBmErrors that arise from reading from a stream.C`Errors triggered when reading from a recv streamCiAn object for asynchronously writing to an associated \xe2\x80\xa6BmAccept the next incoming bidirectional streamBbDuplicate the controller\xe2\x80\x99s state0BeThe number of UDP datagrams observed.AaControl datagrams1BeCreate new object from the given bits00BoWhich side of a connection initiated the stream0CmConvert into a 0-RTT or 0.5-RTT connection at the cost of \xe2\x80\xa6BoShorthand for self == Side::Client0B`Whether the connection is closedBoShorthand for self == Side::Server0CbWhether it is legal to respond with a retry packet0CdWhether to allow clients to migrate to new addresses0CdConstruct a timer that will expire at iBoLow-level protocol logic for the QUIC protoocolCjWait for the connection to be closed without keeping a \xe2\x80\xa6CjOpens an additional path if the multipath extension is \xe2\x80\xa6A`Opens a new pathBmPing the remote endpoint over a specific pathCiAttempts to read from the stream into the provided bufferCeReceive UDP datagrams, or register to be woken if \xe2\x80\xa6CkSend a UDP datagram, or register to be woken if sending \xe2\x80\xa6ClPrivate key used to send authenticated connection resets \xe2\x80\xa60BmGenerate the integrity tag for a retry packet0BgA stable identifier for this connectionCePrivate key used to authenticate data included in \xe2\x80\xa60BlThe position of a token in the packet bufferCgTransport configuration to use for incoming connections0CjWait for all connections on the endpoint to be cleanly \xe2\x80\xa6BoWrite a buffer into this stream in its entiretyCiAbstract implementation of an async timer for runtime \xe2\x80\xa6BoNumber of UDP packets to send/receive at a timeCmConfiguration for the Bbr3 congestion controller0CkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1101BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CjNumber of frames transmitted or received of each frame \xe2\x80\xa60BoThe connection ID was not recognized by the \xe2\x80\xa60DdThe type used to refer to FrameTypes in closing and \xe2\x80\xa6DbA stream of PathEvents for all paths in a connection.AnThe QUIC-MULTIPATH path status0BeConfiguration for qlog trace logging.0BnA stream that can only be used to receive dataAaAccess to streamsChErrors that arise while waiting for a stream to be resetDhError for attempting to retry an Incoming which already \xe2\x80\xa60BkA stream that can only be used to send data3BmObject to get current SystemTime0AdA rustls TLS session0CkResponsible for storing validation tokens received from \xe2\x80\xa60AeA borrowed UDP socketBjErrors that arise from writing to a streamBoErrors triggered while writing to a send streamBoAccept the next incoming uni-directional streamCkWhether the implementation is permitted to set the spin \xe2\x80\xa60CiCloses a path and sends a PATH_ABANDON frame with the \xe2\x80\xa6CdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10CaThe error code to be sent with the abandon frame.BoThe error that was sent with the abandon frame.AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0CnWhether there is no longer any need to keep the connection \xe2\x80\xa6DkDetermine whether this is the last event a Connection will \xe2\x80\xa6CiLook up the local IP address and port used by this socketDgGet the local SocketAddr the underlying socket is bound toBfThe number of bytes lost on this path.BkThe number of bytes lost on the connection.10CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statisticsCjThe final path stats, they are no longer available via \xe2\x80\xa610C`Attempt to write bytes from buf into the stream.AmRead the next segment of dataAoReads the next segment of data.CkRead an exact number of bytes contiguously from the stream.BnSets the PathStatus of this path.BoEpoch qlog event times are recorded relative to0ClError type for attempting to accept an IncomingBjErrors in the configuration of an endpoint0AeGeneric crypto errors0CnConfiguration for the Cubic congestion controller0CdReasons why attempting to finish a stream might failCnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60AnValue exceeds supported bounds0D`Constructs a QlogConfig for individual connections.0AfA noq runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CeLargest UDP payload size the path currently supports.ClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00DcCreates a new FourTuple without a known local address.BkStarting guess for maximum UDP payload sizeCkThe initial value to be used as the maximum UDP payload \xe2\x80\xa60ChUDP payload size that the network must be capable of \xe2\x80\xa6BjThe RTT used before an RTT sample is taken0BfThe initial round-trip-time (in msecs)CeThe amount of concurrent streams which should be usedDdPackets are acked in batches, all with the same now \xe2\x80\xa60AePacing rate (bytes/s)0DeA stream of PathEvents for all paths in this connection.DfGets the local PathStatus for a known PathIdAnRead the next segments of dataCkConvenience method to read all remaining data into a bufferAlProvide control over streamsBoThe sample size used for this key\xe2\x80\x99s algorithm01CiMaximum number of bytes to transmit to a peer without \xe2\x80\xa600BoThe server name specified by the client, if any0BmObject to get current SystemTime0BdSet a custom TokenStore0CaNumber of bytes to transmit from client to serverCnSpecifies the upper bound to the max UDP payload size that \xe2\x80\xa60ChReturns a weak reference to the inner connection struct.CdReturns a WeakPathHandle for this path.DgCreate a server config with the given crypto::ServerConfig0CeSets a prefix to the filename of the generated files.0DbWrite a single Bytes into this stream in its entiretyBbAn ADD_ADDRESS frame was received.BfConfiguration for outgoing connectionsCaClient-side configuration for the crypto protocol10CgThe stream has already been stopped, finished, or resetBmThe stream has already been finished or resetCmError indicating that a stream has not been opened or has \xe2\x80\xa6CjThe stream has not been opened or was already stopped, \xe2\x80\xa6CfThe stream has not been opened or has already been \xe2\x80\xa6CmThe stream has not been opened or was already finished or \xe2\x80\xa63CgErrors in the parameters being used to create a new \xe2\x80\xa60BkProtocol-level identifier for a connection.0CkWe couldn\xe2\x80\x99t decrypt a message. This is invariably fatal.0BjExplicit congestion notification codepoint00CnWe couldn\xe2\x80\x99t encrypt a message because it was larger than \xe2\x80\xa60BhParameters that are semantically invalidCkCannot close the last remaining open path via the local \xe2\x80\xa60Akn0\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa60CiFuture produced by Connection::read_datagramBiThe remote changed the status of the path0BlRTT estimation for a particular network pathCnFuture produced by Connection::send_datagram_waitBiParameters governing incoming connectionsCaServer-side configuration for the crypto protocol10CmErrors that arise while monitoring for a send stream stop \xe2\x80\xa6AgA noq runtime for TokioC`Returns the lifetime of generated Connection IDs0BjWhether the connection is closed, and why.CjConnect to a remote endpoint using a custom configuration.AlConservative estimate of RTTBnGet the 0-RTT keys if available (clients only)0AgWhich types we expectedB`Which handshake type we expected10AcGenerates a new CID0ClThe number of segments to read when GRO is enabled. Used \xe2\x80\xa6DeProcess ConnectionEvents generated by the associated \xe2\x80\xa6EaProcess EndpointEvents emitted from related ConnectionsCgCreate the initial set of keys given the client\xe2\x80\x99s \xe2\x80\xa6000BhThe number of packets lost on this path.BmThe number of packets lost on the connection.10DcMaximum number of Incoming to allow to exist at a time0CjWhether datagrams might get fragmented into multiple parts0CmWhether transmitted datagrams might get fragmented by the \xe2\x80\xa6CkReturns the path\xe2\x80\x99s network path represented as a 4-tuple.CkThe original destination CID when initiating the connectionCiThe original destination connection ID sent by the clientDhReturns the next time at which handle_timeout should be \xe2\x80\xa6D`Configures qlog capturing by setting a QlogFactory.0AgThe runtime type to useCkThe segment size if this transmission contains multiple \xe2\x80\xa600CkSend Quantum (bytes) used to control the size of packet \xe2\x80\xa60ChThe number of streams that may have unacknowledged data.CbSet the lifetime of CIDs created by this generator0BcSet the priority of the send streamAlSet the priority of a streamCnInitialize a QUIC-compatible TLS client configuration with \xe2\x80\xa6000DgWrite a slice of Bytes into this stream, returning how \xe2\x80\xa6AmSend data on the given streamCkWe received a fatal alert. This means the peer is unhappy.0BhBloom filter-based TokenLog0CmThe connection could not be created because not enough of \xe2\x80\xa6000CaEvent resulting from processing a single datagramBlEvents sent from a Connection to an EndpointAoStatistics on Endpoint activityBnThe stream finished before all bytes were readBlAuthentication data for (rustls) TLS session0Ccreceived an invalid Retry Token in a client Initial0ChIterator over ALPN protocol names from a TLS ClientHelloAlThe packet header is invalidBkThe local application closed the connection0DaThe datagram may result in starting a new ConnectionD`Configuration for the NewReno congestion controller0BjDecodes a QUIC packet\xe2\x80\x99s invariant headerCgErrors triggered when opening a recv stream for readingCaDefault implementation of TimeSource0CgError indicating that the provided buffer was too smallChFor clients, if the peer accepted the 0-RTT data packetsAbAck Frequency modeAfExports for benchmarksBoSupply a custom connection ID generator factory0DgCreate a UdpSender that can register a single task for \xe2\x80\xa6CaNumber of bytes to transmit from server to clientAmGet the Incoming0CnThe max_ack_delay we will request the peer to use0CgDisable packet encryption/decryption (for debugging \xe2\x80\xa6CkThe known MTU for the current network path has been updated0BbCryptographic identity of the peerBgGet the peer\xe2\x80\x99s identity, if availableDhFor the rustls TlsSession, the Any type is \xe2\x80\xa610AkReturns packets to transmitDjConfigures qlog capturing through the QLOGDIR environment \xe2\x80\xa60AoReceive an application datagramDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CmWhether to implement fair queuing for send streams having \xe2\x80\xa60BfLength of sign\xe2\x80\x99s output0BnStart a client session with this configurationBnStart a server session with this configuration10BdA REMOVE_ADDRESS frame was received.CgAbstract implementation of a UDP socket for runtime \xe2\x80\xa6BgErrors triggered when abandoning a path0AgThe connection was lost00000ChGlobal configuration for the endpoint, affecting all \xe2\x80\xa60Cithe endpoint encountered an internal error and cannot \xe2\x80\xa60FbBasic adapter to let Incoming be await-ed like a ConnectingBhEncounter a frame ID that was not valid.CeThe peer sent us a TLS message with invalid contents.0Amno viable network path exists0DhNull implementation of TokenStore, which does not store \xe2\x80\xa60CiThe peer deviated from the standard TLS protocol. The \xe2\x80\xa60BmErrors that arise from reading from a stream.C`Errors from RecvStream::read_to_endCaIndicates whether a frame needs to be transmittedCmThe peer violated the QUIC specification as understood by \xe2\x80\xa60CiTransport-level errors occur when a peer violates the \xe2\x80\xa6C`Tokio-compatible UDP socket with some useful \xe2\x80\xa6DiWeak handle for a Path that does not keep the connection \xe2\x80\xa6BnCreate a client endpoint and client connectionAgGet a session referenceDiReturns a QlogConfig for a connection, if logging should \xe2\x80\xa60AiProcess timer expirationsBjParameters negotiated during the handshake0CfGet data negotiated during the handshake, if available0AiInitial congestion windowCiDefault limit on the amount of outstanding data in bytes.001000BnConverts this stream into an unordered stream.DdReturns true until the connection is fully established.CeWhether the connection is in the process of being \xe2\x80\xa61BfVerify the integrity of a retry packet0CnSpecifies the minimum MTU change to stop the MTU discovery \xe2\x80\xa60BdCompute keys for the next key update0AhOne packet was just lost0AhOne packet was just sent0BkConfigures qlog capturing into a directory.0AlRead bytes of handshake data0BeWhether to use the unordered read APIClMaximum number of bytes the peer may transmit across all \xe2\x80\xa600CkCompletes when the stream has been reset by the peer or \xe2\x80\xa60CiCheck whether this stream has been reset by the peer, \xe2\x80\xa6AjThe peer\xe2\x80\x99s UDP addressesAhThe peer\xe2\x80\x99s UDP addressBgThe peer\xe2\x80\x99s UDP address for this path.1CeSaturating integer addition. Computes self + rhs, \xe2\x80\xa6000ChSaturating integer subtraction. Computes self - rhs, \xe2\x80\xa60CkMaximum reordering in time space before time based loss \xe2\x80\xa60ChReason given by the transport for closing the connection0BfReasons why a connection might be lost0CiThe datagram is redirected to its ConnectionBlEvents sent from an Endpoint to a ConnectionAfConnection statistics.0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0AkThe remote closed the path.CfError for when a validation token may have been reused0C`Parameters governing the core QUIC state machine0CbThe peer doesn\xe2\x80\x99t implement any supported version0CdFuture that completes when a connection is fully \xe2\x80\xa6CbThis was a 0-RTT stream and the server rejected it000CjAutomatically select an appropriate runtime from those \xe2\x80\xa6CkWhether to accept QUIC packets containing any value for \xe2\x80\xa60CdMaximum number of incoming packets that may fail \xe2\x80\xa60CnThe interface index of the interface on which the datagram \xe2\x80\xa6AjSwitch to a new UDP socketCiCreates a server endpoint which runs on the given runtimeD`Sets the PathStatus for a known PathIdCfSee proto::TransportConfig::send_window()BoSee TransportConfig::send_window()BmReturns whether a frame should be transmittedD`Convert t into the socket type used by this runtimeCdWrites handshake bytes into the given buffer and \xe2\x80\xa60ClStream produced by Path::observed_external_addrCiReason given by an application for closing the connection0CbThe peer\xe2\x80\x99s QUIC stack aborted the connection \xe2\x80\xa60DjInternal identifier for a Connection currently associated \xe2\x80\xa6CdOne or more application datagrams have been receivedBjDecrypted payload of a QUIC Initial packet0CaThe endpoint can no longer create new connections0Cnreceived a STREAM frame or a RESET_STREAM frame containing \xe2\x80\xa60ClSpecific failure cases from keys_match or a \xe2\x80\xa60A`key update error0CaCurrent limits do not allow us to open more paths0ClThe peer doesn\xe2\x80\x99t support a protocol version/feature we \xe2\x80\xa60BjA QUIC-compatible TLS client configuration0BjA QUIC-compatible TLS server configuration0EfTokenStore implementation that stores up to N tokens per \xe2\x80\xa60CgAn endpoint (local or remote) tried to add too many \xe2\x80\xa6CaPath could not be validated and will be abandonedCmWe didn\xe2\x80\x99t receive a path response in time after opening \xe2\x80\xa61BcA Version Negotiation packet headerCiRecord that the token was used and, ideally, return a \xe2\x80\xa60CjCurrent state of the congestion control algorithm, for \xe2\x80\xa6CcCurrent state of this connection\xe2\x80\x99s congestion \xe2\x80\xa6BaUpdate traffic keys spontaneously0CnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60Cgn0\xe2\x80\x99s (https://n0.computer) NAT Traversal protocol \xe2\x80\xa6CeGet the number of connections that are currently openBmNumber of connections that are currently openCiOpens a new path if no path exists yet for the remote \xe2\x80\xa6CmOpens a new path only if no path on the same network path \xe2\x80\xa6CiMaximum reordering in packet number space before FACK \xe2\x80\xa60CfGet the size of the socket receive bufferAlReceive buffer size in bytesCcGet the size of the socket send bufferAiSend buffer size in bytesBiSet a custom TransportConfig000ChConfiguration for sending and handling validation tokens0CnCreate a server config with the given certificate chain to \xe2\x80\xa60DdWrite a slice of Bytes into this stream in its entiretyCfthe application or application protocol caused the \xe2\x80\xa60AnThe peer closed the connectionBoThe path was closed locally by the application.1B`Constructs controllers on demand0CnCommon congestion controller metrics used both for logging \xe2\x80\xa60ClThe trait for encrypting tokens that power retry packets \xe2\x80\xa60BcThe given server name was malformed0CbHints when the caller identifies a network change.0AcPacket decode errorBdReason for why a path was abandoned.BmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BdCongestion events on the connection.0AiCongestion window (bytes)0ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BoBytes available in the outgoing datagram bufferClReplace the server configuration, affecting new incoming \xe2\x80\xa60Cmthe endpoint has reached the confidentiality or integrity \xe2\x80\xa60CkParameters for controlling the peer\xe2\x80\x99s acknowledgement \xe2\x80\xa60DjThe max_fragment_size value supplied in configuration was \xe2\x80\xa60Bmthe server refused to accept a new connection0BjParse connection id in short header packetCjOne or more application datagrams have been sent after \xe2\x80\xa6Ckreceived more data than permitted in advertised data limits0AoThe TLS handshake was confirmedBjThe connection\xe2\x80\x99s handshake data is readyCeAttempted an ordered read following an unordered readAnWe saw an invalid certificate.0BcParameters governing MTU discovery.0BnNot enough addresses to complete the operationCkdetected an error with protocol compliance that was not \xe2\x80\xa60Cjreceived a frame for a stream identifier that exceeded \xe2\x80\xa60Cnreceived a frame for a stream that was not in a state that \xe2\x80\xa60AnError from setting path status0AjTransport-level error code0ChThe local endpoint does not support the QUIC version \xe2\x80\xa6CkError indicating that the specified QUIC version is not \xe2\x80\xa61C`Packet uses a QUIC version that is not supported1CiMaximum quantity of out-of-order crypto layer data to \xe2\x80\xa60C`Create a VarInt without ensuring it\xe2\x80\x99s in range0ChCumulative number of Quic handshakes ignored on this \xe2\x80\xa6EgReturns true if the two WeakConnectionHandle point at the \xe2\x80\xa6CiMinimum interval between outgoing stateless reset packets0CjConstruct with an approximate maximum memory usage and \xe2\x80\xa60ChCumulative number of Quic handshakes refused on this \xe2\x80\xa6AnReturns the remote path statusDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CnUpdates the set of ALPN protocols configured in the client \xe2\x80\xa6CnUpdates the set of ALPN protocols configured in the server \xe2\x80\xa610CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60CcA stream of NAT traversal updates for a connection.BkNo remote CIDs available to open a new path0CkTransport parameters used to negotiate connection-level \xe2\x80\xa6CgA stream that can be used to receive data out-of-order.CmThe certificate verifier doesn\xe2\x80\x99t support the given type \xe2\x80\xa60CfThe operation is not allowed for this endpoint\xe2\x80\x99s \xe2\x80\xa6CiCumulative number of Quic handshakes accepted by this \xe2\x80\xa6CjSpecifies the amount of time that MTU discovery should \xe2\x80\xa60CiIf the 0-RTT-encrypted data has been accepted by the peer0BgWait for the handshake to be confirmed.CgInform the connection if a path may recover after a \xe2\x80\xa60CgPeriod of inactivity before sending a keep-alive packet0CfThe number of PLPMTUD probe packets lost on this path.0BlPackets were deemed lost or marked congested0CgCumulative number of Quic handshakes sent from this \xe2\x80\xa6CnThe number of remotely initiated open streams of a certain \xe2\x80\xa6AhBench fns for SendBufferCfThe number of PLPMTUD probe packets sent on this path.0Bireceived a frame that was badly formatted0CkThis function doesn\xe2\x80\x99t work until the TLS handshake is \xe2\x80\xa60CkWe received a TLS message that isn\xe2\x80\x99t valid right now. \xe2\x80\xa60CkThe remote address for the path is not supported by the \xe2\x80\xa6CiThe remote SocketAddr supplied was malformed10ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60CnWatches the external address reported by the peer for this \xe2\x80\xa6BdPaths can only be opened client-side0DmError returned when constructing a VarInt from a value >= \xe2\x80\xa60CeA handle to some connection internals, use with care.DkSpecifies the ACK frequency config (see AckFrequencyConfig \xe2\x80\xa60CjThe number of times a black hole was detected in the path.0CgMaximum number of received bytes to buffer for each \xe2\x80\xa60AeIs multipath enabled?ClMaximum number of datagrams that might be described by a \xe2\x80\xa60CkMaximum UDP payload size accepted from peers (excluding \xe2\x80\xa60AmMax UDP payload size in bytesDkSpecifies the MTU discovery config (see MtuDiscoveryConfig \xe2\x80\xa60AmReturn endpoint-facing eventsCkThe preferred IPv4 address that will be communicated to \xe2\x80\xa60CkThe preferred IPv6 address that will be communicated to \xe2\x80\xa60ChThe reordering threshold we will request the peer to use0ClDuration after a retry token was issued for which it\xe2\x80\x99s \xe2\x80\xa60BmSets the max idle timeout for a specific pathDfResize the receive buffer of socket to bytesDcResize the send buffer of socket to bytesBfThe peer\xe2\x80\x99s QUIC transport parametersBdQUIC connection transport parameters1CaGenerates connection IDs for incoming connections0CdAn incoming connection did not support any known \xe2\x80\xa60BjNo default client configuration was set up0BiPath abandoned due to unstable interfaces0ClConfiguration for sending and handling validation tokens \xe2\x80\xa60CmMaximum number of packets that may be sent using a single \xe2\x80\xa60CiNotify connections that the local network address has \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0CfA stream of NAT traversal updates for this connection.CjGet the address observed by the remote over the given pathCiMaximum number of bytes the peer may transmit without \xe2\x80\xa600Chreceived more data in CRYPTO frames than can be buffered0B`The extension was not negotiatedCbWe failed to figure out what time it currently is.0CbWe failed to acquire random bytes from the system.0CnError indicating that this operation requires multipath to \xe2\x80\xa6BnThe extension was not negotiated with the peerAkMultipath is not negotiated210CnError when the multipath extension was not negotiated, but \xe2\x80\xa6CjThe path was opened in a NAT traversal round which was \xe2\x80\xa6BnHeader of an Initial packet, before decryptionCgDerive keying material from this connection\xe2\x80\x99s TLS \xe2\x80\xa6EdFill output with output.len() bytes of keying material \xe2\x80\xa60BnPathological case: many segments, get from endCfGet segments in the old way, using a loop of get callsClCurrent number of remotely initiated streams that may be \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa60CmCreate a client configuration that trusts specified trust \xe2\x80\xa60BkThe peer didn\xe2\x80\x99t give us any certificates.0BkThe peer sent an oversized record/fragment.0CkThe ack-eliciting threshold we will request the peer to use0BiWhether there are any pending retransmitsCdWhether the Multipath for QUIC extension is enabled.CbThe peer\xe2\x80\x99s ACK-frequency parameters have changed0C`Sets the keep_alive_interval for a specific pathBoSet a custom ValidationTokenConfig0BmPath abandoned at the application\xe2\x80\x99s request0CjGet the current value of max_udp_payload_size0ChConfigure how to populate the destination CID of the \xe2\x80\xa60CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6CfWhether the socket address that is initiating this \xe2\x80\xa60CmModify the number of open paths allowed when multipath is \xe2\x80\xa6Cmthe number of connection IDs provided by the peer exceeds \xe2\x80\xa60CbError returned by Session::export_keying_material.0CiA provided certificate revocation list (CRL) was invalid.0CmPath abandoned due to no available connection IDs for the \xe2\x80\xa60Clreceived transport parameters that were badly formatted, \xe2\x80\xa60CiRegisters one address at which this endpoint might be \xe2\x80\xa6ClAdd addresses the local endpoint considers are reachable \xe2\x80\xa6ClMaximum number of outgoing application datagram bytes to \xe2\x80\xa60CiSet the client configuration used by connectBnSets the max_idle_timeout for a specific path.BfThe QUIC protocol version implemented.CfThe path became unusable after a local network change.BoBytes available in the outgoing datagram bufferDhMaximum number of received bytes to buffer for all Incoming0DaVariant of max_concurrent_bidi_streams affecting \xe2\x80\xa60ClModify the number of remotely initiated streams that may \xe2\x80\xa6BmSpurious congestion events on the connection.0CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CkGenerates 8-byte connection IDs that can be efficiently \xe2\x80\xa6CkAn error occurred while handling Encrypted Client Hello \xe2\x80\xa60CkPath abandoned due to resource limitations in the transport0CiGenerates purely random connection IDs of a specified \xe2\x80\xa6ChWhether to use \xe2\x80\x9cGeneric Segmentation Offload\xe2\x80\x9d to \xe2\x80\xa60CmMaximum number of incoming bidirectional streams that may \xe2\x80\xa60BhUpdates this tuple\xe2\x80\x99s local address iffClMaximum number of incoming application datagram bytes to \xe2\x80\xa60BcInitiates a new nat traversal round0BdPackets were incorrectly deemed lostCaequivalent to BBRHandleSpuriousLossDetection: \xe2\x80\xa610CnRemoves one or more addresses from the set of addresses at \xe2\x80\xa6CgRemoves an address the endpoing no longer considers \xe2\x80\xa6C`Sets the keep_alive_interval for a specific pathDeA ConnectionIdParser implementation that assumes the \xe2\x80\xa6CjWe received a TLS handshake message that isn\xe2\x80\x99t valid \xe2\x80\xa60CiHow to construct new congestion::Controllers0BlSets a default per-path maximum idle timeout0CkConfigures an outbound rate limit (in bytes per second) \xe2\x80\xa60BoThe key exchange group negotiated with the peer0CbWhether to send observed address reports to peers.0CiModify the number of remotely initiated bidirectional \xe2\x80\xa6BiEnables the Multipath Extension for QUIC.0CjModify the number of remotely initiated unidirectional \xe2\x80\xa6CeNumber of consecutive PTOs after which network is \xe2\x80\xa60BkSets a default per-path keep alive interval0CjWhether to receive observed address reports from other \xe2\x80\xa60BmGet the current local nat traversal addresses0CkGet the currently advertised nat traversal addresses by \xe2\x80\xa60AcNat traversal draftCkSets the maximum number of nat traversal addresses this \xe2\x80\xa60CjWhen multipath is required and has not been explicitly \xe2\x80\xa6") \ No newline at end of file diff --git a/pr/619/docs/search.index/desc/b4a947a8a2ee.js b/pr/619/docs/search.index/desc/b4a947a8a2ee.js deleted file mode 100644 index 826468f20..000000000 --- a/pr/619/docs/search.index/desc/b4a947a8a2ee.js +++ /dev/null @@ -1 +0,0 @@ -rd_("AmData flows in both directions0CdThe CE codepoint, signalling that congestion was \xe2\x80\xa600AjContains the success valueBeThe PathId of this path.BmReturns the PathId of this path.AoGet the identity of this stream00AfWhich path is now openAhWith path was abandoned.B`Which path had its state droppedAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa643210AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetClWhether a stream communicates data in both directions or \xe2\x80\xa60AhContains the error valueAoThe largest representable valueAlThe maximum path ID allowed.10ClConnects to a QUIC perf server and maintains a specified \xe2\x80\xa6BmData flows only from the stream\xe2\x80\x99s initiator0AnWhich directions data flows in0CaDirectionality for which streams have been openedCdDirectionality for which streams are newly availableCjExplicit congestion notification bits to set on the packet0CeThe Explicit Congestion Notification bits for the \xe2\x80\xa61CdReturns the most recently observed external address.B`The current best RTT estimation.BfThe number of I/O operations executed.0BcLength of QUIC packet being decodedAlLength of the packet payload0BmThe number of bytes the associated buffer hasBbSet a custom TokenLog0CaMinimum RTT registered so far for this estimator.ClConstruct with an approximate maximum memory usage and a \xe2\x80\xa6CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6DiCreates a new QlogConfig that writes a qlog trace to the \xe2\x80\xa6CiCreates a new qlog factory that writes files into the \xe2\x80\xa6D`Create a default config with a particular reset_keyCmCreate a default config with a particular handshake token \xe2\x80\xa6CkCreate a default config with a particular cryptographic \xe2\x80\xa6AmConstruct cid from byte arrayoConstruct emptyAeCreate a new StreamIdDjConstruct a state using the given config and current time \xe2\x80\xa60:8AeCreate a new endpointDcCreate a new instance of FixedLengthConnectionIdParserBdCreate a generator with a random key:987DgBegin decoding a QUIC packet from bytes, returning any \xe2\x80\xa67BkConstruct an error with a code and a reasonCgInitialize Random CID generator with a fixed CID length87BeCreates a new FourTuple.77BfQUIC transport protocol implementationCkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000BcExperimental! Use at your own risk.0ChThe ECT(0) codepoint, indicating that an endpoint is \xe2\x80\xa600ChThe ECT(1) codepoint, indicating that an endpoint is \xe2\x80\xa600CaA complete set of keys for a certain packet space0CbA Long packet header, as used during the handshakeChNot attributed to any particular FrameType.CkAn open network transmission within a multipath-enabled \xe2\x80\xa6Ab(Multi)Path eventsB`An error occurred during readingCeWhether an endpoint was the initiator of a connection0nThe 0 path id.0CaThe address observed by the remote over this path0CjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBlCurrent congestion window of the connection.0gPayloadAoReturns the argument unchanged.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCoMethod for opening a sealed message data in-place.B`Open a single stream if possible1CgReturns the Path structure of an open pathBhPing the remote endpoint over this path.AhPing the remote endpointCkCheck whether the timer has expired, and register to be \xe2\x80\xa6BaReturns application-facing eventsBgRead data contiguously from the stream.AoRead from the given recv streamCcDecode TransportParameters from bufferBiReceive an unreliable, unordered datagramBdMethod for sealing a token in-place.0CiQueue an unreliable, unordered datagram for immediate \xe2\x80\xa6CbSends a Transmit on the given socket.CmNumber of address validation tokens sent to a client when \xe2\x80\xa60BmThe side of the connection (client or server)ChLook up whether we\xe2\x80\x99re the client or server of this \xe2\x80\xa6AlMethod for signing a message0CdAmount of data written to the caller-supplied buffer0hSpin bitAcStop accepting data0BoStop accepting data on the given receive streamCiTry to find and take a token that was stored with the \xe2\x80\xa60BgA chunk of data from the receive stream0CiThe RFC8312 congestion controller, as widely used for TCP0Borustls reports protocol errors using this type.0DbErrors encountered while decoding TransportParametersCdErrors that the nat traversal state might encounter.BeEvents of interest to the applicationCiEvent emitted when the client receives ADD_ADDRESS or \xe2\x80\xa6CjAttributed to a specific FrameType, never \xe2\x80\xa6A`Any other error.0CcThe peer abandoned transmitting data on this streamCnThe peer is unable to continue processing this connection, \xe2\x80\xa6CdThe peer abandoned transmitting data on this stream.1AeA Retry packet headerCdA short packet header, as used during the data phaseCmBest-effort extraction of the ALPN protocols from the TLS \xe2\x80\xa60BiConstruct a fresh Controller0AiThe contents of the chunkCiThe total amount of bytes which have been transferred \xe2\x80\xa6BjThe amount of bytes which had been written210BnUnderlying error describing reason for failureBaClose the connection immediately.CnClose all of this endpoint\xe2\x80\x99s connections immediately and \xe2\x80\xa6AaCloses this path.AnClose a connection immediatelyBcFrame type that triggered the errorCcDistinguishes streams of the same initiator and \xe2\x80\xa60CjReturns whether the codepoint is a CE, signalling that \xe2\x80\xa60AgKey for encrypting data0BgParse a connection id from given bufferAhReturns all known paths.BlUpdate the timer to expire at iBbClose the send stream immediately.BeAbandon transmitting data on a streamCnRespond with a retry packet, requiring the client to retry \xe2\x80\xa60CiDrive future to completion in the backgroundCeShow connection stats the at the end of the benchmarkAmReturns connection statisticsBiReturns relevant stats from this EndpointCaReturns the PathStats for this path.2BcTitle to record in the qlog capture0CmWrite a buffer into this stream, returning how many bytes \xe2\x80\xa6AmSend data on the given streamCcEncode TransportParameters into bufferC`Future produced by Endpoint::acceptClPaths marked as backup will only be used if there are no \xe2\x80\xa60CeChunks returned from RecvStream::read().AmThe initiator of a connectionAdRun as a perf client1CgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6BcThe receiver lagged too far behind.CcFuture produced by Connection::open_biAjA new path has been opened0ChOne or more new streams has been opened and might be \xe2\x80\xa6ChId representing different paths when using multipath \xe2\x80\xa60AbCoding result typeAlThe acceptor of a connectionAdRun as a perf server1mStream eventsAiAn integer less than 2^620CfGet the next incoming connection attempt from a clientClAttempt to accept this incoming connection (an error may \xe2\x80\xa6CcAccept a remotely initiated stream of a certain \xe2\x80\xa61C`The amount of full chunks which had been written0BlAllows to configure the desired cipher suiteCiHelper to construct an endpoint for use with outgoing \xe2\x80\xa6CcWait for the connection to be closed for any reasonAfCoding related traits.BnAccess the configuration used by this endpointChTraits and implementations for the QUIC cryptography \xe2\x80\xa6BjCreate QUIC error code from TLS alert codeBoTLS configuration used for incoming connections210BkAn underlying crypto (e.g. TLS) layer errorCgDecode a plain header from given buffer, with given \xe2\x80\xa6DiDecode a Self from the provided buffer, if the buffer is \xe2\x80\xa6ChThe destination IP address which was encoded in this \xe2\x80\xa6D`Append the encoding of self to the provided buffer.CmNotify the peer that no more data will ever be written to \xe2\x80\xa6CnFinish a send stream, signalling that no more data will be \xe2\x80\xa6B`Process an incoming UDP datagramAfHeader protection keys0ClIgnore this incoming connection attempt, not sending any \xe2\x80\xa60C`Potentially store a token for later one-time use0CfPerform NSS-compatible TLS key logging to the file \xe2\x80\xa6AhThe offset in the stream0B`Packet deliveries were confirmed0AfPacket protection keys0lRandom valueBcHuman-readable reason for the close0BcReason why this path was abandoned.11BhHuman-readable explanation of the reasonBeReason that the connection was closed2AjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataBoReturns the remote address of the network path.1AmTLS interface based on rustls0CnHelper to construct an endpoint for use with both incoming \xe2\x80\xa6BkOptional source IP address for the datagram00CgThe current local PathStatus of this path.B`The new status set by the remote0CfThe size of a single datagram in the associated bufferCkStatistics about datagrams and bytes received on this path.CjStatistics about UDP datagrams received on the connection.10CgStatistics about datagrams and bytes sent on this path.CeStatistics about UDP datagrams transmitted on the \xe2\x80\xa610AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0A`Send would blockCcNo more data is currently available on this stream.CjThe peer is not able to accept additional data, or the \xe2\x80\xa6BfA catch-all error for unlikely errors.0BlA key for signing with HMAC-based algorithms0AhAn Initial packet headerBnA pair of keys for bidirectional communication0BhA simple, standard congestion controller0CdFuture produced by Connection::open_uniCkAbstracts I/O and timer operations for runtime independenceBfA cryptographic session (commonly TLS)0CcThe peer is no longer accepting data on this streamCfFuture returned from SendStream::stopped.ClThe peer is no longer accepting data on this stream, and \xe2\x80\xa6CkThe peer is no longer accepting data on this stream. No \xe2\x80\xa6CgThe peer asked us to stop sending on an outgoing streamAaAccess to streamsCaThe stream is larger than the user-supplied limitCnAttributed to some frame type this implementation does not \xe2\x80\xa6ClIndicates how many bytes and chunks had been transferred \xe2\x80\xa60l0-RTT packetCjReturns the length of a CID for connections created by \xe2\x80\xa60CdProvide the length of dst_cid in short header packetCcThe total number of clients which should be createdAlConnect to a remote endpointAeInitiate a connectionBbDecrypt the Initial packet payloadCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header210ClConstructs a value with arbitrary fields, intended to be \xe2\x80\xa6DjConstruct an event that indicating that a Connection will \xe2\x80\xa6BkThe destination connection ID of the packetBkThe destination Connection ID of the packetAiDestination Connection ID00000CgEncrypt the packet payload with the given packet numberBcEncrypt the given packet\xe2\x80\x99s header10CbCheck if this stream has been opened during 0-RTT.0CmRetrieve implementation-specific metrics used to populate \xe2\x80\xa60CnThe maximum UDP payload size guaranteed to be supported by \xe2\x80\xa60CjUniform interface to send and receive UDP packets with \xe2\x80\xa6BbOne or more packets were just sent0BmInitiate a new outgoing bidirectional stream.CaReturns the path ID of the new path being opened.AdSource Connection ID0000CiCompletes when the peer stops the stream or reads the \xe2\x80\xa6CjCheck if this stream was stopped, get the reason if it wasCcThe total number of streams which should be createdAlProvide control over streamsCeThe length of the AEAD tag appended to packets on \xe2\x80\xa60CdUpgrade the handle to a full ConnectionB`Upgrades to a Path.AkSet the QUIC version to use0lQUIC versionB`The version that was unsupported11CeFuture produced by Connection::accept_biAfAn unreliable datagramBdDatagram support is disabled locally0A`A QUIC endpoint.BcThe main entry point to the libraryChA finished stream has been fully acknowledged or stoppedCkAn incoming connection for which the server has not yet \xe2\x80\xa60BoLong packet types with uniform header structureB`The largest encoded value length0Cmthe connection is being closed abruptly in the absence of \xe2\x80\xa60CeFuture returned by Connection::on_closedClFuture produced by crate::Connection::open_pathCmA currently open stream likely has data or errors waiting \xe2\x80\xa6CkMetadata for a single buffer filled with bytes received \xe2\x80\xa6BkResponse generated directly by the endpointCfIdentifier for a stream within a particular connection0CnCommunication with the peer has lapsed for longer than the \xe2\x80\xa6CkWe didn\xe2\x80\x99t receive any data from the remote within the \xe2\x80\xa61ChResponsible for limiting clients\xe2\x80\x99 ability to reuse \xe2\x80\xa60ClThe datagram is larger than the connection can currently \xe2\x80\xa60AbAn outgoing packet00CmStatistics about UDP datagrams transmitted or received on \xe2\x80\xa60CnA formerly write-blocked stream might be ready for a write \xe2\x80\xa6AkCongestion algorithm to useAhContents of the datagramBoMark the read data as consumed from the stream.BnStatistics about frames received on this path.CcStatistics about frames received on the connection.10CaStatistics about frames transmitted on this path.CfStatistics about frames transmitted on the connection.10DhConstructs cid by reading len bytes from a Buf0DkCreates a new qlog factory that writes files into QLOGDIR, \xe2\x80\xa60BfCreate a generator with a specific keyBjConstruct a VarInt infallibly0BeSucceeds iff x < 2^620AeWhat type we receivedAoWhat handshake type we received10CbWhether 0-RTT is/was possible during the handshakeCmSpecifies the time to wait after completing MTU discovery \xe2\x80\xa60CcReturns Self for use in down-casting to extract \xe2\x80\xa60EhReturns true if the Connection associated with this handle \xe2\x80\xa6CmDuration after an address validation token was issued for \xe2\x80\xa60CeThe local IP address which was used when the peer \xe2\x80\xa6000BnReturns the local address of the network path.ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BnInitiate a new outgoing unidirectional stream.BcGet the priority of the send streamAlGet the priority of a streamCfThe negotiated application protocol, if ALPN is in use0Aeqlog output directoryBbOptional response to transmit backCiOptional seed to be used internally for random number \xe2\x80\xa60AlSlow start threshold (bytes)0BeSucceeds iff x < 2^6200000DaSends a Transmit on the given socket without any \xe2\x80\xa6DkQuickly determine whether cid could have been generated by \xe2\x80\xa600BmA path was abandoned and is no longer usable.0CfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa60CnAt least one new stream of a certain directionality may be \xe2\x80\xa6BkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.CkA path was discarded and all remaining state for it has \xe2\x80\xa60BgInfallible encoding of QUIC primitives.CnIdentifies a network path by the combination of remote and \xe2\x80\xa6A`Handshake packetBcKeys used to protect packet headers0CiCatch-all error for problems while decoding transport \xe2\x80\xa6CeNat traversal attempt failed due to a multipath errorBdKeys used to protect packet payloads0BmErrors that might trigger a path being closed0AnApplication events about paths0BjStatistics related to a transmission path.0AeA read error occurredBmErrors that arise from reading from a stream.C`Errors triggered when reading from a recv streamCiAn object for asynchronously writing to an associated \xe2\x80\xa6BmAccept the next incoming bidirectional streamBbDuplicate the controller\xe2\x80\x99s state0BeThe number of UDP datagrams observed.AaControl datagrams1BeCreate new object from the given bits00BoWhich side of a connection initiated the stream0CmConvert into a 0-RTT or 0.5-RTT connection at the cost of \xe2\x80\xa6BoShorthand for self == Side::Client0B`Whether the connection is closedBoShorthand for self == Side::Server0CbWhether it is legal to respond with a retry packet0CdWhether to allow clients to migrate to new addresses0CdConstruct a timer that will expire at iBoLow-level protocol logic for the QUIC protoocolCjWait for the connection to be closed without keeping a \xe2\x80\xa6CjOpens an additional path if the multipath extension is \xe2\x80\xa6A`Opens a new pathBmPing the remote endpoint over a specific pathCiAttempts to read from the stream into the provided bufferCeReceive UDP datagrams, or register to be woken if \xe2\x80\xa6CkSend a UDP datagram, or register to be woken if sending \xe2\x80\xa6ClPrivate key used to send authenticated connection resets \xe2\x80\xa60BmGenerate the integrity tag for a retry packet0BgA stable identifier for this connectionCePrivate key used to authenticate data included in \xe2\x80\xa60BlThe position of a token in the packet bufferCgTransport configuration to use for incoming connections0CjWait for all connections on the endpoint to be cleanly \xe2\x80\xa6BoWrite a buffer into this stream in its entiretyCiAbstract implementation of an async timer for runtime \xe2\x80\xa6BoNumber of UDP packets to send/receive at a timeCmConfiguration for the Bbr3 congestion controller0CkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1101BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CjNumber of frames transmitted or received of each frame \xe2\x80\xa60BoThe connection ID was not recognized by the \xe2\x80\xa60DdThe type used to refer to FrameTypes in closing and \xe2\x80\xa6DbA stream of PathEvents for all paths in a connection.AnThe QUIC-MULTIPATH path status0BeConfiguration for qlog trace logging.0BnA stream that can only be used to receive dataAaAccess to streamsChErrors that arise while waiting for a stream to be resetDhError for attempting to retry an Incoming which already \xe2\x80\xa60BkA stream that can only be used to send data3BmObject to get current SystemTime0AdA rustls TLS session0CkResponsible for storing validation tokens received from \xe2\x80\xa60AeA borrowed UDP socketBjErrors that arise from writing to a streamBoErrors triggered while writing to a send streamBoAccept the next incoming uni-directional streamCkWhether the implementation is permitted to set the spin \xe2\x80\xa60CiCloses a path and sends a PATH_ABANDON frame with the \xe2\x80\xa6CdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10CaThe error code to be sent with the abandon frame.BoThe error that was sent with the abandon frame.AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0CnWhether there is no longer any need to keep the connection \xe2\x80\xa6DkDetermine whether this is the last event a Connection will \xe2\x80\xa6CiLook up the local IP address and port used by this socketDgGet the local SocketAddr the underlying socket is bound toBfThe number of bytes lost on this path.BkThe number of bytes lost on the connection.10CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statisticsCjThe final path stats, they are no longer available via \xe2\x80\xa610C`Attempt to write bytes from buf into the stream.AmRead the next segment of dataAoReads the next segment of data.CkRead an exact number of bytes contiguously from the stream.BnSets the PathStatus of this path.BoEpoch qlog event times are recorded relative to0ClError type for attempting to accept an IncomingBjErrors in the configuration of an endpoint0AeGeneric crypto errors0CnConfiguration for the Cubic congestion controller0CdReasons why attempting to finish a stream might failCnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60AnValue exceeds supported bounds0D`Constructs a QlogConfig for individual connections.0AfA noq runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CeLargest UDP payload size the path currently supports.ClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00DcCreates a new FourTuple without a known local address.BkStarting guess for maximum UDP payload sizeCkThe initial value to be used as the maximum UDP payload \xe2\x80\xa60ChUDP payload size that the network must be capable of \xe2\x80\xa6BjThe RTT used before an RTT sample is taken0BfThe initial round-trip-time (in msecs)CeThe amount of concurrent streams which should be usedDdPackets are acked in batches, all with the same now \xe2\x80\xa60AePacing rate (bytes/s)0DeA stream of PathEvents for all paths in this connection.DfGets the local PathStatus for a known PathIdAnRead the next segments of dataCkConvenience method to read all remaining data into a bufferAlProvide control over streamsBoThe sample size used for this key\xe2\x80\x99s algorithm01CiMaximum number of bytes to transmit to a peer without \xe2\x80\xa600BoThe server name specified by the client, if any0BmObject to get current SystemTime0BdSet a custom TokenStore0CaNumber of bytes to transmit from client to serverCnSpecifies the upper bound to the max UDP payload size that \xe2\x80\xa60ChReturns a weak reference to the inner connection struct.CdReturns a WeakPathHandle for this path.DgCreate a server config with the given crypto::ServerConfig0CeSets a prefix to the filename of the generated files.0DbWrite a single Bytes into this stream in its entiretyBbAn ADD_ADDRESS frame was received.BfConfiguration for outgoing connectionsCaClient-side configuration for the crypto protocol10CgThe stream has already been stopped, finished, or resetBmThe stream has already been finished or resetCmError indicating that a stream has not been opened or has \xe2\x80\xa6CjThe stream has not been opened or was already stopped, \xe2\x80\xa6CfThe stream has not been opened or has already been \xe2\x80\xa6CmThe stream has not been opened or was already finished or \xe2\x80\xa63CgErrors in the parameters being used to create a new \xe2\x80\xa60BkProtocol-level identifier for a connection.0CkWe couldn\xe2\x80\x99t decrypt a message. This is invariably fatal.0BjExplicit congestion notification codepoint00CnWe couldn\xe2\x80\x99t encrypt a message because it was larger than \xe2\x80\xa60BhParameters that are semantically invalidCkCannot close the last remaining open path via the local \xe2\x80\xa60Akn0\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa60CiFuture produced by Connection::read_datagramBiThe remote changed the status of the path0BlRTT estimation for a particular network pathCnFuture produced by Connection::send_datagram_waitBiParameters governing incoming connectionsCaServer-side configuration for the crypto protocol10CmErrors that arise while monitoring for a send stream stop \xe2\x80\xa6AgA noq runtime for TokioC`Returns the lifetime of generated Connection IDs0BjWhether the connection is closed, and why.CjConnect to a remote endpoint using a custom configuration.AlConservative estimate of RTTBnGet the 0-RTT keys if available (clients only)0AgWhich types we expectedB`Which handshake type we expected10AcGenerates a new CID0ClThe number of segments to read when GRO is enabled. Used \xe2\x80\xa6DeProcess ConnectionEvents generated by the associated \xe2\x80\xa6EaProcess EndpointEvents emitted from related ConnectionsCgCreate the initial set of keys given the client\xe2\x80\x99s \xe2\x80\xa6000BhThe number of packets lost on this path.BmThe number of packets lost on the connection.10DcMaximum number of Incoming to allow to exist at a time0CjWhether datagrams might get fragmented into multiple parts0CmWhether transmitted datagrams might get fragmented by the \xe2\x80\xa6CkReturns the path\xe2\x80\x99s network path represented as a 4-tuple.CkThe original destination CID when initiating the connectionCiThe original destination connection ID sent by the clientDhReturns the next time at which handle_timeout should be \xe2\x80\xa6D`Configures qlog capturing by setting a QlogFactory.0AgThe runtime type to useCkThe segment size if this transmission contains multiple \xe2\x80\xa600CkSend Quantum (bytes) used to control the size of packet \xe2\x80\xa60ChThe number of streams that may have unacknowledged data.CbSet the lifetime of CIDs created by this generator0BcSet the priority of the send streamAlSet the priority of a streamCnInitialize a QUIC-compatible TLS client configuration with \xe2\x80\xa6000DgWrite a slice of Bytes into this stream, returning how \xe2\x80\xa6AmSend data on the given streamCkWe received a fatal alert. This means the peer is unhappy.0BhBloom filter-based TokenLog0CmThe connection could not be created because not enough of \xe2\x80\xa6000CaEvent resulting from processing a single datagramBlEvents sent from a Connection to an EndpointAoStatistics on Endpoint activityBnThe stream finished before all bytes were readBlAuthentication data for (rustls) TLS session0Ccreceived an invalid Retry Token in a client Initial0ChIterator over ALPN protocol names from a TLS ClientHelloAlThe packet header is invalidBkThe local application closed the connection0DaThe datagram may result in starting a new ConnectionD`Configuration for the NewReno congestion controller0BjDecodes a QUIC packet\xe2\x80\x99s invariant headerCgErrors triggered when opening a recv stream for readingCaDefault implementation of TimeSource0CgError indicating that the provided buffer was too smallChFor clients, if the peer accepted the 0-RTT data packetsAbAck Frequency modeAfExports for benchmarksBoSupply a custom connection ID generator factory0DgCreate a UdpSender that can register a single task for \xe2\x80\xa6CaNumber of bytes to transmit from server to clientAmGet the Incoming0CnThe max_ack_delay we will request the peer to use0CgDisable packet encryption/decryption (for debugging \xe2\x80\xa6CkThe known MTU for the current network path has been updated0BbCryptographic identity of the peerBgGet the peer\xe2\x80\x99s identity, if availableDhFor the rustls TlsSession, the Any type is \xe2\x80\xa610AkReturns packets to transmitDjConfigures qlog capturing through the QLOGDIR environment \xe2\x80\xa60AoReceive an application datagramDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CmWhether to implement fair queuing for send streams having \xe2\x80\xa60BfLength of sign\xe2\x80\x99s output0BnStart a client session with this configurationBnStart a server session with this configuration10BdA REMOVE_ADDRESS frame was received.CgAbstract implementation of a UDP socket for runtime \xe2\x80\xa6BgErrors triggered when abandoning a path0AgThe connection was lost00000ChGlobal configuration for the endpoint, affecting all \xe2\x80\xa60Cithe endpoint encountered an internal error and cannot \xe2\x80\xa60FbBasic adapter to let Incoming be await-ed like a ConnectingBhEncounter a frame ID that was not valid.CeThe peer sent us a TLS message with invalid contents.0Amno viable network path exists0DhNull implementation of TokenStore, which does not store \xe2\x80\xa60CiThe peer deviated from the standard TLS protocol. The \xe2\x80\xa60BmErrors that arise from reading from a stream.C`Errors from RecvStream::read_to_endCaIndicates whether a frame needs to be transmittedCmThe peer violated the QUIC specification as understood by \xe2\x80\xa60CiTransport-level errors occur when a peer violates the \xe2\x80\xa6C`Tokio-compatible UDP socket with some useful \xe2\x80\xa6DiWeak handle for a Path that does not keep the connection \xe2\x80\xa6BnCreate a client endpoint and client connectionAgGet a session referenceDiReturns a QlogConfig for a connection, if logging should \xe2\x80\xa60AiProcess timer expirationsBjParameters negotiated during the handshake0CfGet data negotiated during the handshake, if available0AiInitial congestion windowCiDefault limit on the amount of outstanding data in bytes.001000BnConverts this stream into an unordered stream.DdReturns true until the connection is fully established.CeWhether the connection is in the process of being \xe2\x80\xa61BfVerify the integrity of a retry packet0CnSpecifies the minimum MTU change to stop the MTU discovery \xe2\x80\xa60BdCompute keys for the next key update0AhOne packet was just lost0AhOne packet was just sent0BkConfigures qlog capturing into a directory.0AlRead bytes of handshake data0BeWhether to use the unordered read APIClMaximum number of bytes the peer may transmit across all \xe2\x80\xa600CkCompletes when the stream has been reset by the peer or \xe2\x80\xa60CiCheck whether this stream has been reset by the peer, \xe2\x80\xa6AjThe peer\xe2\x80\x99s UDP addressesAhThe peer\xe2\x80\x99s UDP address0BgThe peer\xe2\x80\x99s UDP address for this path.1CeSaturating integer addition. Computes self + rhs, \xe2\x80\xa6000ChSaturating integer subtraction. Computes self - rhs, \xe2\x80\xa60CkMaximum reordering in time space before time based loss \xe2\x80\xa60ChReason given by the transport for closing the connection0BfReasons why a connection might be lost0CiThe datagram is redirected to its ConnectionBlEvents sent from an Endpoint to a ConnectionAfConnection statistics.0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0AkThe remote closed the path.CfError for when a validation token may have been reused0C`Parameters governing the core QUIC state machine0CbThe peer doesn\xe2\x80\x99t implement any supported version0CdFuture that completes when a connection is fully \xe2\x80\xa6CbThis was a 0-RTT stream and the server rejected it000CjAutomatically select an appropriate runtime from those \xe2\x80\xa6CkWhether to accept QUIC packets containing any value for \xe2\x80\xa60CdMaximum number of incoming packets that may fail \xe2\x80\xa60CnThe interface index of the interface on which the datagram \xe2\x80\xa6AjSwitch to a new UDP socketCiCreates a server endpoint which runs on the given runtimeD`Sets the PathStatus for a known PathIdCfSee proto::TransportConfig::send_window()BoSee TransportConfig::send_window()BmReturns whether a frame should be transmittedD`Convert t into the socket type used by this runtimeCdWrites handshake bytes into the given buffer and \xe2\x80\xa60ClStream produced by Path::observed_external_addrCiReason given by an application for closing the connection0CbThe peer\xe2\x80\x99s QUIC stack aborted the connection \xe2\x80\xa60DjInternal identifier for a Connection currently associated \xe2\x80\xa6CdOne or more application datagrams have been receivedBjDecrypted payload of a QUIC Initial packet0CaThe endpoint can no longer create new connections0Cnreceived a STREAM frame or a RESET_STREAM frame containing \xe2\x80\xa60ClSpecific failure cases from keys_match or a \xe2\x80\xa60A`key update error0CaCurrent limits do not allow us to open more paths0ClThe peer doesn\xe2\x80\x99t support a protocol version/feature we \xe2\x80\xa60BjA QUIC-compatible TLS client configuration0BjA QUIC-compatible TLS server configuration0EfTokenStore implementation that stores up to N tokens per \xe2\x80\xa60CgAn endpoint (local or remote) tried to add too many \xe2\x80\xa6CaPath could not be validated and will be abandonedCmWe didn\xe2\x80\x99t receive a path response in time after opening \xe2\x80\xa61BcA Version Negotiation packet headerCiRecord that the token was used and, ideally, return a \xe2\x80\xa60CjCurrent state of the congestion control algorithm, for \xe2\x80\xa6CcCurrent state of this connection\xe2\x80\x99s congestion \xe2\x80\xa6BaUpdate traffic keys spontaneously0CnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60Cgn0\xe2\x80\x99s (https://n0.computer) NAT Traversal protocol \xe2\x80\xa6CeGet the number of connections that are currently openBmNumber of connections that are currently openCiOpens a new path if no path exists yet for the remote \xe2\x80\xa6CmOpens a new path only if no path on the same network path \xe2\x80\xa6CiMaximum reordering in packet number space before FACK \xe2\x80\xa60CfGet the size of the socket receive bufferAlReceive buffer size in bytesCcGet the size of the socket send bufferAiSend buffer size in bytesBiSet a custom TransportConfig000ChConfiguration for sending and handling validation tokens0CnCreate a server config with the given certificate chain to \xe2\x80\xa60DdWrite a slice of Bytes into this stream in its entiretyCfthe application or application protocol caused the \xe2\x80\xa60AnThe peer closed the connectionBoThe path was closed locally by the application.1B`Constructs controllers on demand0CnCommon congestion controller metrics used both for logging \xe2\x80\xa60ClThe trait for encrypting tokens that power retry packets \xe2\x80\xa60BcThe given server name was malformed0CbHints when the caller identifies a network change.0AcPacket decode errorBdReason for why a path was abandoned.BmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BdCongestion events on the connection.0AiCongestion window (bytes)0ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BoBytes available in the outgoing datagram bufferClReplace the server configuration, affecting new incoming \xe2\x80\xa60Cmthe endpoint has reached the confidentiality or integrity \xe2\x80\xa60CkParameters for controlling the peer\xe2\x80\x99s acknowledgement \xe2\x80\xa60DjThe max_fragment_size value supplied in configuration was \xe2\x80\xa60Bmthe server refused to accept a new connection0BjParse connection id in short header packetCjOne or more application datagrams have been sent after \xe2\x80\xa6Ckreceived more data than permitted in advertised data limits0AoThe TLS handshake was confirmedBjThe connection\xe2\x80\x99s handshake data is readyCeAttempted an ordered read following an unordered readAnWe saw an invalid certificate.0BcParameters governing MTU discovery.0BnNot enough addresses to complete the operationCkdetected an error with protocol compliance that was not \xe2\x80\xa60Cjreceived a frame for a stream identifier that exceeded \xe2\x80\xa60Cnreceived a frame for a stream that was not in a state that \xe2\x80\xa60AnError from setting path status0AjTransport-level error code0ChThe local endpoint does not support the QUIC version \xe2\x80\xa6CkError indicating that the specified QUIC version is not \xe2\x80\xa61C`Packet uses a QUIC version that is not supported1CiMaximum quantity of out-of-order crypto layer data to \xe2\x80\xa60C`Create a VarInt without ensuring it\xe2\x80\x99s in range0ChCumulative number of Quic handshakes ignored on this \xe2\x80\xa6EgReturns true if the two WeakConnectionHandle point at the \xe2\x80\xa6CiMinimum interval between outgoing stateless reset packets0CjConstruct with an approximate maximum memory usage and \xe2\x80\xa60ChCumulative number of Quic handshakes refused on this \xe2\x80\xa6AnReturns the remote path statusDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CnUpdates the set of ALPN protocols configured in the client \xe2\x80\xa6CnUpdates the set of ALPN protocols configured in the server \xe2\x80\xa610CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60CcA stream of NAT traversal updates for a connection.BkNo remote CIDs available to open a new path0CkTransport parameters used to negotiate connection-level \xe2\x80\xa6CgA stream that can be used to receive data out-of-order.CmThe certificate verifier doesn\xe2\x80\x99t support the given type \xe2\x80\xa60CfThe operation is not allowed for this endpoint\xe2\x80\x99s \xe2\x80\xa6CiCumulative number of Quic handshakes accepted by this \xe2\x80\xa6CjSpecifies the amount of time that MTU discovery should \xe2\x80\xa60CiIf the 0-RTT-encrypted data has been accepted by the peer0BgWait for the handshake to be confirmed.CgInform the connection if a path may recover after a \xe2\x80\xa60CgPeriod of inactivity before sending a keep-alive packet0CfThe number of PLPMTUD probe packets lost on this path.0BlPackets were deemed lost or marked congested0CgCumulative number of Quic handshakes sent from this \xe2\x80\xa6CnThe number of remotely initiated open streams of a certain \xe2\x80\xa6AhBench fns for SendBufferCfThe number of PLPMTUD probe packets sent on this path.0Bireceived a frame that was badly formatted0CkThis function doesn\xe2\x80\x99t work until the TLS handshake is \xe2\x80\xa60CkWe received a TLS message that isn\xe2\x80\x99t valid right now. \xe2\x80\xa60CkThe remote address for the path is not supported by the \xe2\x80\xa6CiThe remote SocketAddr supplied was malformed10ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60CnWatches the external address reported by the peer for this \xe2\x80\xa6BdPaths can only be opened client-side0DmError returned when constructing a VarInt from a value >= \xe2\x80\xa60CeA handle to some connection internals, use with care.DkSpecifies the ACK frequency config (see AckFrequencyConfig \xe2\x80\xa60CjThe number of times a black hole was detected in the path.0CgMaximum number of received bytes to buffer for each \xe2\x80\xa60AeIs multipath enabled?ClMaximum number of datagrams that might be described by a \xe2\x80\xa60CkMaximum UDP payload size accepted from peers (excluding \xe2\x80\xa60AmMax UDP payload size in bytesDkSpecifies the MTU discovery config (see MtuDiscoveryConfig \xe2\x80\xa60AmReturn endpoint-facing eventsCkThe preferred IPv4 address that will be communicated to \xe2\x80\xa60CkThe preferred IPv6 address that will be communicated to \xe2\x80\xa60ChThe reordering threshold we will request the peer to use0ClDuration after a retry token was issued for which it\xe2\x80\x99s \xe2\x80\xa60BmSets the max idle timeout for a specific pathDfResize the receive buffer of socket to bytesDcResize the send buffer of socket to bytesBfThe peer\xe2\x80\x99s QUIC transport parametersBdQUIC connection transport parameters1CaGenerates connection IDs for incoming connections0CdAn incoming connection did not support any known \xe2\x80\xa60BjNo default client configuration was set up0BiPath abandoned due to unstable interfaces0ClConfiguration for sending and handling validation tokens \xe2\x80\xa60CmMaximum number of packets that may be sent using a single \xe2\x80\xa60CiNotify connections that the local network address has \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0CfA stream of NAT traversal updates for this connection.CjGet the address observed by the remote over the given pathCiMaximum number of bytes the peer may transmit without \xe2\x80\xa600Chreceived more data in CRYPTO frames than can be buffered0B`The extension was not negotiatedCbWe failed to figure out what time it currently is.0CbWe failed to acquire random bytes from the system.0CnError indicating that this operation requires multipath to \xe2\x80\xa6BnThe extension was not negotiated with the peerAkMultipath is not negotiated210CnError when the multipath extension was not negotiated, but \xe2\x80\xa6CjThe path was opened in a NAT traversal round which was \xe2\x80\xa6BnHeader of an Initial packet, before decryptionCgDerive keying material from this connection\xe2\x80\x99s TLS \xe2\x80\xa6EdFill output with output.len() bytes of keying material \xe2\x80\xa60BnPathological case: many segments, get from endCfGet segments in the old way, using a loop of get callsClCurrent number of remotely initiated streams that may be \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa60CmCreate a client configuration that trusts specified trust \xe2\x80\xa60BkThe peer didn\xe2\x80\x99t give us any certificates.0BkThe peer sent an oversized record/fragment.0CkThe ack-eliciting threshold we will request the peer to use0BiWhether there are any pending retransmitsCdWhether the Multipath for QUIC extension is enabled.CbThe peer\xe2\x80\x99s ACK-frequency parameters have changed0C`Sets the keep_alive_interval for a specific pathBoSet a custom ValidationTokenConfig0BmPath abandoned at the application\xe2\x80\x99s request0CjGet the current value of max_udp_payload_size0ChConfigure how to populate the destination CID of the \xe2\x80\xa60CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6CfWhether the socket address that is initiating this \xe2\x80\xa60CmModify the number of open paths allowed when multipath is \xe2\x80\xa6Cmthe number of connection IDs provided by the peer exceeds \xe2\x80\xa60CbError returned by Session::export_keying_material.0CiA provided certificate revocation list (CRL) was invalid.0CmPath abandoned due to no available connection IDs for the \xe2\x80\xa60Clreceived transport parameters that were badly formatted, \xe2\x80\xa60CiRegisters one address at which this endpoint might be \xe2\x80\xa6ClAdd addresses the local endpoint considers are reachable \xe2\x80\xa6ClMaximum number of outgoing application datagram bytes to \xe2\x80\xa60CiSet the client configuration used by connectBnSets the max_idle_timeout for a specific path.BfThe QUIC protocol version implemented.CfThe path became unusable after a local network change.BoBytes available in the outgoing datagram bufferDhMaximum number of received bytes to buffer for all Incoming0DaVariant of max_concurrent_bidi_streams affecting \xe2\x80\xa60ClModify the number of remotely initiated streams that may \xe2\x80\xa6BmSpurious congestion events on the connection.0CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CkGenerates 8-byte connection IDs that can be efficiently \xe2\x80\xa6CkAn error occurred while handling Encrypted Client Hello \xe2\x80\xa60CkPath abandoned due to resource limitations in the transport0CiGenerates purely random connection IDs of a specified \xe2\x80\xa6ChWhether to use \xe2\x80\x9cGeneric Segmentation Offload\xe2\x80\x9d to \xe2\x80\xa60CmMaximum number of incoming bidirectional streams that may \xe2\x80\xa60BhUpdates this tuple\xe2\x80\x99s local address iffClMaximum number of incoming application datagram bytes to \xe2\x80\xa60BcInitiates a new nat traversal round0BdPackets were incorrectly deemed lostCaequivalent to BBRHandleSpuriousLossDetection: \xe2\x80\xa610CnRemoves one or more addresses from the set of addresses at \xe2\x80\xa6CgRemoves an address the endpoing no longer considers \xe2\x80\xa6C`Sets the keep_alive_interval for a specific pathDeA ConnectionIdParser implementation that assumes the \xe2\x80\xa6CjWe received a TLS handshake message that isn\xe2\x80\x99t valid \xe2\x80\xa60CiHow to construct new congestion::Controllers0BlSets a default per-path maximum idle timeout0CkConfigures an outbound rate limit (in bytes per second) \xe2\x80\xa60BoThe key exchange group negotiated with the peer0CbWhether to send observed address reports to peers.0CiModify the number of remotely initiated bidirectional \xe2\x80\xa6BiEnables the Multipath Extension for QUIC.0CjModify the number of remotely initiated unidirectional \xe2\x80\xa6CeNumber of consecutive PTOs after which network is \xe2\x80\xa60BkSets a default per-path keep alive interval0CjWhether to receive observed address reports from other \xe2\x80\xa60BmGet the current local nat traversal addresses0CkGet the currently advertised nat traversal addresses by \xe2\x80\xa60AcNat traversal draftCkSets the maximum number of nat traversal addresses this \xe2\x80\xa60CjWhen multipath is required and has not been explicitly \xe2\x80\xa6") \ No newline at end of file diff --git a/pr/619/docs/search.index/entry/76669476e13c.js b/pr/619/docs/search.index/entry/76669476e13c.js new file mode 100644 index 000000000..cce77200e --- /dev/null +++ b/pr/619/docs/search.index/entry/76669476e13c.js @@ -0,0 +1 @@ +rd_("Af[476,15,477,0,134,0,0]Ak[3177,15,3178,3178,135,0,0]Ag[476,15,477,0,4208,0,0]Al[3177,15,3178,1831,4209,0,0]Al[2035,15,2036,2036,4210,0,0]Al[3177,15,1735,1735,1472,0,0]Ao[1226,13,1227,1227,4051,3115,0]Am[476,13,477,3742,4897,3115,0]Am[476,13,477,4270,1456,3115,0]Al[476,13,477,1124,519,3115,0]Am[476,13,477,1124,4491,3115,0]Am[476,13,477,4157,4484,3115,0]Am[476,13,477,4157,3125,3115,0]Am[476,13,477,4157,3328,3115,0]Am[476,13,477,4157,4483,3115,0]Am[476,13,477,4162,3346,3115,0]Am[476,13,477,4162,4248,3115,0]Aj[476,13,477,0,1482,3115,0]Aj[476,13,477,0,5066,3115,0]Aj[476,13,477,0,1182,3115,0]Aj[476,13,477,0,1465,3115,0]Aj[476,13,477,0,3321,3115,0]Aj[476,13,477,0,3120,3115,0]Aj[476,13,477,0,4951,3115,0]Aj[476,13,477,0,3293,3115,0]Aj[476,13,477,0,2349,3115,0]Aj[476,13,477,0,3306,3115,0]Aj[476,13,477,0,3122,3115,0]Aj[476,13,477,0,1915,3115,0]Aj[476,13,477,0,4194,3115,0]Aj[476,13,477,0,4583,3115,0]Aj[476,13,477,0,3116,3115,0]Aj[476,13,477,0,4450,3115,0]Aj[476,13,477,0,4064,3115,0]Aj[476,13,477,0,4054,3115,0]Aj[476,13,477,0,3103,3115,0]Aj[476,13,477,0,4580,3115,0]Aj[476,13,477,0,4787,3115,0]Aj[476,13,477,0,4200,3115,0]Aj[476,13,477,0,4203,3115,0]Aj[476,13,477,0,4208,3115,0]Aj[476,13,477,0,4956,3115,0]Ai[476,13,477,0,525,3115,0]Ai[476,13,477,0,134,3115,0]Aj[476,13,477,0,2336,3115,0]Ak[476,13,1739,0,5222,3115,0]Ak[476,13,1820,0,1199,3115,0]Ao[3177,13,3178,1858,1483,3115,0]Ao[3177,13,3178,1858,5067,3115,0]Ao[3177,13,3178,3142,1183,3115,0]Ao[3177,13,3178,3151,4898,3115,0]Ao[3177,13,3178,1403,1466,3115,0]Ao[3177,13,3178,1403,3322,3115,0]Ao[3177,13,3178,1403,3121,3115,0]Ao[3177,13,3178,1403,4896,3115,0]Ao[3177,13,3178,1403,4952,3115,0]Ao[3177,13,3178,1403,3296,3115,0]Ao[3177,13,3178,1419,2350,3115,0]Ao[3177,13,3178,1419,3307,3115,0]Ao[3177,13,3178,1419,3123,3115,0]Ao[3177,13,3178,1150,3126,3115,0]Ao[3177,13,3178,1150,4374,3115,0]Ao[3177,13,3178,1155,1916,3115,0]Ao[3177,13,3178,1155,3347,3115,0]Ao[3177,13,3178,1155,4063,3115,0]Ao[3177,13,3178,2050,4082,3115,0]Ao[3177,13,3178,2050,4485,3115,0]Ao[3177,13,3178,2050,4198,3115,0]Ao[3177,13,3178,3743,4584,3115,0]Ao[3177,13,3178,3743,3117,3115,0]Ao[3177,13,3178,3743,4451,3115,0]Ao[3177,13,3178,3279,4065,3115,0]Ao[3177,13,3178,1737,4055,3115,0]Ao[3177,13,3178,1393,3104,3115,0]Ao[3177,13,3178,1393,4466,3115,0]Ao[3177,13,3178,1393,3313,3115,0]Ao[3177,13,3178,1393,3336,3115,0]Ao[3177,13,3178,1393,4205,3115,0]Ao[3177,13,3178,1393,4582,3115,0]Ao[3177,13,3178,1393,4789,3115,0]Ao[3177,13,3178,2360,4793,3115,0]Ao[3177,13,3178,2360,4201,3115,0]Ao[3177,13,3178,1802,2322,3115,0]Ao[3177,13,3178,1802,4893,3115,0]Ao[3177,13,3178,1831,4204,3115,0]Ao[3177,13,3178,1831,4209,3115,0]Al[3177,13,3178,0,4489,3115,0]Al[3177,13,3178,0,4957,3115,0]An[3177,13,3178,3178,526,3115,0]An[3177,13,3178,3178,135,3115,0]Ao[3177,13,3178,3178,2337,3115,0]Ao[3177,13,3178,3178,3102,3115,0]Ao[3177,13,1735,1735,4380,3115,0]Ao[3177,13,5108,5108,5004,3115,0]Ao[3177,13,5108,5108,1201,3115,0]Ao[3177,13,1740,1740,5223,3115,0]Al[3177,13,1821,0,1200,3115,0]Ao[2035,13,2036,2036,4210,3115,0]Ai[476,13,477,1124,519,0,0]Aj[476,13,477,1124,4491,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5005,0,0]Aj[476,13,477,4162,3332,0,0]Ah[476,14,3118,0,1458,0,0]Ah[476,14,3118,0,3077,0,0]Ah[476,14,3118,0,3096,0,0]Ah[476,14,3118,0,4233,0,0]Ah[476,14,3118,0,4224,0,0]Ai[3177,14,3119,0,1459,0,0]Ai[3177,14,3119,0,3078,0,0]Ai[3177,14,3119,0,3097,0,0]Ai[3177,14,3119,0,4234,0,0]Ai[3177,14,3119,0,4225,0,0]Ai[3177,14,4081,0,2332,0,0]Ai[3177,14,4081,0,2352,0,0]Ai[3177,14,4081,0,2316,0,0]Ai[3177,14,4081,0,1903,0,0]Ae[1226,7,1227,0,0,0,0]Ah[3177,14,4595,0,515,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ae[2413,5,2414,0,0,0,0]Af[476,6,477,3178,0,0,0]Ae[3177,6,3178,0,0,0,0]Al[3177,15,1735,1735,1472,0,0]Ag[476,19,477,0,1482,0,0]Ag[476,19,477,0,1465,0,0]Al[3177,19,3178,1858,1483,0,0]Al[3177,19,3178,1403,1466,0,0]Ae[1226,5,1227,0,0,0,0]Ae[1125,5,1729,0,0,0,0]Ae[1125,5,1826,0,0,0,0]Af[476,15,477,0,134,0,0]Ak[3177,15,3178,3178,135,0,0]Ai[476,13,477,0,2349,128,0]Ai[476,13,477,0,3306,128,0]Ai[476,13,477,0,4587,128,0]An[3177,13,3178,1419,2350,128,0]An[3177,13,3178,1419,3307,128,0]An[3177,13,3178,1419,4588,128,0]Ai[476,13,477,0,1482,145,0]Ai[476,13,477,0,1465,145,0]Ai[476,13,477,0,4064,145,0]Ai[476,13,477,0,4203,145,0]Ah[476,13,477,0,525,145,0]Ah[476,13,477,0,134,145,0]Ai[476,13,477,0,2336,145,0]An[3177,13,3178,1858,1483,145,0]An[3177,13,3178,3151,4898,145,0]An[3177,13,3178,1403,1466,145,0]An[3177,13,3178,1150,3126,145,0]An[3177,13,3178,1150,4374,145,0]An[3177,13,3178,1155,3347,145,0]An[3177,13,3178,3279,4065,145,0]An[3177,13,3178,2360,4793,145,0]An[3177,13,3178,1802,4893,145,0]An[3177,13,3178,1831,4204,145,0]Am[3177,13,3178,3178,526,145,0]Am[3177,13,3178,3178,135,145,0]An[3177,13,3178,3178,2337,145,0]Ag[476,13,477,0,2336,0,0]Al[3177,13,3178,3178,2337,0,0]Ai[3177,14,4081,0,1460,0,0]Ai[3177,14,4081,0,3086,0,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Al[2035,14,2036,2036,2334,0,0]Al[2035,14,2036,2036,2348,0,0]An[1226,13,1227,1227,142,1189,0]Ao[1226,13,1227,1227,4075,1189,0]Ao[1226,13,1227,1227,4051,1189,0]Ao[1226,13,1417,1417,4486,1189,0]Ao[4089,13,4090,4090,5160,1189,0]Am[476,13,477,4270,5062,1189,0]Am[476,13,477,3742,3298,1189,0]Am[476,13,477,3742,3300,1189,0]Am[476,13,477,3742,5069,1189,0]D`[476,13,477,3742,4897,1189,0,\"impl-Debug-for-SendDatagramError\"]Db[476,13,477,3742,4897,1875,0,\"impl-Display-for-SendDatagramError\"]Am[476,13,477,2359,2314,1189,0]Am[476,13,477,2359,4347,1189,0]Cg[476,13,477,4270,1456,1875,0,\"impl-Display-for-Lagged\"]Ce[476,13,477,4270,1456,1189,0,\"impl-Debug-for-Lagged\"]Am[476,13,477,4270,3320,1189,0]Am[476,13,477,4270,4997,1189,0]Am[476,13,477,2391,2318,1189,0]Ci[476,13,477,2391,3329,1189,0,\"impl-Debug-for-RetryError\"]Ck[476,13,477,2391,3329,1875,0,\"impl-Display-for-RetryError\"]Am[476,13,477,2391,4465,1189,0]Al[476,13,477,1124,519,1189,0]Am[476,13,477,1124,4491,1189,0]Am[476,13,477,4157,3326,1189,0]Am[476,13,477,4157,5005,1189,0]Co[476,13,477,4157,4484,1875,0,\"impl-Display-for-ReadToEndError\"]Cm[476,13,477,4157,4484,1189,0,\"impl-Debug-for-ReadToEndError\"]Ch[476,13,477,4157,3125,1189,0,\"impl-Debug-for-ReadError\"]Cj[476,13,477,4157,3125,1875,0,\"impl-Display-for-ReadError\"]Ci[476,13,477,4157,3328,1189,0,\"impl-Debug-for-ResetError\"]Ck[476,13,477,4157,3328,1875,0,\"impl-Display-for-ResetError\"]Cm[476,13,477,4157,4483,1189,0,\"impl-Debug-for-ReadExactError\"]Co[476,13,477,4157,4483,1875,0,\"impl-Display-for-ReadExactError\"]Am[476,13,477,1430,4249,1189,0]Am[476,13,477,1167,4078,1189,0]Am[476,13,477,4162,3332,1189,0]Ci[476,13,477,4162,3346,1189,0,\"impl-Debug-for-WriteError\"]Ck[476,13,477,4162,3346,1875,0,\"impl-Display-for-WriteError\"]Ck[476,13,477,4162,4248,1189,0,\"impl-Debug-for-StoppedError\"]Cm[476,13,477,4162,4248,1875,0,\"impl-Display-for-StoppedError\"]Am[476,13,477,4162,1905,1189,0]Cd[476,13,477,0,1482,1875,0,\"impl-Display-for-VarInt\"]Cb[476,13,477,0,1482,1189,0,\"impl-Debug-for-VarInt\"]D`[476,13,477,0,5066,1189,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Db[476,13,477,0,5066,1875,0,\"impl-Display-for-VarIntBoundsExceeded\"]Aj[476,13,477,0,1182,1189,0]Cb[476,13,477,0,1465,1189,0,\"impl-Debug-for-PathId\"]Cd[476,13,477,0,1465,1875,0,\"impl-Display-for-PathId\"]Aj[476,13,477,0,3321,1189,0]Aj[476,13,477,0,3120,1189,0]D`[476,13,477,0,4951,1875,0,\"impl-Display-for-SetPathStatusError\"]Cn[476,13,477,0,4951,1189,0,\"impl-Debug-for-SetPathStatusError\"]Cf[476,13,477,0,3293,1189,0,\"impl-Debug-for-ClosedPath\"]Ch[476,13,477,0,3293,1875,0,\"impl-Display-for-ClosedPath\"]Aj[476,13,477,0,2349,1189,0]Aj[476,13,477,0,3306,1189,0]Aj[476,13,477,0,3122,1189,0]Aj[476,13,477,0,4587,1189,0]Aj[476,13,477,0,1915,1189,0]Cj[476,13,477,0,4194,1875,0,\"impl-Display-for-ClosedStream\"]Ch[476,13,477,0,4194,1189,0,\"impl-Debug-for-ClosedStream\"]Ck[476,13,477,0,4583,1189,0,\"impl-Debug-for-ConnectionError\"]Cm[476,13,477,0,4583,1875,0,\"impl-Display-for-ConnectionError\"]Cg[476,13,477,0,3116,1875,0,\"impl-Display-for-PathError\"]Ce[476,13,477,0,3116,1189,0,\"impl-Debug-for-PathError\"]Cl[476,13,477,0,4450,1875,0,\"impl-Display-for-ClosePathError\"]Cj[476,13,477,0,4450,1189,0,\"impl-Debug-for-ClosePathError\"]Aj[476,13,477,0,4597,1189,0]Aj[476,13,477,0,4606,1189,0]Aj[476,13,477,0,4921,1189,0]Aj[476,13,477,0,4936,1189,0]Aj[476,13,477,0,4064,1189,0]Aj[476,13,477,0,4460,1189,0]Aj[476,13,477,0,4242,1189,0]Aj[476,13,477,0,5123,1189,0]Aj[476,13,477,0,4188,1189,0]Ci[476,13,477,0,4054,1875,0,\"impl-Display-for-ConfigError\"]Cg[476,13,477,0,4054,1189,0,\"impl-Debug-for-ConfigError\"]Cg[476,13,477,0,3103,1875,0,\"impl-Display-for-FrameType\"]Ce[476,13,477,0,3103,1189,0,\"impl-Debug-for-FrameType\"]Ck[476,13,477,0,4580,1189,0,\"impl-Debug-for-ConnectionClose\"]Cm[476,13,477,0,4580,1875,0,\"impl-Display-for-ConnectionClose\"]Cl[476,13,477,0,4787,1189,0,\"impl-Debug-for-ApplicationClose\"]Cn[476,13,477,0,4787,1875,0,\"impl-Display-for-ApplicationClose\"]Cj[476,13,477,0,4200,1875,0,\"impl-Display-for-ConnectError\"]Ch[476,13,477,0,4200,1189,0,\"impl-Debug-for-ConnectError\"]Ch[476,13,477,0,4203,1189,0,\"impl-Debug-for-ConnectionId\"]Cj[476,13,477,0,4203,1875,0,\"impl-Display-for-ConnectionId\"]Aj[476,13,477,0,4208,1189,0]D`[476,13,477,0,4956,1875,0,\"impl-Display-for-TransportErrorCode\"]Cn[476,13,477,0,4956,1189,0,\"impl-Debug-for-TransportErrorCode\"]Aj[476,13,477,0,3309,1189,0]Aj[476,13,477,0,4821,1189,0]Ai[476,13,477,0,525,1189,0]C`[476,13,477,0,134,1875,0,\"impl-Display-for-Dir\"]Bn[476,13,477,0,134,1189,0,\"impl-Debug-for-Dir\"]Cf[476,13,477,0,2336,1875,0,\"impl-Display-for-StreamId\"]Cd[476,13,477,0,2336,1189,0,\"impl-Debug-for-StreamId\"]Aj[476,13,477,0,2346,1189,0]Aj[476,13,3737,0,500,1189,0]Ak[476,13,3737,0,3289,1189,0]Ak[476,13,3737,0,1186,1189,0]Ak[476,13,3737,0,4059,1189,0]Ak[476,13,3737,0,1888,1189,0]Ak[476,13,3737,0,4366,1189,0]Ak[476,13,1739,0,5222,1189,0]Ak[476,13,1739,0,4057,1189,0]Ak[476,13,1739,0,4960,1189,0]Cb[476,13,1820,0,1199,1189,0,\"impl-Debug-for-Error\"]Cd[476,13,1820,0,1199,1875,0,\"impl-Display-for-Error\"]Da[476,13,1820,0,5060,1189,0,\"impl-Debug-for-NoInitialCipherSuite\"]Dc[476,13,1820,0,5060,1875,0,\"impl-Display-for-NoInitialCipherSuite\"]Ao[3177,13,3178,3743,3301,1189,0]Ao[3177,13,3178,2360,2315,1189,0]Cg[3177,13,3178,1858,1483,1189,0,\"impl-Debug-for-VarInt\"]Ci[3177,13,3178,1858,1483,1875,0,\"impl-Display-for-VarInt\"]De[3177,13,3178,1858,5067,1189,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Dg[3177,13,3178,1858,5067,1875,0,\"impl-Display-for-VarIntBoundsExceeded\"]Ao[3177,13,3178,3142,1183,1189,0]Dd[3177,13,3178,3151,4898,1875,0,\"impl-Display-for-SendDatagramError\"]Db[3177,13,3178,3151,4898,1189,0,\"impl-Debug-for-SendDatagramError\"]Ci[3177,13,3178,1403,1466,1875,0,\"impl-Display-for-PathId\"]Cg[3177,13,3178,1403,1466,1189,0,\"impl-Debug-for-PathId\"]Ao[3177,13,3178,1403,4238,1189,0]Ao[3177,13,3178,1403,3322,1189,0]Ao[3177,13,3178,1403,3121,1189,0]Ao[3177,13,3178,1403,4896,1189,0]De[3177,13,3178,1403,4952,1875,0,\"impl-Display-for-SetPathStatusError\"]Dc[3177,13,3178,1403,4952,1189,0,\"impl-Debug-for-SetPathStatusError\"]Ck[3177,13,3178,1403,3296,1189,0,\"impl-Debug-for-ClosedPath\"]Cm[3177,13,3178,1403,3296,1875,0,\"impl-Display-for-ClosedPath\"]Ao[3177,13,3178,1419,2350,1189,0]Ao[3177,13,3178,1419,3307,1189,0]Ao[3177,13,3178,1419,3123,1189,0]Ao[3177,13,3178,1419,4588,1189,0]Cj[3177,13,3178,1150,3126,1189,0,\"impl-Debug-for-ReadError\"]Cl[3177,13,3178,1150,3126,1875,0,\"impl-Display-for-ReadError\"]D`[3177,13,3178,1150,4374,1875,0,\"impl-Display-for-ReadableError\"]Cn[3177,13,3178,1150,4374,1189,0,\"impl-Debug-for-ReadableError\"]Ao[3177,13,3178,1155,1916,1189,0]Cm[3177,13,3178,1155,3347,1875,0,\"impl-Display-for-WriteError\"]Ck[3177,13,3178,1155,3347,1189,0,\"impl-Debug-for-WriteError\"]Cl[3177,13,3178,1155,4063,1189,0,\"impl-Debug-for-FinishError\"]Cn[3177,13,3178,1155,4063,1875,0,\"impl-Display-for-FinishError\"]Ao[3177,13,3178,2050,4082,1189,0]Ao[3177,13,3178,2050,4485,1189,0]Co[3177,13,3178,2050,4198,1875,0,\"impl-Display-for-ClosedStream\"]Cm[3177,13,3178,2050,4198,1189,0,\"impl-Debug-for-ClosedStream\"]Db[3177,13,3178,3743,4584,1875,0,\"impl-Display-for-ConnectionError\"]D`[3177,13,3178,3743,4584,1189,0,\"impl-Debug-for-ConnectionError\"]Cj[3177,13,3178,3743,3117,1189,0,\"impl-Debug-for-PathError\"]Cl[3177,13,3178,3743,3117,1875,0,\"impl-Display-for-PathError\"]Da[3177,13,3178,3743,4451,1875,0,\"impl-Display-for-ClosePathError\"]Co[3177,13,3178,3743,4451,1189,0,\"impl-Debug-for-ClosePathError\"]Di[3177,13,3178,3743,5155,1875,0,\"impl-Display-for-MultipathNotNegotiated\"]Dg[3177,13,3178,3743,5155,1189,0,\"impl-Debug-for-MultipathNotNegotiated\"]Ao[3177,13,3178,3743,1204,1189,0]Ao[3177,13,3178,1146,4598,1189,0]Ao[3177,13,3178,3279,4607,1189,0]Ao[3177,13,3178,3279,4922,1189,0]Ao[3177,13,3178,3279,4937,1189,0]Ao[3177,13,3178,3279,4065,1189,0]Ao[3177,13,3178,1737,4461,1189,0]Ao[3177,13,3178,1737,4244,1189,0]Ao[3177,13,3178,1737,5124,1189,0]Ao[3177,13,3178,1737,4190,1189,0]Cn[3177,13,3178,1737,4055,1875,0,\"impl-Display-for-ConfigError\"]Cl[3177,13,3178,1737,4055,1189,0,\"impl-Debug-for-ConfigError\"]Cl[3177,13,3178,1393,3104,1875,0,\"impl-Display-for-FrameType\"]Cj[3177,13,3178,1393,3104,1189,0,\"impl-Debug-for-FrameType\"]Co[3177,13,3178,1393,4466,1189,0,\"impl-Debug-for-InvalidFrameId\"]Da[3177,13,3178,1393,4466,1875,0,\"impl-Display-for-InvalidFrameId\"]Ck[3177,13,3178,1393,3313,1189,0,\"impl-Debug-for-MaybeFrame\"]Cm[3177,13,3178,1393,3313,1875,0,\"impl-Display-for-MaybeFrame\"]Ck[3177,13,3178,1393,3336,1189,0,\"impl-Debug-for-StreamInfo\"]Cm[3177,13,3178,1393,3336,1875,0,\"impl-Display-for-StreamInfo\"]Cm[3177,13,3178,1393,4205,1189,0,\"impl-Debug-for-DatagramInfo\"]Co[3177,13,3178,1393,4205,1875,0,\"impl-Display-for-DatagramInfo\"]Db[3177,13,3178,1393,4582,1875,0,\"impl-Display-for-ConnectionClose\"]D`[3177,13,3178,1393,4582,1189,0,\"impl-Debug-for-ConnectionClose\"]Dc[3177,13,3178,1393,4789,1875,0,\"impl-Display-for-ApplicationClose\"]Da[3177,13,3178,1393,4789,1189,0,\"impl-Debug-for-ApplicationClose\"]Ci[3177,13,3178,1393,2308,1189,0,\"impl-Debug-for-Datagram\"]Ck[3177,13,3178,1393,2308,1875,0,\"impl-Display-for-Datagram\"]Ao[3177,13,3178,2360,4793,1189,0]Ao[3177,13,3178,2360,2319,1189,0]Cm[3177,13,3178,2360,4201,1189,0,\"impl-Debug-for-ConnectError\"]Co[3177,13,3178,2360,4201,1875,0,\"impl-Display-for-ConnectError\"]Ao[3177,13,3178,2360,4049,1189,0]Ck[3177,13,3178,2360,3330,1189,0,\"impl-Debug-for-RetryError\"]Cm[3177,13,3178,2360,3330,1875,0,\"impl-Display-for-RetryError\"]Ao[3177,13,3178,1802,4369,1189,0]Ao[3177,13,3178,1802,4596,1189,0]Ao[3177,13,3178,1802,5159,1189,0]Ao[3177,13,3178,1802,2322,1189,0]Db[3177,13,3178,1802,4893,1189,0,\"impl-Debug-for-PacketDecodeError\"]Dd[3177,13,3178,1802,4893,1875,0,\"impl-Display-for-PacketDecodeError\"]Ao[3177,13,3178,1831,4586,1189,0]Ao[3177,13,3178,1831,4346,1189,0]Cm[3177,13,3178,1831,4204,1189,0,\"impl-Debug-for-ConnectionId\"]Co[3177,13,3178,1831,4204,1875,0,\"impl-Display-for-ConnectionId\"]Ao[3177,13,3178,1831,4209,1189,0]Ce[3177,13,3178,0,4489,1875,0,\"impl-Display-for-Error\"]Cc[3177,13,3178,0,4489,1189,0,\"impl-Debug-for-Error\"]Cb[3177,13,3178,0,4957,1189,0,\"impl-Debug-for-Code\"]Cd[3177,13,3178,0,4957,1875,0,\"impl-Display-for-Code\"]Ao[3177,13,3178,4387,3310,1189,0]Ao[3177,13,3178,4387,5259,1189,0]Ao[3177,13,3178,4992,4822,1189,0]An[3177,13,3178,3178,526,1189,0]Ce[3177,13,3178,3178,135,1875,0,\"impl-Display-for-Dir\"]Cc[3177,13,3178,3178,135,1189,0,\"impl-Debug-for-Dir\"]Ci[3177,13,3178,3178,2337,1189,0,\"impl-Debug-for-StreamId\"]Ck[3177,13,3178,3178,2337,1875,0,\"impl-Display-for-StreamId\"]Ao[3177,13,3178,3178,2347,1189,0]Cl[3177,13,3178,3178,3102,1875,0,\"impl-Display-for-FourTuple\"]Cj[3177,13,3178,3178,3102,1189,0,\"impl-Debug-for-FourTuple\"]Cn[3177,13,1735,1735,4380,1189,0,\"impl-Debug-for-UnexpectedEnd\"]D`[3177,13,1735,1735,4380,1875,0,\"impl-Display-for-UnexpectedEnd\"]Ao[3177,13,5108,5108,5004,1189,0]Ch[3177,13,5108,5108,1201,1875,0,\"impl-Display-for-Error\"]Cf[3177,13,5108,5108,1201,1189,0,\"impl-Debug-for-Error\"]Ao[3177,13,1740,1740,5223,1189,0]Ao[3177,13,1740,1740,4058,1189,0]Ao[3177,13,1740,1740,4963,1189,0]Ce[3177,13,1821,0,1200,1875,0,\"impl-Display-for-Error\"]Cc[3177,13,1821,0,1200,1189,0,\"impl-Debug-for-Error\"]Dg[3177,13,1821,1821,5061,1875,0,\"impl-Display-for-NoInitialCipherSuite\"]De[3177,13,1821,1821,5061,1189,0,\"impl-Debug-for-NoInitialCipherSuite\"]Am[3177,13,3738,534,501,1189,0]An[3177,13,3738,534,3290,1189,0]Ao[3177,13,3738,1389,1187,1189,0]Ao[3177,13,3738,1389,4060,1189,0]Ao[3177,13,3738,2413,1889,1189,0]Ao[3177,13,3738,2413,4367,1189,0]Ch[3177,13,4853,4853,1202,1875,0,\"impl-Display-for-Error\"]Cf[3177,13,4853,4853,1202,1189,0,\"impl-Debug-for-Error\"]Ao[3177,13,4853,4853,1205,1189,0]An[2035,13,2036,431,4490,1189,0]Ao[2035,13,2036,2036,2334,1189,0]Ao[2035,13,2036,2036,2348,1189,0]Ao[2035,13,2036,2036,4210,1189,0]Aj[476,13,477,4270,5062,0,0]Al[3177,13,3178,1403,4238,0,0]Ag[476,14,477,0,2349,0,0]Al[3177,14,3178,1419,2350,0,0]Al[3177,13,3178,1802,4369,0,0]Al[3177,14,3178,1802,5159,0,0]Ah[3177,14,4595,0,515,0,0]Al[2035,14,2036,2036,2334,0,0]Ag[476,13,477,0,5123,0,0]Al[3177,13,3178,1737,5124,0,0]8Al[1226,13,1417,1417,4486,0,0]Al[4089,13,4090,4090,5160,0,0]Ag[476,13,477,0,4338,0,0]Aj[476,13,477,2359,2314,0,0]Ag[476,13,477,0,3323,0,0]Ag[476,13,477,0,4597,0,0]Ag[476,13,477,0,4460,0,0]Ag[476,13,477,0,4242,0,0]Ag[476,13,477,0,4188,0,0]Ag[476,13,477,0,4203,0,0]Ag[476,13,477,0,4821,0,0]Ag[476,13,477,0,2336,0,0]Ah[476,13,3737,0,1186,0,0]Ah[476,13,3737,0,1888,0,0]Al[3177,13,3178,4616,4339,0,0]Al[3177,13,3178,1146,3324,0,0]Al[3177,13,3178,2360,2315,0,0]Al[3177,13,3178,1802,5286,0,0]Al[3177,13,3178,4387,5254,0,0]Al[3177,13,3178,1146,4598,0,0]Al[3177,13,3178,1737,4461,0,0]Al[3177,13,3178,1737,4244,0,0]Al[3177,13,3178,1737,4190,0,0]Al[3177,13,3178,1802,4369,0,0]Al[3177,13,3178,1831,4204,0,0]Ai[3177,13,3178,0,4489,0,0]Al[3177,13,3178,4387,5259,0,0]Al[3177,13,3178,4992,4822,0,0]Al[3177,13,3178,3178,2337,0,0]Al[3177,13,3178,3178,3102,0,0]Al[3177,13,3738,1389,1187,0,0]Al[3177,13,3738,2413,1889,0,0]Ak[2035,13,2036,431,4490,0,0]Al[1125,13,4304,4304,5208,0,0]Al[1125,13,4304,4304,5209,0,0]Aa[476,3,0,0,0,0,0]Ah[476,13,477,0,525,141,0]Am[3177,13,3178,3178,526,141,0]Ag[476,12,477,0,3339,0,0]Aj[476,13,477,2042,1900,0,0]0Am[476,13,477,1430,4249,1900,0]Aj[476,13,477,0,4378,3339,0]Al[3177,12,3178,1737,3340,0,0]Ao[3177,13,3178,1737,4379,3340,0]Aj[476,13,477,3742,3300,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,13,3178,3743,3301,0,0]Al[3177,14,3178,1419,3123,0,0]Ae[1125,7,1729,0,0,0,0]Ae[1125,7,1826,0,0,0,0]Ac[476,4,477,0,0,0,0]Af[476,5,3737,534,0,0,0]Ag[3177,5,3738,534,0,0,0]Al[1125,15,1126,1126,4996,0,0]Ag[476,15,477,0,4208,0,0]Al[3177,15,3178,1831,4209,0,0]Al[2035,15,2036,2036,4210,0,0]210Ag[476,5,1739,1740,0,0,0]Ae[3177,5,1740,0,0,0,0]Al[3177,15,3178,1802,4596,0,0]Al[3177,15,3178,1393,3313,0,0]Af[476,5,477,1124,0,0,0]Al[3177,15,3178,3743,1204,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Aj[476,15,477,4157,4484,0,0]Af[476,6,477,3178,0,0,0]Ae[3177,6,3178,0,0,0,0]Ag[476,19,477,0,1465,0,0]Al[3177,19,3178,1403,1466,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Ah[476,14,3118,0,4224,0,0]Ai[3177,14,3119,0,4225,0,0]Al[2035,14,2036,2036,2334,0,0]Aa[535,3,0,0,0,0,0]Ai[3177,14,3178,0,4489,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,14,3178,1419,3123,0,0]Al[3177,14,3178,1393,2308,0,0]Al[476,13,477,3742,2329,503,0]Al[476,13,477,2391,2318,503,0]Ak[476,13,477,1124,519,503,0]Al[476,13,477,1124,4491,503,0]Al[476,13,477,4157,3326,503,0]Al[476,13,477,4162,3332,503,0]An[3177,13,3178,1150,1445,503,0]Am[1226,13,1227,1227,142,510,0]An[1226,13,1227,1227,4075,510,0]An[1226,13,1227,1227,4051,510,0]An[1226,13,1417,1417,4083,510,0]An[1226,13,1417,1417,1219,510,0]An[1226,13,1417,1417,4486,510,0]Ak[535,13,536,536,4052,510,0]An[4089,13,4090,4090,5160,510,0]Al[476,13,477,3742,4611,510,0]Al[476,13,477,3742,2329,510,0]Ai[476,13,477,0,4338,510,0]Al[476,13,477,4270,5062,510,0]Al[476,13,477,1124,2330,510,0]Al[476,13,477,1124,4785,510,0]Al[476,13,477,3742,3298,510,0]Al[476,13,477,3742,3300,510,0]Al[476,13,477,3742,1891,510,0]Al[476,13,477,3742,1457,510,0]Al[476,13,477,3742,3081,510,0]Al[476,13,477,3742,2302,510,0]Al[476,13,477,3742,4232,510,0]Al[476,13,477,3742,4239,510,0]Al[476,13,477,3742,5069,510,0]Al[476,13,477,3742,4897,510,0]0Al[476,13,477,2359,2314,510,0]Al[476,13,477,2359,4347,510,0]Al[476,13,477,2359,1436,510,0]Al[476,13,477,4270,1456,510,0]Al[476,13,477,4270,3320,510,0]Al[476,13,477,4270,4997,510,0]Al[476,13,477,2391,2318,510,0]Al[476,13,477,2391,3329,510,0]Al[476,13,477,2391,4465,510,0]Ak[476,13,477,1124,519,510,0]Al[476,13,477,1124,4491,510,0]Al[476,13,477,4157,3326,510,0]Al[476,13,477,4157,5005,510,0]Al[476,13,477,4157,4484,510,0]0Dk[476,13,477,4157,3125,510,0,\"impl-From%3CConnectionError%3E-for-ReadError\"]Df[476,13,477,4157,3125,510,0,\"impl-From%3CResetError%3E-for-ReadError\"]Al[476,13,477,4157,3125,510,0]Al[476,13,477,4157,3328,510,0]0Al[476,13,477,4157,4483,510,0]0Al[476,13,477,1430,4249,510,0]Al[476,13,477,1167,4078,510,0]Al[476,13,477,4162,3332,510,0]Di[476,13,477,4162,3346,510,0,\"impl-From%3CStoppedError%3E-for-WriteError\"]Al[476,13,477,4162,3346,510,0]Dl[476,13,477,4162,3346,510,0,\"impl-From%3CConnectionError%3E-for-WriteError\"]Di[476,13,477,4162,3346,510,0,\"impl-From%3CClosedStream%3E-for-WriteError\"]Al[476,13,477,4162,4248,510,0]0Al[476,13,477,4162,1905,510,0]Ai[476,13,477,0,3323,510,0]Ai[476,13,477,0,4378,510,0]Ai[476,13,477,0,4795,510,0]Ai[476,13,477,0,4603,510,0]Ai[476,13,477,0,4222,510,0]Ai[476,13,477,0,4474,510,0]Ci[476,13,477,0,1482,510,0,\"impl-From%3Cu16%3E-for-VarInt\"]Ci[476,13,477,0,1482,510,0,\"impl-From%3Cu32%3E-for-VarInt\"]Ai[476,13,477,0,1482,510,0]Dh[476,13,477,0,1482,510,0,\"impl-From%3CTransportErrorCode%3E-for-VarInt\"]Cn[476,13,477,0,1482,510,0,\"impl-From%3CStreamId%3E-for-VarInt\"]Ch[476,13,477,0,1482,510,0,\"impl-From%3Cu8%3E-for-VarInt\"]Ai[476,13,477,0,5066,510,0]Ai[476,13,477,0,1182,510,0]Ai[476,13,477,0,1465,510,0]0Ai[476,13,477,0,3321,510,0]Ai[476,13,477,0,3120,510,0]Ai[476,13,477,0,4951,510,0]Ai[476,13,477,0,3293,510,0]Ai[476,13,477,0,2349,510,0]Ai[476,13,477,0,3306,510,0]Ai[476,13,477,0,3122,510,0]Ai[476,13,477,0,4587,510,0]Ai[476,13,477,0,1915,510,0]Ai[476,13,477,0,4194,510,0]Dd[476,13,477,0,4583,510,0,\"impl-From%3CClose%3E-for-ConnectionError\"]Dm[476,13,477,0,4583,510,0,\"impl-From%3CTransportError%3E-for-ConnectionError\"]Ai[476,13,477,0,4583,510,0]Dj[476,13,477,0,4583,510,0,\"impl-From%3CCloseReason%3E-for-ConnectionError\"]Ai[476,13,477,0,3116,510,0]Ai[476,13,477,0,4450,510,0]Ai[476,13,477,0,4597,510,0]Ai[476,13,477,0,4606,510,0]Ai[476,13,477,0,4921,510,0]Ai[476,13,477,0,4936,510,0]Ai[476,13,477,0,4064,510,0]0Ai[476,13,477,0,4460,510,0]Ai[476,13,477,0,4242,510,0]Ai[476,13,477,0,5123,510,0]Ai[476,13,477,0,4188,510,0]Do[476,13,477,0,4054,510,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]Dj[476,13,477,0,4054,510,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]Ai[476,13,477,0,4054,510,0]Ai[476,13,477,0,3103,510,0]Ai[476,13,477,0,4580,510,0]0Ai[476,13,477,0,4787,510,0]Ai[476,13,477,0,4200,510,0]0Ai[476,13,477,0,4203,510,0]Ai[476,13,477,0,4208,510,0]Ai[476,13,477,0,4956,510,0]0Ai[476,13,477,0,3309,510,0]Ai[476,13,477,0,4821,510,0]Ah[476,13,477,0,525,510,0]Ah[476,13,477,0,134,510,0]Ai[476,13,477,0,2336,510,0]0Ai[476,13,477,0,2346,510,0]Ai[476,13,3737,0,500,510,0]Aj[476,13,3737,0,3289,510,0]Aj[476,13,3737,0,1186,510,0]Aj[476,13,3737,0,4059,510,0]Aj[476,13,3737,0,1888,510,0]Aj[476,13,3737,0,4366,510,0]Aj[476,13,3737,0,4884,510,0]Aj[476,13,1739,0,1883,510,0]Ai[476,13,1739,0,513,510,0]Aj[476,13,1739,0,5222,510,0]Aj[476,13,1739,0,4057,510,0]0Aj[476,13,1739,0,4960,510,0]Aj[476,13,1820,0,3341,510,0]Aj[476,13,1820,0,4349,510,0]De[476,13,1820,0,1199,510,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Df[476,13,1820,0,1199,510,0,\"impl-From%3CCertificateError%3E-for-Error\"]Do[476,13,1820,0,1199,510,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]Df[476,13,1820,0,1199,510,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]Dd[476,13,1820,0,1199,510,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]Aj[476,13,1820,0,1199,510,0]Dd[476,13,1820,0,1199,510,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]De[476,13,1820,0,1199,510,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]Do[476,13,1820,0,1199,510,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]Dm[476,13,1820,0,1199,510,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]Df[476,13,1820,0,1199,510,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]D`[476,13,1820,0,1199,510,0,\"impl-From%3COtherError%3E-for-Error\"]Aj[476,13,1820,0,4817,510,0]Aj[476,13,1820,0,5060,510,0]Aj[476,13,1820,0,4819,510,0]Am[2413,13,2414,2414,133,510,0]An[2413,13,2414,2414,2305,510,0]An[3177,13,3178,4616,4339,510,0]An[3177,13,3178,3151,3094,510,0]An[3177,13,3178,1150,1445,510,0]An[3177,13,3178,2050,1909,510,0]An[3177,13,3178,2050,3327,510,0]An[3177,13,3178,2050,3333,510,0]An[3177,13,3178,3743,3301,510,0]An[3177,13,3178,1146,3324,510,0]An[3177,13,3178,1737,4379,510,0]An[3177,13,3178,2360,2315,510,0]An[3177,13,3178,2360,4345,510,0]An[3177,13,3178,2360,4796,510,0]An[3177,13,3178,2360,4357,510,0]An[3177,13,3178,1802,5286,510,0]An[3177,13,3178,4387,5254,510,0]An[3177,13,3178,1429,4604,510,0]An[3177,13,3178,1429,4223,510,0]An[3177,13,3178,1429,4475,510,0]An[3177,13,3178,1858,1483,510,0]Cn[3177,13,3178,1858,1483,510,0,\"impl-From%3Cu32%3E-for-VarInt\"]Cm[3177,13,3178,1858,1483,510,0,\"impl-From%3Cu8%3E-for-VarInt\"]Cn[3177,13,3178,1858,1483,510,0,\"impl-From%3Cu16%3E-for-VarInt\"]Co[3177,13,3178,1858,1483,510,0,\"impl-From%3CCode%3E-for-VarInt\"]Dc[3177,13,3178,1858,1483,510,0,\"impl-From%3CStreamId%3E-for-VarInt\"]An[3177,13,3178,1858,5067,510,0]An[3177,13,3178,3142,1183,510,0]An[3177,13,3178,3151,4898,510,0]An[3177,13,3178,1403,1466,510,0]0An[3177,13,3178,1403,4238,510,0]An[3177,13,3178,1403,3322,510,0]An[3177,13,3178,1403,3121,510,0]An[3177,13,3178,1403,4896,510,0]An[3177,13,3178,1403,4952,510,0]An[3177,13,3178,1403,3296,510,0]An[3177,13,3178,1419,2350,510,0]An[3177,13,3178,1419,3307,510,0]An[3177,13,3178,1419,3123,510,0]An[3177,13,3178,1419,4588,510,0]An[3177,13,3178,1150,3126,510,0]An[3177,13,3178,1150,4374,510,0]An[3177,13,3178,1155,1916,510,0]An[3177,13,3178,1155,3347,510,0]An[3177,13,3178,1155,4063,510,0]An[3177,13,3178,2050,4082,510,0]An[3177,13,3178,2050,4485,510,0]An[3177,13,3178,2050,4198,510,0]An[3177,13,3178,3743,4584,510,0]0An[3177,13,3178,3743,3117,510,0]An[3177,13,3178,3743,4451,510,0]An[3177,13,3178,3743,5155,510,0]An[3177,13,3178,3743,1204,510,0]0An[3177,13,3178,1146,4598,510,0]An[3177,13,3178,3279,4607,510,0]An[3177,13,3178,3279,4922,510,0]An[3177,13,3178,3279,4937,510,0]An[3177,13,3178,3279,4065,510,0]0An[3177,13,3178,1737,4461,510,0]An[3177,13,3178,1737,4244,510,0]An[3177,13,3178,1737,5124,510,0]An[3177,13,3178,1737,4190,510,0]Do[3177,13,3178,1737,4055,510,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]Ed[3177,13,3178,1737,4055,510,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]An[3177,13,3178,1737,4055,510,0]An[3177,13,3178,1393,3104,510,0]An[3177,13,3178,1393,4466,510,0]An[3177,13,3178,1393,3313,510,0]An[3177,13,3178,1393,3336,510,0]An[3177,13,3178,1393,4205,510,0]An[3177,13,3178,1393,4582,510,0]0An[3177,13,3178,1393,4789,510,0]An[3177,13,3178,1393,2308,510,0]An[3177,13,3178,2360,4793,510,0]An[3177,13,3178,2360,2319,510,0]An[3177,13,3178,2360,4201,510,0]0An[3177,13,3178,2360,4049,510,0]An[3177,13,3178,2360,3330,510,0]An[3177,13,3178,1802,4369,510,0]An[3177,13,3178,1802,4596,510,0]An[3177,13,3178,1802,5159,510,0]An[3177,13,3178,1802,2322,510,0]An[3177,13,3178,1802,4893,510,0]0An[3177,13,3178,1831,4586,510,0]An[3177,13,3178,1831,4346,510,0]An[3177,13,3178,1831,4204,510,0]An[3177,13,3178,1831,4209,510,0]Ak[3177,13,3178,0,4489,510,0]0Ak[3177,13,3178,0,4957,510,0]0An[3177,13,3178,4387,3310,510,0]An[3177,13,3178,4387,5259,510,0]An[3177,13,3178,4992,4822,510,0]Am[3177,13,3178,3178,526,510,0]Am[3177,13,3178,3178,135,510,0]An[3177,13,3178,3178,2337,510,0]0An[3177,13,3178,3178,2347,510,0]An[3177,13,3178,3178,3102,510,0]An[3177,13,1735,1735,4380,510,0]An[3177,13,5108,5108,5004,510,0]An[3177,13,5108,5108,1201,510,0]0An[3177,13,1740,1740,1884,510,0]Am[3177,13,1740,1740,514,510,0]An[3177,13,1740,1740,5223,510,0]An[3177,13,1740,1740,4058,510,0]0An[3177,13,1740,1740,4963,510,0]An[3177,13,1821,1821,3342,510,0]An[3177,13,1821,1821,4350,510,0]E`[3177,13,1821,0,1200,510,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]Dg[3177,13,1821,0,1200,510,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]Da[3177,13,1821,0,1200,510,0,\"impl-From%3COtherError%3E-for-Error\"]Df[3177,13,1821,0,1200,510,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Ak[3177,13,1821,0,1200,510,0]Df[3177,13,1821,0,1200,510,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]E`[3177,13,1821,0,1200,510,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]Dn[3177,13,1821,0,1200,510,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]Dg[3177,13,1821,0,1200,510,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]De[3177,13,1821,0,1200,510,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]De[3177,13,1821,0,1200,510,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]Dg[3177,13,1821,0,1200,510,0,\"impl-From%3CCertificateError%3E-for-Error\"]An[3177,13,1821,1821,4818,510,0]An[3177,13,1821,1821,5061,510,0]An[3177,13,1821,1821,4820,510,0]Al[3177,13,3738,534,501,510,0]Am[3177,13,3738,534,3290,510,0]An[3177,13,3738,1389,1187,510,0]An[3177,13,3738,1389,4060,510,0]An[3177,13,3738,2413,1889,510,0]An[3177,13,3738,2413,4367,510,0]An[3177,13,3738,3738,4885,510,0]An[3177,13,4853,4853,1202,510,0]An[3177,13,4853,4853,1205,510,0]An[2035,13,2036,2036,3345,510,0]0Am[2035,13,2036,431,4490,510,0]An[2035,13,2036,2036,2334,510,0]An[2035,13,2036,2036,2348,510,0]An[2035,13,2036,2036,4210,510,0]An[1125,13,1126,1126,3091,510,0]An[1125,13,1126,1126,4996,510,0]Am[1125,13,1729,1729,143,510,0]An[1125,13,1418,1418,1220,510,0]An[1125,13,1418,1418,4084,510,0]An[1125,13,1418,1418,4592,510,0]An[1125,13,4304,4304,5208,510,0]An[1125,13,4304,4304,5209,510,0]Am[1125,13,1826,1826,144,510,0]Ai[476,13,477,0,1482,511,0]Ai[476,13,477,0,1465,511,0]Ai[476,13,477,0,4064,511,0]Ai[476,13,477,0,4203,511,0]Ah[476,13,477,0,525,511,0]Ah[476,13,477,0,134,511,0]Ai[476,13,477,0,2336,511,0]An[3177,13,3178,1858,1483,511,0]An[3177,13,3178,3151,4898,511,0]An[3177,13,3178,1403,1466,511,0]An[3177,13,3178,1150,3126,511,0]An[3177,13,3178,1150,4374,511,0]An[3177,13,3178,1155,3347,511,0]An[3177,13,3178,3279,4065,511,0]An[3177,13,3178,2360,4793,511,0]An[3177,13,3178,1802,4893,511,0]An[3177,13,3178,1831,4204,511,0]Am[3177,13,3178,3178,526,511,0]Am[3177,13,3178,3178,135,511,0]An[3177,13,3178,3178,2337,511,0]An[3177,13,3178,3178,3102,511,0]Am[1226,13,1227,1227,142,512,0]An[1226,13,1227,1227,4075,512,0]An[1226,13,1227,1227,4051,512,0]An[1226,13,1417,1417,4083,512,0]An[1226,13,1417,1417,1219,512,0]An[1226,13,1417,1417,4486,512,0]Ak[535,13,536,536,4052,512,0]An[4089,13,4090,4090,5160,512,0]Al[476,13,477,3742,4611,512,0]Al[476,13,477,3742,2329,512,0]Ai[476,13,477,0,4338,512,0]Al[476,13,477,4270,5062,512,0]Al[476,13,477,1124,2330,512,0]Al[476,13,477,1124,4785,512,0]Al[476,13,477,3742,3298,512,0]Al[476,13,477,3742,3300,512,0]Al[476,13,477,3742,1891,512,0]Al[476,13,477,3742,1457,512,0]Al[476,13,477,3742,3081,512,0]Al[476,13,477,3742,2302,512,0]Al[476,13,477,3742,4232,512,0]Al[476,13,477,3742,4239,512,0]Al[476,13,477,3742,5069,512,0]Al[476,13,477,3742,4897,512,0]Al[476,13,477,2359,2314,512,0]Al[476,13,477,2359,4347,512,0]Al[476,13,477,2359,1436,512,0]Al[476,13,477,4270,1456,512,0]Al[476,13,477,4270,3320,512,0]Al[476,13,477,4270,4997,512,0]Al[476,13,477,2391,2318,512,0]Al[476,13,477,2391,3329,512,0]Al[476,13,477,2391,4465,512,0]Ak[476,13,477,1124,519,512,0]Al[476,13,477,1124,4491,512,0]Al[476,13,477,4157,3326,512,0]Al[476,13,477,4157,5005,512,0]Al[476,13,477,4157,4484,512,0]Al[476,13,477,4157,3125,512,0]Al[476,13,477,4157,3328,512,0]Al[476,13,477,4157,4483,512,0]Al[476,13,477,1430,4249,512,0]Al[476,13,477,1167,4078,512,0]Al[476,13,477,4162,3332,512,0]Al[476,13,477,4162,3346,512,0]Al[476,13,477,4162,4248,512,0]Al[476,13,477,4162,1905,512,0]Ai[476,13,477,0,3323,512,0]Ai[476,13,477,0,4378,512,0]Ai[476,13,477,0,4795,512,0]Ai[476,13,477,0,4603,512,0]Ai[476,13,477,0,4222,512,0]Ai[476,13,477,0,4474,512,0]Ai[476,13,477,0,1482,512,0]Ai[476,13,477,0,5066,512,0]Ai[476,13,477,0,1182,512,0]Ai[476,13,477,0,1465,512,0]Ai[476,13,477,0,3321,512,0]Ai[476,13,477,0,3120,512,0]Ai[476,13,477,0,4951,512,0]Ai[476,13,477,0,3293,512,0]Ai[476,13,477,0,2349,512,0]Ai[476,13,477,0,3306,512,0]Ai[476,13,477,0,3122,512,0]Ai[476,13,477,0,4587,512,0]Ai[476,13,477,0,1915,512,0]Ai[476,13,477,0,4194,512,0]Ai[476,13,477,0,4583,512,0]Ai[476,13,477,0,3116,512,0]Ai[476,13,477,0,4450,512,0]Ai[476,13,477,0,4597,512,0]Ai[476,13,477,0,4606,512,0]Ai[476,13,477,0,4921,512,0]Ai[476,13,477,0,4936,512,0]Ai[476,13,477,0,4064,512,0]Ai[476,13,477,0,4460,512,0]Ai[476,13,477,0,4242,512,0]Ai[476,13,477,0,5123,512,0]Ai[476,13,477,0,4188,512,0]Ai[476,13,477,0,4054,512,0]Ai[476,13,477,0,3103,512,0]Ai[476,13,477,0,4580,512,0]Ai[476,13,477,0,4787,512,0]Ai[476,13,477,0,4200,512,0]Ai[476,13,477,0,4203,512,0]Ai[476,13,477,0,4208,512,0]Ai[476,13,477,0,4956,512,0]Ai[476,13,477,0,3309,512,0]Ai[476,13,477,0,4821,512,0]Ah[476,13,477,0,525,512,0]Ah[476,13,477,0,134,512,0]Ai[476,13,477,0,2336,512,0]Ai[476,13,477,0,2346,512,0]Ai[476,13,3737,0,500,512,0]Aj[476,13,3737,0,3289,512,0]Aj[476,13,3737,0,1186,512,0]Aj[476,13,3737,0,4059,512,0]Aj[476,13,3737,0,1888,512,0]Aj[476,13,3737,0,4366,512,0]Aj[476,13,3737,0,4884,512,0]Aj[476,13,1739,0,1883,512,0]Ai[476,13,1739,0,513,512,0]Aj[476,13,1739,0,5222,512,0]Aj[476,13,1739,0,4057,512,0]Aj[476,13,1739,0,4960,512,0]Aj[476,13,1820,0,3341,512,0]Aj[476,13,1820,0,4349,512,0]Aj[476,13,1820,0,1199,512,0]Aj[476,13,1820,0,4817,512,0]Aj[476,13,1820,0,5060,512,0]Aj[476,13,1820,0,4819,512,0]Am[2413,13,2414,2414,133,512,0]An[2413,13,2414,2414,2305,512,0]An[3177,13,3178,4616,4339,512,0]An[3177,13,3178,3151,3094,512,0]An[3177,13,3178,1150,1445,512,0]An[3177,13,3178,2050,1909,512,0]An[3177,13,3178,2050,3327,512,0]An[3177,13,3178,2050,3333,512,0]An[3177,13,3178,3743,3301,512,0]An[3177,13,3178,1146,3324,512,0]An[3177,13,3178,1737,4379,512,0]An[3177,13,3178,2360,2315,512,0]An[3177,13,3178,2360,4345,512,0]An[3177,13,3178,2360,4796,512,0]An[3177,13,3178,2360,4357,512,0]An[3177,13,3178,1802,5286,512,0]An[3177,13,3178,4387,5254,512,0]An[3177,13,3178,1429,4604,512,0]An[3177,13,3178,1429,4223,512,0]An[3177,13,3178,1429,4475,512,0]An[3177,13,3178,1858,1483,512,0]An[3177,13,3178,1858,5067,512,0]An[3177,13,3178,3142,1183,512,0]An[3177,13,3178,3151,4898,512,0]An[3177,13,3178,1403,1466,512,0]An[3177,13,3178,1403,4238,512,0]An[3177,13,3178,1403,3322,512,0]An[3177,13,3178,1403,3121,512,0]An[3177,13,3178,1403,4896,512,0]An[3177,13,3178,1403,4952,512,0]An[3177,13,3178,1403,3296,512,0]An[3177,13,3178,1419,2350,512,0]An[3177,13,3178,1419,3307,512,0]An[3177,13,3178,1419,3123,512,0]An[3177,13,3178,1419,4588,512,0]An[3177,13,3178,1150,3126,512,0]An[3177,13,3178,1150,4374,512,0]An[3177,13,3178,1155,1916,512,0]An[3177,13,3178,1155,3347,512,0]An[3177,13,3178,1155,4063,512,0]An[3177,13,3178,2050,4082,512,0]An[3177,13,3178,2050,4485,512,0]An[3177,13,3178,2050,4198,512,0]An[3177,13,3178,3743,4584,512,0]An[3177,13,3178,3743,3117,512,0]An[3177,13,3178,3743,4451,512,0]An[3177,13,3178,3743,5155,512,0]An[3177,13,3178,3743,1204,512,0]An[3177,13,3178,1146,4598,512,0]An[3177,13,3178,3279,4607,512,0]An[3177,13,3178,3279,4922,512,0]An[3177,13,3178,3279,4937,512,0]An[3177,13,3178,3279,4065,512,0]An[3177,13,3178,1737,4461,512,0]An[3177,13,3178,1737,4244,512,0]An[3177,13,3178,1737,5124,512,0]An[3177,13,3178,1737,4190,512,0]An[3177,13,3178,1737,4055,512,0]An[3177,13,3178,1393,3104,512,0]An[3177,13,3178,1393,4466,512,0]An[3177,13,3178,1393,3313,512,0]An[3177,13,3178,1393,3336,512,0]An[3177,13,3178,1393,4205,512,0]An[3177,13,3178,1393,4582,512,0]An[3177,13,3178,1393,4789,512,0]An[3177,13,3178,1393,2308,512,0]An[3177,13,3178,2360,4793,512,0]An[3177,13,3178,2360,2319,512,0]An[3177,13,3178,2360,4201,512,0]An[3177,13,3178,2360,4049,512,0]An[3177,13,3178,2360,3330,512,0]An[3177,13,3178,1802,4369,512,0]An[3177,13,3178,1802,4596,512,0]An[3177,13,3178,1802,5159,512,0]An[3177,13,3178,1802,2322,512,0]An[3177,13,3178,1802,4893,512,0]An[3177,13,3178,1831,4586,512,0]An[3177,13,3178,1831,4346,512,0]An[3177,13,3178,1831,4204,512,0]An[3177,13,3178,1831,4209,512,0]Ak[3177,13,3178,0,4489,512,0]Ak[3177,13,3178,0,4957,512,0]An[3177,13,3178,4387,3310,512,0]An[3177,13,3178,4387,5259,512,0]An[3177,13,3178,4992,4822,512,0]Am[3177,13,3178,3178,526,512,0]Am[3177,13,3178,3178,135,512,0]An[3177,13,3178,3178,2337,512,0]An[3177,13,3178,3178,2347,512,0]An[3177,13,3178,3178,3102,512,0]An[3177,13,1735,1735,4380,512,0]An[3177,13,5108,5108,5004,512,0]An[3177,13,5108,5108,1201,512,0]An[3177,13,1740,1740,1884,512,0]Am[3177,13,1740,1740,514,512,0]An[3177,13,1740,1740,5223,512,0]An[3177,13,1740,1740,4058,512,0]An[3177,13,1740,1740,4963,512,0]An[3177,13,1821,1821,3342,512,0]An[3177,13,1821,1821,4350,512,0]Ak[3177,13,1821,0,1200,512,0]An[3177,13,1821,1821,4818,512,0]An[3177,13,1821,1821,5061,512,0]An[3177,13,1821,1821,4820,512,0]Al[3177,13,3738,534,501,512,0]Am[3177,13,3738,534,3290,512,0]An[3177,13,3738,1389,1187,512,0]An[3177,13,3738,1389,4060,512,0]An[3177,13,3738,2413,1889,512,0]An[3177,13,3738,2413,4367,512,0]An[3177,13,3738,3738,4885,512,0]An[3177,13,4853,4853,1202,512,0]An[3177,13,4853,4853,1205,512,0]An[2035,13,2036,2036,3345,512,0]Am[2035,13,2036,431,4490,512,0]An[2035,13,2036,2036,2334,512,0]An[2035,13,2036,2036,2348,512,0]An[2035,13,2036,2036,4210,512,0]An[1125,13,1126,1126,3091,512,0]An[1125,13,1126,1126,4996,512,0]Am[1125,13,1729,1729,143,512,0]An[1125,13,1418,1418,1220,512,0]An[1125,13,1418,1418,4084,512,0]An[1125,13,1418,1418,4592,512,0]An[1125,13,4304,4304,5208,512,0]An[1125,13,4304,4304,5209,512,0]Am[1125,13,1826,1826,144,512,0]Ac[535,7,536,0,0,0,0]Ae[4089,7,4090,0,0,0,0]Ae[4390,7,4391,0,0,0,0]Ae[2413,7,2414,0,0,0,0]Ae[4916,7,4917,0,0,0,0]Al[3177,13,3178,1150,1445,0,0]Ao[3177,13,3178,2360,4357,2320,0]Ah[476,12,1739,0,4886,0,0]Al[3177,13,3178,2050,1909,0,0]Al[3177,12,1740,1740,4887,0,0]Aj[476,13,477,3742,3300,0,0]Ab[1125,3,0,0,0,0,0]Ai[476,13,477,1124,519,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,13,3178,3743,3301,0,0]Al[3177,14,3178,1419,3307,0,0]Aj[476,12,477,2042,3285,0,0]Am[476,13,477,3742,4611,1453,0]Am[476,13,477,3742,2329,1453,0]Am[476,13,477,1124,2330,1453,0]Am[476,13,477,3742,3298,1453,0]Am[476,13,477,3742,1891,1453,0]Am[476,13,477,3742,1457,1453,0]Am[476,13,477,3742,3081,1453,0]Am[476,13,477,3742,2302,1453,0]Am[476,13,477,3742,4232,1453,0]Am[476,13,477,3742,4239,1453,0]Am[476,13,477,2359,1436,1453,0]Am[476,13,477,2391,4465,1453,0]Am[476,13,477,4162,1905,1453,0]?Aj[476,13,477,4157,3326,0,0]Al[3177,13,3178,2050,3327,0,0]Al[3177,13,5108,5108,5004,0,0]Al[3177,13,3178,3151,3094,0,0]Ak[2035,13,2036,431,4490,0,0]Ah[476,12,1739,0,4886,0,0]Al[3177,12,1740,1740,4887,0,0]32Ag[476,13,477,0,5123,0,0]Al[3177,13,3178,1737,5124,0,0]Aj[476,13,477,3742,3300,0,0]Al[3177,13,3178,3743,3301,0,0]Ah[476,12,1739,0,1879,0,0]Al[3177,12,1740,1740,1880,0,0]Al[1226,14,1417,1417,4486,0,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Ai[3177,14,4595,0,1216,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5005,0,0]Al[3177,13,3178,2050,3327,0,0]Ag[476,12,477,0,3343,0,0]Aj[476,13,477,0,4474,3343,0]Aj[476,13,477,0,4821,3343,0]Al[3177,12,3178,1429,3344,0,0]Ao[3177,13,3178,1429,4475,3344,0]Ao[3177,13,3178,4992,4822,3344,0]Af[476,5,477,3142,0,0,0]Ah[3177,5,3178,3142,0,0,0]Ag[476,5,3737,1389,0,0,0]Ah[3177,5,3738,1389,0,0,0]Al[1125,15,1126,1126,4996,0,0]Ag[476,6,1820,1392,0,0,0]Ah[3177,6,1821,1392,0,0,0]Ae[3177,6,5108,0,0,0,0]Ae[3177,6,4853,0,0,0,0]Ah[3177,6,3178,3743,0,0,0]1Al[3177,15,3178,1393,3313,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Aj[476,15,477,4157,3125,0,0]Ag[476,15,477,0,4583,0,0]Al[3177,15,3178,1150,3126,0,0]Al[3177,15,3178,3743,4584,0,0]Al[3177,15,3178,1802,4596,0,0]0Ae[1226,5,1417,0,0,0,0]Ae[1125,5,1418,0,0,0,0]Al[1226,15,1227,1227,4075,0,0]Ag[476,13,477,0,4795,0,0]Al[3177,13,3178,2360,4796,0,0]Ab[1226,3,0,0,0,0,0]Ah[476,12,3737,0,4882,0,0]Ak[476,13,3737,0,3289,4882,0]Ak[476,13,3737,0,4059,4882,0]Ak[476,13,3737,0,4366,4882,0]Al[3177,12,3738,3738,4883,0,0]An[3177,13,3738,534,3290,4883,0]Ao[3177,13,3738,1389,4060,4883,0]Ao[3177,13,3738,2413,4367,4883,0]Al[1125,13,1126,1126,4996,0,0]Ag[476,14,477,0,1182,0,0]Ag[476,14,477,0,2349,0,0]Ag[476,14,477,0,1915,0,0]Al[3177,14,3178,3142,1183,0,0]Al[3177,14,3178,1419,2350,0,0]Al[3177,14,3178,1155,1916,0,0]Al[3177,14,3178,2360,4049,0,0]An[1226,13,1227,1227,142,1184,0]Ao[1226,13,1227,1227,4075,1184,0]Ao[1226,13,1227,1227,4051,1184,0]Am[476,13,477,3742,3300,1184,0]Am[476,13,477,3742,5069,1184,0]Am[476,13,477,3742,4897,1184,0]Am[476,13,477,2359,2314,1184,0]Am[476,13,477,2359,4347,1184,0]Am[476,13,477,4270,1456,1184,0]Al[476,13,477,1124,519,1184,0]Am[476,13,477,1124,4491,1184,0]Am[476,13,477,4157,4484,1184,0]Am[476,13,477,4157,3125,1184,0]Am[476,13,477,4157,3328,1184,0]Am[476,13,477,4157,4483,1184,0]Am[476,13,477,4162,3346,1184,0]Am[476,13,477,4162,4248,1184,0]Aj[476,13,477,0,1482,1184,0]Aj[476,13,477,0,5066,1184,0]Aj[476,13,477,0,1465,1184,0]Aj[476,13,477,0,3321,1184,0]Aj[476,13,477,0,3120,1184,0]Aj[476,13,477,0,4951,1184,0]Aj[476,13,477,0,3293,1184,0]Aj[476,13,477,0,2349,1184,0]Aj[476,13,477,0,3306,1184,0]Aj[476,13,477,0,3122,1184,0]Aj[476,13,477,0,4587,1184,0]Aj[476,13,477,0,1915,1184,0]Aj[476,13,477,0,4194,1184,0]Aj[476,13,477,0,4583,1184,0]Aj[476,13,477,0,3116,1184,0]Aj[476,13,477,0,4450,1184,0]Aj[476,13,477,0,4606,1184,0]Aj[476,13,477,0,4921,1184,0]Aj[476,13,477,0,4936,1184,0]Aj[476,13,477,0,4064,1184,0]Aj[476,13,477,0,4460,1184,0]Aj[476,13,477,0,4242,1184,0]Aj[476,13,477,0,5123,1184,0]Aj[476,13,477,0,4188,1184,0]Aj[476,13,477,0,4054,1184,0]Aj[476,13,477,0,3103,1184,0]Aj[476,13,477,0,4580,1184,0]Aj[476,13,477,0,4787,1184,0]Aj[476,13,477,0,4200,1184,0]Aj[476,13,477,0,4203,1184,0]Aj[476,13,477,0,4208,1184,0]Aj[476,13,477,0,4956,1184,0]Aj[476,13,477,0,3309,1184,0]Ai[476,13,477,0,525,1184,0]Ai[476,13,477,0,134,1184,0]Aj[476,13,477,0,2336,1184,0]Aj[476,13,3737,0,500,1184,0]Ak[476,13,3737,0,3289,1184,0]Ak[476,13,3737,0,1186,1184,0]Ak[476,13,3737,0,4059,1184,0]Ak[476,13,3737,0,1888,1184,0]Ak[476,13,3737,0,4366,1184,0]Ak[476,13,1820,0,1199,1184,0]Ak[476,13,1820,0,4817,1184,0]Ak[476,13,1820,0,5060,1184,0]Ak[476,13,1820,0,4819,1184,0]Ao[3177,13,3178,1858,1483,1184,0]Ao[3177,13,3178,1858,5067,1184,0]Ao[3177,13,3178,3151,4898,1184,0]Ao[3177,13,3178,1403,1466,1184,0]Ao[3177,13,3178,1403,4238,1184,0]Ao[3177,13,3178,1403,3322,1184,0]Ao[3177,13,3178,1403,3121,1184,0]Ao[3177,13,3178,1403,4896,1184,0]Ao[3177,13,3178,1403,4952,1184,0]Ao[3177,13,3178,1403,3296,1184,0]Ao[3177,13,3178,1419,2350,1184,0]Ao[3177,13,3178,1419,3307,1184,0]Ao[3177,13,3178,1419,3123,1184,0]Ao[3177,13,3178,1419,4588,1184,0]Ao[3177,13,3178,1150,3126,1184,0]Ao[3177,13,3178,1150,4374,1184,0]Ao[3177,13,3178,1155,1916,1184,0]Ao[3177,13,3178,1155,3347,1184,0]Ao[3177,13,3178,1155,4063,1184,0]Ao[3177,13,3178,2050,4485,1184,0]Ao[3177,13,3178,2050,4198,1184,0]Ao[3177,13,3178,3743,4584,1184,0]Ao[3177,13,3178,3743,3117,1184,0]Ao[3177,13,3178,3743,4451,1184,0]Ao[3177,13,3178,3743,5155,1184,0]Ao[3177,13,3178,3279,4607,1184,0]Ao[3177,13,3178,3279,4922,1184,0]Ao[3177,13,3178,3279,4937,1184,0]Ao[3177,13,3178,3279,4065,1184,0]Ao[3177,13,3178,1737,4461,1184,0]Ao[3177,13,3178,1737,4244,1184,0]Ao[3177,13,3178,1737,5124,1184,0]Ao[3177,13,3178,1737,4190,1184,0]Ao[3177,13,3178,1737,4055,1184,0]Ao[3177,13,3178,1393,3104,1184,0]Ao[3177,13,3178,1393,3313,1184,0]Ao[3177,13,3178,1393,3336,1184,0]Ao[3177,13,3178,1393,4205,1184,0]Ao[3177,13,3178,1393,4582,1184,0]Ao[3177,13,3178,1393,4789,1184,0]Ao[3177,13,3178,1393,2308,1184,0]Ao[3177,13,3178,2360,4793,1184,0]Ao[3177,13,3178,2360,4201,1184,0]Ao[3177,13,3178,1802,4596,1184,0]Ao[3177,13,3178,1802,5159,1184,0]Ao[3177,13,3178,1802,2322,1184,0]Ao[3177,13,3178,1802,4893,1184,0]Ao[3177,13,3178,1831,4204,1184,0]Ao[3177,13,3178,1831,4209,1184,0]Al[3177,13,3178,0,4489,1184,0]Al[3177,13,3178,0,4957,1184,0]Ao[3177,13,3178,4387,3310,1184,0]Ao[3177,13,3178,4387,5259,1184,0]An[3177,13,3178,3178,526,1184,0]An[3177,13,3178,3178,135,1184,0]Ao[3177,13,3178,3178,2337,1184,0]Ao[3177,13,3178,3178,3102,1184,0]Ao[3177,13,1735,1735,4380,1184,0]Ao[3177,13,5108,5108,5004,1184,0]Ao[3177,13,5108,5108,1201,1184,0]Al[3177,13,1821,0,1200,1184,0]Ao[3177,13,1821,1821,4818,1184,0]Ao[3177,13,1821,1821,5061,1184,0]Ao[3177,13,1821,1821,4820,1184,0]Am[3177,13,3738,534,501,1184,0]An[3177,13,3738,534,3290,1184,0]Ao[3177,13,3738,1389,1187,1184,0]Ao[3177,13,3738,1389,4060,1184,0]Ao[3177,13,3738,2413,1889,1184,0]Ao[3177,13,3738,2413,4367,1184,0]Ao[3177,13,4853,4853,1205,1184,0]Ao[2035,13,2036,2036,2334,1184,0]Ao[2035,13,2036,2036,2348,1184,0]Ao[2035,13,2036,2036,4210,1184,0]Ao[1125,13,1126,1126,4996,1184,0]Ao[1125,13,1418,1418,4592,1184,0]Ao[1125,13,4304,4304,5208,1184,0]Ao[1125,13,4304,4304,5209,1184,0]Aj[476,13,477,3742,3300,0,0]Aj[476,13,477,2359,2314,0,0]Ai[476,13,477,1124,519,0,0]Al[3177,13,3178,3743,3301,0,0]Aj[476,13,477,0,4203,1190,0]Ao[3177,13,3178,1831,4204,1190,0]Ai[3177,14,3178,0,4489,0,0]Ag[476,13,477,0,2336,0,0]Al[3177,13,3178,3178,2337,0,0]Ag[476,13,477,0,4208,0,0]Al[3177,13,3178,1831,4209,0,0]Ah[476,14,1739,0,1883,0,0]Al[3177,14,1740,1740,1884,0,0]Al[3177,12,3178,1802,4927,0,0]Ao[3177,13,3178,1802,5286,4927,0];Al[1226,13,1417,1417,1219,0,0]Ai[535,13,536,536,4052,0,0]Al[1125,13,1418,1418,1220,0,0]Aj[476,12,477,2042,3285,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2315,0,0]Aj[476,12,477,2042,1900,0,0]Am[476,13,477,1430,4249,1900,0]Am[476,13,477,1167,4078,1900,0]Ae[1226,2,1227,0,0,0,0]Ak[1226,14,1227,1227,142,0,0]Aj[476,13,477,3742,3300,0,0]Aj[476,13,477,2359,2314,0,0]Ai[476,13,477,1124,519,0,0]Al[3177,13,3178,3743,3301,0,0]Ae[1125,2,1126,0,0,0,0]Ag[476,13,477,0,3323,0,0]Al[3177,13,3178,1146,3324,0,0]?>Al[3177,13,5108,5108,5004,0,0]Af[476,5,477,2359,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Al[1226,15,1227,1227,4051,0,0]0Ag[476,15,477,0,3321,0,0]Al[3177,15,3178,1403,3322,0,0]Ah[3177,5,3178,1150,0,0,0]Af[476,15,477,0,525,0,0]Al[2413,15,2414,2414,2305,0,0]Ak[3177,15,3178,3178,526,0,0]Al[3177,15,4853,4853,1202,0,0]98Af[476,5,477,4270,0,0,0]Af[476,5,477,3742,0,0,0]Ag[476,15,477,0,3120,0,0]Al[3177,15,3178,1403,3121,0,0]Al[3177,15,3178,2050,4082,0,0]Af[476,5,477,1403,0,0,0]Ah[3177,5,3178,1403,0,0,0]Ae[3177,8,1735,0,0,0,0];:9Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,3743,1204,0,0]Al[3177,15,3178,1393,3104,0,0]Af[476,5,477,1858,0,0,0]Ah[3177,5,3178,1858,0,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2050,1909,0,0]Al[3177,13,3178,2360,2315,0,0]An[1226,13,1227,1227,142,1443,0]Ao[1226,13,1227,1227,4075,1443,0]Ao[1226,13,1227,1227,4051,1443,0]Ao[1226,13,1417,1417,4083,1443,0]Ao[1226,13,1417,1417,1219,1443,0]Ao[1226,13,1417,1417,4486,1443,0]Al[535,13,536,536,4052,1443,0]Ao[4089,13,4090,4090,5160,1443,0]Am[476,13,477,3742,4611,1443,0]Am[476,13,477,3742,2329,1443,0]Aj[476,13,477,0,4338,1443,0]Am[476,13,477,4270,5062,1443,0]Am[476,13,477,1124,2330,1443,0]Am[476,13,477,1124,4785,1443,0]Am[476,13,477,3742,3298,1443,0]Am[476,13,477,3742,3300,1443,0]Am[476,13,477,3742,1891,1443,0]Am[476,13,477,3742,1457,1443,0]Am[476,13,477,3742,3081,1443,0]Am[476,13,477,3742,2302,1443,0]Am[476,13,477,3742,4232,1443,0]Am[476,13,477,3742,4239,1443,0]Am[476,13,477,3742,5069,1443,0]Am[476,13,477,3742,4897,1443,0]Am[476,13,477,2359,2314,1443,0]Am[476,13,477,2359,4347,1443,0]Am[476,13,477,2359,1436,1443,0]Am[476,13,477,4270,1456,1443,0]Am[476,13,477,4270,3320,1443,0]Am[476,13,477,4270,4997,1443,0]Am[476,13,477,2391,2318,1443,0]Am[476,13,477,2391,3329,1443,0]Am[476,13,477,2391,4465,1443,0]Al[476,13,477,1124,519,1443,0]Am[476,13,477,1124,4491,1443,0]Am[476,13,477,4157,3326,1443,0]Am[476,13,477,4157,5005,1443,0]Am[476,13,477,4157,4484,1443,0]Am[476,13,477,4157,3125,1443,0]Am[476,13,477,4157,3328,1443,0]Am[476,13,477,4157,4483,1443,0]Am[476,13,477,1430,4249,1443,0]Am[476,13,477,1167,4078,1443,0]Am[476,13,477,4162,3332,1443,0]Am[476,13,477,4162,3346,1443,0]Am[476,13,477,4162,4248,1443,0]Am[476,13,477,4162,1905,1443,0]Aj[476,13,477,0,3323,1443,0]Aj[476,13,477,0,4378,1443,0]Aj[476,13,477,0,4795,1443,0]Aj[476,13,477,0,4603,1443,0]Aj[476,13,477,0,4222,1443,0]Aj[476,13,477,0,4474,1443,0]Aj[476,13,477,0,1482,1443,0]Aj[476,13,477,0,5066,1443,0]Aj[476,13,477,0,1182,1443,0]Aj[476,13,477,0,1465,1443,0]Aj[476,13,477,0,3321,1443,0]Aj[476,13,477,0,3120,1443,0]Aj[476,13,477,0,4951,1443,0]Aj[476,13,477,0,3293,1443,0]Aj[476,13,477,0,2349,1443,0]Aj[476,13,477,0,3306,1443,0]Aj[476,13,477,0,3122,1443,0]Aj[476,13,477,0,4587,1443,0]Aj[476,13,477,0,1915,1443,0]Aj[476,13,477,0,4194,1443,0]Aj[476,13,477,0,4583,1443,0]Aj[476,13,477,0,3116,1443,0]Aj[476,13,477,0,4450,1443,0]Aj[476,13,477,0,4597,1443,0]Aj[476,13,477,0,4606,1443,0]Aj[476,13,477,0,4921,1443,0]Aj[476,13,477,0,4936,1443,0]Aj[476,13,477,0,4064,1443,0]Aj[476,13,477,0,4460,1443,0]Aj[476,13,477,0,4242,1443,0]Aj[476,13,477,0,5123,1443,0]Aj[476,13,477,0,4188,1443,0]Aj[476,13,477,0,4054,1443,0]Aj[476,13,477,0,3103,1443,0]Aj[476,13,477,0,4580,1443,0]Aj[476,13,477,0,4787,1443,0]Aj[476,13,477,0,4200,1443,0]Aj[476,13,477,0,4203,1443,0]Aj[476,13,477,0,4208,1443,0]Aj[476,13,477,0,4956,1443,0]Aj[476,13,477,0,3309,1443,0]Aj[476,13,477,0,4821,1443,0]Ai[476,13,477,0,525,1443,0]Ai[476,13,477,0,134,1443,0]Aj[476,13,477,0,2336,1443,0]Aj[476,13,477,0,2346,1443,0]Aj[476,13,3737,0,500,1443,0]Ak[476,13,3737,0,3289,1443,0]Ak[476,13,3737,0,1186,1443,0]Ak[476,13,3737,0,4059,1443,0]Ak[476,13,3737,0,1888,1443,0]Ak[476,13,3737,0,4366,1443,0]Ak[476,13,3737,0,4884,1443,0]Ak[476,13,1739,0,1883,1443,0]Aj[476,13,1739,0,513,1443,0]Ak[476,13,1739,0,5222,1443,0]Ak[476,13,1739,0,4057,1443,0]Ak[476,13,1739,0,4960,1443,0]Ak[476,13,1820,0,3341,1443,0]Ak[476,13,1820,0,4349,1443,0]Ak[476,13,1820,0,1199,1443,0]Ak[476,13,1820,0,4817,1443,0]Ak[476,13,1820,0,5060,1443,0]Ak[476,13,1820,0,4819,1443,0]An[2413,13,2414,2414,133,1443,0]Ao[2413,13,2414,2414,2305,1443,0]Ao[3177,13,3178,4616,4339,1443,0]Ao[3177,13,3178,3151,3094,1443,0]Ao[3177,13,3178,1150,1445,1443,0]Ao[3177,13,3178,2050,1909,1443,0]Ao[3177,13,3178,2050,3327,1443,0]Ao[3177,13,3178,2050,3333,1443,0]Ao[3177,13,3178,3743,3301,1443,0]Ao[3177,13,3178,1146,3324,1443,0]Ao[3177,13,3178,1737,4379,1443,0]Ao[3177,13,3178,2360,2315,1443,0]Ao[3177,13,3178,2360,4345,1443,0]Ao[3177,13,3178,2360,4796,1443,0]Ao[3177,13,3178,2360,4357,1443,0]Ao[3177,13,3178,1802,5286,1443,0]Ao[3177,13,3178,4387,5254,1443,0]Ao[3177,13,3178,1429,4604,1443,0]Ao[3177,13,3178,1429,4223,1443,0]Ao[3177,13,3178,1429,4475,1443,0]Ao[3177,13,3178,1858,1483,1443,0]Ao[3177,13,3178,1858,5067,1443,0]Ao[3177,13,3178,3142,1183,1443,0]Ao[3177,13,3178,3151,4898,1443,0]Ao[3177,13,3178,1403,1466,1443,0]Ao[3177,13,3178,1403,4238,1443,0]Ao[3177,13,3178,1403,3322,1443,0]Ao[3177,13,3178,1403,3121,1443,0]Ao[3177,13,3178,1403,4896,1443,0]Ao[3177,13,3178,1403,4952,1443,0]Ao[3177,13,3178,1403,3296,1443,0]Ao[3177,13,3178,1419,2350,1443,0]Ao[3177,13,3178,1419,3307,1443,0]Ao[3177,13,3178,1419,3123,1443,0]Ao[3177,13,3178,1419,4588,1443,0]Ao[3177,13,3178,1150,3126,1443,0]Ao[3177,13,3178,1150,4374,1443,0]Ao[3177,13,3178,1155,1916,1443,0]Ao[3177,13,3178,1155,3347,1443,0]Ao[3177,13,3178,1155,4063,1443,0]Ao[3177,13,3178,2050,4082,1443,0]Ao[3177,13,3178,2050,4485,1443,0]Ao[3177,13,3178,2050,4198,1443,0]Ao[3177,13,3178,3743,4584,1443,0]Ao[3177,13,3178,3743,3117,1443,0]Ao[3177,13,3178,3743,4451,1443,0]Ao[3177,13,3178,3743,5155,1443,0]Ao[3177,13,3178,3743,1204,1443,0]Ao[3177,13,3178,1146,4598,1443,0]Ao[3177,13,3178,3279,4607,1443,0]Ao[3177,13,3178,3279,4922,1443,0]Ao[3177,13,3178,3279,4937,1443,0]Ao[3177,13,3178,3279,4065,1443,0]Ao[3177,13,3178,1737,4461,1443,0]Ao[3177,13,3178,1737,4244,1443,0]Ao[3177,13,3178,1737,5124,1443,0]Ao[3177,13,3178,1737,4190,1443,0]Ao[3177,13,3178,1737,4055,1443,0]Ao[3177,13,3178,1393,3104,1443,0]Ao[3177,13,3178,1393,4466,1443,0]Ao[3177,13,3178,1393,3313,1443,0]Ao[3177,13,3178,1393,3336,1443,0]Ao[3177,13,3178,1393,4205,1443,0]Ao[3177,13,3178,1393,4582,1443,0]Ao[3177,13,3178,1393,4789,1443,0]Ao[3177,13,3178,1393,2308,1443,0]Ao[3177,13,3178,2360,4793,1443,0]Ao[3177,13,3178,2360,2319,1443,0]Ao[3177,13,3178,2360,4201,1443,0]Ao[3177,13,3178,2360,4049,1443,0]Ao[3177,13,3178,2360,3330,1443,0]Ao[3177,13,3178,1802,4369,1443,0]Ao[3177,13,3178,1802,4596,1443,0]Ao[3177,13,3178,1802,5159,1443,0]Ao[3177,13,3178,1802,2322,1443,0]Ao[3177,13,3178,1802,4893,1443,0]Ao[3177,13,3178,1831,4586,1443,0]Ao[3177,13,3178,1831,4346,1443,0]Ao[3177,13,3178,1831,4204,1443,0]Ao[3177,13,3178,1831,4209,1443,0]Al[3177,13,3178,0,4489,1443,0]Al[3177,13,3178,0,4957,1443,0]Ao[3177,13,3178,4387,3310,1443,0]Ao[3177,13,3178,4387,5259,1443,0]Ao[3177,13,3178,4992,4822,1443,0]An[3177,13,3178,3178,526,1443,0]An[3177,13,3178,3178,135,1443,0]Ao[3177,13,3178,3178,2337,1443,0]Ao[3177,13,3178,3178,2347,1443,0]Ao[3177,13,3178,3178,3102,1443,0]Ao[3177,13,1735,1735,4380,1443,0]Ao[3177,13,5108,5108,5004,1443,0]Ao[3177,13,5108,5108,1201,1443,0]Ao[3177,13,1740,1740,1884,1443,0]An[3177,13,1740,1740,514,1443,0]Ao[3177,13,1740,1740,5223,1443,0]Ao[3177,13,1740,1740,4058,1443,0]Ao[3177,13,1740,1740,4963,1443,0]Ao[3177,13,1821,1821,3342,1443,0]Ao[3177,13,1821,1821,4350,1443,0]Al[3177,13,1821,0,1200,1443,0]Ao[3177,13,1821,1821,4818,1443,0]Ao[3177,13,1821,1821,5061,1443,0]Ao[3177,13,1821,1821,4820,1443,0]Am[3177,13,3738,534,501,1443,0]An[3177,13,3738,534,3290,1443,0]Ao[3177,13,3738,1389,1187,1443,0]Ao[3177,13,3738,1389,4060,1443,0]Ao[3177,13,3738,2413,1889,1443,0]Ao[3177,13,3738,2413,4367,1443,0]Ao[3177,13,3738,3738,4885,1443,0]Ao[3177,13,4853,4853,1202,1443,0]Ao[3177,13,4853,4853,1205,1443,0]Ao[2035,13,2036,2036,3345,1443,0]An[2035,13,2036,431,4490,1443,0]Ao[2035,13,2036,2036,2334,1443,0]Ao[2035,13,2036,2036,2348,1443,0]Ao[2035,13,2036,2036,4210,1443,0]Ao[1125,13,1126,1126,3091,1443,0]Ao[1125,13,1126,1126,4996,1443,0]An[1125,13,1729,1729,143,1443,0]Ao[1125,13,1418,1418,1220,1443,0]Ao[1125,13,1418,1418,4084,1443,0]Ao[1125,13,1418,1418,4592,1443,0]Ao[1125,13,4304,4304,5208,1443,0]Ao[1125,13,4304,4304,5209,1443,0]An[1125,13,1826,1826,144,1443,0]Ag[476,14,477,0,1915,0,0]Al[3177,14,3178,1155,1916,0,0]Ak[1226,14,1227,1227,142,0,0]Ac[535,7,536,0,0,0,0]Aj[476,13,477,2359,2314,0,0]Ae[1125,2,1126,0,0,0,0]Ae[4916,7,4917,0,0,0,0]Aj[476,13,477,3742,3300,0,0]Ae[3177,2,3178,0,0,0,0]Al[3177,13,3178,2360,2315,0,0]Af[476,2,477,3178,0,0,0]Ag[476,13,477,0,4956,0,0]Ag[476,14,477,0,3306,0,0]Ag[476,14,477,0,4242,0,0]5Ai[3177,13,3178,0,4957,0,0]Al[3177,14,3178,1419,3307,0,0]Al[3177,14,3178,1737,4244,0,0]Ai[3177,14,3178,0,4489,0,0]Aj[476,13,477,0,1482,3095,0]Aj[476,13,477,0,1465,3095,0]Aj[476,13,477,0,3103,3095,0]Aj[476,13,477,0,4956,3095,0]Aj[476,13,477,0,2336,3095,0]Ao[3177,13,3178,1858,1483,3095,0]Ao[3177,13,3178,1403,1466,3095,0]Ao[3177,13,3178,1393,3104,3095,0]Ao[3177,13,3178,1393,3313,3095,0]Al[3177,13,3178,1802,4596,0,0]Al[3177,13,3178,0,4957,3095,0]Ao[3177,13,3178,3178,2337,3095,0]Al[3177,12,1735,1735,3095,0,0]Al[2035,14,2036,2036,2334,0,0]Aj[476,13,477,0,1482,3100,0]Aj[476,13,477,0,1465,3100,0]Aj[476,13,477,0,3103,3100,0]Aj[476,13,477,0,4956,3100,0]Aj[476,13,477,0,2336,3100,0]Ao[3177,13,3178,1858,1483,3100,0]Ao[3177,13,3178,1403,1466,3100,0]Ao[3177,13,3178,1393,3104,3100,0]Ao[3177,13,3178,1393,3313,3100,0]Ao[3177,13,3178,1393,2308,3100,0]Al[3177,13,3178,0,4957,3100,0]Ao[3177,13,3178,3178,2337,3100,0]Al[3177,12,1735,1735,3100,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]Al[1125,13,1418,1418,4084,0,0]Al[3177,13,3178,2360,2315,0,0]Ag[476,14,1739,0,513,0,0]Ak[3177,14,1740,1740,514,0,0]Aj[476,13,477,2391,2318,0,0]3Ag[476,12,477,0,3343,0,0]Aj[476,13,477,0,4474,3343,0]Aj[476,13,477,0,4821,3343,0]Al[3177,12,3178,1429,3344,0,0]Ao[3177,13,3178,1429,4475,3344,0]Ao[3177,13,3178,4992,4822,3344,0]Al[1125,14,1126,1126,3091,0,0]Ag[476,14,477,0,1182,0,0]Al[3177,14,3178,3142,1183,0,0]Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Ag[476,14,1739,0,513,0,0]Ak[3177,14,1740,1740,514,0,0]Ai[3177,14,4595,0,4827,0,0]Ag[476,14,477,0,4580,0,0]Ag[476,14,477,0,4787,0,0]Ah[476,14,3118,0,3077,0,0]Al[3177,14,3178,1393,4582,0,0]Al[3177,14,3178,1393,4789,0,0]Ai[3177,14,3178,0,4489,0,0]Ai[3177,14,1203,0,4453,0,0]Ai[3177,14,3119,0,3078,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2315,0,0]Ah[476,14,1739,0,1883,0,0]Al[3177,13,3178,3178,3102,0,0]Al[3177,14,1740,1740,1884,0,0]Ac[476,4,477,0,0,0,0]Ag[476,2,1739,1740,0,0,0]Ae[3177,4,3178,0,0,0,0]Ae[3177,2,1740,0,0,0,0]Ac[535,7,536,0,0,0,0]:Ae[1125,2,1126,0,0,0,0]Ae[4916,7,4917,0,0,0,0]Am[476,13,477,3742,4897,1192,0]Am[476,13,477,4157,4484,1192,0]Am[476,13,477,4157,3125,1192,0]Am[476,13,477,4157,3328,1192,0]Am[476,13,477,4157,4483,1192,0]Am[476,13,477,4162,3346,1192,0]Am[476,13,477,4162,4248,1192,0]Aj[476,13,477,0,4583,1192,0]Ao[3177,13,3178,3743,4584,1192,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Al[2035,14,2036,2036,2348,0,0]Ai[476,13,477,1124,519,0,0]Ah[476,14,3118,0,4233,0,0]Ai[3177,14,3119,0,4234,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Al[2035,14,2036,2036,2334,0,0]Ag[476,14,477,0,3122,0,0]Ag[476,14,477,0,4587,0,0]Al[3177,14,3178,1419,3123,0,0]Al[3177,14,3178,1419,4588,0,0]3210Ah[476,12,1739,0,1879,0,0]Al[3177,12,1740,1740,1880,0,0]Ah[476,12,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,12,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Al[3177,15,3178,3151,4898,0,0]Al[3177,15,3178,1150,3126,0,0]Al[3177,15,3178,1155,3347,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Ah[476,10,1739,1740,0,0,0]Af[3177,10,1740,0,0,0,0]Al[3177,15,3178,1802,4596,0,0]Ag[476,5,1739,1740,0,0,0]Ae[3177,5,1740,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ag[476,5,3737,2413,0,0,0]Ah[3177,5,3738,2413,0,0,0]Al[1125,15,1126,1126,4996,0,0]Af[476,5,477,3742,0,0,0]5454Ag[476,10,477,2042,0,0,0];:Aj[476,15,477,4162,3346,0,0]Af[476,5,477,4162,0,0,0]Al[3177,15,3178,1155,3347,0,0]Al[3177,15,3178,1155,4063,0,0]Al[3177,15,3178,2050,4082,0,0]Ah[3177,5,3178,2050,0,0,0]Aj[476,15,477,4157,4484,0,0]Al[3177,15,3178,1393,3313,0,0]Af[476,5,477,1155,0,0,0]Ah[3177,5,3178,1155,0,0,0]Al[3177,15,3178,1802,2322,0,0]Ag[476,12,477,0,5114,0,0]Al[3177,12,3178,4387,5115,0,0]Ao[3177,13,3178,4387,5254,5115,0]Ao[3177,13,3178,4387,5259,5115,0]Ak[1226,14,1227,1227,142,0,0]An[1226,13,1227,1227,142,4452,0]An[2413,13,2414,2414,133,4452,0]Ak[2413,14,2414,2414,133,0,0]Ao[1125,13,1126,1126,3091,4452,0]An[1125,13,1729,1729,143,4452,0]An[1125,13,1826,1826,144,4452,0]Aj[476,13,477,0,1482,3297,0]Aj[476,13,477,0,1465,3297,0]Aj[476,13,477,0,4064,3297,0]Aj[476,13,477,0,4203,3297,0]Ai[476,13,477,0,525,3297,0]Ai[476,13,477,0,134,3297,0]Aj[476,13,477,0,2336,3297,0]Ao[3177,13,3178,1858,1483,3297,0]Ao[3177,13,3178,3151,4898,3297,0]Ao[3177,13,3178,1403,1466,3297,0]Ao[3177,13,3178,1150,3126,3297,0]Ao[3177,13,3178,1150,4374,3297,0]Ao[3177,13,3178,1155,3347,3297,0]Ao[3177,13,3178,3279,4065,3297,0]Ao[3177,13,3178,2360,4793,3297,0]Ao[3177,13,3178,1802,4893,3297,0]Ao[3177,13,3178,1831,4204,3297,0]An[3177,13,3178,3178,526,3297,0]An[3177,13,3178,3178,135,3297,0]Ao[3177,13,3178,3178,2337,3297,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,2360,2315,0,0]Aj[476,13,477,2391,2318,0,0]Ah[476,12,1739,0,3113,0,0]Ah[476,12,1739,0,3106,0,0]Al[3177,13,3178,2360,2319,0,0]Al[3177,12,1740,1740,3114,0,0]Al[3177,12,1740,1740,3107,0,0]Ao[1226,13,1417,1417,4083,1874,0]Ao[1226,13,1417,1417,1219,1874,0]Al[535,13,536,536,4052,1874,0]Aj[476,13,477,0,4338,1874,0]Am[476,13,477,2359,4347,1874,0]Aj[476,13,477,0,1482,1874,0]Aj[476,13,477,0,1465,1874,0]Aj[476,13,477,0,3321,1874,0]Aj[476,13,477,0,3293,1874,0]Aj[476,13,477,0,2349,1874,0]Aj[476,13,477,0,3306,1874,0]Aj[476,13,477,0,3122,1874,0]Aj[476,13,477,0,4587,1874,0]Aj[476,13,477,0,1915,1874,0]Aj[476,13,477,0,4194,1874,0]Aj[476,13,477,0,4606,1874,0]Aj[476,13,477,0,4921,1874,0]Aj[476,13,477,0,4936,1874,0]Aj[476,13,477,0,4064,1874,0]Aj[476,13,477,0,4460,1874,0]Aj[476,13,477,0,5123,1874,0]Aj[476,13,477,0,4821,1874,0]Ak[476,13,3737,0,3289,1874,0]Ak[476,13,3737,0,4059,1874,0]Ak[476,13,3737,0,4366,1874,0]Ak[476,13,3737,0,4884,1874,0]Ao[3177,13,3178,4616,4339,1874,0]Ao[3177,13,3178,4387,5254,1874,0]Ao[3177,13,3178,1858,1483,1874,0]Ao[3177,13,3178,1403,1466,1874,0]Ao[3177,13,3178,1403,3322,1874,0]Ao[3177,13,3178,1403,3296,1874,0]Ao[3177,13,3178,1419,2350,1874,0]Ao[3177,13,3178,1419,3307,1874,0]Ao[3177,13,3178,1419,3123,1874,0]Ao[3177,13,3178,1419,4588,1874,0]Ao[3177,13,3178,1155,1916,1874,0]Ao[3177,13,3178,2050,4485,1874,0]Ao[3177,13,3178,2050,4198,1874,0]Ao[3177,13,3178,3279,4607,1874,0]Ao[3177,13,3178,3279,4922,1874,0]Ao[3177,13,3178,3279,4937,1874,0]Ao[3177,13,3178,3279,4065,1874,0]Ao[3177,13,3178,1737,4461,1874,0]Ao[3177,13,3178,1737,5124,1874,0]Ao[3177,13,3178,4387,5259,1874,0]Ao[3177,13,3178,4992,4822,1874,0]An[3177,13,3738,534,3290,1874,0]Ao[3177,13,3738,1389,4060,1874,0]Ao[3177,13,3738,2413,4367,1874,0]Ao[3177,13,3738,3738,4885,1874,0]Ao[2035,13,2036,2036,2334,1874,0]Ao[1125,13,1418,1418,1220,1874,0]Ao[1125,13,1418,1418,4592,1874,0]Al[3177,13,3178,1831,4346,0,0]Al[3177,13,3178,1802,4369,0,0]Al[3177,13,3178,1802,4596,0,0]Al[3177,14,3178,1802,5159,0,0]Ai[3177,14,4892,0,4958,0,0]Ah[3177,14,4595,0,515,0,0]Ai[3177,14,4595,0,1214,0,0]Ai[3177,14,4595,0,1216,0,0]Ai[3177,14,4595,0,4827,0,0]Ah[476,12,1739,0,3113,0,0]Ah[476,12,1739,0,3106,0,0]Al[3177,12,1740,1740,3114,0,0]Al[3177,12,1740,1740,3107,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5005,0,0]Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]Ab[2035,3,0,0,0,0,0]:6Aj[476,13,477,3742,3300,0,0]Aj[476,13,477,1124,2330,0,0]Al[3177,14,3178,1802,5159,0,0]Ai[3177,14,4892,0,4958,0,0]Ah[3177,14,4595,0,515,0,0]Ai[3177,14,4595,0,1214,0,0]Ai[3177,14,4595,0,4827,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]Ak[1226,14,1227,1227,142,0,0]Al[1226,14,1417,1417,1219,0,0]Al[3177,13,3178,3743,3301,0,0]Ah[476,12,1739,0,3113,0,0]Al[3177,12,1740,1740,3114,0,0]Am[1226,13,1227,1227,142,129,0]An[1226,13,1227,1227,4075,129,0]An[1226,13,1227,1227,4051,129,0]An[1226,13,1417,1417,4083,129,0]An[1226,13,1417,1417,1219,129,0]An[1226,13,1417,1417,4486,129,0]Ak[535,13,536,536,4052,129,0]An[4089,13,4090,4090,5160,129,0]Al[476,13,477,3742,4611,129,0]Al[476,13,477,3742,2329,129,0]Ai[476,13,477,0,4338,129,0]Al[476,13,477,4270,5062,129,0]Al[476,13,477,1124,2330,129,0]Al[476,13,477,1124,4785,129,0]Al[476,13,477,3742,3298,129,0]Al[476,13,477,3742,3300,129,0]Al[476,13,477,3742,1891,129,0]Al[476,13,477,3742,1457,129,0]Al[476,13,477,3742,3081,129,0]Al[476,13,477,3742,2302,129,0]Al[476,13,477,3742,4232,129,0]Al[476,13,477,3742,4239,129,0]Al[476,13,477,3742,5069,129,0]Al[476,13,477,3742,4897,129,0]Al[476,13,477,2359,2314,129,0]Al[476,13,477,2359,4347,129,0]Al[476,13,477,2359,1436,129,0]Al[476,13,477,4270,1456,129,0]Al[476,13,477,4270,3320,129,0]Al[476,13,477,4270,4997,129,0]Al[476,13,477,2391,2318,129,0]Al[476,13,477,2391,3329,129,0]Al[476,13,477,2391,4465,129,0]Ak[476,13,477,1124,519,129,0]Al[476,13,477,1124,4491,129,0]Al[476,13,477,4157,3326,129,0]Al[476,13,477,4157,5005,129,0]Al[476,13,477,4157,4484,129,0]Al[476,13,477,4157,3125,129,0]Al[476,13,477,4157,3328,129,0]Al[476,13,477,4157,4483,129,0]Al[476,13,477,1430,4249,129,0]Al[476,13,477,1167,4078,129,0]Al[476,13,477,4162,3332,129,0]Al[476,13,477,4162,3346,129,0]Al[476,13,477,4162,4248,129,0]Al[476,13,477,4162,1905,129,0]Ai[476,13,477,0,3323,129,0]Ai[476,13,477,0,4378,129,0]Ai[476,13,477,0,4795,129,0]Ai[476,13,477,0,4603,129,0]Ai[476,13,477,0,4222,129,0]Ai[476,13,477,0,4474,129,0]Ai[476,13,477,0,1482,129,0]Ai[476,13,477,0,5066,129,0]Ai[476,13,477,0,1182,129,0]Ai[476,13,477,0,1465,129,0]Ai[476,13,477,0,3321,129,0]Ai[476,13,477,0,3120,129,0]Ai[476,13,477,0,4951,129,0]Ai[476,13,477,0,3293,129,0]Ai[476,13,477,0,2349,129,0]Ai[476,13,477,0,3306,129,0]Ai[476,13,477,0,3122,129,0]Ai[476,13,477,0,4587,129,0]Ai[476,13,477,0,1915,129,0]Ai[476,13,477,0,4194,129,0]Ai[476,13,477,0,4583,129,0]Ai[476,13,477,0,3116,129,0]Ai[476,13,477,0,4450,129,0]Ai[476,13,477,0,4597,129,0]Ai[476,13,477,0,4606,129,0]Ai[476,13,477,0,4921,129,0]Ai[476,13,477,0,4936,129,0]Ai[476,13,477,0,4064,129,0]Ai[476,13,477,0,4460,129,0]Ai[476,13,477,0,4242,129,0]Ai[476,13,477,0,5123,129,0]Ai[476,13,477,0,4188,129,0]Ai[476,13,477,0,4054,129,0]Ai[476,13,477,0,3103,129,0]Ai[476,13,477,0,4580,129,0]Ai[476,13,477,0,4787,129,0]Ai[476,13,477,0,4200,129,0]Ai[476,13,477,0,4203,129,0]Ai[476,13,477,0,4208,129,0]Ai[476,13,477,0,4956,129,0]Ai[476,13,477,0,3309,129,0]Ai[476,13,477,0,4821,129,0]Ah[476,13,477,0,525,129,0]Ah[476,13,477,0,134,129,0]Ai[476,13,477,0,2336,129,0]Ai[476,13,477,0,2346,129,0]Ai[476,13,3737,0,500,129,0]Aj[476,13,3737,0,3289,129,0]Aj[476,13,3737,0,1186,129,0]Aj[476,13,3737,0,4059,129,0]Aj[476,13,3737,0,1888,129,0]Aj[476,13,3737,0,4366,129,0]Aj[476,13,3737,0,4884,129,0]Aj[476,13,1739,0,1883,129,0]Ai[476,13,1739,0,513,129,0]Aj[476,13,1739,0,5222,129,0]Aj[476,13,1739,0,4057,129,0]Aj[476,13,1739,0,4960,129,0]Aj[476,13,1820,0,3341,129,0]Aj[476,13,1820,0,4349,129,0]Aj[476,13,1820,0,1199,129,0]Aj[476,13,1820,0,4817,129,0]Aj[476,13,1820,0,5060,129,0]Aj[476,13,1820,0,4819,129,0]Am[2413,13,2414,2414,133,129,0]An[2413,13,2414,2414,2305,129,0]An[3177,13,3178,4616,4339,129,0]An[3177,13,3178,3151,3094,129,0]An[3177,13,3178,1150,1445,129,0]An[3177,13,3178,2050,1909,129,0]An[3177,13,3178,2050,3327,129,0]An[3177,13,3178,2050,3333,129,0]An[3177,13,3178,3743,3301,129,0]An[3177,13,3178,1146,3324,129,0]An[3177,13,3178,1737,4379,129,0]An[3177,13,3178,2360,2315,129,0]An[3177,13,3178,2360,4345,129,0]An[3177,13,3178,2360,4796,129,0]An[3177,13,3178,2360,4357,129,0]An[3177,13,3178,1802,5286,129,0]An[3177,13,3178,4387,5254,129,0]An[3177,13,3178,1429,4604,129,0]An[3177,13,3178,1429,4223,129,0]An[3177,13,3178,1429,4475,129,0]An[3177,13,3178,1858,1483,129,0]An[3177,13,3178,1858,5067,129,0]An[3177,13,3178,3142,1183,129,0]An[3177,13,3178,3151,4898,129,0]An[3177,13,3178,1403,1466,129,0]An[3177,13,3178,1403,4238,129,0]An[3177,13,3178,1403,3322,129,0]An[3177,13,3178,1403,3121,129,0]An[3177,13,3178,1403,4896,129,0]An[3177,13,3178,1403,4952,129,0]An[3177,13,3178,1403,3296,129,0]An[3177,13,3178,1419,2350,129,0]An[3177,13,3178,1419,3307,129,0]An[3177,13,3178,1419,3123,129,0]An[3177,13,3178,1419,4588,129,0]An[3177,13,3178,1150,3126,129,0]An[3177,13,3178,1150,4374,129,0]An[3177,13,3178,1155,1916,129,0]An[3177,13,3178,1155,3347,129,0]An[3177,13,3178,1155,4063,129,0]An[3177,13,3178,2050,4082,129,0]An[3177,13,3178,2050,4485,129,0]An[3177,13,3178,2050,4198,129,0]An[3177,13,3178,3743,4584,129,0]An[3177,13,3178,3743,3117,129,0]An[3177,13,3178,3743,4451,129,0]An[3177,13,3178,3743,5155,129,0]An[3177,13,3178,3743,1204,129,0]An[3177,13,3178,1146,4598,129,0]An[3177,13,3178,3279,4607,129,0]An[3177,13,3178,3279,4922,129,0]An[3177,13,3178,3279,4937,129,0]An[3177,13,3178,3279,4065,129,0]An[3177,13,3178,1737,4461,129,0]An[3177,13,3178,1737,4244,129,0]An[3177,13,3178,1737,5124,129,0]An[3177,13,3178,1737,4190,129,0]An[3177,13,3178,1737,4055,129,0]An[3177,13,3178,1393,3104,129,0]An[3177,13,3178,1393,4466,129,0]An[3177,13,3178,1393,3313,129,0]An[3177,13,3178,1393,3336,129,0]An[3177,13,3178,1393,4205,129,0]An[3177,13,3178,1393,4582,129,0]An[3177,13,3178,1393,4789,129,0]An[3177,13,3178,1393,2308,129,0]An[3177,13,3178,2360,4793,129,0]An[3177,13,3178,2360,2319,129,0]An[3177,13,3178,2360,4201,129,0]An[3177,13,3178,2360,4049,129,0]An[3177,13,3178,2360,3330,129,0]An[3177,13,3178,1802,4369,129,0]An[3177,13,3178,1802,4596,129,0]An[3177,13,3178,1802,5159,129,0]An[3177,13,3178,1802,2322,129,0]An[3177,13,3178,1802,4893,129,0]An[3177,13,3178,1831,4586,129,0]An[3177,13,3178,1831,4346,129,0]An[3177,13,3178,1831,4204,129,0]An[3177,13,3178,1831,4209,129,0]Ak[3177,13,3178,0,4489,129,0]Ak[3177,13,3178,0,4957,129,0]An[3177,13,3178,4387,3310,129,0]An[3177,13,3178,4387,5259,129,0]An[3177,13,3178,4992,4822,129,0]Am[3177,13,3178,3178,526,129,0]Am[3177,13,3178,3178,135,129,0]An[3177,13,3178,3178,2337,129,0]An[3177,13,3178,3178,2347,129,0]An[3177,13,3178,3178,3102,129,0]An[3177,13,1735,1735,4380,129,0]An[3177,13,5108,5108,5004,129,0]An[3177,13,5108,5108,1201,129,0]An[3177,13,1740,1740,1884,129,0]Am[3177,13,1740,1740,514,129,0]An[3177,13,1740,1740,5223,129,0]An[3177,13,1740,1740,4058,129,0]An[3177,13,1740,1740,4963,129,0]An[3177,13,1821,1821,3342,129,0]An[3177,13,1821,1821,4350,129,0]Ak[3177,13,1821,0,1200,129,0]An[3177,13,1821,1821,4818,129,0]An[3177,13,1821,1821,5061,129,0]An[3177,13,1821,1821,4820,129,0]Al[3177,13,3738,534,501,129,0]Am[3177,13,3738,534,3290,129,0]An[3177,13,3738,1389,1187,129,0]An[3177,13,3738,1389,4060,129,0]An[3177,13,3738,2413,1889,129,0]An[3177,13,3738,2413,4367,129,0]An[3177,13,3738,3738,4885,129,0]An[3177,13,4853,4853,1202,129,0]An[3177,13,4853,4853,1205,129,0]An[2035,13,2036,2036,3345,129,0]Am[2035,13,2036,431,4490,129,0]An[2035,13,2036,2036,2334,129,0]An[2035,13,2036,2036,2348,129,0]An[2035,13,2036,2036,4210,129,0]An[1125,13,1126,1126,3091,129,0]An[1125,13,1126,1126,4996,129,0]Am[1125,13,1729,1729,143,129,0]An[1125,13,1418,1418,1220,129,0]An[1125,13,1418,1418,4084,129,0]An[1125,13,1418,1418,4592,129,0]An[1125,13,4304,4304,5208,129,0]An[1125,13,4304,4304,5209,129,0]Am[1125,13,1826,1826,144,129,0]Aj[476,13,477,3742,5069,0,0]Aj[476,13,477,1124,4491,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Al[3177,14,3178,1802,5159,0,0]Ai[3177,14,4892,0,4958,0,0]Ah[3177,14,4595,0,515,0,0]Ai[3177,14,4595,0,1214,0,0]Af[476,5,477,3742,0,0,0]Al[1226,15,1227,1227,4051,0,0]Ae[2413,6,2414,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1393,0,0,0]Aj[476,15,477,3742,4897,0,0]Al[3177,15,3178,3151,4898,0,0]Af[476,5,477,2359,0,0,0]Ah[3177,5,3178,2360,0,0,0]Al[3177,15,3178,2050,4082,0,0]Af[476,5,477,2391,0,0,0]2Ah[3177,6,3178,1802,0,0,0]Ag[476,19,477,0,1482,0,0]Al[3177,19,3178,1858,1483,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]=Ah[476,12,1739,0,4243,0,0]>Ak[476,13,1820,0,4819,4243,0]>Al[3177,12,1740,1740,4245,0,0]>Ao[3177,13,1821,1821,4820,4245,0]Ao[1125,13,4304,4304,5209,4245,0]An[2413,13,2414,2414,133,4066,0]Ao[2413,13,2414,2414,2305,4066,0]Ag[476,14,477,0,3122,0,0]Ag[476,14,477,0,4587,0,0]Al[3177,14,3178,1419,3123,0,0]Al[3177,14,3178,1419,4588,0,0]Ag[476,13,477,0,4242,0,0]Al[3177,13,3178,1737,4244,0,0]Aj[476,13,477,2042,4448,0,0]0Ak[2035,13,2036,431,4490,0,0]Al[3177,13,3178,3743,3301,0,0]Al[1125,13,1418,1418,4592,0,0]Ae[1125,2,1126,0,0,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2319,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]6Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]32Ak[1226,14,1227,1227,142,0,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Al[2035,14,2036,2036,2348,0,0]Ah[476,14,3737,0,4884,0,0]Al[3177,14,3738,3738,4885,0,0]Al[3177,13,3178,2050,1909,0,0]Al[3177,13,3178,4387,5254,0,0]Al[3177,13,3178,4387,5259,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]>=Al[1226,14,1417,1417,1219,0,0]Ai[535,14,536,536,4052,0,0]Ah[476,13,1820,0,4817,0,0]Ah[476,13,1820,0,4819,0,0]Al[3177,13,1821,1821,4818,0,0]Al[3177,13,1821,1821,4820,0,0]76Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Af[476,5,477,4616,0,0,0]Ah[3177,5,3178,4616,0,0,0]Ag[476,15,477,0,4583,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,3743,4584,0,0]Al[3177,15,3178,2360,4201,0,0]Ah[3177,6,3178,2360,0,0,0]Ah[3177,5,3178,1831,0,0,0]Af[476,5,477,2359,0,0,0]Aj[476,15,477,4157,4483,0,0]Ag[476,5,1820,1821,0,0,0]Ae[3177,5,1821,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Ah[3177,5,3178,2360,0,0,0]Al[3177,15,3178,1802,4893,0,0]?=5454Al[3177,15,3178,2360,4345,0,0]Ag[476,5,3737,2413,0,0,0]Ah[3177,5,3738,2413,0,0,0]Ah[3177,5,3178,1802,0,0,0]98Ah[3177,6,3178,1150,0,0,0]:9Af[476,5,477,1737,0,0,0]Ah[3177,5,3178,1737,0,0,0]Ae[3177,5,1735,0,0,0,0]Al[3177,13,3178,3743,3301,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Al[1125,14,1126,1126,3091,0,0]Ae[3177,2,3178,0,0,0,0]Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Aj[476,12,477,2042,4448,0,0]Ab[4390,3,0,0,0,0,0]Ak[1226,14,1227,1227,142,0,0]Al[1226,14,1417,1417,4083,0,0]98Aj[476,13,477,2391,3329,0,0]Al[3177,13,3178,2360,3330,0,0]Ag[476,13,477,0,4921,0,0]Al[3177,13,3178,3279,4922,0,0];==;:Ak[1226,14,1227,1227,142,0,0]21Al[1125,14,1126,1126,3091,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5005,0,0]Al[3177,13,3178,2050,3327,0,0]Aj[476,13,477,3742,3298,0,0]Aj[476,13,477,2391,2318,0,0]Ai[476,13,477,1124,519,0,0]Al[3177,13,3178,2360,2319,0,0]<;Ag[476,13,477,0,1482,0,0]Ag[476,13,477,0,1465,0,0]Al[3177,13,3178,1858,1483,0,0]Al[3177,13,3178,1403,1466,0,0]20Ae[1226,7,1417,0,0,0,0]?>Al[1226,14,1417,1417,1219,0,0]Ao[1125,13,1126,1126,4996,3131,0]Ag[476,15,477,0,3103,0,0]Af[476,5,477,1393,0,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1393,0,0,0]Af[476,6,477,3743,0,0,0]Ah[3177,6,3178,3743,0,0,0]Al[3177,15,3178,2360,4345,0,0]Ah[3177,5,3178,1831,0,0,0]Af[476,5,477,1419,0,0,0]Ah[3177,5,3178,1419,0,0,0]97Ae[1125,5,1418,0,0,0,0]:8Ah[3177,6,3178,1802,0,0,0]Af[476,5,477,1146,0,0,0]Ah[3177,5,3178,1146,0,0,0]Al[3177,15,3178,1403,4896,0,0]Af[476,5,477,1429,0,0,0]Ah[3177,5,3178,1429,0,0,0]Af[476,5,477,3279,0,0,0]Ah[3177,5,3178,3279,0,0,0]Ag[476,15,477,0,4583,0,0]Al[3177,15,3178,3743,4584,0,0]Af[476,5,477,3742,0,0,0]Aj[476,15,477,4157,3125,0,0]Aj[476,15,477,4157,3328,0,0]Aj[476,15,477,4162,3346,0,0]Aj[476,15,477,4162,4248,0,0]An[1226,13,1227,1227,142,4344,0]Ao[1226,13,1227,1227,4075,4344,0]Ao[1226,13,1227,1227,4051,4344,0]Am[476,13,477,3742,3300,4344,0]Am[476,13,477,3742,5069,4344,0]Am[476,13,477,3742,4897,4344,0]Am[476,13,477,2359,2314,4344,0]Am[476,13,477,2359,4347,4344,0]Am[476,13,477,4270,1456,4344,0]Al[476,13,477,1124,519,4344,0]Am[476,13,477,1124,4491,4344,0]Am[476,13,477,4157,4484,4344,0]Am[476,13,477,4157,3125,4344,0]Am[476,13,477,4157,3328,4344,0]Am[476,13,477,4157,4483,4344,0]Am[476,13,477,4162,3346,4344,0]Am[476,13,477,4162,4248,4344,0]Aj[476,13,477,0,1482,4344,0]Aj[476,13,477,0,5066,4344,0]Aj[476,13,477,0,1465,4344,0]Aj[476,13,477,0,3321,4344,0]Aj[476,13,477,0,3120,4344,0]Aj[476,13,477,0,4951,4344,0]Aj[476,13,477,0,3293,4344,0]Aj[476,13,477,0,2349,4344,0]Aj[476,13,477,0,3306,4344,0]Aj[476,13,477,0,3122,4344,0]Aj[476,13,477,0,4587,4344,0]Aj[476,13,477,0,1915,4344,0]Aj[476,13,477,0,4194,4344,0]Aj[476,13,477,0,4583,4344,0]Aj[476,13,477,0,3116,4344,0]Aj[476,13,477,0,4450,4344,0]Aj[476,13,477,0,4606,4344,0]Aj[476,13,477,0,4921,4344,0]Aj[476,13,477,0,4936,4344,0]Aj[476,13,477,0,4064,4344,0]Aj[476,13,477,0,4460,4344,0]Aj[476,13,477,0,4242,4344,0]Aj[476,13,477,0,5123,4344,0]Aj[476,13,477,0,4188,4344,0]Aj[476,13,477,0,4054,4344,0]Aj[476,13,477,0,3103,4344,0]Aj[476,13,477,0,4580,4344,0]Aj[476,13,477,0,4787,4344,0]Aj[476,13,477,0,4200,4344,0]Aj[476,13,477,0,4203,4344,0]Aj[476,13,477,0,4208,4344,0]Aj[476,13,477,0,4956,4344,0]Aj[476,13,477,0,3309,4344,0]Ai[476,13,477,0,525,4344,0]Ai[476,13,477,0,134,4344,0]Aj[476,13,477,0,2336,4344,0]Aj[476,13,3737,0,500,4344,0]Ak[476,13,3737,0,3289,4344,0]Ak[476,13,3737,0,1186,4344,0]Ak[476,13,3737,0,4059,4344,0]Ak[476,13,3737,0,1888,4344,0]Ak[476,13,3737,0,4366,4344,0]Ak[476,13,1820,0,1199,4344,0]Ak[476,13,1820,0,4817,4344,0]Ak[476,13,1820,0,5060,4344,0]Ak[476,13,1820,0,4819,4344,0]Ao[3177,13,3178,1858,1483,4344,0]Ao[3177,13,3178,1858,5067,4344,0]Ao[3177,13,3178,3151,4898,4344,0]Ao[3177,13,3178,1403,1466,4344,0]Ao[3177,13,3178,1403,4238,4344,0]Ao[3177,13,3178,1403,3322,4344,0]Ao[3177,13,3178,1403,3121,4344,0]Ao[3177,13,3178,1403,4896,4344,0]Ao[3177,13,3178,1403,4952,4344,0]Ao[3177,13,3178,1403,3296,4344,0]Ao[3177,13,3178,1419,2350,4344,0]Ao[3177,13,3178,1419,3307,4344,0]Ao[3177,13,3178,1419,3123,4344,0]Ao[3177,13,3178,1419,4588,4344,0]Ao[3177,13,3178,1150,3126,4344,0]Ao[3177,13,3178,1150,4374,4344,0]Ao[3177,13,3178,1155,1916,4344,0]Ao[3177,13,3178,1155,3347,4344,0]Ao[3177,13,3178,1155,4063,4344,0]Ao[3177,13,3178,2050,4485,4344,0]Ao[3177,13,3178,2050,4198,4344,0]Ao[3177,13,3178,3743,4584,4344,0]Ao[3177,13,3178,3743,3117,4344,0]Ao[3177,13,3178,3743,4451,4344,0]Ao[3177,13,3178,3743,5155,4344,0]Ao[3177,13,3178,3279,4607,4344,0]Ao[3177,13,3178,3279,4922,4344,0]Ao[3177,13,3178,3279,4937,4344,0]Ao[3177,13,3178,3279,4065,4344,0]Ao[3177,13,3178,1737,4461,4344,0]Ao[3177,13,3178,1737,4244,4344,0]Ao[3177,13,3178,1737,5124,4344,0]Ao[3177,13,3178,1737,4190,4344,0]Ao[3177,13,3178,1737,4055,4344,0]Ao[3177,13,3178,1393,3104,4344,0]Ao[3177,13,3178,1393,3313,4344,0]Ao[3177,13,3178,1393,3336,4344,0]Ao[3177,13,3178,1393,4205,4344,0]Ao[3177,13,3178,1393,4582,4344,0]Ao[3177,13,3178,1393,4789,4344,0]Ao[3177,13,3178,1393,2308,4344,0]Ao[3177,13,3178,2360,4793,4344,0]Ao[3177,13,3178,2360,4201,4344,0]Ao[3177,13,3178,1802,4596,4344,0]Ao[3177,13,3178,1802,5159,4344,0]Ao[3177,13,3178,1802,2322,4344,0]Ao[3177,13,3178,1802,4893,4344,0]Ao[3177,13,3178,1831,4204,4344,0]Ao[3177,13,3178,1831,4209,4344,0]Al[3177,13,3178,0,4489,4344,0]Al[3177,13,3178,0,4957,4344,0]Ao[3177,13,3178,4387,3310,4344,0]Ao[3177,13,3178,4387,5259,4344,0]An[3177,13,3178,3178,526,4344,0]An[3177,13,3178,3178,135,4344,0]Ao[3177,13,3178,3178,2337,4344,0]Ao[3177,13,3178,3178,3102,4344,0]Ao[3177,13,1735,1735,4380,4344,0]Ao[3177,13,5108,5108,5004,4344,0]Ao[3177,13,5108,5108,1201,4344,0]Al[3177,13,1821,0,1200,4344,0]Ao[3177,13,1821,1821,4818,4344,0]Ao[3177,13,1821,1821,5061,4344,0]Ao[3177,13,1821,1821,4820,4344,0]Am[3177,13,3738,534,501,4344,0]An[3177,13,3738,534,3290,4344,0]Ao[3177,13,3738,1389,1187,4344,0]Ao[3177,13,3738,1389,4060,4344,0]Ao[3177,13,3738,2413,1889,4344,0]Ao[3177,13,3738,2413,4367,4344,0]Ao[3177,13,4853,4853,1205,4344,0]Ao[2035,13,2036,2036,2334,4344,0]Ao[2035,13,2036,2036,2348,4344,0]Ao[2035,13,2036,2036,4210,4344,0]Ao[1125,13,1126,1126,4996,4344,0]Ao[1125,13,1418,1418,4592,4344,0]Ao[1125,13,4304,4304,5208,4344,0]Ao[1125,13,4304,4304,5209,4344,0]Af[476,7,477,2042,0,0,0]Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Ah[476,12,1739,0,3113,0,0]Al[3177,12,1740,1740,3114,0,0]Al[2035,14,2036,2036,2334,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]10Ae[1125,7,1126,0,0,0,0]Aj[476,13,477,2359,2314,0,0]Ae[4390,7,4391,0,0,0,0]Ae[1226,7,1227,0,0,0,0]Al[3177,13,3178,3743,3301,0,0]Aj[476,13,477,3742,3300,0,0]1Al[3177,13,3178,2050,4485,0,0]Al[1226,13,1417,1417,1219,0,0]Al[1226,14,1417,1417,4083,0,0]Aj[476,12,477,2042,1900,0,0]Am[476,13,477,1430,4249,1900,0]Am[476,13,477,1167,4078,1900,0]Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Af[476,5,477,1124,0,0,0]Ag[476,15,477,0,3103,0,0]Af[476,5,477,1393,0,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1393,0,0,0]Ag[476,15,477,0,4583,0,0]Al[3177,15,3178,3743,4584,0,0]Ah[3177,5,3178,2360,0,0,0]Al[3177,15,3178,3743,1204,0,0]Af[476,5,477,2360,0,0,0]2Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,2360,4201,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]32Ag[476,15,477,0,3116,0,0]Al[3177,15,3178,3743,3117,0,0]Ag[476,15,477,0,3103,0,0]?0?0?43Ag[476,5,1820,1821,0,0,0]Ae[3177,5,1821,0,0,0,0]10Af[476,5,477,4992,0,0,0]Ah[3177,5,3178,4992,0,0,0]Al[3177,15,4853,4853,1202,0,0]7Al[3177,15,3178,1403,4896,0,0]7Al[3177,15,3178,1802,4596,0,0]Ag[476,12,477,0,2342,0,0]Aj[476,13,477,0,4338,2342,0]Aj[476,13,477,0,4222,2342,0]Al[3177,12,3178,1429,2343,0,0]Ao[3177,13,3178,4616,4339,2343,0]Ao[3177,13,3178,1429,4223,2343,0]Ae[4089,7,4090,0,0,0,0]Aj[476,13,477,3742,3300,0,0]Al[3177,13,3178,3743,3301,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]32An[1226,13,1227,1227,142,4462,0]An[2413,13,2414,2414,133,4462,0]Ao[2413,13,2414,2414,2305,4462,0]Ao[1125,13,1126,1126,3091,4462,0]An[1125,13,1729,1729,143,4462,0]An[1125,13,1826,1826,144,4462,0]Ak[2035,13,2036,431,4490,0,0]Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]:9Ae[3177,2,3178,0,0,0,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,2360,2315,0,0]?>43Ae[4390,7,4391,0,0,0,0]6Al[1125,14,1126,1126,3091,0,0]70Ae[1226,7,1227,0,0,0,0]Ag[476,13,477,0,4242,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4244,0,0]Al[3177,13,3178,1737,4190,0,0]Ag[476,14,477,0,4242,0,0]Al[3177,14,3178,1737,4244,0,0]53Aj[476,13,477,4162,3332,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Ag[476,15,477,0,4583,0,0]Al[3177,15,3178,1403,4896,0,0]Al[3177,15,3178,3743,4584,0,0]Ah[476,10,3737,3738,0,0,0]Af[3177,10,3738,0,0,0,0]Ag[476,5,3737,3738,0,0,0]Ae[3177,5,3738,0,0,0,0]Ah[476,10,1739,1740,0,0,0]Af[3177,10,1740,0,0,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,2360,4201,0,0]Ag[476,10,477,3743,0,0,0]Ai[3177,10,3178,3743,0,0,0]Ah[3177,6,3178,1802,0,0,0]Ah[3177,6,3178,1403,0,0,0]Af[476,6,477,3742,0,0,0]Ah[3177,6,3178,3151,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]10Aj[476,15,477,3742,4897,0,0]Al[3177,15,3178,3151,4898,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,14,3178,1419,3123,0,0]Ah[476,14,3737,0,4884,0,0]Al[3177,14,3738,3738,4885,0,0]Aj[476,13,477,3742,3300,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]10Al[3177,13,3178,3151,3094,0,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,2360,2315,0,0]Ab[4916,3,0,0,0,0,0]Ao[1125,13,1126,1126,4996,3131,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Af[476,5,477,3279,0,0,0]Ah[3177,5,3178,3279,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]54Ai[3177,10,3178,1802,0,0,0]Al[3177,15,3178,3743,1204,0,0]7600Al[3177,15,3178,1150,4374,0,0]4365Al[3177,15,4853,4853,1202,0,0]Ae[1125,9,1126,0,0,0,0]:9Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]<;<;Af[476,6,477,1403,0,0,0]Ah[3177,6,3178,1403,0,0,0]32Al[1226,15,1227,1227,4075,0,0]Ac[476,5,477,0,0,0,0]Ae[3177,5,3178,0,0,0,0]Ag[476,15,477,0,4200,0,0]Ag[476,5,1739,1740,0,0,0]Al[3177,15,3178,2360,4201,0,0]Al[3177,15,3178,1802,4893,0,0]Ae[3177,5,1740,0,0,0,0]An[1226,13,1227,1227,142,4452,0]An[2413,13,2414,2414,133,4452,0]Ao[1125,13,1126,1126,3091,4452,0]An[1125,13,1729,1729,143,4452,0]An[1125,13,1826,1826,144,4452,0]Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]Ag[476,13,477,0,1482,0,0]Al[3177,13,3178,1858,1483,0,0]Aj[476,14,477,2359,4347,0,0]Aj[476,13,477,3742,5069,0,0]Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Ag[476,13,477,0,4338,0,0]Al[3177,13,3178,4616,4339,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]7Al[3177,13,3178,3743,3301,0,0]Aj[476,13,477,3742,3300,0,0]Ah[476,13,1820,0,4817,0,0]Ah[476,13,1820,0,4819,0,0]Al[3177,13,1821,1821,4818,0,0]Al[3177,13,1821,1821,4820,0,0]45;:Ao[4089,13,4090,4090,5160,4950,0]Ag[476,13,477,0,4597,0,0]Al[3177,13,3178,1146,4598,0,0]Ae[1125,6,1126,0,0,0,0]Af[476,5,477,4270,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]10Ag[476,15,477,0,3116,0,0]Al[3177,15,3178,3743,3117,0,0]Ae[3177,5,5108,0,0,0,0]Af[476,5,477,4157,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Al[3177,15,4853,4853,1202,0,0]Aj[476,14,477,2359,4347,0,0]Ai[476,13,477,0,525,3083,0]Ai[476,13,477,0,134,3083,0]An[3177,13,3178,3178,526,3083,0]An[3177,13,3178,3178,135,3083,0]Ao[2413,13,2414,2414,2305,3337,0]Ag[476,13,477,0,4936,0,0]Al[3177,13,3178,3279,4937,0,0]Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Aj[476,13,477,3742,3300,0,0]Ag[476,12,477,0,4890,0,0]Al[3177,12,3178,3743,4891,0,0]Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,14,3178,1419,3123,0,0]Ah[476,12,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,12,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Aj[476,14,477,2359,4347,0,0]Al[3177,13,3178,2050,1909,0,0]Ah[3177,2,4385,4161,0,0,0]Ae[1226,7,1227,0,0,0,0]==Ai[476,13,477,1124,519,0,0]Ak[2035,13,2036,431,4490,0,0]032Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Ae[3177,2,3178,0,0,0,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Ag[476,10,477,4387,0,0,0]Ai[3177,10,3178,4387,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,2360,4201,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Af[476,5,477,1737,0,0,0]Ah[3177,5,3178,1737,0,0,0]Ah[476,12,1739,0,3113,0,0]Al[3177,12,1740,1740,3114,0,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,3743,3301,0,0]Al[3177,13,3178,2360,2315,0,0]Al[3177,13,3178,3178,3102,0,0]Ah[476,13,3737,0,4366,0,0]Al[3177,13,3738,2413,4367,0,0]Aj[476,13,477,2042,3129,0,0]0Aj[476,13,477,3742,3300,0,0]6Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]Al[1125,14,1126,1126,3091,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Al[3177,15,4853,4853,1202,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]10Ag[476,15,477,0,4951,0,0]Ag[476,15,477,0,3116,0,0]Ag[476,15,477,0,4450,0,0]Al[3177,15,3178,1403,4952,0,0]Al[3177,15,3178,3743,3117,0,0]Al[3177,15,3178,3743,4451,0,0]Ah[3177,5,3178,3743,0,0,0]Al[3177,15,3178,1403,4896,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1802,0,0,0]Ae[4089,5,4090,0,0,0,0]Al[1125,13,1126,1126,3091,0,0]Aj[476,13,477,3742,3300,0,0]Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Ah[3177,7,5039,5038,0,0,0]0Al[3177,13,3178,3743,3301,0,0]6Ai[476,13,477,1124,519,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Ao[4089,13,4090,4090,5160,4950,0]0Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]10Ag[476,13,477,0,4921,0,0]Al[3177,13,3178,3279,4922,0,0]Am[1226,13,1227,1227,142,498,0]Am[2413,13,2414,2414,133,498,0]An[1125,13,1126,1126,3091,498,0]Am[1125,13,1729,1729,143,498,0]Am[1125,13,1826,1826,144,498,0]??Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ai[476,13,477,1124,519,0,0]An[1226,13,1227,1227,142,4462,0]An[2413,13,2414,2414,133,4462,0]Ao[2413,13,2414,2414,2305,4462,0]Ao[1125,13,1126,1126,3091,4462,0]An[1125,13,1729,1729,143,4462,0]An[1125,13,1826,1826,144,4462,0]Ag[476,13,477,0,4242,0,0]Al[3177,13,3178,1737,4244,0,0]Ag[476,19,477,0,4956,0,0]Ai[3177,19,3178,0,4957,0,0]Ae[1125,5,4304,0,0,0,0]0Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2319,0,0]Al[3177,13,3178,3743,3301,0,0]Ao[4089,13,4090,4090,5160,4950,0];:Ag[476,5,1739,1740,0,0,0]Ae[3177,5,1740,0,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]?>?>Aj[476,13,477,3742,3300,0,0]6Ag[476,13,477,0,4606,0,0]Al[3177,13,3178,3279,4607,0,0]Ae[4089,7,4090,0,0,0,0]Ae[4390,7,4391,0,0,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]?Al[3177,13,5109,5109,5005,0,0]Af[476,5,477,2359,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Al[1226,15,1227,1227,4051,0,0]0Ag[476,15,477,0,3321,0,0]Al[3177,15,3178,1403,3322,0,0]Ah[3177,5,3178,1150,0,0,0]Af[476,15,477,0,525,0,0]Al[2413,15,2414,2414,2305,0,0]Ak[3177,15,3178,3178,526,0,0]Al[3177,15,4854,4854,1202,0,0]98Af[476,5,477,4270,0,0,0]Af[476,5,477,3742,0,0,0]Ag[476,15,477,0,3120,0,0]Al[3177,15,3178,1403,3121,0,0]Al[3177,15,3178,2050,4082,0,0]Af[476,5,477,1403,0,0,0]Ah[3177,5,3178,1403,0,0,0]Ae[3177,8,1735,0,0,0,0];:9Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,3743,1204,0,0]Al[3177,15,3178,1393,3104,0,0]Af[476,5,477,1858,0,0,0]Ah[3177,5,3178,1858,0,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2050,1909,0,0]Al[3177,13,3178,2360,2315,0,0]An[1226,13,1227,1227,142,1443,0]Ao[1226,13,1227,1227,4075,1443,0]Ao[1226,13,1227,1227,4051,1443,0]Ao[1226,13,1417,1417,4083,1443,0]Ao[1226,13,1417,1417,1219,1443,0]Ao[1226,13,1417,1417,4486,1443,0]Al[535,13,536,536,4052,1443,0]Ao[4089,13,4090,4090,5161,1443,0]Am[476,13,477,3742,4612,1443,0]Am[476,13,477,3742,2329,1443,0]Aj[476,13,477,0,4338,1443,0]Am[476,13,477,4270,5063,1443,0]Am[476,13,477,1124,2330,1443,0]Am[476,13,477,1124,4786,1443,0]Am[476,13,477,3742,3298,1443,0]Am[476,13,477,3742,3300,1443,0]Am[476,13,477,3742,1891,1443,0]Am[476,13,477,3742,1457,1443,0]Am[476,13,477,3742,3081,1443,0]Am[476,13,477,3742,2302,1443,0]Am[476,13,477,3742,4232,1443,0]Am[476,13,477,3742,4239,1443,0]Am[476,13,477,3742,5070,1443,0]Am[476,13,477,3742,4898,1443,0]Am[476,13,477,2359,2314,1443,0]Am[476,13,477,2359,4347,1443,0]Am[476,13,477,2359,1436,1443,0]Am[476,13,477,4270,1456,1443,0]Am[476,13,477,4270,3320,1443,0]Am[476,13,477,4270,4998,1443,0]Am[476,13,477,2391,2318,1443,0]Am[476,13,477,2391,3329,1443,0]Am[476,13,477,2391,4465,1443,0]Al[476,13,477,1124,519,1443,0]Am[476,13,477,1124,4491,1443,0]Am[476,13,477,4157,3326,1443,0]Am[476,13,477,4157,5006,1443,0]Am[476,13,477,4157,4484,1443,0]Am[476,13,477,4157,3125,1443,0]Am[476,13,477,4157,3328,1443,0]Am[476,13,477,4157,4483,1443,0]Am[476,13,477,1430,4249,1443,0]Am[476,13,477,1167,4078,1443,0]Am[476,13,477,4162,3332,1443,0]Am[476,13,477,4162,3346,1443,0]Am[476,13,477,4162,4248,1443,0]Am[476,13,477,4162,1905,1443,0]Aj[476,13,477,0,3323,1443,0]Aj[476,13,477,0,4378,1443,0]Aj[476,13,477,0,4796,1443,0]Aj[476,13,477,0,4604,1443,0]Aj[476,13,477,0,4222,1443,0]Aj[476,13,477,0,4474,1443,0]Aj[476,13,477,0,1482,1443,0]Aj[476,13,477,0,5067,1443,0]Aj[476,13,477,0,1182,1443,0]Aj[476,13,477,0,1465,1443,0]Aj[476,13,477,0,3321,1443,0]Aj[476,13,477,0,3120,1443,0]Aj[476,13,477,0,4952,1443,0]Aj[476,13,477,0,3293,1443,0]Aj[476,13,477,0,2349,1443,0]Aj[476,13,477,0,3306,1443,0]Aj[476,13,477,0,3122,1443,0]Aj[476,13,477,0,4588,1443,0]Aj[476,13,477,0,1915,1443,0]Aj[476,13,477,0,4194,1443,0]Aj[476,13,477,0,4584,1443,0]Aj[476,13,477,0,3116,1443,0]Aj[476,13,477,0,4450,1443,0]Aj[476,13,477,0,4598,1443,0]Aj[476,13,477,0,4607,1443,0]Aj[476,13,477,0,4922,1443,0]Aj[476,13,477,0,4937,1443,0]Aj[476,13,477,0,4064,1443,0]Aj[476,13,477,0,4460,1443,0]Aj[476,13,477,0,4242,1443,0]Aj[476,13,477,0,5124,1443,0]Aj[476,13,477,0,4188,1443,0]Aj[476,13,477,0,4054,1443,0]Aj[476,13,477,0,3103,1443,0]Aj[476,13,477,0,4581,1443,0]Aj[476,13,477,0,4788,1443,0]Aj[476,13,477,0,4200,1443,0]Aj[476,13,477,0,4203,1443,0]Aj[476,13,477,0,4208,1443,0]Aj[476,13,477,0,4957,1443,0]Aj[476,13,477,0,3309,1443,0]Aj[476,13,477,0,4822,1443,0]Ai[476,13,477,0,525,1443,0]Ai[476,13,477,0,134,1443,0]Aj[476,13,477,0,2336,1443,0]Aj[476,13,477,0,2346,1443,0]Aj[476,13,3737,0,500,1443,0]Ak[476,13,3737,0,3289,1443,0]Ak[476,13,3737,0,1186,1443,0]Ak[476,13,3737,0,4059,1443,0]Ak[476,13,3737,0,1888,1443,0]Ak[476,13,3737,0,4366,1443,0]Ak[476,13,3737,0,4885,1443,0]Ak[476,13,1739,0,1883,1443,0]Aj[476,13,1739,0,513,1443,0]Ak[476,13,1739,0,5223,1443,0]Ak[476,13,1739,0,4057,1443,0]Ak[476,13,1739,0,4961,1443,0]Ak[476,13,1820,0,3341,1443,0]Ak[476,13,1820,0,4349,1443,0]Ak[476,13,1820,0,1199,1443,0]Ak[476,13,1820,0,4818,1443,0]Ak[476,13,1820,0,5061,1443,0]Ak[476,13,1820,0,4820,1443,0]An[2413,13,2414,2414,133,1443,0]Ao[2413,13,2414,2414,2305,1443,0]Ao[3177,13,3178,4617,4339,1443,0]Ao[3177,13,3178,3151,3094,1443,0]Ao[3177,13,3178,1150,1445,1443,0]Ao[3177,13,3178,2050,1909,1443,0]Ao[3177,13,3178,2050,3327,1443,0]Ao[3177,13,3178,2050,3333,1443,0]Ao[3177,13,3178,3743,3301,1443,0]Ao[3177,13,3178,1146,3324,1443,0]Ao[3177,13,3178,1737,4379,1443,0]Ao[3177,13,3178,2360,2315,1443,0]Ao[3177,13,3178,2360,4345,1443,0]Ao[3177,13,3178,2360,4797,1443,0]Ao[3177,13,3178,2360,4357,1443,0]Ao[3177,13,3178,1802,5287,1443,0]Ao[3177,13,3178,4387,5255,1443,0]Ao[3177,13,3178,1429,4605,1443,0]Ao[3177,13,3178,1429,4223,1443,0]Ao[3177,13,3178,1429,4475,1443,0]Ao[3177,13,3178,1858,1483,1443,0]Ao[3177,13,3178,1858,5068,1443,0]Ao[3177,13,3178,3142,1183,1443,0]Ao[3177,13,3178,3151,4899,1443,0]Ao[3177,13,3178,1403,1466,1443,0]Ao[3177,13,3178,1403,4238,1443,0]Ao[3177,13,3178,1403,3322,1443,0]Ao[3177,13,3178,1403,3121,1443,0]Ao[3177,13,3178,1403,4897,1443,0]Ao[3177,13,3178,1403,4953,1443,0]Ao[3177,13,3178,1403,3296,1443,0]Ao[3177,13,3178,1419,2350,1443,0]Ao[3177,13,3178,1419,3307,1443,0]Ao[3177,13,3178,1419,3123,1443,0]Ao[3177,13,3178,1419,4589,1443,0]Ao[3177,13,3178,1150,3126,1443,0]Ao[3177,13,3178,1150,4374,1443,0]Ao[3177,13,3178,1155,1916,1443,0]Ao[3177,13,3178,1155,3347,1443,0]Ao[3177,13,3178,1155,4063,1443,0]Ao[3177,13,3178,2050,4082,1443,0]Ao[3177,13,3178,2050,4485,1443,0]Ao[3177,13,3178,2050,4198,1443,0]Ao[3177,13,3178,3743,4585,1443,0]Ao[3177,13,3178,3743,3117,1443,0]Ao[3177,13,3178,3743,4451,1443,0]Ao[3177,13,3178,3743,5156,1443,0]Ao[3177,13,3178,3743,1204,1443,0]Ao[3177,13,3178,1146,4599,1443,0]Ao[3177,13,3178,3279,4608,1443,0]Ao[3177,13,3178,3279,4923,1443,0]Ao[3177,13,3178,3279,4938,1443,0]Ao[3177,13,3178,3279,4065,1443,0]Ao[3177,13,3178,1737,4461,1443,0]Ao[3177,13,3178,1737,4244,1443,0]Ao[3177,13,3178,1737,5125,1443,0]Ao[3177,13,3178,1737,4190,1443,0]Ao[3177,13,3178,1737,4055,1443,0]Ao[3177,13,3178,1393,3104,1443,0]Ao[3177,13,3178,1393,4466,1443,0]Ao[3177,13,3178,1393,3313,1443,0]Ao[3177,13,3178,1393,3336,1443,0]Ao[3177,13,3178,1393,4205,1443,0]Ao[3177,13,3178,1393,4583,1443,0]Ao[3177,13,3178,1393,4790,1443,0]Ao[3177,13,3178,1393,2308,1443,0]Ao[3177,13,3178,2360,4794,1443,0]Ao[3177,13,3178,2360,2319,1443,0]Ao[3177,13,3178,2360,4201,1443,0]Ao[3177,13,3178,2360,4049,1443,0]Ao[3177,13,3178,2360,3330,1443,0]Ao[3177,13,3178,1802,4369,1443,0]Ao[3177,13,3178,1802,4597,1443,0]Ao[3177,13,3178,1802,5160,1443,0]Ao[3177,13,3178,1802,2322,1443,0]Ao[3177,13,3178,1802,4894,1443,0]Ao[3177,13,3178,1831,4587,1443,0]Ao[3177,13,3178,1831,4346,1443,0]Ao[3177,13,3178,1831,4204,1443,0]Ao[3177,13,3178,1831,4209,1443,0]Al[3177,13,3178,0,4489,1443,0]Al[3177,13,3178,0,4958,1443,0]Ao[3177,13,3178,4387,3310,1443,0]Ao[3177,13,3178,4387,5260,1443,0]Ao[3177,13,3178,4993,4823,1443,0]An[3177,13,3178,3178,526,1443,0]An[3177,13,3178,3178,135,1443,0]Ao[3177,13,3178,3178,2337,1443,0]Ao[3177,13,3178,3178,2347,1443,0]Ao[3177,13,3178,3178,3102,1443,0]Ao[3177,13,1735,1735,4380,1443,0]Ao[3177,13,5109,5109,5005,1443,0]Ao[3177,13,5109,5109,1201,1443,0]Ao[3177,13,1740,1740,1884,1443,0]An[3177,13,1740,1740,514,1443,0]Ao[3177,13,1740,1740,5224,1443,0]Ao[3177,13,1740,1740,4058,1443,0]Ao[3177,13,1740,1740,4964,1443,0]Ao[3177,13,1821,1821,3342,1443,0]Ao[3177,13,1821,1821,4350,1443,0]Al[3177,13,1821,0,1200,1443,0]Ao[3177,13,1821,1821,4819,1443,0]Ao[3177,13,1821,1821,5062,1443,0]Ao[3177,13,1821,1821,4821,1443,0]Am[3177,13,3738,534,501,1443,0]An[3177,13,3738,534,3290,1443,0]Ao[3177,13,3738,1389,1187,1443,0]Ao[3177,13,3738,1389,4060,1443,0]Ao[3177,13,3738,2413,1889,1443,0]Ao[3177,13,3738,2413,4367,1443,0]Ao[3177,13,3738,3738,4886,1443,0]Ao[3177,13,4854,4854,1202,1443,0]Ao[3177,13,4854,4854,1205,1443,0]Ao[2035,13,2036,2036,3345,1443,0]An[2035,13,2036,431,4490,1443,0]Ao[2035,13,2036,2036,2334,1443,0]Ao[2035,13,2036,2036,2348,1443,0]Ao[2035,13,2036,2036,4210,1443,0]Ao[1125,13,1126,1126,3091,1443,0]Ao[1125,13,1126,1126,4997,1443,0]An[1125,13,1729,1729,143,1443,0]Ao[1125,13,1418,1418,1220,1443,0]Ao[1125,13,1418,1418,4084,1443,0]Ao[1125,13,1418,1418,4593,1443,0]Ao[1125,13,4304,4304,5209,1443,0]Ao[1125,13,4304,4304,5210,1443,0]An[1125,13,1826,1826,144,1443,0]Ag[476,14,477,0,1915,0,0]Al[3177,14,3178,1155,1916,0,0]Ak[1226,14,1227,1227,142,0,0]Ac[535,7,536,0,0,0,0]Aj[476,13,477,2359,2314,0,0]Ae[1125,2,1126,0,0,0,0]Ae[4917,7,4918,0,0,0,0]Aj[476,13,477,3742,3300,0,0]Ae[3177,2,3178,0,0,0,0]Al[3177,13,3178,2360,2315,0,0]Af[476,2,477,3178,0,0,0]Ag[476,13,477,0,4957,0,0]Ag[476,14,477,0,3306,0,0]Ag[476,14,477,0,4242,0,0]5Ai[3177,13,3178,0,4958,0,0]Al[3177,14,3178,1419,3307,0,0]Al[3177,14,3178,1737,4244,0,0]Ai[3177,14,3178,0,4489,0,0]Aj[476,13,477,0,1482,3095,0]Aj[476,13,477,0,1465,3095,0]Aj[476,13,477,0,3103,3095,0]Aj[476,13,477,0,4957,3095,0]Aj[476,13,477,0,2336,3095,0]Ao[3177,13,3178,1858,1483,3095,0]Ao[3177,13,3178,1403,1466,3095,0]Ao[3177,13,3178,1393,3104,3095,0]Ao[3177,13,3178,1393,3313,3095,0]Al[3177,13,3178,1802,4597,0,0]Al[3177,13,3178,0,4958,3095,0]Ao[3177,13,3178,3178,2337,3095,0]Al[3177,12,1735,1735,3095,0,0]Al[2035,14,2036,2036,2334,0,0]Aj[476,13,477,0,1482,3100,0]Aj[476,13,477,0,1465,3100,0]Aj[476,13,477,0,3103,3100,0]Aj[476,13,477,0,4957,3100,0]Aj[476,13,477,0,2336,3100,0]Ao[3177,13,3178,1858,1483,3100,0]Ao[3177,13,3178,1403,1466,3100,0]Ao[3177,13,3178,1393,3104,3100,0]Ao[3177,13,3178,1393,3313,3100,0]Ao[3177,13,3178,1393,2308,3100,0]Al[3177,13,3178,0,4958,3100,0]Ao[3177,13,3178,3178,2337,3100,0]Al[3177,12,1735,1735,3100,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]Al[1125,13,1418,1418,4084,0,0]Al[3177,13,3178,2360,2315,0,0]Ag[476,14,1739,0,513,0,0]Ak[3177,14,1740,1740,514,0,0]Aj[476,13,477,2391,2318,0,0]3Ag[476,12,477,0,3343,0,0]Aj[476,13,477,0,4474,3343,0]Aj[476,13,477,0,4822,3343,0]Al[3177,12,3178,1429,3344,0,0]Ao[3177,13,3178,1429,4475,3344,0]Ao[3177,13,3178,4993,4823,3344,0]Al[1125,14,1126,1126,3091,0,0]Ag[476,14,477,0,1182,0,0]Al[3177,14,3178,3142,1183,0,0]Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Ag[476,14,1739,0,513,0,0]Ak[3177,14,1740,1740,514,0,0]Ai[3177,14,4596,0,4828,0,0]Ag[476,14,477,0,4581,0,0]Ag[476,14,477,0,4788,0,0]Ah[476,14,3118,0,3077,0,0]Al[3177,14,3178,1393,4583,0,0]Al[3177,14,3178,1393,4790,0,0]Ai[3177,14,3178,0,4489,0,0]Ai[3177,14,1203,0,4453,0,0]Ai[3177,14,3119,0,3078,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2315,0,0]Ah[476,14,1739,0,1883,0,0]Al[3177,13,3178,3178,3102,0,0]Al[3177,14,1740,1740,1884,0,0]Ac[476,4,477,0,0,0,0]Ag[476,2,1739,1740,0,0,0]Ae[3177,4,3178,0,0,0,0]Ae[3177,2,1740,0,0,0,0]Ac[535,7,536,0,0,0,0]:Ae[1125,2,1126,0,0,0,0]Ae[4917,7,4918,0,0,0,0]Am[476,13,477,3742,4898,1192,0]Am[476,13,477,4157,4484,1192,0]Am[476,13,477,4157,3125,1192,0]Am[476,13,477,4157,3328,1192,0]Am[476,13,477,4157,4483,1192,0]Am[476,13,477,4162,3346,1192,0]Am[476,13,477,4162,4248,1192,0]Aj[476,13,477,0,4584,1192,0]Ao[3177,13,3178,3743,4585,1192,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Al[2035,14,2036,2036,2348,0,0]Ai[476,13,477,1124,519,0,0]Ah[476,14,3118,0,4233,0,0]Ai[3177,14,3119,0,4234,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Al[2035,14,2036,2036,2334,0,0]Ag[476,14,477,0,3122,0,0]Ag[476,14,477,0,4588,0,0]Al[3177,14,3178,1419,3123,0,0]Al[3177,14,3178,1419,4589,0,0]3210Ah[476,12,1739,0,1879,0,0]Al[3177,12,1740,1740,1880,0,0]Ah[476,12,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,12,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Al[3177,15,3178,3151,4899,0,0]Al[3177,15,3178,1150,3126,0,0]Al[3177,15,3178,1155,3347,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Ah[476,10,1739,1740,0,0,0]Af[3177,10,1740,0,0,0,0]Al[3177,15,3178,1802,4597,0,0]Ag[476,5,1739,1740,0,0,0]Ae[3177,5,1740,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ag[476,5,3737,2413,0,0,0]Ah[3177,5,3738,2413,0,0,0]Al[1125,15,1126,1126,4997,0,0]Af[476,5,477,3742,0,0,0]5454Ag[476,10,477,2042,0,0,0];:Aj[476,15,477,4162,3346,0,0]Af[476,5,477,4162,0,0,0]Al[3177,15,3178,1155,3347,0,0]Al[3177,15,3178,1155,4063,0,0]Al[3177,15,3178,2050,4082,0,0]Ah[3177,5,3178,2050,0,0,0]Aj[476,15,477,4157,4484,0,0]Al[3177,15,3178,1393,3313,0,0]Af[476,5,477,1155,0,0,0]Ah[3177,5,3178,1155,0,0,0]Al[3177,15,3178,1802,2322,0,0]Ag[476,12,477,0,5115,0,0]Al[3177,12,3178,4387,5116,0,0]Ao[3177,13,3178,4387,5255,5116,0]Ao[3177,13,3178,4387,5260,5116,0]Ak[1226,14,1227,1227,142,0,0]An[1226,13,1227,1227,142,4452,0]An[2413,13,2414,2414,133,4452,0]Ak[2413,14,2414,2414,133,0,0]Ao[1125,13,1126,1126,3091,4452,0]An[1125,13,1729,1729,143,4452,0]An[1125,13,1826,1826,144,4452,0]Aj[476,13,477,0,1482,3297,0]Aj[476,13,477,0,1465,3297,0]Aj[476,13,477,0,4064,3297,0]Aj[476,13,477,0,4203,3297,0]Ai[476,13,477,0,525,3297,0]Ai[476,13,477,0,134,3297,0]Aj[476,13,477,0,2336,3297,0]Ao[3177,13,3178,1858,1483,3297,0]Ao[3177,13,3178,3151,4899,3297,0]Ao[3177,13,3178,1403,1466,3297,0]Ao[3177,13,3178,1150,3126,3297,0]Ao[3177,13,3178,1150,4374,3297,0]Ao[3177,13,3178,1155,3347,3297,0]Ao[3177,13,3178,3279,4065,3297,0]Ao[3177,13,3178,2360,4794,3297,0]Ao[3177,13,3178,1802,4894,3297,0]Ao[3177,13,3178,1831,4204,3297,0]An[3177,13,3178,3178,526,3297,0]An[3177,13,3178,3178,135,3297,0]Ao[3177,13,3178,3178,2337,3297,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,2360,2315,0,0]Aj[476,13,477,2391,2318,0,0]Ah[476,12,1739,0,3113,0,0]Ah[476,12,1739,0,3106,0,0]Al[3177,13,3178,2360,2319,0,0]Al[3177,12,1740,1740,3114,0,0]Al[3177,12,1740,1740,3107,0,0]Ao[1226,13,1417,1417,4083,1874,0]Ao[1226,13,1417,1417,1219,1874,0]Al[535,13,536,536,4052,1874,0]Aj[476,13,477,0,4338,1874,0]Am[476,13,477,2359,4347,1874,0]Aj[476,13,477,0,1482,1874,0]Aj[476,13,477,0,1465,1874,0]Aj[476,13,477,0,3321,1874,0]Aj[476,13,477,0,3293,1874,0]Aj[476,13,477,0,2349,1874,0]Aj[476,13,477,0,3306,1874,0]Aj[476,13,477,0,3122,1874,0]Aj[476,13,477,0,4588,1874,0]Aj[476,13,477,0,1915,1874,0]Aj[476,13,477,0,4194,1874,0]Aj[476,13,477,0,4607,1874,0]Aj[476,13,477,0,4922,1874,0]Aj[476,13,477,0,4937,1874,0]Aj[476,13,477,0,4064,1874,0]Aj[476,13,477,0,4460,1874,0]Aj[476,13,477,0,5124,1874,0]Aj[476,13,477,0,4822,1874,0]Ak[476,13,3737,0,3289,1874,0]Ak[476,13,3737,0,4059,1874,0]Ak[476,13,3737,0,4366,1874,0]Ak[476,13,3737,0,4885,1874,0]Ao[3177,13,3178,4617,4339,1874,0]Ao[3177,13,3178,4387,5255,1874,0]Ao[3177,13,3178,1858,1483,1874,0]Ao[3177,13,3178,1403,1466,1874,0]Ao[3177,13,3178,1403,3322,1874,0]Ao[3177,13,3178,1403,3296,1874,0]Ao[3177,13,3178,1419,2350,1874,0]Ao[3177,13,3178,1419,3307,1874,0]Ao[3177,13,3178,1419,3123,1874,0]Ao[3177,13,3178,1419,4589,1874,0]Ao[3177,13,3178,1155,1916,1874,0]Ao[3177,13,3178,2050,4485,1874,0]Ao[3177,13,3178,2050,4198,1874,0]Ao[3177,13,3178,3279,4608,1874,0]Ao[3177,13,3178,3279,4923,1874,0]Ao[3177,13,3178,3279,4938,1874,0]Ao[3177,13,3178,3279,4065,1874,0]Ao[3177,13,3178,1737,4461,1874,0]Ao[3177,13,3178,1737,5125,1874,0]Ao[3177,13,3178,4387,5260,1874,0]Ao[3177,13,3178,4993,4823,1874,0]An[3177,13,3738,534,3290,1874,0]Ao[3177,13,3738,1389,4060,1874,0]Ao[3177,13,3738,2413,4367,1874,0]Ao[3177,13,3738,3738,4886,1874,0]Ao[2035,13,2036,2036,2334,1874,0]Ao[1125,13,1418,1418,1220,1874,0]Ao[1125,13,1418,1418,4593,1874,0]Al[3177,13,3178,1831,4346,0,0]Al[3177,13,3178,1802,4369,0,0]Al[3177,13,3178,1802,4597,0,0]Al[3177,14,3178,1802,5160,0,0]Ai[3177,14,4893,0,4959,0,0]Ah[3177,14,4596,0,515,0,0]Ai[3177,14,4596,0,1214,0,0]Ai[3177,14,4596,0,1216,0,0]Ai[3177,14,4596,0,4828,0,0]Ah[476,12,1739,0,3113,0,0]Ah[476,12,1739,0,3106,0,0]Al[3177,12,1740,1740,3114,0,0]Al[3177,12,1740,1740,3107,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5006,0,0]Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]Ab[2035,3,0,0,0,0,0]:6Aj[476,13,477,3742,3300,0,0]Aj[476,13,477,1124,2330,0,0]Al[3177,14,3178,1802,5160,0,0]Ai[3177,14,4893,0,4959,0,0]Ah[3177,14,4596,0,515,0,0]Ai[3177,14,4596,0,1214,0,0]Ai[3177,14,4596,0,4828,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]Ak[1226,14,1227,1227,142,0,0]Al[1226,14,1417,1417,1219,0,0]Al[3177,13,3178,3743,3301,0,0]Ah[476,12,1739,0,3113,0,0]Al[3177,12,1740,1740,3114,0,0]Am[1226,13,1227,1227,142,129,0]An[1226,13,1227,1227,4075,129,0]An[1226,13,1227,1227,4051,129,0]An[1226,13,1417,1417,4083,129,0]An[1226,13,1417,1417,1219,129,0]An[1226,13,1417,1417,4486,129,0]Ak[535,13,536,536,4052,129,0]An[4089,13,4090,4090,5161,129,0]Al[476,13,477,3742,4612,129,0]Al[476,13,477,3742,2329,129,0]Ai[476,13,477,0,4338,129,0]Al[476,13,477,4270,5063,129,0]Al[476,13,477,1124,2330,129,0]Al[476,13,477,1124,4786,129,0]Al[476,13,477,3742,3298,129,0]Al[476,13,477,3742,3300,129,0]Al[476,13,477,3742,1891,129,0]Al[476,13,477,3742,1457,129,0]Al[476,13,477,3742,3081,129,0]Al[476,13,477,3742,2302,129,0]Al[476,13,477,3742,4232,129,0]Al[476,13,477,3742,4239,129,0]Al[476,13,477,3742,5070,129,0]Al[476,13,477,3742,4898,129,0]Al[476,13,477,2359,2314,129,0]Al[476,13,477,2359,4347,129,0]Al[476,13,477,2359,1436,129,0]Al[476,13,477,4270,1456,129,0]Al[476,13,477,4270,3320,129,0]Al[476,13,477,4270,4998,129,0]Al[476,13,477,2391,2318,129,0]Al[476,13,477,2391,3329,129,0]Al[476,13,477,2391,4465,129,0]Ak[476,13,477,1124,519,129,0]Al[476,13,477,1124,4491,129,0]Al[476,13,477,4157,3326,129,0]Al[476,13,477,4157,5006,129,0]Al[476,13,477,4157,4484,129,0]Al[476,13,477,4157,3125,129,0]Al[476,13,477,4157,3328,129,0]Al[476,13,477,4157,4483,129,0]Al[476,13,477,1430,4249,129,0]Al[476,13,477,1167,4078,129,0]Al[476,13,477,4162,3332,129,0]Al[476,13,477,4162,3346,129,0]Al[476,13,477,4162,4248,129,0]Al[476,13,477,4162,1905,129,0]Ai[476,13,477,0,3323,129,0]Ai[476,13,477,0,4378,129,0]Ai[476,13,477,0,4796,129,0]Ai[476,13,477,0,4604,129,0]Ai[476,13,477,0,4222,129,0]Ai[476,13,477,0,4474,129,0]Ai[476,13,477,0,1482,129,0]Ai[476,13,477,0,5067,129,0]Ai[476,13,477,0,1182,129,0]Ai[476,13,477,0,1465,129,0]Ai[476,13,477,0,3321,129,0]Ai[476,13,477,0,3120,129,0]Ai[476,13,477,0,4952,129,0]Ai[476,13,477,0,3293,129,0]Ai[476,13,477,0,2349,129,0]Ai[476,13,477,0,3306,129,0]Ai[476,13,477,0,3122,129,0]Ai[476,13,477,0,4588,129,0]Ai[476,13,477,0,1915,129,0]Ai[476,13,477,0,4194,129,0]Ai[476,13,477,0,4584,129,0]Ai[476,13,477,0,3116,129,0]Ai[476,13,477,0,4450,129,0]Ai[476,13,477,0,4598,129,0]Ai[476,13,477,0,4607,129,0]Ai[476,13,477,0,4922,129,0]Ai[476,13,477,0,4937,129,0]Ai[476,13,477,0,4064,129,0]Ai[476,13,477,0,4460,129,0]Ai[476,13,477,0,4242,129,0]Ai[476,13,477,0,5124,129,0]Ai[476,13,477,0,4188,129,0]Ai[476,13,477,0,4054,129,0]Ai[476,13,477,0,3103,129,0]Ai[476,13,477,0,4581,129,0]Ai[476,13,477,0,4788,129,0]Ai[476,13,477,0,4200,129,0]Ai[476,13,477,0,4203,129,0]Ai[476,13,477,0,4208,129,0]Ai[476,13,477,0,4957,129,0]Ai[476,13,477,0,3309,129,0]Ai[476,13,477,0,4822,129,0]Ah[476,13,477,0,525,129,0]Ah[476,13,477,0,134,129,0]Ai[476,13,477,0,2336,129,0]Ai[476,13,477,0,2346,129,0]Ai[476,13,3737,0,500,129,0]Aj[476,13,3737,0,3289,129,0]Aj[476,13,3737,0,1186,129,0]Aj[476,13,3737,0,4059,129,0]Aj[476,13,3737,0,1888,129,0]Aj[476,13,3737,0,4366,129,0]Aj[476,13,3737,0,4885,129,0]Aj[476,13,1739,0,1883,129,0]Ai[476,13,1739,0,513,129,0]Aj[476,13,1739,0,5223,129,0]Aj[476,13,1739,0,4057,129,0]Aj[476,13,1739,0,4961,129,0]Aj[476,13,1820,0,3341,129,0]Aj[476,13,1820,0,4349,129,0]Aj[476,13,1820,0,1199,129,0]Aj[476,13,1820,0,4818,129,0]Aj[476,13,1820,0,5061,129,0]Aj[476,13,1820,0,4820,129,0]Am[2413,13,2414,2414,133,129,0]An[2413,13,2414,2414,2305,129,0]An[3177,13,3178,4617,4339,129,0]An[3177,13,3178,3151,3094,129,0]An[3177,13,3178,1150,1445,129,0]An[3177,13,3178,2050,1909,129,0]An[3177,13,3178,2050,3327,129,0]An[3177,13,3178,2050,3333,129,0]An[3177,13,3178,3743,3301,129,0]An[3177,13,3178,1146,3324,129,0]An[3177,13,3178,1737,4379,129,0]An[3177,13,3178,2360,2315,129,0]An[3177,13,3178,2360,4345,129,0]An[3177,13,3178,2360,4797,129,0]An[3177,13,3178,2360,4357,129,0]An[3177,13,3178,1802,5287,129,0]An[3177,13,3178,4387,5255,129,0]An[3177,13,3178,1429,4605,129,0]An[3177,13,3178,1429,4223,129,0]An[3177,13,3178,1429,4475,129,0]An[3177,13,3178,1858,1483,129,0]An[3177,13,3178,1858,5068,129,0]An[3177,13,3178,3142,1183,129,0]An[3177,13,3178,3151,4899,129,0]An[3177,13,3178,1403,1466,129,0]An[3177,13,3178,1403,4238,129,0]An[3177,13,3178,1403,3322,129,0]An[3177,13,3178,1403,3121,129,0]An[3177,13,3178,1403,4897,129,0]An[3177,13,3178,1403,4953,129,0]An[3177,13,3178,1403,3296,129,0]An[3177,13,3178,1419,2350,129,0]An[3177,13,3178,1419,3307,129,0]An[3177,13,3178,1419,3123,129,0]An[3177,13,3178,1419,4589,129,0]An[3177,13,3178,1150,3126,129,0]An[3177,13,3178,1150,4374,129,0]An[3177,13,3178,1155,1916,129,0]An[3177,13,3178,1155,3347,129,0]An[3177,13,3178,1155,4063,129,0]An[3177,13,3178,2050,4082,129,0]An[3177,13,3178,2050,4485,129,0]An[3177,13,3178,2050,4198,129,0]An[3177,13,3178,3743,4585,129,0]An[3177,13,3178,3743,3117,129,0]An[3177,13,3178,3743,4451,129,0]An[3177,13,3178,3743,5156,129,0]An[3177,13,3178,3743,1204,129,0]An[3177,13,3178,1146,4599,129,0]An[3177,13,3178,3279,4608,129,0]An[3177,13,3178,3279,4923,129,0]An[3177,13,3178,3279,4938,129,0]An[3177,13,3178,3279,4065,129,0]An[3177,13,3178,1737,4461,129,0]An[3177,13,3178,1737,4244,129,0]An[3177,13,3178,1737,5125,129,0]An[3177,13,3178,1737,4190,129,0]An[3177,13,3178,1737,4055,129,0]An[3177,13,3178,1393,3104,129,0]An[3177,13,3178,1393,4466,129,0]An[3177,13,3178,1393,3313,129,0]An[3177,13,3178,1393,3336,129,0]An[3177,13,3178,1393,4205,129,0]An[3177,13,3178,1393,4583,129,0]An[3177,13,3178,1393,4790,129,0]An[3177,13,3178,1393,2308,129,0]An[3177,13,3178,2360,4794,129,0]An[3177,13,3178,2360,2319,129,0]An[3177,13,3178,2360,4201,129,0]An[3177,13,3178,2360,4049,129,0]An[3177,13,3178,2360,3330,129,0]An[3177,13,3178,1802,4369,129,0]An[3177,13,3178,1802,4597,129,0]An[3177,13,3178,1802,5160,129,0]An[3177,13,3178,1802,2322,129,0]An[3177,13,3178,1802,4894,129,0]An[3177,13,3178,1831,4587,129,0]An[3177,13,3178,1831,4346,129,0]An[3177,13,3178,1831,4204,129,0]An[3177,13,3178,1831,4209,129,0]Ak[3177,13,3178,0,4489,129,0]Ak[3177,13,3178,0,4958,129,0]An[3177,13,3178,4387,3310,129,0]An[3177,13,3178,4387,5260,129,0]An[3177,13,3178,4993,4823,129,0]Am[3177,13,3178,3178,526,129,0]Am[3177,13,3178,3178,135,129,0]An[3177,13,3178,3178,2337,129,0]An[3177,13,3178,3178,2347,129,0]An[3177,13,3178,3178,3102,129,0]An[3177,13,1735,1735,4380,129,0]An[3177,13,5109,5109,5005,129,0]An[3177,13,5109,5109,1201,129,0]An[3177,13,1740,1740,1884,129,0]Am[3177,13,1740,1740,514,129,0]An[3177,13,1740,1740,5224,129,0]An[3177,13,1740,1740,4058,129,0]An[3177,13,1740,1740,4964,129,0]An[3177,13,1821,1821,3342,129,0]An[3177,13,1821,1821,4350,129,0]Ak[3177,13,1821,0,1200,129,0]An[3177,13,1821,1821,4819,129,0]An[3177,13,1821,1821,5062,129,0]An[3177,13,1821,1821,4821,129,0]Al[3177,13,3738,534,501,129,0]Am[3177,13,3738,534,3290,129,0]An[3177,13,3738,1389,1187,129,0]An[3177,13,3738,1389,4060,129,0]An[3177,13,3738,2413,1889,129,0]An[3177,13,3738,2413,4367,129,0]An[3177,13,3738,3738,4886,129,0]An[3177,13,4854,4854,1202,129,0]An[3177,13,4854,4854,1205,129,0]An[2035,13,2036,2036,3345,129,0]Am[2035,13,2036,431,4490,129,0]An[2035,13,2036,2036,2334,129,0]An[2035,13,2036,2036,2348,129,0]An[2035,13,2036,2036,4210,129,0]An[1125,13,1126,1126,3091,129,0]An[1125,13,1126,1126,4997,129,0]Am[1125,13,1729,1729,143,129,0]An[1125,13,1418,1418,1220,129,0]An[1125,13,1418,1418,4084,129,0]An[1125,13,1418,1418,4593,129,0]An[1125,13,4304,4304,5209,129,0]An[1125,13,4304,4304,5210,129,0]Am[1125,13,1826,1826,144,129,0]Aj[476,13,477,3742,5070,0,0]Aj[476,13,477,1124,4491,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Al[3177,14,3178,1802,5160,0,0]Ai[3177,14,4893,0,4959,0,0]Ah[3177,14,4596,0,515,0,0]Ai[3177,14,4596,0,1214,0,0]Af[476,5,477,3742,0,0,0]Al[1226,15,1227,1227,4051,0,0]Ae[2413,6,2414,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1393,0,0,0]Aj[476,15,477,3742,4898,0,0]Al[3177,15,3178,3151,4899,0,0]Af[476,5,477,2359,0,0,0]Ah[3177,5,3178,2360,0,0,0]Al[3177,15,3178,2050,4082,0,0]Af[476,5,477,2391,0,0,0]2Ah[3177,6,3178,1802,0,0,0]Ag[476,19,477,0,1482,0,0]Al[3177,19,3178,1858,1483,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]=Ah[476,12,1739,0,4243,0,0]>Ak[476,13,1820,0,4820,4243,0]>Al[3177,12,1740,1740,4245,0,0]>Ao[3177,13,1821,1821,4821,4245,0]Ao[1125,13,4304,4304,5210,4245,0]An[2413,13,2414,2414,133,4066,0]Ao[2413,13,2414,2414,2305,4066,0]Ag[476,14,477,0,3122,0,0]Ag[476,14,477,0,4588,0,0]Al[3177,14,3178,1419,3123,0,0]Al[3177,14,3178,1419,4589,0,0]Ag[476,13,477,0,4242,0,0]Al[3177,13,3178,1737,4244,0,0]Aj[476,13,477,2042,4448,0,0]0Ak[2035,13,2036,431,4490,0,0]Al[3177,13,3178,3743,3301,0,0]Al[1125,13,1418,1418,4593,0,0]Ae[1125,2,1126,0,0,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2319,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]6Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]32Ak[1226,14,1227,1227,142,0,0]Ag[476,14,477,0,2346,0,0]Al[3177,14,3178,3178,2347,0,0]Al[2035,14,2036,2036,2348,0,0]Ah[476,14,3737,0,4885,0,0]Al[3177,14,3738,3738,4886,0,0]Al[3177,13,3178,2050,1909,0,0]Al[3177,13,3178,4387,5255,0,0]Al[3177,13,3178,4387,5260,0,0]Aj[476,13,477,4162,3332,0,0]Al[3177,13,3178,2050,3333,0,0]>=Al[1226,14,1417,1417,1219,0,0]Ai[535,14,536,536,4052,0,0]Ah[476,13,1820,0,4818,0,0]Ah[476,13,1820,0,4820,0,0]Al[3177,13,1821,1821,4819,0,0]Al[3177,13,1821,1821,4821,0,0]76Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Af[476,5,477,4617,0,0,0]Ah[3177,5,3178,4617,0,0,0]Ag[476,15,477,0,4584,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,3743,4585,0,0]Al[3177,15,3178,2360,4201,0,0]Ah[3177,6,3178,2360,0,0,0]Ah[3177,5,3178,1831,0,0,0]Af[476,5,477,2359,0,0,0]Aj[476,15,477,4157,4483,0,0]Ag[476,5,1820,1821,0,0,0]Ae[3177,5,1821,0,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Ah[3177,5,3178,2360,0,0,0]Al[3177,15,3178,1802,4894,0,0]?=5454Al[3177,15,3178,2360,4345,0,0]Ag[476,5,3737,2413,0,0,0]Ah[3177,5,3738,2413,0,0,0]Ah[3177,5,3178,1802,0,0,0]98Ah[3177,6,3178,1150,0,0,0]:9Af[476,5,477,1737,0,0,0]Ah[3177,5,3178,1737,0,0,0]Ae[3177,5,1735,0,0,0,0]Al[3177,13,3178,3743,3301,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Al[1125,14,1126,1126,3091,0,0]Ae[3177,2,3178,0,0,0,0]Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Aj[476,12,477,2042,4448,0,0]Ab[4390,3,0,0,0,0,0]Ak[1226,14,1227,1227,142,0,0]Al[1226,14,1417,1417,4083,0,0]98Aj[476,13,477,2391,3329,0,0]Al[3177,13,3178,2360,3330,0,0]Ag[476,13,477,0,4922,0,0]Al[3177,13,3178,3279,4923,0,0];==;:Ak[1226,14,1227,1227,142,0,0]21Al[1125,14,1126,1126,3091,0,0]Aj[476,13,477,4157,3326,0,0]Aj[476,13,477,4157,5006,0,0]Al[3177,13,3178,2050,3327,0,0]Aj[476,13,477,3742,3298,0,0]Aj[476,13,477,3742,3300,0,0]Aj[476,13,477,2391,2318,0,0]Ai[476,13,477,1124,519,0,0]Al[3177,13,3178,2360,2319,0,0]=43Ae[4390,7,4391,0,0,0,0]6Al[1125,14,1126,1126,3091,0,0]70Ae[1226,7,1227,0,0,0,0]Ag[476,13,477,0,4242,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4244,0,0]Al[3177,13,3178,1737,4190,0,0]Ag[476,14,477,0,4242,0,0]Al[3177,14,3178,1737,4244,0,0]53Aj[476,13,477,4162,3332,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Ag[476,15,477,0,4584,0,0]Al[3177,15,3178,1403,4897,0,0]Al[3177,15,3178,3743,4585,0,0]Ah[476,10,3737,3738,0,0,0]Af[3177,10,3738,0,0,0,0]Ag[476,5,3737,3738,0,0,0]Ae[3177,5,3738,0,0,0,0]Ah[476,10,1739,1740,0,0,0]Af[3177,10,1740,0,0,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,2360,4201,0,0]Ag[476,10,477,3743,0,0,0]Ai[3177,10,3178,3743,0,0,0]Ah[3177,6,3178,1802,0,0,0]Ah[3177,6,3178,1403,0,0,0]Af[476,6,477,3742,0,0,0]Ah[3177,6,3178,3151,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]10Aj[476,15,477,3742,4898,0,0]Al[3177,15,3178,3151,4899,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,14,3178,1419,3123,0,0]Ah[476,14,3737,0,4885,0,0]Al[3177,14,3738,3738,4886,0,0]Aj[476,13,477,3742,3300,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]10Al[3177,13,3178,3151,3094,0,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,2360,2315,0,0]Ab[4917,3,0,0,0,0,0]Ao[1125,13,1126,1126,4997,3131,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Af[476,5,477,3279,0,0,0]Ah[3177,5,3178,3279,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]54Ai[3177,10,3178,1802,0,0,0]Al[3177,15,3178,3743,1204,0,0]7600Al[3177,15,3178,1150,4374,0,0]4365Al[3177,15,4854,4854,1202,0,0]Ae[1125,9,1126,0,0,0,0]:9Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]<;<;Af[476,6,477,1403,0,0,0]Ah[3177,6,3178,1403,0,0,0]32Al[1226,15,1227,1227,4075,0,0]Ac[476,5,477,0,0,0,0]Ae[3177,5,3178,0,0,0,0]Ag[476,15,477,0,4200,0,0]Ag[476,5,1739,1740,0,0,0]Al[3177,15,3178,2360,4201,0,0]Al[3177,15,3178,1802,4894,0,0]Ae[3177,5,1740,0,0,0,0]An[1226,13,1227,1227,142,4452,0]An[2413,13,2414,2414,133,4452,0]Ao[1125,13,1126,1126,3091,4452,0]An[1125,13,1729,1729,143,4452,0]An[1125,13,1826,1826,144,4452,0]Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]Ag[476,13,477,0,1482,0,0]Al[3177,13,3178,1858,1483,0,0]Aj[476,14,477,2359,4347,0,0]Aj[476,13,477,3742,5070,0,0]Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Ag[476,13,477,0,4338,0,0]Al[3177,13,3178,4617,4339,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]7Al[3177,13,3178,3743,3301,0,0]Aj[476,13,477,3742,3300,0,0]Ah[476,13,1820,0,4818,0,0]Ah[476,13,1820,0,4820,0,0]Al[3177,13,1821,1821,4819,0,0]Al[3177,13,1821,1821,4821,0,0]45;:Ao[4089,13,4090,4090,5161,4951,0]Ag[476,13,477,0,4598,0,0]Al[3177,13,3178,1146,4599,0,0]Ae[1125,6,1126,0,0,0,0]Af[476,5,477,4270,0,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]10Ag[476,15,477,0,3116,0,0]Al[3177,15,3178,3743,3117,0,0]Ae[3177,5,5109,0,0,0,0]Af[476,5,477,4157,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Al[3177,15,4854,4854,1202,0,0]Aj[476,14,477,2359,4347,0,0]Ai[476,13,477,0,525,3083,0]Ai[476,13,477,0,134,3083,0]An[3177,13,3178,3178,526,3083,0]An[3177,13,3178,3178,135,3083,0]Ao[2413,13,2414,2414,2305,3337,0]Ag[476,13,477,0,4937,0,0]Al[3177,13,3178,3279,4938,0,0]Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Aj[476,13,477,3742,3300,0,0]Ag[476,12,477,0,4891,0,0]Al[3177,12,3178,3743,4892,0,0]Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]Ag[476,14,477,0,3122,0,0]Al[3177,14,3178,1419,3123,0,0]Ah[476,12,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Ak[476,13,3737,0,1186,3302,0]Ak[476,13,3737,0,1888,3302,0]Al[3177,12,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ao[3177,13,3738,1389,1187,3303,0]Ao[3177,13,3738,2413,1889,3303,0]Aj[476,14,477,2359,4347,0,0]Al[3177,13,3178,2050,1909,0,0]Ah[3177,2,4385,4161,0,0,0]Ae[1226,7,1227,0,0,0,0]==Ai[476,13,477,1124,519,0,0]Ak[2035,13,2036,431,4490,0,0]032Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Ae[3177,2,3178,0,0,0,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Ag[476,10,477,4387,0,0,0]Ai[3177,10,3178,4387,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]Ag[476,15,477,0,4200,0,0]Al[3177,15,3178,2360,4201,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Af[476,5,477,1737,0,0,0]Ah[3177,5,3178,1737,0,0,0]Ah[476,12,1739,0,3113,0,0]Al[3177,12,1740,1740,3114,0,0]Aj[476,13,477,2359,2314,0,0]Al[3177,13,3178,3743,3301,0,0]Al[3177,13,3178,2360,2315,0,0]Al[3177,13,3178,3178,3102,0,0]Ah[476,13,3737,0,4366,0,0]Al[3177,13,3738,2413,4367,0,0]Aj[476,13,477,2042,3129,0,0]0Aj[476,13,477,3742,3300,0,0]6Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]Al[1125,14,1126,1126,3091,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Al[3177,15,4854,4854,1202,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]10Ag[476,15,477,0,4952,0,0]Ag[476,15,477,0,3116,0,0]Ag[476,15,477,0,4450,0,0]Al[3177,15,3178,1403,4953,0,0]Al[3177,15,3178,3743,3117,0,0]Al[3177,15,3178,3743,4451,0,0]Ah[3177,5,3178,3743,0,0,0]Al[3177,15,3178,1403,4897,0,0]Ag[476,15,477,0,3103,0,0]Al[3177,15,3178,1393,3104,0,0]Ah[3177,5,3178,1802,0,0,0]Ae[4089,5,4090,0,0,0,0]Al[1125,13,1126,1126,3091,0,0]Aj[476,13,477,3742,3300,0,0]Ah[476,12,1739,0,1901,0,0]Ak[476,13,1820,0,3341,1901,0]Al[3177,12,1740,1740,1902,0,0]Ao[3177,13,1821,1821,3342,1902,0]Ah[3177,7,5040,5039,0,0,0]0Al[3177,13,3178,3743,3301,0,0]6Ai[476,13,477,1124,519,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]Ao[4089,13,4090,4090,5161,4951,0]0Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]10Ag[476,13,477,0,4922,0,0]Al[3177,13,3178,3279,4923,0,0]Am[1226,13,1227,1227,142,498,0]Am[2413,13,2414,2414,133,498,0]An[1125,13,1126,1126,3091,498,0]Am[1125,13,1729,1729,143,498,0]Am[1125,13,1826,1826,144,498,0]??Ah[476,13,3737,0,3302,0,0]Aj[476,13,3737,0,500,3302,0]Al[3177,13,3738,3738,3303,0,0]Am[3177,13,3738,534,501,3303,0]Ai[476,13,477,1124,519,0,0]An[1226,13,1227,1227,142,4462,0]An[2413,13,2414,2414,133,4462,0]Ao[2413,13,2414,2414,2305,4462,0]Ao[1125,13,1126,1126,3091,4462,0]An[1125,13,1729,1729,143,4462,0]An[1125,13,1826,1826,144,4462,0]Ag[476,13,477,0,4242,0,0]Al[3177,13,3178,1737,4244,0,0]Ag[476,19,477,0,4957,0,0]Ai[3177,19,3178,0,4958,0,0]Ae[1125,5,4304,0,0,0,0]0Ag[476,13,477,0,4460,0,0]Al[3177,13,3178,1737,4461,0,0]Ag[476,13,477,0,4188,0,0]Al[3177,13,3178,1737,4190,0,0]Aj[476,13,477,2359,2314,0,0]Aj[476,13,477,2391,2318,0,0]Al[3177,13,3178,2360,2319,0,0]Al[3177,13,3178,3743,3301,0,0]Ao[4089,13,4090,4090,5161,4951,0];:Ag[476,5,1739,1740,0,0,0]Ae[3177,5,1740,0,0,0,0]Ah[476,15,1820,0,1199,0,0]Ai[3177,15,1821,0,1200,0,0]?>?>Aj[476,13,477,3742,3300,0,0]6Ag[476,13,477,0,4607,0,0]Al[3177,13,3178,3279,4608,0,0]Ae[4089,7,4090,0,0,0,0]Ae[4390,7,4391,0,0,0,0]Ag[476,14,477,0,3306,0,0]Al[3177,14,3178,1419,3307,0,0]?>>>>A`[\"{IFbBCAb}\",[]]?A`[\"{KIfBFKl}\",[]]A`[\"{cc{}}\",[\"T\"]]000000A`[\"{KIfABDb}\",[]]11111A`[\"{BBChIFb}\",[]]2222Aa[\"{AONjAOKd}\",[]]333A`[\"{BHMnIF`}\",[]]A`[\"{BEInIF`}\",[]]A`[\"{AINhIF`}\",[]]A`[\"{BCMlIF`}\",[]]7A`[\"{BCOfIF`}\",[]]A`[\"{BHLlIF`}\",[]]A`[\"{BHGfIF`}\",[]]A`[\"{BEHdIF`}\",[]]A`[\"{BBNfIF`}\",[]]A`[\"{BBOhIF`}\",[]]A`[\"{BEFnIF`}\",[]]>>>>>>>>>>>>An[\"{{{AHOh{c}}}AJBbCNf}\",[\"S\"]]??????????????Bm[\"{{{AHOh{KId}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bk[\"{{{AHOh{KGb}}{AHOh{CGbc}}}ICfKEl}\",[\"H\"]]Bn[\"{{{AHOh{AOL`}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{B@Mf}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bm[\"{{{AHOh{DAj}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bm[\"{{{AHOh{A@l}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{ABD`}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bm[\"{{{AHOh{KIf}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{BFDf}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bk[\"{{{AHOh{KGd}}{AHOh{CGbc}}}ICfKEl}\",[\"H\"]]Bn[\"{{{AHOh{AHFl}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{BBBl}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{AJBf}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{AOLb}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{BEGd}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{BFCl}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{B@Mh}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bm[\"{{{AHOh{DAl}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bm[\"{{{AHOh{A@n}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{ABDb}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Bn[\"{{{AHOh{AHCl}}{AHOh{CGbc}}}ICfKEl}\",[\"__H\"]]Aa[\"{{}c{}}\",[\"U\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n[\"{{}ICf}\",[]]0000Cc[\"{{{AHOh{CGbKDj}}KC`}{{KGh{{KG`{ICn}}AHFl}}}}\",[]]Cf[\"{{{AHOh{CGbBB@j}}}{{KG`{c}}}{}}\",[\"Iterator::Item\"]]Dl[\"{{{AHOh{BFBn}}ICd{AHOh{CGb{K@j{Oj}}}}}{{KGh{{AHOh{{K@j{Oj}}}}AOKb}}}}\",[]]Bi[\"{{{AHOh{CGbNNj}}A@n}{{KG`{ABDb}}}}\",[]]Dl[\"{{{AHOh{BFC`}}ICd{AHOh{CGb{K@j{Oj}}}}}{{KGh{{AHOh{{K@j{Oj}}}}AOKd}}}}\",[]]Bf[\"{{{AHOh{AILh}}KGb}{{KG`{D@n}}}}\",[]]Bf[\"{{{AHOh{D@n}}}{{KGh{ICfAIKj}}}}\",[]]A`[\"{AIMdCN`}\",[]]Am[\"{{{AHOh{CGbAILj}}}ICf}\",[]]A`[\"{AIMfCN`}\",[]]Ck[\"{{{ABd{{AHOh{CGbAIJj}}}}{AHOh{CGbNJb}}}{{DAf{ICf}}}}\",[]]Dk[\"{{{ABd{{AHOh{CGbBD@h}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbABCb}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbABCd}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbAILd}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{ABd{{AHOh{CGbNLf}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{ABd{{AHOh{CGbKFb}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbAHAb}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbAAOl}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbBAA`}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbBAAn}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{ABd{{AHOh{CGbKCh}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{ABd{{AHOh{CGbBBNb}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{ABd{{AHOh{CGbNNb}}}}{AHOh{CGbNJb}}}{{DAf{c}}}{}}\",[\"Future::Output\"]]Bf[\"{{{AHOh{CGbAILj}}}{{KG`{IFh}}}}\",[]]De[\"{{{AHOh{CGbAIOl}}{AHOh{CGb{K@j{Oj}}}}}{{KGh{{KG`{KC`}}AHFj}}}}\",[]]Bm[\"{{{AHOh{CGbAIOn}}DBn}{{KGh{KDjBBBl}}}}\",[]]C`[\"{{DAl{AHOh{CGbc}}}{{KGh{BGAjIFb}}}A@h}\",[\"R\"]]Bf[\"{{{AHOh{CGbAHBl}}}{{KG`{ICj}}}}\",[]]Ec[\"{{{AHOh{BCAd}}AJBb{AHOh{CGb{K@j{AIMn}}}}{AHOh{CGb{K@j{ABCl}}}}}{{KGj{KC`}}}}\",[]]Cn[\"{{{AHOh{BFBn}}ICd{AHOh{CGb{ABj{Oj}}}}}{{KGh{ICfAOKb}}}}\",[]]Cn[\"{{{AHOh{BFC`}}ICd{AHOh{CGb{ABj{Oj}}}}}{{KGh{ICfAOKd}}}}\",[]]C`[\"{{{AHOh{CGbAHBl}}ICjDBn}{{KGh{ICfBFDf}}}}\",[]]Cc[\"{{{AHOh{BCAd}}AJBb{AHOh{ABEh}}}{{KGj{ICf}}}}\",[]]Bn[\"{{{AHOh{CGbBH@h}}CMn}{{AHOh{CGbBH@h}}}}\",[]]Bn[\"{{{AHOh{CGbBH@j}}CMn}{{AHOh{CGbBH@j}}}}\",[]]Aj[\"{{{AHOh{AILh}}}DAj}\",[]]Aj[\"{{{AHOh{AILj}}}DAl}\",[]]Cn[\"{{{AHOh{NJn}}{AHOh{{K@j{Oj}}}}{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]Cn[\"{{{AHOh{NK`}}{AHOh{{K@j{Oj}}}}{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]A`[\"{BC@lCN`}\",[]]A`[\"{ABEdKC`}\",[]]A`[\"{ABEfKC`}\",[]]o[\"{IH`DBn}\",[]]Bm[\"{{{AHOh{CGbAIOl}}KId}{{KGh{ICfB@Ld}}}}\",[]]Bm[\"{{{AHOh{CGbBGAl}}KId}{{KGh{ICfB@Ld}}}}\",[]]Bm[\"{{{AHOh{CGbAIOn}}KIf}{{KGh{ICfB@Ll}}}}\",[]]Bn[\"{{{AHOh{AJAn}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bn[\"{{{AHOh{BBOd}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bn[\"{{{AHOh{BEJl}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bn[\"{{{AHOh{AJB`}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bn[\"{{{AHOh{BBOf}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bn[\"{{{AHOh{BEJn}}{AHOh{CMj}}}{{KG`{ICj}}}}\",[]]Bd[\"{{{AHOh{BEGh}}}{{KG`{BB@h}}}}\",[]]Bd[\"{{{AHOh{BEGj}}}{{KG`{BB@j}}}}\",[]]Bi[\"{{{A@d{BFBf}}NKdCMl}{{A@f{AILl}}}}\",[]]Bi[\"{{{A@d{AIKb}}NKdCMl}{{A@f{AILl}}}}\",[]]Bi[\"{{{A@d{AOKf}}NKdCMl}{{A@f{AILl}}}}\",[]]Bi[\"{{{A@d{BBAl}}NKdCMl}{{A@f{AILl}}}}\",[]]Bi[\"{{{A@d{BFBh}}NKdCMl}{{A@f{AILn}}}}\",[]]Bi[\"{{{A@d{AIKd}}NKdCMl}{{A@f{AILn}}}}\",[]]Bi[\"{{{A@d{AOKh}}NKdCMl}{{A@f{AILn}}}}\",[]]Bi[\"{{{A@d{BBAn}}NKdCMl}{{A@f{AILn}}}}\",[]]Aj[\"{BG@j{{A@d{BFBh}}}}\",[]]o[\"{IClICj}\",[]]A`[\"{ABEjCN`}\",[]]o[\"{NOfKC`}\",[]]o[\"{ICnICj}\",[]]A`[\"{ABElCN`}\",[]]o[\"{NOhKC`}\",[]]Aa[\"{AOJbBCMb}\",[]]Ai[\"{{{AHOh{AAl}}}AAl}\",[]]Ak[\"{{{AHOh{AOMf}}}AOMf}\",[]]Ak[\"{{{AHOh{AOJf}}}AOJf}\",[]]Ak[\"{{{AHOh{AILh}}}AILh}\",[]]Ak[\"{{{AHOh{BGIl}}}BGIl}\",[]]Ak[\"{{{AHOh{BFDd}}}BFDd}\",[]]Ak[\"{{{AHOh{ABAd}}}ABAd}\",[]]Ak[\"{{{AHOh{BAOf}}}BAOf}\",[]]Ai[\"{{{AHOh{KF`}}}KF`}\",[]]Ai[\"{{{AHOh{D@n}}}D@n}\",[]]Ak[\"{{{AHOh{BCAf}}}BCAf}\",[]]Ak[\"{{{AHOh{BC@h}}}BC@h}\",[]]Ak[\"{{{AHOh{AHFj}}}AHFj}\",[]]Ak[\"{{{AHOh{AJ@`}}}AJ@`}\",[]]Ak[\"{{{AHOh{BC@f}}}BC@f}\",[]]Ak[\"{{{AHOh{AJBd}}}AJBd}\",[]]Ak[\"{{{AHOh{BAC`}}}BAC`}\",[]]Ai[\"{{{AHOh{KId}}}KId}\",[]]Ak[\"{{{AHOh{BGIf}}}BGIf}\",[]]Ai[\"{{{AHOh{KGb}}}KGb}\",[]]Ak[\"{{{AHOh{AIOb}}}AIOb}\",[]]Ak[\"{{{AHOh{AHF`}}}AHF`}\",[]]Ak[\"{{{AHOh{BFK`}}}BFK`}\",[]]Ak[\"{{{AHOh{AIKj}}}AIKj}\",[]]Ak[\"{{{AHOh{ABEj}}}ABEj}\",[]]Ak[\"{{{AHOh{AIMd}}}AIMd}\",[]]Ak[\"{{{AHOh{AHFd}}}AHFd}\",[]]Ak[\"{{{AHOh{BCMh}}}BCMh}\",[]]Ai[\"{{{AHOh{NOf}}}NOf}\",[]]Ak[\"{{{AHOh{B@Ld}}}B@Ld}\",[]]Ak[\"{{{AHOh{BCM`}}}BCM`}\",[]]Ak[\"{{{AHOh{AHEh}}}AHEh}\",[]]Ak[\"{{{AHOh{BBLd}}}BBLd}\",[]]Ak[\"{{{AHOh{BCOn}}}BCOn}\",[]]Ak[\"{{{AHOh{BFGd}}}BFGd}\",[]]Ak[\"{{{AHOh{BFIb}}}BFIb}\",[]]Ak[\"{{{AHOh{AOL`}}}AOL`}\",[]]Ak[\"{{{AHOh{BBMh}}}BBMh}\",[]]Ak[\"{{{AHOh{BABd}}}BABd}\",[]]Ak[\"{{{AHOh{BH@h}}}BH@h}\",[]]Ak[\"{{{AHOh{B@Kh}}}B@Kh}\",[]]Ak[\"{{{AHOh{AOJl}}}AOJl}\",[]]Ak[\"{{{AHOh{AHCn}}}AHCn}\",[]]Ak[\"{{{AHOh{BCLj}}}BCLj}\",[]]Ak[\"{{{AHOh{BEFh}}}BEFh}\",[]]Ak[\"{{{AHOh{B@M`}}}B@M`}\",[]]Ak[\"{{{AHOh{B@Mf}}}B@Mf}\",[]]Ak[\"{{{AHOh{B@N`}}}B@N`}\",[]]Ak[\"{{{AHOh{BFKj}}}BFKj}\",[]]Ak[\"{{{AHOh{AIMj}}}AIMj}\",[]]Ai[\"{{{AHOh{DAj}}}DAj}\",[]]Ai[\"{{{AHOh{A@l}}}A@l}\",[]]Ak[\"{{{AHOh{ABD`}}}ABD`}\",[]]Ai[\"{{{AHOh{CNh}}}CNh}\",[]]Ak[\"{{{AHOh{AIKb}}}AIKb}\",[]]Ai[\"{{{AHOh{IDd}}}IDd}\",[]]Ak[\"{{{AHOh{AOKf}}}AOKf}\",[]]Ai[\"{{{AHOh{NL`}}}NL`}\",[]]Ak[\"{{{AHOh{BBAl}}}BBAl}\",[]]Ai[\"{{{AHOh{IEn}}}IEn}\",[]]Ak[\"{{{AHOh{BEJd}}}BEJd}\",[]]Ak[\"{{{AHOh{BGHj}}}BGHj}\",[]]Ak[\"{{{AHOh{BEJh}}}BEJh}\",[]]Ai[\"{{{AHOh{KIf}}}KIf}\",[]]Ak[\"{{{AHOh{BGIh}}}BGIh}\",[]]Ak[\"{{{AHOh{BFDf}}}BFDf}\",[]]Ai[\"{{{AHOh{KGd}}}KGd}\",[]]Ak[\"{{{AHOh{BAAl}}}BAAl}\",[]]Ak[\"{{{AHOh{AIOd}}}AIOd}\",[]]Ak[\"{{{AHOh{AHFb}}}AHFb}\",[]]Ak[\"{{{AHOh{BFDb}}}BFDb}\",[]]Ak[\"{{{AHOh{BFKb}}}BFKb}\",[]]Ak[\"{{{AHOh{AIL`}}}AIL`}\",[]]Ak[\"{{{AHOh{ABEl}}}ABEl}\",[]]Ak[\"{{{AHOh{AIMf}}}AIMf}\",[]]Ak[\"{{{AHOh{AHFf}}}AHFf}\",[]]Ak[\"{{{AHOh{BCMj}}}BCMj}\",[]]Ak[\"{{{AHOh{AHFl}}}AHFl}\",[]]Ak[\"{{{AHOh{BBBl}}}BBBl}\",[]]Ai[\"{{{AHOh{NOh}}}NOh}\",[]]Ak[\"{{{AHOh{AJBf}}}AJBf}\",[]]Ak[\"{{{AHOh{AOKn}}}AOKn}\",[]]Ak[\"{{{AHOh{BC@j}}}BC@j}\",[]]Ak[\"{{{AHOh{B@Ll}}}B@Ll}\",[]]Ak[\"{{{AHOh{BCMb}}}BCMb}\",[]]Ak[\"{{{AHOh{AHEj}}}AHEj}\",[]]Ak[\"{{{AHOh{BBLf}}}BBLf}\",[]]Ak[\"{{{AHOh{BHDh}}}BHDh}\",[]]Ak[\"{{{AHOh{BD@`}}}BD@`}\",[]]Ak[\"{{{AHOh{BFGf}}}BFGf}\",[]]Ak[\"{{{AHOh{BFId}}}BFId}\",[]]Ak[\"{{{AHOh{AOLb}}}AOLb}\",[]]Ak[\"{{{AHOh{BBMj}}}BBMj}\",[]]Ak[\"{{{AHOh{BABh}}}BABh}\",[]]Ak[\"{{{AHOh{BH@j}}}BH@j}\",[]]Ak[\"{{{AHOh{B@Kl}}}B@Kl}\",[]]Ak[\"{{{AHOh{AOJn}}}AOJn}\",[]]Ak[\"{{{AHOh{AHD`}}}AHD`}\",[]]Ak[\"{{{AHOh{AINb}}}AINb}\",[]]Ak[\"{{{AHOh{AJA`}}}AJA`}\",[]]Ak[\"{{{AHOh{B@Mj}}}B@Mj}\",[]]Ak[\"{{{AHOh{BCLn}}}BCLn}\",[]]Ak[\"{{{AHOh{BEFl}}}BEFl}\",[]]Ak[\"{{{AHOh{AB@h}}}AB@h}\",[]]Ak[\"{{{AHOh{BEGd}}}BEGd}\",[]]Ak[\"{{{AHOh{B@Mb}}}B@Mb}\",[]]Ak[\"{{{AHOh{BCNj}}}BCNj}\",[]]Ak[\"{{{AHOh{BHE`}}}BHE`}\",[]]Ak[\"{{{AHOh{ABBd}}}ABBd}\",[]]Ak[\"{{{AHOh{BFCl}}}BFCl}\",[]]Ak[\"{{{AHOh{B@Mh}}}B@Mh}\",[]]Ak[\"{{{AHOh{B@Nb}}}B@Nb}\",[]]Ak[\"{{{AHOh{BCAb}}}BCAb}\",[]]Ak[\"{{{AHOh{BFKl}}}BFKl}\",[]]Ak[\"{{{AHOh{AIMl}}}AIMl}\",[]]Ak[\"{{{AHOh{BIAh}}}BIAh}\",[]]Ai[\"{{{AHOh{DAl}}}DAl}\",[]]Ai[\"{{{AHOh{A@n}}}A@n}\",[]]Ak[\"{{{AHOh{ABDb}}}ABDb}\",[]]Ak[\"{{{AHOh{AHCl}}}AHCl}\",[]]Ak[\"{{{AHOh{BBCh}}}BBCh}\",[]]Ak[\"{{{AHOh{BGAj}}}BGAj}\",[]]Ai[\"{{{AHOh{IFb}}}IFb}\",[]]Ai[\"{{{AHOh{IF`}}}IF`}\",[]]Ak[\"{{{AHOh{BEJf}}}BEJf}\",[]]Ak[\"{{{AHOh{BGHl}}}BGHl}\",[]]Ak[\"{{{AHOh{BEJj}}}BEJj}\",[]]Ai[\"{{{AHOh{CNj}}}CNj}\",[]]Ak[\"{{{AHOh{AIKd}}}AIKd}\",[]]Ai[\"{{{AHOh{IDf}}}IDf}\",[]]Ak[\"{{{AHOh{AOKh}}}AOKh}\",[]]Ai[\"{{{AHOh{NLb}}}NLb}\",[]]Ak[\"{{{AHOh{BBAn}}}BBAn}\",[]]Ai[\"{{{AHOh{IFj}}}IFj}\",[]]Ak[\"{{{AHOh{ABCl}}}ABCl}\",[]]Ak[\"{{{AHOh{ABEh}}}ABEh}\",[]]Ak[\"{{{AHOh{B@Nd}}}B@Nd}\",[]]Ak[\"{{{AHOh{BG@j}}}BG@j}\",[]]Ak[\"{{{AHOh{BCNb}}}BCNb}\",[]]Ak[\"{{{AHOh{BHKb}}}BHKb}\",[]]Ak[\"{{{AHOh{BHKd}}}BHKd}\",[]]Bn[\"{{{AHOh{AILh}}KId{AHOh{{K@j{Oj}}}}}ICf}\",[]]Bn[\"{{{AHOh{ABAd}}KId{AHOh{{K@j{Oj}}}}}ICf}\",[]]Bf[\"{{{AHOh{D@n}}}{{KGh{ICfBBLd}}}}\",[]]Bf[\"{{{AHOh{CGbAILj}}NKdKIfICj}ICf}\",[]]Bj[\"{{{AHOh{B@Mf}}}{{AHOh{{K@j{Oj}}}}}}\",[]]Bj[\"{{{AHOh{B@Mh}}}{{AHOh{{K@j{Oj}}}}}}\",[]]Aa[\"{BCAbAINb}\",[]]A`[\"{ABD`CN`}\",[]]A`[\"{ABDbCN`}\",[]]A`[\"{B@N`DBn}\",[]]A`[\"{B@NbDBn}\",[]]l[\"{NKf}\",[]]l[\"{NKh}\",[]]Cf[\"{{{AHOh{BFH`}}{AHOh{CGbA@h}}}{{KGh{B@MhBFCl}}}}\",[]]Cf[\"{{{AHOh{BIDn}}{AHOh{CGbA@h}}}{{KGh{B@MhBFCl}}}}\",[]]Bc[\"{{{AHOh{AILj}}}{{ABj{KGd}}}}\",[]]Bd[\"{{{AHOh{IHf}}{AHOh{CMj}}}ICf}\",[]]Am[\"{{{AHOh{AOJh}}KC`}ICf}\",[]]Ai[\"{{{AHOh{IHh}}}ICf}\",[]]Bg[\"{{{ABd{{AHOh{CGbAIJj}}}}NKd}ICf}\",[]]Bm[\"{{{AHOh{CGbAJ@h}}KId}{{KGh{ICfB@Ld}}}}\",[]]Bm[\"{{{AHOh{CGbAJ@j}}KIf}{{KGh{ICfB@Ll}}}}\",[]]Am[\"{ABAl{{KGh{ICfAJ@b}}}}\",[]]Dc[\"{{{AHOh{CGbABAf}}ABAn{AHOh{CGb{ABj{Oj}}}}}{{KGh{ABEfAJ@d}}}}\",[]]Bj[\"{{{AHOh{NMh}}{ABd{{A@f{KEj}}}}}ICf}\",[]]Bk[\"{{{AHOh{BACb}}{ABd{{A@f{KEj}}}}}ICf}\",[]]Bk[\"{{{AHOh{AOMl}}{ABd{{A@f{KEj}}}}}ICf}\",[]]o[\"{AAlDBn}\",[]]Ak[\"{{{AHOh{AILh}}}BCMh}\",[]]Ak[\"{{{AHOh{ABAd}}}BAOf}\",[]]Aj[\"{{{AHOh{D@n}}}AHFd}\",[]]An[\"{{{AHOh{CGbAILj}}}BCMj}\",[]]Ce[\"{{{AHOh{CGbAIOf}}{KG`{KI`}}}{{AHOh{CGbAIOf}}}}\",[]]Ce[\"{{{AHOh{CGbAIOh}}{KG`{KI`}}}{{AHOh{CGbAIOh}}}}\",[]]Ck[\"{{{AHOh{CGbAJ@h}}{AHOh{{K@j{Oj}}}}}{{KGh{KC`AJBd}}}}\",[]]Ck[\"{{{AHOh{CGbAJ@j}}{AHOh{{K@j{Oj}}}}}{{KGh{KC`AJBf}}}}\",[]]Bl[\"{{{AHOh{BGAj}}{AHOh{CGbc}}}ICfKDh}\",[\"W\"]]Aj[\"{{{AHOh{ABAd}}}KCh}\",[]]An[\"{ABAl{{KGh{AILdBCM`}}}}\",[]]Bi[\"{{{AHOh{CGbNNj}}A@n}{{KG`{ABDb}}}}\",[]]Fj[\"{{{AHOh{CGbABAf}}ABAnNKd{AHOh{CGb{ABj{Oj}}}}{KG`{{A@d{BABh}}}}}{{KGh{{KBn{BEGdAILj}}{A@f{AOJb}}}}}}\",[]]Am[\"{AHOh{{AHOh{c}}}{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000o[\"{NOfKC`}\",[]]o[\"{NOhKC`}\",[]]A`[\"{AAlAOJf}\",[]]Bc[\"{{AJ@nBBLbAAl}{{KGl{AOJh}}}}\",[]]Aj[\"{AJ@n{{KGj{ABAd}}}}\",[]]Ba[\"{{}{{KGh{ICf{A@f{IE`}}}}}}\",[]]Ak[\"{{{AHOh{AILh}}}BCM`}\",[]]Be[\"{{{AHOh{ABAf}}}{{AHOh{BBMj}}}}\",[]]o[\"{OjBFKj}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{BABdA@d}\",[]]o[\"{OjBFKl}\",[]]A`[\"{AIMfCN`}\",[]]A`[\"{BABhA@d}\",[]]A`[\"{BCAbKG`}\",[]]Bm[\"{{{AHOh{CGbc}}}{{KGh{KIdBBCh}}}A@h}\",[\"B\"]]Bm[\"{{{AHOh{CGbc}}}{{KGh{KGbBBCh}}}A@h}\",[\"B\"]]Bn[\"{{{AHOh{CGbc}}}{{KGh{AHCnBBCh}}}A@h}\",[\"B\"]]Bn[\"{{{AHOh{CGbc}}}{{KGh{BFKjBBCh}}}A@h}\",[\"B\"]]Bn[\"{{{AHOh{CGbc}}}{{KGh{ABD`BBCh}}}A@h}\",[\"B\"]]Bi[\"{{{AHOh{CGbc}}}{{KH`{KIf}}}A@h}\",[\"B\"]]Bi[\"{{{AHOh{CGbc}}}{{KH`{KGd}}}A@h}\",[\"B\"]]Bj[\"{{{AHOh{CGbc}}}{{KH`{AHD`}}}A@h}\",[\"B\"]]Bj[\"{{{AHOh{CGbc}}}{{KH`{AINb}}}A@h}\",[\"B\"]]Ek[\"{{{AHOh{CGb{KEh{AAOn}}}}{AHOh{c}}{AHOh{{K@j{CMn}}}}DBn}{{KGh{BCNjBFCl}}}{BFH`IHd}}\",[\"\"]]Bj[\"{{{AHOh{CGbc}}}{{KH`{BFKl}}}A@h}\",[\"B\"]]Bj[\"{{{AHOh{CGbc}}}{{KH`{ABDb}}}A@h}\",[\"B\"]]Bj[\"{{{AHOh{CGbc}}}{{KH`{AHBn}}}A@h}\",[\"B\"]]A`[\"{ABClKG`}\",[]]Bk[\"{{{AHOh{KId}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bk[\"{{{AHOh{KGb}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{AHCn}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{BFKj}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{ABD`}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bk[\"{{{AHOh{KIf}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bk[\"{{{AHOh{KGd}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{AHD`}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{AINb}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{AB@h}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{BFKl}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{ABDb}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bl[\"{{{AHOh{AHCh}}{AHOh{CGbc}}}ICfKDh}\",[\"B\"]]Bj[\"{{{AHOh{CGbAJ@h}}}{{KGh{ICfB@Ld}}}}\",[]]Bj[\"{{{AHOh{CGbAJ@j}}}{{KGh{ICfAOKn}}}}\",[]]An[\"{{{AHOh{AONh}}ABA`}ICf}\",[]]Ea[\"{{{AHOh{CGbABAf}}NKdAHCl{KG`{B@Nb}}AAOn{AHOh{CGb{ABj{Oj}}}}}{{KG`{BAOb}}}}\",[]]o[\"{D@bNKf}\",[]]o[\"{D@dNKh}\",[]]A`[\"{ABAlICf}\",[]]Ba[\"{{{AHOh{CGbABAf}}ABAn}ICf}\",[]]Bh[\"{{{AHOh{AJAn}}{AHOh{CMj}}ICj}ICf}\",[]]Bh[\"{{{AHOh{BBOd}}{AHOh{CMj}}ICj}ICf}\",[]]Bh[\"{{{AHOh{BEJl}}{AHOh{CMj}}ICj}ICf}\",[]]Bh[\"{{{AHOh{AJB`}}{AHOh{CMj}}ICj}ICf}\",[]]Bh[\"{{{AHOh{BBOf}}{AHOh{CMj}}ICj}ICf}\",[]]Bh[\"{{{AHOh{BEJn}}{AHOh{CMj}}ICj}ICf}\",[]]A`[\"{AHBfDBn}\",[]]o[\"{IClCN`}\",[]]o[\"{ICnCN`}\",[]]Ch[\"{{{AHOh{CGbAILl}}NKdNKdCN`CN`DBn{AHOh{BAAj}}}ICf}\",[]]Cg[\"{{{AHOh{CGbCNh}}NKdNKdCN`CN`DBn{AHOh{BAAj}}}ICf}\",[]]Cg[\"{{{AHOh{CGbIDd}}NKdNKdCN`CN`DBn{AHOh{BAAj}}}ICf}\",[]]Cg[\"{{{AHOh{CGbNL`}}NKdNKdCN`CN`DBn{AHOh{BAAj}}}ICf}\",[]]Ch[\"{{{AHOh{CGbAILn}}NKdNKdCN`CN`DBn{AHOh{BAAl}}}ICf}\",[]]Cg[\"{{{AHOh{CGbCNj}}NKdNKdCN`CN`DBn{AHOh{BAAl}}}ICf}\",[]]Cg[\"{{{AHOh{CGbIDf}}NKdNKdCN`CN`DBn{AHOh{BAAl}}}ICf}\",[]]Cg[\"{{{AHOh{CGbNLb}}NKdNKdCN`CN`DBn{AHOh{BAAl}}}ICf}\",[]]o[\"{D@bNKf}\",[]]o[\"{D@dNKh}\",[]]o[\"{BEKhOj}\",[]]A`[\"{BCLjICj}\",[]]A`[\"{BEFhICj}\",[]]Aa[\"{AH@jBFD`}\",[]]A`[\"{BCLnICj}\",[]]A`[\"{BEFlICj}\",[]]A`[\"{BCAbKI`}\",[]]Aa[\"{BBLjBCMb}\",[]]Aa[\"{AH@lBFDb}\",[]]Bg[\"{{{AHOh{ABAd}}AHGd}{{KGj{ICf}}}}\",[]]A`[\"{ABAlICf}\",[]]Cf[\"{{{AHOh{CGbABAf}}ABAn{AHOh{CGb{ABj{Oj}}}}}ABEf}\",[]]l[\"{NKf}\",[]]Ak[\"{{{AHOh{AHCl}}}AJ@n}\",[]]l[\"{NKh}\",[]]An[\"{{ABAbAAl}{{KGl{ICf}}}}\",[]]B`[\"{{BABdAJ@n}{{KGj{ABAd}}}}\",[]]Bc[\"{BAB`{{KGh{ICf{A@f{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BFDd}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BC@h}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{AHFj}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{AJ@`}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BC@f}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{AJBd}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BAC`}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BCM`}}}{{KG`{{AHOh{IE`}}}}}}\",[]]Bk[\"{{{AHOh{BCMb}}}{{KG`{{AHOh{IE`}}}}}}\",[]]A`[\"{ABEdKG`}\",[]]A`[\"{ABEfKG`}\",[]]A`[\"{ABEhKG`}\",[]]Bg[\"{{{AHOh{D@n}}}{{KGh{AIObAIKj}}}}\",[]]Aa[\"{BAAbAIOb}\",[]]Aa[\"{BAAdAIOd}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]A`[\"{ABClKC`}\",[]]Aa[\"{AHFdABEj}\",[]]Aa[\"{BCMhABEj}\",[]]Aa[\"{AHFfABEl}\",[]]Aa[\"{BCMjABEl}\",[]]3210Dh[\"{{{AHOh{NJn}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfAOKb}}}}\",[]]Dh[\"{{{AHOh{NK`}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfAOKd}}}}\",[]]Aj[\"{{{AHOh{AILl}}}CN`}\",[]]Ai[\"{{{AHOh{CNh}}}CN`}\",[]]Ai[\"{{{AHOh{IDd}}}CN`}\",[]]Ai[\"{{{AHOh{NL`}}}CN`}\",[]]Aj[\"{{{AHOh{AILn}}}CN`}\",[]]Ai[\"{{{AHOh{CNj}}}CN`}\",[]]Ai[\"{{{AHOh{IDf}}}CN`}\",[]]Ai[\"{{{AHOh{NLb}}}CN`}\",[]]Aj[\"{{{AHOh{BGOf}}}KC`}\",[]]Aj[\"{{{AHOh{BGOh}}}KC`}\",[]]Aj[\"{{{AHOh{BI@n}}}KC`}\",[]]Aj[\"{{{AHOh{BIAh}}}KC`}\",[]]o[\"{AAlKC`}\",[]]n[\"{{}NJ`}\",[]]0A`[\"{A@jAB@b}\",[]]111Ba[\"{{AHOh{AHOh{c}}}ABCf{}}\",[\"K\"]]0000000000000000000Cg[\"{{{AHOh{ABAd}}AJ@n{AHOh{CMj}}}{{KGh{AILdB@M`}}}}\",[]]Dl[\"{{{AHOh{CGbABAf}}NKdB@KlAJ@n{AHOh{CMj}}}{{KGh{{KBn{BEGdAILj}}B@Mb}}}}\",[]]Bd[\"{{{AHOh{ABAl}}}{{KG`{BEGh}}}}\",[]]Dm[\"{{{AHOh{AHEb}}KGbCN`{AHOh{{K@j{Oj}}}}{AHOh{CGbAAOn}}}{{KGh{ICfAOKb}}}}\",[]]Ca[\"{{{AHOh{AHDd}}KC`{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]Bd[\"{{{AHOh{ABAn}}}{{KG`{BEGj}}}}\",[]]Dm[\"{{{AHOh{AHEd}}KGdCN`{AHOh{{K@j{Oj}}}}{AHOh{CGbAAOn}}}{{KGh{ICfAOKd}}}}\",[]]Ca[\"{{{AHOh{AHDf}}KC`{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]o[\"{{}AONf}\",[]]n[\"{{}IHf}\",[]]o[\"{{}AOJh}\",[]]o[\"{{}BANd}\",[]]o[\"{{}BAOf}\",[]]n[\"{{}KId}\",[]]n[\"{{}KGb}\",[]]o[\"{{}AIOb}\",[]]o[\"{{}AIKj}\",[]]o[\"{{}ABEj}\",[]]o[\"{{}AIMd}\",[]]o[\"{{}AHFd}\",[]]o[\"{{}BCMh}\",[]]n[\"{{}NOf}\",[]]o[\"{{}B@Ld}\",[]]o[\"{{}BCOn}\",[]]o[\"{{}BFGd}\",[]]o[\"{{}BFIb}\",[]]o[\"{{}AOL`}\",[]]o[\"{{}BBMh}\",[]]o[\"{{}BH@h}\",[]]o[\"{{}BEJl}\",[]]o[\"{{}AIKb}\",[]]o[\"{{}AOKf}\",[]]o[\"{{}BBAl}\",[]]o[\"{{}BFBj}\",[]]o[\"{{}BANf}\",[]]o[\"{{}BI@n}\",[]]n[\"{{}KIf}\",[]]n[\"{{}KGd}\",[]]o[\"{{}AIOd}\",[]]o[\"{{}AIL`}\",[]]o[\"{{}ABEl}\",[]]o[\"{{}AIMf}\",[]]o[\"{{}AHFf}\",[]]o[\"{{}BCMj}\",[]]n[\"{{}NOh}\",[]]o[\"{{}BC@j}\",[]]o[\"{{}B@Ll}\",[]]o[\"{{}BD@`}\",[]]o[\"{{}BFGf}\",[]]o[\"{{}BFId}\",[]]o[\"{{}AOLb}\",[]]o[\"{{}BBMj}\",[]]o[\"{{}BH@j}\",[]]o[\"{{}BIAh}\",[]]o[\"{{}BEJn}\",[]]o[\"{{}AIKd}\",[]]o[\"{{}AOKh}\",[]]o[\"{{}BBAn}\",[]]o[\"{{}BFBl}\",[]]o[\"{{}ABCl}\",[]]n[\"{{}IHh}\",[]]o[\"{{}BCNb}\",[]]o[\"{{}BAOd}\",[]]Ak[\"{{{AHOh{BBBb}}}B@Mh}\",[]]Ak[\"{{{AHOh{BCNj}}}B@Mh}\",[]]Aa[\"{BHE`B@Mh}\",[]]Aa[\"{BFKnB@Mh}\",[]]A`[\"{D@fB@Mh}\",[]]A`[\"{IGlB@Mh}\",[]]A`[\"{IH`B@Mh}\",[]]Aa[\"{BEKhB@Mh}\",[]]Cg[\"{{{AHOh{AHEb}}KGbCN`{AHOh{CGb{K@j{Oj}}}}KC`}ICf}\",[]]Ca[\"{{{AHOh{AHDd}}KC`{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]Cg[\"{{{AHOh{AHEd}}KGdCN`{AHOh{CGb{K@j{Oj}}}}KC`}ICf}\",[]]Ca[\"{{{AHOh{AHDf}}KC`{AHOh{CGb{K@j{Oj}}}}}ICf}\",[]]Aj[\"{{{AHOh{AIOl}}}DBn}\",[]]Aj[\"{{{AHOh{BGAl}}}DBn}\",[]]Ak[\"{{{AHOh{AILl}}}BFBj}\",[]]Aj[\"{{{AHOh{CNh}}}BFBj}\",[]]Aj[\"{{{AHOh{IDd}}}BFBj}\",[]]Aj[\"{{{AHOh{NL`}}}BFBj}\",[]]Ak[\"{{{AHOh{AILn}}}BFBl}\",[]]Aj[\"{{{AHOh{CNj}}}BFBl}\",[]]Aj[\"{{{AHOh{IDf}}}BFBl}\",[]]Aj[\"{{{AHOh{NLb}}}BFBl}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMl}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}CMl}{{AHOh{CGbBD@`}}}}\",[]]Bf[\"{{{AHOh{CGbAILl}}NKdCN`CN`}ICf}\",[]]Bf[\"{{{AHOh{CGbAILn}}NKdCN`CN`}ICf}\",[]]Aj[\"{{{AHOh{AILh}}}KFb}\",[]]Bc[\"{{{AHOh{ABCd}}}{{KG`{KGb}}}}\",[]]Aa[\"{BHE`B@Mh}\",[]]Aa[\"{BFKnB@Mh}\",[]]A`[\"{D@fB@Mh}\",[]]A`[\"{IGlB@Mh}\",[]]Aa[\"{BEKhB@Mh}\",[]]Aj[\"{{{AHOh{AJ@h}}}NNb}\",[]]Bn[\"{{{AHOh{AJ@j}}}{{KGh{{KG`{KIf}}B@Ll}}}}\",[]]o[\"{AAlKC`}\",[]]o[\"{IHfKC`}\",[]]Am[\"{{{AHOh{CGbAILj}}}NNj}\",[]]Aj[\"{{{AHOh{AHEb}}}KC`}\",[]]Aj[\"{{{AHOh{AHEd}}}KC`}\",[]]A`[\"{AHOhKIb}\",[]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bd[\"{{{AHOh{BGIl}}}{{KG`{AILh}}}}\",[]]Bc[\"{{{AHOh{BCAf}}}{{KG`{D@n}}}}\",[]]Bn[\"{{{AHOh{CGbB@Kh}}CMn}{{AHOh{CGbB@Kh}}}}\",[]]Bn[\"{{{AHOh{CGbB@Kl}}CMn}{{AHOh{CGbB@Kl}}}}\",[]]A`[\"{BHE`CMn}\",[]]A`[\"{BFKnCMn}\",[]]o[\"{D@fCMn}\",[]]o[\"{IGlCMn}\",[]]A`[\"{AHBfKG`}\",[]]Aa[\"{ABEhAHOh}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Aa[\"{BC@lABA`}\",[]]A`[\"{KDjBC@j}\",[]]Aa[\"{AHFdAIMd}\",[]]Aa[\"{BCMhAIMd}\",[]]Aa[\"{AHFfAIMf}\",[]]Aa[\"{BCMjAIMf}\",[]]3210Bh[\"{{{AHOh{CGbc}}KC`}B@Mf{A@hIHd}}\",[\"\"]]Bh[\"{{{AHOh{CGbc}}KC`}B@Mh{A@hIHd}}\",[\"\"]]o[\"{{}BCNl}\",[]]o[\"{{}BCNn}\",[]]A`[\"{CN`BI@n}\",[]]Cd[\"{{{AHOh{CMj}}}{{KGl{AOMfc}}}{}}\",[\"FromStr::Err\"]]Cd[\"{{{AHOh{CMj}}}{{KGl{AOJfc}}}{}}\",[\"FromStr::Err\"]]o[\"{CMnKId}\",[]]o[\"{CMnKIf}\",[]]Al[\"{CN`{{KGh{KIdBGIf}}}}\",[]]Al[\"{CN`{{KGh{KIfBGIh}}}}\",[]]Aa[\"{BGGjAOK`}\",[]]Aa[\"{BIE`BB@b}\",[]]Aa[\"{BGGlAOK`}\",[]]Aa[\"{BIEbBB@b}\",[]]Af[\"{{}{{KG`{Ab}}}}\",[]]0000Aj[\"{{{AHOh{AILj}}}DBn}\",[]]Bo[\"{{{AHOh{CGbBFIb}}ABA`}{{AHOh{CGbBFIb}}}}\",[]]Bo[\"{{{AHOh{CGbBFId}}ABA`}{{AHOh{CGbBFId}}}}\",[]]Bb[\"{{{A@f{AILl}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{CNh}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{IDd}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{NL`}}}{{A@f{A@b}}}}\",[]]Bb[\"{{{A@f{AILn}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{CNj}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{IDf}}}{{A@f{A@b}}}}\",[]]Ba[\"{{{A@f{NLb}}}{{A@f{A@b}}}}\",[]]Aj[\"{{{AHOh{BGIl}}}DBn}\",[]]Bo[\"{{{AHOh{CGbBH@h}}ABA`}{{AHOh{CGbBH@h}}}}\",[]]Bo[\"{{{AHOh{CGbBH@j}}ABA`}{{AHOh{CGbBH@j}}}}\",[]]Bc[\"{{{AHOh{AILd}}}{{KG`{KEn}}}}\",[]]Bc[\"{{{AHOh{AILh}}}{{KG`{KEn}}}}\",[]]Bc[\"{{{AHOh{ABAl}}}{{KG`{KEn}}}}\",[]]Bc[\"{{{AHOh{ABAn}}}{{KG`{KEn}}}}\",[]]Bc[\"{{{AHOh{AHCl}}}{{KG`{KEn}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bc[\"{{{AHOh{AHBl}}}{{KG`{KC`}}}}\",[]]Am[\"{{{AHOh{AONh}}KC`}ICf}\",[]]Aj[\"{{{AHOh{AILh}}}NLf}\",[]]Bg[\"{{{AHOh{AJ@h}}}{{KGh{CElB@Ld}}}}\",[]]Bg[\"{{{AHOh{AJ@j}}}{{KGh{CElB@Ll}}}}\",[]]A`[\"{BAOjKG`}\",[]]A`[\"{BAOlKG`}\",[]]A`[\"{AHBfKG`}\",[]]A`[\"{AOJbKG`}\",[]]Ck[\"{{{AHOh{CGbBBMh}}{KG`{{IId{Oj}}}}}{{AHOh{CGbBBMh}}}}\",[]]Ck[\"{{{AHOh{CGbBBMj}}{KG`{{IId{Oj}}}}}{{AHOh{CGbBBMj}}}}\",[]]A`[\"{BFBjKG`}\",[]]A`[\"{BFBlKG`}\",[]]Ac[\"{AHOhc{}}\",[\"T\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Ao[\"{c{{KGh{e}}}{}{}}\",[\"U\",\"T\"]]00000000000000000000000000000000000000000000000000000Al[\"{CN`{{KGh{KIdBGIf}}}}\",[]]Al[\"{KC`{{KGh{KIdBGIf}}}}\",[]]Al[\"{ICd{{KGh{KIdBGIf}}}}\",[]]33333333333333333333Aj[\"{ABA`{{KGh{AOL`}}}}\",[]]444444Ai[\"{CN`{{KGh{AHCn}}}}\",[]]5555555555555555555555555555Aj[\"{B@Kf{{KGh{BEJd}}}}\",[]]Bc[\"{{{A@d{B@Kf}}}{{KGh{BEJd}}}}\",[]]77Bc[\"{{{A@d{BABb}}}{{KGh{BEJh}}}}\",[]]Aj[\"{BABb{{KGh{BEJh}}}}\",[]]999999999999999999999Al[\"{ICd{{KGh{KIfBGIh}}}}\",[]]:Al[\"{CN`{{KGh{KIfBGIh}}}}\",[]]Al[\"{KC`{{KGh{KIfBGIh}}}}\",[]]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Bm[\"{B@Kf{{KGh{BEJfc}}}{}}\",[\"TryFrom::Error\"]]?Cf[\"{{{A@d{B@Kf}}}{{KGh{BEJfc}}}{}}\",[\"TryFrom::Error\"]]Ao[\"{c{{KGh{e}}}{}{}}\",[\"U\",\"T\"]]Cf[\"{{{A@d{BABb}}}{{KGh{BEJjc}}}{}}\",[\"TryFrom::Error\"]]1Bm[\"{BABb{{KGh{BEJjc}}}{}}\",[\"TryFrom::Error\"]]22222222222222222222222Aj[\"{{}{{KGh{c}}}{}}\",[\"U\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cd[\"{{{ABd{{AHOh{CGbc}}}}{AHOh{CGbNJb}}}DAf{}}\",[\"F\"]]000000000Cc[\"{{{AHOh{BCAd}}AJBb{AHOh{ABEh}}}{{KGj{ICf}}}}\",[]]Bk[\"{{{AHOh{BGOf}}B@Mf}{{KGh{ICfAIMj}}}}\",[]]Bk[\"{{{AHOh{BGOh}}B@Mh}{{KGh{ICfAIMl}}}}\",[]]0Bk[\"{{{AHOh{BI@n}}B@Mh}{{KGh{ICfAIMl}}}}\",[]]Ak[\"{{{AHOh{AILh}}}AAOl}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{KIdIEl}}}}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{DAjIEl}}}}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{A@lIEl}}}}\",[]]Bj[\"{{{AHOh{CGbBACd}}}{{KGh{ABD`IEl}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{KIf}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{DAl}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{A@n}}}}\",[]]Bg[\"{{{AHOh{CGbBACd}}}{{KGn{ABDb}}}}\",[]]Aa[\"{AOJfBGId}\",[]]Bd[\"{{{AHOh{AILl}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{CNh}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{IDd}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{NL`}}}{{A@f{AILl}}}}\",[]]Bd[\"{{{AHOh{AILn}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{CNj}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{IDf}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{NLb}}}{{A@f{AILn}}}}\",[]]A`[\"{ABEjCN`}\",[]]An[\"{{{AHOh{CGbAILj}}}AHBl}\",[]]A`[\"{ABElCN`}\",[]]C`[\"{{{AHOh{CGbB@Mf}}}{{AHOh{CGb{K@j{Oj}}}}}}\",[]]C`[\"{{{AHOh{CGbB@Mh}}}{{AHOh{CGb{K@j{Oj}}}}}}\",[]]Ah[\"{Oj{{KG`{B@N`}}}}\",[]]Ah[\"{Oj{{KG`{B@Nb}}}}\",[]]Ah[\"{Oj{{KG`{B@Nd}}}}\",[]]A`[\"{ABD`DAj}\",[]]A`[\"{ABDbDAl}\",[]]Bi[\"{AILd{{KGh{{KBn{AILhBD@h}}AILd}}}}\",[]]Aa[\"{{}c{}}\",[\"I\"]]o[\"{DAjDBn}\",[]]o[\"{DAlDBn}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]21Aj[\"{{{AHOh{ABAl}}}DBn}\",[]]Aj[\"{{{AHOh{ABAn}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBABd}}DBn}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}DBn}{{AHOh{CGbBABh}}}}\",[]]Bm[\"{{{AHOh{NMh}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]Bn[\"{{{AHOh{BACb}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]Bn[\"{{{AHOh{AOMl}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Ak[\"{{{AHOh{AILh}}}ABCb}\",[]]Bc[\"{{{AHOh{AILh}}AJ@nAIOb}ABCd}\",[]]Ce[\"{{{AHOh{CGbAILj}}AHClAIOdNKd}{{KGh{KGdAHEj}}}}\",[]]43Bm[\"{{{AHOh{CGbAILj}}KGd}{{KGh{ICfAIL`}}}}\",[]]E`[\"{{{ABd{{AHOh{CGbBGHn}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbBEFd}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbAIO`}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbBG@l}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]Ec[\"{{{AHOh{CGbAIOl}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{Oj}}}}}{{DAf{{KGh{KC`AHFj}}}}}}\",[]]Ef[\"{{{ABd{{AHOh{CGbAIOl}}}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{Oj}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]E`[\"{{{ABd{{AHOh{CGbAIOl}}}}{AHOh{CGbNJb}}{AHOh{CGbNMb}}}{{DAf{{KGj{ICf}}}}}}\",[]]Fg[\"{{{AHOh{CGbBBL`}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{AIMn}}}}{AHOh{CGb{K@j{ABCl}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]Dn[\"{{{ABd{{AHOh{CGbAHGb}}}}{AHOh{ABEh}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]>=Ce[\"{{{AHOh{CGbBBMh}}{A@d{NJn}}}{{AHOh{CGbBBMh}}}}\",[]]Ce[\"{{{AHOh{CGbBBMj}}{A@d{NK`}}}{{AHOh{CGbBBMj}}}}\",[]]Cj[\"{{{AHOh{BABf}}CMnB@Mf{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BEJh}}CMnB@Mf{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BABj}}CMnB@Mh{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BEJj}}CMnB@Mh{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BHKd}}CMnB@Md{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Bb[\"{KC`{{KBn{KC`{KG`{KC`}}}}}}\",[]]000Aj[\"{{{AHOh{AILh}}}KC`}\",[]]A`[\"{AHOhKI`}\",[]]000000000000000000000000000000000000000000000000000000000000000000Cf[\"{{{AHOh{CGbBABd}}{A@d{BFBn}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{BFC`}}}{{AHOh{CGbBABh}}}}\",[]]A`[\"{BHE`IGb}\",[]]A`[\"{BABdA@d}\",[]]A`[\"{BABhA@d}\",[]]Aj[\"{{{AHOh{ABAd}}}ICf}\",[]]Ck[\"{{{AHOh{CGbAJ@h}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfAJBd}}}}\",[]]n[\"{{}KC`}\",[]]Ak[\"{{{AHOh{AILh}}}AHAb}\",[]]Ba[\"{{{AHOh{CGbABEj}}ABEj}ICf}\",[]]Ba[\"{{{AHOh{CGbAIMd}}AIMd}ICf}\",[]]Ba[\"{{{AHOh{CGbBCMh}}AHFd}ICf}\",[]]Ba[\"{{{AHOh{CGbABEl}}ABEl}ICf}\",[]]Ba[\"{{{AHOh{CGbAIMf}}AIMf}ICf}\",[]]Ba[\"{{{AHOh{CGbBCMj}}AHFf}ICf}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}DBn}{{AHOh{CGbBD@`}}}}\",[]]Bi[\"{{{AHOh{CGb}}}{{AHOh{CGbc}}}{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bc[\"{{AHOh{AHOh{CGbc}}}ICf{}}\",[\"T\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cc[\"{{{AHOh{CGbAILj}}NKdKGdKIf}{{KGh{ICfBBLf}}}}\",[]]A`[\"{AHBfDBn}\",[]]B`[\"{{AHOh{AHOh{c}}}DBn{}}\",[\"K\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Aa[\"{BCLjBFKj}\",[]]A`[\"{BEFhKId}\",[]]Aa[\"{BCLnBFKl}\",[]]A`[\"{BEFlKIf}\",[]]A`[\"{BFAnKIf}\",[]]A`[\"{BCO`KIf}\",[]]o[\"{NMnKIf}\",[]]Aa[\"{BCLjAIN`}\",[]]Aa[\"{BCLnAINb}\",[]]o[\"{KIdCN`}\",[]]o[\"{KIfCN`}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]Aj[\"{{{AHOh{BAOd}}}DBn}\",[]]Bd[\"{{{AHOh{BBL`}}}{{KGj{AJ@n}}}}\",[]]Bd[\"{{{AHOh{ABAd}}}{{KGj{AJ@n}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{BCMhCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BCMjCN`}\",[]]Cc[\"{{{AHOh{BCNb}}{AHOh{AJ@f}}CN`}{{A@d{AONh}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}DBn}{{AHOh{CGbBD@`}}}}\",[]]Bg[\"{{{AHOh{AILh}}KGb}{{KG`{AHFd}}}}\",[]]A`[\"{AHC`A@f}\",[]]Bj[\"{{{AHOh{CGbAILj}}KGd}{{KG`{AHFf}}}}\",[]]A`[\"{AHCbA@f}\",[]]Db[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]00Eg[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}{AHOh{{K@j{Oj}}}}}{{DAf{{KGh{KC`AJBd}}}}}}\",[]]Ec[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}{AHOh{{K@j{Oj}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]0Bm[\"{{{AHOh{IHh}}{AHOh{D@l}}}{{KGj{ICf}}}}\",[]]Cd[\"{{{AHOh{CGbAIOl}}KC`}{{KGh{{KG`{ICl}}AHFj}}}}\",[]]Cd[\"{{{AHOh{CGbBGAl}}KC`}{{KGh{{KG`{ICl}}AHFj}}}}\",[]]Cn[\"{{{AHOh{CGbAIOl}}{AHOh{CGb{K@j{Oj}}}}}{{KGh{ICfBC@f}}}}\",[]]Bj[\"{{{AHOh{D@n}}AIOb}{{KGh{ICfBFK`}}}}\",[]]Bn[\"{{{AHOh{CGbAIOf}}NKd}{{AHOh{CGbAIOf}}}}\",[]]Bn[\"{{{AHOh{CGbAIOh}}NKd}{{AHOh{CGbAIOh}}}}\",[]]A`[\"{BC@lAGb}\",[]]o[\"{IHfCN`}\",[]]o[\"{{}AJ@n}\",[]]0o[\"{{}AHOh}\",[]]Bk[\"{{ABAl{A@d{BABd}}}{{KGh{AILdBCM`}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bh[\"{{{AHOh{AHBf}}AJ@n}{{KGl{AHGd}}}}\",[]]A`[\"{AHFdCMl}\",[]]Aj[\"{{{AHOh{AILj}}}CMl}\",[]]A`[\"{AHFfCMl}\",[]]Ce[\"{{{AHOh{CGbAIOf}}{KG`{KI`}}}{{AHOh{CGbAIOf}}}}\",[]]Ce[\"{{{AHOh{CGbAIOh}}{KG`{KI`}}}{{AHOh{CGbAIOh}}}}\",[]]Aa[\"{ABEdAJ@n}\",[]]Aa[\"{ABEfAJ@n}\",[]]Aa[\"{ABEhAJ@n}\",[]]Aa[\"{AJ@nAHCl}\",[]]o[\"{AAlCMl}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMl}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}CMl}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHBfCMl}\",[]]Bo[\"{{{AHOh{CGbBCOn}}ABA`}{{AHOh{CGbBCOn}}}}\",[]]Bo[\"{{{AHOh{CGbBD@`}}ABA`}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHBfKG`}\",[]]k[\"{{}}\",[]]0000000000Bh[\"{ABAlc{}}\",[\"IntoFuture::IntoFuture\"]]11A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]o[\"{AAlKC`}\",[]]Ao[\"{{AHOhc}{{NKj{c}}}{}}\",[\"S\"]]0C`[\"{{{AHOh{CGbAILl}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bo[\"{{{AHOh{CGbCNh}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]C`[\"{{{AHOh{CGbAILn}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bo[\"{{{AHOh{CGbCNj}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bk[\"{{{AHOh{CGbIHh}}NKd{AHOh{BCNb}}}ICf}\",[]]A`[\"{BFBjKG`}\",[]]A`[\"{BFBlKG`}\",[]]Bn[\"{{{AHOh{KId}}{AHOh{KId}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KGb}}{AHOh{KGb}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AOL`}}{AHOh{AOL`}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{B@Mf}}{AHOh{B@Mf}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{DAj}}{AHOh{DAj}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{A@l}}{AHOh{A@l}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{ABD`}}{AHOh{ABD`}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KIf}}{AHOh{KIf}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BFDf}}{AHOh{BFDf}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KGd}}{AHOh{KGd}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AHFl}}{AHOh{AHFl}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BBBl}}{AHOh{BBBl}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AJBf}}{AHOh{AJBf}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AOLb}}{AHOh{AOLb}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BEGd}}{AHOh{BEGd}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BFCl}}{AHOh{BFCl}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{B@Mh}}{AHOh{B@Mh}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{DAl}}{AHOh{DAl}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{A@n}}{AHOh{A@n}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{ABDb}}{AHOh{ABDb}}}{{KG`{ABCf}}}}\",[]]Ak[\"{{{AHOh{AILh}}}AIO`}\",[]]Bk[\"{{{AHOh{AILj}}KGd}{{KGh{AIOdAIL`}}}}\",[]]Df[\"{{{AHOh{CGbAIOl}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{{KG`{KC`}}AHFj}}}}\",[]]Cc[\"{{{AHOh{CGbAIOl}}KC`}{{KGh{{ABj{Oj}}BC@h}}}}\",[]]Bb[\"{{{AHOh{CGbAILj}}ABDb}AIOn}\",[]]Aj[\"{{{AHOh{AHDd}}}KC`}\",[]]Aj[\"{{{AHOh{AHDf}}}KC`}\",[]]Bb[\"{{{AHOh{CGbAILj}}ABDb}AJ@j}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CN`}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}CN`}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHBfKG`}\",[]]A`[\"{BAOjKG`}\",[]]A`[\"{BAOlKG`}\",[]]Cf[\"{{{AHOh{CGbBABd}}{A@d{AJAf}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{AJAh}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kh}}{A@d{AJAn}}}{{AHOh{CGbB@Kh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kl}}{A@d{AJB`}}}{{AHOh{CGbB@Kl}}}}\",[]]o[\"{AAlCN`}\",[]]Bn[\"{{{AHOh{CGbBFIb}}CMl}{{AHOh{CGbBFIb}}}}\",[]]Bn[\"{{{AHOh{CGbBFId}}CMl}{{AHOh{CGbBFId}}}}\",[]]Ak[\"{{{AHOh{AILh}}}BGIl}\",[]]Aj[\"{{{AHOh{D@n}}}BCAf}\",[]]Aj[\"{{{A@d{BABf}}}BABd}\",[]]Aj[\"{{{A@d{BABj}}}BABh}\",[]]Aj[\"{{BCNlc}BCNlABDj}\",[\"\"]]Aj[\"{{BCNnc}BCNnABDj}\",[\"\"]]Bm[\"{{{AHOh{CGbAJ@h}}ICj}{{KGh{ICfAJBd}}}}\",[]]n[\"{{}KEn}\",[]]o[\"{NJ`NJ`}\",[]]0000Bd[\"{{{AHOh{BGOf}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BGOh}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BI@n}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BIAh}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{AILh}}}{{KG`{BCM`}}}}\",[]]Ck[\"{{{AHOh{ABAd}}B@KhAJ@n{AHOh{CMj}}}{{KGh{AILdB@M`}}}}\",[]]Ak[\"{{{AHOh{BAAl}}}ABA`}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]An[\"{{AIOjDBn}{{KGl{KC`}}}}\",[]]Cl[\"{{{AHOh{NMj}}}{{KG`{{KBn{{A@f{AHDd}}{A@f{AHEb}}}}}}}}\",[]]Cm[\"{{{AHOh{AJAj}}}{{KG`{{KBn{{A@f{AHDd}}{A@f{AHEb}}}}}}}}\",[]]Cl[\"{{{AHOh{NMl}}}{{KG`{{KBn{{A@f{AHDf}}{A@f{AHEd}}}}}}}}\",[]]Cm[\"{{{AHOh{AJAl}}}{{KG`{{KBn{{A@f{AHDf}}{A@f{AHEd}}}}}}}}\",[]]A`[\"{BGGjABj}\",[]]A`[\"{BIE`ABj}\",[]]A`[\"{BGGlABj}\",[]]A`[\"{BIEbABj}\",[]]An[\"{{{AHOh{CGbBGOf}}}B@Mf}\",[]]An[\"{{{AHOh{CGbBGOh}}}B@Mh}\",[]]An[\"{{{AHOh{CGbBI@n}}}B@Mh}\",[]]An[\"{{{AHOh{CGbBIAh}}}B@Mh}\",[]]Ak[\"{{{AHOh{BCAd}}}B@Oj}\",[]]Ba[\"{{{AHOh{CGbAILj}}BCMf}ICf}\",[]]Bo[\"{{{AHOh{CGbABAf}}BEGdBAOd}{{KG`{BCMf}}}}\",[]]B`[\"{{{AHOh{NMj}}B@MfDAj}D@b}\",[]]Bn[\"{{{AHOh{BABf}}CMnB@Mf}{{KGh{D@bBFLb}}}}\",[]]Ba[\"{{{AHOh{AJAj}}B@MfDAj}D@b}\",[]]Bn[\"{{{AHOh{BEJh}}CMnB@Mf}{{KGh{D@bBFLb}}}}\",[]]B`[\"{{{AHOh{NMl}}B@MhDAl}D@d}\",[]]Bn[\"{{{AHOh{BABj}}CMnB@Mh}{{KGh{D@dBFLh}}}}\",[]]Ba[\"{{{AHOh{AJAl}}B@MhDAl}D@d}\",[]]Bn[\"{{{AHOh{BEJj}}CMnB@Mh}{{KGh{D@dBFLh}}}}\",[]]Bn[\"{{{AHOh{BHKd}}CMnB@Md}{{KGh{D@dBFLh}}}}\",[]]Aj[\"{{}{{NMd{c}}}{}}\",[\"T\"]]0A`[\"{AHFdCN`}\",[]]A`[\"{BCMhCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BCMjCN`}\",[]]Bn[\"{{{AHOh{CGbBABd}}KC`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}KC`}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{BBL`}}}DBn}\",[]]0Aj[\"{{{AHOh{BCAd}}}DBn}\",[]]Bk[\"{{{AHOh{AILj}}KGd}{{KGh{AHClAIL`}}}}\",[]]Cc[\"{{{AHOh{BCNb}}{AHOh{AIOj}}CN`}{{A@d{AONh}}}}\",[]]Ak[\"{{{AHOh{ABAl}}}B@Mf}\",[]]Ak[\"{{{AHOh{ABAn}}}B@Mh}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bf[\"{{{AHOh{CGbAILj}}}{{KG`{NKd}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{A@d{AOLn}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{A@d{AOM`}}}{{AHOh{CGbBD@`}}}}\",[]]43A`[\"{AAlAOMf}\",[]]A`[\"{ABEdKG`}\",[]]A`[\"{ABEfKG`}\",[]]A`[\"{ABEhKG`}\",[]]A`[\"{BFBjKG`}\",[]]A`[\"{BFBlKG`}\",[]]Ai[\"{{{AHOh{NNj}}}KC`}\",[]]Bo[\"{{{AHOh{CGbBI@n}}ABA`}{{AHOh{CGbBI@n}}}}\",[]]Bo[\"{{{AHOh{CGbBIAh}}ABA`}{{AHOh{CGbBIAh}}}}\",[]]Bj[\"{{{AHOh{AJ@h}}CEl}{{KGh{ICfB@Ld}}}}\",[]]Bm[\"{{{AHOh{CGbAJ@j}}CEl}{{KGh{ICfB@Ll}}}}\",[]]?>A`[\"{IHfAONf}\",[]]A`[\"{AOJhIHf}\",[]]Bj[\"{{{A@d{B@Kf}}IHj}{{KGh{BEJdBGHj}}}}\",[]]Bj[\"{{{A@d{BABb}}IHj}{{KGh{BEJhBGHj}}}}\",[]]Bj[\"{{{A@d{B@Kf}}IHj}{{KGh{BEJfBGHl}}}}\",[]]Bj[\"{{{A@d{BABb}}IHj}{{KGh{BEJjBGHl}}}}\",[]]Co[\"{{{AHOh{CGbAJ@h}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{NOfAJBd}}}}\",[]]Co[\"{{{AHOh{CGbAJ@j}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{NOhAJBf}}}}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]A`[\"{AHBfDBn}\",[]]Cd[\"{{{AHOh{CGbBBMh}}{A@d{A`}}}{{AHOh{CGbBBMh}}}}\",[]]Cd[\"{{{AHOh{CGbBBMj}}{A@d{A`}}}{{AHOh{CGbBBMj}}}}\",[]]Bk[\"{{{AHOh{BBL`}}}{{ABd{{A@f{AHGb}}}}}}\",[]]o[\"{AAlCN`}\",[]]Aa[\"{AONfAHDh}\",[]]76Aa[\"{AJ@bABAl}\",[]]Aa[\"{AJ@dABAn}\",[]]Cf[\"{{{AHOh{CGbBFGd}}{KG`{ABA`}}}{{AHOh{CGbBFGd}}}}\",[]]Cf[\"{{{AHOh{CGbBFGf}}{KG`{ABA`}}}{{AHOh{CGbBFGf}}}}\",[]]9;:An[\"{{{AHOh{AONh}}ABA`}ICf}\",[]]B`[\"{{{AHOh{CGbAILl}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbCNh}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbIDd}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbNL`}}CMl}ICf}\",[]]B`[\"{{{AHOh{CGbAILn}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbCNj}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbIDf}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbNLb}}CMl}ICf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Bj[\"{{{AHOh{AILh}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Db[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]Db[\"{{{AHOh{CGbAILj}}NKdB@Oj{AHOh{CGb{ABj{Oj}}}}}{{KG`{ABEf}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{AHOh{CMj}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{AHOh{CMj}}}{{AHOh{CGbBD@`}}}}\",[]]Ak[\"{{{AHOh{AILh}}}BAA`}\",[]]Bj[\"{{{AHOh{AILh}}ICj}{{KGh{ICfBFDd}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}DBn}{{AHOh{CGbBD@`}}}}\",[]]Ai[\"{{{AHOh{NJn}}}KC`}\",[]]Ai[\"{{{AHOh{NK`}}}KC`}\",[]]Dh[\"{{{AHOh{B@Kj}}CMn{AHOh{CMj}}{AHOh{BGAj}}}{{KGh{{A@f{NMj}}B@M`}}}}\",[]]Cb[\"{{{AHOh{BABf}}CMn{AHOh{BGAj}}}{{A@f{NMj}}}}\",[]]Dh[\"{{{AHOh{BEJd}}CMn{AHOh{CMj}}{AHOh{BGAj}}}{{KGh{{A@f{NMj}}B@M`}}}}\",[]]Cb[\"{{{AHOh{BEJh}}CMn{AHOh{BGAj}}}{{A@f{NMj}}}}\",[]]Dh[\"{{{AHOh{B@Kn}}CMn{AHOh{CMj}}{AHOh{BGAj}}}{{KGh{{A@f{NMl}}B@Mb}}}}\",[]]Cb[\"{{{AHOh{BABj}}CMn{AHOh{BGAj}}}{{A@f{NMl}}}}\",[]]Dh[\"{{{AHOh{BEJf}}CMn{AHOh{CMj}}{AHOh{BGAj}}}{{KGh{{A@f{NMl}}B@Mb}}}}\",[]]Cb[\"{{{AHOh{BEJj}}CMn{AHOh{BGAj}}}{{A@f{NMl}}}}\",[]]Dh[\"{{{AHOh{BHKb}}CMn{AHOh{CMj}}{AHOh{BGAj}}}{{KGh{{A@f{NMl}}B@Ln}}}}\",[]]Cb[\"{{{AHOh{BHKd}}CMn{AHOh{BGAj}}}{{A@f{NMl}}}}\",[]]Dd[\"{{{ABd{{AHOh{CGbc}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{KGh}}}}}{}}\",[\"S\"]]0Bn[\"{{AJ@nBBLbAAl}{{KGl{{KBn{ABAbAILf}}}}}}\",[]]Bd[\"{{{AHOh{AILj}}}{{AHOh{NMl}}}}\",[]]A`[\"{AOJhIHf}\",[]]Cb[\"{{{AHOh{AOLn}}DAjAJ@nB@MfNKd}{{KG`{AIOf}}}}\",[]]Cb[\"{{{AHOh{BCNl}}DAjAJ@nB@MfNKd}{{KG`{AIOf}}}}\",[]]Cb[\"{{{AHOh{AOM`}}DAlAJ@nB@MhNKd}{{KG`{AIOh}}}}\",[]]Cb[\"{{{AHOh{BCNn}}DAlAJ@nB@MhNKd}{{KG`{AIOh}}}}\",[]]B`[\"{{{AHOh{CGbAILj}}NKd}ICf}\",[]]Ca[\"{{{AHOh{CGbAILd}}}{{KGh{{A@f{A@b}}BCM`}}}}\",[]]Bj[\"{{{AHOh{AILh}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAl}}}{{KG`{{A@f{A@b}}}}}}\",[]]o[\"{AIMdOj}\",[]]o[\"{AIMfOj}\",[]]Ai[\"{{{AHOh{CMj}}}DBn}\",[]]Aj[\"{{{AHOh{AILl}}}CN`}\",[]]Ai[\"{{{AHOh{CNh}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAIKb}}CN`}{{AHOh{CGbAIKb}}}}\",[]]Ai[\"{{{AHOh{IDd}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAOKf}}CN`}{{AHOh{CGbAOKf}}}}\",[]]Ai[\"{{{AHOh{NL`}}}CN`}\",[]]Bn[\"{{{AHOh{CGbBBAl}}CN`}{{AHOh{CGbBBAl}}}}\",[]]Aj[\"{{{AHOh{AILn}}}CN`}\",[]]Ai[\"{{{AHOh{CNj}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAIKd}}CN`}{{AHOh{CGbAIKd}}}}\",[]]Ai[\"{{{AHOh{IDf}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAOKh}}CN`}{{AHOh{CGbAOKh}}}}\",[]]Ai[\"{{{AHOh{NLb}}}CN`}\",[]]Bn[\"{{{AHOh{CGbBBAn}}CN`}{{AHOh{CGbBBAn}}}}\",[]]Aa[\"{AIOlBGAl}\",[]]Ai[\"{{{AHOh{NMj}}}DBn}\",[]]Aj[\"{{{AHOh{AJAj}}}DBn}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]Ai[\"{{{AHOh{NMl}}}DBn}\",[]]Aj[\"{{{AHOh{AJAl}}}DBn}\",[]]Co[\"{{{AHOh{NMj}}B@Mf{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]D`[\"{{{AHOh{AJAj}}B@Mf{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]Co[\"{{{AHOh{NMl}}B@Mh{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]D`[\"{{{AHOh{AJAl}}B@Mh{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBFIb}}CMl}{{AHOh{CGbBFIb}}}}\",[]]Bn[\"{{{AHOh{CGbBFId}}CMl}{{AHOh{CGbBFId}}}}\",[]]Cd[\"{{{AHOh{CGbNMj}}}{{KG`{{NKf{{A@f{AHEb}}}}}}}}\",[]]Ce[\"{{{AHOh{CGbAJAj}}}{{KG`{{NKf{{A@f{AHEb}}}}}}}}\",[]]Cd[\"{{{AHOh{CGbNMl}}}{{KG`{{NKh{{A@f{AHEd}}}}}}}}\",[]]Ce[\"{{{AHOh{CGbAJAl}}}{{KG`{{NKh{{A@f{AHEd}}}}}}}}\",[]]Bf[\"{{{AHOh{CGbAILl}}CMlCN`NKd}ICf}\",[]]Be[\"{{{AHOh{CGbCNh}}CMlCN`NKd}ICf}\",[]]Bf[\"{{{AHOh{CGbAILn}}CMlCN`NKd}ICf}\",[]]Be[\"{{{AHOh{CGbCNj}}CMlCN`NKd}ICf}\",[]]Bf[\"{{{AHOh{CGbAILl}}NKdCMlCN`}ICf}\",[]]Be[\"{{{AHOh{CGbCNh}}NKdCMlCN`}ICf}\",[]]Bf[\"{{{AHOh{CGbAILn}}NKdCMlCN`}ICf}\",[]]Be[\"{{{AHOh{CGbCNj}}NKdCMlCN`}ICf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]De[\"{{{AHOh{CGbBCOn}}c{AHOh{CMj}}}{{AHOh{CGbBCOn}}}{{ICh{D@l}}}}\",[\"\"]]De[\"{{{AHOh{CGbBD@`}}c{AHOh{CMj}}}{{AHOh{CGbBD@`}}}{{ICh{D@l}}}}\",[\"\"]]Ci[\"{{{AHOh{CGbNMj}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnIEf}}}}\",[]]Cj[\"{{{AHOh{CGbAJAj}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnIEf}}}}\",[]]Cj[\"{{{AHOh{CGbNMl}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnBCAb}}}}\",[]]Ck[\"{{{AHOh{CGbAJAl}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnBCAb}}}}\",[]]o[\"{AAlDBn}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KId}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}KIf}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHBfKG`}\",[]]Ca[\"{{{AHOh{CGbAIOl}}}{{KGh{{KG`{KId}}AJ@`}}}}\",[]]Ca[\"{{{AHOh{CGbBGAl}}}{{KGh{{KG`{KId}}AJ@`}}}}\",[]]Ca[\"{{{AHOh{CGbAIOn}}}{{KGh{{KG`{KIf}}B@Ll}}}}\",[]]Ak[\"{{{AHOh{AILd}}}AJ@n}\",[]]Ak[\"{{{AHOh{AILh}}}AJ@n}\",[]]Ak[\"{{{AHOh{ABAl}}}AJ@n}\",[]]Bg[\"{{{AHOh{D@n}}}{{KGh{AJ@nAIKj}}}}\",[]]Ak[\"{{{AHOh{ABAn}}}AJ@n}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]B`[\"{{KIdc}KId{{D@`{KId}}}}\",[\"\"]]B`[\"{{KGbc}KGb{{D@`{KGb}}}}\",[\"\"]]B`[\"{{KIfc}KIf{{D@`{KIf}}}}\",[\"\"]]B`[\"{{KGdc}KGd{{D@`{KGd}}}}\",[\"\"]]20Ae[\"{{ABA`CN`}AGb}\",[]]Bn[\"{{{AHOh{CGbBCOn}}AG`}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}AG`}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{IHfABA`}\",[]]B`[\"{{}{{AHOh{{K@j{BG@j}}}}}}\",[]]An[\"{{AHOh{OOb{CGbOj}}}ICf}\",[]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000An[\"{{}{{KG`{{A@d{NMh}}}}}}\",[]]Bn[\"{{{AHOh{CGbBBMh}}DBn}{{AHOh{CGbBBMh}}}}\",[]]Bn[\"{{{AHOh{CGbBBMj}}DBn}{{AHOh{CGbBBMj}}}}\",[]]Aj[\"{{{AHOh{AHEb}}}CN`}\",[]]Aj[\"{{{AHOh{AHEd}}}CN`}\",[]]A`[\"{ABClKG`}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Bf[\"{{{AHOh{CMj}}}{{KGl{CN`BBB`}}}}\",[]]Bn[\"{{{AHOh{ABAd}}{A@f{BBL`}}}{{KGj{ICf}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Cj[\"{{{AHOh{NMf}}BBLbBBBj{AHOh{AAl}}}{{KBn{AJ@nABAb}}}}\",[]]Cb[\"{{{AHOh{CGbAILj}}KGdAIOd}{{KGh{AIOdBFKb}}}}\",[]]Am[\"{{{AHOh{AILh}}CN`}ICf}\",[]]B`[\"{{{AHOh{CGbAILj}}CN`}ICf}\",[]]A`[\"{BC@jDBn}\",[]]B`[\"{{{AHOh{CGbIHf}}BC@l}ICf}\",[]]Aa[\"{AONfAHDh}\",[]]Bn[\"{{{AHOh{NMh}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Bo[\"{{{AHOh{BACb}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Bo[\"{{{AHOh{AOMl}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Ci[\"{{{AHOh{CGbNMj}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@b}}}}\",[]]Cj[\"{{{AHOh{CGbAJAj}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@b}}}}\",[]]Ci[\"{{{AHOh{CGbNMl}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@d}}}}\",[]]Cj[\"{{{AHOh{CGbAJAl}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@d}}}}\",[]]Cb[\"{{{AHOh{ABDl}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Cb[\"{{{AHOh{BANd}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Cb[\"{{{AHOh{B@Ol}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Cb[\"{{{AHOh{ABDn}}ICdAJAdABA`}{{KGh{ICfBCOj}}}}\",[]]Cb[\"{{{AHOh{BANf}}ICdAJAdABA`}{{KGh{ICfBCOj}}}}\",[]]Cb[\"{{{AHOh{B@On}}ICdAJAdABA`}{{KGh{ICfBCOj}}}}\",[]]Al[\"{{}{{KGh{B@KdBGHl}}}}\",[]]Bn[\"{{{AHOh{AILh}}KGb}{{KG`{{A@f{AILl}}}}}}\",[]]Bo[\"{{{AHOh{AILj}}KGd}{{KG`{{AHOh{AILn}}}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Aj[\"{{{AHOh{AILh}}}ICf}\",[]]Am[\"{{{AHOh{CGbAILj}}}ICf}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AAlIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{A@jIEj}}}}\",[]]Bg[\"{{{AHOh{AIJh}}}{{KGh{AB@bIEj}}}}\",[]]Bg[\"{{{AHOh{AIJh}}}{{KGh{AHBfIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AAnIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AB`IEj}}}}\",[]]Ak[\"{{{AHOh{BCAd}}}B@Oj}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{AOL`}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{KG`{AOLb}}}{{AHOh{CGbBD@`}}}}\",[]]<;Aj[\"{{{AHOh{ABAd}}}KC`}\",[]]Aj[\"{{{AHOh{ABAf}}}KC`}\",[]]Bc[\"{{{AHOh{AILh}}AJ@nAIOb}ABCd}\",[]]Co[\"{{{AHOh{CGbAILj}}AHClAIOdNKd}{{KGh{{KBn{KGdDBn}}AHEj}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}CMn}{{AHOh{CGbBD@`}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Bg[\"{{{AHOh{BCAd}}AJBb}{{KGj{KC`}}}}\",[]]A`[\"{AHBfCN`}\",[]]10Aj[\"{{{AHOh{AAl}}}BCOl}\",[]]Cf[\"{{{AHOh{CGbBABd}}{A@d{BCOn}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kh}}{A@d{BCOn}}}{{AHOh{CGbB@Kh}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{BD@`}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kl}}{A@d{BD@`}}}{{AHOh{CGbB@Kl}}}}\",[]]Aa[\"{BABdBH@h}\",[]]Aa[\"{BABhBH@j}\",[]]Bj[\"{{{ABj{BBLb}}BBBj}{{KGh{BABdIEn}}}}\",[]]Bj[\"{{{ABj{BBLb}}BBBj}{{KGh{BABhIF`}}}}\",[]]Co[\"{{{AHOh{CGbAJ@h}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{ICfAJBd}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BFBjCN`}\",[]]A`[\"{BFBlCN`}\",[]]Bc[\"{{{AHOh{AILh}}}{{KG`{KC`}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Aj[\"{{{AHOh{AHBl}}}KC`}\",[]]Be[\"{{{AHOh{ABAd}}{KG`{BABd}}}ICf}\",[]]Bo[\"{{{AHOh{CGbABAf}}{KG`{{A@d{BABh}}}}}ICf}\",[]]Bd[\"{{{AHOh{BG@j}}}{{KG`{BBBh}}}}\",[]]o[\"{{}AHOh}\",[]]n[\"{{}NJ`}\",[]]0000Bn[\"{{{AHOh{CGbBCOn}}KC`}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}KC`}{{AHOh{CGbBD@`}}}}\",[]]o[\"{CN`KId}\",[]]o[\"{CN`KIf}\",[]]A`[\"{BAOfCN`}\",[]]Bf[\"{{{AHOh{BGIl}}{AHOh{BGIl}}}DBn}\",[]]Bo[\"{{{AHOh{CGbBBMh}}ABA`}{{AHOh{CGbBBMh}}}}\",[]]Bo[\"{{{AHOh{CGbBBMj}}ABA`}{{AHOh{CGbBBMj}}}}\",[]]Ae[\"{{KC`CN`}BANd}\",[]]Ae[\"{{KC`CN`}BANf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]7Bg[\"{{{AHOh{AILj}}KGd}{{KG`{AIOd}}}}\",[]]An[\"{{{AHOh{AILh}}ICj}BAAn}\",[]]Bm[\"{{{AHOh{CGbBEJd}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJh}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJf}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJj}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Am[\"{{{AHOh{AILh}}KId}ICf}\",[]]B`[\"{{{AHOh{CGbAILj}}KIf}ICf}\",[]]Ce[\"{{{AHOh{CGbBBMh}}{ABj{CMn}}}{{AHOh{CGbBBMh}}}}\",[]]Ce[\"{{{AHOh{CGbBBMj}}{ABj{CMn}}}{{AHOh{CGbBBMj}}}}\",[]]Fg[\"{{{AHOh{BHEb}}{AHOh{BBLb}}{AHOh{{K@j{BBLb}}}}{AHOh{AJ@l}}{AHOh{{K@j{Oj}}}}ABEn}{{KGh{BFJlIEh}}}}\",[]]Af[\"{{BCNlNKd}BCNl}\",[]]Af[\"{{BCNnNKd}BCNn}\",[]]A`[\"{BAOfCN`}\",[]]Al[\"{BACd{{KGh{DAjIEl}}}}\",[]]Al[\"{BACd{{KGh{A@lIEl}}}}\",[]]Ai[\"{BACd{{KGn{DAl}}}}\",[]]Ai[\"{BACd{{KGn{A@n}}}}\",[]]o[\"{NJ`NJ`}\",[]]Bo[\"{{{AHOh{CGbBFIb}}ABA`}{{AHOh{CGbBFIb}}}}\",[]]Bo[\"{{{AHOh{CGbBFId}}ABA`}{{AHOh{CGbBFId}}}}\",[]]Bb[\"{{{AHOh{NMj}}}{{KG`{DBn}}}}\",[]]Bc[\"{{{AHOh{AJAj}}}{{KG`{DBn}}}}\",[]]Bb[\"{{{AHOh{NMl}}}{{KG`{DBn}}}}\",[]]Bc[\"{{{AHOh{AJAl}}}{{KG`{DBn}}}}\",[]]Bg[\"{{{AHOh{AILh}}}{{KGh{ICfBCM`}}}}\",[]]Ba[\"{{{AHOh{BFCf}}KGbAHCl}DBn}\",[]]Ba[\"{{{AHOh{BFCh}}KGdAHCl}DBn}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{ABA`}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{KG`{ABA`}}}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Bo[\"{{{AHOh{CGbAILl}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbCNh}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbIDd}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbNL`}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bo[\"{{{AHOh{CGbAILn}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbCNj}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbIDf}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbNLb}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]A`[\"{BAOfCN`}\",[]]Al[\"{{{AHOh{NNj}}A@n}CN`}\",[]]Bi[\"{{{AHOh{CGbAJ@f}}CN`}{{KGl{ICf}}}}\",[]]<;A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Cf[\"{{{AHOh{CGbBCOn}}{KG`{BFGd}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{KG`{BFGf}}}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AAlIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{A@jIEj}}}}\",[]]Bj[\"{{{AHOh{CGbAIJh}}}{{KGh{AB@bIEj}}}}\",[]]Bj[\"{{{AHOh{CGbAIJh}}}{{KGh{AHBfIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AAnIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AB`IEj}}}}\",[]]Cd[\"{{{A@d{AILf}}CN`DBn}{{KGl{{KBn{BC@lBC@l}}}}}}\",[]]Bn[\"{{{AHOh{CGbBABd}}CN`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}CN`}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{AILh}}}DBn}\",[]]Ak[\"{{{AHOh{BBL`}}}B@Oj}\",[]]0Ci[\"{{{AHOh{CGbBBMh}}CMl}{{KGh{{AHOh{CGbBBMh}}AOJl}}}}\",[]]Ci[\"{{{AHOh{CGbBBMj}}CMl}{{KGh{{AHOh{CGbBBMj}}AOJn}}}}\",[]]A`[\"{AHBfCMl}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{BFIb}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{KG`{BFId}}}{{AHOh{CGbBD@`}}}}\",[]]Bg[\"{{{AHOh{CGbAILj}}}{{KG`{BAOd}}}}\",[]]Cf[\"{{{AHOh{CGbBABd}}{KG`{BABl}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{KG`{BABl}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbBABd}}{KG`{BABn}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{KG`{BABn}}}{{AHOh{CGbBABh}}}}\",[]]Cd[\"{{}{{KGh{{KBn{{ABj{BBLb}}BBBj}}{A@f{IE`}}}}}}\",[]]Bn[\"{{{AHOh{CGbBFGd}}KId}{{AHOh{CGbBFGd}}}}\",[]]Bn[\"{{{AHOh{CGbBFGf}}KIf}{{AHOh{CGbBFGf}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bo[\"{{{AHOh{CGbBABd}}ABA`}{{AHOh{CGbBABd}}}}\",[]]Bo[\"{{{AHOh{CGbBABh}}ABA`}{{AHOh{CGbBABh}}}}\",[]]Ci[\"{{{AHOh{D@n}}{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIKj}}}}\",[]]Bj[\"{{{AHOh{BCAd}}AJBbKC`}{{KGj{ICf}}}}\",[]]054Bm[\"{{{AHOh{NMj}}}{{KGh{{KG`{BGAj}}IEf}}}}\",[]]Bn[\"{{{AHOh{AJAj}}}{{KGh{{KG`{BGAj}}IEf}}}}\",[]]Bn[\"{{{AHOh{NMl}}}{{KGh{{KG`{BGAj}}BCAb}}}}\",[]]Bo[\"{{{AHOh{AJAl}}}{{KGh{{KG`{BGAj}}BCAb}}}}\",[]]Aj[\"{{{AHOh{AHEb}}}CN`}\",[]]Aj[\"{{{AHOh{AHEd}}}CN`}\",[]]Bl[\"{{{AHOh{ABAd}}{KG`{{A@d{BFCf}}}}}ICf}\",[]]Cc[\"{{{AHOh{CGbAILj}}{KG`{{AHOh{BFCh}}}}NKd}ICf}\",[]]Aj[\"{{{AHOh{ABAf}}}CN`}\",[]]Bf[\"{{{AHOh{AHCl}}{AHOh{AHCl}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBBAl}}AG`}{{AHOh{CGbBBAl}}}}\",[]]Bn[\"{{{AHOh{CGbBBAn}}AG`}{{AHOh{CGbBBAn}}}}\",[]]Ak[\"{{{AHOh{AHGb}}}B@Oj}\",[]]0Ak[\"{{{AHOh{AILh}}}BG@l}\",[]]Cb[\"{{{AHOh{AILj}}KGd}{{KGh{{KG`{AJ@n}}AIL`}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KId}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}KIf}{{AHOh{CGbBD@`}}}}\",[]]A`[\"{AHBfKG`}\",[]]Bo[\"{{{AHOh{AHBf}}{AHOh{CMj}}}{{KGj{BCOl}}}}\",[]]Em[\"{{{AHOh{AILh}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLn}}}}\",[]]El[\"{{{AHOh{NMj}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLn}}}}\",[]]Em[\"{{{AHOh{AJAj}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLn}}}}\",[]]El[\"{{{AHOh{NMl}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHM`}}}}\",[]]Em[\"{{{AHOh{AJAl}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHM`}}}}\",[]]Am[\"{{{AHOh{CGbAHBj}}}ICf}\",[]]0Am[\"{{{AHOh{AILj}}A@n}CN`}\",[]]Ak[\"{{{AHOh{AILh}}}BGHn}\",[]]Bg[\"{{{AHOh{D@n}}}{{KGh{BEFdAIKj}}}}\",[]]>=E`[\"{{{AHOh{BHEb}}{AHOh{{K@j{Oj}}}}{AHOh{BBLb}}{AHOh{BGOj}}}{{KGh{BHGhIEh}}}}\",[]]0Bg[\"{{{A@d{BBCb}}}{{KGh{B@KhBGIj}}}}\",[]]Bg[\"{{{A@d{BBCb}}}{{KGh{B@KlBGIj}}}}\",[]]Bn[\"{{{AHOh{CGbBFGd}}KId}{{AHOh{CGbBFGd}}}}\",[]]Bn[\"{{{AHOh{CGbBFGf}}KIf}{{AHOh{CGbBFGf}}}}\",[]]o[\"{NJ`NJ`}\",[]]0000Aj[\"{{{AHOh{AILj}}}DBn}\",[]]0Bd[\"{{{AHOh{CGbAILl}}CN`ABA`}ICf}\",[]]Bc[\"{{{AHOh{CGbCNh}}CN`ABA`}ICf}\",[]]Bd[\"{{{AHOh{CGbAILn}}CN`ABA`}ICf}\",[]]Bc[\"{{{AHOh{CGbCNj}}CN`ABA`}ICf}\",[]]Ci[\"{{{AHOh{D@n}}{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIKj}}}}\",[]]Cd[\"{{{AHOh{CGbAAl}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbA@j}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Ce[\"{{{AHOh{CGbAB@b}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Ce[\"{{{AHOh{CGbAHBf}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbAAn}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbAB`}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Bo[\"{{{AHOh{CGbBABd}}BH@h}{{AHOh{CGbBABd}}}}\",[]]Bo[\"{{{AHOh{CGbBABh}}BH@j}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{BBMh}}}CN`}\",[]]Aj[\"{{{AHOh{BBMj}}}CN`}\",[]]Cd[\"{{{AHOh{CGbB@Kh}}{A@d{A`}}}{{AHOh{CGbB@Kh}}}}\",[]]Cd[\"{{{AHOh{CGbB@Kl}}{A@d{A`}}}{{AHOh{CGbB@Kl}}}}\",[]]Cl[\"{{BBMh{KG`{BABd}}{A@f{BBL`}}{A@d{NMh}}}{{KGj{ABAd}}}}\",[]]Aj[\"{{{AHOh{ABAl}}}DBn}\",[]]Aj[\"{{{AHOh{ABAn}}}DBn}\",[]]Ca[\"{{{AHOh{CGbAILj}}NKdAINf}{{KGh{ICfBHDh}}}}\",[]]Bd[\"{{{AHOh{BHEb}}}{{ABj{BCOd}}}}\",[]]Bj[\"{{{AHOh{AILh}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bm[\"{{{AHOh{CGbAILj}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KC`}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}KC`}{{AHOh{CGbBD@`}}}}\",[]]Bm[\"{{}{{KGh{{KBn{BBLbBFIn}}{A@f{IE`}}}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]An[\"{{{AHOh{ABAd}}B@Kh}ICf}\",[]]Dc[\"{{{AHOh{CGbAILj}}NKdKGd{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIL`}}}}\",[]]o[\"{{}AHOh}\",[]]Aj[\"{{{AHOh{AILh}}}KC`}\",[]]Bn[\"{{{AHOh{CGbBABd}}CN`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}CN`}{{AHOh{CGbBABh}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KId}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}KIf}{{AHOh{CGbBD@`}}}}\",[]]:Bc[\"{{{AHOh{CGbAILj}}A@nKIf}ICf}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Ak[\"{{}{{KGh{B@KhIEn}}}}\",[]]Ak[\"{{}{{KGh{B@KlIF`}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}DBn}{{AHOh{CGbBD@`}}}}\",[]]87Cg[\"{{{AHOh{CGbAAl}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbA@j}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Ch[\"{{{AHOh{CGbAB@b}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Ch[\"{{{AHOh{CGbAHBf}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbAAn}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbAB`}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAHCl}}{AHOh{AHCl}}}DBn}\",[]]n[\"{{}ICf}\",[]]Ce[\"{{{AHOh{CGbBCOn}}{KG`{KC`}}}{{AHOh{CGbBCOn}}}}\",[]]Ce[\"{{{AHOh{CGbBD@`}}{KG`{KC`}}}{{AHOh{CGbBD@`}}}}\",[]]Bn[\"{{{AHOh{AILh}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Cd[\"{{{AHOh{CGbAILj}}NKd}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Am[\"{{{AHOh{CGbAILl}}}ICf}\",[]]Al[\"{{{AHOh{CGbCNh}}}ICf}\",[]]Al[\"{{{AHOh{CGbIDd}}}ICf}\",[]]Am[\"{{{AHOh{CGbAILn}}}ICf}\",[]]Al[\"{{{AHOh{CGbCNj}}}ICf}\",[]]Al[\"{{{AHOh{CGbIDf}}}ICf}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Bj[\"{{{AHOh{AILh}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bm[\"{{{AHOh{CGbAILj}}AJ@n}{{KGh{ICfIFd}}}}\",[]]D`[\"{{{AHOh{CGbAILj}}KGd{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIL`}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{A@d{BFBf}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{A@d{BFBh}}}{{AHOh{CGbBD@`}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{ABA`}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBD@`}}{KG`{ABA`}}}{{AHOh{CGbBD@`}}}}\",[]]Ce[\"{{{AHOh{CGbBCOn}}{KG`{CN`}}}{{AHOh{CGbBCOn}}}}\",[]]Ce[\"{{{AHOh{CGbBD@`}}{KG`{CN`}}}{{AHOh{CGbBD@`}}}}\",[]]Aa[\"{BAOjAINd}\",[]]Aa[\"{BAOlAINd}\",[]];Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}DBn}{{AHOh{CGbBD@`}}}}\",[]]Am[\"{{{AHOh{AILh}}KId}ICf}\",[]]o[\"{NJ`NJ`}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMn}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{CGbBD@`}}CMn}{{AHOh{CGbBD@`}}}}\",[]]310;:54Bn[\"{{{AHOh{AILh}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Bn[\"{{{AHOh{AILj}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]10A`[\"{BGAjKG`}\",[]]Bm[\"{{{AHOh{CGbBCOn}}Oj}{{AHOh{CGbBCOn}}}}\",[]]Bm[\"{{{AHOh{CGbBD@`}}Oj}{{AHOh{CGbBD@`}}}}\",[]]o[\"{{}AINf}\",[]]") \ No newline at end of file diff --git a/pr/619/docs/search.index/function/c7020792e5cc.js b/pr/619/docs/search.index/function/c7020792e5cc.js new file mode 100644 index 000000000..440c56769 --- /dev/null +++ b/pr/619/docs/search.index/function/c7020792e5cc.js @@ -0,0 +1 @@ +rd_("Bf[\"{{{AHOh{AOJf}}{AHOh{AOJf}}}DBn}\",[]]Bf[\"{{{AHOh{BFDb}}{AHOh{BFDb}}}DBn}\",[]]Bd[\"{{{AHOh{KF`}}{AHOh{KF`}}}DBn}\",[]]Bd[\"{{{AHOh{D@n}}{AHOh{D@n}}}DBn}\",[]]Bf[\"{{{AHOh{BCAf}}{AHOh{BCAf}}}DBn}\",[]]Bf[\"{{{AHOh{BC@h}}{AHOh{BC@h}}}DBn}\",[]]Bf[\"{{{AHOh{AHFj}}{AHOh{AHFj}}}DBn}\",[]]Bf[\"{{{AHOh{AJ@`}}{AHOh{AJ@`}}}DBn}\",[]]Bf[\"{{{AHOh{BC@f}}{AHOh{BC@f}}}DBn}\",[]]Bf[\"{{{AHOh{AJBd}}{AHOh{AJBd}}}DBn}\",[]]Bf[\"{{{AHOh{BAC`}}{AHOh{BAC`}}}DBn}\",[]]Bd[\"{{{AHOh{KId}}{AHOh{KId}}}DBn}\",[]]Bf[\"{{{AHOh{BGId}}{AHOh{BGId}}}DBn}\",[]]Bd[\"{{{AHOh{ICl}}{AHOh{ICl}}}DBn}\",[]]Bd[\"{{{AHOh{KGb}}{AHOh{KGb}}}DBn}\",[]]Bf[\"{{{AHOh{AIOb}}{AHOh{AIOb}}}DBn}\",[]]Bf[\"{{{AHOh{AHF`}}{AHOh{AHF`}}}DBn}\",[]]Bf[\"{{{AHOh{BFJn}}{AHOh{BFJn}}}DBn}\",[]]Bf[\"{{{AHOh{AIKj}}{AHOh{AIKj}}}DBn}\",[]]Bf[\"{{{AHOh{ABEj}}{AHOh{ABEj}}}DBn}\",[]]Bf[\"{{{AHOh{AIMd}}{AHOh{AIMd}}}DBn}\",[]]Bf[\"{{{AHOh{AHFd}}{AHOh{AHFd}}}DBn}\",[]]Bd[\"{{{AHOh{NOf}}{AHOh{NOf}}}DBn}\",[]]Bf[\"{{{AHOh{B@Ld}}{AHOh{B@Ld}}}DBn}\",[]]Bf[\"{{{AHOh{BCLn}}{AHOh{BCLn}}}DBn}\",[]]Bf[\"{{{AHOh{AHEh}}{AHOh{AHEh}}}DBn}\",[]]Bf[\"{{{AHOh{BBLd}}{AHOh{BBLd}}}DBn}\",[]]Bf[\"{{{AHOh{AOL`}}{AHOh{AOL`}}}DBn}\",[]]Bf[\"{{{AHOh{AOJl}}{AHOh{AOJl}}}DBn}\",[]]Bf[\"{{{AHOh{AHCn}}{AHOh{AHCn}}}DBn}\",[]]Bf[\"{{{AHOh{BCLh}}{AHOh{BCLh}}}DBn}\",[]]Bf[\"{{{AHOh{BEFf}}{AHOh{BEFf}}}DBn}\",[]]Bf[\"{{{AHOh{B@M`}}{AHOh{B@M`}}}DBn}\",[]]Bf[\"{{{AHOh{B@Mf}}{AHOh{B@Mf}}}DBn}\",[]]Bf[\"{{{AHOh{B@N`}}{AHOh{B@N`}}}DBn}\",[]]Bf[\"{{{AHOh{BFKh}}{AHOh{BFKh}}}DBn}\",[]]Bd[\"{{{AHOh{DAj}}{AHOh{DAj}}}DBn}\",[]]Bd[\"{{{AHOh{A@l}}{AHOh{A@l}}}DBn}\",[]]Bf[\"{{{AHOh{ABD`}}{AHOh{ABD`}}}DBn}\",[]]Bf[\"{{{AHOh{BHLl}}{AHOh{BHLl}}}DBn}\",[]]Bd[\"{{{AHOh{IEn}}{AHOh{IEn}}}DBn}\",[]]Bd[\"{{{AHOh{KIf}}{AHOh{KIf}}}DBn}\",[]]Bf[\"{{{AHOh{BGIf}}{AHOh{BGIf}}}DBn}\",[]]Bd[\"{{{AHOh{ICn}}{AHOh{ICn}}}DBn}\",[]]Bf[\"{{{AHOh{BFDd}}{AHOh{BFDd}}}DBn}\",[]]Bd[\"{{{AHOh{KGd}}{AHOh{KGd}}}DBn}\",[]]Bf[\"{{{AHOh{AIOd}}{AHOh{AIOd}}}DBn}\",[]]Bf[\"{{{AHOh{AHFb}}{AHOh{AHFb}}}DBn}\",[]]Bf[\"{{{AHOh{BFD`}}{AHOh{BFD`}}}DBn}\",[]]Bf[\"{{{AHOh{BFK`}}{AHOh{BFK`}}}DBn}\",[]]Bf[\"{{{AHOh{AIL`}}{AHOh{AIL`}}}DBn}\",[]]Bf[\"{{{AHOh{ABEl}}{AHOh{ABEl}}}DBn}\",[]]Bf[\"{{{AHOh{AIMf}}{AHOh{AIMf}}}DBn}\",[]]Bf[\"{{{AHOh{AHFf}}{AHOh{AHFf}}}DBn}\",[]]Bf[\"{{{AHOh{AHFl}}{AHOh{AHFl}}}DBn}\",[]]Bf[\"{{{AHOh{BBBl}}{AHOh{BBBl}}}DBn}\",[]]Bd[\"{{{AHOh{NOh}}{AHOh{NOh}}}DBn}\",[]]Bf[\"{{{AHOh{AJBf}}{AHOh{AJBf}}}DBn}\",[]]Bf[\"{{{AHOh{AOKn}}{AHOh{AOKn}}}DBn}\",[]]Bf[\"{{{AHOh{AONd}}{AHOh{AONd}}}DBn}\",[]]Bf[\"{{{AHOh{BC@j}}{AHOh{BC@j}}}DBn}\",[]]Bf[\"{{{AHOh{B@Ll}}{AHOh{B@Ll}}}DBn}\",[]]Bf[\"{{{AHOh{BCM`}}{AHOh{BCM`}}}DBn}\",[]]Bf[\"{{{AHOh{AHEj}}{AHOh{AHEj}}}DBn}\",[]]Bf[\"{{{AHOh{BBLf}}{AHOh{BBLf}}}DBn}\",[]]Bf[\"{{{AHOh{AOLb}}{AHOh{AOLb}}}DBn}\",[]]Bf[\"{{{AHOh{AOJn}}{AHOh{AOJn}}}DBn}\",[]]Bf[\"{{{AHOh{AHD`}}{AHOh{AHD`}}}DBn}\",[]]Bf[\"{{{AHOh{BBNd}}{AHOh{BBNd}}}DBn}\",[]]Bf[\"{{{AHOh{AINb}}{AHOh{AINb}}}DBn}\",[]]Bf[\"{{{AHOh{AJA`}}{AHOh{AJA`}}}DBn}\",[]]Bf[\"{{{AHOh{B@Mj}}{AHOh{B@Mj}}}DBn}\",[]]Bf[\"{{{AHOh{BCLl}}{AHOh{BCLl}}}DBn}\",[]]Bf[\"{{{AHOh{BEFj}}{AHOh{BEFj}}}DBn}\",[]]Bf[\"{{{AHOh{BEGb}}{AHOh{BEGb}}}DBn}\",[]]Bf[\"{{{AHOh{B@Mb}}{AHOh{B@Mb}}}DBn}\",[]]Bf[\"{{{AHOh{ABBd}}{AHOh{ABBd}}}DBn}\",[]]Bf[\"{{{AHOh{BFCj}}{AHOh{BFCj}}}DBn}\",[]]Bf[\"{{{AHOh{B@Mh}}{AHOh{B@Mh}}}DBn}\",[]]Bf[\"{{{AHOh{B@Nb}}{AHOh{B@Nb}}}DBn}\",[]]Bf[\"{{{AHOh{BCAb}}{AHOh{BCAb}}}DBn}\",[]]Bf[\"{{{AHOh{BFKj}}{AHOh{BFKj}}}DBn}\",[]]Bd[\"{{{AHOh{DAl}}{AHOh{DAl}}}DBn}\",[]]Bd[\"{{{AHOh{A@n}}{AHOh{A@n}}}DBn}\",[]]Bf[\"{{{AHOh{ABDb}}{AHOh{ABDb}}}DBn}\",[]]Bf[\"{{{AHOh{AHCl}}{AHOh{AHCl}}}DBn}\",[]]Bf[\"{{{AHOh{BBCh}}{AHOh{BBCh}}}DBn}\",[]]Bf[\"{{{AHOh{BGAh}}{AHOh{BGAh}}}DBn}\",[]]Bd[\"{{{AHOh{IFb}}{AHOh{IFb}}}DBn}\",[]]Bf[\"{{{AHOh{BHLn}}{AHOh{BHLn}}}DBn}\",[]]Bd[\"{{{AHOh{IF`}}{AHOh{IF`}}}DBn}\",[]]Bf[\"{{{AHOh{B@Nd}}{AHOh{B@Nd}}}DBn}\",[]]Ai[\"{{{AHOh{D@n}}}KGb}\",[]]Aj[\"{{{AHOh{BCAf}}}KGb}\",[]]Ak[\"{{{AHOh{AIOl}}}ABD`}\",[]]Ak[\"{{{AHOh{BGAj}}}ABD`}\",[]]Ak[\"{{{AHOh{AJ@h}}}ABD`}\",[]]o[\"{KFdKGb}\",[]]A`[\"{AH@jKGb}\",[]]A`[\"{AHC`KGb}\",[]]A`[\"{BAAbKGb}\",[]]A`[\"{BA@`KGb}\",[]]o[\"{KFfKGd}\",[]]A`[\"{AH@lKGd}\",[]]A`[\"{AHCbKGd}\",[]]A`[\"{BAAdKGd}\",[]]A`[\"{BA@bKGd}\",[]]Aa[\"{ABChABDb}\",[]]Aa[\"{ABF`ABDb}\",[]]Aa[\"{ABAhABDb}\",[]]A`[\"{NMnABDb}\",[]]A`[\"{AOMfNMf}\",[]]A`[\"{D@fABBd}\",[]]Ac[\"{{ABEjABEj}}\",[]]Ac[\"{{AIMdAIMd}}\",[]]Ac[\"{{BCMfAHFd}}\",[]]Bc[\"{{ABElABEl}c{}}\",[\"Add::Output\"]]Bc[\"{{AIMfAIMf}c{}}\",[\"Add::Output\"]]Bc[\"{{BCMhAHFf}c{}}\",[\"Add::Output\"]]Be[\"{{{AHOh{KId}}{AHOh{KId}}}ABCf}\",[]]Be[\"{{{AHOh{KGb}}{AHOh{KGb}}}ABCf}\",[]]Bg[\"{{{AHOh{AOL`}}{AHOh{AOL`}}}ABCf}\",[]]Bg[\"{{{AHOh{B@Mf}}{AHOh{B@Mf}}}ABCf}\",[]]Be[\"{{{AHOh{DAj}}{AHOh{DAj}}}ABCf}\",[]]Be[\"{{{AHOh{A@l}}{AHOh{A@l}}}ABCf}\",[]]Bg[\"{{{AHOh{ABD`}}{AHOh{ABD`}}}ABCf}\",[]]Be[\"{{{AHOh{KIf}}{AHOh{KIf}}}ABCf}\",[]]Bg[\"{{{AHOh{BFDd}}{AHOh{BFDd}}}ABCf}\",[]]Be[\"{{{AHOh{KGd}}{AHOh{KGd}}}ABCf}\",[]]Bg[\"{{{AHOh{AHFl}}{AHOh{AHFl}}}ABCf}\",[]]Bg[\"{{{AHOh{BBBl}}{AHOh{BBBl}}}ABCf}\",[]]Bg[\"{{{AHOh{AJBf}}{AHOh{AJBf}}}ABCf}\",[]]Bg[\"{{{AHOh{AOLb}}{AHOh{AOLb}}}ABCf}\",[]]Bg[\"{{{AHOh{BEGb}}{AHOh{BEGb}}}ABCf}\",[]]Bg[\"{{{AHOh{BFCj}}{AHOh{BFCj}}}ABCf}\",[]]Bg[\"{{{AHOh{B@Mh}}{AHOh{B@Mh}}}ABCf}\",[]]Be[\"{{{AHOh{DAl}}{AHOh{DAl}}}ABCf}\",[]]Be[\"{{{AHOh{A@n}}{AHOh{A@n}}}ABCf}\",[]]Bg[\"{{{AHOh{ABDb}}{AHOh{ABDb}}}ABCf}\",[]]A`[\"{ABD`A@l}\",[]]A`[\"{ABDbA@n}\",[]]o[\"{KFhA@n}\",[]]A`[\"{AHAlA@n}\",[]]A`[\"{ABEdKG`}\",[]]A`[\"{ABEfKG`}\",[]]A`[\"{ABClKG`}\",[]]A`[\"{ABEhKG`}\",[]]Bh[\"{{{AHOh{AAl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOMf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOJf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BC@l}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BHE`}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BGHl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AILd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AILh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BGIj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFDb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{ABAd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BAOf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{KF`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AIO`}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BG@j}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABAl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AJ@b}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBNb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{D@n}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCAf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AIOl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BGAj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BC@h}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AHFj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AJ@`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BC@f}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BACb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOMl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AJ@h}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AJBd}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BAC`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{NNb}}{AHOh{CGbAHCj}}}KGf}\",[]]Cd[\"{{{AHOh{KId}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BGId}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Cd[\"{{{AHOh{ICl}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{KGb}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{AIOb}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AHF`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BFJn}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{AIKj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{ABEj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AIMd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AHFd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BCMf}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{NOf}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{B@Ld}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BCLn}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{AHEh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BBLd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BCNj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BCOl}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BFGb}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BFI`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AOL`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BBMh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BABd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BH@f}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{B@Kh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AOJl}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{AHCn}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BCLh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BEFf}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{B@M`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{B@Mf}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{B@N`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BFKh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{AIMj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BEJj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{DAj}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{A@l}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{ABD`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{ABEd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{CNh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AIKb}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{IDd}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AOKf}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{NL`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BBAl}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BHLl}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{AOKb}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Ce[\"{{{AHOh{BFL`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]Cd[\"{{{AHOh{IEn}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Ce[\"{{{AHOh{BGHh}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Bi[\"{{{AHOh{AILj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABAf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{KIf}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BGIf}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{ICn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFDd}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{KGd}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BAAl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AIOd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AHFb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFD`}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFK`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AIL`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{ABEl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AIMf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AHFf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCMh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AHFl}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBBl}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{NOh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AJBf}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AOKn}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AONd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BC@j}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{B@Ll}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BCM`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AHEj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBLf}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BHDf}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{IFh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCNl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCOn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFGd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFIb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOLb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BBMj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BABh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BH@h}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{B@Kl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOJn}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AHD`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBNd}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AINb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AJA`}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{B@Mj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BCLl}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BEFj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AB@h}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BEGb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABAn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{B@Mb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AOJb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AJ@d}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBBb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCNh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BHDn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABBd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFCj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BCMd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BAOd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{B@Mh}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{B@Nb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCAb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BFKj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{AIMl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BIAf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BEJl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{DAl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{A@n}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{ABDb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{ABEf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AHCl}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BBCh}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BGAh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{IFb}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bi[\"{{{AHOh{BHLn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOKd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BFLf}}{AHOh{CGbAHCj}}}KGf}\",[]]Cd[\"{{{AHOh{IF`}}{AHOh{CGbAHCj}}}{{KGh{ICfIDn}}}}\",[]]0Bi[\"{{{AHOh{BGHj}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{CNj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AIKd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{IDf}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{AOKh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{NLb}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BBAn}}{AHOh{CGbAHCj}}}KGf}\",[]]Bh[\"{{{AHOh{IFd}}{AHOh{CGbAHCj}}}KGf}\",[]]0Bh[\"{{{AHOh{IFj}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{BCAd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABCl}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{ABEh}}{AHOh{CGbAHCj}}}KGf}\",[]]Bi[\"{{{AHOh{B@Nd}}{AHOh{CGbAHCj}}}KGf}\",[]]Bd[\"{{{AHOh{BGHl}}}{{KG`{AJ@n}}}}\",[]]Ak[\"{{{AHOh{BAAl}}}ABA`}\",[]]A`[\"{ABEjCN`}\",[]]A`[\"{ABElCN`}\",[]]Aj[\"{{{AHOh{BBBb}}}KC`}\",[]]A`[\"{BHDnCN`}\",[]]o[\"{D@fCN`}\",[]]A`[\"{ABClKC`}\",[]]Cf[\"{{{AHOh{CGbBH@f}}{A@d{ABDl}}}{{AHOh{CGbBH@f}}}}\",[]]Cf[\"{{{AHOh{CGbBH@h}}{A@d{ABDn}}}{{AHOh{CGbBH@h}}}}\",[]]8Af[\"{{ABA`CN`}BC@l}\",[]]Ah[\"{{}{{A@d{BHE`}}}}\",[]]Ae[\"{{KC`CMn}BANd}\",[]]Ce[\"{{BBMh{KG`{BABd}}AHGd{A@d{NMh}}}{{KGj{ABAd}}}}\",[]]Ai[\"{{{A@f{IHn}}}AIOf}\",[]]A`[\"{NM`BCNj}\",[]]Ai[\"{{{A@d{NJn}}}BBMh}\",[]]Be[\"{{{A@d{BABf}}{A@d{BFBl}}}BABd}\",[]]Aj[\"{{{A@d{B@Kj}}}B@Kh}\",[]]B`[\"{{{AHOh{{K@j{Oj}}}}}B@Mf}\",[]]Ae[\"{{CMnKC`}BEJj}\",[]]Ah[\"{{DAjA@lCN`}ABD`}\",[]]Ao[\"{{{A@d{AOKf}}NKdCMl}IDd}\",[]]Ao[\"{{{A@d{BBAl}}NKdCMl}NL`}\",[]]Ae[\"{{KC`CMn}BANf}\",[]]Ai[\"{{{A@f{IHn}}}AIOh}\",[]]Bo[\"{{{A@d{BBMj}}{KG`{{A@d{BABh}}}}DBn}ABAf}\",[]]A`[\"{KC`BIDl}\",[]]o[\"{{}BI@l}\",[]]A`[\"{NM`BCNl}\",[]]Ai[\"{{{A@d{NK`}}}BBMj}\",[]]Be[\"{{{A@d{BABj}}{A@d{BFBn}}}BABh}\",[]]Aj[\"{{{A@d{B@Kn}}}B@Kl}\",[]]Ek[\"{{AAOn{AHOh{c}}{AHOh{{K@j{CMn}}}}DBn}{{KGh{{KBn{BBBb{KG`{AAOn}}}}BFCj}}}{BFGnIHd}}\",[\"\"]]B`[\"{{{AHOh{{K@j{Oj}}}}}B@Mh}\",[]]Af[\"{{BFKjKI`}BCAb}\",[]]A`[\"{KC`BIAf}\",[]]Ae[\"{{CMnKC`}BEJl}\",[]]Ah[\"{{DAlA@nCN`}ABDb}\",[]]Am[\"{{AJ@n{KG`{KEn}}}AHCl}\",[]]Ao[\"{{{A@d{AOKh}}NKdCMl}IDf}\",[]]Ao[\"{{{A@d{BBAn}}NKdCMl}NLb}\",[]]Aj[\"{AJBb{{KGj{BCAd}}}}\",[]]Aa[\"{BEJdBHK`}\",[]]Aa[\"{BEJhBHKb}\",[]]o[\"{DAjDAj}\",[]]o[\"{DAlDAl}\",[]]Ak[\"{{{AHOh{AJAf}}}AJAd}\",[]]Ai[\"{{{AHOh{NMh}}}NKd}\",[]]0Aj[\"{{{AHOh{BACb}}}NKd}\",[]]Ak[\"{{{AHOh{BBCd}}}AJAd}\",[]]Ak[\"{{{AHOh{AJAh}}}AJAd}\",[]]Ak[\"{{{AHOh{BBCf}}}AJAd}\",[]]Bg[\"{{{AHOh{AILh}}KGb}{{KG`{ABA`}}}}\",[]]Aa[\"{AHFdABA`}\",[]]Bg[\"{{{AHOh{AILj}}KGd}{{KG`{ABA`}}}}\",[]]Aa[\"{AHFfABA`}\",[]]Ah[\"{AAn{{KGl{ICf}}}}\",[]]Ah[\"{AB`{{KGl{ICf}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Aa[\"{BA@`AJ@n}\",[]]Aa[\"{BA@bAJ@n}\",[]]Aa[\"{ABClAJ@n}\",[]]Aa[\"{BCAbBFKj}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{AB@hICj}\",[]]Am[\"{{{AHOh{CGbABCb}}}ICf}\",[]]Am[\"{{{AHOh{CGbABAl}}}ICf}\",[]]Al[\"{{{AHOh{CGbD@n}}}ICf}\",[]]Am[\"{{{AHOh{CGbBCAf}}}ICf}\",[]]Am[\"{{{AHOh{CGbAIOl}}}ICf}\",[]]Am[\"{{{AHOh{CGbAJ@h}}}ICf}\",[]]Al[\"{{{AHOh{CGbKDj}}}ICf}\",[]]A`[\"{cc{}}\",[\"T\"]]00000000000000000000000Aa[\"{BCLnBFDb}\",[]]1111111111111Aa[\"{AHFjBC@h}\",[]]2Aa[\"{BCLnAHFj}\",[]]Aa[\"{AJ@`AHFj}\",[]]4Aa[\"{BCLnAJ@`}\",[]]5Aa[\"{AHFjBC@f}\",[]]6666Aa[\"{BAC`AJBd}\",[]]7Aa[\"{BCLnAJBd}\",[]]Aa[\"{B@LdAJBd}\",[]]9Aa[\"{BCLnBAC`}\",[]]:::::::o[\"{CMlKId}\",[]]o[\"{CMnKId}\",[]]>>>A`[\"{KIfAOLb}\",[]]?????Aa[\"{BD@`AOJn}\",[]]Aa[\"{BGIfAOJn}\",[]]A`[\"{cc{}}\",[\"T\"]]00000Aa[\"{BCAbBCLl}\",[]]11111Aa[\"{BFLfB@Mb}\",[]]2222222Aa[\"{BBChBFCj}\",[]]33333A`[\"{IFbBCAb}\",[]]4A`[\"{KIfBFKj}\",[]]5555555A`[\"{KIfABDb}\",[]]66666A`[\"{BBChIFb}\",[]]7777Aa[\"{AONjAOKd}\",[]]888A`[\"{BHMlIF`}\",[]]A`[\"{BEIlIF`}\",[]]A`[\"{AINhIF`}\",[]]A`[\"{BCMjIF`}\",[]]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Bm[\"{B@Kf{{KGh{BEJdc}}}{}}\",[\"TryFrom::Error\"]]?Cf[\"{{{A@d{B@Kf}}}{{KGh{BEJdc}}}{}}\",[\"TryFrom::Error\"]]Ao[\"{c{{KGh{e}}}{}{}}\",[\"U\",\"T\"]]Cf[\"{{{A@d{BABb}}}{{KGh{BEJhc}}}{}}\",[\"TryFrom::Error\"]]1Bm[\"{BABb{{KGh{BEJhc}}}{}}\",[\"TryFrom::Error\"]]22222222222222222222222Aj[\"{{}{{KGh{c}}}{}}\",[\"U\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cd[\"{{{ABd{{AHOh{CGbc}}}}{AHOh{CGbNJb}}}DAf{}}\",[\"F\"]]000000000Cc[\"{{{AHOh{BCAd}}AJBb{AHOh{ABEh}}}{{KGj{ICf}}}}\",[]]Bk[\"{{{AHOh{BGOd}}B@Mf}{{KGh{ICfAIMj}}}}\",[]]Bk[\"{{{AHOh{BGOf}}B@Mh}{{KGh{ICfAIMl}}}}\",[]]0Bk[\"{{{AHOh{BI@l}}B@Mh}{{KGh{ICfAIMl}}}}\",[]]Ak[\"{{{AHOh{AILh}}}AAOl}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{KIdIEl}}}}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{DAjIEl}}}}\",[]]Bi[\"{{{AHOh{CGbBACd}}}{{KGh{A@lIEl}}}}\",[]]Bj[\"{{{AHOh{CGbBACd}}}{{KGh{ABD`IEl}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{KIf}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{DAl}}}}\",[]]Bf[\"{{{AHOh{CGbBACd}}}{{KGn{A@n}}}}\",[]]Bg[\"{{{AHOh{CGbBACd}}}{{KGn{ABDb}}}}\",[]]Aa[\"{AOJfBGIb}\",[]]Bd[\"{{{AHOh{AILl}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{CNh}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{IDd}}}{{A@f{AILl}}}}\",[]]Bc[\"{{{AHOh{NL`}}}{{A@f{AILl}}}}\",[]]Bd[\"{{{AHOh{AILn}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{CNj}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{IDf}}}{{A@f{AILn}}}}\",[]]Bc[\"{{{AHOh{NLb}}}{{A@f{AILn}}}}\",[]]A`[\"{ABEjCN`}\",[]]An[\"{{{AHOh{CGbAILj}}}AHBl}\",[]]A`[\"{ABElCN`}\",[]]C`[\"{{{AHOh{CGbB@Mf}}}{{AHOh{CGb{K@j{Oj}}}}}}\",[]]C`[\"{{{AHOh{CGbB@Mh}}}{{AHOh{CGb{K@j{Oj}}}}}}\",[]]Ah[\"{Oj{{KG`{B@N`}}}}\",[]]Ah[\"{Oj{{KG`{B@Nb}}}}\",[]]Ah[\"{Oj{{KG`{B@Nd}}}}\",[]]A`[\"{ABD`DAj}\",[]]A`[\"{ABDbDAl}\",[]]Bi[\"{AILd{{KGh{{KBn{AILhBD@f}}AILd}}}}\",[]]Aa[\"{{}c{}}\",[\"I\"]]o[\"{DAjDBn}\",[]]o[\"{DAlDBn}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]21Aj[\"{{{AHOh{ABAl}}}DBn}\",[]]Aj[\"{{{AHOh{ABAn}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBABd}}DBn}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}DBn}{{AHOh{CGbBABh}}}}\",[]]Bm[\"{{{AHOh{NMh}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]Bn[\"{{{AHOh{BACb}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]Bn[\"{{{AHOh{AOMl}}NKd}{{ABd{{A@f{AIJj}}}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Ak[\"{{{AHOh{AILh}}}ABCb}\",[]]Bc[\"{{{AHOh{AILh}}AJ@nAIOb}ABCd}\",[]]Ce[\"{{{AHOh{CGbAILj}}AHClAIOdNKd}{{KGh{KGdAHEj}}}}\",[]]43Bm[\"{{{AHOh{CGbAILj}}KGd}{{KGh{ICfAIL`}}}}\",[]]E`[\"{{{ABd{{AHOh{CGbBGHl}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbBEFb}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbAIO`}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]E`[\"{{{ABd{{AHOh{CGbBG@j}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{c}}}}}{}}\",[\"Stream::Item\"]]Ec[\"{{{AHOh{CGbAIOl}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{Oj}}}}}{{DAf{{KGh{KC`AHFj}}}}}}\",[]]Ef[\"{{{ABd{{AHOh{CGbAIOl}}}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{Oj}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]E`[\"{{{ABd{{AHOh{CGbAIOl}}}}{AHOh{CGbNJb}}{AHOh{CGbNMb}}}{{DAf{{KGj{ICf}}}}}}\",[]]Fg[\"{{{AHOh{CGbBBL`}}{AHOh{CGbNJb}}{AHOh{CGb{K@j{AIMn}}}}{AHOh{CGb{K@j{ABCl}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]Dn[\"{{{ABd{{AHOh{CGbAHGb}}}}{AHOh{ABEh}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]>=Ce[\"{{{AHOh{CGbBBMh}}{A@d{NJn}}}{{AHOh{CGbBBMh}}}}\",[]]Ce[\"{{{AHOh{CGbBBMj}}{A@d{NK`}}}{{AHOh{CGbBBMj}}}}\",[]]Cj[\"{{{AHOh{BABf}}CMnB@Mf{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BEJf}}CMnB@Mf{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BABj}}CMnB@Mh{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BEJh}}CMnB@Mh{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Cj[\"{{{AHOh{BHKb}}CMnB@Md{AHOh{{K@j{Oj}}}}}{{IId{Oj}}}}\",[]]Bb[\"{KC`{{KBn{KC`{KG`{KC`}}}}}}\",[]]000Aj[\"{{{AHOh{AILh}}}KC`}\",[]]A`[\"{AHOhKI`}\",[]]000000000000000000000000000000000000000000000000000000000000000000Cf[\"{{{AHOh{CGbBABd}}{A@d{BFBl}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{BFBn}}}{{AHOh{CGbBABh}}}}\",[]]A`[\"{BHDnIGb}\",[]]A`[\"{BABdA@d}\",[]]A`[\"{BABhA@d}\",[]]Aj[\"{{{AHOh{ABAd}}}ICf}\",[]]Ck[\"{{{AHOh{CGbAJ@h}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfAJBd}}}}\",[]]n[\"{{}KC`}\",[]]Ak[\"{{{AHOh{AILh}}}AHAb}\",[]]Ba[\"{{{AHOh{CGbABEj}}ABEj}ICf}\",[]]Ba[\"{{{AHOh{CGbAIMd}}AIMd}ICf}\",[]]Ba[\"{{{AHOh{CGbBCMf}}AHFd}ICf}\",[]]Ba[\"{{{AHOh{CGbABEl}}ABEl}ICf}\",[]]Ba[\"{{{AHOh{CGbAIMf}}AIMf}ICf}\",[]]Ba[\"{{{AHOh{CGbBCMh}}AHFf}ICf}\",[]]Bn[\"{{{AHOh{CGbBCOl}}DBn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bi[\"{{{AHOh{CGb}}}{{AHOh{CGbc}}}{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bc[\"{{AHOh{AHOh{CGbc}}}ICf{}}\",[\"T\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cc[\"{{{AHOh{CGbAILj}}NKdKGdKIf}{{KGh{ICfBBLf}}}}\",[]]A`[\"{AHBfDBn}\",[]]B`[\"{{AHOh{AHOh{c}}}DBn{}}\",[\"K\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Aa[\"{BCLhBFKh}\",[]]A`[\"{BEFfKId}\",[]]Aa[\"{BCLlBFKj}\",[]]A`[\"{BEFjKIf}\",[]]A`[\"{BFAlKIf}\",[]]A`[\"{BCNnKIf}\",[]]o[\"{NMnKIf}\",[]]Aa[\"{BCLhAIN`}\",[]]Aa[\"{BCLlAINb}\",[]]o[\"{KIdCN`}\",[]]o[\"{KIfCN`}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]Aj[\"{{{AHOh{BAOd}}}DBn}\",[]]Bd[\"{{{AHOh{BBL`}}}{{KGj{AJ@n}}}}\",[]]Bd[\"{{{AHOh{ABAd}}}{{KGj{AJ@n}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{BCMfCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BCMhCN`}\",[]]Cc[\"{{{AHOh{BCN`}}{AHOh{AJ@f}}CN`}{{A@d{AONh}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}DBn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Bg[\"{{{AHOh{AILh}}KGb}{{KG`{AHFd}}}}\",[]]A`[\"{AHC`A@f}\",[]]Bj[\"{{{AHOh{CGbAILj}}KGd}{{KG`{AHFf}}}}\",[]]A`[\"{AHCbA@f}\",[]]Db[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]00Ec[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}{AHOh{{K@j{Oj}}}}}{{DAf{{KGj{KC`}}}}}}\",[]]Eg[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}{AHOh{{K@j{Oj}}}}}{{DAf{{KGh{KC`AJBd}}}}}}\",[]]1Bm[\"{{{AHOh{IHh}}{AHOh{D@l}}}{{KGj{ICf}}}}\",[]]Cd[\"{{{AHOh{CGbAIOl}}KC`}{{KGh{{KG`{ICl}}AHFj}}}}\",[]]Cd[\"{{{AHOh{CGbBGAj}}KC`}{{KGh{{KG`{ICl}}AHFj}}}}\",[]]Cn[\"{{{AHOh{CGbAIOl}}{AHOh{CGb{K@j{Oj}}}}}{{KGh{ICfBC@f}}}}\",[]]Bj[\"{{{AHOh{D@n}}AIOb}{{KGh{ICfBFJn}}}}\",[]]Bn[\"{{{AHOh{CGbAIOf}}NKd}{{AHOh{CGbAIOf}}}}\",[]]Bn[\"{{{AHOh{CGbAIOh}}NKd}{{AHOh{CGbAIOh}}}}\",[]]A`[\"{BC@lAGb}\",[]]o[\"{IHfCN`}\",[]]o[\"{{}AJ@n}\",[]]0o[\"{{}AHOh}\",[]]Bk[\"{{ABAl{A@d{BABd}}}{{KGh{AILdBCLn}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bh[\"{{{AHOh{AHBf}}AJ@n}{{KGl{AHGd}}}}\",[]]A`[\"{AHFdCMl}\",[]]Aj[\"{{{AHOh{AILj}}}CMl}\",[]]A`[\"{AHFfCMl}\",[]]Ce[\"{{{AHOh{CGbAIOf}}{KG`{KI`}}}{{AHOh{CGbAIOf}}}}\",[]]Ce[\"{{{AHOh{CGbAIOh}}{KG`{KI`}}}{{AHOh{CGbAIOh}}}}\",[]]Aa[\"{ABEdAJ@n}\",[]]Aa[\"{ABEfAJ@n}\",[]]Aa[\"{ABEhAJ@n}\",[]]Aa[\"{AJ@nAHCl}\",[]]o[\"{AAlCMl}\",[]]Bn[\"{{{AHOh{CGbBCOl}}CMl}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMl}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHBfCMl}\",[]]Bo[\"{{{AHOh{CGbBCOl}}ABA`}{{AHOh{CGbBCOl}}}}\",[]]Bo[\"{{{AHOh{CGbBCOn}}ABA`}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHBfKG`}\",[]]k[\"{{}}\",[]]0000000000Bh[\"{ABAlc{}}\",[\"IntoFuture::IntoFuture\"]]11A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]o[\"{AAlKC`}\",[]]Ao[\"{{AHOhc}{{NKj{c}}}{}}\",[\"S\"]]0C`[\"{{{AHOh{CGbAILl}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bo[\"{{{AHOh{CGbCNh}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]C`[\"{{{AHOh{CGbAILn}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bo[\"{{{AHOh{CGbCNj}}NKdCN`DBn{KG`{CN`}}}ICf}\",[]]Bk[\"{{{AHOh{CGbIHh}}NKd{AHOh{BCN`}}}ICf}\",[]]A`[\"{BFBhKG`}\",[]]A`[\"{BFBjKG`}\",[]]Bn[\"{{{AHOh{KId}}{AHOh{KId}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KGb}}{AHOh{KGb}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AOL`}}{AHOh{AOL`}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{B@Mf}}{AHOh{B@Mf}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{DAj}}{AHOh{DAj}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{A@l}}{AHOh{A@l}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{ABD`}}{AHOh{ABD`}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KIf}}{AHOh{KIf}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BFDd}}{AHOh{BFDd}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{KGd}}{AHOh{KGd}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AHFl}}{AHOh{AHFl}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BBBl}}{AHOh{BBBl}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AJBf}}{AHOh{AJBf}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{AOLb}}{AHOh{AOLb}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BEGb}}{AHOh{BEGb}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{BFCj}}{AHOh{BFCj}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{B@Mh}}{AHOh{B@Mh}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{DAl}}{AHOh{DAl}}}{{KG`{ABCf}}}}\",[]]Bn[\"{{{AHOh{A@n}}{AHOh{A@n}}}{{KG`{ABCf}}}}\",[]]C`[\"{{{AHOh{ABDb}}{AHOh{ABDb}}}{{KG`{ABCf}}}}\",[]]Ak[\"{{{AHOh{AILh}}}AIO`}\",[]]Bk[\"{{{AHOh{AILj}}KGd}{{KGh{AIOdAIL`}}}}\",[]]Df[\"{{{AHOh{CGbAIOl}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{{KG`{KC`}}AHFj}}}}\",[]]Cc[\"{{{AHOh{CGbAIOl}}KC`}{{KGh{{ABj{Oj}}BC@h}}}}\",[]]Bb[\"{{{AHOh{CGbAILj}}ABDb}AIOn}\",[]]Aj[\"{{{AHOh{AHDd}}}KC`}\",[]]Aj[\"{{{AHOh{AHDf}}}KC`}\",[]]Bb[\"{{{AHOh{CGbAILj}}ABDb}AJ@j}\",[]]Bn[\"{{{AHOh{CGbBCOl}}CN`}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CN`}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHBfKG`}\",[]]A`[\"{BAOjKG`}\",[]]A`[\"{BAOlKG`}\",[]]Cf[\"{{{AHOh{CGbBABd}}{A@d{AJAf}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{AJAh}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kh}}{A@d{AJAn}}}{{AHOh{CGbB@Kh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kl}}{A@d{AJB`}}}{{AHOh{CGbB@Kl}}}}\",[]]o[\"{AAlCN`}\",[]]Bn[\"{{{AHOh{CGbBFI`}}CMl}{{AHOh{CGbBFI`}}}}\",[]]Bn[\"{{{AHOh{CGbBFIb}}CMl}{{AHOh{CGbBFIb}}}}\",[]]Ak[\"{{{AHOh{AILh}}}BGIj}\",[]]Aj[\"{{{AHOh{D@n}}}BCAf}\",[]]Aj[\"{{{A@d{BABf}}}BABd}\",[]]Aj[\"{{{A@d{BABj}}}BABh}\",[]]Aj[\"{{BCNjc}BCNjABDj}\",[\"\"]]Aj[\"{{BCNlc}BCNlABDj}\",[\"\"]]Bm[\"{{{AHOh{CGbAJ@h}}ICj}{{KGh{ICfAJBd}}}}\",[]]n[\"{{}KEn}\",[]]o[\"{NJ`NJ`}\",[]]0000Bd[\"{{{AHOh{BGOd}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BGOf}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BI@l}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{BIAf}}}{{KG`{ABA`}}}}\",[]]Bd[\"{{{AHOh{AILh}}}{{KG`{BCLn}}}}\",[]]Ck[\"{{{AHOh{ABAd}}B@KhAJ@n{AHOh{CMj}}}{{KGh{AILdB@M`}}}}\",[]]Ak[\"{{{AHOh{BAAl}}}ABA`}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]An[\"{{AIOjDBn}{{KGl{KC`}}}}\",[]]Cl[\"{{{AHOh{NMj}}}{{KG`{{KBn{{A@f{AHDd}}{A@f{AHEb}}}}}}}}\",[]]Cm[\"{{{AHOh{AJAj}}}{{KG`{{KBn{{A@f{AHDd}}{A@f{AHEb}}}}}}}}\",[]]Cl[\"{{{AHOh{NMl}}}{{KG`{{KBn{{A@f{AHDf}}{A@f{AHEd}}}}}}}}\",[]]Cm[\"{{{AHOh{AJAl}}}{{KG`{{KBn{{A@f{AHDf}}{A@f{AHEd}}}}}}}}\",[]]A`[\"{BGGhABj}\",[]]A`[\"{BIDnABj}\",[]]A`[\"{BGGjABj}\",[]]A`[\"{BIE`ABj}\",[]]An[\"{{{AHOh{CGbBGOd}}}B@Mf}\",[]]An[\"{{{AHOh{CGbBGOf}}}B@Mh}\",[]]An[\"{{{AHOh{CGbBI@l}}}B@Mh}\",[]]An[\"{{{AHOh{CGbBIAf}}}B@Mh}\",[]]Ak[\"{{{AHOh{BCAd}}}B@Oj}\",[]]Ba[\"{{{AHOh{CGbAILj}}BCMd}ICf}\",[]]Bo[\"{{{AHOh{CGbABAf}}BEGbBAOd}{{KG`{BCMd}}}}\",[]]B`[\"{{{AHOh{NMj}}B@MfDAj}D@b}\",[]]Bn[\"{{{AHOh{BABf}}CMnB@Mf}{{KGh{D@bBFL`}}}}\",[]]Ba[\"{{{AHOh{AJAj}}B@MfDAj}D@b}\",[]]Bn[\"{{{AHOh{BEJf}}CMnB@Mf}{{KGh{D@bBFL`}}}}\",[]]B`[\"{{{AHOh{NMl}}B@MhDAl}D@d}\",[]]Bn[\"{{{AHOh{BABj}}CMnB@Mh}{{KGh{D@dBFLf}}}}\",[]]Ba[\"{{{AHOh{AJAl}}B@MhDAl}D@d}\",[]]Bn[\"{{{AHOh{BEJh}}CMnB@Mh}{{KGh{D@dBFLf}}}}\",[]]Bn[\"{{{AHOh{BHKb}}CMnB@Md}{{KGh{D@dBFLf}}}}\",[]]Aj[\"{{}{{NMd{c}}}{}}\",[\"T\"]]0A`[\"{AHFdCN`}\",[]]A`[\"{BCMfCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BCMhCN`}\",[]]Bn[\"{{{AHOh{CGbBABd}}KC`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}KC`}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{BBL`}}}DBn}\",[]]0Aj[\"{{{AHOh{BCAd}}}DBn}\",[]]Bk[\"{{{AHOh{AILj}}KGd}{{KGh{AHClAIL`}}}}\",[]]Cc[\"{{{AHOh{BCN`}}{AHOh{AIOj}}CN`}{{A@d{AONh}}}}\",[]]Ak[\"{{{AHOh{ABAl}}}B@Mf}\",[]]Ak[\"{{{AHOh{ABAn}}}B@Mh}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bf[\"{{{AHOh{CGbAILj}}}{{KG`{NKd}}}}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{A@d{AOLn}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{A@d{AOM`}}}{{AHOh{CGbBCOn}}}}\",[]]43A`[\"{AAlAOMf}\",[]]A`[\"{ABEdKG`}\",[]]A`[\"{ABEfKG`}\",[]]A`[\"{ABEhKG`}\",[]]A`[\"{BFBhKG`}\",[]]A`[\"{BFBjKG`}\",[]]Ai[\"{{{AHOh{NNj}}}KC`}\",[]]Bo[\"{{{AHOh{CGbBI@l}}ABA`}{{AHOh{CGbBI@l}}}}\",[]]Bo[\"{{{AHOh{CGbBIAf}}ABA`}{{AHOh{CGbBIAf}}}}\",[]]Bj[\"{{{AHOh{AJ@h}}CEl}{{KGh{ICfB@Ld}}}}\",[]]Bm[\"{{{AHOh{CGbAJ@j}}CEl}{{KGh{ICfB@Ll}}}}\",[]]?>A`[\"{IHfAONf}\",[]]A`[\"{AOJhIHf}\",[]]Bj[\"{{{A@d{B@Kf}}IHj}{{KGh{BEJbBGHh}}}}\",[]]Bj[\"{{{A@d{BABb}}IHj}{{KGh{BEJfBGHh}}}}\",[]]Bj[\"{{{A@d{B@Kf}}IHj}{{KGh{BEJdBGHj}}}}\",[]]Bj[\"{{{A@d{BABb}}IHj}{{KGh{BEJhBGHj}}}}\",[]]Co[\"{{{AHOh{CGbAJ@h}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{NOfAJBd}}}}\",[]]Co[\"{{{AHOh{CGbAJ@j}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{NOhAJBf}}}}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]A`[\"{AHBfDBn}\",[]]Cd[\"{{{AHOh{CGbBBMh}}{A@d{A`}}}{{AHOh{CGbBBMh}}}}\",[]]Cd[\"{{{AHOh{CGbBBMj}}{A@d{A`}}}{{AHOh{CGbBBMj}}}}\",[]]Bk[\"{{{AHOh{BBL`}}}{{ABd{{A@f{AHGb}}}}}}\",[]]o[\"{AAlCN`}\",[]]Aa[\"{AONfAHDh}\",[]]76Aa[\"{AJ@bABAl}\",[]]Aa[\"{AJ@dABAn}\",[]]Cf[\"{{{AHOh{CGbBFGb}}{KG`{ABA`}}}{{AHOh{CGbBFGb}}}}\",[]]Cf[\"{{{AHOh{CGbBFGd}}{KG`{ABA`}}}{{AHOh{CGbBFGd}}}}\",[]]9;:An[\"{{{AHOh{AONh}}ABA`}ICf}\",[]]B`[\"{{{AHOh{CGbAILl}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbCNh}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbIDd}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbNL`}}CMl}ICf}\",[]]B`[\"{{{AHOh{CGbAILn}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbCNj}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbIDf}}CMl}ICf}\",[]]Ao[\"{{{AHOh{CGbNLb}}CMl}ICf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Bj[\"{{{AHOh{AILh}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Db[\"{{{ABd{{AHOh{CGbAJ@h}}}}{AHOh{CGbNJb}}}{{DAf{{KGj{ICf}}}}}}\",[]]Db[\"{{{AHOh{CGbAILj}}NKdB@Oj{AHOh{CGb{ABj{Oj}}}}}{{KG`{ABEf}}}}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{AHOh{CMj}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{AHOh{CMj}}}{{AHOh{CGbBCOn}}}}\",[]]Ak[\"{{{AHOh{AILh}}}BAA`}\",[]]Bj[\"{{{AHOh{AILh}}ICj}{{KGh{ICfBFDb}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}DBn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Ai[\"{{{AHOh{NJn}}}KC`}\",[]]Ai[\"{{{AHOh{NK`}}}KC`}\",[]]Dh[\"{{{AHOh{B@Kj}}CMn{AHOh{CMj}}{AHOh{BGAh}}}{{KGh{{A@f{NMj}}B@M`}}}}\",[]]Cb[\"{{{AHOh{BABf}}CMn{AHOh{BGAh}}}{{A@f{NMj}}}}\",[]]Dh[\"{{{AHOh{BEJb}}CMn{AHOh{CMj}}{AHOh{BGAh}}}{{KGh{{A@f{NMj}}B@M`}}}}\",[]]Cb[\"{{{AHOh{BEJf}}CMn{AHOh{BGAh}}}{{A@f{NMj}}}}\",[]]Dh[\"{{{AHOh{B@Kn}}CMn{AHOh{CMj}}{AHOh{BGAh}}}{{KGh{{A@f{NMl}}B@Mb}}}}\",[]]Cb[\"{{{AHOh{BABj}}CMn{AHOh{BGAh}}}{{A@f{NMl}}}}\",[]]Dh[\"{{{AHOh{BEJd}}CMn{AHOh{CMj}}{AHOh{BGAh}}}{{KGh{{A@f{NMl}}B@Mb}}}}\",[]]Cb[\"{{{AHOh{BEJh}}CMn{AHOh{BGAh}}}{{A@f{NMl}}}}\",[]]Dh[\"{{{AHOh{BHK`}}CMn{AHOh{CMj}}{AHOh{BGAh}}}{{KGh{{A@f{NMl}}B@Ln}}}}\",[]]Cb[\"{{{AHOh{BHKb}}CMn{AHOh{BGAh}}}{{A@f{NMl}}}}\",[]]Dd[\"{{{ABd{{AHOh{CGbc}}}}{AHOh{CGbNJb}}}{{DAf{{KG`{KGh}}}}}{}}\",[\"S\"]]0Bn[\"{{AJ@nBBLbAAl}{{KGl{{KBn{ABAbAILf}}}}}}\",[]]Bd[\"{{{AHOh{AILj}}}{{AHOh{NMl}}}}\",[]]A`[\"{AOJhIHf}\",[]]Cb[\"{{{AHOh{AOLn}}DAjAJ@nB@MfNKd}{{KG`{AIOf}}}}\",[]]Cb[\"{{{AHOh{BCNj}}DAjAJ@nB@MfNKd}{{KG`{AIOf}}}}\",[]]Cb[\"{{{AHOh{AOM`}}DAlAJ@nB@MhNKd}{{KG`{AIOh}}}}\",[]]Cb[\"{{{AHOh{BCNl}}DAlAJ@nB@MhNKd}{{KG`{AIOh}}}}\",[]]B`[\"{{{AHOh{CGbAILj}}NKd}ICf}\",[]]Ca[\"{{{AHOh{CGbAILd}}}{{KGh{{A@f{A@b}}BCLn}}}}\",[]]Bj[\"{{{AHOh{AILh}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAj}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bi[\"{{{AHOh{NMl}}}{{KG`{{A@f{A@b}}}}}}\",[]]Bj[\"{{{AHOh{AJAl}}}{{KG`{{A@f{A@b}}}}}}\",[]]o[\"{AIMdOj}\",[]]o[\"{AIMfOj}\",[]]Ai[\"{{{AHOh{CMj}}}DBn}\",[]]Aj[\"{{{AHOh{AILl}}}CN`}\",[]]Ai[\"{{{AHOh{CNh}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAIKb}}CN`}{{AHOh{CGbAIKb}}}}\",[]]Ai[\"{{{AHOh{IDd}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAOKf}}CN`}{{AHOh{CGbAOKf}}}}\",[]]Ai[\"{{{AHOh{NL`}}}CN`}\",[]]Bn[\"{{{AHOh{CGbBBAl}}CN`}{{AHOh{CGbBBAl}}}}\",[]]Aj[\"{{{AHOh{AILn}}}CN`}\",[]]Ai[\"{{{AHOh{CNj}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAIKd}}CN`}{{AHOh{CGbAIKd}}}}\",[]]Ai[\"{{{AHOh{IDf}}}CN`}\",[]]Bn[\"{{{AHOh{CGbAOKh}}CN`}{{AHOh{CGbAOKh}}}}\",[]]Ai[\"{{{AHOh{NLb}}}CN`}\",[]]Bn[\"{{{AHOh{CGbBBAn}}CN`}{{AHOh{CGbBBAn}}}}\",[]]Aa[\"{AIOlBGAj}\",[]]Ai[\"{{{AHOh{NMj}}}DBn}\",[]]Aj[\"{{{AHOh{AJAj}}}DBn}\",[]]Aj[\"{{{AHOh{AILj}}}DBn}\",[]]Ai[\"{{{AHOh{NMl}}}DBn}\",[]]Aj[\"{{{AHOh{AJAl}}}DBn}\",[]]Co[\"{{{AHOh{NMj}}B@Mf{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]D`[\"{{{AHOh{AJAj}}B@Mf{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]Co[\"{{{AHOh{NMl}}B@Mh{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]D`[\"{{{AHOh{AJAl}}B@Mh{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBFI`}}CMl}{{AHOh{CGbBFI`}}}}\",[]]Bn[\"{{{AHOh{CGbBFIb}}CMl}{{AHOh{CGbBFIb}}}}\",[]]Cd[\"{{{AHOh{CGbNMj}}}{{KG`{{NKf{{A@f{AHEb}}}}}}}}\",[]]Ce[\"{{{AHOh{CGbAJAj}}}{{KG`{{NKf{{A@f{AHEb}}}}}}}}\",[]]Cd[\"{{{AHOh{CGbNMl}}}{{KG`{{NKh{{A@f{AHEd}}}}}}}}\",[]]Ce[\"{{{AHOh{CGbAJAl}}}{{KG`{{NKh{{A@f{AHEd}}}}}}}}\",[]]Bf[\"{{{AHOh{CGbAILl}}CMlCN`NKd}ICf}\",[]]Be[\"{{{AHOh{CGbCNh}}CMlCN`NKd}ICf}\",[]]Bf[\"{{{AHOh{CGbAILn}}CMlCN`NKd}ICf}\",[]]Be[\"{{{AHOh{CGbCNj}}CMlCN`NKd}ICf}\",[]]Bf[\"{{{AHOh{CGbAILl}}NKdCMlCN`}ICf}\",[]]Be[\"{{{AHOh{CGbCNh}}NKdCMlCN`}ICf}\",[]]Bf[\"{{{AHOh{CGbAILn}}NKdCMlCN`}ICf}\",[]]Be[\"{{{AHOh{CGbCNj}}NKdCMlCN`}ICf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]De[\"{{{AHOh{CGbBCOl}}c{AHOh{CMj}}}{{AHOh{CGbBCOl}}}{{ICh{D@l}}}}\",[\"\"]]De[\"{{{AHOh{CGbBCOn}}c{AHOh{CMj}}}{{AHOh{CGbBCOn}}}{{ICh{D@l}}}}\",[\"\"]]Ci[\"{{{AHOh{CGbNMj}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnIEf}}}}\",[]]Cj[\"{{{AHOh{CGbAJAj}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnIEf}}}}\",[]]Cj[\"{{{AHOh{CGbNMl}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnBCAb}}}}\",[]]Ck[\"{{{AHOh{CGbAJAl}}{AHOh{{K@j{Oj}}}}}{{KGh{DBnBCAb}}}}\",[]]o[\"{AAlDBn}\",[]]Bn[\"{{{AHOh{CGbBCOl}}KId}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KIf}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHBfKG`}\",[]]Ca[\"{{{AHOh{CGbAIOl}}}{{KGh{{KG`{KId}}AJ@`}}}}\",[]]Ca[\"{{{AHOh{CGbBGAj}}}{{KGh{{KG`{KId}}AJ@`}}}}\",[]]Ca[\"{{{AHOh{CGbAIOn}}}{{KGh{{KG`{KIf}}B@Ll}}}}\",[]]Ak[\"{{{AHOh{AILd}}}AJ@n}\",[]]Ak[\"{{{AHOh{ABAl}}}AJ@n}\",[]]Bg[\"{{{AHOh{D@n}}}{{KGh{AJ@nAIKj}}}}\",[]]Ak[\"{{{AHOh{ABAn}}}AJ@n}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]B`[\"{{KIdc}KId{{D@`{KId}}}}\",[\"\"]]B`[\"{{KGbc}KGb{{D@`{KGb}}}}\",[\"\"]]B`[\"{{KIfc}KIf{{D@`{KIf}}}}\",[\"\"]]B`[\"{{KGdc}KGd{{D@`{KGd}}}}\",[\"\"]]20Ae[\"{{ABA`CN`}AGb}\",[]]Bn[\"{{{AHOh{CGbBCOl}}AG`}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}AG`}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{IHfABA`}\",[]]B`[\"{{}{{AHOh{{K@j{BG@h}}}}}}\",[]]An[\"{{AHOh{OOb{CGbOj}}}ICf}\",[]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000An[\"{{}{{KG`{{A@d{NMh}}}}}}\",[]]Bn[\"{{{AHOh{CGbBBMh}}DBn}{{AHOh{CGbBBMh}}}}\",[]]Bn[\"{{{AHOh{CGbBBMj}}DBn}{{AHOh{CGbBBMj}}}}\",[]]Aj[\"{{{AHOh{AHEb}}}CN`}\",[]]Aj[\"{{{AHOh{AHEd}}}CN`}\",[]]A`[\"{ABClKG`}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Bf[\"{{{AHOh{CMj}}}{{KGl{CN`BBB`}}}}\",[]]Bn[\"{{{AHOh{ABAd}}{A@f{BBL`}}}{{KGj{ICf}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Cj[\"{{{AHOh{NMf}}BBLbBBBj{AHOh{AAl}}}{{KBn{AJ@nABAb}}}}\",[]]Cb[\"{{{AHOh{CGbAILj}}KGdAIOd}{{KGh{AIOdBFK`}}}}\",[]]Am[\"{{{AHOh{AILh}}CN`}ICf}\",[]]B`[\"{{{AHOh{CGbAILj}}CN`}ICf}\",[]]A`[\"{BC@jDBn}\",[]]B`[\"{{{AHOh{CGbIHf}}BC@l}ICf}\",[]]Aa[\"{AONfAHDh}\",[]]Bn[\"{{{AHOh{NMh}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Bo[\"{{{AHOh{BACb}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Bo[\"{{{AHOh{AOMl}}AHGd}{{KGj{{A@f{BBL`}}}}}}\",[]]Ci[\"{{{AHOh{CGbNMj}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@b}}}}\",[]]Cj[\"{{{AHOh{CGbAJAj}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@b}}}}\",[]]Ci[\"{{{AHOh{CGbNMl}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@d}}}}\",[]]Cj[\"{{{AHOh{CGbAJAl}}{AHOh{CGb{ABj{Oj}}}}}{{KG`{D@d}}}}\",[]]Cb[\"{{{AHOh{ABDl}}ICdAJAdABA`}{{KGh{ICfBCOf}}}}\",[]]Cb[\"{{{AHOh{BANd}}ICdAJAdABA`}{{KGh{ICfBCOf}}}}\",[]]Cb[\"{{{AHOh{B@Ol}}ICdAJAdABA`}{{KGh{ICfBCOf}}}}\",[]]Cb[\"{{{AHOh{ABDn}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Cb[\"{{{AHOh{BANf}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Cb[\"{{{AHOh{B@On}}ICdAJAdABA`}{{KGh{ICfBCOh}}}}\",[]]Al[\"{{}{{KGh{B@KdBGHj}}}}\",[]]Bn[\"{{{AHOh{AILh}}KGb}{{KG`{{A@f{AILl}}}}}}\",[]]Bo[\"{{{AHOh{AILj}}KGd}{{KG`{{AHOh{AILn}}}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Aj[\"{{{AHOh{AILh}}}ICf}\",[]]Am[\"{{{AHOh{CGbAILj}}}ICf}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AAlIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{A@jIEj}}}}\",[]]Bg[\"{{{AHOh{AIJh}}}{{KGh{AB@bIEj}}}}\",[]]Bg[\"{{{AHOh{AIJh}}}{{KGh{AHBfIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AAnIEj}}}}\",[]]Bf[\"{{{AHOh{AIJh}}}{{KGh{AB`IEj}}}}\",[]]Ak[\"{{{AHOh{BCAd}}}B@Oj}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{KG`{AOL`}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{AOLb}}}{{AHOh{CGbBCOn}}}}\",[]]<;Aj[\"{{{AHOh{ABAd}}}KC`}\",[]]Aj[\"{{{AHOh{ABAf}}}KC`}\",[]]Bc[\"{{{AHOh{AILh}}AJ@nAIOb}ABCd}\",[]]Co[\"{{{AHOh{CGbAILj}}AHClAIOdNKd}{{KGh{{KBn{KGdDBn}}AHEj}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}CMn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMn}{{AHOh{CGbBCOn}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Bg[\"{{{AHOh{BCAd}}AJBb}{{KGj{KC`}}}}\",[]]A`[\"{AHBfCN`}\",[]]10Aj[\"{{{AHOh{AAl}}}BCOj}\",[]]Cf[\"{{{AHOh{CGbBABd}}{A@d{BCOl}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kh}}{A@d{BCOl}}}{{AHOh{CGbB@Kh}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{A@d{BCOn}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbB@Kl}}{A@d{BCOn}}}{{AHOh{CGbB@Kl}}}}\",[]]Aa[\"{BABdBH@f}\",[]]Aa[\"{BABhBH@h}\",[]]Bj[\"{{{ABj{BBLb}}BBBj}{{KGh{BABdIEn}}}}\",[]]Bj[\"{{{ABj{BBLb}}BBBj}{{KGh{BABhIF`}}}}\",[]]Co[\"{{{AHOh{CGbAJ@h}}{AHOh{CGb{K@j{ICj}}}}}{{KGh{ICfAJBd}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]A`[\"{BFBhCN`}\",[]]A`[\"{BFBjCN`}\",[]]Bc[\"{{{AHOh{AILh}}}{{KG`{KC`}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Aj[\"{{{AHOh{AHBl}}}KC`}\",[]]Be[\"{{{AHOh{ABAd}}{KG`{BABd}}}ICf}\",[]]Bo[\"{{{AHOh{CGbABAf}}{KG`{{A@d{BABh}}}}}ICf}\",[]]Bd[\"{{{AHOh{BG@h}}}{{KG`{BBBh}}}}\",[]]o[\"{{}AHOh}\",[]]n[\"{{}NJ`}\",[]]0000Bn[\"{{{AHOh{CGbBCOl}}KC`}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KC`}{{AHOh{CGbBCOn}}}}\",[]]o[\"{CN`KId}\",[]]o[\"{CN`KIf}\",[]]A`[\"{BAOfCN`}\",[]]Bf[\"{{{AHOh{BGIj}}{AHOh{BGIj}}}DBn}\",[]]Bo[\"{{{AHOh{CGbBBMh}}ABA`}{{AHOh{CGbBBMh}}}}\",[]]Bo[\"{{{AHOh{CGbBBMj}}ABA`}{{AHOh{CGbBBMj}}}}\",[]]Ae[\"{{KC`CN`}BANd}\",[]]Ae[\"{{KC`CN`}BANf}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]7Bg[\"{{{AHOh{AILj}}KGd}{{KG`{AIOd}}}}\",[]]An[\"{{{AHOh{AILh}}ICj}BAAn}\",[]]Bm[\"{{{AHOh{CGbBEJb}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJf}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJd}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Bm[\"{{{AHOh{CGbBEJh}}{ABj{{ABj{Oj}}}}}ICf}\",[]]Am[\"{{{AHOh{AILh}}KId}ICf}\",[]]B`[\"{{{AHOh{CGbAILj}}KIf}ICf}\",[]]Ce[\"{{{AHOh{CGbBBMh}}{ABj{CMn}}}{{AHOh{CGbBBMh}}}}\",[]]Ce[\"{{{AHOh{CGbBBMj}}{ABj{CMn}}}{{AHOh{CGbBBMj}}}}\",[]]Fg[\"{{{AHOh{BHE`}}{AHOh{BBLb}}{AHOh{{K@j{BBLb}}}}{AHOh{AJ@l}}{AHOh{{K@j{Oj}}}}ABEn}{{KGh{BFJjIEh}}}}\",[]]Af[\"{{BCNjNKd}BCNj}\",[]]Af[\"{{BCNlNKd}BCNl}\",[]]A`[\"{BAOfCN`}\",[]]Al[\"{BACd{{KGh{DAjIEl}}}}\",[]]Al[\"{BACd{{KGh{A@lIEl}}}}\",[]]Ai[\"{BACd{{KGn{DAl}}}}\",[]]Ai[\"{BACd{{KGn{A@n}}}}\",[]]o[\"{NJ`NJ`}\",[]]Bo[\"{{{AHOh{CGbBFI`}}ABA`}{{AHOh{CGbBFI`}}}}\",[]]Bo[\"{{{AHOh{CGbBFIb}}ABA`}{{AHOh{CGbBFIb}}}}\",[]]Bb[\"{{{AHOh{NMj}}}{{KG`{DBn}}}}\",[]]Bc[\"{{{AHOh{AJAj}}}{{KG`{DBn}}}}\",[]]Bb[\"{{{AHOh{NMl}}}{{KG`{DBn}}}}\",[]]Bc[\"{{{AHOh{AJAl}}}{{KG`{DBn}}}}\",[]]Bg[\"{{{AHOh{AILh}}}{{KGh{ICfBCLn}}}}\",[]]Ba[\"{{{AHOh{BFCd}}KGbAHCl}DBn}\",[]]Ba[\"{{{AHOh{BFCf}}KGdAHCl}DBn}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{KG`{ABA`}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{ABA`}}}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Bo[\"{{{AHOh{CGbAILl}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbCNh}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbIDd}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbNL`}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bo[\"{{{AHOh{CGbAILn}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbCNj}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbIDf}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]Bn[\"{{{AHOh{CGbNLb}}NKdNKdDBnDBnCN`CN`}ICf}\",[]]A`[\"{BAOfCN`}\",[]]Al[\"{{{AHOh{NNj}}A@n}CN`}\",[]]Bi[\"{{{AHOh{CGbAJ@f}}CN`}{{KGl{ICf}}}}\",[]]<;A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]10Cf[\"{{{AHOh{CGbBCOl}}{KG`{BFGb}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{BFGd}}}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AAlIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{A@jIEj}}}}\",[]]Bj[\"{{{AHOh{CGbAIJh}}}{{KGh{AB@bIEj}}}}\",[]]Bj[\"{{{AHOh{CGbAIJh}}}{{KGh{AHBfIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AAnIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAIJh}}}{{KGh{AB`IEj}}}}\",[]]Cd[\"{{{A@d{AILf}}CN`DBn}{{KGl{{KBn{BC@lBC@l}}}}}}\",[]]Bn[\"{{{AHOh{CGbBABd}}CN`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}CN`}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{AILh}}}DBn}\",[]]Ak[\"{{{AHOh{BBL`}}}B@Oj}\",[]]0Ci[\"{{{AHOh{CGbBBMh}}CMl}{{KGh{{AHOh{CGbBBMh}}AOJl}}}}\",[]]Ci[\"{{{AHOh{CGbBBMj}}CMl}{{KGh{{AHOh{CGbBBMj}}AOJn}}}}\",[]]A`[\"{AHBfCMl}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{KG`{BFI`}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{BFIb}}}{{AHOh{CGbBCOn}}}}\",[]]Bg[\"{{{AHOh{CGbAILj}}}{{KG`{BAOd}}}}\",[]]Cf[\"{{{AHOh{CGbBABd}}{KG`{BABl}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{KG`{BABl}}}{{AHOh{CGbBABh}}}}\",[]]Cf[\"{{{AHOh{CGbBABd}}{KG`{BABn}}}{{AHOh{CGbBABd}}}}\",[]]Cf[\"{{{AHOh{CGbBABh}}{KG`{BABn}}}{{AHOh{CGbBABh}}}}\",[]]Cd[\"{{}{{KGh{{KBn{{ABj{BBLb}}BBBj}}{A@f{IE`}}}}}}\",[]]Bn[\"{{{AHOh{CGbBFGb}}KId}{{AHOh{CGbBFGb}}}}\",[]]Bn[\"{{{AHOh{CGbBFGd}}KIf}{{AHOh{CGbBFGd}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bo[\"{{{AHOh{CGbBABd}}ABA`}{{AHOh{CGbBABd}}}}\",[]]Bo[\"{{{AHOh{CGbBABh}}ABA`}{{AHOh{CGbBABh}}}}\",[]]Ci[\"{{{AHOh{D@n}}{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIKj}}}}\",[]]Bj[\"{{{AHOh{BCAd}}AJBbKC`}{{KGj{ICf}}}}\",[]]054Bm[\"{{{AHOh{NMj}}}{{KGh{{KG`{BGAh}}IEf}}}}\",[]]Bn[\"{{{AHOh{AJAj}}}{{KGh{{KG`{BGAh}}IEf}}}}\",[]]Bn[\"{{{AHOh{NMl}}}{{KGh{{KG`{BGAh}}BCAb}}}}\",[]]Bo[\"{{{AHOh{AJAl}}}{{KGh{{KG`{BGAh}}BCAb}}}}\",[]]Aj[\"{{{AHOh{AHEb}}}CN`}\",[]]Aj[\"{{{AHOh{AHEd}}}CN`}\",[]]Bl[\"{{{AHOh{ABAd}}{KG`{{A@d{BFCd}}}}}ICf}\",[]]Cc[\"{{{AHOh{CGbAILj}}{KG`{{AHOh{BFCf}}}}NKd}ICf}\",[]]Aj[\"{{{AHOh{ABAf}}}CN`}\",[]]Bf[\"{{{AHOh{AHCl}}{AHOh{AHCl}}}DBn}\",[]]Bn[\"{{{AHOh{CGbBBAl}}AG`}{{AHOh{CGbBBAl}}}}\",[]]Bn[\"{{{AHOh{CGbBBAn}}AG`}{{AHOh{CGbBBAn}}}}\",[]]Ak[\"{{{AHOh{AHGb}}}B@Oj}\",[]]0Ak[\"{{{AHOh{AILh}}}BG@j}\",[]]Cb[\"{{{AHOh{AILj}}KGd}{{KGh{{KG`{AJ@n}}AIL`}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]Bn[\"{{{AHOh{CGbBCOl}}KId}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KIf}{{AHOh{CGbBCOn}}}}\",[]]A`[\"{AHBfKG`}\",[]]Bo[\"{{{AHOh{AHBf}}{AHOh{CMj}}}{{KGj{BCOj}}}}\",[]]Em[\"{{{AHOh{AILh}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLl}}}}\",[]]El[\"{{{AHOh{NMj}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLl}}}}\",[]]Em[\"{{{AHOh{AJAj}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLl}}}}\",[]]El[\"{{{AHOh{NMl}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLn}}}}\",[]]Em[\"{{{AHOh{AJAl}}{AHOh{CGb{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}{AHOh{{K@j{Oj}}}}}{{KGh{ICfBHLn}}}}\",[]]Am[\"{{{AHOh{CGbAHBj}}}ICf}\",[]]0Am[\"{{{AHOh{AILj}}A@n}CN`}\",[]]Ak[\"{{{AHOh{AILh}}}BGHl}\",[]]Bg[\"{{{AHOh{D@n}}}{{KGh{BEFbAIKj}}}}\",[]]>=E`[\"{{{AHOh{BHE`}}{AHOh{{K@j{Oj}}}}{AHOh{BBLb}}{AHOh{BGOh}}}{{KGh{BHGfIEh}}}}\",[]]0Bg[\"{{{A@d{BBCb}}}{{KGh{B@KhBGIh}}}}\",[]]Bg[\"{{{A@d{BBCb}}}{{KGh{B@KlBGIh}}}}\",[]]Bn[\"{{{AHOh{CGbBFGb}}KId}{{AHOh{CGbBFGb}}}}\",[]]Bn[\"{{{AHOh{CGbBFGd}}KIf}{{AHOh{CGbBFGd}}}}\",[]]o[\"{NJ`NJ`}\",[]]0000Aj[\"{{{AHOh{AILj}}}DBn}\",[]]0Bd[\"{{{AHOh{CGbAILl}}CN`ABA`}ICf}\",[]]Bc[\"{{{AHOh{CGbCNh}}CN`ABA`}ICf}\",[]]Bd[\"{{{AHOh{CGbAILn}}CN`ABA`}ICf}\",[]]Bc[\"{{{AHOh{CGbCNj}}CN`ABA`}ICf}\",[]]Ci[\"{{{AHOh{D@n}}{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIKj}}}}\",[]]Cd[\"{{{AHOh{CGbAAl}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbA@j}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Ce[\"{{{AHOh{CGbAB@b}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Ce[\"{{{AHOh{CGbAHBf}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbAAn}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Cd[\"{{{AHOh{CGbAB`}}{AHOh{AIJh}}}{{KGh{ICfIEj}}}}\",[]]Bo[\"{{{AHOh{CGbBABd}}BH@f}{{AHOh{CGbBABd}}}}\",[]]Bo[\"{{{AHOh{CGbBABh}}BH@h}{{AHOh{CGbBABh}}}}\",[]]Aj[\"{{{AHOh{BBMh}}}CN`}\",[]]Aj[\"{{{AHOh{BBMj}}}CN`}\",[]]Cd[\"{{{AHOh{CGbB@Kh}}{A@d{A`}}}{{AHOh{CGbB@Kh}}}}\",[]]Cd[\"{{{AHOh{CGbB@Kl}}{A@d{A`}}}{{AHOh{CGbB@Kl}}}}\",[]]Cl[\"{{BBMh{KG`{BABd}}{A@f{BBL`}}{A@d{NMh}}}{{KGj{ABAd}}}}\",[]]Aj[\"{{{AHOh{ABAl}}}DBn}\",[]]Aj[\"{{{AHOh{ABAn}}}DBn}\",[]]Ca[\"{{{AHOh{CGbAILj}}NKdAINf}{{KGh{ICfBHDf}}}}\",[]]Bd[\"{{{AHOh{BHE`}}}{{ABj{BCOb}}}}\",[]]Bj[\"{{{AHOh{AILh}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bm[\"{{{AHOh{CGbAILj}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}KC`}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KC`}{{AHOh{CGbBCOn}}}}\",[]]Bm[\"{{}{{KGh{{KBn{BBLbBFIl}}{A@f{IE`}}}}}}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]A`[\"{AIMdCN`}\",[]]A`[\"{AIMfCN`}\",[]]An[\"{{{AHOh{ABAd}}B@Kh}ICf}\",[]]Dc[\"{{{AHOh{CGbAILj}}NKdKGd{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIL`}}}}\",[]]o[\"{{}AHOh}\",[]]Aj[\"{{{AHOh{AILh}}}KC`}\",[]]Bn[\"{{{AHOh{CGbBABd}}CN`}{{AHOh{CGbBABd}}}}\",[]]Bn[\"{{{AHOh{CGbBABh}}CN`}{{AHOh{CGbBABh}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}KId}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}KIf}{{AHOh{CGbBCOn}}}}\",[]]:Bc[\"{{{AHOh{CGbAILj}}A@nKIf}ICf}\",[]]A`[\"{AHFdCN`}\",[]]A`[\"{AHFfCN`}\",[]]Ak[\"{{}{{KGh{B@KhIEn}}}}\",[]]Ak[\"{{}{{KGh{B@KlIF`}}}}\",[]]Bn[\"{{{AHOh{CGbBCOl}}DBn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]87Cg[\"{{{AHOh{CGbAAl}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbA@j}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Ch[\"{{{AHOh{CGbAB@b}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Ch[\"{{{AHOh{CGbAHBf}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbAAn}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Cg[\"{{{AHOh{CGbAB`}}{AHOh{CGbAIJh}}}{{KGh{ICfIEj}}}}\",[]]Bi[\"{{{AHOh{CGbAHCl}}{AHOh{AHCl}}}DBn}\",[]]n[\"{{}ICf}\",[]]Ce[\"{{{AHOh{CGbBCOl}}{KG`{KC`}}}{{AHOh{CGbBCOl}}}}\",[]]Ce[\"{{{AHOh{CGbBCOn}}{KG`{KC`}}}{{AHOh{CGbBCOn}}}}\",[]]Bn[\"{{{AHOh{AILh}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Cd[\"{{{AHOh{CGbAILj}}NKd}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Am[\"{{{AHOh{CGbAILl}}}ICf}\",[]]Al[\"{{{AHOh{CGbCNh}}}ICf}\",[]]Al[\"{{{AHOh{CGbIDd}}}ICf}\",[]]Am[\"{{{AHOh{CGbAILn}}}ICf}\",[]]Al[\"{{{AHOh{CGbCNj}}}ICf}\",[]]Al[\"{{{AHOh{CGbIDf}}}ICf}\",[]]Ai[\"{AILf{{KGl{ICf}}}}\",[]]Bj[\"{{{AHOh{AILh}}AJ@n}{{KGh{ICfIFd}}}}\",[]]Bm[\"{{{AHOh{CGbAILj}}AJ@n}{{KGh{ICfIFd}}}}\",[]]D`[\"{{{AHOh{CGbAILj}}KGd{KG`{ABA`}}}{{KGh{{KG`{ABA`}}AIL`}}}}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{A@d{BFBd}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{A@d{BFBf}}}{{AHOh{CGbBCOn}}}}\",[]]Cf[\"{{{AHOh{CGbBCOl}}{KG`{ABA`}}}{{AHOh{CGbBCOl}}}}\",[]]Cf[\"{{{AHOh{CGbBCOn}}{KG`{ABA`}}}{{AHOh{CGbBCOn}}}}\",[]]Ce[\"{{{AHOh{CGbBCOl}}{KG`{CN`}}}{{AHOh{CGbBCOl}}}}\",[]]Ce[\"{{{AHOh{CGbBCOn}}{KG`{CN`}}}{{AHOh{CGbBCOn}}}}\",[]]Aa[\"{BAOjAINd}\",[]]Aa[\"{BAOlAINd}\",[]];Bn[\"{{{AHOh{CGbBCOl}}DBn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}DBn}{{AHOh{CGbBCOn}}}}\",[]]Am[\"{{{AHOh{AILh}}KId}ICf}\",[]]o[\"{NJ`NJ`}\",[]]Bn[\"{{{AHOh{CGbBCOl}}CMn}{{AHOh{CGbBCOl}}}}\",[]]Bn[\"{{{AHOh{CGbBCOn}}CMn}{{AHOh{CGbBCOn}}}}\",[]]310;:54Bn[\"{{{AHOh{AILh}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]Bn[\"{{{AHOh{AILj}}}{{KGh{{ABj{AJ@n}}IFd}}}}\",[]]10A`[\"{BGAhKG`}\",[]]Bm[\"{{{AHOh{CGbBCOl}}Oj}{{AHOh{CGbBCOl}}}}\",[]]Bm[\"{{{AHOh{CGbBCOn}}Oj}{{AHOh{CGbBCOn}}}}\",[]]o[\"{{}AINf}\",[]]") \ No newline at end of file diff --git a/pr/619/docs/search.index/generic_inverted_index/4d33a67ed87f.js b/pr/619/docs/search.index/generic_inverted_index/4d33a67ed87f.js deleted file mode 100644 index 11baa20e6..000000000 --- a/pr/619/docs/search.index/generic_inverted_index/4d33a67ed87f.js +++ /dev/null @@ -1 +0,0 @@ -rb_("QU9gADswAAABAADuAAIAawPtAFoMAAA7MAAAAQAAawIsACMCFwA8AgwASgIAAE0CAABPAgAAUQIDAFYCAABZAgAAWwIGAGQCAABoAgIAbAIJAHgCAAB6AgYAggIEAIkCAACLAgIAjwIBAJICBACYAgsApQIDAKoCAAC1AhcA0gIDANcCEgDrAgMA8AIDAPUCBAD8AgUAAwMEAAkDBgARAwQAFwMAABkDBgAhAwQAJwMDACwDAgAzAwAAOwMLAEgDDQB6CYwABwvtABUQAADCEAEAOzAAAAEAAN4BEACYAAIAzwXtAAcKNQBAChMAVQoFAFwKGwB6CgEAfgoUAJQKAACXCh8AuAoEAL4KKgDqCgAA7AoAAO4KAADwChYAOzAAAAEAACYBCwBrAgAA1gIAAEcDAACIBxMAtwoAAL0KAADpCgAA7woAAJ8OBwEbEAEAUxABADswAAABAACFAQYAXwQAAEYJAQDrCgAA7QoAABwNegHYEQUAOzAAAAEAAAYAAgDaBgMA3wYCADswAAABAAApAAUAVgMUAJoFAADVBgQA4wYMAEEJAQA7MAAAAQAACgACAHwEAAD1CwkAOzAAAAEAAAwAAQBrBAwAOzAAAAEAAAUAAgBwDAMAWBEBAALEEQAAxREAAAAAAALQAQAA3gYAAERmAAAAOzAAAAEAAO0ADgAHCjUAQAoTAFUKBQBcChsAegoBAH4KFACUCgAAlwofALgKBAC+CioA6goAAOwKAADuCgAA8AoWAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/generic_inverted_index/828b7994c50d.js b/pr/619/docs/search.index/generic_inverted_index/828b7994c50d.js new file mode 100644 index 000000000..7635c9fd7 --- /dev/null +++ b/pr/619/docs/search.index/generic_inverted_index/828b7994c50d.js @@ -0,0 +1 @@ +rb_("QU9gADswAAABAADuAAIAawPtAFoMAAA7MAAAAQAAawIsACMCFwA8AgwASgIAAE0CAABPAgAAUQIDAFYCAABZAgAAWwIGAGQCAABoAgIAbAIJAHgCAAB6AgUAgQIEAIgCAQCLAgIAjwICAJMCBACZAgsApgICAK4CAAC1AhcA0gIDANcCEgDrAgMA8AIDAPUCBAD8AgUAAwMEAAkDBgARAwQAFwMAABkDBgAhAwQAJwMDACwDAgAzAwAAOwMLAEgDDQB6CYwABwvtABUQAADCEAEAOzAAAAEAAN4BEACYAAIAzwXtAAcKNQBAChQAVgoFAF0KGwB7CgEAfwoTAJQKAACXCh8AuAoEAL4KKgDqCgAA7AoAAO4KAADwChYAOzAAAAEAACYBCwBrAgAA1gIAAEcDAACIBxMAtwoAAL0KAADpCgAA7woAAJ8OBwEbEAEAUxABADswAAABAACFAQYAXwQAAEYJAQDrCgAA7QoAABwNegHXEQUAOzAAAAEAAAYAAgDaBgMA3wYCADswAAABAAApAAUAVgMUAJoFAADVBgQA4wYMAEEJAQA7MAAAAQAACgACAHwEAAD1CwkAOzAAAAEAAAwAAQBrBAwAOzAAAAEAAAUAAgBwDAMAWBEBAALEEQAAxREAAAAAAALQAQAA3gYAAERmAAAAOzAAAAEAAO0ADgAHCjUAQAoUAFYKBQBdChsAewoBAH8KEwCUCgAAlwofALgKBAC+CioA6goAAOwKAADuCgAA8AoWAA==") \ No newline at end of file diff --git a/pr/619/docs/search.index/name/3b16bb0727a1.js b/pr/619/docs/search.index/name/13e9ded8cacd.js similarity index 59% rename from pr/619/docs/search.index/name/3b16bb0727a1.js rename to pr/619/docs/search.index/name/13e9ded8cacd.js index 927b3dd61..5dfe67a71 100644 --- a/pr/619/docs/search.index/name/3b16bb0727a1.js +++ b/pr/619/docs/search.index/name/13e9ded8cacd.js @@ -1 +1 @@ -rd_("b()b->bBi0bCe00bFnbIdbOkb[]beq0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bid000000000000000000brtbtybu8cAck0cAddcAnycArccBoxcBufcClicDir0cErrcMAX000cNotcOpt00cOrdcPincUni0cVeccadd00000ccmp0000000000000000000cdir000cecn000cf32cf64cfmt0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cget0ci32cimpcios0clen000clog0cmincmutcnew0000000000000000000000000000000000cnoqcnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdArgsdAsFddBbr300dDropdEct000dEct100dFromdHashdIntodKeys0dLong0dNonedPath00dPing0dPolldReaddSide0dZERO0dacks0daddr00dbbr3dbooldbulkdcodedcwnd0ddataddrop000000dfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnext0dopen00dpath0dperfdping000dpoll00000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128duniteAsRefeByteseChunk0eCloneeCloseeCubic00eDebugeDerefeError00000000000eEvent00eKnowneOther0eRangeeReset000eRetry0eShort0eSizedeStats0eSuiteeTokioeWriteealpns0earrayebenchebuild00000000ebytes00000ecauseeclone00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerroreframe0eindex0eis_ce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats000000000etitle0etokenetokioetupleeusizeewrite00fAcceptfAckEcn0fAes128fAes256fBackup0fBorrowfBufMutfChunksfClient00fClosedfCrypto0fCursorfFuturefHasherfIpAddrfLaggedfOpenBifOpened00000fOptionfPathId0fResult00000fServer00fStream000fStringfTypeIdfVarInt0faccept000fborrow000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode000000000000fdst_ipfencode000000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0fon_ack0000000fpacket00frandomfreason0000000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000fsrc_ip00fstatus00fstream0fstridefudp_rx000fudp_tx000fvarintfverify0fwindow0000000gBlocked00gCommandgContextgDefaultgDisplaygFromStrgGeneral0gHmacKey0gInitialgInstantgKeyPair0gLayeredgMaxData0gNewReno00gOpenUnigPadding0gPathAck0gPathBufgReadBufgRequestgRuntime0gSession0gStopped00000gStreamsgToOwnedgTooLonggTryFromgTryIntogUnknowngWritten0gZeroRttgcid_len000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt00000gdefault00000000000000000000000000000000000000000000000000000gdrainedgdst_cid0000000gencrypt000gis_0rtt0gmetrics0000000gmin_mtu0gnoq_udpgon_sent0gopen_bigpath_idgpointergruntimegsrc_cid0000gstopped0gstreams000gtag_len0gtype_id000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgrade0gversion00000hAcceptBihBytesMuthChacha20hCommandshDatagram00hDerefMuthDisabled0hDurationhEndpoint00hFinished0hIncoming0hIteratorhLayerExthLongTypehMAX_SIZE0hNO_ERROR0hNewToken0hOnClosedhOpenPathhOrderinghReadable0hRecvMetahResponsehStreamId0hTimedOut00hToStringhTokenLog0hTooLarge0hTransmit00hUdpStats0hUnixTimehWritable0hcong_alghcontentshdatagram0hdurationhendpoint0hfinalizehframe_rx000hframe_tx000hfrom_buf0hfrom_env0hfrom_keyhfrom_str0hfrom_u320hfrom_u640hgot_type000hgroup_id0000hhas_0rtthincominghinterval0hinto_any0000000his_alivehlifetime0hlocal_ip0000hmax_data0hmax_sizehnew_renohnoq_perfhon_byteshopen_unihpriority0hprotocol0hqlog_dirhresponsehrng_seed0hssthresh0hto_owned00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_from000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_into000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_poll000000000htry_sendhvalidate000iAbandoned000iAcceptUniiAddAssigniArbitraryiAsyncRead0iAvailable000iBorrowMutiCommonOptiConnectediCriterioniDatagramsiDecodableiDiscarded000iEncodableiFormatteriFourTupleiFrameType0iHandshakeiHeaderKey0iHistogramiMalformediMaxPathId0iMultipathiPacketKey0iPartialEqiPathError0iPathEvent000iPathStats0iReadError00iTryFutureiTryStreamiUdpSenderiUdpSocketiValueEnumiaccept_biiarbitrary0000000ias_rustlsiassemblericlone_box0000000idatagrams000ideref_mut0ifrom_bits00iinitiator0iinto_0rttiinto_iteriis_client0iis_closediis_server0imay_retry0imigration0inew_timer00inew_token0inoq_protoion_closediopen_path0ipath_acks0iping_pathipoll_next000ipoll_read00ipoll_recvipoll_sendireach_out0ireferenceireset_key0iretry_tag0000isize_hint000istable_idito_string000000000000000000000000000000000000000000000000000000000000000000itoken_key0itoken_positransport00iwait_idleiwrite_alljArgMatchesjAsyncTimerjAsyncWrite0jBATCH_SIZEjBbr3Config0jClosedPath00000jComparablejConnectingjConnection00jController0jEquivalent0jFrameStats0jIntoFuturejInvalidCid0jIoSliceMutjMaybeFrame0jNamedGroupjNonZeroU32jOtherErrorjPartialOrdjPathAckEcn0jPathEventsjPathStatus0jQlogConfig0jRecvStream00jResetErrorjRetryError0jSendStream00jServerNamejSocketAddrjStreamInfojSubcommandjSystemTimejTimeSource0jTlsSession0jTokenStore0jUdpSockRefjWriteError0jaccept_unijadd_assign00000jallow_spin0jborrow_mut000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclone_into00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclose_pathjcongestion000jconn_statsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jerror_code000000jframe_type0jinto_inner0jis_drained0jlocal_addr0jlost_bytes000jnew_senderjpad_to_mtu0jpath_stats000jpoll_closejpoll_flush0jpoll_write00jprint_jsonjread_chunk0jread_exactjset_statusjstart_time0jthroughputjtotal_sizekAcceptErrorkCLIENT_ADDRkCipherSuitekClientStatskCloseReasonkConfigError0kContentTypekCryptoError0kCubicConfig0kDataBlocked0kFinishErrorkIdleTimeout0kIntoRequestkOutOfBounds0kPathAbandon0kQlogFactory0kResetStream0kRuntimeTypekSERVER_ADDRkSERVER_NAMEkSmolRuntimekStopSending0kStreamEvent0kStreamStats0kUnspecifiedkaccept_withkadd_address0kbind_socketkcertificatekcurrent_mtu00kdescription0kdestination00kfrom_remotekinitial_mtu000kinitial_rtt00kinto_future0000000000000kmax_path_id0kmax_streamsknamed_layer0kon_end_acks000kon_intervalkpacing_rate0kpartial_cmp0000000000000000000kpath_eventskpath_statuskread_chunkskread_to_endkrecv_stream0ksample_size0ksend_bufferksend_stream0ksend_window00kserver_name0ktime_source0ktoken_store0kupload_sizekupper_bound0kweak_handle0kwith_crypto0kwith_prefix0kwrite_chunklAckFrequency0lAddressAddedlClientConfig00000lClosedStream000000lConnectError00lConnectionId00lDatagramInfolDecryptError0lEcnCodepoint00lEncryptError0lIllegalValuelImmediateAck0lIntoIteratorlLOCALHOST_V4lLastOpenPath0lNatTraversallNonZeroUsizelNoneTokenLog0lObservedAddr000lPathResponse0lPathsBlocked0lReadDatagramlRemoteStatus000lRttEstimator0lSendDatagramlServerConfig00000lSocketAddrV4lSocketAddrV6lStoppedErrorlTokioRuntimelUnstructuredlaugment_args0000lcid_lifetime000lclose_reasonlconnect_withlconservativeldata_blocked0ldrain_streamlearly_crypto000levent_streamlexpect_types000lgenerate_cid000lgro_segmentslhandle_event0linitial_keys00000000linto_request0llost_packets000lmax_incoming0lmay_fragment00lnetwork_pathlnew_receiverlnoprotection0lorig_dst_cid0lpath_abandon0lpoll_timeoutlqlog_factory0lreset_stream0lruntime_typelsegment_size00lsend_quantum0lsend_streamslset_lifetime0lset_priority0lstop_sending0lstream_statslupload_statslwith_initial000lwrite_chunks0mAlertReceived0mBloomTokenLog0mCidsExhausted000mCloneToUninitmDatagramEventmEndpointEventmEndpointStatsmFinishedEarlymHandshakeData0mHandshakeDone0mHandshakeTypemINVALID_TOKEN0mIncomingAlpns0mInvalidHeadermLocallyClosed0mMaxStreamData0mMaxStreamsUni0mNewConnectionmNewRenoConfig0mParseIntErrormPartialDecodemPathChallenge0mPossibleValuemPrivateKeyDermReadableErrormRemoveAddress0mRootCertStoremStdSystemTime0mUnexpectedEndmaccepted_0rttmack_frequency00mbench_exports0mcid_generator00mcreate_sendermdata_transfermdownload_sizemduration_histmimmediate_ack0minto_incoming0mmax_ack_delay0mno_protectionmobserved_addr0mon_first_bytemon_mtu_update0000000mpath_response0mpaths_blocked0mpeer_identity0000mpoll_shutdownmpoll_transmitmqlog_from_env0mread_datagrammsend_datagrammsend_fairness0msignature_len0mstart_session000000000mtry_poll_next0nAddIpv4Address0nAddIpv6Address0nAddressRemovednAsyncUdpSocketnCertificateDernClosePathError0nCommandFactorynConnectionLost000000nEndpointConfig0nFromArgMatchesnINTERNAL_ERROR0nIncomingFuturenInvalidFrameIdnInvalidMessage00nMaxStreamsBidi0nNO_VIABLE_PATH0nNoneTokenStore0nPeerMisbehaved00nReachOutAtIpv40nReachOutAtIpv60nReadExactErrornReadToEndErrornShouldTransmitnTransferResultnTransportError00nUdpSocketStatenWeakPathHandlenconnect_clientncrypto_sessionndownload_statsnfor_connection000nhandle_timeoutnhandshake_data00000nhandshake_done0nhas_subcommandninitial_window0000000000000ninto_unorderednis_handshaking0000nis_valid_retry000nminimum_change0nnext_1rtt_keys000non_packet_lost000non_packet_sent000npath_challenge0nqlog_from_path0nread_handshake000nread_unorderednreceive_window00nreceived_reset00nremote_address0000nremove_address0nsaturating_add000nsaturating_sub0nthroughput_bpsntime_threshold0ntotal_durationnvalue_variantsoConnectionClose000oConnectionError0oConnectionEvent0oConnectionStats0oGetRandomFailedoNewConnectionId0oOpenStreamStatsoPathCidsBlocked0oProtectedHeader0oQlogFileFactory0oRemoteAbandoned0oSignatureSchemeoSystemTimeErroroTokenReuseError0oTransportConfig00oTryFromIntErroroVersionMismatch0oZeroRttAcceptedoZeroRttRejected000obloom_token_logoclone_to_uninit00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000odefault_runtimeogrease_quic_bit0ointegrity_limit0ointerface_indexomax_stream_data0omax_streams_uni0oparse_byte_sizeorebind_abstractosend_unreliableoserver_endpointoset_path_statusoset_send_window0oshould_transmitostream_finishedothroughput_histowrap_udp_socket00owrite_handshake000A`AddressDiscoveryA`ApplicationClose000A`CertificateErrorA`ConnectionClosed0A`ConnectionHandleA`DatagramReceivedA`DecryptedInitial0A`EndpointStopping0A`FINAL_SIZE_ERROR0A`InconsistentKeys00A`KEY_UPDATE_ERROR0A`MaxPathIdReached0A`ObservedIpv4Addr0A`ObservedIpv6Addr0A`PathStatusBackup0A`PeerIncompatible00A`QuicClientConfig0A`QuicServerConfig0A`TokenMemoryCache0A`TooManyAddressesA`ValidationFailed00A`VersionNegotiate0A`check_and_insert00000A`configure_clientA`congestion_state0A`connection_close0A`force_key_update0A`from_arg_matches00000A`max_gso_segmentsA`max_idle_timeout0A`max_streams_bidi0A`n0_nat_traversal0A`open_connections0A`open_path_ensure0A`packet_threshold0A`receive_datagramA`recv_buffer_size0A`send_buffer_size0A`transport_config0000A`validation_token0A`with_single_cert0A`write_all_chunksAaAPPLICATION_ERROR0AaApplicationClosed000AaControllerFactory0AaControllerMetrics0AaHandshakeTokenKey0AaInvalidServerName0AaNetworkChangeHint0AaPacketDecodeError0AaPathAbandonReason00AaSendDatagramError0AaStreamDataBlocked0AaStreamsBlockedUni0AaUnsupportedByPeer0Aacongestion_events0Aacongestion_window0Aamax_datagram_sizeAanew_connection_id0Aapath_cids_blocked0Aasend_buffer_spaceAaset_server_config0Aaset_up_connectionAato_possible_valueAbAEAD_LIMIT_REACHED0AbAckFrequencyConfig0AbBadMaxFragmentSize0AbCONNECTION_REFUSED0AbConnectionIdParserAbDatagramsUnblockedAbFLOW_CONTROL_ERROR0AbHandshakeConfirmedAbHandshakeDataReadyAbIllegalOrderedReadAbInvalidCertificate0AbMtuDiscoveryConfig0AbNotEnoughAddressesAbPERF_CIPHER_SUITESAbPROTOCOL_VIOLATION0AbPrivatePkcs8KeyDerAbRetireConnectionId0AbSTREAM_LIMIT_ERROR0AbSTREAM_STATE_ERROR0AbServerCertVerifiedAbServerCertVerifierAbSetPathStatusError0AbStreamsBlockedBidi0AbTokioCurrentThreadAbTransportErrorCode0AbUnsupportedVersion00000Abcommand_for_update0000Abcrypto_buffer_size0Abfrom_u64_unchecked0Abignored_handshakesAbis_same_connectionAbmin_reset_interval0Abnew_expected_items0Abpath_status_backup0Abrefused_handshakesAbremote_path_statusAbsend_datagram_waitAbset_alpn_protocols000Abset_receive_window0Absupported_versions0Abtoken_memory_cacheAbverify_server_certAbwith_start_instant0AcCongestionAlgorithmAcNatTraversalUpdatesAcPathNewConnectionId0AcPathStatusAvailable0AcRemoteCidsExhausted0AcTransportParametersAcUnorderedRecvStreamAcUnsupportedNameType0AcWrongConnectionSideAcaccepted_handshakesAcarbitrary_take_rest000Acaugment_subcommandsAcblack_hole_cooldown0Acearly_data_accepted000Achandshake_confirmedAcis_path_recoverable0Ackeep_alive_interval0Aclost_plpmtud_probes0Acon_congestion_event0000000Acoutgoing_handshakesAcremote_open_streamsAcsend_buffer_benches00Acsend_data_on_streamAcsent_plpmtud_probes0Acstream_data_blocked0Acstreams_blocked_uni0AdFRAME_ENCODING_ERROR0AdHandshakeNotComplete0AdInappropriateMessage000AdInvalidRemoteAddress000AdNoInitialCipherSuite0AdObservedExternalAddrAdServerSideNotAllowed0AdSupportedCipherSuiteAdVarIntBoundsExceeded0AdVerifierBuilderErrorAdWeakConnectionHandleAdack_frequency_config0Adblack_holes_detected0Adfrom_arg_matches_mut00000Adhandle_client_streamAdincoming_buffer_size0Adis_multipath_enabledAdmax_receive_segments0Admax_udp_payload_size00Admtu_discovery_config0Adpoll_endpoint_eventsAdpreferred_address_v40Adpreferred_address_v60Adread_certs_from_fileAdreordering_threshold0Adretire_connection_id0Adretry_token_lifetime0Adset_max_idle_timeoutAdset_recv_buffer_sizeAdset_send_buffer_sizeAdstreams_blocked_bidi0Adtransport_parameters00000AeConnectionIdGenerator0AeDigitallySignedStructAeNoApplicationProtocol0AeNoDefaultClientConfig0AePATH_UNSTABLE_OR_POOR0AeValidationTokenConfig0Aeconfidentiality_limit0Aehandle_network_change0Aeincoming_buffer_bytesAeis_probably_same_pathAeloss_reduction_factor0Aemax_transmit_segments0Aenat_traversal_updatesAepath_observed_addressAepath_status_available0Aestream_receive_window00AfCRYPTO_BUFFER_EXCEEDED0AfExtensionNotNegotiatedAfFailedToGetCurrentTime0AfFailedToGetRandomBytes0AfMultipathNotNegotiated000000AfNatTraversalRoundEndedAfPathRetireConnectionId0AfProtectedInitialHeaderAfSkipServerVerificationAfbuild_transport_configAfexport_keying_material0000Afget_into_many_segmentsAfget_loop_many_segmentsAfmax_concurrent_streamsAfobserved_external_addr0Afpath_new_connection_id0Afverify_tls12_signatureAfverify_tls13_signatureAfwith_root_certificates0AgCertRevocationListErrorAgHandshakeSignatureValidAgNoCertificatesPresented0AgPeerSentOversizedRecord0Agack_eliciting_threshold0Agaugment_args_for_update0000Aghas_pending_retransmitsAgis_multipath_negotiatedAgon_ack_frequency_update000Agset_keep_alive_intervalAgupdate_from_arg_matches00000Agvalidation_token_config0AhAPPLICATION_ABANDON_PATH0AhNoProtectionClientConfigAhNoProtectionServerConfigAhget_max_udp_payload_size0Ahinitial_dst_cid_provider0Ahnew_with_abstract_socketAhremote_address_validated0Ahset_max_concurrent_pathsAhsupported_verify_schemesAiCONNECTION_ID_LIMIT_ERROR0AiEncryptedClientHelloErrorAiExportKeyingMaterialError0AiInvalidCertRevocationList0AiNO_CID_AVAILABLE_FOR_PATH0AiTRANSPORT_PARAMETER_ERROR0AiUnsupportedOperationErrorAiadd_nat_traversal_address0Aidatagram_send_buffer_size0Aigenerate_self_signed_certAiopen_bidirectional_streamAipath_retire_connection_id0Aiset_default_client_configAiset_path_max_idle_timeoutAjDEFAULT_SUPPORTED_VERSIONSAjUnusableAfterNetworkChangeAjdatagram_send_buffer_spaceAjincoming_buffer_size_total0Ajmax_concurrent_uni_streams0Ajopen_unidirectional_streamAjset_max_concurrent_streamsAjspurious_congestion_events0Ajtry_with_platform_verifier0AkHashedConnectionIdGeneratorAkInvalidEncryptedClientHello0AkPATH_RESOURCE_LIMIT_REACHED0AkRandomConnectionIdGeneratorAkenable_segmentation_offload0Akmax_concurrent_bidi_streams0Akupdate_from_arg_matches_mut00000Akupdate_local_if_same_remoteAlconfigure_tracing_subscriberAldatagram_receive_buffer_size0Alinitiate_nat_traversal_round0Alon_spurious_congestion_event00000Alreceive_bidirectional_streamAlremove_nat_traversal_address0Alset_path_keep_alive_intervalAmFixedLengthConnectionIdParserAmInappropriateHandshakeMessage000Amcongestion_controller_factory0Amdefault_path_max_idle_timeout0Ammax_outgoing_bytes_per_second0Amnegotiated_key_exchange_group0Amreceive_unidirectional_streamAmsend_observed_address_reports0Amset_max_concurrent_bi_streamsAnaugment_subcommands_for_updateAnmax_concurrent_multipath_paths0Anset_max_concurrent_uni_streamsAopersistent_congestion_threshold0B`default_path_keep_alive_interval0B`receive_observed_address_reports0Baget_local_nat_traversal_addresses0Bbget_remote_nat_traversal_addresses0Bbmax_remote_nat_traversal_addressesBfset_max_remote_nat_traversal_addresses0BoDEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED") \ No newline at end of file +rd_("b()b->bBi0bCe00bFnbIdbOkb[]beq0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bid000000000000000000brtbtybu8cAck0cAddcAnycArccBoxcBufcClicDir0cErrcMAX000cNotcOpt00cOrdcPincUni0cVeccadd00000ccmp0000000000000000000cdir000cecn000cf32cf64cfmt0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cget0ci32cimpcios0clen000clog0cmincmutcnew0000000000000000000000000000000000cnoqcnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdArgsdAsFddBbr300dDropdEct000dEct100dFromdHashdIntodKeys0dLong0dNonedPath00dPing0dPolldReaddSide0dZERO0dacks0daddr00dbbr3dbooldbulkdcodedcwnd0ddataddrop000000dfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnext0dopen00dpath0dperfdping000dpoll00000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128duniteAsRefeByteseChunk0eCloneeCloseeCubic00eDebugeDerefeError00000000000eEvent00eKnowneOther0eRangeeReset000eRetry0eShort0eSizedeStats0eSuiteeTokioeWriteealpns0earrayebenchebuild00000000ebytes00000ecauseeclone00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerroreframe0eindex0eis_ce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats000000000etitle0etokenetokioetupleeusizeewrite00fAcceptfAckEcn0fAes128fAes256fBackup0fBorrowfBufMutfChunksfClient00fClosedfCrypto0fCursorfFuturefHasherfIpAddrfLaggedfOpenBifOpened00000fOptionfPathId0fResult00000fServer00fStream000fStringfTypeIdfVarInt0faccept000fborrow000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode000000000000fdst_ipfencode000000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0fon_ack0000000fpacket00frandomfreason0000000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000fsrc_ip00fstatus00fstream0fstridefudp_rx000fudp_tx000fvarintfverify0fwindow0000000gBlocked00gCommandgContextgDefaultgDisplaygFromStrgGeneral0gHmacKey0gInitialgInstantgKeyPair0gLayeredgMaxData0gNewReno00gOpenUnigPadding0gPathAck0gPathBufgReadBufgRequestgRuntime0gSession0gStopped00000gStreamsgToOwnedgTooLonggTryFromgTryIntogUnknowngWritten0gZeroRttgcid_len000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt00000gdefault00000000000000000000000000000000000000000000000000000gdrainedgdst_cid0000000gencrypt000gis_0rtt0gmetrics0000000gmin_mtu0gnoq_udpgon_sent0gopen_bigpath_idgpointergruntimegsrc_cid0000gstopped0gstreams000gtag_len0gtype_id000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgrade0gversion00000hAcceptBihBytesMuthChacha20hCommandshDatagram00hDerefMuthDisabled0hDurationhEndpoint00hFinished0hIncoming0hIteratorhLayerExthLongTypehMAX_SIZE0hNO_ERROR0hNewToken0hOnClosedhOpenPathhOrderinghReadable0hRecvMetahResponsehStreamId0hTimedOut00hToStringhTokenLog0hTooLarge0hTransmit00hUdpStats0hUnixTimehWritable0hcong_alghcontentshdatagram0hdurationhendpoint0hfinalizehframe_rx000hframe_tx000hfrom_buf0hfrom_env0hfrom_keyhfrom_str0hfrom_u320hfrom_u640hgot_type000hgroup_id0000hhas_0rtthincominghinterval0hinto_any0000000his_alivehlifetime0hlocal_ip0000hmax_data0hmax_sizehnew_renohnoq_perfhon_byteshopen_unihpriority0hprotocol0hqlog_dirhresponsehrng_seed0hssthresh0hto_owned00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_from000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_into000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_poll000000000htry_sendhvalidate000iAbandoned000iAcceptUniiAddAssigniArbitraryiAsyncRead0iAvailable000iBorrowMutiCommonOptiConnectediCriterioniDatagramsiDecodableiDiscarded000iEncodableiFormatteriFourTupleiFrameType0iHandshakeiHeaderKey0iHistogramiMalformediMaxPathId0iMultipathiPacketKey0iPartialEqiPathError0iPathEvent000iPathStats0iReadError00iTryFutureiTryStreamiUdpSenderiUdpSocketiValueEnumiaccept_biiarbitrary0000000ias_rustlsiassemblericlone_box0000000idatagrams000ideref_mut0ifrom_bits00iinitiator0iinto_0rttiinto_iteriis_client0iis_closediis_server0imay_retry0imigration0inew_timer00inew_token0inoq_protoion_closediopen_path0ipath_acks0iping_pathipoll_next000ipoll_read00ipoll_recvipoll_sendireach_out0ireferenceireset_key0iretry_tag0000isize_hint000istable_idito_string000000000000000000000000000000000000000000000000000000000000000000itoken_key0itoken_positransport00iwait_idleiwrite_alljArgMatchesjAsyncTimerjAsyncWrite0jBATCH_SIZEjBbr3Config0jClosedPath00000jComparablejConnectingjConnection00jController0jEquivalent0jFrameStats0jIntoFuturejInvalidCid0jIoSliceMutjMaybeFrame0jNamedGroupjNonZeroU32jOtherErrorjPartialOrdjPathAckEcn0jPathEventsjPathStatus0jQlogConfig0jRecvStream00jResetErrorjRetryError0jSendStream00jServerNamejSocketAddrjStreamInfojSubcommandjSystemTimejTimeSource0jTlsSession0jTokenStore0jUdpSockRefjWriteError0jaccept_unijadd_assign00000jallow_spin0jborrow_mut000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclone_into00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclose_pathjcongestion000jconn_statsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jerror_code000000jframe_type0jinto_inner0jis_drained0jlocal_addr0jlost_bytes000jnew_senderjpad_to_mtu0jpath_stats000jpoll_closejpoll_flush0jpoll_write00jprint_jsonjread_chunk0jread_exactjset_statusjstart_time0jthroughputjtotal_sizekAcceptErrorkCLIENT_ADDRkCipherSuitekClientStatskCloseReasonkConfigError0kContentTypekCryptoError0kCubicConfig0kDataBlocked0kFinishErrorkIdleTimeout0kIntoRequestkOutOfBounds0kPathAbandon0kQlogFactory0kResetStream0kRuntimeTypekSERVER_ADDRkSERVER_NAMEkSmolRuntimekStopSending0kStreamEvent0kStreamStats0kUnspecifiedkaccept_withkadd_address0kbind_socketkcertificatekcurrent_mtu00kdescription0kdestination00kfrom_remotekinitial_mtu000kinitial_rtt00kinto_future0000000000000kmax_path_id0kmax_streamsknamed_layer0kon_end_acks000kon_intervalkpacing_rate0kpartial_cmp0000000000000000000kpath_eventskpath_statuskread_chunkskread_to_endkrecv_stream0ksample_size0ksend_bufferksend_stream0ksend_window00kserver_name0ktime_source0ktoken_store0kupload_sizekupper_bound0kweak_handle0kwith_crypto0kwith_prefix0kwrite_chunklAckFrequency0lAddressAddedlClientConfig00000lClosedStream000000lConnectError00lConnectionId00lDatagramInfolDecryptError0lEcnCodepoint00lEncryptError0lIllegalValuelImmediateAck0lIntoIteratorlLOCALHOST_V4lLastOpenPath0lNatTraversallNonZeroUsizelNoneTokenLog0lObservedAddr000lPathResponse0lPathsBlocked0lReadDatagramlRemoteStatus000lRttEstimator0lSendDatagramlServerConfig00000lSocketAddrV4lSocketAddrV6lStoppedErrorlTokioRuntimelUnstructuredlaugment_args0000lcid_lifetime000lclose_reasonlconnect_withlconservativeldata_blocked0ldrain_streamlearly_crypto000levent_streamlexpect_types000lgenerate_cid000lgro_segmentslhandle_event0linitial_keys00000000linto_request0llost_packets000lmax_incoming0lmay_fragment00lnetwork_pathlnew_receiverlnoprotection0lorig_dst_cid0lpath_abandon0lpoll_timeoutlqlog_factory0lreset_stream0lruntime_typelsegment_size00lsend_quantum0lsend_streamslset_lifetime0lset_priority0lstop_sending0lstream_statslupload_statslwith_initial000lwrite_chunks0mAlertReceived0mBloomTokenLog0mCidsExhausted000mCloneToUninitmDatagramEventmEndpointEventmEndpointStatsmFinishedEarlymHandshakeData0mHandshakeDone0mHandshakeTypemINVALID_TOKEN0mIncomingAlpns0mInvalidHeadermLocallyClosed0mMaxStreamData0mMaxStreamsUni0mNewConnectionmNewRenoConfig0mParseIntErrormPartialDecodemPathChallenge0mPossibleValuemPrivateKeyDermReadableErrormRemoveAddress0mRootCertStoremStdSystemTime0mUnexpectedEndmaccepted_0rttmack_frequency00mbench_exports0mcid_generator00mcreate_sendermdata_transfermdownload_sizemduration_histmimmediate_ack0minto_incoming0mmax_ack_delay0mno_protectionmobserved_addr0mon_first_bytemon_mtu_update0000000mpath_response0mpaths_blocked0mpeer_identity0000mpoll_shutdownmpoll_transmitmqlog_from_env0mread_datagrammsend_datagrammsend_fairness0msignature_len0mstart_session000000000mtry_poll_next0nAddIpv4Address0nAddIpv6Address0nAddressRemovednAsyncUdpSocketnCertificateDernClosePathError0nCommandFactorynConnectionLost000000nEndpointConfig0nFromArgMatchesnINTERNAL_ERROR0nIncomingFuturenInvalidFrameIdnInvalidMessage00nMaxStreamsBidi0nNO_VIABLE_PATH0nNoneTokenStore0nPeerMisbehaved00nReachOutAtIpv40nReachOutAtIpv60nReadExactErrornReadToEndErrornShouldTransmitnTransferResultnTransportError00nUdpSocketStatenWeakPathHandlenconnect_clientncrypto_sessionndownload_statsnfor_connection000nhandle_timeoutnhandshake_data00000nhandshake_done0nhas_subcommandninitial_window0000000000000ninto_unorderednis_handshaking0000nis_valid_retry000nminimum_change0nnext_1rtt_keys000non_packet_lost000non_packet_sent000npath_challenge0nqlog_from_path0nread_handshake000nread_unorderednreceive_window00nreceived_reset00nremote_address000nremove_address0nsaturating_add000nsaturating_sub0nthroughput_bpsntime_threshold0ntotal_durationnvalue_variantsoConnectionClose000oConnectionError0oConnectionEvent0oConnectionStats0oGetRandomFailedoNewConnectionId0oOpenStreamStatsoPathCidsBlocked0oProtectedHeader0oQlogFileFactory0oRemoteAbandoned0oSignatureSchemeoSystemTimeErroroTokenReuseError0oTransportConfig00oTryFromIntErroroVersionMismatch0oZeroRttAcceptedoZeroRttRejected000obloom_token_logoclone_to_uninit00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000odefault_runtimeogrease_quic_bit0ointegrity_limit0ointerface_indexomax_stream_data0omax_streams_uni0oparse_byte_sizeorebind_abstractosend_unreliableoserver_endpointoset_path_statusoset_send_window0oshould_transmitostream_finishedothroughput_histowrap_udp_socket00owrite_handshake000A`AddressDiscoveryA`ApplicationClose000A`CertificateErrorA`ConnectionClosed0A`ConnectionHandleA`DatagramReceivedA`DecryptedInitial0A`EndpointStopping0A`FINAL_SIZE_ERROR0A`InconsistentKeys00A`KEY_UPDATE_ERROR0A`MaxPathIdReached0A`ObservedIpv4Addr0A`ObservedIpv6Addr0A`PathStatusBackup0A`PeerIncompatible00A`QuicClientConfig0A`QuicServerConfig0A`TokenMemoryCache0A`TooManyAddressesA`ValidationFailed00A`VersionNegotiate0A`check_and_insert00000A`configure_clientA`congestion_state0A`connection_close0A`force_key_update0A`from_arg_matches00000A`max_gso_segmentsA`max_idle_timeout0A`max_streams_bidi0A`n0_nat_traversal0A`open_connections0A`open_path_ensure0A`packet_threshold0A`receive_datagramA`recv_buffer_size0A`send_buffer_size0A`transport_config0000A`validation_token0A`with_single_cert0A`write_all_chunksAaAPPLICATION_ERROR0AaApplicationClosed000AaControllerFactory0AaControllerMetrics0AaHandshakeTokenKey0AaInvalidServerName0AaNetworkChangeHint0AaPacketDecodeError0AaPathAbandonReason00AaSendDatagramError0AaStreamDataBlocked0AaStreamsBlockedUni0AaUnsupportedByPeer0Aacongestion_events0Aacongestion_window0Aamax_datagram_sizeAanew_connection_id0Aapath_cids_blocked0Aasend_buffer_spaceAaset_server_config0Aaset_up_connectionAato_possible_valueAbAEAD_LIMIT_REACHED0AbAckFrequencyConfig0AbBadMaxFragmentSize0AbCONNECTION_REFUSED0AbConnectionIdParserAbDatagramsUnblockedAbFLOW_CONTROL_ERROR0AbHandshakeConfirmedAbHandshakeDataReadyAbIllegalOrderedReadAbInvalidCertificate0AbMtuDiscoveryConfig0AbNotEnoughAddressesAbPERF_CIPHER_SUITESAbPROTOCOL_VIOLATION0AbPrivatePkcs8KeyDerAbRetireConnectionId0AbSTREAM_LIMIT_ERROR0AbSTREAM_STATE_ERROR0AbServerCertVerifiedAbServerCertVerifierAbSetPathStatusError0AbStreamsBlockedBidi0AbTokioCurrentThreadAbTransportErrorCode0AbUnsupportedVersion00000Abcommand_for_update0000Abcrypto_buffer_size0Abfrom_u64_unchecked0Abignored_handshakesAbis_same_connectionAbmin_reset_interval0Abnew_expected_items0Abpath_status_backup0Abrefused_handshakesAbremote_path_statusAbsend_datagram_waitAbset_alpn_protocols000Abset_receive_window0Absupported_versions0Abtoken_memory_cacheAbverify_server_certAbwith_start_instant0AcCongestionAlgorithmAcNatTraversalUpdatesAcPathNewConnectionId0AcPathStatusAvailable0AcRemoteCidsExhausted0AcTransportParametersAcUnorderedRecvStreamAcUnsupportedNameType0AcWrongConnectionSideAcaccepted_handshakesAcarbitrary_take_rest000Acaugment_subcommandsAcblack_hole_cooldown0Acearly_data_accepted000Achandshake_confirmedAcis_path_recoverable0Ackeep_alive_interval0Aclost_plpmtud_probes0Acon_congestion_event0000000Acoutgoing_handshakesAcremote_open_streamsAcsend_buffer_benches00Acsend_data_on_streamAcsent_plpmtud_probes0Acstream_data_blocked0Acstreams_blocked_uni0AdFRAME_ENCODING_ERROR0AdHandshakeNotComplete0AdInappropriateMessage000AdInvalidRemoteAddress000AdNoInitialCipherSuite0AdObservedExternalAddrAdServerSideNotAllowed0AdSupportedCipherSuiteAdVarIntBoundsExceeded0AdVerifierBuilderErrorAdWeakConnectionHandleAdack_frequency_config0Adblack_holes_detected0Adfrom_arg_matches_mut00000Adhandle_client_streamAdincoming_buffer_size0Adis_multipath_enabledAdmax_receive_segments0Admax_udp_payload_size00Admtu_discovery_config0Adpoll_endpoint_eventsAdpreferred_address_v40Adpreferred_address_v60Adread_certs_from_fileAdreordering_threshold0Adretire_connection_id0Adretry_token_lifetime0Adset_max_idle_timeoutAdset_recv_buffer_sizeAdset_send_buffer_sizeAdstreams_blocked_bidi0Adtransport_parameters00000AeConnectionIdGenerator0AeDigitallySignedStructAeNoApplicationProtocol0AeNoDefaultClientConfig0AePATH_UNSTABLE_OR_POOR0AeValidationTokenConfig0Aeconfidentiality_limit0Aehandle_network_change0Aeincoming_buffer_bytesAeis_probably_same_pathAeloss_reduction_factor0Aemax_transmit_segments0Aenat_traversal_updatesAepath_observed_addressAepath_status_available0Aestream_receive_window00AfCRYPTO_BUFFER_EXCEEDED0AfExtensionNotNegotiatedAfFailedToGetCurrentTime0AfFailedToGetRandomBytes0AfMultipathNotNegotiated000000AfNatTraversalRoundEndedAfPathRetireConnectionId0AfProtectedInitialHeaderAfSkipServerVerificationAfbuild_transport_configAfexport_keying_material0000Afget_into_many_segmentsAfget_loop_many_segmentsAfmax_concurrent_streamsAfobserved_external_addr0Afpath_new_connection_id0Afverify_tls12_signatureAfverify_tls13_signatureAfwith_root_certificates0AgCertRevocationListErrorAgHandshakeSignatureValidAgNoCertificatesPresented0AgPeerSentOversizedRecord0Agack_eliciting_threshold0Agaugment_args_for_update0000Aghas_pending_retransmitsAgis_multipath_negotiatedAgon_ack_frequency_update000Agset_keep_alive_intervalAgupdate_from_arg_matches00000Agvalidation_token_config0AhAPPLICATION_ABANDON_PATH0AhNoProtectionClientConfigAhNoProtectionServerConfigAhget_max_udp_payload_size0Ahinitial_dst_cid_provider0Ahnew_with_abstract_socketAhremote_address_validated0Ahset_max_concurrent_pathsAhsupported_verify_schemesAiCONNECTION_ID_LIMIT_ERROR0AiEncryptedClientHelloErrorAiExportKeyingMaterialError0AiInvalidCertRevocationList0AiNO_CID_AVAILABLE_FOR_PATH0AiTRANSPORT_PARAMETER_ERROR0AiUnsupportedOperationErrorAiadd_nat_traversal_address0Aidatagram_send_buffer_size0Aigenerate_self_signed_certAiopen_bidirectional_streamAipath_retire_connection_id0Aiset_default_client_configAiset_path_max_idle_timeoutAjDEFAULT_SUPPORTED_VERSIONSAjUnusableAfterNetworkChangeAjdatagram_send_buffer_spaceAjincoming_buffer_size_total0Ajmax_concurrent_uni_streams0Ajopen_unidirectional_streamAjset_max_concurrent_streamsAjspurious_congestion_events0Ajtry_with_platform_verifier0AkHashedConnectionIdGeneratorAkInvalidEncryptedClientHello0AkPATH_RESOURCE_LIMIT_REACHED0AkRandomConnectionIdGeneratorAkenable_segmentation_offload0Akmax_concurrent_bidi_streams0Akupdate_from_arg_matches_mut00000Akupdate_local_if_same_remoteAlconfigure_tracing_subscriberAldatagram_receive_buffer_size0Alinitiate_nat_traversal_round0Alon_spurious_congestion_event00000Alreceive_bidirectional_streamAlremove_nat_traversal_address0Alset_path_keep_alive_intervalAmFixedLengthConnectionIdParserAmInappropriateHandshakeMessage000Amcongestion_controller_factory0Amdefault_path_max_idle_timeout0Ammax_outgoing_bytes_per_second0Amnegotiated_key_exchange_group0Amreceive_unidirectional_streamAmsend_observed_address_reports0Amset_max_concurrent_bi_streamsAnaugment_subcommands_for_updateAnmax_concurrent_multipath_paths0Anset_max_concurrent_uni_streamsAopersistent_congestion_threshold0B`default_path_keep_alive_interval0B`receive_observed_address_reports0Baget_local_nat_traversal_addresses0Bbget_remote_nat_traversal_addresses0Bbmax_remote_nat_traversal_addressesBfset_max_remote_nat_traversal_addresses0BoDEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED") \ No newline at end of file diff --git a/pr/619/docs/search.index/normalizedName/5a08d7469d41.js b/pr/619/docs/search.index/normalizedName/9a8f39ae04e1.js similarity index 60% rename from pr/619/docs/search.index/normalizedName/5a08d7469d41.js rename to pr/619/docs/search.index/normalizedName/9a8f39ae04e1.js index 8e7bc61c9..5f34b7601 100644 --- a/pr/619/docs/search.index/normalizedName/5a08d7469d41.js +++ b/pr/619/docs/search.index/normalizedName/9a8f39ae04e1.js @@ -1 +1 @@ -rd_("b()b->bbi0bce00bfnbidbokb[]beq00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003333333333333333333brtbtybu8cack0caddcanycarccboxcbufcclicdir0cerrcmax000cnotcopt00cordcpincuni0cvec>>>>>>ccmp00000000000000000009999cecn000cf32cf64cfmt0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cget0ci32cimpcios0clen000clog0cmincmutcnew0000000000000000000000000000000000cnoqcnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdargsdasfddbbr300ddropdect000dect100dfromdhashdintodkeys0dlong0dnonedpath00dping0dpolldreaddside0dzero0dacks0daddr00dbbr3dbooldbulkdcodedcwnd0ddataddrop000000dfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnext0dopen00dpath0dperfdping000dpoll00000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128duniteasrefebytesechunk0ecloneecloseecubic00edebugederefeerror00000000000eevent00eknowneother0erangeereset000eretry0eshort0esizedestats0esuiteetokioewriteealpns0earrayebenchebuild00000000ebytes00000ecauseeclone00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerroreframe0eindex0disce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats000000000etitle0etokenetokioetupleeusizeewrite00facceptfackecn0faes128faes256fbackup0fborrowfbufmutfchunksfclient00fclosedfcrypto0fcursorffuturefhasherfipaddrflaggedfopenbifopened00000foptionfpathid0fresult00000fserver00fstream000fstringftypeidfvarint0faccept000fborrow000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode000000000000edstipfencode000000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0eonack0000000fpacket00frandomfreason0000000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000esrcip00fstatus00fstream0fstrideeudprx000eudptx000fvarintfverify0fwindow0000000gblocked00gcommandgcontextgdefaultgdisplaygfromstrggeneral0ghmackey0ginitialginstantgkeypair0glayeredgmaxdata0gnewreno00gopenunigpadding0gpathack0gpathbufgreadbufgrequestgruntime0gsession0gstopped00000gstreamsgtoownedgtoolonggtryfromgtryintogunknowngwritten0gzerorttfcidlen000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt00000gdefault00000000000000000000000000000000000000000000000000000gdrainedfdstcid0000000gencrypt000fis0rtt0gmetrics0000000fminmtu0fnoqudpfonsent0fopenbifpathidgpointergruntimefsrccid0000gstopped0gstreams000ftaglen0ftypeid000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgrade0gversion00000hacceptbihbytesmuthchacha20hcommandshdatagram00hderefmuthdisabled0hdurationhendpoint00hfinished0hincoming0hiteratorhlayerexthlongtypegmaxsize0gnoerror0hnewtoken0honclosedhopenpathhorderinghreadable0hrecvmetahresponsehstreamid0htimedout00htostringhtokenlog0htoolarge0htransmit00hudpstats0hunixtimehwritable0gcongalghcontentshdatagram0hdurationhendpoint0hfinalizegframerx000gframetx000gfrombuf0gfromenv0gfromkeygfromstr0gfromu320gfromu640ggottype000ggroupid0000ghas0rtthincominghinterval0gintoany0000000gisalivehlifetime0glocalip0000gmaxdata0gmaxsizegnewrenognoqperfgonbytesgopenunihpriority0hprotocol0gqlogdirhresponsegrngseed0hssthresh0gtoowned00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtryfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtryinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtrypoll000000000gtrysendhvalidate000iabandoned000iacceptuniiaddassigniarbitraryiasyncread0iavailable000iborrowmuticommonopticonnectedicriterionidatagramsidecodableidiscarded000iencodableiformatterifourtupleiframetype0ihandshakeiheaderkey0ihistogramimalformedimaxpathid0imultipathipacketkey0ipartialeqipatherror0ipathevent000ipathstats0ireaderror00itryfutureitrystreamiudpsenderiudpsocketivalueenumhacceptbiiarbitrary0000000hasrustlsiassemblerhclonebox0000000idatagrams000hderefmut0hfrombits00iinitiator0hinto0rtthintoiterhisclient0hisclosedhisserver0hmayretry0imigration0hnewtimer00hnewtoken0hnoqprotohonclosedhopenpath0hpathacks0hpingpathhpollnext000hpollread00hpollrecvhpollsendhreachout0ireferencehresetkey0hretrytag0000hsizehint000hstableidhtostring000000000000000000000000000000000000000000000000000000000000000000htokenkey0htokenpositransport00hwaitidlehwritealljargmatchesjasynctimerjasyncwrite0ibatchsizejbbr3config0jclosedpath00000jcomparablejconnectingjconnection00jcontroller0jequivalent0jframestats0jintofuturejinvalidcid0jioslicemutjmaybeframe0jnamedgroupjnonzerou32jothererrorjpartialordjpathackecn0jpatheventsjpathstatus0jqlogconfig0jrecvstream00jreseterrorjretryerror0jsendstream00jservernamejsocketaddrjstreaminfojsubcommandjsystemtimejtimesource0jtlssession0jtokenstore0judpsockrefjwriteerror0iacceptuniiaddassign00000iallowspin0iborrowmut000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000icloneinto00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000iclosepathjcongestion000iconnstatsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ierrorcode000000iframetype0iintoinner0iisdrained0ilocaladdr0ilostbytes000inewsenderhpadtomtu0ipathstats000ipollcloseipollflush0ipollwrite00iprintjsonireadchunk0ireadexactisetstatusistarttime0jthroughputitotalsizekaccepterrorjclientaddrkciphersuitekclientstatskclosereasonkconfigerror0kcontenttypekcryptoerror0kcubicconfig0kdatablocked0kfinisherrorkidletimeout0kintorequestkoutofbounds0kpathabandon0kqlogfactory0kresetstream0kruntimetypejserveraddrjservernameksmolruntimekstopsending0kstreamevent0kstreamstats0kunspecifiedjacceptwithjaddaddress0jbindsocketkcertificatejcurrentmtu00kdescription0kdestination00jfromremotejinitialmtu000jinitialrtt00jintofuture0000000000000imaxpathid0jmaxstreamsjnamedlayer0ionendacks000jonintervaljpacingrate0jpartialcmp0000000000000000000jpatheventsjpathstatusjreadchunksireadtoendjrecvstream0jsamplesize0jsendbufferjsendstream0jsendwindow00jservername0jtimesource0jtokenstore0juploadsizejupperbound0jweakhandle0jwithcrypto0jwithprefix0jwritechunklackfrequency0laddressaddedlclientconfig00000lclosedstream000000lconnecterror00lconnectionid00ldatagraminfoldecrypterror0lecncodepoint00lencrypterror0lillegalvaluelimmediateack0lintoiteratorklocalhostv4llastopenpath0lnattraversallnonzerousizelnonetokenlog0lobservedaddr000lpathresponse0lpathsblocked0lreaddatagramlremotestatus000lrttestimator0lsenddatagramlserverconfig00000lsocketaddrv4lsocketaddrv6lstoppederrorltokioruntimelunstructuredkaugmentargs0000kcidlifetime000kclosereasonkconnectwithlconservativekdatablocked0kdrainstreamkearlycrypto000keventstreamkexpecttypes000kgeneratecid000kgrosegmentskhandleevent0kinitialkeys00000000kintorequest0klostpackets000kmaxincoming0kmayfragment00knetworkpathknewreceiverlnoprotection0jorigdstcid0kpathabandon0kpolltimeoutkqlogfactory0kresetstream0kruntimetypeksegmentsize00ksendquantum0ksendstreamsksetlifetime0ksetpriority0kstopsending0kstreamstatskuploadstatskwithinitial000kwritechunks0malertreceived0mbloomtokenlog0mcidsexhausted000mclonetouninitmdatagrameventmendpointeventmendpointstatsmfinishedearlymhandshakedata0mhandshakedone0mhandshaketypelinvalidtoken0mincomingalpns0minvalidheadermlocallyclosed0mmaxstreamdata0mmaxstreamsuni0mnewconnectionmnewrenoconfig0mparseinterrormpartialdecodempathchallenge0mpossiblevaluemprivatekeydermreadableerrormremoveaddress0mrootcertstoremstdsystemtime0munexpectedendlaccepted0rttlackfrequency00lbenchexports0lcidgenerator00lcreatesenderldatatransferldownloadsizeldurationhistlimmediateack0lintoincoming0kmaxackdelay0lnoprotectionlobservedaddr0konfirstbytekonmtuupdate0000000lpathresponse0lpathsblocked0lpeeridentity0000lpollshutdownlpolltransmitkqlogfromenv0lreaddatagramlsenddatagramlsendfairness0lsignaturelen0lstartsession000000000ktrypollnext0naddipv4address0naddipv6address0naddressremovednasyncudpsocketncertificatedernclosepatherror0ncommandfactorynconnectionlost000000nendpointconfig0nfromargmatchesminternalerror0nincomingfutureninvalidframeidninvalidmessage00nmaxstreamsbidi0lnoviablepath0nnonetokenstore0npeermisbehaved00nreachoutatipv40nreachoutatipv60nreadexacterrornreadtoenderrornshouldtransmitntransferresultntransporterror00nudpsocketstatenweakpathhandlemconnectclientmcryptosessionmdownloadstatsmforconnection000mhandletimeoutmhandshakedata00000mhandshakedone0mhassubcommandminitialwindow0000000000000mintounorderedmishandshaking0000lisvalidretry000mminimumchange0lnext1rttkeys000lonpacketlost000lonpacketsent000mpathchallenge0lqlogfrompath0mreadhandshake000mreadunorderedmreceivewindow00mreceivedreset00mremoteaddress0000mremoveaddress0msaturatingadd000msaturatingsub0mthroughputbpsmtimethreshold0mtotaldurationmvaluevariantsoconnectionclose000oconnectionerror0oconnectionevent0oconnectionstats0ogetrandomfailedonewconnectionid0oopenstreamstatsopathcidsblocked0oprotectedheader0oqlogfilefactory0oremoteabandoned0osignatureschemeosystemtimeerrorotokenreuseerror0otransportconfig00otryfrominterroroversionmismatch0ozerorttacceptedozerorttrejected000mbloomtokenlogmclonetouninit00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ndefaultruntimemgreasequicbit0nintegritylimit0ninterfaceindexmmaxstreamdata0mmaxstreamsuni0mparsebytesizenrebindabstractnsendunreliablenserverendpointmsetpathstatusmsetsendwindow0nshouldtransmitnstreamfinishednthroughputhistmwrapudpsocket00nwritehandshake000A`addressdiscoveryA`applicationclose000A`certificateerrorA`connectionclosed0A`connectionhandleA`datagramreceivedA`decryptedinitial0A`endpointstopping0nfinalsizeerror0A`inconsistentkeys00nkeyupdateerror0A`maxpathidreached0A`observedipv4addr0A`observedipv6addr0A`pathstatusbackup0A`peerincompatible00A`quicclientconfig0A`quicserverconfig0A`tokenmemorycache0A`toomanyaddressesA`validationfailed00A`versionnegotiate0ncheckandinsert00000oconfigureclientocongestionstate0oconnectionclose0nforcekeyupdate0nfromargmatches00000nmaxgsosegmentsnmaxidletimeout0nmaxstreamsbidi0nn0nattraversal0oopenconnections0nopenpathensure0opacketthreshold0oreceivedatagramnrecvbuffersize0nsendbuffersize0otransportconfig0000ovalidationtoken0nwithsinglecert0nwriteallchunksA`applicationerror0Aaapplicationclosed000Aacontrollerfactory0Aacontrollermetrics0Aahandshaketokenkey0Aainvalidservername0Aanetworkchangehint0Aapacketdecodeerror0Aapathabandonreason00Aasenddatagramerror0Aastreamdatablocked0Aastreamsblockeduni0Aaunsupportedbypeer0A`congestionevents0A`congestionwindow0omaxdatagramsizeonewconnectionid0opathcidsblocked0osendbufferspaceosetserverconfig0osetupconnectionotopossiblevalueA`aeadlimitreached0Abackfrequencyconfig0Abbadmaxfragmentsize0Aaconnectionrefused0AbconnectionidparserAbdatagramsunblockedA`flowcontrolerror0AbhandshakeconfirmedAbhandshakedatareadyAbillegalorderedreadAbinvalidcertificate0Abmtudiscoveryconfig0AbnotenoughaddressesA`perfciphersuitesAaprotocolviolation0Abprivatepkcs8keyderAbretireconnectionid0A`streamlimiterror0A`streamstateerror0AbservercertverifiedAbservercertverifierAbsetpathstatuserror0Abstreamsblockedbidi0AbtokiocurrentthreadAbtransporterrorcode0Abunsupportedversion00000A`commandforupdate0000A`cryptobuffersize0A`fromu64unchecked0AaignoredhandshakesA`issameconnectionA`minresetinterval0A`newexpecteditems0A`pathstatusbackup0AarefusedhandshakesA`remotepathstatusA`senddatagramwaitA`setalpnprotocols000A`setreceivewindow0Aasupportedversions0A`tokenmemorycacheA`verifyservercertA`withstartinstant0AccongestionalgorithmAcnattraversalupdatesAcpathnewconnectionid0Acpathstatusavailable0Acremotecidsexhausted0ActransportparametersAcunorderedrecvstreamAcunsupportednametype0AcwrongconnectionsideAbacceptedhandshakesAaarbitrarytakerest000AbaugmentsubcommandsAablackholecooldown0Aaearlydataaccepted000AbhandshakeconfirmedAaispathrecoverable0Aakeepaliveinterval0Aalostplpmtudprobes0Aaoncongestionevent0000000AboutgoinghandshakesAaremoteopenstreamsAasendbufferbenches00A`senddataonstreamAasentplpmtudprobes0Aastreamdatablocked0Aastreamsblockeduni0Abframeencodingerror0Adhandshakenotcomplete0Adinappropriatemessage000Adinvalidremoteaddress000Adnoinitialciphersuite0AdobservedexternaladdrAdserversidenotallowed0AdsupportedciphersuiteAdvarintboundsexceeded0AdverifierbuildererrorAdweakconnectionhandleAbackfrequencyconfig0Abblackholesdetected0Aafromargmatchesmut00000AbhandleclientstreamAbincomingbuffersize0AbismultipathenabledAbmaxreceivesegments0Aamaxudppayloadsize00Abmtudiscoveryconfig0AbpollendpointeventsAbpreferredaddressv40Abpreferredaddressv60AareadcertsfromfileAcreorderingthreshold0Abretireconnectionid0Abretrytokenlifetime0AasetmaxidletimeoutAasetrecvbuffersizeAasetsendbuffersizeAbstreamsblockedbidi0Actransportparameters00000Aeconnectionidgenerator0AedigitallysignedstructAenoapplicationprotocol0Aenodefaultclientconfig0Abpathunstableorpoor0Aevalidationtokenconfig0Adconfidentialitylimit0Achandlenetworkchange0AcincomingbufferbytesAbisprobablysamepathAclossreductionfactor0Acmaxtransmitsegments0AcnattraversalupdatesAcpathobservedaddressAcpathstatusavailable0Acstreamreceivewindow00Adcryptobufferexceeded0AfextensionnotnegotiatedAffailedtogetcurrenttime0Affailedtogetrandombytes0Afmultipathnotnegotiated000000AfnattraversalroundendedAfpathretireconnectionid0AfprotectedinitialheaderAfskipserververificationAdbuildtransportconfigAdexportkeyingmaterial0000AcgetintomanysegmentsAcgetloopmanysegmentsAdmaxconcurrentstreamsAdobservedexternaladdr0Acpathnewconnectionid0Adverifytls12signatureAdverifytls13signatureAdwithrootcertificates0AgcertrevocationlisterrorAghandshakesignaturevalidAgnocertificatespresented0Agpeersentoversizedrecord0Aeackelicitingthreshold0Adaugmentargsforupdate0000AehaspendingretransmitsAeismultipathnegotiatedAdonackfrequencyupdate000AdsetkeepaliveintervalAdupdatefromargmatches00000Aevalidationtokenconfig0Afapplicationabandonpath0AhnoprotectionclientconfigAhnoprotectionserverconfigAdgetmaxudppayloadsize0Aeinitialdstcidprovider0AenewwithabstractsocketAfremoteaddressvalidated0AesetmaxconcurrentpathsAfsupportedverifyschemesAfconnectionidlimiterror0AiencryptedclienthelloerrorAiexportkeyingmaterialerror0Aiinvalidcertrevocationlist0Aenocidavailableforpath0Agtransportparametererror0AiunsupportedoperationerrorAfaddnattraversaladdress0Afdatagramsendbuffersize0AfgenerateselfsignedcertAgopenbidirectionalstreamAfpathretireconnectionid0AfsetdefaultclientconfigAesetpathmaxidletimeoutAhdefaultsupportedversionsAjunusableafternetworkchangeAgdatagramsendbufferspaceAgincomingbuffersizetotal0Agmaxconcurrentunistreams0AhopenunidirectionalstreamAgsetmaxconcurrentstreamsAhspuriouscongestionevents0Agtrywithplatformverifier0AkhashedconnectionidgeneratorAkinvalidencryptedclienthello0Ahpathresourcelimitreached0AkrandomconnectionidgeneratorAienablesegmentationoffload0Ahmaxconcurrentbidistreams0Agupdatefromargmatchesmut00000AgupdatelocalifsameremoteAjconfiguretracingsubscriberAidatagramreceivebuffersize0Aiinitiatenattraversalround0Aionspuriouscongestionevent00000AjreceivebidirectionalstreamAiremovenattraversaladdress0AhsetpathkeepaliveintervalAmfixedlengthconnectionidparserAminappropriatehandshakemessage000Akcongestioncontrollerfactory0Aidefaultpathmaxidletimeout0Aimaxoutgoingbytespersecond0Ajnegotiatedkeyexchangegroup0AkreceiveunidirectionalstreamAjsendobservedaddressreports0AisetmaxconcurrentbistreamsAkaugmentsubcommandsforupdateAkmaxconcurrentmultipathpaths0AjsetmaxconcurrentunistreamsAmpersistentcongestionthreshold0Aldefaultpathkeepaliveinterval0Amreceiveobservedaddressreports0Amgetlocalnattraversaladdresses0Angetremotenattraversaladdresses0AnmaxremotenattraversaladdressesBasetmaxremotenattraversaladdresses0Bjdefaultconcurrentmultipathpathswhenenabled") \ No newline at end of file +rd_("b()b->bbi0bce00bfnbidbokb[]beq00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003333333333333333333brtbtybu8cack0caddcanycarccboxcbufcclicdir0cerrcmax000cnotcopt00cordcpincuni0cvec>>>>>>ccmp00000000000000000009999cecn000cf32cf64cfmt0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cget0ci32cimpcios0clen000clog0cmincmutcnew0000000000000000000000000000000000cnoqcnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdargsdasfddbbr300ddropdect000dect100dfromdhashdintodkeys0dlong0dnonedpath00dping0dpolldreaddside0dzero0dacks0daddr00dbbr3dbooldbulkdcodedcwnd0ddataddrop000000dfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnext0dopen00dpath0dperfdping000dpoll00000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128duniteasrefebytesechunk0ecloneecloseecubic00edebugederefeerror00000000000eevent00eknowneother0erangeereset000eretry0eshort0esizedestats0esuiteetokioewriteealpns0earrayebenchebuild00000000ebytes00000ecauseeclone00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerroreframe0eindex0disce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats000000000etitle0etokenetokioetupleeusizeewrite00facceptfackecn0faes128faes256fbackup0fborrowfbufmutfchunksfclient00fclosedfcrypto0fcursorffuturefhasherfipaddrflaggedfopenbifopened00000foptionfpathid0fresult00000fserver00fstream000fstringftypeidfvarint0faccept000fborrow000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode000000000000edstipfencode000000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0eonack0000000fpacket00frandomfreason0000000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000esrcip00fstatus00fstream0fstrideeudprx000eudptx000fvarintfverify0fwindow0000000gblocked00gcommandgcontextgdefaultgdisplaygfromstrggeneral0ghmackey0ginitialginstantgkeypair0glayeredgmaxdata0gnewreno00gopenunigpadding0gpathack0gpathbufgreadbufgrequestgruntime0gsession0gstopped00000gstreamsgtoownedgtoolonggtryfromgtryintogunknowngwritten0gzerorttfcidlen000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt00000gdefault00000000000000000000000000000000000000000000000000000gdrainedfdstcid0000000gencrypt000fis0rtt0gmetrics0000000fminmtu0fnoqudpfonsent0fopenbifpathidgpointergruntimefsrccid0000gstopped0gstreams000ftaglen0ftypeid000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgrade0gversion00000hacceptbihbytesmuthchacha20hcommandshdatagram00hderefmuthdisabled0hdurationhendpoint00hfinished0hincoming0hiteratorhlayerexthlongtypegmaxsize0gnoerror0hnewtoken0honclosedhopenpathhorderinghreadable0hrecvmetahresponsehstreamid0htimedout00htostringhtokenlog0htoolarge0htransmit00hudpstats0hunixtimehwritable0gcongalghcontentshdatagram0hdurationhendpoint0hfinalizegframerx000gframetx000gfrombuf0gfromenv0gfromkeygfromstr0gfromu320gfromu640ggottype000ggroupid0000ghas0rtthincominghinterval0gintoany0000000gisalivehlifetime0glocalip0000gmaxdata0gmaxsizegnewrenognoqperfgonbytesgopenunihpriority0hprotocol0gqlogdirhresponsegrngseed0hssthresh0gtoowned00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtryfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtryinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gtrypoll000000000gtrysendhvalidate000iabandoned000iacceptuniiaddassigniarbitraryiasyncread0iavailable000iborrowmuticommonopticonnectedicriterionidatagramsidecodableidiscarded000iencodableiformatterifourtupleiframetype0ihandshakeiheaderkey0ihistogramimalformedimaxpathid0imultipathipacketkey0ipartialeqipatherror0ipathevent000ipathstats0ireaderror00itryfutureitrystreamiudpsenderiudpsocketivalueenumhacceptbiiarbitrary0000000hasrustlsiassemblerhclonebox0000000idatagrams000hderefmut0hfrombits00iinitiator0hinto0rtthintoiterhisclient0hisclosedhisserver0hmayretry0imigration0hnewtimer00hnewtoken0hnoqprotohonclosedhopenpath0hpathacks0hpingpathhpollnext000hpollread00hpollrecvhpollsendhreachout0ireferencehresetkey0hretrytag0000hsizehint000hstableidhtostring000000000000000000000000000000000000000000000000000000000000000000htokenkey0htokenpositransport00hwaitidlehwritealljargmatchesjasynctimerjasyncwrite0ibatchsizejbbr3config0jclosedpath00000jcomparablejconnectingjconnection00jcontroller0jequivalent0jframestats0jintofuturejinvalidcid0jioslicemutjmaybeframe0jnamedgroupjnonzerou32jothererrorjpartialordjpathackecn0jpatheventsjpathstatus0jqlogconfig0jrecvstream00jreseterrorjretryerror0jsendstream00jservernamejsocketaddrjstreaminfojsubcommandjsystemtimejtimesource0jtlssession0jtokenstore0judpsockrefjwriteerror0iacceptuniiaddassign00000iallowspin0iborrowmut000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000icloneinto00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000iclosepathjcongestion000iconnstatsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ierrorcode000000iframetype0iintoinner0iisdrained0ilocaladdr0ilostbytes000inewsenderhpadtomtu0ipathstats000ipollcloseipollflush0ipollwrite00iprintjsonireadchunk0ireadexactisetstatusistarttime0jthroughputitotalsizekaccepterrorjclientaddrkciphersuitekclientstatskclosereasonkconfigerror0kcontenttypekcryptoerror0kcubicconfig0kdatablocked0kfinisherrorkidletimeout0kintorequestkoutofbounds0kpathabandon0kqlogfactory0kresetstream0kruntimetypejserveraddrjservernameksmolruntimekstopsending0kstreamevent0kstreamstats0kunspecifiedjacceptwithjaddaddress0jbindsocketkcertificatejcurrentmtu00kdescription0kdestination00jfromremotejinitialmtu000jinitialrtt00jintofuture0000000000000imaxpathid0jmaxstreamsjnamedlayer0ionendacks000jonintervaljpacingrate0jpartialcmp0000000000000000000jpatheventsjpathstatusjreadchunksireadtoendjrecvstream0jsamplesize0jsendbufferjsendstream0jsendwindow00jservername0jtimesource0jtokenstore0juploadsizejupperbound0jweakhandle0jwithcrypto0jwithprefix0jwritechunklackfrequency0laddressaddedlclientconfig00000lclosedstream000000lconnecterror00lconnectionid00ldatagraminfoldecrypterror0lecncodepoint00lencrypterror0lillegalvaluelimmediateack0lintoiteratorklocalhostv4llastopenpath0lnattraversallnonzerousizelnonetokenlog0lobservedaddr000lpathresponse0lpathsblocked0lreaddatagramlremotestatus000lrttestimator0lsenddatagramlserverconfig00000lsocketaddrv4lsocketaddrv6lstoppederrorltokioruntimelunstructuredkaugmentargs0000kcidlifetime000kclosereasonkconnectwithlconservativekdatablocked0kdrainstreamkearlycrypto000keventstreamkexpecttypes000kgeneratecid000kgrosegmentskhandleevent0kinitialkeys00000000kintorequest0klostpackets000kmaxincoming0kmayfragment00knetworkpathknewreceiverlnoprotection0jorigdstcid0kpathabandon0kpolltimeoutkqlogfactory0kresetstream0kruntimetypeksegmentsize00ksendquantum0ksendstreamsksetlifetime0ksetpriority0kstopsending0kstreamstatskuploadstatskwithinitial000kwritechunks0malertreceived0mbloomtokenlog0mcidsexhausted000mclonetouninitmdatagrameventmendpointeventmendpointstatsmfinishedearlymhandshakedata0mhandshakedone0mhandshaketypelinvalidtoken0mincomingalpns0minvalidheadermlocallyclosed0mmaxstreamdata0mmaxstreamsuni0mnewconnectionmnewrenoconfig0mparseinterrormpartialdecodempathchallenge0mpossiblevaluemprivatekeydermreadableerrormremoveaddress0mrootcertstoremstdsystemtime0munexpectedendlaccepted0rttlackfrequency00lbenchexports0lcidgenerator00lcreatesenderldatatransferldownloadsizeldurationhistlimmediateack0lintoincoming0kmaxackdelay0lnoprotectionlobservedaddr0konfirstbytekonmtuupdate0000000lpathresponse0lpathsblocked0lpeeridentity0000lpollshutdownlpolltransmitkqlogfromenv0lreaddatagramlsenddatagramlsendfairness0lsignaturelen0lstartsession000000000ktrypollnext0naddipv4address0naddipv6address0naddressremovednasyncudpsocketncertificatedernclosepatherror0ncommandfactorynconnectionlost000000nendpointconfig0nfromargmatchesminternalerror0nincomingfutureninvalidframeidninvalidmessage00nmaxstreamsbidi0lnoviablepath0nnonetokenstore0npeermisbehaved00nreachoutatipv40nreachoutatipv60nreadexacterrornreadtoenderrornshouldtransmitntransferresultntransporterror00nudpsocketstatenweakpathhandlemconnectclientmcryptosessionmdownloadstatsmforconnection000mhandletimeoutmhandshakedata00000mhandshakedone0mhassubcommandminitialwindow0000000000000mintounorderedmishandshaking0000lisvalidretry000mminimumchange0lnext1rttkeys000lonpacketlost000lonpacketsent000mpathchallenge0lqlogfrompath0mreadhandshake000mreadunorderedmreceivewindow00mreceivedreset00mremoteaddress000mremoveaddress0msaturatingadd000msaturatingsub0mthroughputbpsmtimethreshold0mtotaldurationmvaluevariantsoconnectionclose000oconnectionerror0oconnectionevent0oconnectionstats0ogetrandomfailedonewconnectionid0oopenstreamstatsopathcidsblocked0oprotectedheader0oqlogfilefactory0oremoteabandoned0osignatureschemeosystemtimeerrorotokenreuseerror0otransportconfig00otryfrominterroroversionmismatch0ozerorttacceptedozerorttrejected000mbloomtokenlogmclonetouninit00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ndefaultruntimemgreasequicbit0nintegritylimit0ninterfaceindexmmaxstreamdata0mmaxstreamsuni0mparsebytesizenrebindabstractnsendunreliablenserverendpointmsetpathstatusmsetsendwindow0nshouldtransmitnstreamfinishednthroughputhistmwrapudpsocket00nwritehandshake000A`addressdiscoveryA`applicationclose000A`certificateerrorA`connectionclosed0A`connectionhandleA`datagramreceivedA`decryptedinitial0A`endpointstopping0nfinalsizeerror0A`inconsistentkeys00nkeyupdateerror0A`maxpathidreached0A`observedipv4addr0A`observedipv6addr0A`pathstatusbackup0A`peerincompatible00A`quicclientconfig0A`quicserverconfig0A`tokenmemorycache0A`toomanyaddressesA`validationfailed00A`versionnegotiate0ncheckandinsert00000oconfigureclientocongestionstate0oconnectionclose0nforcekeyupdate0nfromargmatches00000nmaxgsosegmentsnmaxidletimeout0nmaxstreamsbidi0nn0nattraversal0oopenconnections0nopenpathensure0opacketthreshold0oreceivedatagramnrecvbuffersize0nsendbuffersize0otransportconfig0000ovalidationtoken0nwithsinglecert0nwriteallchunksA`applicationerror0Aaapplicationclosed000Aacontrollerfactory0Aacontrollermetrics0Aahandshaketokenkey0Aainvalidservername0Aanetworkchangehint0Aapacketdecodeerror0Aapathabandonreason00Aasenddatagramerror0Aastreamdatablocked0Aastreamsblockeduni0Aaunsupportedbypeer0A`congestionevents0A`congestionwindow0omaxdatagramsizeonewconnectionid0opathcidsblocked0osendbufferspaceosetserverconfig0osetupconnectionotopossiblevalueA`aeadlimitreached0Abackfrequencyconfig0Abbadmaxfragmentsize0Aaconnectionrefused0AbconnectionidparserAbdatagramsunblockedA`flowcontrolerror0AbhandshakeconfirmedAbhandshakedatareadyAbillegalorderedreadAbinvalidcertificate0Abmtudiscoveryconfig0AbnotenoughaddressesA`perfciphersuitesAaprotocolviolation0Abprivatepkcs8keyderAbretireconnectionid0A`streamlimiterror0A`streamstateerror0AbservercertverifiedAbservercertverifierAbsetpathstatuserror0Abstreamsblockedbidi0AbtokiocurrentthreadAbtransporterrorcode0Abunsupportedversion00000A`commandforupdate0000A`cryptobuffersize0A`fromu64unchecked0AaignoredhandshakesA`issameconnectionA`minresetinterval0A`newexpecteditems0A`pathstatusbackup0AarefusedhandshakesA`remotepathstatusA`senddatagramwaitA`setalpnprotocols000A`setreceivewindow0Aasupportedversions0A`tokenmemorycacheA`verifyservercertA`withstartinstant0AccongestionalgorithmAcnattraversalupdatesAcpathnewconnectionid0Acpathstatusavailable0Acremotecidsexhausted0ActransportparametersAcunorderedrecvstreamAcunsupportednametype0AcwrongconnectionsideAbacceptedhandshakesAaarbitrarytakerest000AbaugmentsubcommandsAablackholecooldown0Aaearlydataaccepted000AbhandshakeconfirmedAaispathrecoverable0Aakeepaliveinterval0Aalostplpmtudprobes0Aaoncongestionevent0000000AboutgoinghandshakesAaremoteopenstreamsAasendbufferbenches00A`senddataonstreamAasentplpmtudprobes0Aastreamdatablocked0Aastreamsblockeduni0Abframeencodingerror0Adhandshakenotcomplete0Adinappropriatemessage000Adinvalidremoteaddress000Adnoinitialciphersuite0AdobservedexternaladdrAdserversidenotallowed0AdsupportedciphersuiteAdvarintboundsexceeded0AdverifierbuildererrorAdweakconnectionhandleAbackfrequencyconfig0Abblackholesdetected0Aafromargmatchesmut00000AbhandleclientstreamAbincomingbuffersize0AbismultipathenabledAbmaxreceivesegments0Aamaxudppayloadsize00Abmtudiscoveryconfig0AbpollendpointeventsAbpreferredaddressv40Abpreferredaddressv60AareadcertsfromfileAcreorderingthreshold0Abretireconnectionid0Abretrytokenlifetime0AasetmaxidletimeoutAasetrecvbuffersizeAasetsendbuffersizeAbstreamsblockedbidi0Actransportparameters00000Aeconnectionidgenerator0AedigitallysignedstructAenoapplicationprotocol0Aenodefaultclientconfig0Abpathunstableorpoor0Aevalidationtokenconfig0Adconfidentialitylimit0Achandlenetworkchange0AcincomingbufferbytesAbisprobablysamepathAclossreductionfactor0Acmaxtransmitsegments0AcnattraversalupdatesAcpathobservedaddressAcpathstatusavailable0Acstreamreceivewindow00Adcryptobufferexceeded0AfextensionnotnegotiatedAffailedtogetcurrenttime0Affailedtogetrandombytes0Afmultipathnotnegotiated000000AfnattraversalroundendedAfpathretireconnectionid0AfprotectedinitialheaderAfskipserververificationAdbuildtransportconfigAdexportkeyingmaterial0000AcgetintomanysegmentsAcgetloopmanysegmentsAdmaxconcurrentstreamsAdobservedexternaladdr0Acpathnewconnectionid0Adverifytls12signatureAdverifytls13signatureAdwithrootcertificates0AgcertrevocationlisterrorAghandshakesignaturevalidAgnocertificatespresented0Agpeersentoversizedrecord0Aeackelicitingthreshold0Adaugmentargsforupdate0000AehaspendingretransmitsAeismultipathnegotiatedAdonackfrequencyupdate000AdsetkeepaliveintervalAdupdatefromargmatches00000Aevalidationtokenconfig0Afapplicationabandonpath0AhnoprotectionclientconfigAhnoprotectionserverconfigAdgetmaxudppayloadsize0Aeinitialdstcidprovider0AenewwithabstractsocketAfremoteaddressvalidated0AesetmaxconcurrentpathsAfsupportedverifyschemesAfconnectionidlimiterror0AiencryptedclienthelloerrorAiexportkeyingmaterialerror0Aiinvalidcertrevocationlist0Aenocidavailableforpath0Agtransportparametererror0AiunsupportedoperationerrorAfaddnattraversaladdress0Afdatagramsendbuffersize0AfgenerateselfsignedcertAgopenbidirectionalstreamAfpathretireconnectionid0AfsetdefaultclientconfigAesetpathmaxidletimeoutAhdefaultsupportedversionsAjunusableafternetworkchangeAgdatagramsendbufferspaceAgincomingbuffersizetotal0Agmaxconcurrentunistreams0AhopenunidirectionalstreamAgsetmaxconcurrentstreamsAhspuriouscongestionevents0Agtrywithplatformverifier0AkhashedconnectionidgeneratorAkinvalidencryptedclienthello0Ahpathresourcelimitreached0AkrandomconnectionidgeneratorAienablesegmentationoffload0Ahmaxconcurrentbidistreams0Agupdatefromargmatchesmut00000AgupdatelocalifsameremoteAjconfiguretracingsubscriberAidatagramreceivebuffersize0Aiinitiatenattraversalround0Aionspuriouscongestionevent00000AjreceivebidirectionalstreamAiremovenattraversaladdress0AhsetpathkeepaliveintervalAmfixedlengthconnectionidparserAminappropriatehandshakemessage000Akcongestioncontrollerfactory0Aidefaultpathmaxidletimeout0Aimaxoutgoingbytespersecond0Ajnegotiatedkeyexchangegroup0AkreceiveunidirectionalstreamAjsendobservedaddressreports0AisetmaxconcurrentbistreamsAkaugmentsubcommandsforupdateAkmaxconcurrentmultipathpaths0AjsetmaxconcurrentunistreamsAmpersistentcongestionthreshold0Aldefaultpathkeepaliveinterval0Amreceiveobservedaddressreports0Amgetlocalnattraversaladdresses0Angetremotenattraversaladdresses0AnmaxremotenattraversaladdressesBasetmaxremotenattraversaladdresses0Bjdefaultconcurrentmultipathpathswhenenabled") \ No newline at end of file diff --git a/pr/619/docs/search.index/root.js b/pr/619/docs/search.index/root.js index f8e1277fc..d28fb37e2 100644 --- a/pr/619/docs/search.index/root.js +++ b/pr/619/docs/search.index/root.js @@ -1 +1 @@ -rr_('{"normalizedName":{"I":"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","N":"ADLi","E":"OjAAAAAAAAA=","H":"WgjXRp1B"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"JFDJy0NX"},"name":{"N":"ADLi","E":"OjAAAAAAAAA=","H":"Oxa7Byeh"},"path":{"N":"BBf","E":"OzAAAAEAAKISugACAAQACQAAAAsAcAB9AAEAhwAEAJIAAQCVACEAuQDzAK8BCAC5ASIA3QEOAPABAAD1AQAA9wEFAAMCAQAHAgIACwIAAA4CBgAYAkoCZAQAAGYEEgB6BAIAfgQDAIMECgCPBAkAowQAALUEAgC5BAMAvgQAAMAEAADFBAAAxwQBAMsEoABtBQEAcQUIAHsFCACFBQIAiwUIAJgFAgCcBQUApQUFALQFAgDABQIAxAUCAMsF9ADBBgQAxwYAAMkGAADMBjwACgcQAB0HAwAiBwMAJwcZAEIHDABUBwEAWAcAAF0HAQBhBwAAYwcDAG8HAABxBwIAdgcAAHkHAAB8B3YA9AcDAPoHBgACCPoA/wgAAAEJAQAFCQEADAkAABIJBQAcCQAAHgkAACEJAgAnCQEAMAkFADgJHQBXCRQAbgmVAgYMAQAODAIAEwwAABkMAQAgDAAAJAwDADMMAAA7DAkARgwHAE8MGQBqDBAAfAxRAM8MAwDXDAAA2gwBAN0MAQD1DAEAEw2EAZoOAgCfDjAB0Q8AANwPAQDiDwMA6A8BAOsPAQDuDwEA9Q8DAPoPQQA9EAIAQhAWAF8QAQBiEAIAbRABAHIQBAB4EAMAgRAFAIoQAQCaEBIArhAgANAQIADzEAMA+xAAAP4QAQABEQEABREHABERAQAWEQEAHBEDACERAAAjEQIAJxE3AGURBQBuEQEAcxEFAHwRBQCGEQEAixFYAOURAADpEQAA7hEBAPERAQD4EQAAARIBAAQSAwAJEqcAshIAALQSAAC3EgEAuhIAAL0SAwDCEgsAzxIBANcSAwDcEhgA9hIXAA8TAgAYEwEAIxMRADYTAgA7EwMAQBMHAEoTAwBPEwUAWRMCAF8TAABhEwEAZBMbAIETAgCGEwUAjhMfALATCwC+EwUAxxMBAM4TJQD1EwQA/RMFAAUUHQAkFAIAKRQQADwUGwBaFAoAaBQFAG8UFgCHFAMAjBQZAKkUHwA=","H":"8fnEi42U"},"entry":{"N":"ACLa","E":"OjAAAAEAAAAAAAcBEAAAAAAAAQAHAAgACgB8AH8AgACBAIIAgwCMAJAAkQCUALcAuACtAa4BuAHsAe0B7gHvAfEB8gH2Af0B/gH/AQICBQIKAhUCFgJjBHkEfQSCBI4EmQSaBJsEnASfBKAEpASlBKYEpwSoBKkEqgSrBKwErQSyBLgEvQS/BMEExATGBMkEbAVvBXAFegWEBYgFiQWKBZQFlQWWBZcFogWjBasFrAWtBa4FsQWyBbMFtwW6BbsFvAW9Bb4FwwXHBcgFwAbGBsgGygbLBgkHGwccByEHJgdBB08HUAdRB1IHUwdZB1wHZwdoB2kHagduB3UHdwd4B/gH+QcBCP4IBAkHCQgJCwkPCRAJGgkbCSQJLgkvCTYJNwlWCWwJBAwFDAkMCgwLDAwMDQwRDBQMFwwYDBwMIwwqDC0MLgw2DDcMOQw6DEUMTgx7DM4M0wzVDNYM4AziDOcM6AzrDO4M7wzxDPIM8wz0DPwMAg0FDQYNCA0JDZgOmQ6dDp4O1A/XD+EP8A/0DzwQQBBBEFkQWhBmEGkQdxB8EH8QgBCIEIkQjBCPEJAQlRCWEJkQrRDPEPcQABEDEQ8RExEUERgRIBEiEWARYxFkEW0RchF7Ee0R8xH3EfkR+hH9EQASCBK2EsESzhLbEvUSDhMcEx4THxNOE1UTVhNeE4ATrhOvE7wTvRPJE8wT9BP8EzoUOxRlFG4UpxSoFA==","H":"lpw6U3rZ"},"desc":{"N":"GBi","E":"OzAAAAEAAJ8NiAEAAAEABwABAAoAXAB6AAAAfAAIAIwAAQCPAAIAlAAaALcA8wCtAQEAuAECANkBAgDdAQEA4gEBAOUBAADqAQgA9QEBAP0BAgACAgAABQIAAAgCAgAQAgEAFQICABwCBgA7AgAASQIAAEsCAQBOAgAAUAIAAFUCAABXAgEAWgIAAGICAQBlAgIAawIAAHYCAQB5AgAAgQIAAIcCAQCKAgAAjgIAAJECAACXAgAApAIAAKkCAACrAgkAzQIEANYCAADqAgAA7wIAAPQCAAD6AgEAAgMAAAgDAAAQAwAAFgMAABgDAAAgAwAAJgMAACsDAAAvAwMANAMGAEcDAABWAxQAWQQEAF8EAABjBAAAZQQAAGcEAABpBAAAawQMAHkEAAB9BAAAfwQAAIIEAACLBAAAjgQAAJQEAQCXBAUAnwQBAKMECgCyBAAAuAQAAL0EAAC/BAAAwQQFAMkEAQDMBAIA0AQDANsEjABsBQQAeQUBAHwFAgCEBQAAhgUFAJEFAACUBQMAnAUDAKIFAQCpBQUAsQUCALcFAAC6BQQAwwUBAMYFAgDPBe0AwAYBAMMGAQDGBgAAyAYAAMoGAQDOBgAA0gYAANUGCADfBgEA4wYLAPIGAAD5BgEA/AYBAAIHAgAGBwMAGwcCAB8HAAAhBwEAJAcLADYHAQBBBwAARQcCAEkHAgBPBwQAWQcAAFwHAgBhBwAAYwcHAG4HAAB1BwAAdwcBAH8HAACCBxkApAcyANgHAQDqBwIA7gcCAPgHAQABCAAAAwgAAAcI7QD+CAQABAkAAAcJAQALCQAADwkBABYJAQAaCQEAJAkAAC4JAQAzCQQARgkBAFAJBABWCQAAWgkCAF4JAgBpCQEAbAkCAHoJwgBAClIAlAoAAJcKZwEDDAIACQwEABEMAQAUDAAAFwwBABwMAAAeDAEAIwwAACUMAQAqDAAALQwBADYMAQA5DAEAPAwJAEcMAgBLDAMAUgwBAFoMAABlDAMAbQwBAHAMAwB1DAEAeQwCAH8MAACBDAUAiAxCAM4MAADTDAAA1QwBAOAMAADiDAAA5wwBAOsMAADuDAEA8QwFAPwMAAACDQAABQ0EABQNBQAcDXoBmA4BAJ0OCQG6DwAAwQ8CAMUPAgDODwEA0Q8DANcPAADcDwEA4Q8AAOQPAQDoDwQA7g8CAPIPAgD2DwMAChAPABsQAQAeEAAAIBABACQQEwA8EAAAQBABAFYQAQBZEAEAZhAAAGkQAABsEAAAdRADAHwQAAB/EAEAgxADAIgQAQCMEAAAjxABAJUQAQCZEAUAoRABAKYQAgCqEAAArBABALQQAQC7EAEAvxAEAM4QAgDTEAEA2BABAOUQAwD3EAAA/hACAAMRAAAIEQMADxEAABERAwAWEQIAHREBACARAAAiEQAAJhEAACgRAgAwEQIANBECADgRBgBEEQAAUBEBAFQRCQBgEQAAYxEBAG0RAAByEQAAdREBAHsRAAB+EQMAhREAAI0RAACPEQAAkREAAJYRAACYEQMAnREAAJ8RAAChEQAApBEAAKYRAACoEQAArBEAAK8RAACxEQAAsxEAALcRAAC5EQAAuxEAAL0RAAC/EQAAwRECAMcRAADJEQAA1hEBAN4RAADhEQIA5REAAO0RAgDxEQIA9xEAAPkRAQD9EQAAABIAAAgSjQCcEgQAohIAAKgSAQCrEgEArhIAALASAACyEgAAtBIAALYSAADBEgAAyBIGANsSAADeEgEA4RICAOYSAQDqEgUA8xICAP0SAAACEwAADhMAABwTAAAeEwEAIxMDAC4TAwA1EwEASxMAAE4TAgBVEwEAWRMCAF4TAABkEwQAcxMBAIATAQCEEwAAhhMDAJITBACaEwAAnBMAAKUTAgCpEwIArhMBALETAAC0EwMAvBMBAMkTAADMEwAA0hMGAOgTAADrEwEA8hMCAPYTAAD5EwAA/BMAABEUAQAlFAEAKBQBACwUAAAuFAAANBQDADoUAQBCFAQAShQAAEwUAABOFAUAWBQBAGIUAABlFAAAbhQAAHMUAwCAFAAAkBQFAJcUAACeFAAAoRQBAKcUAQCzFAAAtxQAAA==","H":"tKlHqKLu"},"function":{"N":"AABl","E":"OzAAAAEAAJwDVwAAAAoAfAAYALcAAQCtAQEAuAEAANwBAADsASMAFQICAGMEAABlBAAAeQQAAH0EAACCBAAAjgQAAJkELQDJBAEAbAUAAG8FAQB6BQAAhAUAAIgFAwCRBQAAlAUDAJsFLwDABgAAwwYAAMYGAgDKBgIA0AYAAAkHAAAbBwYAJAcAACYHAABBBwAATAcwAPMHAAD4BwEAAQgAAP0IMwA2CQEAVgkAAGwJAQAEDDYARQwAAE4MAABpDAAAewwAAM4MAADTDAMA2Aw6AJgOAwCdDgEA0A8AANIPGADtDwcA+Q8AADwQAABAEAEAVhAhAHkQIACtEAAAzxABAO8QLAAgEQIAJhEAAFoRMADjESUAsRIrAPUSAQAMExwANRMAADcTEwBMExcAgBMAAIQTDACuEwIAuBMVAPQTAAD3EwAA+hMKABYUEgA6FAUAVhQDAGMUCwB6FAAAhhQFAKYUBAA=","H":"r33AiqcK"},"type":{"N":"AKb","E":"OzAAAAEAABYTmgACAAQACQAAAAsAcAB9AAIAhwAFAJAAAACSAAEAlQAhALkA8wCuAQkAuQEyAPABAQD1AQkAAwIBAAcCAgALAgAADgIHABcCgQKfBAAAowQCAKgEAQCyBAAAtQQCALkEAwC+BAAAwAQAAMUEAADHBAEAygS5AIUFEACYBQIAnAUGAKUFBQC0BQIAwAUGAMsFgwFRBwQAWAcAAF0HAQBhBwAAYwcDAG8HAABxBwIAdQcEAHwHewD5BwMB/wgAAAEJAQAECQIADAkAAA8JAQASCQUAHAkAAB4JAAAhCQIAJwkBADAJ0wIGDAEACQwDAA4MAwATDAAAGQwBACAMAAAkDAMAKgwAAC0MAQAzDAAANgwBADoMQAB8DFYA1QwCANoMAQDdDAEA4AwAAOcMAQDrDAAA9AwCAAgNAAATDbwC0Q8AANwPAQDhDwQA6A8BAOsPAQDuDwIA9Q9jAF8QAQBiEAIAbRABAHIQCQCBEAUAihABAJoQVgDzEAQA+xAAAP4QAQABEQEABREHABERAQAWEQEAHBFCAGMRAABlEQUAbRECAHMRBQB8EQUAhhEBAIsRWADlEQAA6REAAO4RAQDxEQIA+BEAAAESAQAEEqwAshIAALQSAAC3EgEAuhIAAL0SAwDCEgsAzxIBANcSAwDcEjEADxMCABgTAQAcEwAAHhMAACMTFQA7EwMAQBMHAEoTAwBPEwUAVhMAAFkTAgBfEwAAYRMBAGQTHwCGEwUAjhMtAL4TBQDHEwEAzhMrAP0TBQAFFB0AJBQCACkUEAA8FBsAWhQKAGgUBQBvFBYAhxQDAIwUGQCpFB8A","H":"nqWHwF50"},"alias":{"N":"`","E":"OzAAAAEAAMgUAQAAAMgU","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"TTOmfth/"}}') \ No newline at end of file +rr_('{"normalizedName":{"I":"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","N":"ADLh","E":"OjAAAAAAAAA=","H":"mo85rgTh"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"JFDJy0NX"},"name":{"N":"ADLh","E":"OjAAAAAAAAA=","H":"E+ne2MrN"},"path":{"N":"BBf","E":"OzAAAAEAAKESugACAAQACQAAAAsAcAB9AAEAhwAEAJIAAQCVACEAuQDzAK8BCAC5ASIA3QEOAPABAAD1AQAA9wEFAAMCAQAHAgIACwIAAA4CBgAYAkoCZAQAAGYEEgB6BAIAfgQDAIMECgCPBAkAowQAALUEAgC5BAMAvgQAAMAEAADFBAAAxwQBAMsEoABtBQEAcQUIAHsFCACFBQIAiwUIAJgFAgCcBQUApQUFALQFAgDABQIAxAUCAMsF9ADBBgQAxwYAAMkGAADMBjwACgcQAB0HAwAiBwMAJwcZAEIHDABUBwEAWAcAAF0HAQBhBwAAYwcDAG8HAABxBwIAdgcAAHkHAAB8B3YA9AcDAPoHBgACCPoA/wgAAAEJAQAFCQEADAkAABIJBQAcCQAAHgkAACEJAgAnCQEAMAkFADgJHQBXCRQAbgmVAgYMAQAODAIAEwwAABkMAQAgDAAAJAwDADMMAAA7DAkARgwHAE8MGQBqDBAAfAxRAM8MAwDXDAAA2gwBAN0MAQD1DAEAEw2EAZoOAgCfDjAB0Q8AANwPAQDiDwMA6A8BAOsPAQDuDwEA9Q8DAPoPQQA9EAIAQhAWAF8QAQBiEAIAbRABAHIQBAB4EAMAgRAFAIoQAQCaEBIArhAgANAQIADzEAMA+xAAAP4QAQABEQEABREHABERAQAWEQEAHBEDACERAAAjEQIAJxE3AGURBQBuEQEAcxEFAHwRBQCGEQEAixFXAOQRAADoEQAA7REBAPARAQD3EQAAABIBAAMSAwAIEqcAsRIAALMSAAC2EgEAuRIAALwSAwDBEgsAzhIBANYSAwDbEhgA9RIXAA4TAgAXEwEAIhMRADUTAgA6EwMAPxMHAEkTAwBOEwUAWBMCAF4TAABgEwEAYxMbAIATAgCFEwUAjRMfAK8TCwC9EwUAxhMBAM0TJQD0EwQA/BMFAAQUHQAjFAIAKBQQADsUGwBZFAoAZxQFAG4UFgCGFAMAixQZAKgUHwA=","H":"8fnEi42U"},"entry":{"N":"ACL`","E":"OjAAAAEAAAAAAAcBEAAAAAAAAQAHAAgACgB8AH8AgACBAIIAgwCMAJAAkQCUALcAuACtAa4BuAHsAe0B7gHvAfEB8gH2Af0B/gH/AQICBQIKAhUCFgJjBHkEfQSCBI4EmQSaBJsEnASfBKAEpASlBKYEpwSoBKkEqgSrBKwErQSyBLgEvQS/BMEExATGBMkEbAVvBXAFegWEBYgFiQWKBZQFlQWWBZcFogWjBasFrAWtBa4FsQWyBbMFtwW6BbsFvAW9Bb4FwwXHBcgFwAbGBsgGygbLBgkHGwccByEHJgdBB08HUAdRB1IHUwdZB1wHZwdoB2kHagduB3UHdwd4B/gH+QcBCP4IBAkHCQgJCwkPCRAJGgkbCSQJLgkvCTYJNwlWCWwJBAwFDAkMCgwLDAwMDQwRDBQMFwwYDBwMIwwqDC0MLgw2DDcMOQw6DEUMTgx7DM4M0wzVDNYM4AziDOcM6AzrDO4M7wzxDPIM8wz0DPwMAg0FDQYNCA0JDZgOmQ6dDp4O1A/XD+EP8A/0DzwQQBBBEFkQWhBmEGkQdxB8EH8QgBCIEIkQjBCPEJAQlRCWEJkQrRDPEPcQABEDEQ8RExEUERgRIBEiEWARYxFkEW0RchF7EewR8hH2EfgR+RH8Ef8RBxK1EsASzRLaEvQSDRMbEx0THhNNE1QTVRNdE38TrROuE7sTvBPIE8sT8xP7EzkUOhRkFG0UphSnFA==","H":"dmaUduE8"},"desc":{"N":"GBh","E":"OzAAAAEAAJ8NiAEAAAEABwABAAoAXAB6AAAAfAAIAIwAAQCPAAIAlAAaALcA8wCtAQEAuAECANkBAgDdAQEA4gEBAOUBAADqAQgA9QEBAP0BAgACAgAABQIAAAgCAgAQAgEAFQICABwCBgA7AgAASQIAAEsCAQBOAgAAUAIAAFUCAABXAgEAWgIAAGICAQBlAgIAawIAAHYCAQB5AgAAgAIAAIYCAQCKAgAAjgIAAJICAACYAgAApQIAAKkCBACvAgUAzQIEANYCAADqAgAA7wIAAPQCAAD6AgEAAgMAAAgDAAAQAwAAFgMAABgDAAAgAwAAJgMAACsDAAAvAwMANAMGAEcDAABWAxQAWQQEAF8EAABjBAAAZQQAAGcEAABpBAAAawQMAHkEAAB9BAAAfwQAAIIEAACLBAAAjgQAAJQEAQCXBAUAnwQBAKMECgCyBAAAuAQAAL0EAAC/BAAAwQQFAMkEAQDMBAIA0AQDANsEjABsBQQAeQUBAHwFAgCEBQAAhgUFAJEFAACUBQMAnAUDAKIFAQCpBQUAsQUCALcFAAC6BQQAwwUBAMYFAgDPBe0AwAYBAMMGAQDGBgAAyAYAAMoGAQDOBgAA0gYAANUGCADfBgEA4wYLAPIGAAD5BgEA/AYBAAIHAgAGBwMAGwcCAB8HAAAhBwEAJAcLADYHAQBBBwAARQcCAEkHAgBPBwQAWQcAAFwHAgBhBwAAYwcHAG4HAAB1BwAAdwcBAH8HAACCBxkApAcyANgHAQDqBwIA7gcCAPgHAQABCAAAAwgAAAcI7QD+CAQABAkAAAcJAQALCQAADwkBABYJAQAaCQEAJAkAAC4JAQAzCQQARgkBAFAJBABWCQAAWgkCAF4JAgBpCQEAbAkCAHoJwgBAClIAlAoAAJcKZwEDDAIACQwEABEMAQAUDAAAFwwBABwMAAAeDAEAIwwAACUMAQAqDAAALQwBADYMAQA5DAEAPAwJAEcMAgBLDAMAUgwBAFoMAABlDAMAbQwBAHAMAwB1DAEAeQwCAH8MAACBDAUAiAxCAM4MAADTDAAA1QwBAOAMAADiDAAA5wwBAOsMAADuDAEA8QwFAPwMAAACDQAABQ0EABQNBQAcDXoBmA4BAJ0OCQG6DwAAwQ8DAMYPAQDODwEA0Q8DANcPAADcDwEA4Q8AAOQPAQDoDwQA7g8CAPIPAgD2DwMAChAPABsQAQAeEAAAIBABACQQEwA8EAAAQBABAFYQAQBZEAEAZhAAAGkQAABsEAAAdRADAHwQAAB/EAEAgxADAIgQAQCMEAAAjxABAJUQAQCZEAUAoRABAKYQAgCqEAAArBABALQQAQC7EAEAvxAEAM4QAgDTEAEA2BABAOUQAwD3EAAA/hACAAMRAAAIEQMADxEAABERAwAWEQIAHREBACARAAAiEQAAJhEAACgRAgAwEQIANBECADgRBgBEEQAAUBEBAFQRCQBgEQAAYxEBAG0RAAByEQAAdREBAHsRAAB+EQMAhREAAI0RAACPEQAAkREAAJYRAACYEQMAnREAAJ8RAAChEQAApBEAAKYRAACoEQAArBEAAK8RAACxEQAAsxEAALcRAAC5EQAAuxEAAL0RAAC/EQAAwRECAMcRAADJEQAA1REBAN0RAADgEQIA5BEAAOwRAgDwEQIA9hEAAPgRAQD8EQAA/xEAAAcSjQCbEgQAoRIAAKcSAQCqEgEArRIAAK8SAACxEgAAsxIAALUSAADAEgAAxxIGANoSAADdEgEA4BICAOUSAQDpEgUA8hICAPwSAAABEwAADRMAABsTAAAdEwEAIhMDAC0TAwA0EwEAShMAAE0TAgBUEwEAWBMCAF0TAABjEwQAchMBAH8TAQCDEwAAhRMDAJETBACZEwAAmxMAAKQTAgCoEwIArRMBALATAACzEwMAuxMBAMgTAADLEwAA0RMGAOcTAADqEwEA8RMCAPUTAAD4EwAA+xMAABAUAQAkFAEAJxQBACsUAAAtFAAAMxQDADkUAQBBFAQASRQAAEsUAABNFAUAVxQBAGEUAABkFAAAbRQAAHIUAwB/FAAAjxQFAJYUAACdFAAAoBQBAKYUAQCyFAAAthQAAA==","H":"kAoxbKYk"},"function":{"N":"AABk","E":"OzAAAAEAAJwDVwAAAAoAfAAYALcAAQCtAQEAuAEAANwBAADsASMAFQICAGMEAABlBAAAeQQAAH0EAACCBAAAjgQAAJkELQDJBAEAbAUAAG8FAQB6BQAAhAUAAIgFAwCRBQAAlAUDAJsFLwDABgAAwwYAAMYGAgDKBgIA0AYAAAkHAAAbBwYAJAcAACYHAABBBwAATAcwAPMHAAD4BwEAAQgAAP0IMwA2CQEAVgkAAGwJAQAEDDYARQwAAE4MAABpDAAAewwAAM4MAADTDAMA2Aw6AJgOAwCdDgEA0A8AANIPGADtDwcA+Q8AADwQAABAEAEAVhAhAHkQIACtEAAAzxABAO8QLAAgEQIAJhEAAFoRMADiESUAsBIrAPQSAQALExwANBMAADYTEwBLExcAfxMAAIMTDACtEwIAtxMVAPMTAAD2EwAA+RMKABUUEgA5FAUAVRQDAGIUCwB5FAAAhRQFAKUUBAA=","H":"xwIHkuXM"},"type":{"N":"AKb","E":"OzAAAAEAABUTmgACAAQACQAAAAsAcAB9AAIAhwAFAJAAAACSAAEAlQAhALkA8wCuAQkAuQEyAPABAQD1AQkAAwIBAAcCAgALAgAADgIHABcCgQKfBAAAowQCAKgEAQCyBAAAtQQCALkEAwC+BAAAwAQAAMUEAADHBAEAygS5AIUFEACYBQIAnAUGAKUFBQC0BQIAwAUGAMsFgwFRBwQAWAcAAF0HAQBhBwAAYwcDAG8HAABxBwIAdQcEAHwHewD5BwMB/wgAAAEJAQAECQIADAkAAA8JAQASCQUAHAkAAB4JAAAhCQIAJwkBADAJ0wIGDAEACQwDAA4MAwATDAAAGQwBACAMAAAkDAMAKgwAAC0MAQAzDAAANgwBADoMQAB8DFYA1QwCANoMAQDdDAEA4AwAAOcMAQDrDAAA9AwCAAgNAAATDbwC0Q8AANwPAQDhDwQA6A8BAOsPAQDuDwIA9Q9jAF8QAQBiEAIAbRABAHIQCQCBEAUAihABAJoQVgDzEAQA+xAAAP4QAQABEQEABREHABERAQAWEQEAHBFCAGMRAABlEQUAbRECAHMRBQB8EQUAhhEBAIsRVwDkEQAA6BEAAO0RAQDwEQIA9xEAAAASAQADEqwAsRIAALMSAAC2EgEAuRIAALwSAwDBEgsAzhIBANYSAwDbEjEADhMCABcTAQAbEwAAHRMAACITFQA6EwMAPxMHAEkTAwBOEwUAVRMAAFgTAgBeEwAAYBMBAGMTHwCFEwUAjRMtAL0TBQDGEwEAzRMrAPwTBQAEFB0AIxQCACgUEAA7FBsAWRQKAGcUBQBuFBYAhhQDAIsUGQCoFB8A","H":"ay28vThT"},"alias":{"N":"`","E":"OzAAAAEAAMcUAQAAAMcU","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"got5lMUN"}}') \ No newline at end of file diff --git a/pr/619/docs/search.index/type/6b2dbcbd3853.js b/pr/619/docs/search.index/type/6b2dbcbd3853.js new file mode 100644 index 000000000..37f3bbd36 --- /dev/null +++ b/pr/619/docs/search.index/type/6b2dbcbd3853.js @@ -0,0 +1 @@ +rd_("CDc[\"\",\"ADswAAABAAAFAAIAWQQEAJYUAAAC9gYAABYHAAA6MAAAAQAAAAAACgAQAAAA6gHrAX4F0QyhEucS/BJzFH8UoRSyFDowAAABAAAAAAAcABAAAAAcAh0CHgIfAiACIQIiAmgEfQWCBcQG8gYiB24JMhGkEugSexMuFC8UdhSbFJwUnRSeFJ8UoBS1FLkUOzAAAAEAADgBEgBmBAAAagUAAHwFAAD3BgAAFQcAACUHAACDDAMAFA0FAAoOjAC3EAAAMxEHAJIRAAAIEowApRIAAKcSAAAyEwAAfBMAAJwTAAA6MAAAAQAAAAAAIQAQAAAAfwWFBYYFhwXwBvEG+Ab5BvoG+wb8Bv0GAAwBDAIMAwxZDMcPyw/jEEkRoBKwE+8T8BMGFEgUSRRKFEsUbhRyFIAUohQ7MAAAAQAAQwAVAFYDFACEBAAAkAQCAGgFAQBrBQAAgAUBAJoFAADjBgwA9AcBAP8LAABvDAAAIRAAAFUQAADkEAAAixEAALoRBwAzEwAAdxMDAOcTAABvFAAAoxQAADswAAABAABgAA0A4gBGAJoBAQCDBAAAoAcAAKMHAADkBwAA5gcAAKkQAwDcEgUA1xMAAAcUAABNFAUAYBQAADswAAABAAANAAYAagQAANIMAACXDgAAHRADAKISAACPFAUAOzAAAAEAABMACQCABAEAiQQBAOMHAADlBwAAwQ8CAMoPAABEEQAAChMAAKMTBwA7MAAAAQAACgADAAEHBwBCBwEA+RIAAAF4DAAABJ0HAACfBwAAogcAAHYMAAAAOzAAAAEAAAUAAgDQAQAAKRQEAAAAAc4FAAA=\"]Bk[\"AAAAAAAAAAAEIxEAACQRAABbFAAAXBQAAA==\",\"\"]0Bg[\"\",\"AAAFUAkAAFEJAABSCQAAUwkAAFQJAAA=\"]AGg[\"AAAAAALCAQAA0QEAAAAAAmgFAABpBQAABKAHAACjBwAA5AcAAOYHAAA7MAAAAQAADQAFAJgFAQB2CQEAfgwEANIMAADGEQMAOjAAAAEAAAAAAAsAEAAAAIkEigTjB+UHyg/tEO4QsBGxEbIRsxEKEwR6BAAAQgcAAEMHAAA6EAAABGAEAABiBAAANRQAADYUAAAFfwQAAJ8HAACiBwAAxA8AAMYPAAADdAwAAHUMAADFDwAAOzAAAAEAAAYAAwDQAQAA3gYAACkUBAABgBMAAAF3DAAA\",\"AAAAAeERAAAAAm0FAABuBQAAAAJSDAAAUwwAAAAFfgwAAH8MAACADAAAgQwAAIIMAAAAAAJgBAAAYgQAAA==\"]ANg[\"AAAEZwIAAM4CAADNBgAA0QYAAANUDAAAVQwAAFYMAAACwgEAANEBAAA7MAAAAQAAjAABAAgSjAAAOzAAAAEAAAcAAwBoBQEAdxMDAMUUAQAEoAcAAKMHAADkBwAA5gcAADswAAABAAASAAcAmAUBABcHAAB2CQEAfgwEANIMAADGEQMArBIDADowAAABAAAAAAAKABAAAACABIEEiQSKBOMH5QfKD7ARsRGyEbMRBXoEAACDBQAAQgcAAEMHAABFEQAABGAEAABiBAAANRQAADYUAAAEnwcAAKIHAADEDwAAxg8AAATzBgAAdAwAAHUMAADFDwAABSkUAAAqFAAAKxQAACwUAAAtFAAAAYATAAAAAc4FAAA=\",\"AAAAAAACbQUAAG4FAAAAAlIMAABTDAAAATsQAAAFfgwAAH8MAACADAAAgQwAAIIMAAAAAAJgBAAAYgQAAAAAAAAAAwwHAACZEQAAmhEAAA==\"]Dc[\"\",\"AAAAADswAAABAAAHAAEAWQkHADswAAABAAAJAAIAPxEEAJQRBAAAAZMRAAA=\"]ADi[\"AAAABr8BAADBAQAAzQEAAM8BAABREAAAUhAAAAJ6CgAAfgoAADowAAABAAAAAAAJABAAAADAAcUBxgHOAdcB2AHrCu0KNxQ4FDswAAABAAANAAQAywQHAPUPAADpEAMABhQAAALJAQAAMxMAADswAAABAAAXAAsAtQEBALwBAAB8DAEAywwBAEgQAwDWEAEAIxEBAAITAwDXEwAAWxQBAKoUAQABXRQAAAAAAAAAAAAAAc4FAAA=\",\"AAABugEAAALTBAAAlRIAAAAAAAK6DwAAzhAAAAAAAAAAAAAAAAAEzwYAANMGAADPDAAA0AwAAA==\",1]ADe[\"AAAAAr0BAADIAQAAOzAAAAEAAAcAAQBZCQcAAASFBQAAhgUAAIcFAACgEgAAAAABXRQAAA==\",\"AAAAADswAAABAAAQAAMAxAYAAFkJBwBGDAcAOzAAAAEAAAsABAAlBwAAJREAAD8RBACUEQQAOzAAAAEAAA8ABQDLBAcAZAwCAKkSAgDjEgAAchQAADowAAABAAAAAAAKABAAAABPEVERUxFVEVcRkxG2EbcRuBG5EecTBKkQAACqEAAAqxAAAKwQAAAAAAVOEQAAUBEAAFIRAABUEQAAVhEAAAAAAAAAAAPOBQAAvg8AAMAPAAA=\",1]Ec[\"AAAAAAAAOzAAAAEAAAYAAgDaBgMA3wYCADswAAABAAAGAAIA1QYEAEEJAQADfAQAAHgFAAB5BQAA\",\"\"]Dg[\"AAAAAAAAAAABThQAAAGQFAAAAAAAAAAAAAABhAcAAA==\",\"AAAAAAAB6hIAAAHSEwAA\"]Eo[\"AAAAAQ4FAAABxAEAAAIwAAAAoAAAAAEpEAAAAVsDAAACFwEAABgBAAA=\",\"AAABrwAAAAEOBQAAAZITAAAAAT4MAAA=\"]Ic[\"AAAAAVAFAAAD1QEAAKwTAAAwFAAAAl4AAACtAAAABosBAACMAQAAYQQAAM0FAAA2EAAAgBQAAAFoAwAA\",\"AAABsAAAAAJQBQAAlBMAAAABQgwAAAAAAAAAAAAAAAAAAAKxAAAAsgAAAA==\"]Ik[\"AAAAAtsEAAABEwAAASIHAAABwQYAAAG5AAAAAYsRAAABTRQAAAKiEgAAjxQAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAAIwFvwaBBwIIAxAaEEwQ2hAnEcoR\",\"AAAAAdsEAAAAAekSAAAB0RMAAA==\"]Ck[\"AAAAAeoBAAAAAAAAAVEUAAABkxQAAA==\",\"AAAAAAAB7RIAAAHVEwAA\"]Ck[\"AAAAAesBAAAAAAAAAVIUAAABlBQAAA==\",\"AAAAAAAB7hIAAAHWEwAA\"]Kk[\"AAAAAAAABH8FAACFBQAAhgUAAIcFAAAAOzAAAAEAAAkAAQD1CwkAOzAAAAEAAA0AAQBqBA0AOzAAAAEAAAkABABwDAMAwQ8CAEQRAABYEQEAAAF4DAAAA3YMAADEDwAAxg8AAAJ1DAAAxQ8AAA==\",\"AAAAAAABJREAAANkDAAAZQwAAGYMAAA=\"]Nk[\"AAAAAAAAAggTAAAJEwAABHcTAAB4EwAAeRMAAHoTAAACfRMAAH4TAAAFFwcAAKwSAACtEgAArhIAAK8SAAACgAQAAIEEAAACgwUAAEURAAAAAAHzBgAAAAAAAc4FAAA=\",\"AAAAAAJ7BQAAYRQAAAAFmRQAAMAUAADBFAAAwhQAAMMUAAAB5xMAAAI7EAAAmhQAAAAAAAAAAAAAAASuEAAArxAAALAQAACxEAAA\"]Bg[\"AAAAAAAAAATeEQAA3xEAAAoUAAALFAAA\",\"\"]Bk[\"\",\"AAAAAd0RAAAAAAAAAAAAAAAAAAAAAAHODwAA\"]Cc[\"AAAAAAAAAeMQAAAB5BAAAA==\",\"AAAAAAACcAkAAHEJAAA=\"]FHk[\"AAAAADswAAABAAAXAAkAHAIGAGgEAACQBQAABAgAAFAMAACyEAMA6BIAAC4UAQCbFAUAOzAAAAEAACYCEgBfBAAAeAQAAH4EAAD3BgAAQAwDABQNBQAcDXoBPRAAAEIQAAC3EAAA1RAAADMRBwCSEQAACBKMAKUSAACnEgAAfBMAAOITAAA7MAAAAQAAxgAQALkAKAApAXAAnAEOAGEEAAB/BQAAzQUAANoGAwDfBgIA8AYBADwMAwC/DwAAsBMAANETBQBIFAMAgBQAAJUUAAA7MAAAAQAAqABCAFYDFAB7BAAAhQQBAJAEAgBrBQAAgAUBAJoFAADVBgQA4wYMAPEHAQD0BwEA9wgBAEEJAQBXCQEAYgkBAFIMAQBiDAEAbwwAABoNAQC7DwEAzA8BAAQQAQAHEAEAIRAAAEMQAQBNEAEAVRAAALgQAADIEAEA4RABAOQQAABKEQEAkxEAAJ4RAACgEQAAohEAAKURAACnEQAAqREAALQRDQDLEQEAzhECAN4RAQCWEgEA+hIBADMTAABoEwEAbhMBAHcTAwCWEwEA2BMBAOgTAQDsEwEAChQBABIUAQA/FAEAUxQBAG8UAgB7FAMAixQDAKMUAACzFAEAtxQBALoUAQC+FAEAxRQBADswAAABAACcACcA4gBGAJoBAQC1AQEAXgQAAHwEAACDBAAAeAUBAJIFAQCgBwAAowcAAOQHAADmBwAA9QsJAHwMAQDLDAEAyA8BAP0PAQA7EAAASBADANYQAQAjEQEALREBAEYRAQCjEgAA8BIBAAITAwB9EwEAnxMBAM0TAQDgEwEA4xMDAAcUAABNFAUAWxQBAGAUAACXFAEAmhQAAKoUBQC8FAEAOzAAAAEAACkADABqBA0AmAUBABcHAAB2CQEAbAwAANIMAACXDgAAHRADAMYRAwCsEgMA3RMBAI8UBQA7MAAAAQAAHAANAIAEAQCJBAEA4wcAAOUHAABwDAMAwQ8CAMoPAADtEAEARBEAAFgRAQAKEwAAoxMHAKQUAAA6MAAAAQAAAAAADwAQAAAAegSDBQEHAgcDBwQHBQcGBwcHCAc6EEURxBHFEfkSdxQDYAQAAGIEAAB4DAAAB38EAACdBwAAnwcAAKIHAAB2DAAAxA8AAMYPAAAE8wYAAHQMAAB1DAAAxQ8AADswAAABAAAFAAIA3gYAACkUBAAAAXcMAAABzgUAAA==\",\"AAAAAAA7MAAAAQAA7QABABwN7QAAOjAAAAEAAAAAAFkAEAAAAIUEhgTxB/IH9wj4CFcJWAliCWMJUgxTDGIMYwwaDRsNuw+8D8wPzQ8EEAUQBxAIEEMQRBBNEE4QyBDJEOEQ4hBKEUsRnhGgEaIRpRGnEakRtBG1EcsRzBHeEd8RlhKXEvoS+xJoE2kTbhNvE5YTlxPYE9kT6BPpE+wT7RMKFAsUEhQTFD8UQBRTFFQUcBRxFHsUfBR9FH4UixSMFI0UjhSzFLQUtxS4FLoUuxS+FL8UxRTGFDswAAABAAAzABUAtQEBAJIFAQB8DAEAywwBAP0PAQBIEAMA1hABACMRAQAtEQEARhEBAPASAQACEwMAfRMBAJ8TAQDNEwEA4BMBAOMTAwBbFAEAlxQBAKoUBQC8FAEABHYJAAB3CQAA3RMAAN4TAAAAAsQRAADFEQAA\"]Ic[\"AAAAAZsRAAAABHwFAABGCQAARwkAAJ8SAAA7MAAAAQAADAADAJMEBQD4BgUAKBQAAAADnAcAAEYRAABHEQAAAaQQAAAAB04RAABQEQAAUhEAAFQRAABWEQAAxBEAAMURAAAAAZ0HAAA=\",\"\"]Ko[\"AAACYgIAAM8CAAAAADswAAABAAALAAMAxQEBANcBAQAzEQcAOzAAAAEAAAcAAQDLBAcAOzAAAAEAAA8ABQDxBwEABBABAE0QAQC0EQEAuhEHAAAC3RMAAN4TAAA=\",\"AAAAAfsPAAAAAAAAAAAAAAAAAAAAAAX6DwAA/A8AAAMQAAAGEAAA3xMAAA==\"]AAg[\"AAAEYwIAAM0CAABICQAASQkAAAS7AQAAwwEAAMcBAADUAQAAAmsCAADWAgAAAAA6MAAAAQAAAAAAEwAQAAAAhQSGBPcI+Ai6ELwQvhDAEMEQTxFREVMRVRFXEfoS+xK3FLgUuhS7FAJ9EwAAfhMAAAV+DAAAfwwAAIAMAACBDAAAggwAAAAFThEAAFARAABSEQAAVBEAAFYRAAAAAAAC0AEAAN4GAAA=\",\"AAAAAAAAAAAAAAAAAAAAAAAABPkIAAD6CAAA+wgAAPwIAAA=\"]C@o[\"AAADRQkAAGoTAABrEwAABbkBAABcCgAA3REAAHATAABxEwAAOjAAAAEAAAAAAAcAEAAAAMQB1QFKCUsJPgqVCr0KpBIBpRIAAAWwEwAASBQAAEkUAABKFAAASxQAADowAAABAAAAAAAXABAAAAD0B/UHug9DEEQQzhCeEaARohGlEacRqRG6EbsRvBG9Eb4RvxHAEcER2BPZE3sUfBQD1xMAAK4UAACvFAAABB0QAAAeEAAAHxAAACAQAAA7MAAAAQAACQADAOMHAADlBwAAoxMHADswAAABAAAHAAEAAQcHAAACnwcAAKIHAAA=\",\"AAAEcgUAAHMFAACwDwAAsQ8AADswAAABAAAWAAsARAcHAJwRAQCfEQAAoREAAKMRAQCmEQAAqBEAAJgSAQAEFAEACBQAAFkUAQACrBMAADAUAAABnxIAAAAAAAAAAAAAAAAAADowAAABAAAAAABxABAAAACvAbABsgGzARACEQIZAhoCZwRpBIsE1QTYBM4G0gb/BgAHNgc3BzMJNAlpCWoJTwxRDGcMaAxtDG4MeQx6DLYPtw+4D7kPzw/2D/cPGBAZEEwQphCnEMQQxRDGEMcQ0xDUENgQ2RDlEOYQHREeEScRKREqETARMRE7ETwRPRE+EcIRwxHVEdYRmxKcEp0SnhLlEuYS8hLzEv4SABMoEykTKhMrEy0TLhMvEzATbBNyE3MTdBOQE6ETohOrE7ETshOzE7QTtRO2E88T0BPqE+sT8RPyExAUERQzFDQUdBR1FIEUghQ=\"]Ac[\"AAAAAAFHAwAA\",\"\"]Gc[\"AAAABBAFAABFBwAA6gcAAJ0RAAADWgkAAEcMAACcFAAAATQRAAABSRQAAAK7EQAAvxEAAAEcAQAAAR4QAAABpBMAAAECBwAA\",\"AAAAARAFAAA=\"]Gc[\"AAAABFoFAABJBwAA7gcAAKQRAAADXgkAAEsMAACfFAAAATgRAAACngEAAEsUAAACvREAAMERAAAAASAQAAABqBMAAAEGBwAA\",\"AAAAAVoFAAA=\"]Ca[\"AAAAAAJrAgAA1gIAADswAAABAAAFAAEA1xEFAA==\",\"\",1]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAAAvQGAAAKBwAA\",\"AAAAAAACuRAAALsQAAAAAroQAAC8EAAAAAKsEgAArRIAAA==\"]Eo[\"AAAAAAAAAAAAAAAAAAAAAAAAAvUGAAALBwAA\",\"AAAAAAACvRAAAL8QAAAAA74QAADAEAAAwRAAAAACrhIAAK8SAAA=\"]Ck[\"AAAAAAAAAAAAAAAAAAAAAAAABXsAAACzAQAA3wcAAPwHAAD7CAAA\",\"\"]Bg[\"AAAAAAAAAccPAAAAAAAAAsQRAADFEQAA\",\"\"]Hc[\"AAAABGcAAADkBAAAjwUAAFAQAAABHgIAAAYOAAAAZgQAAGoFAAAzBwAA0xEAADIUAAADzgAAAGYJAADLDwAAAALuEwAATBQAAA==\",\"AAAAAeQEAAAB9ggAAAFkBAAA\"]Ic[\"\",\"AAAAAAAAAAA7MAAAAQAACQABAPULCQA7MAAAAQAADQABAGoEDQA7MAAAAQAACQAEAHAMAwDBDwIARBEAAFgRAQAAAXgMAAADdgwAAMQPAADGDwAAA3QMAAB1DAAAxQ8AAAAAAXcMAAA=\"]Hk[\"AAAD3QEAAFsMAABeDAAAAQ0FAAABxAEAAAQvAAAAnwAAALkQAAC7EAAAASgQAAABWgMAAAMWAQAAjhEAAI8RAAA=\",\"AAAC3QEAAFcMAAAChwQAAA0FAAABkRMAAAABPQwAAA==\"]Hk[\"AAAD3gEAAFwMAABfDAAAAU8FAAAB1QEAAARdAAAArAAAAL0QAAC/EAAAAooBAAA1EAAAAWcDAAADfAQAAJARAACREQAA\",\"AAAC3gEAAFgMAAADiAQAAE8FAACTEwAAAAFBDAAA\"]AMo[\"AAAAAAGoEAAAAAA6MAAAAQAAAAAAEQAQAAAAyQF7BGIMYwwaDRsNuw+8D0oRSxGWEpcSixSMFLMUtBS+FL8UAoMEAADXEwAABB0QAAAeEAAAHxAAACAQAAA7MAAAAQAABwABAKMTBwA7MAAAAQAABwABAAEHBwAAAAAC0AEAAN4GAAA=\",\"AAAHdAUAAHUFAABbDAAAXAwAAF4MAABfDAAAphIAADowAAABAAAAAAAXABAAAADnB+gHVQlhCV0MYAxhDLIPsw/KEMsQzBAcEZsRqxGsEa0RrhGvEdoTRhRHFF4UXxQ7MAAAAQAACwECAJ8OBwGYEwMAOzAAAAEAAF8ABAALAFsAbRMAAJ0TAQAJFAAAAZUUAAAAAATGEQAAxxEAAMgRAADJEQAABLARAACxEQAAshEAALMRAAAB+RIAAAAAAAAAAAePBAAAjAUAAP4GAACcDgAAHxEAAC8RAADKEQAA\"]Dk[\"AAAAAAI/CgAAkwoAAAAAADswAAABAAAFAAEA3BIFAAACgAQAAIEEAAAAAmAEAABiBAAA\",\"\"]C@k[\"\",\"ADswAAABAAAFAAIAWQQEAJYUAAAC9gYAABYHAAA6MAAAAQAAAAAACgAQAAAA6gHrAX4F0QyhEucS/BJzFH8UoRSyFDowAAABAAAAAAAcABAAAAAcAh0CHgIfAiACIQIiAmgEfQWCBcQG8gYiB24JMhGkEugSexMuFC8UdhSbFJwUnRSeFJ8UoBS1FLkUOzAAAAEAADQBEQBmBAAAagUAAHwFAAD3BgAAFQcAACUHAAAUDQUACg6MALcQAAAzEQcAkhEAAAgSjAClEgAApxIAADITAAB8EwAAnBMAADowAAABAAAAAAAfABAAAAB/BYUFhgWHBfAG8Qb4BvkG+gb7BvwG/QYADAEMAgwDDMcPyw/jEEkRoBKwE+8T8BMGFEgUSRRKFEsUbhSAFKIUOzAAAAEAAEEAEwBWAxQAhAQAAJAEAgBoBQEAawUAAIAFAQCaBQAA4wYMAPQHAQD/CwAAbwwAACEQAABVEAAA5BAAALoRBwAzEwAAdxMDAG8UAACjFAAAOzAAAAEAAFsACwDiAEYAmgEBAIMEAACgBwAAowcAAOQHAADmBwAA3BIFAAcUAABNFAUAYBQAADswAAABAAAMAAUAagQAANIMAACXDgAAHRADAI8UBQA7MAAAAQAAEwAJAIAEAQCJBAEA4wcAAOUHAADBDwIAyg8AAEQRAAAKEwAAoxMHADswAAABAAAJAAIAAQcHAEIHAQABeAwAAAOfBwAAogcAAHYMAAAABSkUAAAqFAAAKxQAACwUAAAtFAAA\"]Bc[\"AAAAAAAAAAAAAAACxBEAAMURAAA=\",\"\"]Kc[\"AAAAAAF2EwAAADswAAABAAAGAAIA+AYFAEkRAAACawUAAFUQAAABgwQAAAAD7RAAAO4QAAAKEwAAAToQAAA=\",\"AAAAAAABfgQAADswAAABAAAFAAEAkwQFAAAAAAAAAAAAAAAABxsCAADUBAAA1wQAAA0HAAAOBwAAEAcAABEHAAA=\"]Do[\"AAAAAAABGAAAAAAAAeYAAAAAAAAAAAAAAAAC1AQAAP8GAAA=\",\"AAAAAAAAAAACyA8AAMkPAAA=\"]Dk[\"AAAAAAABNgAAAAEvAQAAAAAAAAAAAAAAAAAC1wQAAAAHAAA=\",\"AAAAAAAAAAABXgQAAA==\"]Ac[\"AAABdgIAAA==\",\"\"]Fg[\"AAAABBIFAABGBwAA6wcAAJ8RAAADWwkAAEgMAACdFAAAATURAAAAAAEeAQAAAAGlEwAAAQMHAAA=\",\"AAAAARIFAAAAAcUBAAA=\"]Fg[\"AAAABFwFAABKBwAA7wcAAKYRAAADXwkAAEwMAACgFAAAATkRAAABoAEAAAAAAAGpEwAAAQcHAAA=\",\"AAAAAVwFAAAAAdcBAAA=\"]Bk[\"\",\"AAAAAAAAAAA7MAAAAQAASAACAOIARgCaAQEA\"]Ck[\"\",\"AAAAAAHEBgAAOzAAAAEAAAkAAgAlBwAAJwcIAAFyFAAAAecTAAA=\"]Ck[\"AAACdwIAAIoCAAA=\",\"AAAAAAAAAvQTAAD1EwAAAAACxhEAAMcRAAA=\"]Bo[\"\",\"AAAAAAAAAAAAAAAAAjUUAAA2FAAAAAAAAYATAAA=\"]Eo[\"\",\"AAAAAAA7MAAAAQAABQABAOkSBQA7MAAAAQAABQABANETBQAAOzAAAAEAAAUAAQBNFAUAOzAAAAEAAAUAAQCPFAUA\"]Cc[\"\",\"AAAAAAKREwAAkhMAAAAEPAwAAD0MAAA+DAAAPwwAAA==\"]Eo[\"AAAAARYFAAAAATMAAAAAAAIlAQAAJgEAAA==\",\"AAA7MAAAAQAACgACAKkCBACvAgUAAhYFAACDFAAAAAABCBMAAA==\"]Eo[\"AAAAAVYFAAAAAWUAAAAAAAKaAQAAmwEAAA==\",\"AAA7MAAAAQAACgACAC8DAwA0AwYAAlYFAACEFAAAAAABCRMAAA==\"]Dg[\"AAABFgMAAAFVBQAAAAFjAAAAApUBAACWAQAA\",\"AAABJgMAAAFVBQAAAAAAAAF8BAAA\"]Eo[\"AAAAAAAAAqQBAAClAQAA\",\"AAAAAAAAB24UAACZFAAAohQAAMAUAADBFAAAwhQAAMMUAAACbxQAAKMUAAABmhQAAA==\"]Bk[\"AAAAAAAAAVUBAAA=\",\"AAAB7wIAAAAAAXgEAAA=\"]Bg[\"AAAAAWAFAAAAAAGmAQAA\",\"AAAAAWAFAAA=\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAc0MAAA=\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA+AHAAD9BwAA/AgAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAo8EAADhBwAA\",\"\"]Cc[\"AAAAAAAAAAJBCQAAQgkAAAAAAAAAAAAC0AEAAN4GAAA=\",\"\"]Fo[\"AAAAAAACfAUAAKcSAAAAAAAAAAAAAAAAAAAEAwgAAM8PAADnEAAA4BEAAA==\",\"AAGlBwAAAAAAAAAAAAAAAAAAAAAAAALoEAAAjREAAA==\"]Bk[\"AAAAAX4FAAAAAAHHDwAAASEQAAA=\",\"AAHYBwAA\"]Bg[\"AAAAAAAABOkQAADqEAAA6xAAAOwQAAA=\",\"\"]Ag[\"AAAAAr0BAADIAQAA\",\"\"]Dg[\"AAAAAAAAAAAAAnYJAAB3CQAA\",\"AAAAAAAAAAAABX4MAAB/DAAAgAwAAIEMAACCDAAA\"]AEg[\"AAAAAALCAQAA0QEAAAAAAmgFAABpBQAABKAHAACjBwAA5AcAAOYHAAA7MAAAAQAACwAEAJgFAQB+DAQA0gwAAMYRAwA6MAAAAQAAAAAACwAQAAAAiQSKBOMH5QfKD+0Q7hCwEbERshGzEQoTBHoEAABCBwAAQwcAADoQAAAEYAQAAGIEAAA1FAAANhQAAAV/BAAAnwcAAKIHAADEDwAAxg8AAAN0DAAAdQwAAMUPAAA7MAAAAQAABgADANABAADeBgAAKRQEAAGAEwAAAXcMAAA=\",\"AAAAAeERAAAAAm0FAABuBQAAAAJSDAAAUwwAAAAAAAACYAQAAGIEAAA=\"]He[\"\",\"AAAAAAAEgwwAAIQMAACFDAAAhgwAAAJZDAAAchQAAAKLEQAA5xMAAAWpEAAAqhAAAKsQAACsEAAA1xMAAAGiEgAAAAH5EgAAAAGdBwAAAAHQAQAAAAABzgUAAA==\",1]AMk[\"AAACygEAANMBAAAGuwEAAMMBAADHAQAA1AEAAHATAABxEwAABH0FAABuCQAAPQoAAJYKAAAEgwwAAIQMAACFDAAAhgwAAALvEwAA8BMAADowAAABAAAAAAAHABAAAABBCUIJyBDJEGgTaRNwFHEUOjAAAAEAAAAAAAkAEAAAAF4EoAejB+QH5gfID8kPOxCXFJgUAALjBwAA5QcAAA==\",\"AAAAOjAAAAEAAAAAABAAEAAAALEBfQd+B38HgAcFCAYIhww+ED8Q4BBMEU0R9hL3EjETehQDawkAAKgQAAAsEwAABoMMAACEDAAAhQwAAIYMAAD9EgAA/xIAAAAAAAKYBQAAmQUAAAACegQAADoQAAAAA38EAADEDwAAxg8AAAN0DAAAdQwAAMUPAAAAAAJ3DAAA1wwAADowAAABAAAAAAALABAAAAC0AYwEjQTWBNkEvQa+BjgHgQcCCAMIGhA=\"]Bg[\"AAAAAAAAAAAAAXUEAAA=\",\"AAAAAcsFAAA=\"]Bk[\"AAAAAAAAADswAAABAAANAAIAmgUAAOMGDAA=\",\"\"]Cc[\"AAABOAkAAAABIgIAAAAAAAFeBAAA\",\"AAAAAAAAAAF7BAAA\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAd4GAAA=\",\"\"]Be[\"AAAAAAAAA4UFAACGBQAAhwUAAA==\",\"\",1]Bg[\"AAAAAAAAADswAAABAAAUAAEAVgMUAA==\",\"\"]Dk[\"AAAAAAHWAQAA\",\"AAAAAARkCQAAZQkAAGcJAABoCQAAAAFmCQAAAAAAAAAAAAAAAAF4EAAA\"]Cc[\"AAAAAeMEAAAAAQ0AAAACxgAAAMcAAAA=\",\"AAAAAeMEAAA=\"]Bg[\"AAAAAAAAAAAAAXAEAAA=\",\"AAAAAfYHAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWwAAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXEAAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAbEAAAA=\",\"\"]C@m[\"AAAAAAHWAQAAATITAAABBhQAAALJAQAAMxMAADowAAABAAAAAAAdABAAAAC8AZIFkwX9D/4PLREuEfAS8RKfE6ATzRPOE+AT4RPjE+QT5RPmE+4TBxRMFJcUmBSsFK0UrhSvFLwUvRQ7MAAAAQAABgADAHYJAQAdEAMAXRQAAAGkFAAAAXcUAAAAAAHzBgAAAAAAAc4FAAA=\",\"AAAFUAkAAFEJAABSCQAAUwkAAFQJAAAEVAwAAFUMAABWDAAAlRIAADowAAABAAAAAAAXABAAAACrAccEyASeB6EH9wf1CPYIZAllCWcJaAlrCZ8QoBChEKIQoxAsEzUTmBOZE5oTmxM7MAAAAQAAIAAOAOYBAADoAQAAXwQAAGQEAAB4BAAAfgQAACcHCACDDAMAvQ8AANUQAAA/EQQAlBEEAHUTAADiEwAAOzAAAAEAACQACgBhBAAAkwQFAM0FAAAACAAAZgkAAL8PAAAkEBMA4xIBAPQTAQD3EwEAOzAAAAEAAAgABAC4EAAAthEDAM4RAgAPFAAAOzAAAAEAAAwABgBeBAAAyA8BAKkQAwCOEQMA7hMAAEwUAAAErBIAAK0SAACuEgAArxIAADswAAABAAAGAAMAcAwDAFgRAQCkFAAABHoEAAA6EAAARREAAHcUAAAAAAHzBgAAAdABAAAAADswAAABAAAeAA8AswADANQGAADiBgAAMAcCADEJAAByCQMAeAkBAAkQAAAiEAEARRACANsQBADNEQAAmhIAABQUAADEFAAA\",1]Mg[\"AAAAAe4EAAAAOjAAAAEAAAAAAAcAEAAAABkAnADmAWQEvQ/YEdsRnRMCJRAAAOMSAAACVwMAAOQGAAAC5wAAAOgAAAAAAeMHAAAAAAGfBwAA\",\"AAGqBwAAAANnAAAAaAAAAO4EAAACawIAAPcHAAAC2BEAANsRAAAAAdYGAAAAAAAAAAAAAAAABWwAAABtAAAAbgAAAG8AAABwAAAA\"]A@c[\"AAAAAR0FAAAABzgAAACkAAAA6AEAANoRAADcEQAAdRMAAJ4TAAAHMgEAADMBAAC/DwAALRAAADkQAADNEAAA5BIAAARfAwAA6QYAAG8MAAAPFAAAAaMSAAABlw4AAALlBwAApBQAAAF3FAAAAAGiBwAA\",\"AAHBBwAAAAEdBQAAAtYCAAB7BQAAAtoRAADcEQAAAdsGAAAAAAFsDAAAAAH5EgAAAAAAAAAABXEAAAByAAAAcwAAAHQAAAB1AAAA\"]Bo[\"\",\"AAAAAAAAOzAAAAEAAKgAAwC5ACgAKQFwAJwBDgA=\"]CDm[\"\",\"AAA7MAAAAQAA7QABAAcL7QA7MAAAAQAA9AAOAAcKNQBACjkAewoCAH8KEwCUCgAAlwofALgKBAC+CioA6goAAOwKAADuCgAA8AoWAOISAACDFAEAOjAAAAEAAAAAABIAEAAAAIIFzAXEBkoJSwk9Cj4KPwp6Cn4KkwqVCpYKtwq9CukK7wqRE5ITOjAAAAEAAAAAABIAEAAAAGYEagUlBzMHcAlxCesK7QrTEekS6hLrEuwS7RLuEpwTMhQ3FDgUOjAAAAEAAAAAACoAEAAAAPAG8QYACGYJAAwBDAIMAww8DD0MPgw/DFkMyw/1DzkQzRDjEOkQ6hDrEOwQSREIEwkT0RPSE9MT1BPVE9YT9BP1E/cT+BNuFHIUmRSiFMAUwRTCFMMUOjAAAAEAAAAAABoAEAAAAHsEkASRBJIEgAWBBdUG1gbXBtgG2QZvDFUQuhC8EL4QwBDBEOQQkxHOEc8R0BHnEw8UbxSjFDswAAABAABiAA8A4gBGAJoBAQBeBAAAfAQAAIMEAAB4BQEAnAcAAMgPAQA7EAAAoxIAANwSBQDuEwAATBQGAGAUAACaFAAAOzAAAAEAABEACACYBQEAbAwAANIMAACXDgAApBAAAMYRAwDdEwEAjxQFADowAAABAAAAAAAIABAAAACABIEEyg/tEO4QWBFZEQoTpBQ6MAAAAQAAAAAACwAQAAAAegSDBUIHQwc6EE4RUBFSEVQRVhH5EncUBGAEAABiBAAANRQAADYUAAADnQcAAJ8HAACiBwAAAnQMAADFDwAAOzAAAAEAAAYAAwDQAQAA3gYAACkUBAABgBMAAAABzgUAAA==\",1]Le[\"\",\"AAAAAtkBAADCBgAAAyMHAAC0DwAAtQ8AAAMVBwAA/RIAAP8SAAA6MAAAAQAAAAAABwAQAAAAxw+gEqkSqhKrEu8T8BMoFAKEBAAA/wsAAAG8AQAAAV0UAAAEwQ8AAMIPAADDDwAARBEAAAABeAwAAAR/BAAAdgwAAMQPAADGDwAAAXUMAAAAAAF3DAAA\",1]Gc[\"\",\"AAAAOjAAAAEAAAAAAAcAEAAAAOoB6wGhEvwScxR/FKEUshQCIgcAAKgQAAAFwQYAAEYJAABHCQAA+A8AAJ8SAAABsBMAAAGLEQAAAdcTAAA=\"]Bo[\"\",\"AAAAApMTAACUEwAAAARADAAAQQwAAEIMAABDDAAA\"]Bk[\"\",\"AAAAAAAAOzAAAAEAAAYAAgDaBgMA3wYCAA==\"]Fc[\"AAAAAdIBAAAAAAAABJIFAACTBQAA/Q8AAP4PAAA=\",\"AAA7MAAAAQAAQgABAIgMQgAAAAAAAAAAAAAAAAAAAAABEgcAAA==\"]Ao[\"\",\"AAA7MAAAAQAA7QABAAcI7QA=\"]AAg[\"AAAEgAIAAJICAACYAgAAsA8AAAHsBAAAA3sTAAC1FAAAuRQAAAMWAAAAmwAAANcRAAABJBAAADowAAABAAAAAAAMABAAAABWA5AEkQRoBWkFgAXjBssR6BMSFD8UfRSNFALiAAAA4wAAAA==\",\"AAGpBwAAB2ICAABjAgAAZQIAAGYCAABnAgAASAkAAGoTAAAB7AQAAARKCQAAPQoAAD4KAAA/CgAAAdcRAAABPAwAAAPVBgAAzhEAAM8RAAAAAAAAAAAAAAAAAagPAAA=\"]AAk[\"AAAE9AIAABgDAAAgAwAAsQ8AAAEaBQAAAAQ0AAAAogAAANkRAAB8EwAABCsBAAAsAQAAKxAAAIAUAAA6MAAAAQAAAAAACgAQAAAAXQOSBGsFgQXoBswR6RMTFEAUfhSOFAABlw4AAA==\",\"AAHABwAAOzAAAAEAAAYAAwDNAgQASQkAAGsTAAABGgUAAARLCQAAkwoAAJUKAACWCgAAAkAMAADZEQAAAtoGAAAACAAAAdARAAAAAAAAAAAAAAAABKoPAACrDwAArA8AAK0PAAA=\"]Gc[\"AAA7MAAAAQAACwAEAJoQBACVEwAAQRQEALYUAAA=\",\"ADswAAABAAAJAAMAggcBAIUHAgBjEwQAOzAAAAEAAAsABACaEAQAlRMAAEEUBAC2FAAA\"]Ic[\"AAAAAAAAAAA7MAAAAQAACQABAPULCQA7MAAAAQAADQABAGoEDQA7MAAAAQAACQAEAHAMAwDBDwIARBEAAFgRAQAAAXgMAAADdgwAAMQPAADGDwAAA3QMAAB1DAAAxQ8AAAAAAXcMAAA=\",\"\"]Cc[\"AAAAAr8BAABMEQAAAAAAAAF8DAAAAAGJBAAAAUIHAAA=\",\"\"]Cc[\"AAAAAs0BAABNEQAAAAAAAAF9DAAAAAGKBAAAAUMHAAA=\",\"\"]ACg[\"AAAAAoETAACCEwAAAAXFAQAAxgEAANcBAADYAQAAkhEAADswAAABAAALAAMAywQHAH8FAABkDAIAOzAAAAEAAA0ABQBrBQAA9AcBAMwPAQAhEAAAuhEHAAeOEQAAjxEAAJARAACREQAABxQAAGAUAACaFAAABmwMAACXDgAAHRAAAB4QAAAfEAAAIBAAADswAAABAAAHAAEAoxMHADswAAABAAAKAAQAAQcHAEURAAD5EgAAdxQAAAABnQcAAAHzBgAAAAAAAc4FAAA=\",\"AAAAA+ABAADhAQAA4gEAAAAB1RAAAA==\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACdgUAABgHAAA=\",\"AAAAAAAAAAK2EQAAtxEAAAAAAAAAAAAAAAAC9AYAAAoHAAA=\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACdwUAABoHAAA=\",\"AAAAAAAAAAK4EQAAuREAAAAAAAAAAAAAAAAC9QYAAAsHAAA=\"]Ak[\"\",\"AAAAAAIbEAAAHBAAAA==\"]Fc[\"AAAABBQFAABHBwAA7AcAAKERAAACXAkAAEkMAAABNhEAAAAAASABAAAAAaYTAAABBAcAAA==\",\"AAAAARQFAAAAAcYBAAA=\"]Fc[\"AAAABF4FAABLBwAA8AcAAKgRAAACYAkAAE0MAAABOhEAAAGiAQAAAAAAAaoTAAABCAcAAA==\",\"AAAAAV4FAAAAAdgBAAA=\"]Bg[\"AAAAAAAAAAAAAW8EAAA=\",\"AAAAAW8JAAA=\"]Ag[\"AAACvgEAAMwBAAA=\",\"\"]Ao[\"AAAAAAAAAAAAAAAAAAF2DAAA\",\"\"]Ag[\"\",\"AAACwhAAAMMQAAA=\"]Bg[\"AAAAAAAAAAAAAaISAAA=\",\"AAABegAAAA==\"]Dg[\"AAAAAuABAADhAQAAAAADhQUAAGQMAACpEgAAAAG8AQAAAV0UAAA=\",\"AAAAAZUSAAA=\"]Hg[\"AAAAAasRAAABmBMAAAO5EAAAQBEAAJURAAAB9BMAAAG2EQAAAakQAAACxhEAAKwSAAABsBEAAAAAAAABKhQAAA==\",\"AAAAAAAAAAJPEQAAUREAAAAAAAJOEQAAUBEAAA==\"]Ig[\"AAAAAa4RAAABmhMAAAO9EAAAQhEAAJcRAAAB9xMAAAG4EQAAAasQAAACyBEAAK4SAAABshEAAAAAAAABLBQAAA==\",\"AAAAAAGMEQAAAAADUxEAAFURAABXEQAAAAAAA1IRAABUEQAAVhEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnkAAACtDwAA\",\"\"]Bk[\"AAAAAAAAAeEAAAAAAAF3BAAA\",\"AAAAAf8HAAA=\"]Cc[\"AAAAAeAQAAABrBMAAAACYQQAAM0FAAA=\",\"AAAAAAEECAAA\"]Ek[\"AAAAAfcEAAAAASEAAAAAAAHzAAAAAAAAAAAAAAAAAtYEAAC9BgAA\",\"AAGxBwAAAAH3BAAAAAAAAAAAAe0QAAA=\"]Ek[\"AAAAASoFAAAAAUMAAAABRAEAAAAAAAAAAAAAAAAAAtkEAAC+BgAA\",\"AAHIBwAAAAEqBQAAAAAAAAAAAe4QAAA=\"]Be[\"AAAAAAA7MAAAAQAAjAABAAgSjAA=\",\"\",1]Bg[\"AAAAAAAAAAAAAXIEAAA=\",\"AAAAATsMAAA=\"]Ec[\"AAAAAAAAAAAAAAAAAAKfBwAAogcAAAHzBgAAAtABAADeBgAA\",\"AAAAAAAAAAAAAAAAAAAAAdABAAA=\"]Dk[\"AAAAAAAAAAABTxQAAAGRFAAA\",\"AAAAAAAB6xIAAAHTEwAAAAAAAAAAAAAAAAABhAcAAA==\"]Dg[\"AAAAAUIFAAAAAAJvAQAAcAEAAAHsBgAAAAAAAAAAAAAAAAEbAgAA\",\"AAAAAUIFAAA=\"]ACg[\"AAAAA7kBAABVCgAA3REAAAPyBgAAtwoAADIRAAAABEgUAABJFAAAShQAAEsUAAA6MAAAAQAAAAAADQAQAAAAVwlYCWIJYwkHEAgQ4RDiEG4TbxOWE5cT7BPtEzswAAABAAAPAAcALREBANwSBQCfEwEA7hMAAEwUAACsFAEAvBQBAAABpBQAAAF3FAAA\",\"AAAAA6wBAAC3AQAApRAAAASfEAAAoBAAAKEQAACiEAAAAuYBAADoAQAAAAAC7hMAAEwUAAAAAaQUAAABdxQAAAAAAAAAAATnAQAA6QEAADUJAADgEQAA\"]Bk[\"AAAAAAEiBwAA\",\"AAAAAAAAAAGLEQAAAAGiEgAA\"]Ho[\"AAAABeEEAACOBQAAywUAANEMAAD2EgAAArUPAAB2FAAAAhUHAAAyEwAAA8QAAACgEgAABhQAAAFpBQAAAZwHAAABpBAAAA==\",\"AAAAAuEEAADCBgAAASMHAAAAAAABvAEAAAFdFAAA\"]Gc[\"AAAAAvcSAAAIFAAAAckGAAAB9wYAAAEqAQAAArgQAAAzEwAAAAEXBwAAAAGDBQAAAAGdBwAAAfMGAAAAAAABzgUAAA==\",\"AAAAAAAAAAHJAQAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXgAAAA=\",\"\"]Fg[\"AAAD9gYAABYHAAAVEAAABGAMAADREAAA0hEAAF4UAAAFHQIAAIIFAADMBQAAngcAAGUJAAAAAsoAAAD1DwAA\",\"AAABKxEAAA==\"]Fg[\"AAAABGEMAADSEAAA1BEAAF8UAAACoQcAAGcJAAAB9wYAAAFyAQAAAAABFwcAAAABgwUAAAAAAAAAAAHOBQAA\",\"AAABLBEAAA==\"]Dg[\"AAAAAUcFAAAAAVcAAAABewEAAA==\",\"AAAAAUcFAAAAAAAAAAAAAAAAAAAAAAF7AAAA\"]Bk[\"AAAAAAEcAgAAAAAAAAFsBAAA\",\"AAAAAWoMAAA=\"]Cc[\"AAAAAAH3BwAAAAAAAAFtBAAA\",\"AAAAAAACawwAAPgSAAA=\"]Dk[\"\",\"AAAAADswAAABAAATAAEAiAcTADswAAABAAATAAEAmwATADswAAABAAATAAEAJBATAA==\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXYAAAA=\",\"\"]Fg[\"AAAAAWEFAAAAAAGoAQAAAAAAAAAAAX8EAAAAAAABdwwAAAa1AAAAtAEAABQCAADiBgAAOAcAAJoSAAA=\",\"AAHXBwAAAAFhBQAA\"]Hk[\"AAAErwAAAGYCAAByBQAAVwwAAAEPBQAAAAIxAAAAoQAAAAEqEAAAAlwDAADnBgAAAhkBAAAaAQAA\",\"AAABmAIAAARpAAAAagAAAGsAAAAPBQAAAcQBAAAAAT8MAAAB2QYAAA==\"]Kc[\"AAAEsAAAANECAABzBQAAWAwAAAFRBQAAAARfAAAArgAAAD0QAABCEAAAA40BAACOAQAANxAAAAJpAwAA7gYAAA==\",\"AAABIAMAAAFRBQAAAdUBAAABQwwAAANhBAAAzQUAAOAGAAAAAAAAAAAAAAAAAAR2AAAAdwAAAHgAAAB5AAAA\"]Ak[\"AAAAAAJTEAAAVBAAAA==\",\"\"]Ao[\"AAAAAAAAAAACtQEAANwSAAA=\",\"\"]Ao[\"AAAAAAAAAAACtgEAAN8SAAA=\",\"\"]Dc[\"AAAAAAAAAAABGwEAAAAAAAAAAAAAAAWzAAAAjAQAADAHAAD/DwAA2xAAAA==\",\"\"]Fc[\"AAAAAAAAAY8BAAAAAAAAAAAAAAAAAAW0AAAAjQQAADEHAAAAEAAA3BAAAA==\",\"AAAAAAAAAAAAARcHAAAAAoMFAABFEQAA\"]Fc[\"AAAAAWIFAAAAAAGpAQAAAoQEAAD/CwAAAAAAAAF4DAAAAAAAAAAFtgAAADIHAAAyCQAAARAAAN0QAAA=\",\"AAAAAWIFAAA=\"]Hg[\"AAABlQAAAAHzBAAAAAIeAAAAFA0AAAAAAe8AAAAAAAAAAAAAAAADrwEAANUEAABPDAAA\",\"AAGtBwAAAAHzBAAAAAAAAAAAAAAAAAAAAAAEOQcAADoHAAA9BwAAPgcAAA==\"]Hg[\"AAAAApgAAAAkBQAAAAI+AAAAFw0AAAE8AQAAAAAAAAAAAAAAAAADsAEAANgEAABRDAAA\",\"AAHEBwAAAAEkBQAAAAAAAAAAAAAAAAAAAAAEOwcAADwHAAA/BwAAQAcAAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAGAEwAA\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXcAAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm0AAAAPBwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnIAAAAUBwAA\",\"\"]Bg[\"AAAAAAAAAAAAAXEEAAA=\",\"AAAAARMNAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAbIAAAA=\",\"\"]Hc[\"AAAAAAAB+A8AAAEoFAAAAAFQFAAAAZIUAAAAAAAAAAAAADowAAABAAAAAAANABAAAAD+BjEJdAmcDgYQCRBFEB8RLxHNEf4SABPfExQU\",\"AAAAAAAB7BIAAAHUEwAA\"]Ak[\"AAAAAAIuFAAALxQAAA==\",\"\"]Cg[\"AAAAATETAAABawkAAAF+BAAAAAABgwQAAA==\",\"AAAAAAFQDAAA\"]Ag[\"\",\"AAAAAAAAAeEGAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm4AAAC+DwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnMAAADADwAA\",\"\"]Ag[\"AAAAAAAAAAHvBgAA\",\"\"]Dk[\"AAAAAAAAOzAAAAEAAKgAAwC5ACgAKQFwAJwBDgAAOzAAAAEAAEgAAgDiAEYAmgEBAA==\",\"\"]Hg[\"AAAAAlIFAAAZBwAAAWgJAAAEYAAAAJ0TAACeEwAACRQAAAOQAQAAkQEAAJUUAAABagMAAAABbAwAAAAB+RIAAAAAAfMGAAA=\",\"AAABAhAAAAFSBQAAAdYBAAAAAc0QAAA=\"]Dk[\"AAAAAQUFAAAAASgAAAAAAeUGAAACBwEAAAgBAAA=\",\"AAAAAgUFAABcCgAAAAAAAdcGAAA=\"]Dk[\"AAAAATwFAAAAAU4AAAACYQEAAGIBAAAB6gYAAA==\",\"AAAAATwFAAABvQoAAAAB3AYAAA==\"]Ck[\"AAAAAT4QAAAAAAAAAqAHAADkBwAA\",\"AAAAAAAAAAACqRAAAKoQAAA=\"]Ck[\"AAAAAT8QAAAAAAAAAqMHAADmBwAA\",\"AAAAAAAAAAACqxAAAKwQAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAigRAACoEgAA\"]Ek[\"AAAAAwUIAACYEgAABBQAAAAAAAAAAAHjBwAAAAABnwcAAA==\",\"AAAAAAAAAAK2EQAAtxEAAAKpEAAAqhAAAA==\"]Ek[\"AAAAAwYIAACZEgAABRQAAAAAAAAAAAHlBwAAAAABogcAAA==\",\"AAAAAAAAAAK4EQAAuREAAAKrEAAArBAAAA==\"]Cg[\"AAAAAfoEAAAAASQAAAAAAAL4AAAA+QAAAA==\",\"AAAAAfoEAAA=\"]Dg[\"AAAAATAFAAAAAUoAAAACTwEAAFABAAA=\",\"AAAAATAFAAAAAAAAAAFsDAAAAAH5EgAA\"]Bo[\"AAAAAfAEAAAAARsAAAAAAAHqAAAA\",\"AAAAAfAEAAA=\"]Cc[\"AAAB7wIAAAEgBQAAAAE6AAAAATYBAAA=\",\"AAAAASAFAAA=\"]Ig[\"AAABlwAAAAH1BAAAAAIgAAAAFg0AAAAAAfEAAAAAAAAAAAAAAAA6MAAAAQAAAAAADQAQAAAA5wEZAjkHPQc5CT0Jtg/6D8QQKBOhE7ETzxOBFA==\",\"AAGvBwAAAAL1BAAAjwUAAAABvQ8AAA==\"]Ic[\"AAAAApoAAAAmBQAAAAJAAAAAGQ0AAAE+AQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAADQAQAAAA6QEaAjsHPwc7CT8JuA/8D8YQKROiE7IT0BOCFA==\",\"AAHGBwAAAAEmBQAAAAABvw8AAA==\"]Gg[\"AAACSQIAAFACAAAB5wQAAAACEQAAACkHAAAC1AAAANUAAAA=\",\"AAACSwIAAEwCAAAB5wQAAAAAAAACyA8AAMkPAAAAAAJ6BAAAOhAAAAAAAXQMAAA=\"]Do[\"AAAAASgFAAAAAkEAAAClAAAAA0ABAABBAQAALhAAAAFgAwAA\",\"AAAAASgFAAAAAAAAAV4EAAA=\"]Ck[\"AAAAAgwUAAANFAAAAAAAAAAAAAABeAwAAA==\",\"AAAAAAABJREAAA==\"]Co[\"AAAAAAABFQcAAAOpEgAAqhIAAKsSAAAAAbwBAAA=\",\"AAAAAAAB+A8AAA==\"]KBa[\"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\",1]Eo[\"AAAAAAA7MAAAAQAABQABAOkSBQA7MAAAAQAABQABANETBQAAOzAAAAEAAAUAAQBNFAUAOzAAAAEAAAUAAQCPFAUA\",\"\"]Ck[\"AAAAAAAAAX8FAAAAAAFqBAAA\",\"AAAAAAAAA2QMAABlDAAAZgwAAA==\"]Dg[\"AAAAAREFAAAAAAHMBAAAAZ4RAAABHQEAAA==\",\"AAG6BwAAAAERBQAAAAAAAZ4RAAA=\"]Dc[\"AAAAAVsFAAAAAAKfAQAA0AQAAAGlEQAA\",\"AAHTBwAAAAFbBQAAAAAAAaURAAA=\"]Fg[\"AAAAAfIEAAAAAR0AAAAAAALtAAAA7gAAAA==\",\"AAGsBwAAAAHyBAAAAARmBAAAMwcAANMRAAAyFAAAAWYJAAAAAu4TAABMFAAA\"]Fc[\"AAAAASMFAAAAAT0AAAACOgEAADsBAAA=\",\"AAHDBwAAAAEjBQAAAAACORAAAM0QAAACbwwAAA8UAAAAAAGkFAAAAXcUAAA=\"]Eo[\"AAAAAdERAAABZAkAAAACvwAAAFkMAAABkxEAAAABbgQAAA==\",\"AAAAAAHMBQAAAAJZDAAA9Q8AAAABnAcAAAGkEAAA\"]Dk[\"AAAABqESAAD8EgAAcxQAAH8UAAChFAAAshQAAAAAAAAB1xMAAA==\",\"AAAAAAAAAAGLEQAA\"]Oo[\"AAAAOjAAAAEAAAAAABEAEAAAAIcE3gSNBcUG9gdvCTsMagyHDBMNOBBPEEgR5xLaEw4UMRR6FAejEAAApBIAACwTAAB2EwAAexMAALUUAAC5FAAAOjAAAAEAAAAAAAcAEAAAAOYBZARrDL0PPxGUEfgSnBM6MAAAAQAAAAAABwAQAAAAwABJEeMSbhSZFKIUwBTCFAFoBQAAAAAAAAAAAAEpFAAA\",\"AAAAAd4EAAAB9QgAAAABWQwAAA==\"]ACk[\"AAAAOjAAAAEAAAAAAAgAEAAAAIgEVQldDLIP+w8cEa0RRhRHFDowAAABAAAAAAAHABAAAABoBHsFkAUECFAMjBHoEjAUOjAAAAEAAAAAAAoAEAAAAOgBeAQ9EEIQtxDVEJIRpRJ1E3wT4hM6MAAAAQAAAAAABwAQAAAAKQG/DzkQzRDkEoAUwRTDFAVrBQAAbwwAAA8UAABvFAAAoxQAAASjEgAABxQAAGAUAACaFAAAAmwMAACXDgAAAaQUAAADRREAAPkSAAB3FAAA\",\"AAAAAAAAAAAAAAAAAAGdBwAAAAAAAAHOBQAA\"]Io[\"AAAAA0QHAADpBwAAnBEAAANZCQAARgwAAJsUAAABMxEAAAFIFAAAA/QHAAC6EQAAvhEAAAABHRAAAAGjEwAAAQEHAAA=\",\"AAAAAARGDAAARwwAAEgMAABJDAAAAAXLBAAAzAQAAM0EAADOBAAA4xIAAA==\"]Io[\"AAAAA0gHAADtBwAAoxEAAANdCQAASgwAAJ4UAAABNxEAAAFKFAAAA/UHAAC8EQAAwBEAAAABHxAAAAGnEwAAAQUHAAA=\",\"AAAAAARKDAAASwwAAEwMAABNDAAAAAXPBAAA0AQAANEEAADSBAAA5BIAAA==\"]No[\"AAABlgAAAAH0BAAAAAIfAAAAFQ0AAAAAAfAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAAEAJnBM4GNgczCWkJZwxtDHkM9g8YEKYQ0xDYEOUQHREpETAROxE9EZkRwhHVEZsSnRLlEvISLRMvE3ITsxO1E+oT8RMQFDMUdBQ=\",\"AAGuBwAAAAH0BAAAAAAAAAAAAAAAAAAAAAAEOQkAADoJAAA9CQAAPgkAAA==\"]No[\"AAAAApkAAAAlBQAAAAI/AAAAGA0AAAE9AQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAAEQJpBNIGNwc0CWoJaAxuDHoM9w8ZEKcQ1BDZEOYQHhEqETERPBE+EZoRwxHWEZwSnhLmEvMSLhMwE3MTtBO2E+sT8hMRFDQUdRQ=\",\"AAHFBwAAAAElBQAAAAAAAAAAAAAAAAAAAAAEOwkAADwJAAA/CQAAQAkAAA==\"]Cc[\"AAAAAQwFAAAAAAAAARQBAAA=\",\"AAAAAQwFAAAAAAEADAAA\"]Ck[\"AAAAAU0FAAAAAAGHAQAA\",\"AAAAAU0FAAAAAAMBDAAAAgwAAAMMAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAF/BAAAAAAAAXcMAAA=\",\"\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAa4PAAA=\"]Eo[\"AAAAAT0FAAAAAVAAAAACZQEAAGYBAAAB6wYAAA==\",\"AAAAAT0FAAAAAAHdBgAAAAAAAAAAAAAAAAACcQUAAK8PAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAArAUAACxFAAA\"]Ck[\"AAAAAAAAAAABYBQAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAABxxQAAA==\"]Ag[\"AAACtAIAADEDAAA=\",\"\"]Bo[\"AAAAAAAAAcgAAAAAAAABcgwAAA==\",\"AAAAATgQAAA=\"]Fc[\"AAAAAe8EAAAAAxoAAABrDAAA+BIAAAHLDwAAAAHpAAAA\",\"AAGrBwAAAAHvBAAAAAEzBwAAAAAAAAAAAAAAAAAAATQHAAA=\"]Gc[\"AAAAAR8FAAAAATkAAAABNQEAAAABoxIAAAFsDAAAAAH5EgAA\",\"AAHCBwAAAAEfBQAAAAF1EwAAATkQAAAAAaMSAAAAAAAAAAAAAAABNQcAAA==\"]Do[\"AAAAAAAAAAHMDwAAApIFAAD9DwAA\",\"AAAAAb0BAAAAAAABzA8AAASSBQAA/Q8AAI4RAACPEQAA\"]Do[\"AAAAAAAAAAHNDwAAApMFAAD+DwAA\",\"AAAAAcgBAAAAAAABzQ8AAASTBQAA/g8AAJARAACREQAA\"]Ao[\"AAAAAAGoEAAAAAABzhAAAA==\",\"\"]Fk[\"AAABqhEAAAJpAAAA5wcAAAEgAgAAAAHQAAAAApAEAADOEQAAAsgPAAA7EAAAAAHKDwAAAnoEAAA6EAAAAAF2DAAAAnQMAAB1DAAA\",\"\"]Cc[\"AAAAAAAAAAN7BAAAkgQAANARAAA=\",\"AAAAAAABPRAAAA==\"]Ec[\"AAABTAIAAAHoBAAAAAISAAAAKgcAAALWAAAA1wAAAA==\",\"AAABTgIAAAHoBAAAAAAAAs4RAADPEQAA\"]Bo[\"AAABKxEAAAAAAALLAAAAzAAAAA==\",\"AAAAAAGCBQAA\"]Ck[\"AAABLBEAAAAAAAJ2AQAAdwEAAA==\",\"AAAAAAAAAAAAAAABgwUAAA==\"]Ao[\"AAAAAAAAAbATAAABug8AAA==\",\"\"]Hg[\"AAAAAmsAAAD/BwAAASECAAABcAkAAAPcAAAA8AYAAOMQAAACgAUAAFUQAAAAApgFAADSDAAABsEPAADCDwAAww8AAO0QAABEEQAAChMAAAAAAsQPAADGDwAAAcUPAAA=\",\"\"]Dk[\"AAAAAAABcQkAAALxBgAAAAgAAAKBBQAA5BAAAAABmQUAAAHuEAAA\",\"AAAAAAABQhAAAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAGAEwAA\",\"\"]AAk[\"AAABAhAAAAHCBgAAAtYBAAAjBwAABMEGAABrDAAA+A8AAPgSAAACbhQAAKIUAAADixEAAG8UAACjFAAABZwHAACOEQAAjxEAAJARAACREQAAAaQQAAAAAAABnQcAAA==\",\"AAAABBkHAADREQAA0hEAANQRAAADqwEAALQPAAC1DwAAAdMRAAAFmRQAAMAUAADBFAAAwhQAAMMUAAABDxQAAAGaFAAAAaISAAAAAAAAAAAAAtEPAADrDwAAOzAAAAEAAAUAAgASAgIA/w8CAA==\"]Cc[\"AAAAAT4FAAAAAVEAAAACZwEAAGgBAAA=\",\"AAAAAT4FAAA=\"]Dc[\"AAAAAAAAAAA7MAAAAQAABQABANwSBQA=\",\"AAAABN8BAADjAQAA5AEAAOUBAAA=\"]Ao[\"AAAAAd8BAAAAAAAAAUgQAAA=\",\"\"]Ao[\"AAAAAeQBAAAAAAAAAUkQAAA=\",\"\"]Eo[\"AAAAAawRAAABmRMAAAO7EAAAQREAAJYRAAAB9RMAAAG3EQAAAaoQAAACxxEAAK0SAAABsREAAAAAAAABKxQAAA==\",\"\"]Eo[\"AAAAAa8RAAABmxMAAAO/EAAAQxEAAJgRAAAB+BMAAAG5EQAAAawQAAACyREAAK8SAAABsxEAAAAAAAABLRQAAA==\",\"\"]Bc[\"AAAAAAAAApMEAAD4BgAAAAFKEAAA\",\"\"]Bc[\"AAAAAAAAApYEAAD7BgAAAAFLEAAA\",\"\"]Ec[\"AAAAAdkBAAAAAv0SAAD/EgAAAu8TAADwEwAAAoQEAAD/CwAAAAAAAAABfwQAAA==\",\"AAAAAAFHAwAA\"]Gg[\"AAAAAeoEAAAAAhQAAAAsBwAAAt0AAADeAAAA\",\"AAADVQIAAFcCAABYAgAAAeoEAAAAAAABVRAAAAACmAUAANIMAAAC7RAAAAoTAAAAAAABxQ8AAA==\"]Eg[\"AAAAASsFAAAAAkQAAACnAAAAA0UBAABGAQAAMBAAAAFiAwAA\",\"AAAAASsFAAAAAAAAAAGZBQAAAe4QAAA=\"]Ec[\"AAAAAAAAAXUBAAAAAAAAAAAAAAAAAALaBAAAdQkAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAc4FAAA=\"]Ec[\"AAABRAwAAAHdBAAAAAELAAAAAbsAAAA=\",\"AAAAAd0EAAAAAUcJAAAAAAAAAAAAAAAAAAABvwYAAA==\"]Dg[\"AAAAAAF9BQAAAAAAAAAAAAAAAAAAAALoEAAAjREAAA==\",\"AAGmBwAAAAAAAcEGAAA=\"]Ac[\"AAABeQIAAA==\",\"\"]Do[\"AAAAAQQFAAAAAScAAAAAAAIFAQAABgEAAA==\",\"AAAChgIAAIcCAAABBAUAAAAAAAAAAd0TAAA=\"]Dk[\"AAAAATsFAAAAAU0AAAACXwEAAGABAAA=\",\"AAAC+gIAAPsCAAABOwUAAAAAAAAAAd4TAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAkwJAABOCQAA\"]Dk[\"AAAAAAAAAAABIwEAAA==\",\"AAABpQIAAAAAAAAAAAABgAQAAAFCBwAAAWAEAAABnwcAAA==\"]Dg[\"AAAAAAAAAZgBAAA=\",\"AAABKwMAAAAAAAAAAAABgQQAAAFDBwAAAWIEAAABogcAAA==\"]Dk[\"AAAAARMFAAAAAcUBAAABzQQAAAGgEQAAAR8BAAA=\",\"AAG7BwAAAAETBQAAAAAAAaARAAA=\"]Dk[\"AAAAAV0FAAAAAdcBAAACoQEAANEEAAABpxEAAA==\",\"AAHUBwAAAAFdBQAAAAAAAacRAAA=\"]Ck[\"AAAAASwFAAAAAUUAAAACRwEAAEgBAAA=\",\"AAAAASwFAAAAAAHxBgAA\"]Eg[\"AAAAAf8EAAAAAiYAAACdAAAAASYQAAABWAMAAAIAAQAA8BIAAA==\",\"AAG2BwAAAYACAAAC/wQAAFUKAAA=\"]Eg[\"AAAAATYFAAAAAkwAAACoAAAAAloBAAAxEAAAAWMDAAAB8RIAAA==\",\"AAHOBwAAAfQCAAABNgUAAAG3CgAA\"]Ao[\"AAAAAAAAAAAC1hAAAI4RAAA=\",\"\"]Ao[\"AAAAAAAAAAAC1xAAAJARAAA=\",\"\"]Do[\"AAABegAAAAHcBAAAAAABugAAAA==\",\"AAAAAdwEAAAAAUYJAAAAAAAAAAAAAAAAAAAB2hAAAA==\"]Bg[\"AAAAAAAABNsAAACHBQAAZgwAAKsSAAA=\",\"\"]Ak[\"AAAAAAABRgAAAAFJAQAA\",\"\"]Do[\"AAAAAAAAAAAAAAAAAAAAAAAAAigRAACoEgAA\",\"AAGkBwAAAAAAAAAAAAAAAAAAAAAAAAHnEAAA\"]Cg[\"AAAAAAPyBgAAbgkAADIRAAA=\",\"AAAAAAAAAAK6DwAAzhAAAA==\"]Ag[\"AAACpQIAACsDAAA=\",\"\"]Ac[\"\",\"AAAAAeISAAA=\"]Cc[\"AAAAAXkKAAACegoAAOkKAAAB6woAAALpEAAA6xAAAA==\",\"\"]Gg[\"AAAAAQMFAAABdhQAAAAAAfcIAAAEBAEAAEoQAAADEwAAWxQAAAGkEAAA\",\"AAAAA8EBAAADBQAAgxQAAAABNxQAAAAB9wgAAANKEAAAAxMAAFsUAAA=\"]Bc[\"AAAAAcEBAAAAAAAAAAAAAU4RAAA=\",\"\"]Gg[\"AAAAAToFAAAAAAFeAQAAAfgIAAADSxAAAAUTAABcFAAAAAAAAAGdBwAA\",\"AAAAA88BAAA6BQAAhBQAAAABOBQAAAAB+AgAAANLEAAABRMAAFwUAAA=\"]Bc[\"AAAAAc8BAAAAAAAAAAAAAVIRAAA=\",\"\"]Fg[\"AAABWAIAAAH4BAAAAAEiAAAAAAAC9AAAAPUAAAA=\",\"AAGyBwAAAAH4BAAAAAFwCQAAAvAGAADjEAAAA5AEAACRBAAAgAUAAA==\"]Eo[\"AAAAAS4FAAAAAUgAAAACSwEAAEwBAAA=\",\"AAHKBwAAAAEuBQAAAAFxCQAAAQAIAAAEkgQAAIEFAADkEAAA0BEAAA==\"]Ao[\"\",\"AAAAAAAAAAAAAAABVhEAAA==\"]Ek[\"AAAAAQgFAAAAASsAAAAAAAINAQAADgEAAA==\",\"AAABjgIAAAEIBQAAAAAAAAGcBwAAAaQQAAAAAk4RAABQEQAA\"]Eg[\"AAAAAUQFAAAAAVYAAAACcwEAAHQBAAA=\",\"AAABCAMAAAFEBQAAAAAAAAAAAAJSEQAAVBEAAAABnQcAAA==\"]Ao[\"AAAAAAAAAAHBEAAAAAGCDAAA\",\"\"]Jk[\"AAAAAQkFAAAABSwAAACeAAAAbQUAALkQAAC7EAAAAgAMAAAnEAAABFkDAABSDAAAuhAAALwQAAAEDwEAABABAACOEQAAjxEAAAJ+DAAAfwwAAAKwEQAAsREAAA==\",\"AAAAAgkFAADREAAAAsIBAACyEAAAAAABQQkAAA==\"]Og[\"AAAAAUkFAAAABVkAAACrAAAAbgUAAL0QAAC/EAAABoABAACBAQAAAQwAAAIMAAADDAAANBAAAARmAwAAUwwAAL4QAADAEAAAApARAACREQAAAoAMAACBDAAAArIRAACzEQAA\",\"AAAABEkFAADbBwAA3AcAANIQAAAE0QEAALMQAAC0EAAAtRAAAAAAAUIJAAACeAUAAHkFAAAAAAAAAAAAAAA7MAAAAQAACgACAN0HBQD6BwQA\"]Cc[\"AAAAAT8FAAAAAVIAAAACaQEAAGoBAAA=\",\"AAAAAT8FAAA=\"]Ck[\"AAABdAUAAAEKBQAAAAEtAAAAAAABEQEAAA==\",\"AAAAAgoFAABUDAAA\"]Dg[\"AAABdQUAAAFKBQAAAAFaAAAAAYIBAAAAAAAAAAAAAfMGAAA=\",\"AAAAAkoFAABVDAAA\"]Cc[\"AAAAAWMFAAAAAWYAAAABqgEAAA==\",\"AAAAAmMFAABWDAAA\"]Dg[\"AAAAAAAAAAAAAAABRREAAA==\",\"AAAABrYQAADvEgAA2xMAANwTAAAMFAAADRQAAA==\"]Ak[\"AAAAAAAAAAAB3hIAAA==\",\"\"]Ak[\"AAAAAAAAAAAB4RIAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnAAAAASAgAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnUAAAATAgAA\",\"\"]Bg[\"AAAAAAAAAAAAAXMEAAA=\",\"AAAAAUgRAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm8AAAA0BwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnQAAAA1BwAA\",\"\"]Bo[\"AAAAAAAAAAAAAAAEAQcAAAIHAAADBwAABAcAAA==\",\"\"]Ec[\"AAAABKwBAAC3AQAAHgUAAKUQAAAAAAE0AQAAAAAAAAQFBwAABgcAAAcHAAAIBwAA\",\"AAAAAR4FAAA=\"]Bg[\"AAAAAAAAAAAAAXQEAAA=\",\"AAAAAAF2EwAA\"]Ag[\"AAAAAAABJQcAAA==\",\"\"]Cc[\"AAAAAX0KAAACfgoAAO8KAAAB7QoAAALqEAAA7BAAAA==\",\"\"]No[\"AAAAAQEFAAABIwcAAAEyEwAAAfUPAAAGYgwAAMgQAADYEwAA7BMAAFMUAAB7FAAABwIBAAC8AQAAywwAAEgQAAACEwAA4xMAAOUTAAABXRQAAAAAAAAAAAAAA88GAADPDAAABhMAAA==\",\"AAAAAgEFAABREAAAAAHAAQAAAQgTAAAGYgwAAMgQAADYEwAA7BMAAFMUAAB7FAAABcsMAABIEAAAAhMAAOMTAADlEwAA\"]Bo[\"AAAAAVEQAAAAAcABAAAAAroQAABPEQAAAAF+DAAA\",\"\"]Nc[\"AAAAATgFAAAAAAFcAQAAOjAAAAEAAAAAAAcAEAAAAMkBYwzJEDMT2RPtE1QUfBQFzAwAAEkQAAAEEwAA5BMAAOYTAAAAAAAAAAAAAAAEzgUAANMGAADQDAAABxMAAA==\",\"AAAAAjgFAABSEAAAAAHOAQAAAQkTAAAGYwwAAMkQAADZEwAA7RMAAFQUAAB8FAAABcwMAABJEAAABBMAAOQTAADmEwAA\"]Bo[\"AAAAAVIQAAAAAc4BAAAAAr4QAABTEQAAAAGADAAA\",\"\"]Ao[\"AAAAAAAAAAAC4xMAAOQTAAA=\",\"\"]Ao[\"AAAAAAAAAAAC5RMAAOYTAAA=\",\"\"]Dc[\"AAABVQIAAAHrBAAAAAIVAAAALQcAAALfAAAA4AAAAA==\",\"AAABWgIAAAHrBAAA\"]Bk[\"AAAAAeIBAAAAAATaAAAAhgUAAGUMAACqEgAA\",\"\"]Ec[\"AAAAApMTAACUEwAAApETAACSEwAABEAMAABBDAAAQgwAAEMMAAAEPAwAAD0MAAA+DAAAPwwAAA==\",\"\"]Cc[\"AAAAAAAAAAAB3RIAAA==\",\"AAGnBwAAAAK7AQAAcBMAAA==\"]Cc[\"AAAAAAAAAAAB4BIAAA==\",\"AAG+BwAAAALHAQAAcRMAAA==\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAB8wYAAA==\"]Cg[\"AAAAAbMPAAAAAAF/AQAAAbgQAAA=\",\"AAHaBwAAAAAAAeITAAA=\"]Ek[\"AAAAAeIEAAAAAAHFAAAAAAAAAAAAAAAAAAAEbBMAAHQTAACQEwAAqxMAAA==\",\"AAGoBwAAAALiBAAAjgUAAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3IJAABGEAAAsBQAAA==\",\"\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3MJAABHEAAAsRQAAA==\",\"\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAk0JAABPCQAA\"]Ac[\"\",\"AAAAAAHHBAAA\"]Bc[\"AAAAAAABXwQAAA==\",\"AAAAAAHIBAAA\"]Ec[\"AAAAARUFAAAAAcYBAAABzgQAAAKiEQAAChQAAAEhAQAA\",\"AAG8BwAAAAEVBQAAAAAAAqIRAAAKFAAA\"]Ec[\"AAAAAV8FAAAAAdgBAAACowEAANIEAAACqREAAAsUAAA=\",\"AAHVBwAAAAFfBQAAAAAAAqkRAAALFAAA\"]Ag[\"\",\"AAAAAAABnxIAAA==\"]Co[\"AAAAArEBAADbBwAAAAABeAEAAA==\",\"AAAAAAAAAAAAAAAAAAAAAdABAAA=\"]Ac[\"\",\"AAAAAAE1EwAA\"]Cg[\"AAAAAAAAAggTAAAJEwAAAAABohIAAA==\",\"AAAAAAAAAAHnEwAA\"]Do[\"AAAAASkFAAAAAkIAAACmAAAAA0IBAABDAQAALxAAAAFhAwAA\",\"AAAAASkFAAAAAAABewQAAA==\"]Ak[\"AAAAAAACNxQAADgUAAA=\",\"\"]Ac[\"AAAAAeMBAAA=\",\"\"]Ac[\"AAAAAeUBAAA=\",\"\"]Eo[\"AAACEAMAACYDAAABUwUAAAABYQAAAAKSAQAAkwEAAA==\",\"AAAAAVMFAAAAAAAF1QYAANYGAADXBgAA2AYAANkGAAA=\"]Fk[\"AAAABMoQAADLEAAA2xMAANwTAAABtA8AAAElEQAAAaASAAAAAAFdFAAAAAAAAAAAAAF3DAAA\",\"AAAAAAAAA6kSAACqEgAAqxIAAA==\"]Fc[\"AAAAAAABwQYAAAIIEwAACRMAAAGLEQAAAAGiEgAAAAACNRQAADYUAAAAAAABgBMAAA==\",\"AAAAAAAAAXIUAAAB5xMAAA==\"]Co[\"AAAAAfsEAAAAASUAAAAAAAL6AAAA+wAAAA==\",\"AAAAAfsEAAAAAWoFAAA=\"]Co[\"AAAAATEFAAAAAUsAAAACUQEAAFIBAAA=\",\"AAAAATEFAAAAAAAAAAGXDgAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAARMHAAA=\",\"\"]Ik[\"AAAAAgAFAABZFAAAAAAAApYSAABuEwAABQEBAAC8AQAAfAwAACMRAAB9EwAAA3YJAADdEwAAXRQAAA==\",\"AAG3BwAAAAK/AQAAAAUAAAAAAAKWEgAAbhMAAAN8DAAAIxEAAH0TAAACdgkAAN0TAAA=\"]Ig[\"AAAAAjcFAABaFAAAAAABWwEAAAPJAQAAlxIAAG8TAAADfQwAACQRAAB+EwAAAncJAADeEwAA\",\"AAHPBwAAAALNAQAANwUAAAHJBgAAAAAClxIAAG8TAAADfQwAACQRAAB+EwAAAncJAADeEwAA\"]Ao[\"AAAAAAAAAc0AAAAAAAF2BAAA\",\"\"]Bc[\"AAAAAAABTwAAAAJjAQAAZAEAAA==\",\"\"]Ag[\"AAACrQIAADgDAAA=\",\"\"]Ak[\"AAAAAAAAApQEAAD5BgAA\",\"\"]Ak[\"AAAAAAAAApcEAAD8BgAA\",\"\"]Ag[\"AAACrwIAADkDAAA=\",\"\"]Dk[\"AAAAAekEAAAAAhMAAAArBwAAAtgAAADZAAAA\",\"AAABUAIAAAHpBAAAAAAAAAAAAcoPAAA=\"]Dg[\"AAAAAeYEAAAAAhAAAAAoBwAAAtIAAADTAAAA\",\"AAABSQIAAAHmBAAAAAAAAAE7EAAA\"]Co[\"AAABphIAAAEtBQAAAAFHAAAAAUoBAAA=\",\"AAHJBwAAATgJAAABLQUAAA==\"]Ec[\"AAAAAAABpxIAAAG8AAAAAAAAAAAAAAAAAAADiwQAADUJAADODwAA\",\"AAAAAbkBAAAAAAAAAdcTAAA=\"]Hk[\"AAAC6gIAAAIDAAABSwUAAAABWwAAAAKDAQAAhAEAAAAAAAAAAAAAAAAABBgCAABxBQAA1AYAABIHAAA=\",\"AAABFgMAAALSAQAASwUAAAAAAvcTAAD4EwAAAAACyBEAAMkRAAA=\"]Fc[\"AAAAA7YQAADMEAAA7xIAAAAC/RIAAP8SAAADpwEAAO8TAADwEwAAAoQEAAD/CwAAAAAAAAABfwQAAA==\",\"AAAAAdkBAAA=\"]Dc[\"AAAAAmgAAADlBAAAAh8CAAD2CAAAAQ8AAAABzwAAAA==\",\"AAAAAuUEAABQEAAA\"]Eg[\"AAAAAQYFAAAAASkAAAAAAAIJAQAACgEAAAAAAAAAAAAAAAMNBwAApw8AAK4PAAA=\",\"AAABigIAAAEGBQAA\"]Eg[\"AAAAAUAFAAAAAVMAAAACawEAAGwBAAAAAAAAAAAAAAAAAAMQBwAAqQ8AAK8PAAA=\",\"AAABAgMAAAFABQAA\"]Hk[\"AAAFOwIAAEsCAABOAgAAVwIAAFoCAAAB+QQAAAACIwAAAC4HAAAAAAL2AAAA9wAAAA==\",\"AAADdgIAAHcCAAB5AgAAAvkEAADFBgAAAswFAACjEAAAAZwTAAAB9Q8AAAGTEQAA\"]Ek[\"AAAAAS8FAAAAAkkAAAAvBwAAAk0BAABOAQAA\",\"AAAB6gIAAAEvBQAAAAAAAAAAAAAAAAAAAAAC2gQAABMHAAA=\"]Bk[\"AAAAAAABtxAAAAF+AQAA\",\"AAAAAAAAAAG4EAAA\"]Fo[\"AAABlwAAAAH2BAAAAAEWDQAAAAAB8gAAAAAAAAAAAAAAAAY6BwAAPgcAADoJAAA+CQAAtw8AAMUQAAA=\",\"AAGwBwAAAAL2BAAAjQUAAA==\"]Fo[\"AAAAApoAAAAnBQAAAAEZDQAAAT8BAAAAAAAAAAAAAAAAAAY8BwAAQAcAADwJAABACQAAuQ8AAMcQAAA=\",\"AAHHBwAAAAEnBQAAAZAFAAA=\"]Ag[\"AAACqQIAADIDAAA=\",\"\"]Cg[\"AAAAAWUFAAAAAAADug8AACEQAADOEAAA\",\"AAHZBwAAAAFlBQAA\"]Dc[\"AAAAAkUFAADcBwAAAAABeQEAAA==\",\"AAAAAUUFAAAAAAAAAAAAAAAAAAHeBgAA\"]Dg[\"AAAAAYETAAABUxAAAAAAAAL8AAAAjxEAAA==\",\"AAFDCQAAAb4BAAABgRMAAAFTEAAA\"]Dg[\"AAAAAYITAAABVBAAAAABVgEAAAABkREAAA==\",\"AAFECQAAAcwBAAABghMAAAFUEAAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAawPAAA=\",\"\"]Ac[\"\",\"AAAAAAFhFAAA\"]Ag[\"AAACsAIAADQDAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAD3BIAAN0SAADeEgAA\"]Bc[\"\",\"AAAAAAAAAAAD3xIAAOASAADhEgAA\"]Ak[\"\",\"AAAAAQETAAAAAAEoFAAA\"]ADg[\"AAAAAfwEAAAAAAA6MAAAAQAAAAAAFAAQAAAA8QcaDbsPBBAHEEMQShHLEd4R+hJoExIUcBR9FIsUjRSzFLcUuhS+FMUUOjAAAAEAAAAAAA0AEAAAAP0A1hBGEfASAhMDE58TzRPgE5cUqhSsFK4UvBQAAAHEEQAA\",\"AAGzBwAAAAH8BAAAAAAAOjAAAAEAAAAAABQAEAAAAPEHGg27DwQQBxBDEEoRyxHeEfoSaBMSFHAUfRSLFI0UsxS3FLoUvhTFFDowAAABAAAAAAAKABAAAADWEEYR8BKfE80T4BOXFKoUrBSuFLwUAAABxBEAAA==\"]ADk[\"AAAAATMFAAAAAAFXAQAAOjAAAAEAAAAAABQAEAAAAPIHGw28DwUQCBBEEEsRzBHfEfsSaRMTFHEUfhSMFI4UtBS4FLsUvxTGFDowAAABAAAAAAAMABAAAADXEEcR8RIEEwUToBPOE+ETmBSrFK0UrxS9FAAAAcURAAA=\",\"AAHLBwAAAAEzBQAAAAAAOjAAAAEAAAAAABQAEAAAAPIHGw28DwUQCBBEEEsRzBHfEfsSaRMTFHEUfhSMFI4UtBS4FLsUvxTGFDowAAABAAAAAAAKABAAAADXEEcR8RKgE84T4ROYFKsUrRSvFL0UAAABxREAAA==\"]Ag[\"AAAChwIAAPoCAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAWsEAAA=\",\"AAAAAAAAAVkMAAA=\"]Bk[\"AAAAAAAAAAAAAAFxDAAA\",\"AAAAAAABMhQAAA==\"]Do[\"AAAAAQcFAAAAASoAAAAAAAILAQAADAEAAAAAAAAAAAAAAAIOBwAAqA8AAA==\",\"AAAAAQcFAAA=\"]Do[\"AAAAAUEFAAAAAVQAAAACbQEAAG4BAAAAAAAAAAAAAAAAAAIRBwAAqg8AAA==\",\"AAAAAUEFAAA=\"]Ag[\"AAACqgIAADoDAAA=\",\"\"]Fc[\"AAAAAUMFAAAAAlUAAACpAAAAAnEBAAAyEAAAAmQDAAC4EAAA\",\"AAAAAUMFAAAAAAAAAAAAAAABnQcAAAAAAAABzgUAAA==\"]Ao[\"AAAAAAHHBAAA\",\"AAAAAAGeBwAA\"]Ao[\"AAAAAAHIBAAA\",\"AAAAAAGhBwAA\"]Ag[\"AAACrAIAADcDAAA=\",\"\"]Ag[\"AAACswIAADADAAA=\",\"\"]Dg[\"AAAAARcFAAAAAAABdxMAAAAAAAFQEQAA\",\"AAAAAhcFAAB5CgAAAXoKAAAAAekQAAA=\"]Do[\"AAAB2gEAAAFXBQAAAAAAAXkTAAAAAAABVBEAAA==\",\"AAAAAVcFAAAB6QoAAAHrCgAAAesQAAA=\"]Do[\"AAAAARkFAAAAAAADvBAAAFERAAB4EwAAAAF/DAAA\",\"AAAAAhkFAAB9CgAAAX4KAAAAAeoQAAA=\"]Eg[\"AAAB2wEAAAFZBQAAAAAAA8AQAABVEQAAehMAAAABgQwAAA==\",\"AAAAAVkFAAAB7woAAAHtCgAAAewQAAA=\"]Cc[\"AAAAAAAAApUEAAD6BgAAAAEVAQAA\",\"AAG5BwAAAAHDAQAA\"]Cc[\"AAAAAAAAA4kBAACYBAAA/QYAAA==\",\"AAHSBwAAAAHUAQAA\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAwwHAADiBwAA/gcAAA==\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAasPAAA=\",\"\"]Ao[\"AAAAAAAAAcsEAAAAAaoUAAA=\",\"\"]Bk[\"AAAAAAAAAc8EAAAAAasUAAA=\",\"AAAAAdMEAAA=\"]Eg[\"AAAAAAAAAAAAAAAAAAAAAAAABHgJAAAiEAAA3hAAACoTAAA=\",\"AAG9BwAAAATpBwAA6gcAAOsHAADsBwAA\"]Eg[\"AAAAAAAAAAAAAAAAAAAAAAAABHkJAAAjEAAA3xAAACsTAAA=\",\"AAHWBwAAAATtBwAA7gcAAO8HAADwBwAA\"]Bo[\"AAAAAAABwAEAAAAAAcsMAAAAAYAEAAAAAWAEAAA=\",\"\"]Bo[\"AAAAAAABzgEAAAAAAcwMAAAAAYEEAAAAAWIEAAA=\",\"\"]Ak[\"AAAAAAABnRMAAAEGFAAA\",\"\"]Ao[\"AAAAAAABnhMAAAAAAQcUAAA=\",\"\"]Fo[\"AAAAAUgFAAAAAlgAAACqAAAAA3wBAAB9AQAAMxAAAAFlAwAA\",\"AAABEAMAAAFIBQAAAAAAAAJ4BQAAeQUAAAAAAAAAAALQAQAA3gYAAA==\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAQ8HAAA=\"]Dg[\"AAAAASEFAAAAATsAAAABNwEAAA==\",\"AAAAASEFAAAAAAAAAAAAAAAAAAAAAAEUBwAA\"]Dg[\"AAAAAeAEAAAAAgwAAAAnBwAAAsIAAADDAAAA\",\"AAABOwIAAAHgBAAAAAABSREAAA==\"]Do[\"AAAAARwFAAAAAjcAAACjAAAAAzABAAAxAQAALBAAAAFeAwAA\",\"AAAAARwFAAAAAAAAAYMEAAA=\"]Ek[\"AAAAAf0EAAAAAAAC6BMAAD8UAAAD/gAAAC0RAADNEwAA\",\"AAG0BwAAAAH9BAAAAAAAAugTAAA/FAAAAS0RAAA=\"]Ek[\"AAAAATQFAAAAAAFYAQAAAukTAABAFAAAAi4RAADOEwAA\",\"AAHMBwAAAAE0BQAAAAAAAukTAABAFAAAAS4RAAA=\"]Bo[\"AAAAAAAAAAABeAUAAAAAAAAAAALQAQAA3gYAAA==\",\"\"]Fg[\"AAAAAf4EAAAAAAAEVwkAAE0QAAC0EQAAlhMAAAL/AAAA4BMAAA==\",\"AAG1BwAAAAH+BAAAAAAABFcJAABNEAAAtBEAAJYTAAA=\"]Fg[\"AAAAATUFAAAAAAFZAQAABFgJAABOEAAAtREAAJcTAAAB4RMAAA==\",\"AAHNBwAAAAE1BQAAAAAABFgJAABOEAAAtREAAJcTAAA=\"]Ag[\"\",\"AAAAAAAAAXIUAAA=\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAAAAGAEwAA\"]Co[\"AAAAAfEEAAAAARwAAAAAAALrAAAA7AAAAA==\",\"AAAAAfEEAAAAAAHLDwAA\"]Co[\"AAAAASIFAAAAATwAAAACOAEAADkBAAA=\",\"AAAAASIFAAAAAAAAAaMSAAA=\"]Fg[\"AAABZQIAAAELBQAAAAEuAAAAAAHmBgAAAhIBAAATAQAA\",\"AAACkgIAAM0GAAABCwUAAAAAAAHYBgAAAAAAAAAAAAAAAAGnDwAA\"]Gc[\"AAAB0AIAAALSAQAATAUAAAABXAAAAAKFAQAAhgEAAAHtBgAA\",\"AAACGAMAANEGAAABTAUAAAAAAd8GAAAAAAAAAAAAAAAAAAIYAgAAqQ8AAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA94HAAD7BwAA+ggAAA==\",\"\"]Cg[\"AAABjgIAAAAAAAAAASQBAAA=\",\"AAAAAAAAAAK6EAAAvBAAAA==\"]Cg[\"AAABCAMAAAAAAAGZAQAA\",\"AAAAAAAAAAO+EAAAwBAAAMEQAAA=\"]Bo[\"AAAAAtMEAABkBQAAATUTAAA=\",\"AAAAAmQFAADhEQAA\"]Bo[\"AAAAAAAAAckAAAAAAAABcwwAAA==\",\"AAAAAQ4UAAA=\"]Io[\"AAAAAVQFAAAAAWIAAAABlAEAAAaaBQAATxEAAFERAABTEQAAVREAAFcRAAAAAAAFThEAAFARAABSEQAAVBEAAFYRAAAAAAAAAAABxBQAAA==\",\"AAAAAVQFAAAAAAT0EwAA9RMAAPcTAAD4EwAAAAF8BAAA\"]Co[\"AAAAAmoAAADoBwAAAAAB0QAAAAKRBAAAzxEAAAHJDwAA\",\"AAABqhEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAkwJAACuEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk4JAACwEAAA\",\"\"]Co[\"AAAAARgFAAAAAAAAAicBAAAoAQAA\",\"AAAAARgFAAAAAALpEAAA6hAAAA==\"]Dc[\"AAAAAVgFAAAAAAKcAQAAnQEAAA==\",\"AAAAAlgFAADiEgAAAAAC6xAAAOwQAAA=\"]Cc[\"AAAAAAGrAQAAAAG+AAAAAAAAAXAMAAA=\",\"AAAAATEUAAA=\"]Ac[\"\",\"AAABRAwAAA==\"]Ec[\"AAABhgIAAAHtBAAAAAEXAAAAAAAC5AAAAOUAAAA=\",\"AAAAAe0EAAAESgkAAD0KAAA+CgAAPwoAAA==\"]Do[\"AAAB+wIAAAEbBQAAAAE1AAAAAi0BAAAuAQAA\",\"AAAAARsFAAAESwkAAJMKAACVCgAAlgoAAA==\"]Ak[\"\",\"AAAAAAACNxQAADgUAAA=\"]Ck[\"AAAAAt8EAABhCQAAAfUIAAABbRMAAAHBAAAA\",\"AAAAAt8EAABPEAAA\"]Bg[\"AAAAAX0HAAACnxAAALIQAAAAAQAMAAA=\",\"\"]Bk[\"AAAAAX4HAAACoBAAALMQAAAAAgEMAAACDAAA\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAjUUAAA2FAAA\",\"\"]Fo[\"AAAAAQIFAAAAAAADhQQAAGIJAABTFAAAAgMBAAC1AQAA\",\"AAG4BwAAAAECBQAAAAAAAoUEAABiCQAAAbUBAAAAAAAAAAAAAAABBhMAAA==\"]Fo[\"AAAAATkFAAAAAAFdAQAAA4YEAABjCQAAVBQAAAG2AQAA\",\"AAHQBwAAAAE5BQAAAAAAAoYEAABjCQAAAbYBAAAAAAAAAAAAAAABBxMAAA==\"]Ck[\"AAAAATIFAAAAAAJTAQAAVAEAAA==\",\"AAAAATIFAAAAAAAAAWAUAAA=\"]Ec[\"AAAAAUYFAAAAAAF6AQAAAAAAAAAAAAAAAAAFsgEAAN0HAAD6BwAA+QgAAM0MAAA=\",\"AAAAAUYFAAA=\"]Dg[\"AAAAAAFhFAAAAAG9AAAAAAAAAAACNRQAADYUAAAAAAABgBMAAA==\",\"AAABugEAAA==\"]Ag[\"AAACsgIAADYDAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAjUUAAA2FAAA\"]Cc[\"AAAAAWYFAAAAAAAAAAAAAVYRAAA=\",\"AAAB2gEAAAFmBQAA\"]Ck[\"AAAAAWcFAAAAAAACwRAAAFcRAAAAAYIMAAA=\",\"AAAB2wEAAAFnBQAA\"]Ag[\"AAACsQIAADUDAAA=\",\"\"]Dg[\"AAAAAAABMgAAAAAAASIBAAA=\",\"AAAAAAAAAAAAAAAAAAAAAykUAAAqFAAAKxQAAA==\"]Ck[\"AAAAAAABZAAAAAGXAQAA\",\"AAAAAAAAAAAAAAAAAAAAAiwUAAAtFAAA\"]Ag[\"AAACqwIAAC8DAAA=\",\"\"]Do[\"AAAAAX8HAAACoRAAALQQAAAAAQMMAAAB4RAAAA==\",\"AALLAQAAvwcAAAFFCQAAAAAAAAHhEAAA\"]Ec[\"AAAAAk4FAACABwAAAqIQAAC1EAAAAAGIAQAAAeIQAAA=\",\"AAHRBwAAAdMBAAABTgUAAAAAAAHiEAAA\"]Bg[\"AAAAAAAAAAABeQUAAA==\",\"AAABygEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk0JAACvEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk8JAACxEAAA\",\"\"]") \ No newline at end of file diff --git a/pr/619/docs/search.index/type/9ea587c05e74.js b/pr/619/docs/search.index/type/9ea587c05e74.js deleted file mode 100644 index b89176b5f..000000000 --- a/pr/619/docs/search.index/type/9ea587c05e74.js +++ /dev/null @@ -1 +0,0 @@ -rd_("CDc[\"\",\"ADswAAABAAAFAAIAWQQEAJcUAAAC9gYAABYHAAA6MAAAAQAAAAAACgAQAAAA6gHrAX4F0QyiEugS/RJ0FIAUohSzFDowAAABAAAAAAAcABAAAAAcAh0CHgIfAiACIQIiAmgEfQWCBcQG8gYiB24JMhGlEukSfBMvFDAUdxScFJ0UnhSfFKAUoRS2FLoUOzAAAAEAADgBEgBmBAAAagUAAHwFAAD3BgAAFQcAACUHAACDDAMAFA0FAAoOjAC3EAAAMxEHAJIRAAAJEowAphIAAKgSAAAzEwAAfRMAAJ0TAAA6MAAAAQAAAAAAIQAQAAAAfwWFBYYFhwXwBvEG+Ab5BvoG+wb8Bv0GAAwBDAIMAwxZDMcPyw/jEEkRoRKxE/AT8RMHFEkUShRLFEwUbxRzFIEUoxQ7MAAAAQAAQwAVAFYDFACEBAAAkAQCAGgFAQBrBQAAgAUBAJoFAADjBgwA9AcBAP8LAABvDAAAIRAAAFUQAADkEAAAixEAALoRBwA0EwAAeBMDAOgTAABwFAAApBQAADswAAABAABgAA0A4gBGAJoBAQCDBAAAoAcAAKMHAADkBwAA5gcAAKkQAwDdEgUA2BMAAAgUAABOFAUAYRQAADswAAABAAANAAYAagQAANIMAACXDgAAHRADAKMSAACQFAUAOzAAAAEAABMACQCABAEAiQQBAOMHAADlBwAAwQ8CAMoPAABEEQAACxMAAKQTBwA7MAAAAQAACgADAAEHBwBCBwEA+hIAAAF4DAAABJ0HAACfBwAAogcAAHYMAAAAOzAAAAEAAAUAAgDQAQAAKhQEAAAAAc4FAAA=\"]Bk[\"AAAAAAAAAAAEIxEAACQRAABcFAAAXRQAAA==\",\"\"]0Bg[\"\",\"AAAFUAkAAFEJAABSCQAAUwkAAFQJAAA=\"]AGg[\"AAAAAALCAQAA0QEAAAAAAmgFAABpBQAABKAHAACjBwAA5AcAAOYHAAA7MAAAAQAADQAFAJgFAQB2CQEAfgwEANIMAADGEQMAOjAAAAEAAAAAAAsAEAAAAIkEigTjB+UHyg/tEO4QsBGxEbIRsxELEwR6BAAAQgcAAEMHAAA6EAAABGAEAABiBAAANhQAADcUAAAFfwQAAJ8HAACiBwAAxQ8AAMYPAAADdAwAAHUMAADEDwAAOzAAAAEAAAYAAwDQAQAA3gYAACoUBAABgRMAAAF3DAAA\",\"AAAAAeIRAAAAAm0FAABuBQAAAAJSDAAAUwwAAAAFfgwAAH8MAACADAAAgQwAAIIMAAAAAAJgBAAAYgQAAA==\"]ANg[\"AAAEZwIAAM4CAADNBgAA0QYAAANUDAAAVQwAAFYMAAACwgEAANEBAAA7MAAAAQAAjAABAAkSjAAAOzAAAAEAAAcAAwBoBQEAeBMDAMYUAQAEoAcAAKMHAADkBwAA5gcAADswAAABAAASAAcAmAUBABcHAAB2CQEAfgwEANIMAADGEQMArRIDADowAAABAAAAAAAKABAAAACABIEEiQSKBOMH5QfKD7ARsRGyEbMRBXoEAACDBQAAQgcAAEMHAABFEQAABGAEAABiBAAANhQAADcUAAAEnwcAAKIHAADFDwAAxg8AAATzBgAAdAwAAHUMAADEDwAABSoUAAArFAAALBQAAC0UAAAuFAAAAYETAAAAAc4FAAA=\",\"AAAAAAACbQUAAG4FAAAAAlIMAABTDAAAATsQAAAFfgwAAH8MAACADAAAgQwAAIIMAAAAAAJgBAAAYgQAAAAAAAAAAwwHAACZEQAAmhEAAA==\"]Dc[\"\",\"AAAAADswAAABAAAHAAEAWQkHADswAAABAAAJAAIAPxEEAJQRBAAAAZMRAAA=\"]ADi[\"AAAABr8BAADBAQAAzQEAAM8BAABREAAAUhAAAAJ5CgAAfAoAADowAAABAAAAAAAJABAAAADAAcUBxgHOAdcB2AHrCu0KOBQ5FDswAAABAAANAAQAywQHAPUPAADpEAMABxQAAALJAQAANBMAADswAAABAAAXAAsAtQEBALwBAAB8DAEAywwBAEgQAwDWEAEAIxEBAAMTAwDYEwAAXBQBAKsUAQABXhQAAAAAAAAAAAAAAc4FAAA=\",\"AAABugEAAALTBAAAlhIAAAAAAAK6DwAAzhAAAAAAAAAAAAAAAAAEzwYAANMGAADPDAAA0AwAAA==\",1]ADe[\"AAAAAr0BAADIAQAAOzAAAAEAAAcAAQBZCQcAAASFBQAAhgUAAIcFAAChEgAAAAABXhQAAA==\",\"AAAAADswAAABAAAQAAMAxAYAAFkJBwBGDAcAOzAAAAEAAAsABAAlBwAAJREAAD8RBACUEQQAOzAAAAEAAA8ABQDLBAcAZAwCAKoSAgDkEgAAcxQAADowAAABAAAAAAAKABAAAABPEVERUxFVEVcRkxG2EbcRuBG5EegTBKkQAACqEAAAqxAAAKwQAAAAAAVOEQAAUBEAAFIRAABUEQAAVhEAAAAAAAAAAAPOBQAAvg8AAMAPAAA=\",1]Ec[\"AAAAAAAAOzAAAAEAAAYAAgDaBgMA3wYCADswAAABAAAGAAIA1QYEAEEJAQADfAQAAHgFAAB5BQAA\",\"\"]Dg[\"AAAAAAAAAAABTxQAAAGRFAAAAAAAAAAAAAABhAcAAA==\",\"AAAAAAAB6xIAAAHTEwAA\"]Eo[\"AAAAAQ4FAAABxAEAAAIwAAAAoAAAAAEpEAAAAVsDAAACFwEAABgBAAA=\",\"AAABrwAAAAEOBQAAAZMTAAAAAT4MAAA=\"]Ic[\"AAAAAVAFAAAD1QEAAK0TAAAxFAAAAl4AAACtAAAABosBAACMAQAAYQQAAM0FAAA2EAAAgRQAAAFoAwAA\",\"AAABsAAAAAJQBQAAlRMAAAABQgwAAAAAAAAAAAAAAAAAAAKxAAAAsgAAAA==\"]Ik[\"AAAAAtsEAAACEwAAASIHAAABwQYAAAG5AAAAAYsRAAABThQAAAKjEgAAkBQAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAAIwFvwaBBwIIAxAaEEwQ2hAnEcoR\",\"AAAAAdsEAAAAAeoSAAAB0hMAAA==\"]Ck[\"AAAAAeoBAAAAAAAAAVIUAAABlBQAAA==\",\"AAAAAAAB7hIAAAHWEwAA\"]Ck[\"AAAAAesBAAAAAAAAAVMUAAABlRQAAA==\",\"AAAAAAAB7xIAAAHXEwAA\"]Kk[\"AAAAAAAABH8FAACFBQAAhgUAAIcFAAAAOzAAAAEAAAkAAQD1CwkAOzAAAAEAAA0AAQBqBA0AOzAAAAEAAAkABABwDAMAwQ8CAEQRAABYEQEAAAF4DAAAA3YMAADFDwAAxg8AAAJ1DAAAxA8AAA==\",\"AAAAAAABJREAAANkDAAAZQwAAGYMAAA=\"]Nk[\"AAAAAAAAAgkTAAAKEwAABHgTAAB5EwAAehMAAHsTAAACfhMAAH8TAAAFFwcAAK0SAACuEgAArxIAALASAAACgAQAAIEEAAACgwUAAEURAAAAAAHzBgAAAAAAAc4FAAA=\",\"AAAAAAJ7BQAAYhQAAAAFmhQAAMEUAADCFAAAwxQAAMQUAAAB6BMAAAI7EAAAmxQAAAAAAAAAAAAAAASuEAAArxAAALAQAACxEAAA\"]Bg[\"AAAAAAAAAATfEQAA4BEAAAsUAAAMFAAA\",\"\"]Bk[\"\",\"AAAAAd4RAAAAAAAAAAAAAAAAAAAAAAHODwAA\"]Cc[\"AAAAAAAAAeMQAAAB5BAAAA==\",\"AAAAAAACcAkAAHEJAAA=\"]FHk[\"AAAAADswAAABAAAXAAkAHAIGAGgEAACQBQAABAgAAFAMAACyEAMA6RIAAC8UAQCcFAUAOzAAAAEAACYCEgBfBAAAeAQAAH4EAAD3BgAAQAwDABQNBQAcDXoBPRAAAEIQAAC3EAAA1RAAADMRBwCSEQAACRKMAKYSAACoEgAAfRMAAOMTAAA7MAAAAQAAxgAQALkAKAApAXAAnAEOAGEEAAB/BQAAzQUAANoGAwDfBgIA8AYBADwMAwC/DwAAsRMAANITBQBJFAMAgRQAAJYUAAA7MAAAAQAAqABCAFYDFAB7BAAAhQQBAJAEAgBrBQAAgAUBAJoFAADVBgQA4wYMAPEHAQD0BwEA9wgBAEEJAQBXCQEAYgkBAFIMAQBiDAEAbwwAABoNAQC7DwEAzA8BAAQQAQAHEAEAIRAAAEMQAQBNEAEAVRAAALgQAADIEAEA4RABAOQQAABKEQEAkxEAAJ4RAACgEQAAohEAAKURAACnEQAAqREAALQRDQDLEQEAzhECAN8RAQCXEgEA+xIBADQTAABpEwEAbxMBAHgTAwCXEwEA2RMBAOkTAQDtEwEACxQBABMUAQBAFAEAVBQBAHAUAgB8FAMAjBQDAKQUAAC0FAEAuBQBALsUAQC/FAEAxhQBADswAAABAACcACcA4gBGAJoBAQC1AQEAXgQAAHwEAACDBAAAeAUBAJIFAQCgBwAAowcAAOQHAADmBwAA9QsJAHwMAQDLDAEAyA8BAP0PAQA7EAAASBADANYQAQAjEQEALREBAEYRAQCkEgAA8RIBAAMTAwB+EwEAoBMBAM4TAQDhEwEA5BMDAAgUAABOFAUAXBQBAGEUAACYFAEAmxQAAKsUBQC9FAEAOzAAAAEAACkADABqBA0AmAUBABcHAAB2CQEAbAwAANIMAACXDgAAHRADAMYRAwCtEgMA3hMBAJAUBQA7MAAAAQAAHAANAIAEAQCJBAEA4wcAAOUHAABwDAMAwQ8CAMoPAADtEAEARBEAAFgRAQALEwAApBMHAKUUAAA6MAAAAQAAAAAADwAQAAAAegSDBQEHAgcDBwQHBQcGBwcHCAc6EEURxBHFEfoSeBQDYAQAAGIEAAB4DAAAB38EAACdBwAAnwcAAKIHAAB2DAAAxQ8AAMYPAAAE8wYAAHQMAAB1DAAAxA8AADswAAABAAAFAAIA3gYAACoUBAAAAXcMAAABzgUAAA==\",\"AAAAAAA7MAAAAQAA7QABABwN7QAAOjAAAAEAAAAAAFkAEAAAAIUEhgTxB/IH9wj4CFcJWAliCWMJUgxTDGIMYwwaDRsNuw+8D8wPzQ8EEAUQBxAIEEMQRBBNEE4QyBDJEOEQ4hBKEUsRnhGgEaIRpRGnEakRtBG1EcsRzBHfEeARlxKYEvsS/BJpE2oTbxNwE5cTmBPZE9oT6RPqE+0T7hMLFAwUExQUFEAUQRRUFFUUcRRyFHwUfRR+FH8UjBSNFI4UjxS0FLUUuBS5FLsUvBS/FMAUxhTHFDswAAABAAAzABUAtQEBAJIFAQB8DAEAywwBAP0PAQBIEAMA1hABACMRAQAtEQEARhEBAPESAQADEwMAfhMBAKATAQDOEwEA4RMBAOQTAwBcFAEAmBQBAKsUBQC9FAEABHYJAAB3CQAA3hMAAN8TAAAAAsQRAADFEQAA\"]Ic[\"AAAAAZsRAAAABHwFAABGCQAARwkAAKASAAA7MAAAAQAADAADAJMEBQD4BgUAKRQAAAADnAcAAEYRAABHEQAAAaQQAAAAB04RAABQEQAAUhEAAFQRAABWEQAAxBEAAMURAAAAAZ0HAAA=\",\"\"]Ko[\"AAACYgIAAM8CAAAAADswAAABAAALAAMAxQEBANcBAQAzEQcAOzAAAAEAAAcAAQDLBAcAOzAAAAEAAA8ABQDxBwEABBABAE0QAQC0EQEAuhEHAAAC3hMAAN8TAAA=\",\"AAAAAfsPAAAAAAAAAAAAAAAAAAAAAAX6DwAA/A8AAAMQAAAGEAAA4BMAAA==\"]AAg[\"AAAEYwIAAM0CAABICQAASQkAAAS7AQAAwwEAAMcBAADUAQAAAmsCAADWAgAAAAA6MAAAAQAAAAAAEwAQAAAAhQSGBPcI+Ai6ELwQvhDAEMEQTxFREVMRVRFXEfsS/BK4FLkUuxS8FAJ+EwAAfxMAAAV+DAAAfwwAAIAMAACBDAAAggwAAAAFThEAAFARAABSEQAAVBEAAFYRAAAAAAAC0AEAAN4GAAA=\",\"AAAAAAAAAAAAAAAAAAAAAAAABPkIAAD6CAAA+wgAAPwIAAA=\"]C@o[\"AAADRQkAAGsTAABsEwAABbkBAABbCgAA3hEAAHETAAByEwAAOjAAAAEAAAAAAAcAEAAAAMQB1QFKCUsJPQqVCr0KpRIBphIAAAWxEwAASRQAAEoUAABLFAAATBQAADowAAABAAAAAAAXABAAAAD0B/UHug9DEEQQzhCeEaARohGlEacRqRG6EbsRvBG9Eb4RvxHAEcER2RPaE3wUfRQD2BMAAK8UAACwFAAABB0QAAAeEAAAHxAAACAQAAA7MAAAAQAACQADAOMHAADlBwAApBMHADswAAABAAAHAAEAAQcHAAACnwcAAKIHAAA=\",\"AAAEcgUAAHMFAACwDwAAsQ8AADswAAABAAAWAAsARAcHAJwRAQCfEQAAoREAAKMRAQCmEQAAqBEAAJkSAQAFFAEACRQAAFoUAQACrRMAADEUAAABoBIAAAAAAAAAAAAAAAAAADowAAABAAAAAABxABAAAACvAbABsgGzARACEQIZAhoCZwRpBIsE1QTYBM4G0gb/BgAHNgc3BzMJNAlpCWoJTwxRDGcMaAxtDG4MeQx6DLYPtw+4D7kPzw/2D/cPGBAZEEwQphCnEMQQxRDGEMcQ0xDUENgQ2RDlEOYQHREeEScRKREqETARMRE7ETwRPRE+EcIRwxHWEdcRnBKdEp4SnxLmEucS8xL0Ev8SARMpEyoTKxMsEy4TLxMwEzETbRNzE3QTdRORE6IToxOsE7ITsxO0E7UTthO3E9AT0RPrE+wT8hPzExEUEhQ0FDUUdRR2FIIUgxQ=\"]Ac[\"AAAAAAFHAwAA\",\"\"]Gc[\"AAAABBAFAABFBwAA6gcAAJ0RAAADWgkAAEcMAACdFAAAATQRAAABShQAAAK7EQAAvxEAAAEcAQAAAR4QAAABpRMAAAECBwAA\",\"AAAAARAFAAA=\"]Gc[\"AAAABFoFAABJBwAA7gcAAKQRAAADXgkAAEsMAACgFAAAATgRAAACngEAAEwUAAACvREAAMERAAAAASAQAAABqRMAAAEGBwAA\",\"AAAAAVoFAAA=\"]Ca[\"AAAAAAJrAgAA1gIAADswAAABAAAFAAEA2BEFAA==\",\"\",1]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAAAvQGAAAKBwAA\",\"AAAAAAACuRAAALsQAAAAAroQAAC8EAAAAAKtEgAArhIAAA==\"]Eo[\"AAAAAAAAAAAAAAAAAAAAAAAAAvUGAAALBwAA\",\"AAAAAAACvRAAAL8QAAAAA74QAADAEAAAwRAAAAACrxIAALASAAA=\"]Ck[\"AAAAAAAAAAAAAAAAAAAAAAAABXsAAACzAQAA3wcAAPwHAAD7CAAA\",\"\"]Bg[\"AAAAAAAAAccPAAAAAAAAAsQRAADFEQAA\",\"\"]Gk[\"AAAABGcAAADkBAAAjwUAAFAQAAABHgIAAAYOAAAAZgQAAGoFAAAzBwAA1BEAADMUAAACzgAAAMsPAAAAAu8TAABNFAAA\",\"AAAAAeQEAAAB9ggAAAFkBAAA\"]Ic[\"\",\"AAAAAAAAAAA7MAAAAQAACQABAPULCQA7MAAAAQAADQABAGoEDQA7MAAAAQAACQAEAHAMAwDBDwIARBEAAFgRAQAAAXgMAAADdgwAAMUPAADGDwAAA3QMAAB1DAAAxA8AAAAAAXcMAAA=\"]Hk[\"AAAD3QEAAFsMAABeDAAAAQ0FAAABxAEAAAQvAAAAnwAAALkQAAC7EAAAASgQAAABWgMAAAMWAQAAjhEAAI8RAAA=\",\"AAAC3QEAAFcMAAAChwQAAA0FAAABkhMAAAABPQwAAA==\"]Hk[\"AAAD3gEAAFwMAABfDAAAAU8FAAAB1QEAAARdAAAArAAAAL0QAAC/EAAAAooBAAA1EAAAAWcDAAADfAQAAJARAACREQAA\",\"AAAC3gEAAFgMAAADiAQAAE8FAACUEwAAAAFBDAAA\"]AMo[\"AAAAAAGoEAAAAAA6MAAAAQAAAAAAEQAQAAAAyQF7BGIMYwwaDRsNuw+8D0oRSxGXEpgSjBSNFLQUtRS/FMAUAoMEAADYEwAABB0QAAAeEAAAHxAAACAQAAA7MAAAAQAABwABAKQTBwA7MAAAAQAABwABAAEHBwAAAAAC0AEAAN4GAAA=\",\"AAAHdAUAAHUFAABbDAAAXAwAAF4MAABfDAAApxIAADowAAABAAAAAAAXABAAAADnB+gHVQlhCV0MYAxhDLIPsw/KEMsQzBAcEZsRqxGsEa0RrhGvEdsTRxRIFF8UYBQ7MAAAAQAACwECAJ8OBwGZEwMAOzAAAAEAAF8ABAALAFsAbhMAAJ4TAQAKFAAAAZYUAAAAAATGEQAAxxEAAMgRAADJEQAABLARAACxEQAAshEAALMRAAAB+hIAAAAAAAAAAAePBAAAjAUAAP4GAACcDgAAHxEAAC8RAADKEQAA\"]Dk[\"AAAAAAI/CgAAkwoAAAAAADswAAABAAAFAAEA3RIFAAACgAQAAIEEAAAAAmAEAABiBAAA\",\"\"]C@k[\"\",\"ADswAAABAAAFAAIAWQQEAJcUAAAC9gYAABYHAAA6MAAAAQAAAAAACgAQAAAA6gHrAX4F0QyiEugS/RJ0FIAUohSzFDowAAABAAAAAAAcABAAAAAcAh0CHgIfAiACIQIiAmgEfQWCBcQG8gYiB24JMhGlEukSfBMvFDAUdxScFJ0UnhSfFKAUoRS2FLoUOzAAAAEAADQBEQBmBAAAagUAAHwFAAD3BgAAFQcAACUHAAAUDQUACg6MALcQAAAzEQcAkhEAAAkSjACmEgAAqBIAADMTAAB9EwAAnRMAADowAAABAAAAAAAfABAAAAB/BYUFhgWHBfAG8Qb4BvkG+gb7BvwG/QYADAEMAgwDDMcPyw/jEEkRoRKxE/AT8RMHFEkUShRLFEwUbxSBFKMUOzAAAAEAAEEAEwBWAxQAhAQAAJAEAgBoBQEAawUAAIAFAQCaBQAA4wYMAPQHAQD/CwAAbwwAACEQAABVEAAA5BAAALoRBwA0EwAAeBMDAHAUAACkFAAAOzAAAAEAAFsACwDiAEYAmgEBAIMEAACgBwAAowcAAOQHAADmBwAA3RIFAAgUAABOFAUAYRQAADswAAABAAAMAAUAagQAANIMAACXDgAAHRADAJAUBQA7MAAAAQAAEwAJAIAEAQCJBAEA4wcAAOUHAADBDwIAyg8AAEQRAAALEwAApBMHADswAAABAAAJAAIAAQcHAEIHAQABeAwAAAOfBwAAogcAAHYMAAAABSoUAAArFAAALBQAAC0UAAAuFAAA\"]Bc[\"AAAAAAAAAAAAAAACxBEAAMURAAA=\",\"\"]Kc[\"AAAAAAF3EwAAADswAAABAAAGAAIA+AYFAEkRAAACawUAAFUQAAABgwQAAAAD7RAAAO4QAAALEwAAAToQAAA=\",\"AAAAAAABfgQAADswAAABAAAFAAEAkwQFAAAAAAAAAAAAAAAABxsCAADUBAAA1wQAAA0HAAAOBwAAEAcAABEHAAA=\"]Do[\"AAAAAAABGAAAAAAAAeYAAAAAAAAAAAAAAAAC1AQAAP8GAAA=\",\"AAAAAAAAAAACyA8AAMkPAAA=\"]Dk[\"AAAAAAABNgAAAAEvAQAAAAAAAAAAAAAAAAAC1wQAAAAHAAA=\",\"AAAAAAAAAAABXgQAAA==\"]Ac[\"AAABdgIAAA==\",\"\"]Fg[\"AAAABBIFAABGBwAA6wcAAJ8RAAADWwkAAEgMAACeFAAAATURAAAAAAEeAQAAAAGmEwAAAQMHAAA=\",\"AAAAARIFAAAAAcUBAAA=\"]Fg[\"AAAABFwFAABKBwAA7wcAAKYRAAADXwkAAEwMAAChFAAAATkRAAABoAEAAAAAAAGqEwAAAQcHAAA=\",\"AAAAAVwFAAAAAdcBAAA=\"]Bk[\"\",\"AAAAAAAAAAA7MAAAAQAASAACAOIARgCaAQEA\"]Ck[\"\",\"AAAAAAHEBgAAOzAAAAEAAAkAAgAlBwAAJwcIAAFzFAAAAegTAAA=\"]Ck[\"AAACdwIAAIoCAAA=\",\"AAAAAAAAAvUTAAD2EwAAAAACxhEAAMcRAAA=\"]Bo[\"\",\"AAAAAAAAAAAAAAAAAjYUAAA3FAAAAAAAAYETAAA=\"]Eo[\"\",\"AAAAAAA7MAAAAQAABQABAOoSBQA7MAAAAQAABQABANITBQAAOzAAAAEAAAUAAQBOFAUAOzAAAAEAAAUAAQCQFAUA\"]Cc[\"\",\"AAAAAAKSEwAAkxMAAAAEPAwAAD0MAAA+DAAAPwwAAA==\"]Eo[\"AAAAARYFAAAAATMAAAAAAAIlAQAAJgEAAA==\",\"AAA7MAAAAQAACgACAKkCAACrAgkAAhYFAACEFAAAAAABCRMAAA==\"]Eo[\"AAAAAVYFAAAAAWUAAAAAAAKaAQAAmwEAAA==\",\"AAA7MAAAAQAACgACAC8DAwA0AwYAAlYFAACFFAAAAAABChMAAA==\"]Dg[\"AAABFgMAAAFVBQAAAAFjAAAAApUBAACWAQAA\",\"AAABJgMAAAFVBQAAAAAAAAF8BAAA\"]Eo[\"AAAAAAAAAqQBAAClAQAA\",\"AAAAAAAAB28UAACaFAAAoxQAAMEUAADCFAAAwxQAAMQUAAACcBQAAKQUAAABmxQAAA==\"]Bk[\"AAAAAAAAAVUBAAA=\",\"AAAB7wIAAAAAAXgEAAA=\"]Bg[\"AAAAAWAFAAAAAAGmAQAA\",\"AAAAAWAFAAA=\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAc0MAAA=\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA+AHAAD9BwAA/AgAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAo8EAADhBwAA\",\"\"]Cc[\"AAAAAAAAAAJBCQAAQgkAAAAAAAAAAAAC0AEAAN4GAAA=\",\"\"]Fo[\"AAAAAAACfAUAAKgSAAAAAAAAAAAAAAAAAAAEAwgAAM8PAADnEAAA4REAAA==\",\"AAGlBwAAAAAAAAAAAAAAAAAAAAAAAALoEAAAjREAAA==\"]Bk[\"AAAAAX4FAAAAAAHHDwAAASEQAAA=\",\"AAHYBwAA\"]Bg[\"AAAAAAAABOkQAADqEAAA6xAAAOwQAAA=\",\"\"]Ag[\"AAAAAr0BAADIAQAA\",\"\"]Dg[\"AAAAAAAAAAAAAnYJAAB3CQAA\",\"AAAAAAAAAAAABX4MAAB/DAAAgAwAAIEMAACCDAAA\"]AEg[\"AAAAAALCAQAA0QEAAAAAAmgFAABpBQAABKAHAACjBwAA5AcAAOYHAAA7MAAAAQAACwAEAJgFAQB+DAQA0gwAAMYRAwA6MAAAAQAAAAAACwAQAAAAiQSKBOMH5QfKD+0Q7hCwEbERshGzEQsTBHoEAABCBwAAQwcAADoQAAAEYAQAAGIEAAA2FAAANxQAAAV/BAAAnwcAAKIHAADFDwAAxg8AAAN0DAAAdQwAAMQPAAA7MAAAAQAABgADANABAADeBgAAKhQEAAGBEwAAAXcMAAA=\",\"AAAAAeIRAAAAAm0FAABuBQAAAAJSDAAAUwwAAAAAAAACYAQAAGIEAAA=\"]He[\"\",\"AAAAAAAEgwwAAIQMAACFDAAAhgwAAAJZDAAAcxQAAAKLEQAA6BMAAAWpEAAAqhAAAKsQAACsEAAA2BMAAAGjEgAAAAH6EgAAAAGdBwAAAAHQAQAAAAABzgUAAA==\",1]AMk[\"AAACygEAANMBAAAGuwEAAMMBAADHAQAA1AEAAHETAAByEwAABH0FAABuCQAAPgoAAJYKAAAEgwwAAIQMAACFDAAAhgwAAALwEwAA8RMAADowAAABAAAAAAAHABAAAABBCUIJyBDJEGkTahNxFHIUOjAAAAEAAAAAAAkAEAAAAF4EoAejB+QH5gfID8kPOxCYFJkUAALjBwAA5QcAAA==\",\"AAAAOjAAAAEAAAAAABAAEAAAALEBfQd+B38HgAcFCAYIhww+ED8Q4BBMEU0R9xL4EjITexQDawkAAKgQAAAtEwAABoMMAACEDAAAhQwAAIYMAAD+EgAAABMAAAAAAAKYBQAAmQUAAAACegQAADoQAAAAA38EAADFDwAAxg8AAAN0DAAAdQwAAMQPAAAAAAJ3DAAA1wwAADowAAABAAAAAAALABAAAAC0AYwEjQTWBNkEvQa+BjgHgQcCCAMIGhA=\"]Bg[\"AAAAAAAAAAAAAXUEAAA=\",\"AAAAAcsFAAA=\"]Bk[\"AAAAAAAAADswAAABAAANAAIAmgUAAOMGDAA=\",\"\"]Cc[\"AAABOAkAAAABIgIAAAAAAAFeBAAA\",\"AAAAAAAAAAF7BAAA\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAd4GAAA=\",\"\"]Be[\"AAAAAAAAA4UFAACGBQAAhwUAAA==\",\"\",1]Bg[\"AAAAAAAAADswAAABAAAUAAEAVgMUAA==\",\"\"]Dk[\"AAAAAAHWAQAA\",\"AAAAAAVkCQAAZQkAAGYJAABnCQAAaAkAAAAAAAAAAAAAAAAAAAF4EAAA\"]Cc[\"AAAAAeMEAAAAAQ0AAAACxgAAAMcAAAA=\",\"AAAAAeMEAAA=\"]Bg[\"AAAAAAAAAAAAAXAEAAA=\",\"AAAAAfYHAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWwAAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXEAAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAbEAAAA=\",\"\"]C@a[\"AAAAAAHWAQAAATMTAAABBxQAAALJAQAANBMAADowAAABAAAAAAAdABAAAAC8AZIFkwX9D/4PLREuEfES8hKgE6ETzhPPE+ET4hPkE+UT5hPnE+8TCBRNFJgUmRStFK4UrxSwFL0UvhQ7MAAAAQAABgADAHYJAQAdEAMAXhQAAAGlFAAAAXgUAAAAAAHzBgAAAAAAAc4FAAA=\",\"AAAFUAkAAFEJAABSCQAAUwkAAFQJAAAEVAwAAFUMAABWDAAAlhIAADswAAABAAAYAAwAqwEAAMcEAQCeBwAAoQcAAPcHAAD1CAEAZAkEAGsJAACfEAQALRMAADYTAACZEwMAOzAAAAEAACAADgDmAQAA6AEAAF8EAABkBAAAeAQAAH4EAAAnBwgAgwwDAL0PAADVEAAAPxEEAJQRBAB2EwAA4xMAADswAAABAAAjAAkAYQQAAJMEBQDNBQAAAAgAAL8PAAAkEBMA5BIBAPUTAQD4EwEAOzAAAAEAAAgABAC4EAAAthEDAM4RAgAQFAAAOzAAAAEAAAwABgBeBAAAyA8BAKkQAwCOEQMA7xMAAE0UAAAErRIAAK4SAACvEgAAsBIAADswAAABAAAGAAMAcAwDAFgRAQClFAAABHoEAAA6EAAARREAAHgUAAAAAAHzBgAAAdABAAAAADswAAABAAAeAA8AswADANQGAADiBgAAMAcCADEJAAByCQMAeAkBAAkQAAAiEAEARRACANsQBADNEQAAmxIAABUUAADFFAAA\",1]Mg[\"AAAAAe4EAAAAOjAAAAEAAAAAAAcAEAAAABkAnADmAWQEvQ/ZEdwRnhMCJRAAAOQSAAACVwMAAOQGAAAC5wAAAOgAAAAAAeMHAAAAAAGfBwAA\",\"AAGqBwAAAANnAAAAaAAAAO4EAAACawIAAPcHAAAC2REAANwRAAAAAdYGAAAAAAAAAAAAAAAABWwAAABtAAAAbgAAAG8AAABwAAAA\"]A@c[\"AAAAAR0FAAAABzgAAACkAAAA6AEAANsRAADdEQAAdhMAAJ8TAAAHMgEAADMBAAC/DwAALRAAADkQAADNEAAA5RIAAARfAwAA6QYAAG8MAAAQFAAAAaQSAAABlw4AAALlBwAApRQAAAF4FAAAAAGiBwAA\",\"AAHBBwAAAAEdBQAAAtYCAAB7BQAAAtsRAADdEQAAAdsGAAAAAAFsDAAAAAH6EgAAAAAAAAAABXEAAAByAAAAcwAAAHQAAAB1AAAA\"]Bo[\"\",\"AAAAAAAAOzAAAAEAAKgAAwC5ACgAKQFwAJwBDgA=\"]CDi[\"\",\"AAA7MAAAAQAA7QABAAcL7QA7MAAAAQAA9AAOAAcKNQBACjgAegoBAH0KFQCUCgAAlwofALgKBAC+CioA6goAAOwKAADuCgAA8AoWAOMSAACEFAEAOjAAAAEAAAAAABIAEAAAAIIFzAXEBkoJSwk9Cj4KPwp5CnwKkwqVCpYKtwq9CukK7wqSE5MTOjAAAAEAAAAAABIAEAAAAGYEagUlBzMHcAlxCesK7QrUEeoS6xLsEu0S7hLvEp0TMxQ4FDkUOjAAAAEAAAAAACkAEAAAAPAG8QYACAAMAQwCDAMMPAw9DD4MPwxZDMsP9Q85EM0Q4xDpEOoQ6xDsEEkRCRMKE9IT0xPUE9UT1hPXE/UT9hP4E/kTbxRzFJoUoxTBFMIUwxTEFDowAAABAAAAAAAaABAAAAB7BJAEkQSSBIAFgQXVBtYG1wbYBtkGbwxVELoQvBC+EMAQwRDkEJMRzhHPEdAR6BMQFHAUpBQ7MAAAAQAAYgAPAOIARgCaAQEAXgQAAHwEAACDBAAAeAUBAJwHAADIDwEAOxAAAKQSAADdEgUA7xMAAE0UBgBhFAAAmxQAADswAAABAAARAAgAmAUBAGwMAADSDAAAlw4AAKQQAADGEQMA3hMBAJAUBQA6MAAAAQAAAAAACAAQAAAAgASBBMoP7RDuEFgRWRELE6UUOjAAAAEAAAAAAAsAEAAAAHoEgwVCB0MHOhBOEVARUhFUEVYR+hJ4FARgBAAAYgQAADYUAAA3FAAAA50HAACfBwAAogcAAAJ0DAAAxA8AADswAAABAAAGAAMA0AEAAN4GAAAqFAQAAYETAAAAAc4FAAA=\",1]Le[\"\",\"AAAAAtkBAADCBgAAAyMHAAC0DwAAtQ8AAAMVBwAA/hIAAAATAAA6MAAAAQAAAAAABwAQAAAAxw+hEqoSqxKsEvAT8RMpFAKEBAAA/wsAAAG8AQAAAV4UAAAEwQ8AAMIPAADDDwAARBEAAAABeAwAAAR/BAAAdgwAAMUPAADGDwAAAXUMAAAAAAF3DAAA\",1]Gc[\"\",\"AAAAOjAAAAEAAAAAAAcAEAAAAOoB6wGiEv0SdBSAFKIUsxQCIgcAAKgQAAAFwQYAAEYJAABHCQAA+A8AAKASAAABsRMAAAGLEQAAAdgTAAA=\"]Bo[\"\",\"AAAAApQTAACVEwAAAARADAAAQQwAAEIMAABDDAAA\"]Bk[\"\",\"AAAAAAAAOzAAAAEAAAYAAgDaBgMA3wYCAA==\"]Fc[\"AAAAAdIBAAAAAAAABJIFAACTBQAA/Q8AAP4PAAA=\",\"AAA7MAAAAQAAQgABAIgMQgAAAAAAAAAAAAAAAAAAAAABEgcAAA==\"]Ao[\"\",\"AAA7MAAAAQAA7QABAAcI7QA=\"]AAg[\"AAAEgQIAAJECAACXAgAAsA8AAAHsBAAAA3wTAAC2FAAAuhQAAAMWAAAAmwAAANgRAAABJBAAADowAAABAAAAAAAMABAAAABWA5AEkQRoBWkFgAXjBssR6RMTFEAUfhSOFALiAAAA4wAAAA==\",\"AAGpBwAAB2ICAABjAgAAZQIAAGYCAABnAgAASAkAAGsTAAAB7AQAAARKCQAAPQoAAD4KAAA/CgAAAdgRAAABPAwAAAPVBgAAzhEAAM8RAAAAAAAAAAAAAAAAAagPAAA=\"]AAk[\"AAAE9AIAABgDAAAgAwAAsQ8AAAEaBQAAAAQ0AAAAogAAANoRAAB9EwAABCsBAAAsAQAAKxAAAIEUAAA6MAAAAQAAAAAACgAQAAAAXQOSBGsFgQXoBswR6hMUFEEUfxSPFAABlw4AAA==\",\"AAHABwAAOzAAAAEAAAYAAwDNAgQASQkAAGwTAAABGgUAAARLCQAAkwoAAJUKAACWCgAAAkAMAADaEQAAAtoGAAAACAAAAdARAAAAAAAAAAAAAAAABKoPAACrDwAArA8AAK0PAAA=\"]Gc[\"AAA7MAAAAQAACwAEAJoQBACWEwAAQhQEALcUAAA=\",\"ADswAAABAAAJAAMAggcBAIUHAgBkEwQAOzAAAAEAAAsABACaEAQAlhMAAEIUBAC3FAAA\"]Ic[\"AAAAAAAAAAA7MAAAAQAACQABAPULCQA7MAAAAQAADQABAGoEDQA7MAAAAQAACQAEAHAMAwDBDwIARBEAAFgRAQAAAXgMAAADdgwAAMUPAADGDwAAA3QMAAB1DAAAxA8AAAAAAXcMAAA=\",\"\"]Cc[\"AAAAAr8BAABMEQAAAAAAAAF8DAAAAAGJBAAAAUIHAAA=\",\"\"]Cc[\"AAAAAs0BAABNEQAAAAAAAAF9DAAAAAGKBAAAAUMHAAA=\",\"\"]ACg[\"AAAAAoITAACDEwAAAAXFAQAAxgEAANcBAADYAQAAkhEAADswAAABAAALAAMAywQHAH8FAABkDAIAOzAAAAEAAA0ABQBrBQAA9AcBAMwPAQAhEAAAuhEHAAeOEQAAjxEAAJARAACREQAACBQAAGEUAACbFAAABmwMAACXDgAAHRAAAB4QAAAfEAAAIBAAADswAAABAAAHAAEApBMHADswAAABAAAKAAQAAQcHAEURAAD6EgAAeBQAAAABnQcAAAHzBgAAAAAAAc4FAAA=\",\"AAAAA+ABAADhAQAA4gEAAAAB1RAAAA==\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACdgUAABgHAAA=\",\"AAAAAAAAAAK2EQAAtxEAAAAAAAAAAAAAAAAC9AYAAAoHAAA=\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACdwUAABoHAAA=\",\"AAAAAAAAAAK4EQAAuREAAAAAAAAAAAAAAAAC9QYAAAsHAAA=\"]Ak[\"\",\"AAAAAAIbEAAAHBAAAA==\"]Fc[\"AAAABBQFAABHBwAA7AcAAKERAAACXAkAAEkMAAABNhEAAAAAASABAAAAAacTAAABBAcAAA==\",\"AAAAARQFAAAAAcYBAAA=\"]Fc[\"AAAABF4FAABLBwAA8AcAAKgRAAACYAkAAE0MAAABOhEAAAGiAQAAAAAAAasTAAABCAcAAA==\",\"AAAAAV4FAAAAAdgBAAA=\"]Bg[\"AAAAAAAAAAAAAW8EAAA=\",\"AAAAAW8JAAA=\"]Ag[\"AAACvgEAAMwBAAA=\",\"\"]Ao[\"AAAAAAAAAAAAAAAAAAF2DAAA\",\"\"]Ag[\"\",\"AAACwhAAAMMQAAA=\"]Bg[\"AAAAAAAAAAAAAaMSAAA=\",\"AAABegAAAA==\"]Dg[\"AAAAAuABAADhAQAAAAADhQUAAGQMAACqEgAAAAG8AQAAAV4UAAA=\",\"AAAAAZYSAAA=\"]Hg[\"AAAAAasRAAABmRMAAAO5EAAAQBEAAJURAAAB9RMAAAG2EQAAAakQAAACxhEAAK0SAAABsBEAAAAAAAABKxQAAA==\",\"AAAAAAAAAAJPEQAAUREAAAAAAAJOEQAAUBEAAA==\"]Ig[\"AAAAAa4RAAABmxMAAAO9EAAAQhEAAJcRAAAB+BMAAAG4EQAAAasQAAACyBEAAK8SAAABshEAAAAAAAABLRQAAA==\",\"AAAAAAGMEQAAAAADUxEAAFURAABXEQAAAAAAA1IRAABUEQAAVhEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnkAAACtDwAA\",\"\"]Bk[\"AAAAAAAAAeEAAAAAAAF3BAAA\",\"AAAAAf8HAAA=\"]Cc[\"AAAAAeAQAAABrRMAAAACYQQAAM0FAAA=\",\"AAAAAAEECAAA\"]Ek[\"AAAAAfcEAAAAASEAAAAAAAHzAAAAAAAAAAAAAAAAAtYEAAC9BgAA\",\"AAGxBwAAAAH3BAAAAAAAAAAAAe0QAAA=\"]Ek[\"AAAAASoFAAAAAUMAAAABRAEAAAAAAAAAAAAAAAAAAtkEAAC+BgAA\",\"AAHIBwAAAAEqBQAAAAAAAAAAAe4QAAA=\"]Be[\"AAAAAAA7MAAAAQAAjAABAAkSjAA=\",\"\",1]Bg[\"AAAAAAAAAAAAAXIEAAA=\",\"AAAAATsMAAA=\"]Ec[\"AAAAAAAAAAAAAAAAAAKfBwAAogcAAAHzBgAAAtABAADeBgAA\",\"AAAAAAAAAAAAAAAAAAAAAdABAAA=\"]Dk[\"AAAAAAAAAAABUBQAAAGSFAAA\",\"AAAAAAAB7BIAAAHUEwAAAAAAAAAAAAAAAAABhAcAAA==\"]Dg[\"AAAAAUIFAAAAAAJvAQAAcAEAAAHsBgAAAAAAAAAAAAAAAAEbAgAA\",\"AAAAAUIFAAA=\"]ACg[\"AAAAA7kBAABUCgAA3hEAAAPyBgAAtwoAADIRAAAABEkUAABKFAAASxQAAEwUAAA6MAAAAQAAAAAADQAQAAAAVwlYCWIJYwkHEAgQ4RDiEG8TcBOXE5gT7RPuEzswAAABAAAPAAcALREBAN0SBQCgEwEA7xMAAE0UAACtFAEAvRQBAAABpRQAAAF4FAAA\",\"AAAAA6wBAAC3AQAApRAAAASfEAAAoBAAAKEQAACiEAAAAuYBAADoAQAAAAAC7xMAAE0UAAAAAaUUAAABeBQAAAAAAAAAAATnAQAA6QEAADUJAADhEQAA\"]Bk[\"AAAAAAEiBwAA\",\"AAAAAAAAAAGLEQAAAAGjEgAA\"]Ho[\"AAAABeEEAACOBQAAywUAANEMAAD3EgAAArUPAAB3FAAAAhUHAAAzEwAAA8QAAAChEgAABxQAAAFpBQAAAZwHAAABpBAAAA==\",\"AAAAAuEEAADCBgAAASMHAAAAAAABvAEAAAFeFAAA\"]Gc[\"AAAAAvgSAAAJFAAAAckGAAAB9wYAAAEqAQAAArgQAAA0EwAAAAEXBwAAAAGDBQAAAAGdBwAAAfMGAAAAAAABzgUAAA==\",\"AAAAAAAAAAHJAQAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXgAAAA=\",\"\"]Fg[\"AAAD9gYAABYHAAAVEAAABGAMAADREAAA0xEAAF8UAAAFHQIAAIIFAADMBQAAngcAAGYJAAAAAsoAAAD1DwAA\",\"AAABKxEAAA==\"]Fg[\"AAAABGEMAADSEAAA1REAAGAUAAACoQcAAGcJAAAB9wYAAAFyAQAAAAABFwcAAAABgwUAAAAAAAAAAAHOBQAA\",\"AAABLBEAAA==\"]Dg[\"AAAAAUcFAAAAAVcAAAABewEAAA==\",\"AAAAAUcFAAAAAAAAAAAAAAAAAAAAAAF7AAAA\"]Bk[\"AAAAAAEcAgAAAAAAAAFsBAAA\",\"AAAAAWoMAAA=\"]Cc[\"AAAAAAH3BwAAAAAAAAFtBAAA\",\"AAAAAAACawwAAPkSAAA=\"]Dk[\"\",\"AAAAADswAAABAAATAAEAiAcTADswAAABAAATAAEAmwATADswAAABAAATAAEAJBATAA==\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXYAAAA=\",\"\"]Fg[\"AAAAAWEFAAAAAAGoAQAAAAAAAAAAAX8EAAAAAAABdwwAAAa1AAAAtAEAABQCAADiBgAAOAcAAJsSAAA=\",\"AAHXBwAAAAFhBQAA\"]Hk[\"AAAErwAAAGYCAAByBQAAVwwAAAEPBQAAAAIxAAAAoQAAAAEqEAAAAlwDAADnBgAAAhkBAAAaAQAA\",\"AAABlwIAAARpAAAAagAAAGsAAAAPBQAAAcQBAAAAAT8MAAAB2QYAAA==\"]Kc[\"AAAEsAAAANECAABzBQAAWAwAAAFRBQAAAARfAAAArgAAAD0QAABCEAAAA40BAACOAQAANxAAAAJpAwAA7gYAAA==\",\"AAABIAMAAAFRBQAAAdUBAAABQwwAAANhBAAAzQUAAOAGAAAAAAAAAAAAAAAAAAR2AAAAdwAAAHgAAAB5AAAA\"]Ak[\"AAAAAAJTEAAAVBAAAA==\",\"\"]Ao[\"AAAAAAAAAAACtQEAAN0SAAA=\",\"\"]Ao[\"AAAAAAAAAAACtgEAAOASAAA=\",\"\"]Dc[\"AAAAAAAAAAABGwEAAAAAAAAAAAAAAAWzAAAAjAQAADAHAAD/DwAA2xAAAA==\",\"\"]Fc[\"AAAAAAAAAY8BAAAAAAAAAAAAAAAAAAW0AAAAjQQAADEHAAAAEAAA3BAAAA==\",\"AAAAAAAAAAAAARcHAAAAAoMFAABFEQAA\"]Fc[\"AAAAAWIFAAAAAAGpAQAAAoQEAAD/CwAAAAAAAAF4DAAAAAAAAAAFtgAAADIHAAAyCQAAARAAAN0QAAA=\",\"AAAAAWIFAAA=\"]Hg[\"AAABlQAAAAHzBAAAAAIeAAAAFA0AAAAAAe8AAAAAAAAAAAAAAAADrwEAANUEAABPDAAA\",\"AAGtBwAAAAHzBAAAAAAAAAAAAAAAAAAAAAAEOQcAADoHAAA9BwAAPgcAAA==\"]Hg[\"AAAAApgAAAAkBQAAAAI+AAAAFw0AAAE8AQAAAAAAAAAAAAAAAAADsAEAANgEAABRDAAA\",\"AAHEBwAAAAEkBQAAAAAAAAAAAAAAAAAAAAAEOwcAADwHAAA/BwAAQAcAAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAGBEwAA\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXcAAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm0AAAAPBwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnIAAAAUBwAA\",\"\"]Bg[\"AAAAAAAAAAAAAXEEAAA=\",\"AAAAARMNAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAbIAAAA=\",\"\"]Hc[\"AAAAAAAB+A8AAAEpFAAAAAFRFAAAAZMUAAAAAAAAAAAAADowAAABAAAAAAANABAAAAD+BjEJdAmcDgYQCRBFEB8RLxHNEf8SARPgExUU\",\"AAAAAAAB7RIAAAHVEwAA\"]Ak[\"AAAAAAIvFAAAMBQAAA==\",\"\"]Cg[\"AAAAATITAAABawkAAAF+BAAAAAABgwQAAA==\",\"AAAAAAFQDAAA\"]Ag[\"\",\"AAAAAAAAAeEGAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm4AAAC+DwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnMAAADADwAA\",\"\"]Ag[\"AAAAAAAAAAHvBgAA\",\"\"]Dk[\"AAAAAAAAOzAAAAEAAKgAAwC5ACgAKQFwAJwBDgAAOzAAAAEAAEgAAgDiAEYAmgEBAA==\",\"\"]Hg[\"AAAAAlIFAAAZBwAAAWgJAAAEYAAAAJ4TAACfEwAAChQAAAOQAQAAkQEAAJYUAAABagMAAAABbAwAAAAB+hIAAAAAAfMGAAA=\",\"AAABAhAAAAFSBQAAAdYBAAAAAc0QAAA=\"]Dk[\"AAAAAQUFAAAAASgAAAAAAeUGAAACBwEAAAgBAAA=\",\"AAAAAgUFAABbCgAAAAAAAdcGAAA=\"]Dk[\"AAAAATwFAAAAAU4AAAACYQEAAGIBAAAB6gYAAA==\",\"AAAAATwFAAABvQoAAAAB3AYAAA==\"]Ck[\"AAAAAT4QAAAAAAAAAqAHAADkBwAA\",\"AAAAAAAAAAACqRAAAKoQAAA=\"]Ck[\"AAAAAT8QAAAAAAAAAqMHAADmBwAA\",\"AAAAAAAAAAACqxAAAKwQAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAigRAACpEgAA\"]Ek[\"AAAAAwUIAACZEgAABRQAAAAAAAAAAAHjBwAAAAABnwcAAA==\",\"AAAAAAAAAAK2EQAAtxEAAAKpEAAAqhAAAA==\"]Ek[\"AAAAAwYIAACaEgAABhQAAAAAAAAAAAHlBwAAAAABogcAAA==\",\"AAAAAAAAAAK4EQAAuREAAAKrEAAArBAAAA==\"]Cg[\"AAAAAfoEAAAAASQAAAAAAAL4AAAA+QAAAA==\",\"AAAAAfoEAAA=\"]Dg[\"AAAAATAFAAAAAUoAAAACTwEAAFABAAA=\",\"AAAAATAFAAAAAAAAAAFsDAAAAAH6EgAA\"]Bo[\"AAAAAfAEAAAAARsAAAAAAAHqAAAA\",\"AAAAAfAEAAA=\"]Cc[\"AAAB7wIAAAEgBQAAAAE6AAAAATYBAAA=\",\"AAAAASAFAAA=\"]Ig[\"AAABlwAAAAH1BAAAAAIgAAAAFg0AAAAAAfEAAAAAAAAAAAAAAAA6MAAAAQAAAAAADQAQAAAA5wEZAjkHPQc5CT0Jtg/6D8QQKROiE7IT0BOCFA==\",\"AAGvBwAAAAL1BAAAjwUAAAABvQ8AAA==\"]Ic[\"AAAAApoAAAAmBQAAAAJAAAAAGQ0AAAE+AQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAADQAQAAAA6QEaAjsHPwc7CT8JuA/8D8YQKhOjE7MT0RODFA==\",\"AAHGBwAAAAEmBQAAAAABvw8AAA==\"]Gg[\"AAACSQIAAFACAAAB5wQAAAACEQAAACkHAAAC1AAAANUAAAA=\",\"AAACSwIAAEwCAAAB5wQAAAAAAAACyA8AAMkPAAAAAAJ6BAAAOhAAAAAAAXQMAAA=\"]Do[\"AAAAASgFAAAAAkEAAAClAAAAA0ABAABBAQAALhAAAAFgAwAA\",\"AAAAASgFAAAAAAAAAV4EAAA=\"]Ck[\"AAAAAg0UAAAOFAAAAAAAAAAAAAABeAwAAA==\",\"AAAAAAABJREAAA==\"]Co[\"AAAAAAABFQcAAAOqEgAAqxIAAKwSAAAAAbwBAAA=\",\"AAAAAAAB+A8AAA==\"]KAe[\"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\",1]Eo[\"AAAAAAA7MAAAAQAABQABAOoSBQA7MAAAAQAABQABANITBQAAOzAAAAEAAAUAAQBOFAUAOzAAAAEAAAUAAQCQFAUA\",\"\"]Ck[\"AAAAAAAAAX8FAAAAAAFqBAAA\",\"AAAAAAAAA2QMAABlDAAAZgwAAA==\"]Dg[\"AAAAAREFAAAAAAHMBAAAAZ4RAAABHQEAAA==\",\"AAG6BwAAAAERBQAAAAAAAZ4RAAA=\"]Dc[\"AAAAAVsFAAAAAAKfAQAA0AQAAAGlEQAA\",\"AAHTBwAAAAFbBQAAAAAAAaURAAA=\"]Fc[\"AAAAAfIEAAAAAR0AAAAAAALtAAAA7gAAAA==\",\"AAGsBwAAAAHyBAAAAARmBAAAMwcAANQRAAAzFAAAAAAC7xMAAE0UAAA=\"]Fc[\"AAAAASMFAAAAAT0AAAACOgEAADsBAAA=\",\"AAHDBwAAAAEjBQAAAAACORAAAM0QAAACbwwAABAUAAAAAAGlFAAAAXgUAAA=\"]Eo[\"AAAAAdERAAABZAkAAAACvwAAAFkMAAABkxEAAAABbgQAAA==\",\"AAAAAAHMBQAAAAJZDAAA9Q8AAAABnAcAAAGkEAAA\"]Dk[\"AAAABqISAAD9EgAAdBQAAIAUAACiFAAAsxQAAAAAAAAB2BMAAA==\",\"AAAAAAAAAAGLEQAA\"]A@g[\"AAAAOjAAAAEAAAAAABIAEAAAAIcE3gSNBcUG9gdvCTsMagyHDBMNOBBPEEgR0hHoEtsTDxQyFHsUOjAAAAEAAAAAAAcAEAAAAGUJoxClEi0TdxN8E7YUuhQ6MAAAAQAAAAAABwAQAAAA5gFkBGsMvQ8/EZQR+RKdEzowAAABAAAAAAAHABAAAADAAEkR5BJvFJoUoxTBFMMUAWgFAAAAAAAAAAAAASoUAAA=\",\"AAAAAd4EAAAB9QgAAAABWQwAAA==\"]ACk[\"AAAAOjAAAAEAAAAAAAgAEAAAAIgEVQldDLIP+w8cEa0RRxRIFDowAAABAAAAAAAHABAAAABoBHsFkAUECFAMjBHpEjEUOjAAAAEAAAAAAAoAEAAAAOgBeAQ9EEIQtxDVEJIRphJ2E30T4xM6MAAAAQAAAAAABwAQAAAAKQG/DzkQzRDlEoEUwhTEFAVrBQAAbwwAABAUAABwFAAApBQAAASkEgAACBQAAGEUAACbFAAAAmwMAACXDgAAAaUUAAADRREAAPoSAAB4FAAA\",\"AAAAAAAAAAAAAAAAAAGdBwAAAAAAAAHOBQAA\"]Io[\"AAAAA0QHAADpBwAAnBEAAANZCQAARgwAAJwUAAABMxEAAAFJFAAAA/QHAAC6EQAAvhEAAAABHRAAAAGkEwAAAQEHAAA=\",\"AAAAAARGDAAARwwAAEgMAABJDAAAAAXLBAAAzAQAAM0EAADOBAAA5BIAAA==\"]Io[\"AAAAA0gHAADtBwAAoxEAAANdCQAASgwAAJ8UAAABNxEAAAFLFAAAA/UHAAC8EQAAwBEAAAABHxAAAAGoEwAAAQUHAAA=\",\"AAAAAARKDAAASwwAAEwMAABNDAAAAAXPBAAA0AQAANEEAADSBAAA5RIAAA==\"]No[\"AAABlgAAAAH0BAAAAAIfAAAAFQ0AAAAAAfAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAAEAJnBM4GNgczCWkJZwxtDHkM9g8YEKYQ0xDYEOUQHREpETAROxE9EZkRwhHWEZwSnhLmEvMSLhMwE3MTtBO2E+sT8hMRFDQUdRQ=\",\"AAGuBwAAAAH0BAAAAAAAAAAAAAAAAAAAAAAEOQkAADoJAAA9CQAAPgkAAA==\"]No[\"AAAAApkAAAAlBQAAAAI/AAAAGA0AAAE9AQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAAEQJpBNIGNwc0CWoJaAxuDHoM9w8ZEKcQ1BDZEOYQHhEqETERPBE+EZoRwxHXEZ0SnxLnEvQSLxMxE3QTtRO3E+wT8xMSFDUUdhQ=\",\"AAHFBwAAAAElBQAAAAAAAAAAAAAAAAAAAAAEOwkAADwJAAA/CQAAQAkAAA==\"]Cc[\"AAAAAQwFAAAAAAAAARQBAAA=\",\"AAAAAQwFAAAAAAEADAAA\"]Ck[\"AAAAAU0FAAAAAAGHAQAA\",\"AAAAAU0FAAAAAAMBDAAAAgwAAAMMAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAF/BAAAAAAAAXcMAAA=\",\"\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAa4PAAA=\"]Eo[\"AAAAAT0FAAAAAVAAAAACZQEAAGYBAAAB6wYAAA==\",\"AAAAAT0FAAAAAAHdBgAAAAAAAAAAAAAAAAACcQUAAK8PAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAArEUAACyFAAA\"]Ck[\"AAAAAAAAAAABYRQAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAByBQAAA==\"]Ag[\"AAACqwIAADEDAAA=\",\"\"]Bo[\"AAAAAAAAAcgAAAAAAAABcgwAAA==\",\"AAAAATgQAAA=\"]Fc[\"AAAAAe8EAAAAAxoAAABrDAAA+RIAAAHLDwAAAAHpAAAA\",\"AAGrBwAAAAHvBAAAAAEzBwAAAAAAAAAAAAAAAAAAATQHAAA=\"]Gc[\"AAAAAR8FAAAAATkAAAABNQEAAAABpBIAAAFsDAAAAAH6EgAA\",\"AAHCBwAAAAEfBQAAAAF2EwAAATkQAAAAAaQSAAAAAAAAAAAAAAABNQcAAA==\"]Do[\"AAAAAAAAAAHMDwAAApIFAAD9DwAA\",\"AAAAAb0BAAAAAAABzA8AAASSBQAA/Q8AAI4RAACPEQAA\"]Do[\"AAAAAAAAAAHNDwAAApMFAAD+DwAA\",\"AAAAAcgBAAAAAAABzQ8AAASTBQAA/g8AAJARAACREQAA\"]Ao[\"AAAAAAGoEAAAAAABzhAAAA==\",\"\"]Fk[\"AAABqhEAAAJpAAAA5wcAAAEgAgAAAAHQAAAAApAEAADOEQAAAsgPAAA7EAAAAAHKDwAAAnoEAAA6EAAAAAF2DAAAAnQMAAB1DAAA\",\"\"]Cc[\"AAAAAAAAAAN7BAAAkgQAANARAAA=\",\"AAAAAAABPRAAAA==\"]Ec[\"AAABTAIAAAHoBAAAAAISAAAAKgcAAALWAAAA1wAAAA==\",\"AAABTgIAAAHoBAAAAAAAAs4RAADPEQAA\"]Bo[\"AAABKxEAAAAAAALLAAAAzAAAAA==\",\"AAAAAAGCBQAA\"]Ck[\"AAABLBEAAAAAAAJ2AQAAdwEAAA==\",\"AAAAAAAAAAAAAAABgwUAAA==\"]Ao[\"AAAAAAAAAbETAAABug8AAA==\",\"\"]Hg[\"AAAAAmsAAAD/BwAAASECAAABcAkAAAPcAAAA8AYAAOMQAAACgAUAAFUQAAAAApgFAADSDAAABsEPAADCDwAAww8AAO0QAABEEQAACxMAAAAAAsUPAADGDwAAAcQPAAA=\",\"\"]Dk[\"AAAAAAABcQkAAALxBgAAAAgAAAKBBQAA5BAAAAABmQUAAAHuEAAA\",\"AAAAAAABQhAAAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAGBEwAA\",\"\"]AAo[\"AAABAhAAAAHCBgAAAtYBAAAjBwAABMEGAABrDAAA+A8AAPkSAAACbxQAAKMUAAADixEAAHAUAACkFAAABZwHAACOEQAAjxEAAJARAACREQAAAaQQAAAAAAABnQcAAA==\",\"AAAABRkHAADREQAA0hEAANMRAADVEQAAA6sBAAC0DwAAtQ8AAAHUEQAABZoUAADBFAAAwhQAAMMUAADEFAAAARAUAAABmxQAAAGjEgAAAAAAAAAAAALRDwAA6w8AADswAAABAAAFAAIAEgICAP8PAgA=\"]Cc[\"AAAAAT4FAAAAAVEAAAACZwEAAGgBAAA=\",\"AAAAAT4FAAA=\"]Dc[\"AAAAAAAAAAA7MAAAAQAABQABAN0SBQA=\",\"AAAABN8BAADjAQAA5AEAAOUBAAA=\"]Ao[\"AAAAAd8BAAAAAAAAAUgQAAA=\",\"\"]Ao[\"AAAAAeQBAAAAAAAAAUkQAAA=\",\"\"]Eo[\"AAAAAawRAAABmhMAAAO7EAAAQREAAJYRAAAB9hMAAAG3EQAAAaoQAAACxxEAAK4SAAABsREAAAAAAAABLBQAAA==\",\"\"]Eo[\"AAAAAa8RAAABnBMAAAO/EAAAQxEAAJgRAAAB+RMAAAG5EQAAAawQAAACyREAALASAAABsxEAAAAAAAABLhQAAA==\",\"\"]Bc[\"AAAAAAAAApMEAAD4BgAAAAFKEAAA\",\"\"]Bc[\"AAAAAAAAApYEAAD7BgAAAAFLEAAA\",\"\"]Ec[\"AAAAAdkBAAAAAv4SAAAAEwAAAvATAADxEwAAAoQEAAD/CwAAAAAAAAABfwQAAA==\",\"AAAAAAFHAwAA\"]Gg[\"AAAAAeoEAAAAAhQAAAAsBwAAAt0AAADeAAAA\",\"AAADVQIAAFcCAABYAgAAAeoEAAAAAAABVRAAAAACmAUAANIMAAAC7RAAAAsTAAAAAAABxA8AAA==\"]Eg[\"AAAAASsFAAAAAkQAAACnAAAAA0UBAABGAQAAMBAAAAFiAwAA\",\"AAAAASsFAAAAAAAAAAGZBQAAAe4QAAA=\"]Ec[\"AAAAAAAAAXUBAAAAAAAAAAAAAAAAAALaBAAAdQkAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAc4FAAA=\"]Ec[\"AAABRAwAAAHdBAAAAAELAAAAAbsAAAA=\",\"AAAAAd0EAAAAAUcJAAAAAAAAAAAAAAAAAAABvwYAAA==\"]Dg[\"AAAAAAF9BQAAAAAAAAAAAAAAAAAAAALoEAAAjREAAA==\",\"AAGmBwAAAAAAAcEGAAA=\"]Ac[\"AAABeQIAAA==\",\"\"]Do[\"AAAAAQQFAAAAAScAAAAAAAIFAQAABgEAAA==\",\"AAAChwIAAIgCAAABBAUAAAAAAAAAAd4TAAA=\"]Dk[\"AAAAATsFAAAAAU0AAAACXwEAAGABAAA=\",\"AAAC+gIAAPsCAAABOwUAAAAAAAAAAd8TAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAkwJAABOCQAA\"]Dk[\"AAAAAAAAAAABIwEAAA==\",\"AAABpAIAAAAAAAAAAAABgAQAAAFCBwAAAWAEAAABnwcAAA==\"]Dg[\"AAAAAAAAAZgBAAA=\",\"AAABKwMAAAAAAAAAAAABgQQAAAFDBwAAAWIEAAABogcAAA==\"]Dk[\"AAAAARMFAAAAAcUBAAABzQQAAAGgEQAAAR8BAAA=\",\"AAG7BwAAAAETBQAAAAAAAaARAAA=\"]Dk[\"AAAAAV0FAAAAAdcBAAACoQEAANEEAAABpxEAAA==\",\"AAHUBwAAAAFdBQAAAAAAAacRAAA=\"]Ck[\"AAAAASwFAAAAAUUAAAACRwEAAEgBAAA=\",\"AAAAASwFAAAAAAHxBgAA\"]Eg[\"AAAAAf8EAAAAAiYAAACdAAAAASYQAAABWAMAAAIAAQAA8RIAAA==\",\"AAG2BwAAAYECAAAC/wQAAFQKAAA=\"]Eg[\"AAAAATYFAAAAAkwAAACoAAAAAloBAAAxEAAAAWMDAAAB8hIAAA==\",\"AAHOBwAAAfQCAAABNgUAAAG3CgAA\"]Ao[\"AAAAAAAAAAAC1hAAAI4RAAA=\",\"\"]Ao[\"AAAAAAAAAAAC1xAAAJARAAA=\",\"\"]Do[\"AAABegAAAAHcBAAAAAABugAAAA==\",\"AAAAAdwEAAAAAUYJAAAAAAAAAAAAAAAAAAAB2hAAAA==\"]Bg[\"AAAAAAAABNsAAACHBQAAZgwAAKwSAAA=\",\"\"]Ak[\"AAAAAAABRgAAAAFJAQAA\",\"\"]Do[\"AAAAAAAAAAAAAAAAAAAAAAAAAigRAACpEgAA\",\"AAGkBwAAAAAAAAAAAAAAAAAAAAAAAAHnEAAA\"]Cg[\"AAAAAAPyBgAAbgkAADIRAAA=\",\"AAAAAAAAAAK6DwAAzhAAAA==\"]Ag[\"AAACpAIAACsDAAA=\",\"\"]Ac[\"\",\"AAAAAeMSAAA=\"]Cc[\"AAAAAXgKAAACeQoAAOkKAAAB6woAAALpEAAA6xAAAA==\",\"\"]Gg[\"AAAAAQMFAAABdxQAAAAAAfcIAAAEBAEAAEoQAAAEEwAAXBQAAAGkEAAA\",\"AAAAA8EBAAADBQAAhBQAAAABOBQAAAAB9wgAAANKEAAABBMAAFwUAAA=\"]Bc[\"AAAAAcEBAAAAAAAAAAAAAU4RAAA=\",\"\"]Gg[\"AAAAAToFAAAAAAFeAQAAAfgIAAADSxAAAAYTAABdFAAAAAAAAAGdBwAA\",\"AAAAA88BAAA6BQAAhRQAAAABORQAAAAB+AgAAANLEAAABhMAAF0UAAA=\"]Bc[\"AAAAAc8BAAAAAAAAAAAAAVIRAAA=\",\"\"]Fg[\"AAABWAIAAAH4BAAAAAEiAAAAAAAC9AAAAPUAAAA=\",\"AAGyBwAAAAH4BAAAAAFwCQAAAvAGAADjEAAAA5AEAACRBAAAgAUAAA==\"]Eo[\"AAAAAS4FAAAAAUgAAAACSwEAAEwBAAA=\",\"AAHKBwAAAAEuBQAAAAFxCQAAAQAIAAAEkgQAAIEFAADkEAAA0BEAAA==\"]Ao[\"\",\"AAAAAAAAAAAAAAABVhEAAA==\"]Ek[\"AAAAAQgFAAAAASsAAAAAAAINAQAADgEAAA==\",\"AAABjgIAAAEIBQAAAAAAAAGcBwAAAaQQAAAAAk4RAABQEQAA\"]Eg[\"AAAAAUQFAAAAAVYAAAACcwEAAHQBAAA=\",\"AAABCAMAAAFEBQAAAAAAAAAAAAJSEQAAVBEAAAABnQcAAA==\"]Ao[\"AAAAAAAAAAHBEAAAAAGCDAAA\",\"\"]Jk[\"AAAAAQkFAAAABSwAAACeAAAAbQUAALkQAAC7EAAAAgAMAAAnEAAABFkDAABSDAAAuhAAALwQAAAEDwEAABABAACOEQAAjxEAAAJ+DAAAfwwAAAKwEQAAsREAAA==\",\"AAAAAgkFAADREAAAAsIBAACyEAAAAAABQQkAAA==\"]Og[\"AAAAAUkFAAAABVkAAACrAAAAbgUAAL0QAAC/EAAABoABAACBAQAAAQwAAAIMAAADDAAANBAAAARmAwAAUwwAAL4QAADAEAAAApARAACREQAAAoAMAACBDAAAArIRAACzEQAA\",\"AAAABEkFAADbBwAA3AcAANIQAAAE0QEAALMQAAC0EAAAtRAAAAAAAUIJAAACeAUAAHkFAAAAAAAAAAAAAAA7MAAAAQAACgACAN0HBQD6BwQA\"]Cc[\"AAAAAT8FAAAAAVIAAAACaQEAAGoBAAA=\",\"AAAAAT8FAAA=\"]Ck[\"AAABdAUAAAEKBQAAAAEtAAAAAAABEQEAAA==\",\"AAAAAgoFAABUDAAA\"]Dg[\"AAABdQUAAAFKBQAAAAFaAAAAAYIBAAAAAAAAAAAAAfMGAAA=\",\"AAAAAkoFAABVDAAA\"]Cc[\"AAAAAWMFAAAAAWYAAAABqgEAAA==\",\"AAAAAmMFAABWDAAA\"]Dg[\"AAAAAAAAAAAAAAABRREAAA==\",\"AAAABrYQAADwEgAA3BMAAN0TAAANFAAADhQAAA==\"]Ak[\"AAAAAAAAAAAB3xIAAA==\",\"\"]Ak[\"AAAAAAAAAAAB4hIAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnAAAAASAgAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnUAAAATAgAA\",\"\"]Bg[\"AAAAAAAAAAAAAXMEAAA=\",\"AAAAAUgRAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAm8AAAA0BwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAnQAAAA1BwAA\",\"\"]Bo[\"AAAAAAAAAAAAAAAEAQcAAAIHAAADBwAABAcAAA==\",\"\"]Ec[\"AAAABKwBAAC3AQAAHgUAAKUQAAAAAAE0AQAAAAAAAAQFBwAABgcAAAcHAAAIBwAA\",\"AAAAAR4FAAA=\"]Bg[\"AAAAAAAAAAAAAXQEAAA=\",\"AAAAAAF3EwAA\"]Ag[\"AAAAAAABJQcAAA==\",\"\"]Cc[\"AAAAAX0KAAACfAoAAO8KAAAB7QoAAALqEAAA7BAAAA==\",\"\"]No[\"AAAAAQEFAAABIwcAAAEzEwAAAfUPAAAGYgwAAMgQAADZEwAA7RMAAFQUAAB8FAAABwIBAAC8AQAAywwAAEgQAAADEwAA5BMAAOYTAAABXhQAAAAAAAAAAAAAA88GAADPDAAABxMAAA==\",\"AAAAAgEFAABREAAAAAHAAQAAAQkTAAAGYgwAAMgQAADZEwAA7RMAAFQUAAB8FAAABcsMAABIEAAAAxMAAOQTAADmEwAA\"]Bo[\"AAAAAVEQAAAAAcABAAAAAroQAABPEQAAAAF+DAAA\",\"\"]Nc[\"AAAAATgFAAAAAAFcAQAAOjAAAAEAAAAAAAcAEAAAAMkBYwzJEDQT2hPuE1UUfRQFzAwAAEkQAAAFEwAA5RMAAOcTAAAAAAAAAAAAAAAEzgUAANMGAADQDAAACBMAAA==\",\"AAAAAjgFAABSEAAAAAHOAQAAAQoTAAAGYwwAAMkQAADaEwAA7hMAAFUUAAB9FAAABcwMAABJEAAABRMAAOUTAADnEwAA\"]Bo[\"AAAAAVIQAAAAAc4BAAAAAr4QAABTEQAAAAGADAAA\",\"\"]Ao[\"AAAAAAAAAAAC5BMAAOUTAAA=\",\"\"]Ao[\"AAAAAAAAAAAC5hMAAOcTAAA=\",\"\"]Dc[\"AAABVQIAAAHrBAAAAAIVAAAALQcAAALfAAAA4AAAAA==\",\"AAABWgIAAAHrBAAA\"]Bk[\"AAAAAeIBAAAAAATaAAAAhgUAAGUMAACrEgAA\",\"\"]Ec[\"AAAAApQTAACVEwAAApITAACTEwAABEAMAABBDAAAQgwAAEMMAAAEPAwAAD0MAAA+DAAAPwwAAA==\",\"\"]Cc[\"AAAAAAAAAAAB3hIAAA==\",\"AAGnBwAAAAK7AQAAcRMAAA==\"]Cc[\"AAAAAAAAAAAB4RIAAA==\",\"AAG+BwAAAALHAQAAchMAAA==\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAB8wYAAA==\"]Cg[\"AAAAAbMPAAAAAAF/AQAAAbgQAAA=\",\"AAHaBwAAAAAAAeMTAAA=\"]Ek[\"AAAAAeIEAAAAAAHFAAAAAAAAAAAAAAAAAAAEbRMAAHUTAACREwAArBMAAA==\",\"AAGoBwAAAALiBAAAjgUAAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3IJAABGEAAAsRQAAA==\",\"\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3MJAABHEAAAshQAAA==\",\"\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAk0JAABPCQAA\"]Ac[\"\",\"AAAAAAHHBAAA\"]Bc[\"AAAAAAABXwQAAA==\",\"AAAAAAHIBAAA\"]Ec[\"AAAAARUFAAAAAcYBAAABzgQAAAKiEQAACxQAAAEhAQAA\",\"AAG8BwAAAAEVBQAAAAAAAqIRAAALFAAA\"]Ec[\"AAAAAV8FAAAAAdgBAAACowEAANIEAAACqREAAAwUAAA=\",\"AAHVBwAAAAFfBQAAAAAAAqkRAAAMFAAA\"]Ag[\"\",\"AAAAAAABoBIAAA==\"]Co[\"AAAAArEBAADbBwAAAAABeAEAAA==\",\"AAAAAAAAAAAAAAAAAAAAAdABAAA=\"]Ac[\"\",\"AAAAAAE2EwAA\"]Cg[\"AAAAAAAAAgkTAAAKEwAAAAABoxIAAA==\",\"AAAAAAAAAAHoEwAA\"]Do[\"AAAAASkFAAAAAkIAAACmAAAAA0IBAABDAQAALxAAAAFhAwAA\",\"AAAAASkFAAAAAAABewQAAA==\"]Ak[\"AAAAAAACOBQAADkUAAA=\",\"\"]Ac[\"AAAAAeMBAAA=\",\"\"]Ac[\"AAAAAeUBAAA=\",\"\"]Eo[\"AAACEAMAACYDAAABUwUAAAABYQAAAAKSAQAAkwEAAA==\",\"AAAAAVMFAAAAAAAF1QYAANYGAADXBgAA2AYAANkGAAA=\"]Fk[\"AAAABMoQAADLEAAA3BMAAN0TAAABtA8AAAElEQAAAaESAAAAAAFeFAAAAAAAAAAAAAF3DAAA\",\"AAAAAAAAA6oSAACrEgAArBIAAA==\"]Fc[\"AAAAAAABwQYAAAIJEwAAChMAAAGLEQAAAAGjEgAAAAACNhQAADcUAAAAAAABgRMAAA==\",\"AAAAAAAAAXMUAAAB6BMAAA==\"]Co[\"AAAAAfsEAAAAASUAAAAAAAL6AAAA+wAAAA==\",\"AAAAAfsEAAAAAWoFAAA=\"]Co[\"AAAAATEFAAAAAUsAAAACUQEAAFIBAAA=\",\"AAAAATEFAAAAAAAAAAGXDgAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAARMHAAA=\",\"\"]Ik[\"AAAAAgAFAABaFAAAAAAAApcSAABvEwAABQEBAAC8AQAAfAwAACMRAAB+EwAAA3YJAADeEwAAXhQAAA==\",\"AAG3BwAAAAK/AQAAAAUAAAAAAAKXEgAAbxMAAAN8DAAAIxEAAH4TAAACdgkAAN4TAAA=\"]Ig[\"AAAAAjcFAABbFAAAAAABWwEAAAPJAQAAmBIAAHATAAADfQwAACQRAAB/EwAAAncJAADfEwAA\",\"AAHPBwAAAALNAQAANwUAAAHJBgAAAAACmBIAAHATAAADfQwAACQRAAB/EwAAAncJAADfEwAA\"]Ao[\"AAAAAAAAAc0AAAAAAAF2BAAA\",\"\"]Bc[\"AAAAAAABTwAAAAJjAQAAZAEAAA==\",\"\"]Ag[\"AAACqQIAADgDAAA=\",\"\"]Ak[\"AAAAAAAAApQEAAD5BgAA\",\"\"]Ak[\"AAAAAAAAApcEAAD8BgAA\",\"\"]Ag[\"AAACswIAADkDAAA=\",\"\"]Dk[\"AAAAAekEAAAAAhMAAAArBwAAAtgAAADZAAAA\",\"AAABUAIAAAHpBAAAAAAAAAAAAcoPAAA=\"]Dg[\"AAAAAeYEAAAAAhAAAAAoBwAAAtIAAADTAAAA\",\"AAABSQIAAAHmBAAAAAAAAAE7EAAA\"]Co[\"AAABpxIAAAEtBQAAAAFHAAAAAUoBAAA=\",\"AAHJBwAAATgJAAABLQUAAA==\"]Ec[\"AAAAAAABqBIAAAG8AAAAAAAAAAAAAAAAAAADiwQAADUJAADODwAA\",\"AAAAAbkBAAAAAAAAAdgTAAA=\"]Hk[\"AAAC6gIAAAIDAAABSwUAAAABWwAAAAKDAQAAhAEAAAAAAAAAAAAAAAAABBgCAABxBQAA1AYAABIHAAA=\",\"AAABFgMAAALSAQAASwUAAAAAAvgTAAD5EwAAAAACyBEAAMkRAAA=\"]Fc[\"AAAAA7YQAADMEAAA8BIAAAAC/hIAAAATAAADpwEAAPATAADxEwAAAoQEAAD/CwAAAAAAAAABfwQAAA==\",\"AAAAAdkBAAA=\"]Dc[\"AAAAAmgAAADlBAAAAh8CAAD2CAAAAQ8AAAABzwAAAA==\",\"AAAAAuUEAABQEAAA\"]Eg[\"AAAAAQYFAAAAASkAAAAAAAIJAQAACgEAAAAAAAAAAAAAAAMNBwAApw8AAK4PAAA=\",\"AAABigIAAAEGBQAA\"]Eg[\"AAAAAUAFAAAAAVMAAAACawEAAGwBAAAAAAAAAAAAAAAAAAMQBwAAqQ8AAK8PAAA=\",\"AAABAgMAAAFABQAA\"]Hk[\"AAAFOwIAAEsCAABOAgAAVwIAAFoCAAAB+QQAAAACIwAAAC4HAAAAAAL2AAAA9wAAAA==\",\"AAADdgIAAHcCAAB5AgAAAvkEAADFBgAAAswFAACjEAAAAZ0TAAAB9Q8AAAGTEQAA\"]Ek[\"AAAAAS8FAAAAAkkAAAAvBwAAAk0BAABOAQAA\",\"AAAB6gIAAAEvBQAAAAAAAAAAAAAAAAAAAAAC2gQAABMHAAA=\"]Bk[\"AAAAAAABtxAAAAF+AQAA\",\"AAAAAAAAAAG4EAAA\"]Fo[\"AAABlwAAAAH2BAAAAAEWDQAAAAAB8gAAAAAAAAAAAAAAAAY6BwAAPgcAADoJAAA+CQAAtw8AAMUQAAA=\",\"AAGwBwAAAAL2BAAAjQUAAA==\"]Fo[\"AAAAApoAAAAnBQAAAAEZDQAAAT8BAAAAAAAAAAAAAAAAAAY8BwAAQAcAADwJAABACQAAuQ8AAMcQAAA=\",\"AAHHBwAAAAEnBQAAAZAFAAA=\"]Ag[\"AAACrAIAADIDAAA=\",\"\"]Cg[\"AAAAAWUFAAAAAAADug8AACEQAADOEAAA\",\"AAHZBwAAAAFlBQAA\"]Dc[\"AAAAAkUFAADcBwAAAAABeQEAAA==\",\"AAAAAUUFAAAAAAAAAAAAAAAAAAHeBgAA\"]Dg[\"AAAAAYITAAABUxAAAAAAAAL8AAAAjxEAAA==\",\"AAFDCQAAAb4BAAABghMAAAFTEAAA\"]Dg[\"AAAAAYMTAAABVBAAAAABVgEAAAABkREAAA==\",\"AAFECQAAAcwBAAABgxMAAAFUEAAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAawPAAA=\",\"\"]Ac[\"\",\"AAAAAAFiFAAA\"]Ag[\"AAACsQIAADQDAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAD3RIAAN4SAADfEgAA\"]Bc[\"\",\"AAAAAAAAAAAD4BIAAOESAADiEgAA\"]Ak[\"\",\"AAAAAQITAAAAAAEpFAAA\"]ADg[\"AAAAAfwEAAAAAAA6MAAAAQAAAAAAFAAQAAAA8QcaDbsPBBAHEEMQShHLEd8R+xJpExMUcRR+FIwUjhS0FLgUuxS/FMYUOjAAAAEAAAAAAA0AEAAAAP0A1hBGEfESAxMEE6ATzhPhE5gUqxStFK8UvRQAAAHEEQAA\",\"AAGzBwAAAAH8BAAAAAAAOjAAAAEAAAAAABQAEAAAAPEHGg27DwQQBxBDEEoRyxHfEfsSaRMTFHEUfhSMFI4UtBS4FLsUvxTGFDowAAABAAAAAAAKABAAAADWEEYR8RKgE84T4ROYFKsUrRSvFL0UAAABxBEAAA==\"]ADk[\"AAAAATMFAAAAAAFXAQAAOjAAAAEAAAAAABQAEAAAAPIHGw28DwUQCBBEEEsRzBHgEfwSahMUFHIUfxSNFI8UtRS5FLwUwBTHFDowAAABAAAAAAAMABAAAADXEEcR8hIFEwYToRPPE+ITmRSsFK4UsBS+FAAAAcURAAA=\",\"AAHLBwAAAAEzBQAAAAAAOjAAAAEAAAAAABQAEAAAAPIHGw28DwUQCBBEEEsRzBHgEfwSahMUFHIUfxSNFI8UtRS5FLwUwBTHFDowAAABAAAAAAAKABAAAADXEEcR8hKhE88T4hOZFKwUrhSwFL4UAAABxREAAA==\"]Ag[\"AAAChwIAAPoCAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAWsEAAA=\",\"AAAAAAAAAVkMAAA=\"]Bk[\"AAAAAAAAAAAAAAFxDAAA\",\"AAAAAAABMxQAAA==\"]Do[\"AAAAAQcFAAAAASoAAAAAAAILAQAADAEAAAAAAAAAAAAAAAIOBwAAqA8AAA==\",\"AAAAAQcFAAA=\"]Do[\"AAAAAUEFAAAAAVQAAAACbQEAAG4BAAAAAAAAAAAAAAAAAAIRBwAAqg8AAA==\",\"AAAAAUEFAAA=\"]Ag[\"AAACsAIAADoDAAA=\",\"\"]Fc[\"AAAAAUMFAAAAAlUAAACpAAAAAnEBAAAyEAAAAmQDAAC4EAAA\",\"AAAAAUMFAAAAAAAAAAAAAAABnQcAAAAAAAABzgUAAA==\"]Ao[\"AAAAAAHHBAAA\",\"AAAAAAGeBwAA\"]Ao[\"AAAAAAHIBAAA\",\"AAAAAAGhBwAA\"]Ag[\"AAACrQIAADcDAAA=\",\"\"]Ag[\"AAACrwIAADADAAA=\",\"\"]Dg[\"AAAAARcFAAAAAAABeBMAAAAAAAFQEQAA\",\"AAAAAhcFAAB4CgAAAXkKAAAAAekQAAA=\"]Do[\"AAAB2gEAAAFXBQAAAAAAAXoTAAAAAAABVBEAAA==\",\"AAAAAVcFAAAB6QoAAAHrCgAAAesQAAA=\"]Do[\"AAAAARkFAAAAAAADvBAAAFERAAB5EwAAAAF/DAAA\",\"AAAAAhkFAAB9CgAAAXwKAAAAAeoQAAA=\"]Eg[\"AAAB2wEAAAFZBQAAAAAAA8AQAABVEQAAexMAAAABgQwAAA==\",\"AAAAAVkFAAAB7woAAAHtCgAAAewQAAA=\"]Cc[\"AAAAAAAAApUEAAD6BgAAAAEVAQAA\",\"AAG5BwAAAAHDAQAA\"]Cc[\"AAAAAAAAA4kBAACYBAAA/QYAAA==\",\"AAHSBwAAAAHUAQAA\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAwwHAADiBwAA/gcAAA==\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAasPAAA=\",\"\"]Ao[\"AAAAAAAAAcsEAAAAAasUAAA=\",\"\"]Bk[\"AAAAAAAAAc8EAAAAAawUAAA=\",\"AAAAAdMEAAA=\"]Eg[\"AAAAAAAAAAAAAAAAAAAAAAAABHgJAAAiEAAA3hAAACsTAAA=\",\"AAG9BwAAAATpBwAA6gcAAOsHAADsBwAA\"]Eg[\"AAAAAAAAAAAAAAAAAAAAAAAABHkJAAAjEAAA3xAAACwTAAA=\",\"AAHWBwAAAATtBwAA7gcAAO8HAADwBwAA\"]Bo[\"AAAAAAABwAEAAAAAAcsMAAAAAYAEAAAAAWAEAAA=\",\"\"]Bo[\"AAAAAAABzgEAAAAAAcwMAAAAAYEEAAAAAWIEAAA=\",\"\"]Ak[\"AAAAAAABnhMAAAEHFAAA\",\"\"]Ao[\"AAAAAAABnxMAAAAAAQgUAAA=\",\"\"]Fo[\"AAAAAUgFAAAAAlgAAACqAAAAA3wBAAB9AQAAMxAAAAFlAwAA\",\"AAABEAMAAAFIBQAAAAAAAAJ4BQAAeQUAAAAAAAAAAALQAQAA3gYAAA==\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAQ8HAAA=\"]Dg[\"AAAAASEFAAAAATsAAAABNwEAAA==\",\"AAAAASEFAAAAAAAAAAAAAAAAAAAAAAEUBwAA\"]Dg[\"AAAAAeAEAAAAAgwAAAAnBwAAAsIAAADDAAAA\",\"AAABOwIAAAHgBAAAAAABSREAAA==\"]Do[\"AAAAARwFAAAAAjcAAACjAAAAAzABAAAxAQAALBAAAAFeAwAA\",\"AAAAARwFAAAAAAAAAYMEAAA=\"]Ek[\"AAAAAf0EAAAAAAAC6RMAAEAUAAAD/gAAAC0RAADOEwAA\",\"AAG0BwAAAAH9BAAAAAAAAukTAABAFAAAAS0RAAA=\"]Ek[\"AAAAATQFAAAAAAFYAQAAAuoTAABBFAAAAi4RAADPEwAA\",\"AAHMBwAAAAE0BQAAAAAAAuoTAABBFAAAAS4RAAA=\"]Bo[\"AAAAAAAAAAABeAUAAAAAAAAAAALQAQAA3gYAAA==\",\"\"]Fg[\"AAAAAf4EAAAAAAAEVwkAAE0QAAC0EQAAlxMAAAL/AAAA4RMAAA==\",\"AAG1BwAAAAH+BAAAAAAABFcJAABNEAAAtBEAAJcTAAA=\"]Fg[\"AAAAATUFAAAAAAFZAQAABFgJAABOEAAAtREAAJgTAAAB4hMAAA==\",\"AAHNBwAAAAE1BQAAAAAABFgJAABOEAAAtREAAJgTAAA=\"]Ag[\"\",\"AAAAAAAAAXMUAAA=\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAAAAGBEwAA\"]Co[\"AAAAAfEEAAAAARwAAAAAAALrAAAA7AAAAA==\",\"AAAAAfEEAAAAAAHLDwAA\"]Co[\"AAAAASIFAAAAATwAAAACOAEAADkBAAA=\",\"AAAAASIFAAAAAAAAAaQSAAA=\"]Fg[\"AAABZQIAAAELBQAAAAEuAAAAAAHmBgAAAhIBAAATAQAA\",\"AAACkQIAAM0GAAABCwUAAAAAAAHYBgAAAAAAAAAAAAAAAAGnDwAA\"]Gc[\"AAAB0AIAAALSAQAATAUAAAABXAAAAAKFAQAAhgEAAAHtBgAA\",\"AAACGAMAANEGAAABTAUAAAAAAd8GAAAAAAAAAAAAAAAAAAIYAgAAqQ8AAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA94HAAD7BwAA+ggAAA==\",\"\"]Cg[\"AAABjgIAAAAAAAAAASQBAAA=\",\"AAAAAAAAAAK6EAAAvBAAAA==\"]Cg[\"AAABCAMAAAAAAAGZAQAA\",\"AAAAAAAAAAO+EAAAwBAAAMEQAAA=\"]Bo[\"AAAAAtMEAABkBQAAATYTAAA=\",\"AAAAAmQFAADiEQAA\"]Bo[\"AAAAAAAAAckAAAAAAAABcwwAAA==\",\"AAAAAQ8UAAA=\"]Io[\"AAAAAVQFAAAAAWIAAAABlAEAAAaaBQAATxEAAFERAABTEQAAVREAAFcRAAAAAAAFThEAAFARAABSEQAAVBEAAFYRAAAAAAAAAAABxRQAAA==\",\"AAAAAVQFAAAAAAT1EwAA9hMAAPgTAAD5EwAAAAF8BAAA\"]Co[\"AAAAAmoAAADoBwAAAAAB0QAAAAKRBAAAzxEAAAHJDwAA\",\"AAABqhEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAkwJAACuEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk4JAACwEAAA\",\"\"]Co[\"AAAAARgFAAAAAAAAAicBAAAoAQAA\",\"AAAAARgFAAAAAALpEAAA6hAAAA==\"]Dc[\"AAAAAVgFAAAAAAKcAQAAnQEAAA==\",\"AAAAAlgFAADjEgAAAAAC6xAAAOwQAAA=\"]Cc[\"AAAAAAGrAQAAAAG+AAAAAAAAAXAMAAA=\",\"AAAAATIUAAA=\"]Ac[\"\",\"AAABRAwAAA==\"]Ec[\"AAABiAIAAAHtBAAAAAEXAAAAAAAC5AAAAOUAAAA=\",\"AAAAAe0EAAAESgkAAD0KAAA+CgAAPwoAAA==\"]Do[\"AAAB+wIAAAEbBQAAAAE1AAAAAi0BAAAuAQAA\",\"AAAAARsFAAAESwkAAJMKAACVCgAAlgoAAA==\"]Ak[\"\",\"AAAAAAACOBQAADkUAAA=\"]Ck[\"AAAAAt8EAABhCQAAAfUIAAABbhMAAAHBAAAA\",\"AAAAAt8EAABPEAAA\"]Bg[\"AAAAAX0HAAACnxAAALIQAAAAAQAMAAA=\",\"\"]Bk[\"AAAAAX4HAAACoBAAALMQAAAAAgEMAAACDAAA\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAjYUAAA3FAAA\",\"\"]Fo[\"AAAAAQIFAAAAAAADhQQAAGIJAABUFAAAAgMBAAC1AQAA\",\"AAG4BwAAAAECBQAAAAAAAoUEAABiCQAAAbUBAAAAAAAAAAAAAAABBxMAAA==\"]Fo[\"AAAAATkFAAAAAAFdAQAAA4YEAABjCQAAVRQAAAG2AQAA\",\"AAHQBwAAAAE5BQAAAAAAAoYEAABjCQAAAbYBAAAAAAAAAAAAAAABCBMAAA==\"]Ck[\"AAAAATIFAAAAAAJTAQAAVAEAAA==\",\"AAAAATIFAAAAAAAAAWEUAAA=\"]Ec[\"AAAAAUYFAAAAAAF6AQAAAAAAAAAAAAAAAAAFsgEAAN0HAAD6BwAA+QgAAM0MAAA=\",\"AAAAAUYFAAA=\"]Dg[\"AAAAAAFiFAAAAAG9AAAAAAAAAAACNhQAADcUAAAAAAABgRMAAA==\",\"AAABugEAAA==\"]Ag[\"AAACtAIAADYDAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAjYUAAA3FAAA\"]Cc[\"AAAAAWYFAAAAAAAAAAAAAVYRAAA=\",\"AAAB2gEAAAFmBQAA\"]Ck[\"AAAAAWcFAAAAAAACwRAAAFcRAAAAAYIMAAA=\",\"AAAB2wEAAAFnBQAA\"]Ag[\"AAACsgIAADUDAAA=\",\"\"]Dg[\"AAAAAAABMgAAAAAAASIBAAA=\",\"AAAAAAAAAAAAAAAAAAAAAyoUAAArFAAALBQAAA==\"]Ck[\"AAAAAAABZAAAAAGXAQAA\",\"AAAAAAAAAAAAAAAAAAAAAi0UAAAuFAAA\"]Ag[\"AAACrgIAAC8DAAA=\",\"\"]Do[\"AAAAAX8HAAACoRAAALQQAAAAAQMMAAAB4RAAAA==\",\"AALLAQAAvwcAAAFFCQAAAAAAAAHhEAAA\"]Ec[\"AAAAAk4FAACABwAAAqIQAAC1EAAAAAGIAQAAAeIQAAA=\",\"AAHRBwAAAdMBAAABTgUAAAAAAAHiEAAA\"]Bg[\"AAAAAAAAAAABeQUAAA==\",\"AAABygEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk0JAACvEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAk8JAACxEAAA\",\"\"]") \ No newline at end of file diff --git a/pr/619/docs/src/noq/connection.rs.html b/pr/619/docs/src/noq/connection.rs.html index 32d45bc7d..c579ebbb8 100644 --- a/pr/619/docs/src/noq/connection.rs.html +++ b/pr/619/docs/src/noq/connection.rs.html @@ -186,13 +186,13 @@ 186 /// 187 /// Will panic if called after `poll` has returned `Ready`. 188 pub fn local_ip(&self) -> Option<IpAddr> { -189 let conn = self.conn.as_ref().unwrap(); +189 let conn = self.conn.as_ref().expect("used after yielding Ready"); 190 let inner = conn.lock_without_waking("local_ip"); 191 192 inner 193 .inner 194 .network_path(PathId::ZERO) -195 .expect("path exists when connecting") +195 .expect("PathId::ZERO is the only path during the handshake") 196 .local_ip() 197 } 198 @@ -201,1689 +201,1643 @@ 201 /// Will panic if called after `poll` has returned `Ready`. 202 pub fn remote_address(&self) -> SocketAddr { 203 let conn_ref: &ConnectionRef = self.conn.as_ref().expect("used after yielding Ready"); -204 // TODO: another unwrap -205 conn_ref -206 .lock_without_waking("remote_address") -207 .inner -208 .network_path(PathId::ZERO) -209 .expect("path exists when connecting") -210 .remote() -211 } -212} -213 -214impl Future for Connecting { -215 type Output = Result<Connection, ConnectionError>; -216 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { -217 Pin::new(&mut self.connected).poll(cx).map(|_| { -218 let conn = self.conn.take().unwrap(); -219 let inner = conn.lock_without_waking("connecting"); -220 if inner.connected { -221 drop(inner); -222 Ok(Connection(conn)) -223 } else { -224 Err(inner -225 .error -226 .clone() -227 .expect("connected signaled without connection success or error")) -228 } -229 }) -230 } -231} -232 -233/// Future that completes when a connection is fully established -234/// -235/// For clients, the resulting value indicates if 0-RTT was accepted. For servers, the resulting -236/// value is meaningless. -237pub struct ZeroRttAccepted(oneshot::Receiver<bool>); -238 -239impl Future for ZeroRttAccepted { -240 type Output = bool; -241 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { -242 Pin::new(&mut self.0).poll(cx).map(|x| x.unwrap_or(false)) -243 } -244} -245 -246/// A future that drives protocol logic for a connection -247/// -248/// This future handles the protocol logic for a single connection, routing events from the -249/// `Connection` API object to the `Endpoint` task and the related stream-related interfaces. -250/// It also keeps track of outstanding timeouts for the `Connection`. -251/// -252/// If the connection encounters an error condition, this future will yield an error. It will -253/// terminate (yielding `Ok(())`) if the connection was closed without error. Unlike other -254/// connection-related futures, this waits for the draining period to complete to ensure that -255/// packets still in flight from the peer are handled gracefully. -256#[must_use = "connection drivers must be spawned for their connections to function"] -257#[derive(Debug)] -258struct ConnectionDriver(ConnectionRef); -259 -260impl Future for ConnectionDriver { -261 type Output = Result<(), io::Error>; -262 -263 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { -264 let conn = &mut *self.0.lock_without_waking("poll"); -265 -266 let span = debug_span!("drive", id = conn.handle.0); -267 let _guard = span.enter(); -268 -269 if let Err(e) = conn.process_conn_events(&self.0.shared, cx) { -270 conn.terminate(e, &self.0.shared); -271 return Poll::Ready(Ok(())); -272 } -273 let mut keep_going = conn.drive_transmit(cx)?; -274 // If a timer expires, there might be more to transmit. When we transmit something, we -275 // might need to reset a timer. Hence, we must loop until neither happens. -276 keep_going |= conn.drive_timer(cx); -277 conn.forward_endpoint_events(); -278 conn.forward_app_events(&self.0.shared); -279 -280 if !conn.inner.is_drained() { -281 if keep_going { -282 // If the connection hasn't processed all tasks, schedule it again -283 cx.waker().wake_by_ref(); -284 } else { -285 conn.driver = Some(cx.waker().clone()); -286 } -287 return Poll::Pending; -288 } -289 if conn.error.is_none() { -290 unreachable!("drained connections always have an error"); -291 } -292 Poll::Ready(Ok(())) -293 } -294} -295 -296/// A QUIC connection. -297/// -298/// If all references to a connection (including every clone of the `Connection` handle, streams of -299/// incoming streams, and the various stream types) have been dropped, then the connection will be -300/// automatically closed with an `error_code` of 0 and an empty `reason`. You can also close the -301/// connection explicitly by calling [`Connection::close()`]. -302/// -303/// Closing the connection immediately abandons efforts to deliver data to the peer. Upon -304/// receiving CONNECTION_CLOSE the peer *may* drop any stream data not yet delivered to the -305/// application. [`Connection::close()`] describes in more detail how to gracefully close a -306/// connection without losing application data. -307/// -308/// May be cloned to obtain another handle to the same connection. -309/// -310/// [`Connection::close()`]: Connection::close -311#[derive(Debug, Clone)] -312pub struct Connection(ConnectionRef); -313 -314impl Connection { -315 /// Returns a weak reference to the inner connection struct. -316 pub fn weak_handle(&self) -> WeakConnectionHandle { -317 self.0.weak_handle() -318 } -319 -320 /// Initiate a new outgoing unidirectional stream. -321 /// -322 /// Streams are cheap and instantaneous to open unless blocked by flow control. As a -323 /// consequence, the peer won't be notified that a stream has been opened until the stream is -324 /// actually used. -325 pub fn open_uni(&self) -> OpenUni<'_> { -326 OpenUni { -327 conn: &self.0, -328 notify: self.0.shared.stream_budget_available[Dir::Uni as usize].notified(), -329 } -330 } -331 -332 /// Initiate a new outgoing bidirectional stream. -333 /// -334 /// Streams are cheap and instantaneous to open unless blocked by flow control. As a -335 /// consequence, the peer won't be notified that a stream has been opened until the stream is -336 /// actually used. Calling [`open_bi()`] then waiting on the [`RecvStream`] without writing -337 /// anything to [`SendStream`] will never succeed. -338 /// -339 /// [`open_bi()`]: crate::Connection::open_bi -340 /// [`SendStream`]: crate::SendStream -341 /// [`RecvStream`]: crate::RecvStream -342 pub fn open_bi(&self) -> OpenBi<'_> { -343 OpenBi { -344 conn: &self.0, -345 notify: self.0.shared.stream_budget_available[Dir::Bi as usize].notified(), -346 } -347 } -348 -349 /// Accept the next incoming uni-directional stream -350 pub fn accept_uni(&self) -> AcceptUni<'_> { -351 AcceptUni { -352 conn: &self.0, -353 notify: self.0.shared.stream_incoming[Dir::Uni as usize].notified(), -354 } -355 } -356 -357 /// Accept the next incoming bidirectional stream -358 /// -359 /// **Important Note**: The `Connection` that calls [`open_bi()`] must write to its [`SendStream`] -360 /// before the other `Connection` is able to `accept_bi()`. Calling [`open_bi()`] then -361 /// waiting on the [`RecvStream`] without writing anything to [`SendStream`] will never succeed. -362 /// -363 /// [`accept_bi()`]: crate::Connection::accept_bi -364 /// [`open_bi()`]: crate::Connection::open_bi -365 /// [`SendStream`]: crate::SendStream -366 /// [`RecvStream`]: crate::RecvStream -367 pub fn accept_bi(&self) -> AcceptBi<'_> { -368 AcceptBi { -369 conn: &self.0, -370 notify: self.0.shared.stream_incoming[Dir::Bi as usize].notified(), -371 } -372 } -373 -374 /// Receive an application datagram -375 pub fn read_datagram(&self) -> ReadDatagram<'_> { -376 ReadDatagram { -377 conn: &self.0, -378 notify: self.0.shared.datagram_received.notified(), -379 } -380 } -381 -382 /// Opens a new path if no path exists yet for the remote address. -383 /// -384 /// Otherwise behaves exactly as [`open_path`]. -385 /// -386 /// [`open_path`]: Self::open_path -387 pub fn open_path_ensure(&self, addr: SocketAddr, initial_status: PathStatus) -> OpenPath { -388 let mut state = self.0.lock_and_wake("open_path"); -389 -390 // If endpoint::State::ipv6 is true we want to keep all our IP addresses as IPv6. -391 // If not, we do not support IPv6. We can not access endpoint::State from here -392 // however, but either all our paths use an IPv6 address, or all our paths use an -393 // IPv4 address. So we can use that information. -394 let ipv6 = state -395 .inner -396 .paths() -397 .iter() -398 .filter_map(|id| { -399 state -400 .inner -401 .network_path(*id) -402 .map(|addrs| addrs.remote().is_ipv6()) -403 .ok() -404 }) -405 .next() -406 .unwrap_or_default(); -407 if addr.is_ipv6() && !ipv6 { -408 return OpenPath::rejected(PathError::InvalidRemoteAddress(addr)); -409 } -410 let addr = if ipv6 { -411 SocketAddr::V6(ensure_ipv6(addr)) -412 } else { -413 addr -414 }; -415 -416 let now = state.runtime.now(); -417 // TODO(matheus23): For now this means it's impossible to make use of short-circuiting path validation currently. -418 // However, changing that would mean changing the API. -419 let addrs = FourTuple::from_remote(addr); -420 let open_res = state.inner.open_path_ensure(addrs, initial_status, now); -421 match open_res { -422 Ok((path_id, existed)) if existed => { -423 let recv = state.open_path.get(&path_id).map(|tx| tx.subscribe()); -424 drop(state); -425 match recv { -426 Some(recv) => OpenPath::new(path_id, recv, self.0.clone()), -427 None => OpenPath::ready(path_id, self.0.clone()), -428 } -429 } -430 Ok((path_id, _)) => { -431 let (tx, rx) = watch::channel(Ok(())); -432 state.open_path.insert(path_id, tx); -433 drop(state); -434 OpenPath::new(path_id, rx, self.0.clone()) -435 } -436 Err(err) => OpenPath::rejected(err), -437 } -438 } -439 -440 /// Opens an additional path if the multipath extension is negotiated. -441 /// -442 /// The returned future completes once the path is either fully opened and ready to -443 /// carry application data, or if there was an error. -444 /// -445 /// Dropping the returned future does not cancel the opening of the path, the -446 /// [`PathEvent::Opened`] event will still be emitted from [`Self::path_events`] if the -447 /// path opens. The [`PathId`] for the events can be extracted from -448 /// [`OpenPath::path_id`]. -449 /// -450 /// Failure to open a path can either occur immediately, before polling the returned -451 /// future, or at a later time. If the failure is immediate [`OpenPath::path_id`] will -452 /// return `None` and the future will be ready immediately. If the failure happens -453 /// later, a [`PathEvent`] will be emitted. -454 pub fn open_path(&self, addr: SocketAddr, initial_status: PathStatus) -> OpenPath { -455 let mut state = self.0.lock_and_wake("open_path"); -456 -457 // If endpoint::State::ipv6 is true we want to keep all our IP addresses as IPv6. -458 // If not, we do not support IPv6. We can not access endpoint::State from here -459 // however, but either all our paths use an IPv6 address, or all our paths use an -460 // IPv4 address. So we can use that information. -461 let ipv6 = state -462 .inner -463 .paths() -464 .iter() -465 .filter_map(|id| { -466 state -467 .inner -468 .network_path(*id) -469 .map(|addrs| addrs.remote().is_ipv6()) -470 .ok() -471 }) -472 .next() -473 .unwrap_or_default(); -474 if addr.is_ipv6() && !ipv6 { -475 return OpenPath::rejected(PathError::InvalidRemoteAddress(addr)); -476 } -477 let addr = if ipv6 { -478 SocketAddr::V6(ensure_ipv6(addr)) -479 } else { -480 addr -481 }; -482 -483 let (on_open_path_send, on_open_path_recv) = watch::channel(Ok(())); -484 let now = state.runtime.now(); -485 // TODO(matheus23): For now this means it's impossible to make use of short-circuiting path validation currently. -486 // However, changing that would mean changing the API. -487 let addrs = FourTuple::from_remote(addr); -488 let open_res = state.inner.open_path(addrs, initial_status, now); -489 match open_res { -490 Ok(path_id) => { -491 state.open_path.insert(path_id, on_open_path_send); -492 drop(state); -493 OpenPath::new(path_id, on_open_path_recv, self.0.clone()) -494 } -495 Err(err) => OpenPath::rejected(err), -496 } -497 } -498 -499 /// Returns the [`Path`] structure of an open path -500 pub fn path(&self, id: PathId) -> Option<Path> { -501 Path::new(&self.0, id) -502 } -503 -504 /// A stream of [`PathEvent`]s for all paths in this connection. -505 /// -506 /// The stream will yield a [`PathEvent`] whenever there is a change in the state of any path in this connection. -507 /// The events need to be processed immediately, since there isn't an unbounded buffer for them. -508 /// -509 /// If processing of events lags behind too much, you will get an error of type [`crate::Lagged`] indicating -510 /// how many events were lost. The stream continues after a lag, delivering the oldest retained message next. -511 pub fn path_events(&self) -> crate::PathEvents { -512 crate::PathEvents::new( -513 self.0 -514 .lock_without_waking("path_events") -515 .path_events -516 .subscribe(), -517 ) -518 } -519 -520 /// A stream of NAT traversal updates for this connection. -521 /// -522 /// The events need to be processed immediately, since there isn't an unbounded buffer for them. -523 /// -524 /// If processing of events lags behind too much, you will get an error of type [`crate::Lagged`] indicating -525 /// how many events were lost. The stream continues after a lag, delivering the oldest retained message next. -526 pub fn nat_traversal_updates(&self) -> crate::NatTraversalUpdates { -527 crate::NatTraversalUpdates::new( -528 self.0 -529 .lock_without_waking("nat_traversal_updates") -530 .nat_traversal_updates -531 .subscribe(), -532 ) -533 } -534 -535 /// Wait for the connection to be closed for any reason -536 /// -537 /// Despite the return type's name, closed connections are often not an error condition at the -538 /// application layer. Cases that might be routine include [`ConnectionError::LocallyClosed`] -539 /// and [`ConnectionError::ApplicationClosed`]. -540 pub async fn closed(&self) -> ConnectionError { -541 { -542 let conn = self.0.lock_without_waking("closed"); -543 if let Some(error) = conn.error.as_ref() { -544 return error.clone(); -545 } -546 // Construct the future while the lock is held to ensure we can't miss a wakeup if -547 // the `Notify` is signaled immediately after we release the lock. `await` it after -548 // the lock guard is out of scope. -549 self.0.shared.closed.notified() -550 } -551 .await; -552 self.0 -553 .lock_without_waking("closed") -554 .error -555 .as_ref() -556 .expect("closed without an error") -557 .clone() -558 } -559 -560 /// Wait for the connection to be closed without keeping a strong reference to the connection -561 /// -562 /// Returns a future that resolves, once the connection is closed, to a tuple of -563 /// ([`ConnectionError`], [`ConnectionStats`]). -564 /// -565 /// Calling [`Self::closed`] keeps the connection alive until it is either closed locally via [`Connection::close`] -566 /// or closed by the remote peer. This function instead does not keep the connection itself alive, -567 /// so if all *other* clones of the connection are dropped, the connection will be closed implicitly even -568 /// if there are futures returned from this function still being awaited. -569 pub fn on_closed(&self) -> OnClosed { -570 let (tx, rx) = oneshot::channel(); -571 let mut state = self.0.lock_without_waking("on_closed"); -572 if let Some(error) = &state.error { -573 // Connection already closed, send immediately -574 let _ = tx.send((error.clone(), state.inner.stats())); -575 } else { -576 state.on_closed.push(tx); -577 } -578 drop(state); -579 OnClosed { -580 conn: self.weak_handle(), -581 rx, -582 } -583 } -584 -585 /// Whether the connection is closed, and why. -586 /// -587 /// The close_reason is always set to `Some(ConnectionError)` when a socket is -588 /// closed; whether it was closed manually by calling [`Connection::close()`] or due to -589 /// an internal error (such as an idle timeout or the peer closing the -590 /// connection). -591 /// -592 /// Note: when the connection is closed, `connection.close_reason().is_some()` will always be true. -593 pub fn close_reason(&self) -> Option<ConnectionError> { -594 self.0.lock_without_waking("close_reason").error.clone() -595 } -596 -597 /// Close the connection immediately. -598 /// -599 /// Pending operations will fail immediately with [`ConnectionError::LocallyClosed`]. No -600 /// more data is sent to the peer and the peer may drop buffered data upon receiving -601 /// the CONNECTION_CLOSE frame. -602 /// -603 /// `error_code` and `reason` are not interpreted, and are provided directly to the peer. -604 /// -605 /// `reason` will be truncated to fit in a single packet with overhead; to improve odds that it -606 /// is preserved in full, it should be kept under 1KiB. -607 /// -608 /// # Gracefully closing a connection -609 /// -610 /// Only the peer last receiving application data can be certain that all data is -611 /// delivered. The only reliable action it can then take is to close the connection, -612 /// potentially with a custom error code. The delivery of the final CONNECTION_CLOSE -613 /// frame is very likely if both endpoints stay online long enough, and -614 /// [`Endpoint::wait_idle()`] can be used to provide sufficient time. Otherwise, the -615 /// remote peer will time out the connection, provided that the idle timeout is not -616 /// disabled. -617 /// -618 /// The sending side can not guarantee all stream data is delivered to the remote -619 /// application. It only knows the data is delivered to the QUIC stack of the remote -620 /// endpoint. Once the local side sends a CONNECTION_CLOSE frame in response to calling -621 /// [`close()`] the remote endpoint may drop any data it received but is as yet -622 /// undelivered to the application, including data that was acknowledged as received to -623 /// the local endpoint. -624 /// -625 /// [`ConnectionError::LocallyClosed`]: crate::ConnectionError::LocallyClosed -626 /// [`Endpoint::wait_idle()`]: crate::Endpoint::wait_idle -627 /// [`close()`]: Connection::close -628 pub fn close(&self, error_code: VarInt, reason: &[u8]) { -629 let conn = &mut *self.0.lock_without_waking("close"); // conn.close self-wakes -630 conn.close(error_code, Bytes::copy_from_slice(reason), &self.0.shared); -631 } -632 -633 /// Wait for the handshake to be confirmed. -634 /// -635 /// As a server, who must be authenticated by clients, -636 /// this happens when the handshake completes -637 /// upon receiving a TLS Finished message from the client. -638 /// In return, the server send a HANDSHAKE_DONE frame. -639 /// -640 /// As a client, this happens when receiving a HANDSHAKE_DONE frame. -641 /// At this point, the server has either accepted our authentication, -642 /// or, if client authentication is not required, accepted our lack of authentication. -643 pub async fn handshake_confirmed(&self) -> Result<(), ConnectionError> { -644 { -645 let conn = self.0.lock_without_waking("handshake_confirmed"); -646 if let Some(error) = conn.error.as_ref() { -647 return Err(error.clone()); -648 } -649 if conn.handshake_confirmed { -650 return Ok(()); -651 } -652 // Construct the future while the lock is held to ensure we can't miss a wakeup if -653 // the `Notify` is signaled immediately after we release the lock. `await` it after -654 // the lock guard is out of scope. -655 self.0.shared.handshake_confirmed.notified() -656 } -657 .await; -658 if let Some(error) = self -659 .0 -660 .lock_without_waking("handshake_confirmed") -661 .error -662 .as_ref() -663 { -664 Err(error.clone()) -665 } else { -666 Ok(()) -667 } -668 } -669 -670 /// Transmit `data` as an unreliable, unordered application datagram -671 /// -672 /// Application datagrams are a low-level primitive. They may be lost or delivered out of order, -673 /// and `data` must both fit inside a single QUIC packet and be smaller than the maximum -674 /// dictated by the peer. -675 /// -676 /// Previously queued datagrams which are still unsent may be discarded to make space for this -677 /// datagram, in order of oldest to newest. -678 pub fn send_datagram(&self, data: Bytes) -> Result<(), SendDatagramError> { -679 let conn = &mut *self.0.lock_and_wake("send_datagram"); -680 if let Some(ref x) = conn.error { -681 return Err(SendDatagramError::ConnectionLost(x.clone())); -682 } -683 use proto::SendDatagramError::*; -684 match conn.inner.datagrams().send(data, true) { -685 Ok(()) => Ok(()), -686 Err(e) => Err(match e { -687 Blocked(..) => unreachable!(), -688 UnsupportedByPeer => SendDatagramError::UnsupportedByPeer, -689 Disabled => SendDatagramError::Disabled, -690 TooLarge => SendDatagramError::TooLarge, -691 }), -692 } -693 } -694 -695 /// Transmit `data` as an unreliable, unordered application datagram -696 /// -697 /// Unlike [`send_datagram()`], this method will wait for buffer space during congestion -698 /// conditions, which effectively prioritizes old datagrams over new datagrams. -699 /// -700 /// See [`send_datagram()`] for details. -701 /// -702 /// [`send_datagram()`]: Connection::send_datagram -703 pub fn send_datagram_wait(&self, data: Bytes) -> SendDatagram<'_> { -704 SendDatagram { -705 conn: &self.0, -706 data: Some(data), -707 notify: self.0.shared.datagrams_unblocked.notified(), -708 } -709 } -710 -711 /// Compute the maximum size of datagrams that may be passed to [`send_datagram()`]. -712 /// -713 /// Returns `None` if datagrams are unsupported by the peer or disabled locally. -714 /// -715 /// This may change over the lifetime of a connection according to variation in the path MTU -716 /// estimate. The peer can also enforce an arbitrarily small fixed limit, but if the peer's -717 /// limit is large this is guaranteed to be a little over a kilobyte at minimum. -718 /// -719 /// Not necessarily the maximum size of received datagrams. -720 /// -721 /// [`send_datagram()`]: Connection::send_datagram -722 pub fn max_datagram_size(&self) -> Option<usize> { -723 self.0 -724 .lock_without_waking("max_datagram_size") -725 .inner -726 .datagrams() -727 .max_size() -728 } -729 -730 /// Bytes available in the outgoing datagram buffer -731 /// -732 /// When greater than zero, calling [`send_datagram()`](Self::send_datagram) with a datagram of -733 /// at most this size is guaranteed not to cause older datagrams to be dropped. -734 pub fn datagram_send_buffer_space(&self) -> usize { -735 self.0 -736 .lock_without_waking("datagram_send_buffer_space") -737 .inner -738 .datagrams() -739 .send_buffer_space() -740 } -741 -742 /// The side of the connection (client or server) -743 pub fn side(&self) -> Side { -744 self.0.lock_without_waking("side").inner.side() -745 } -746 -747 /// The peer's UDP address -748 /// -749 /// If [`ServerConfig::migration`] is `true`, clients may change addresses at will, -750 /// e.g. when switching to a cellular internet connection. -751 /// -752 /// If [`multipath`] is enabled this will return the address of *any* -753 /// path, and may not be consistent. Prefer [`Path::remote_address`] instead. -754 /// -755 /// [`ServerConfig::migration`]: crate::ServerConfig::migration -756 /// [`multipath`]: crate::TransportConfig::max_concurrent_multipath_paths -757 pub fn remote_address(&self) -> SocketAddr { -758 // TODO: an unwrap again -759 let state = self.0.lock_without_waking("remote_address"); -760 state -761 .inner -762 .paths() -763 .iter() -764 .filter_map(|id| state.inner.network_path(*id).ok()) -765 .next() -766 .unwrap() -767 .remote() +204 conn_ref +205 .lock_without_waking("remote_address") +206 .inner +207 .network_path(PathId::ZERO) +208 .expect("PathId::ZERO is the only path during the handshake") +209 .remote() +210 } +211} +212 +213impl Future for Connecting { +214 type Output = Result<Connection, ConnectionError>; +215 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { +216 Pin::new(&mut self.connected).poll(cx).map(|_| { +217 let conn = self.conn.take().unwrap(); +218 let inner = conn.lock_without_waking("connecting"); +219 if inner.connected { +220 drop(inner); +221 Ok(Connection(conn)) +222 } else { +223 Err(inner +224 .error +225 .clone() +226 .expect("connected signaled without connection success or error")) +227 } +228 }) +229 } +230} +231 +232/// Future that completes when a connection is fully established +233/// +234/// For clients, the resulting value indicates if 0-RTT was accepted. For servers, the resulting +235/// value is meaningless. +236pub struct ZeroRttAccepted(oneshot::Receiver<bool>); +237 +238impl Future for ZeroRttAccepted { +239 type Output = bool; +240 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { +241 Pin::new(&mut self.0).poll(cx).map(|x| x.unwrap_or(false)) +242 } +243} +244 +245/// A future that drives protocol logic for a connection +246/// +247/// This future handles the protocol logic for a single connection, routing events from the +248/// `Connection` API object to the `Endpoint` task and the related stream-related interfaces. +249/// It also keeps track of outstanding timeouts for the `Connection`. +250/// +251/// If the connection encounters an error condition, this future will yield an error. It will +252/// terminate (yielding `Ok(())`) if the connection was closed without error. Unlike other +253/// connection-related futures, this waits for the draining period to complete to ensure that +254/// packets still in flight from the peer are handled gracefully. +255#[must_use = "connection drivers must be spawned for their connections to function"] +256#[derive(Debug)] +257struct ConnectionDriver(ConnectionRef); +258 +259impl Future for ConnectionDriver { +260 type Output = Result<(), io::Error>; +261 +262 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { +263 let conn = &mut *self.0.lock_without_waking("poll"); +264 +265 let span = debug_span!("drive", id = conn.handle.0); +266 let _guard = span.enter(); +267 +268 if let Err(e) = conn.process_conn_events(&self.0.shared, cx) { +269 conn.terminate(e, &self.0.shared); +270 return Poll::Ready(Ok(())); +271 } +272 let mut keep_going = conn.drive_transmit(cx)?; +273 // If a timer expires, there might be more to transmit. When we transmit something, we +274 // might need to reset a timer. Hence, we must loop until neither happens. +275 keep_going |= conn.drive_timer(cx); +276 conn.forward_endpoint_events(); +277 conn.forward_app_events(&self.0.shared); +278 +279 if !conn.inner.is_drained() { +280 if keep_going { +281 // If the connection hasn't processed all tasks, schedule it again +282 cx.waker().wake_by_ref(); +283 } else { +284 conn.driver = Some(cx.waker().clone()); +285 } +286 return Poll::Pending; +287 } +288 if conn.error.is_none() { +289 unreachable!("drained connections always have an error"); +290 } +291 Poll::Ready(Ok(())) +292 } +293} +294 +295/// A QUIC connection. +296/// +297/// If all references to a connection (including every clone of the `Connection` handle, streams of +298/// incoming streams, and the various stream types) have been dropped, then the connection will be +299/// automatically closed with an `error_code` of 0 and an empty `reason`. You can also close the +300/// connection explicitly by calling [`Connection::close()`]. +301/// +302/// Closing the connection immediately abandons efforts to deliver data to the peer. Upon +303/// receiving CONNECTION_CLOSE the peer *may* drop any stream data not yet delivered to the +304/// application. [`Connection::close()`] describes in more detail how to gracefully close a +305/// connection without losing application data. +306/// +307/// May be cloned to obtain another handle to the same connection. +308/// +309/// [`Connection::close()`]: Connection::close +310#[derive(Debug, Clone)] +311pub struct Connection(ConnectionRef); +312 +313impl Connection { +314 /// Returns a weak reference to the inner connection struct. +315 pub fn weak_handle(&self) -> WeakConnectionHandle { +316 self.0.weak_handle() +317 } +318 +319 /// Initiate a new outgoing unidirectional stream. +320 /// +321 /// Streams are cheap and instantaneous to open unless blocked by flow control. As a +322 /// consequence, the peer won't be notified that a stream has been opened until the stream is +323 /// actually used. +324 pub fn open_uni(&self) -> OpenUni<'_> { +325 OpenUni { +326 conn: &self.0, +327 notify: self.0.shared.stream_budget_available[Dir::Uni as usize].notified(), +328 } +329 } +330 +331 /// Initiate a new outgoing bidirectional stream. +332 /// +333 /// Streams are cheap and instantaneous to open unless blocked by flow control. As a +334 /// consequence, the peer won't be notified that a stream has been opened until the stream is +335 /// actually used. Calling [`open_bi()`] then waiting on the [`RecvStream`] without writing +336 /// anything to [`SendStream`] will never succeed. +337 /// +338 /// [`open_bi()`]: crate::Connection::open_bi +339 /// [`SendStream`]: crate::SendStream +340 /// [`RecvStream`]: crate::RecvStream +341 pub fn open_bi(&self) -> OpenBi<'_> { +342 OpenBi { +343 conn: &self.0, +344 notify: self.0.shared.stream_budget_available[Dir::Bi as usize].notified(), +345 } +346 } +347 +348 /// Accept the next incoming uni-directional stream +349 pub fn accept_uni(&self) -> AcceptUni<'_> { +350 AcceptUni { +351 conn: &self.0, +352 notify: self.0.shared.stream_incoming[Dir::Uni as usize].notified(), +353 } +354 } +355 +356 /// Accept the next incoming bidirectional stream +357 /// +358 /// **Important Note**: The `Connection` that calls [`open_bi()`] must write to its [`SendStream`] +359 /// before the other `Connection` is able to `accept_bi()`. Calling [`open_bi()`] then +360 /// waiting on the [`RecvStream`] without writing anything to [`SendStream`] will never succeed. +361 /// +362 /// [`accept_bi()`]: crate::Connection::accept_bi +363 /// [`open_bi()`]: crate::Connection::open_bi +364 /// [`SendStream`]: crate::SendStream +365 /// [`RecvStream`]: crate::RecvStream +366 pub fn accept_bi(&self) -> AcceptBi<'_> { +367 AcceptBi { +368 conn: &self.0, +369 notify: self.0.shared.stream_incoming[Dir::Bi as usize].notified(), +370 } +371 } +372 +373 /// Receive an application datagram +374 pub fn read_datagram(&self) -> ReadDatagram<'_> { +375 ReadDatagram { +376 conn: &self.0, +377 notify: self.0.shared.datagram_received.notified(), +378 } +379 } +380 +381 /// Opens a new path if no path exists yet for the remote address. +382 /// +383 /// Otherwise behaves exactly as [`open_path`]. +384 /// +385 /// [`open_path`]: Self::open_path +386 pub fn open_path_ensure(&self, addr: SocketAddr, initial_status: PathStatus) -> OpenPath { +387 let mut state = self.0.lock_and_wake("open_path"); +388 +389 // If endpoint::State::ipv6 is true we want to keep all our IP addresses as IPv6. +390 // If not, we do not support IPv6. We can not access endpoint::State from here +391 // however, but either all our paths use an IPv6 address, or all our paths use an +392 // IPv4 address. So we can use that information. +393 let ipv6 = state +394 .inner +395 .paths() +396 .iter() +397 .filter_map(|id| { +398 state +399 .inner +400 .network_path(*id) +401 .map(|addrs| addrs.remote().is_ipv6()) +402 .ok() +403 }) +404 .next() +405 .unwrap_or_default(); +406 if addr.is_ipv6() && !ipv6 { +407 return OpenPath::rejected(PathError::InvalidRemoteAddress(addr)); +408 } +409 let addr = if ipv6 { +410 SocketAddr::V6(ensure_ipv6(addr)) +411 } else { +412 addr +413 }; +414 +415 let now = state.runtime.now(); +416 // TODO(matheus23): For now this means it's impossible to make use of short-circuiting path validation currently. +417 // However, changing that would mean changing the API. +418 let addrs = FourTuple::from_remote(addr); +419 let open_res = state.inner.open_path_ensure(addrs, initial_status, now); +420 match open_res { +421 Ok((path_id, existed)) if existed => { +422 let recv = state.open_path.get(&path_id).map(|tx| tx.subscribe()); +423 drop(state); +424 match recv { +425 Some(recv) => OpenPath::new(path_id, recv, self.0.clone()), +426 None => OpenPath::ready(path_id, self.0.clone()), +427 } +428 } +429 Ok((path_id, _)) => { +430 let (tx, rx) = watch::channel(Ok(())); +431 state.open_path.insert(path_id, tx); +432 drop(state); +433 OpenPath::new(path_id, rx, self.0.clone()) +434 } +435 Err(err) => OpenPath::rejected(err), +436 } +437 } +438 +439 /// Opens an additional path if the multipath extension is negotiated. +440 /// +441 /// The returned future completes once the path is either fully opened and ready to +442 /// carry application data, or if there was an error. +443 /// +444 /// Dropping the returned future does not cancel the opening of the path, the +445 /// [`PathEvent::Opened`] event will still be emitted from [`Self::path_events`] if the +446 /// path opens. The [`PathId`] for the events can be extracted from +447 /// [`OpenPath::path_id`]. +448 /// +449 /// Failure to open a path can either occur immediately, before polling the returned +450 /// future, or at a later time. If the failure is immediate [`OpenPath::path_id`] will +451 /// return `None` and the future will be ready immediately. If the failure happens +452 /// later, a [`PathEvent`] will be emitted. +453 pub fn open_path(&self, addr: SocketAddr, initial_status: PathStatus) -> OpenPath { +454 let mut state = self.0.lock_and_wake("open_path"); +455 +456 // If endpoint::State::ipv6 is true we want to keep all our IP addresses as IPv6. +457 // If not, we do not support IPv6. We can not access endpoint::State from here +458 // however, but either all our paths use an IPv6 address, or all our paths use an +459 // IPv4 address. So we can use that information. +460 let ipv6 = state +461 .inner +462 .paths() +463 .iter() +464 .filter_map(|id| { +465 state +466 .inner +467 .network_path(*id) +468 .map(|addrs| addrs.remote().is_ipv6()) +469 .ok() +470 }) +471 .next() +472 .unwrap_or_default(); +473 if addr.is_ipv6() && !ipv6 { +474 return OpenPath::rejected(PathError::InvalidRemoteAddress(addr)); +475 } +476 let addr = if ipv6 { +477 SocketAddr::V6(ensure_ipv6(addr)) +478 } else { +479 addr +480 }; +481 +482 let (on_open_path_send, on_open_path_recv) = watch::channel(Ok(())); +483 let now = state.runtime.now(); +484 // TODO(matheus23): For now this means it's impossible to make use of short-circuiting path validation currently. +485 // However, changing that would mean changing the API. +486 let addrs = FourTuple::from_remote(addr); +487 let open_res = state.inner.open_path(addrs, initial_status, now); +488 match open_res { +489 Ok(path_id) => { +490 state.open_path.insert(path_id, on_open_path_send); +491 drop(state); +492 OpenPath::new(path_id, on_open_path_recv, self.0.clone()) +493 } +494 Err(err) => OpenPath::rejected(err), +495 } +496 } +497 +498 /// Returns the [`Path`] structure of an open path +499 pub fn path(&self, id: PathId) -> Option<Path> { +500 Path::new(&self.0, id) +501 } +502 +503 /// A stream of [`PathEvent`]s for all paths in this connection. +504 /// +505 /// The stream will yield a [`PathEvent`] whenever there is a change in the state of any path in this connection. +506 /// The events need to be processed immediately, since there isn't an unbounded buffer for them. +507 /// +508 /// If processing of events lags behind too much, you will get an error of type [`crate::Lagged`] indicating +509 /// how many events were lost. The stream continues after a lag, delivering the oldest retained message next. +510 pub fn path_events(&self) -> crate::PathEvents { +511 crate::PathEvents::new( +512 self.0 +513 .lock_without_waking("path_events") +514 .path_events +515 .subscribe(), +516 ) +517 } +518 +519 /// A stream of NAT traversal updates for this connection. +520 /// +521 /// The events need to be processed immediately, since there isn't an unbounded buffer for them. +522 /// +523 /// If processing of events lags behind too much, you will get an error of type [`crate::Lagged`] indicating +524 /// how many events were lost. The stream continues after a lag, delivering the oldest retained message next. +525 pub fn nat_traversal_updates(&self) -> crate::NatTraversalUpdates { +526 crate::NatTraversalUpdates::new( +527 self.0 +528 .lock_without_waking("nat_traversal_updates") +529 .nat_traversal_updates +530 .subscribe(), +531 ) +532 } +533 +534 /// Wait for the connection to be closed for any reason +535 /// +536 /// Despite the return type's name, closed connections are often not an error condition at the +537 /// application layer. Cases that might be routine include [`ConnectionError::LocallyClosed`] +538 /// and [`ConnectionError::ApplicationClosed`]. +539 pub async fn closed(&self) -> ConnectionError { +540 { +541 let conn = self.0.lock_without_waking("closed"); +542 if let Some(error) = conn.error.as_ref() { +543 return error.clone(); +544 } +545 // Construct the future while the lock is held to ensure we can't miss a wakeup if +546 // the `Notify` is signaled immediately after we release the lock. `await` it after +547 // the lock guard is out of scope. +548 self.0.shared.closed.notified() +549 } +550 .await; +551 self.0 +552 .lock_without_waking("closed") +553 .error +554 .as_ref() +555 .expect("closed without an error") +556 .clone() +557 } +558 +559 /// Wait for the connection to be closed without keeping a strong reference to the connection +560 /// +561 /// Returns a future that resolves, once the connection is closed, to a tuple of +562 /// ([`ConnectionError`], [`ConnectionStats`]). +563 /// +564 /// Calling [`Self::closed`] keeps the connection alive until it is either closed locally via [`Connection::close`] +565 /// or closed by the remote peer. This function instead does not keep the connection itself alive, +566 /// so if all *other* clones of the connection are dropped, the connection will be closed implicitly even +567 /// if there are futures returned from this function still being awaited. +568 pub fn on_closed(&self) -> OnClosed { +569 let (tx, rx) = oneshot::channel(); +570 let mut state = self.0.lock_without_waking("on_closed"); +571 if let Some(error) = &state.error { +572 // Connection already closed, send immediately +573 let _ = tx.send((error.clone(), state.inner.stats())); +574 } else { +575 state.on_closed.push(tx); +576 } +577 drop(state); +578 OnClosed { +579 conn: self.weak_handle(), +580 rx, +581 } +582 } +583 +584 /// Whether the connection is closed, and why. +585 /// +586 /// The close_reason is always set to `Some(ConnectionError)` when a socket is +587 /// closed; whether it was closed manually by calling [`Connection::close()`] or due to +588 /// an internal error (such as an idle timeout or the peer closing the +589 /// connection). +590 /// +591 /// Note: when the connection is closed, `connection.close_reason().is_some()` will always be true. +592 pub fn close_reason(&self) -> Option<ConnectionError> { +593 self.0.lock_without_waking("close_reason").error.clone() +594 } +595 +596 /// Close the connection immediately. +597 /// +598 /// Pending operations will fail immediately with [`ConnectionError::LocallyClosed`]. No +599 /// more data is sent to the peer and the peer may drop buffered data upon receiving +600 /// the CONNECTION_CLOSE frame. +601 /// +602 /// `error_code` and `reason` are not interpreted, and are provided directly to the peer. +603 /// +604 /// `reason` will be truncated to fit in a single packet with overhead; to improve odds that it +605 /// is preserved in full, it should be kept under 1KiB. +606 /// +607 /// # Gracefully closing a connection +608 /// +609 /// Only the peer last receiving application data can be certain that all data is +610 /// delivered. The only reliable action it can then take is to close the connection, +611 /// potentially with a custom error code. The delivery of the final CONNECTION_CLOSE +612 /// frame is very likely if both endpoints stay online long enough, and +613 /// [`Endpoint::wait_idle()`] can be used to provide sufficient time. Otherwise, the +614 /// remote peer will time out the connection, provided that the idle timeout is not +615 /// disabled. +616 /// +617 /// The sending side can not guarantee all stream data is delivered to the remote +618 /// application. It only knows the data is delivered to the QUIC stack of the remote +619 /// endpoint. Once the local side sends a CONNECTION_CLOSE frame in response to calling +620 /// [`close()`] the remote endpoint may drop any data it received but is as yet +621 /// undelivered to the application, including data that was acknowledged as received to +622 /// the local endpoint. +623 /// +624 /// [`ConnectionError::LocallyClosed`]: crate::ConnectionError::LocallyClosed +625 /// [`Endpoint::wait_idle()`]: crate::Endpoint::wait_idle +626 /// [`close()`]: Connection::close +627 pub fn close(&self, error_code: VarInt, reason: &[u8]) { +628 let conn = &mut *self.0.lock_without_waking("close"); // conn.close self-wakes +629 conn.close(error_code, Bytes::copy_from_slice(reason), &self.0.shared); +630 } +631 +632 /// Wait for the handshake to be confirmed. +633 /// +634 /// As a server, who must be authenticated by clients, +635 /// this happens when the handshake completes +636 /// upon receiving a TLS Finished message from the client. +637 /// In return, the server send a HANDSHAKE_DONE frame. +638 /// +639 /// As a client, this happens when receiving a HANDSHAKE_DONE frame. +640 /// At this point, the server has either accepted our authentication, +641 /// or, if client authentication is not required, accepted our lack of authentication. +642 pub async fn handshake_confirmed(&self) -> Result<(), ConnectionError> { +643 { +644 let conn = self.0.lock_without_waking("handshake_confirmed"); +645 if let Some(error) = conn.error.as_ref() { +646 return Err(error.clone()); +647 } +648 if conn.handshake_confirmed { +649 return Ok(()); +650 } +651 // Construct the future while the lock is held to ensure we can't miss a wakeup if +652 // the `Notify` is signaled immediately after we release the lock. `await` it after +653 // the lock guard is out of scope. +654 self.0.shared.handshake_confirmed.notified() +655 } +656 .await; +657 if let Some(error) = self +658 .0 +659 .lock_without_waking("handshake_confirmed") +660 .error +661 .as_ref() +662 { +663 Err(error.clone()) +664 } else { +665 Ok(()) +666 } +667 } +668 +669 /// Transmit `data` as an unreliable, unordered application datagram +670 /// +671 /// Application datagrams are a low-level primitive. They may be lost or delivered out of order, +672 /// and `data` must both fit inside a single QUIC packet and be smaller than the maximum +673 /// dictated by the peer. +674 /// +675 /// Previously queued datagrams which are still unsent may be discarded to make space for this +676 /// datagram, in order of oldest to newest. +677 pub fn send_datagram(&self, data: Bytes) -> Result<(), SendDatagramError> { +678 let conn = &mut *self.0.lock_and_wake("send_datagram"); +679 if let Some(ref x) = conn.error { +680 return Err(SendDatagramError::ConnectionLost(x.clone())); +681 } +682 use proto::SendDatagramError::*; +683 match conn.inner.datagrams().send(data, true) { +684 Ok(()) => Ok(()), +685 Err(e) => Err(match e { +686 Blocked(..) => unreachable!(), +687 UnsupportedByPeer => SendDatagramError::UnsupportedByPeer, +688 Disabled => SendDatagramError::Disabled, +689 TooLarge => SendDatagramError::TooLarge, +690 }), +691 } +692 } +693 +694 /// Transmit `data` as an unreliable, unordered application datagram +695 /// +696 /// Unlike [`send_datagram()`], this method will wait for buffer space during congestion +697 /// conditions, which effectively prioritizes old datagrams over new datagrams. +698 /// +699 /// See [`send_datagram()`] for details. +700 /// +701 /// [`send_datagram()`]: Connection::send_datagram +702 pub fn send_datagram_wait(&self, data: Bytes) -> SendDatagram<'_> { +703 SendDatagram { +704 conn: &self.0, +705 data: Some(data), +706 notify: self.0.shared.datagrams_unblocked.notified(), +707 } +708 } +709 +710 /// Compute the maximum size of datagrams that may be passed to [`send_datagram()`]. +711 /// +712 /// Returns `None` if datagrams are unsupported by the peer or disabled locally. +713 /// +714 /// This may change over the lifetime of a connection according to variation in the path MTU +715 /// estimate. The peer can also enforce an arbitrarily small fixed limit, but if the peer's +716 /// limit is large this is guaranteed to be a little over a kilobyte at minimum. +717 /// +718 /// Not necessarily the maximum size of received datagrams. +719 /// +720 /// [`send_datagram()`]: Connection::send_datagram +721 pub fn max_datagram_size(&self) -> Option<usize> { +722 self.0 +723 .lock_without_waking("max_datagram_size") +724 .inner +725 .datagrams() +726 .max_size() +727 } +728 +729 /// Bytes available in the outgoing datagram buffer +730 /// +731 /// When greater than zero, calling [`send_datagram()`](Self::send_datagram) with a datagram of +732 /// at most this size is guaranteed not to cause older datagrams to be dropped. +733 pub fn datagram_send_buffer_space(&self) -> usize { +734 self.0 +735 .lock_without_waking("datagram_send_buffer_space") +736 .inner +737 .datagrams() +738 .send_buffer_space() +739 } +740 +741 /// The side of the connection (client or server) +742 pub fn side(&self) -> Side { +743 self.0.lock_without_waking("side").inner.side() +744 } +745 +746 /// Current best estimate of this connection's latency (round-trip-time) +747 pub fn rtt(&self, path_id: PathId) -> Option<Duration> { +748 self.0.lock_without_waking("rtt").inner.rtt(path_id) +749 } +750 +751 /// Returns connection statistics +752 pub fn stats(&self) -> ConnectionStats { +753 self.0.lock_without_waking("stats").inner.stats() +754 } +755 +756 /// Returns path statistics +757 pub fn path_stats(&self, path_id: PathId) -> Option<PathStats> { +758 self.0.lock_without_waking("path_stats").path_stats(path_id) +759 } +760 +761 /// Current state of the congestion control algorithm, for debugging purposes +762 pub fn congestion_state(&self, path_id: PathId) -> Option<Box<dyn Controller>> { +763 self.0 +764 .lock_without_waking("congestion_state") +765 .inner +766 .congestion_state(path_id) +767 .map(|c| c.clone_box()) 768 } 769 -770 /// The local IP address which was used when the peer established -771 /// the connection -772 /// -773 /// This can be different from the address the endpoint is bound to, in case -774 /// the endpoint is bound to a wildcard address like `0.0.0.0` or `::`. +770 /// Parameters negotiated during the handshake +771 /// +772 /// Guaranteed to return `Some` on fully established connections or after +773 /// [`Connecting::handshake_data()`] succeeds. See that method's documentations for details on +774 /// the returned value. 775 /// -776 /// This will return `None` for clients, or when the platform does not expose this -777 /// information. See [`noq_udp::RecvMeta::dst_ip`](udp::RecvMeta::dst_ip) for a list of -778 /// supported platforms when using [`noq_udp`](udp) for I/O, which is the default. -779 pub fn local_ip(&self) -> Option<IpAddr> { -780 // TODO: an unwrap again -781 let state = self.0.lock_without_waking("remote_address"); -782 state -783 .inner -784 .paths() -785 .iter() -786 .filter_map(|id| state.inner.network_path(*id).ok()) -787 .next() -788 .unwrap() -789 .local_ip() -790 } -791 -792 /// Current best estimate of this connection's latency (round-trip-time) -793 pub fn rtt(&self, path_id: PathId) -> Option<Duration> { -794 self.0.lock_without_waking("rtt").inner.rtt(path_id) -795 } -796 -797 /// Returns connection statistics -798 pub fn stats(&self) -> ConnectionStats { -799 self.0.lock_without_waking("stats").inner.stats() -800 } -801 -802 /// Returns path statistics -803 pub fn path_stats(&self, path_id: PathId) -> Option<PathStats> { -804 self.0.lock_without_waking("path_stats").path_stats(path_id) -805 } -806 -807 /// Current state of the congestion control algorithm, for debugging purposes -808 pub fn congestion_state(&self, path_id: PathId) -> Option<Box<dyn Controller>> { -809 self.0 -810 .lock_without_waking("congestion_state") -811 .inner -812 .congestion_state(path_id) -813 .map(|c| c.clone_box()) +776 /// [`Connection::handshake_data()`]: crate::Connecting::handshake_data +777 pub fn handshake_data(&self) -> Option<Box<dyn Any>> { +778 self.0 +779 .lock_without_waking("handshake_data") +780 .inner +781 .crypto_session() +782 .handshake_data() +783 } +784 +785 /// Cryptographic identity of the peer +786 /// +787 /// The dynamic type returned is determined by the configured +788 /// [`Session`](proto::crypto::Session). For the default `rustls` session, the return value can +789 /// be [`downcast`](Box::downcast) to a <code>Vec<[rustls::pki_types::CertificateDer]></code> +790 pub fn peer_identity(&self) -> Option<Box<dyn Any>> { +791 self.0 +792 .lock_without_waking("peer_identity") +793 .inner +794 .crypto_session() +795 .peer_identity() +796 } +797 +798 /// A stable identifier for this connection +799 /// +800 /// Peer addresses and connection IDs can change, but this value will remain +801 /// fixed for the lifetime of the connection. +802 pub fn stable_id(&self) -> usize { +803 self.0.stable_id() +804 } +805 +806 /// Update traffic keys spontaneously +807 /// +808 /// This primarily exists for testing purposes. +809 pub fn force_key_update(&self) { +810 self.0 +811 .lock_and_wake("force_key_update") +812 .inner +813 .force_key_update() 814 } 815 -816 /// Parameters negotiated during the handshake +816 /// Derive keying material from this connection's TLS session secrets. 817 /// -818 /// Guaranteed to return `Some` on fully established connections or after -819 /// [`Connecting::handshake_data()`] succeeds. See that method's documentations for details on -820 /// the returned value. -821 /// -822 /// [`Connection::handshake_data()`]: crate::Connecting::handshake_data -823 pub fn handshake_data(&self) -> Option<Box<dyn Any>> { -824 self.0 -825 .lock_without_waking("handshake_data") -826 .inner -827 .crypto_session() -828 .handshake_data() -829 } -830 -831 /// Cryptographic identity of the peer -832 /// -833 /// The dynamic type returned is determined by the configured -834 /// [`Session`](proto::crypto::Session). For the default `rustls` session, the return value can -835 /// be [`downcast`](Box::downcast) to a <code>Vec<[rustls::pki_types::CertificateDer]></code> -836 pub fn peer_identity(&self) -> Option<Box<dyn Any>> { -837 self.0 -838 .lock_without_waking("peer_identity") -839 .inner -840 .crypto_session() -841 .peer_identity() -842 } -843 -844 /// A stable identifier for this connection -845 /// -846 /// Peer addresses and connection IDs can change, but this value will remain -847 /// fixed for the lifetime of the connection. -848 pub fn stable_id(&self) -> usize { -849 self.0.stable_id() +818 /// When both peers call this method with the same `label` and `context` +819 /// arguments and `output` buffers of equal length, they will get the +820 /// same sequence of bytes in `output`. These bytes are cryptographically +821 /// strong and pseudorandom, and are suitable for use as keying material. +822 /// +823 /// See [RFC5705](https://tools.ietf.org/html/rfc5705) for more information. +824 pub fn export_keying_material( +825 &self, +826 output: &mut [u8], +827 label: &[u8], +828 context: &[u8], +829 ) -> Result<(), proto::crypto::ExportKeyingMaterialError> { +830 self.0 +831 .lock_without_waking("export_keying_material") +832 .inner +833 .crypto_session() +834 .export_keying_material(output, label, context) +835 } +836 +837 /// Modify the number of remotely initiated unidirectional streams that may be concurrently open +838 /// +839 /// No streams may be opened by the peer unless fewer than `count` are already open. Large +840 /// `count`s increase both minimum and worst-case memory consumption. +841 pub fn set_max_concurrent_uni_streams(&self, count: VarInt) { +842 let mut conn = self.0.lock_and_wake("set_max_concurrent_uni_streams"); +843 conn.inner.set_max_concurrent_streams(Dir::Uni, count); +844 } +845 +846 /// See [`proto::TransportConfig::send_window()`] +847 pub fn set_send_window(&self, send_window: u64) { +848 let mut conn = self.0.lock_and_wake("set_send_window"); +849 conn.inner.set_send_window(send_window); 850 } 851 -852 /// Update traffic keys spontaneously -853 /// -854 /// This primarily exists for testing purposes. -855 pub fn force_key_update(&self) { -856 self.0 -857 .lock_and_wake("force_key_update") -858 .inner -859 .force_key_update() -860 } -861 -862 /// Derive keying material from this connection's TLS session secrets. -863 /// -864 /// When both peers call this method with the same `label` and `context` -865 /// arguments and `output` buffers of equal length, they will get the -866 /// same sequence of bytes in `output`. These bytes are cryptographically -867 /// strong and pseudorandom, and are suitable for use as keying material. -868 /// -869 /// See [RFC5705](https://tools.ietf.org/html/rfc5705) for more information. -870 pub fn export_keying_material( -871 &self, -872 output: &mut [u8], -873 label: &[u8], -874 context: &[u8], -875 ) -> Result<(), proto::crypto::ExportKeyingMaterialError> { -876 self.0 -877 .lock_without_waking("export_keying_material") -878 .inner -879 .crypto_session() -880 .export_keying_material(output, label, context) -881 } -882 -883 /// Modify the number of remotely initiated unidirectional streams that may be concurrently open -884 /// -885 /// No streams may be opened by the peer unless fewer than `count` are already open. Large -886 /// `count`s increase both minimum and worst-case memory consumption. -887 pub fn set_max_concurrent_uni_streams(&self, count: VarInt) { -888 let mut conn = self.0.lock_and_wake("set_max_concurrent_uni_streams"); -889 conn.inner.set_max_concurrent_streams(Dir::Uni, count); -890 } -891 -892 /// See [`proto::TransportConfig::send_window()`] -893 pub fn set_send_window(&self, send_window: u64) { -894 let mut conn = self.0.lock_and_wake("set_send_window"); -895 conn.inner.set_send_window(send_window); -896 } -897 -898 /// See [`proto::TransportConfig::receive_window()`] -899 pub fn set_receive_window(&self, receive_window: VarInt) { -900 let mut conn = self.0.lock_and_wake("set_receive_window"); -901 conn.inner.set_receive_window(receive_window); -902 } -903 -904 /// Modify the number of remotely initiated bidirectional streams that may be concurrently open -905 /// -906 /// No streams may be opened by the peer unless fewer than `count` are already open. Large -907 /// `count`s increase both minimum and worst-case memory consumption. -908 pub fn set_max_concurrent_bi_streams(&self, count: VarInt) { -909 let mut conn = self.0.lock_and_wake("set_max_concurrent_bi_streams"); -910 conn.inner.set_max_concurrent_streams(Dir::Bi, count); -911 } -912 -913 /// Track changes on our external address as reported by the peer. -914 pub fn observed_external_addr(&self) -> crate::ObservedExternalAddr { -915 let conn = self.0.lock_without_waking("external_addr"); -916 crate::ObservedExternalAddr::new(conn.observed_external_addr.subscribe()) -917 } -918 -919 /// Is multipath enabled? -920 // TODO(flub): not a useful API, once we do real things with multipath we can remove -921 // this again. -922 pub fn is_multipath_enabled(&self) -> bool { -923 let conn = self.0.lock_without_waking("is_multipath_enabled"); -924 conn.inner.is_multipath_negotiated() -925 } -926 -927 /// Registers one address at which this endpoint might be reachable -928 /// -929 /// When the NAT traversal extension is negotiated, servers send these addresses to clients in -930 /// `ADD_ADDRESS` frames. This allows clients to obtain server address candidates to initiate -931 /// NAT traversal attempts. Clients provide their own reachable addresses in `REACH_OUT` frames -932 /// when [`Self::initiate_nat_traversal_round`] is called. -933 pub fn add_nat_traversal_address( -934 &self, -935 address: SocketAddr, -936 ) -> Result<(), n0_nat_traversal::Error> { -937 let mut conn = self.0.lock_and_wake("add_nat_traversal_addresses"); -938 conn.inner.add_nat_traversal_address(address) -939 } -940 -941 /// Removes one or more addresses from the set of addresses at which this endpoint is reachable -942 /// -943 /// When the NAT traversal extension is negotiated, servers send address removals to -944 /// clients in `REMOVE_ADDRESS` frames. This allows clients to stop using outdated -945 /// server address candidates that are no longer valid for NAT traversal. -946 /// -947 /// For clients, removed addresses will no longer be advertised in `REACH_OUT` frames. -948 /// -949 /// Addresses not present in the set will be silently ignored. -950 pub fn remove_nat_traversal_address( -951 &self, -952 address: SocketAddr, -953 ) -> Result<(), n0_nat_traversal::Error> { -954 let mut conn = self.0.lock_and_wake("remove_nat_traversal_addresses"); -955 conn.inner.remove_nat_traversal_address(address) -956 } -957 -958 /// Get the current local nat traversal addresses -959 pub fn get_local_nat_traversal_addresses( -960 &self, -961 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -962 let conn = self -963 .0 -964 .lock_without_waking("get_local_nat_traversal_addresses"); -965 conn.inner.get_local_nat_traversal_addresses() -966 } -967 -968 /// Get the currently advertised nat traversal addresses by the server -969 pub fn get_remote_nat_traversal_addresses( -970 &self, -971 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -972 let conn = self -973 .0 -974 .lock_without_waking("get_remote_nat_traversal_addresses"); -975 conn.inner.get_remote_nat_traversal_addresses() -976 } -977 -978 /// Initiates a new nat traversal round -979 /// -980 /// A nat traversal round involves advertising the client's local addresses in `REACH_OUT` -981 /// frames, and initiating probing of the known remote addresses. When a new round is -982 /// initiated, the previous one is cancelled, and paths that have not been opened are closed. -983 /// -984 /// Returns the server addresses that are now being probed. -985 pub fn initiate_nat_traversal_round(&self) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -986 let mut conn = self.0.lock_and_wake("initiate_nat_traversal_round"); -987 let now = conn.runtime.now(); -988 conn.inner.initiate_nat_traversal_round(now) -989 } -990} -991 -992pin_project! { -993 /// Future produced by [`Connection::open_uni`] -994 pub struct OpenUni<'a> { -995 conn: &'a ConnectionRef, -996 #[pin] -997 notify: Notified<'a>, -998 } -999} -1000 -1001impl Future for OpenUni<'_> { -1002 type Output = Result<SendStream, ConnectionError>; -1003 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1004 let this = self.project(); -1005 let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Uni))?; -1006 Poll::Ready(Ok(SendStream::new(conn, id, is_0rtt))) -1007 } -1008} -1009 -1010pin_project! { -1011 /// Future produced by [`Connection::open_bi`] -1012 pub struct OpenBi<'a> { -1013 conn: &'a ConnectionRef, -1014 #[pin] -1015 notify: Notified<'a>, -1016 } -1017} -1018 -1019impl Future for OpenBi<'_> { -1020 type Output = Result<(SendStream, RecvStream), ConnectionError>; -1021 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1022 let this = self.project(); -1023 let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Bi))?; -1024 -1025 Poll::Ready(Ok(( -1026 SendStream::new(conn.clone(), id, is_0rtt), -1027 RecvStream::new(conn, id, is_0rtt), -1028 ))) -1029 } -1030} -1031 -1032fn poll_open<'a>( -1033 ctx: &mut Context<'_>, -1034 conn: &'a ConnectionRef, -1035 mut notify: Pin<&mut Notified<'a>>, -1036 dir: Dir, -1037) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> { -1038 let mut state = conn.lock_without_waking("poll_open"); -1039 if let Some(ref e) = state.error { -1040 return Poll::Ready(Err(e.clone())); -1041 } else if let Some(id) = state.inner.streams().open(dir) { -1042 let is_0rtt = state.inner.side().is_client() && state.inner.is_handshaking(); -1043 drop(state); // Release the lock so clone can take it -1044 return Poll::Ready(Ok((conn.clone(), id, is_0rtt))); -1045 } -1046 loop { -1047 match notify.as_mut().poll(ctx) { -1048 // `state` lock ensures we didn't race with readiness -1049 Poll::Pending => return Poll::Pending, -1050 // Spurious wakeup, get a new future -1051 Poll::Ready(()) => { -1052 notify.set(conn.shared.stream_budget_available[dir as usize].notified()) -1053 } -1054 } -1055 } -1056} -1057 -1058pin_project! { -1059 /// Future produced by [`Connection::accept_uni`] -1060 pub struct AcceptUni<'a> { -1061 conn: &'a ConnectionRef, -1062 #[pin] -1063 notify: Notified<'a>, -1064 } -1065} -1066 -1067impl Future for AcceptUni<'_> { -1068 type Output = Result<RecvStream, ConnectionError>; -1069 -1070 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1071 let this = self.project(); -1072 let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Uni))?; -1073 Poll::Ready(Ok(RecvStream::new(conn, id, is_0rtt))) -1074 } -1075} -1076 -1077pin_project! { -1078 /// Future produced by [`Connection::accept_bi`] -1079 pub struct AcceptBi<'a> { -1080 conn: &'a ConnectionRef, -1081 #[pin] -1082 notify: Notified<'a>, -1083 } -1084} -1085 -1086impl Future for AcceptBi<'_> { -1087 type Output = Result<(SendStream, RecvStream), ConnectionError>; -1088 -1089 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1090 let this = self.project(); -1091 let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Bi))?; -1092 Poll::Ready(Ok(( -1093 SendStream::new(conn.clone(), id, is_0rtt), -1094 RecvStream::new(conn, id, is_0rtt), -1095 ))) -1096 } -1097} -1098 -1099fn poll_accept<'a>( -1100 ctx: &mut Context<'_>, -1101 conn: &'a ConnectionRef, -1102 mut notify: Pin<&mut Notified<'a>>, -1103 dir: Dir, -1104) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> { -1105 let mut state = conn.lock_and_wake("poll_accept"); -1106 // Check for incoming streams before checking `state.error` so that already-received streams, -1107 // which are necessarily finite, can be drained from a closed connection. -1108 if let Some(id) = state.inner.streams().accept(dir) { -1109 let is_0rtt = state.inner.is_handshaking(); -1110 drop(state); // Release the lock (wake on drop) so clone can take it -1111 return Poll::Ready(Ok((conn.clone(), id, is_0rtt))); -1112 } else if let Some(ref e) = state.error { -1113 return Poll::Ready(Err(e.clone())); -1114 } -1115 loop { -1116 match notify.as_mut().poll(ctx) { -1117 // `state` lock ensures we didn't race with readiness -1118 Poll::Pending => return Poll::Pending, -1119 // Spurious wakeup, get a new future -1120 Poll::Ready(()) => notify.set(conn.shared.stream_incoming[dir as usize].notified()), -1121 } -1122 } -1123} -1124 -1125pin_project! { -1126 /// Future produced by [`Connection::read_datagram`] -1127 pub struct ReadDatagram<'a> { -1128 conn: &'a ConnectionRef, -1129 #[pin] -1130 notify: Notified<'a>, -1131 } -1132} -1133 -1134impl Future for ReadDatagram<'_> { -1135 type Output = Result<Bytes, ConnectionError>; -1136 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1137 let mut this = self.project(); -1138 let mut state = this.conn.lock_without_waking("ReadDatagram::poll"); -1139 // Check for buffered datagrams before checking `state.error` so that already-received -1140 // datagrams, which are necessarily finite, can be drained from a closed connection. -1141 if let Some(x) = state.inner.datagrams().recv() { -1142 return Poll::Ready(Ok(x)); -1143 } else if let Some(ref e) = state.error { -1144 return Poll::Ready(Err(e.clone())); -1145 } -1146 loop { -1147 match this.notify.as_mut().poll(ctx) { -1148 // `state` lock ensures we didn't race with readiness -1149 Poll::Pending => return Poll::Pending, -1150 // Spurious wakeup, get a new future -1151 Poll::Ready(()) => this -1152 .notify -1153 .set(this.conn.shared.datagram_received.notified()), -1154 } +852 /// See [`proto::TransportConfig::receive_window()`] +853 pub fn set_receive_window(&self, receive_window: VarInt) { +854 let mut conn = self.0.lock_and_wake("set_receive_window"); +855 conn.inner.set_receive_window(receive_window); +856 } +857 +858 /// Modify the number of remotely initiated bidirectional streams that may be concurrently open +859 /// +860 /// No streams may be opened by the peer unless fewer than `count` are already open. Large +861 /// `count`s increase both minimum and worst-case memory consumption. +862 pub fn set_max_concurrent_bi_streams(&self, count: VarInt) { +863 let mut conn = self.0.lock_and_wake("set_max_concurrent_bi_streams"); +864 conn.inner.set_max_concurrent_streams(Dir::Bi, count); +865 } +866 +867 /// Track changes on our external address as reported by the peer. +868 pub fn observed_external_addr(&self) -> crate::ObservedExternalAddr { +869 let conn = self.0.lock_without_waking("external_addr"); +870 crate::ObservedExternalAddr::new(conn.observed_external_addr.subscribe()) +871 } +872 +873 /// Is multipath enabled? +874 // TODO(flub): not a useful API, once we do real things with multipath we can remove +875 // this again. +876 pub fn is_multipath_enabled(&self) -> bool { +877 let conn = self.0.lock_without_waking("is_multipath_enabled"); +878 conn.inner.is_multipath_negotiated() +879 } +880 +881 /// Registers one address at which this endpoint might be reachable +882 /// +883 /// When the NAT traversal extension is negotiated, servers send these addresses to clients in +884 /// `ADD_ADDRESS` frames. This allows clients to obtain server address candidates to initiate +885 /// NAT traversal attempts. Clients provide their own reachable addresses in `REACH_OUT` frames +886 /// when [`Self::initiate_nat_traversal_round`] is called. +887 pub fn add_nat_traversal_address( +888 &self, +889 address: SocketAddr, +890 ) -> Result<(), n0_nat_traversal::Error> { +891 let mut conn = self.0.lock_and_wake("add_nat_traversal_addresses"); +892 conn.inner.add_nat_traversal_address(address) +893 } +894 +895 /// Removes one or more addresses from the set of addresses at which this endpoint is reachable +896 /// +897 /// When the NAT traversal extension is negotiated, servers send address removals to +898 /// clients in `REMOVE_ADDRESS` frames. This allows clients to stop using outdated +899 /// server address candidates that are no longer valid for NAT traversal. +900 /// +901 /// For clients, removed addresses will no longer be advertised in `REACH_OUT` frames. +902 /// +903 /// Addresses not present in the set will be silently ignored. +904 pub fn remove_nat_traversal_address( +905 &self, +906 address: SocketAddr, +907 ) -> Result<(), n0_nat_traversal::Error> { +908 let mut conn = self.0.lock_and_wake("remove_nat_traversal_addresses"); +909 conn.inner.remove_nat_traversal_address(address) +910 } +911 +912 /// Get the current local nat traversal addresses +913 pub fn get_local_nat_traversal_addresses( +914 &self, +915 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +916 let conn = self +917 .0 +918 .lock_without_waking("get_local_nat_traversal_addresses"); +919 conn.inner.get_local_nat_traversal_addresses() +920 } +921 +922 /// Get the currently advertised nat traversal addresses by the server +923 pub fn get_remote_nat_traversal_addresses( +924 &self, +925 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +926 let conn = self +927 .0 +928 .lock_without_waking("get_remote_nat_traversal_addresses"); +929 conn.inner.get_remote_nat_traversal_addresses() +930 } +931 +932 /// Initiates a new nat traversal round +933 /// +934 /// A nat traversal round involves advertising the client's local addresses in `REACH_OUT` +935 /// frames, and initiating probing of the known remote addresses. When a new round is +936 /// initiated, the previous one is cancelled, and paths that have not been opened are closed. +937 /// +938 /// Returns the server addresses that are now being probed. +939 pub fn initiate_nat_traversal_round(&self) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +940 let mut conn = self.0.lock_and_wake("initiate_nat_traversal_round"); +941 let now = conn.runtime.now(); +942 conn.inner.initiate_nat_traversal_round(now) +943 } +944} +945 +946pin_project! { +947 /// Future produced by [`Connection::open_uni`] +948 pub struct OpenUni<'a> { +949 conn: &'a ConnectionRef, +950 #[pin] +951 notify: Notified<'a>, +952 } +953} +954 +955impl Future for OpenUni<'_> { +956 type Output = Result<SendStream, ConnectionError>; +957 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +958 let this = self.project(); +959 let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Uni))?; +960 Poll::Ready(Ok(SendStream::new(conn, id, is_0rtt))) +961 } +962} +963 +964pin_project! { +965 /// Future produced by [`Connection::open_bi`] +966 pub struct OpenBi<'a> { +967 conn: &'a ConnectionRef, +968 #[pin] +969 notify: Notified<'a>, +970 } +971} +972 +973impl Future for OpenBi<'_> { +974 type Output = Result<(SendStream, RecvStream), ConnectionError>; +975 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +976 let this = self.project(); +977 let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Bi))?; +978 +979 Poll::Ready(Ok(( +980 SendStream::new(conn.clone(), id, is_0rtt), +981 RecvStream::new(conn, id, is_0rtt), +982 ))) +983 } +984} +985 +986fn poll_open<'a>( +987 ctx: &mut Context<'_>, +988 conn: &'a ConnectionRef, +989 mut notify: Pin<&mut Notified<'a>>, +990 dir: Dir, +991) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> { +992 let mut state = conn.lock_without_waking("poll_open"); +993 if let Some(ref e) = state.error { +994 return Poll::Ready(Err(e.clone())); +995 } else if let Some(id) = state.inner.streams().open(dir) { +996 let is_0rtt = state.inner.side().is_client() && state.inner.is_handshaking(); +997 drop(state); // Release the lock so clone can take it +998 return Poll::Ready(Ok((conn.clone(), id, is_0rtt))); +999 } +1000 loop { +1001 match notify.as_mut().poll(ctx) { +1002 // `state` lock ensures we didn't race with readiness +1003 Poll::Pending => return Poll::Pending, +1004 // Spurious wakeup, get a new future +1005 Poll::Ready(()) => { +1006 notify.set(conn.shared.stream_budget_available[dir as usize].notified()) +1007 } +1008 } +1009 } +1010} +1011 +1012pin_project! { +1013 /// Future produced by [`Connection::accept_uni`] +1014 pub struct AcceptUni<'a> { +1015 conn: &'a ConnectionRef, +1016 #[pin] +1017 notify: Notified<'a>, +1018 } +1019} +1020 +1021impl Future for AcceptUni<'_> { +1022 type Output = Result<RecvStream, ConnectionError>; +1023 +1024 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +1025 let this = self.project(); +1026 let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Uni))?; +1027 Poll::Ready(Ok(RecvStream::new(conn, id, is_0rtt))) +1028 } +1029} +1030 +1031pin_project! { +1032 /// Future produced by [`Connection::accept_bi`] +1033 pub struct AcceptBi<'a> { +1034 conn: &'a ConnectionRef, +1035 #[pin] +1036 notify: Notified<'a>, +1037 } +1038} +1039 +1040impl Future for AcceptBi<'_> { +1041 type Output = Result<(SendStream, RecvStream), ConnectionError>; +1042 +1043 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +1044 let this = self.project(); +1045 let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Bi))?; +1046 Poll::Ready(Ok(( +1047 SendStream::new(conn.clone(), id, is_0rtt), +1048 RecvStream::new(conn, id, is_0rtt), +1049 ))) +1050 } +1051} +1052 +1053fn poll_accept<'a>( +1054 ctx: &mut Context<'_>, +1055 conn: &'a ConnectionRef, +1056 mut notify: Pin<&mut Notified<'a>>, +1057 dir: Dir, +1058) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> { +1059 let mut state = conn.lock_and_wake("poll_accept"); +1060 // Check for incoming streams before checking `state.error` so that already-received streams, +1061 // which are necessarily finite, can be drained from a closed connection. +1062 if let Some(id) = state.inner.streams().accept(dir) { +1063 let is_0rtt = state.inner.is_handshaking(); +1064 drop(state); // Release the lock (wake on drop) so clone can take it +1065 return Poll::Ready(Ok((conn.clone(), id, is_0rtt))); +1066 } else if let Some(ref e) = state.error { +1067 return Poll::Ready(Err(e.clone())); +1068 } +1069 loop { +1070 match notify.as_mut().poll(ctx) { +1071 // `state` lock ensures we didn't race with readiness +1072 Poll::Pending => return Poll::Pending, +1073 // Spurious wakeup, get a new future +1074 Poll::Ready(()) => notify.set(conn.shared.stream_incoming[dir as usize].notified()), +1075 } +1076 } +1077} +1078 +1079pin_project! { +1080 /// Future produced by [`Connection::read_datagram`] +1081 pub struct ReadDatagram<'a> { +1082 conn: &'a ConnectionRef, +1083 #[pin] +1084 notify: Notified<'a>, +1085 } +1086} +1087 +1088impl Future for ReadDatagram<'_> { +1089 type Output = Result<Bytes, ConnectionError>; +1090 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +1091 let mut this = self.project(); +1092 let mut state = this.conn.lock_without_waking("ReadDatagram::poll"); +1093 // Check for buffered datagrams before checking `state.error` so that already-received +1094 // datagrams, which are necessarily finite, can be drained from a closed connection. +1095 if let Some(x) = state.inner.datagrams().recv() { +1096 return Poll::Ready(Ok(x)); +1097 } else if let Some(ref e) = state.error { +1098 return Poll::Ready(Err(e.clone())); +1099 } +1100 loop { +1101 match this.notify.as_mut().poll(ctx) { +1102 // `state` lock ensures we didn't race with readiness +1103 Poll::Pending => return Poll::Pending, +1104 // Spurious wakeup, get a new future +1105 Poll::Ready(()) => this +1106 .notify +1107 .set(this.conn.shared.datagram_received.notified()), +1108 } +1109 } +1110 } +1111} +1112 +1113pin_project! { +1114 /// Future produced by [`Connection::send_datagram_wait`] +1115 pub struct SendDatagram<'a> { +1116 conn: &'a ConnectionRef, +1117 data: Option<Bytes>, +1118 #[pin] +1119 notify: Notified<'a>, +1120 } +1121} +1122 +1123impl Future for SendDatagram<'_> { +1124 type Output = Result<(), SendDatagramError>; +1125 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +1126 let mut this = self.project(); +1127 let mut state = this.conn.lock_and_wake("SendDatagram::poll"); +1128 if let Some(ref e) = state.error { +1129 return Poll::Ready(Err(SendDatagramError::ConnectionLost(e.clone()))); +1130 } +1131 use proto::SendDatagramError::*; +1132 match state +1133 .inner +1134 .datagrams() +1135 .send(this.data.take().unwrap(), false) +1136 { +1137 Ok(()) => Poll::Ready(Ok(())), +1138 Err(e) => Poll::Ready(Err(match e { +1139 Blocked(data) => { +1140 this.data.replace(data); +1141 loop { +1142 match this.notify.as_mut().poll(ctx) { +1143 Poll::Pending => return Poll::Pending, +1144 // Spurious wakeup, get a new future +1145 Poll::Ready(()) => this +1146 .notify +1147 .set(this.conn.shared.datagrams_unblocked.notified()), +1148 } +1149 } +1150 } +1151 UnsupportedByPeer => SendDatagramError::UnsupportedByPeer, +1152 Disabled => SendDatagramError::Disabled, +1153 TooLarge => SendDatagramError::TooLarge, +1154 })), 1155 } 1156 } 1157} 1158 -1159pin_project! { -1160 /// Future produced by [`Connection::send_datagram_wait`] -1161 pub struct SendDatagram<'a> { -1162 conn: &'a ConnectionRef, -1163 data: Option<Bytes>, -1164 #[pin] -1165 notify: Notified<'a>, -1166 } -1167} -1168 -1169impl Future for SendDatagram<'_> { -1170 type Output = Result<(), SendDatagramError>; -1171 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -1172 let mut this = self.project(); -1173 let mut state = this.conn.lock_and_wake("SendDatagram::poll"); -1174 if let Some(ref e) = state.error { -1175 return Poll::Ready(Err(SendDatagramError::ConnectionLost(e.clone()))); -1176 } -1177 use proto::SendDatagramError::*; -1178 match state -1179 .inner -1180 .datagrams() -1181 .send(this.data.take().unwrap(), false) -1182 { -1183 Ok(()) => Poll::Ready(Ok(())), -1184 Err(e) => Poll::Ready(Err(match e { -1185 Blocked(data) => { -1186 this.data.replace(data); -1187 loop { -1188 match this.notify.as_mut().poll(ctx) { -1189 Poll::Pending => return Poll::Pending, -1190 // Spurious wakeup, get a new future -1191 Poll::Ready(()) => this -1192 .notify -1193 .set(this.conn.shared.datagrams_unblocked.notified()), -1194 } -1195 } -1196 } -1197 UnsupportedByPeer => SendDatagramError::UnsupportedByPeer, -1198 Disabled => SendDatagramError::Disabled, -1199 TooLarge => SendDatagramError::TooLarge, -1200 })), -1201 } -1202 } -1203} -1204 -1205/// Future returned by [`Connection::on_closed`] -1206/// -1207/// Resolves to a tuple of ([`ConnectionError`], [`ConnectionStats`]). -1208pub struct OnClosed { -1209 rx: oneshot::Receiver<(ConnectionError, ConnectionStats)>, -1210 conn: WeakConnectionHandle, -1211} -1212 -1213impl Drop for OnClosed { -1214 fn drop(&mut self) { -1215 if self.rx.is_terminated() { -1216 return; -1217 }; -1218 if let Some(conn) = self.conn.upgrade() { -1219 self.rx.close(); -1220 conn.0 -1221 .lock_without_waking("OnClosed::drop") -1222 .on_closed -1223 .retain(|tx| !tx.is_closed()); -1224 } -1225 } -1226} -1227 -1228impl Future for OnClosed { -1229 type Output = (ConnectionError, ConnectionStats); -1230 -1231 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { -1232 let this = self.get_mut(); -1233 // The `expect` is safe because `State::drop` ensures that all senders are triggered -1234 // before being dropped. -1235 Pin::new(&mut this.rx) -1236 .poll(cx) -1237 .map(|x| x.expect("on_close sender is never dropped before sending")) -1238 } -1239} -1240 -1241#[derive(Debug)] -1242#[allow(clippy::redundant_allocation)] -1243pub(crate) struct ConnectionRef(Arc<Arc<ConnectionInner>>); -1244 -1245impl ConnectionRef { -1246 #[allow(clippy::redundant_allocation)] -1247 fn from_arc(inner: Arc<Arc<ConnectionInner>>) -> Self { -1248 inner.shared.ref_count.fetch_add(1, Ordering::Relaxed); -1249 Self(inner) -1250 } -1251 -1252 pub(crate) fn stable_id(&self) -> usize { -1253 &*self.0 as *const _ as usize -1254 } -1255 -1256 pub(crate) fn weak_handle(&self) -> WeakConnectionHandle { -1257 WeakConnectionHandle(Arc::downgrade(&self.0)) -1258 } -1259} -1260 -1261impl Clone for ConnectionRef { -1262 fn clone(&self) -> Self { -1263 Self::from_arc(Arc::clone(&self.0)) -1264 } -1265} -1266 -1267impl Drop for ConnectionRef { -1268 fn drop(&mut self) { -1269 if self.shared.ref_count.fetch_sub(1, Ordering::Relaxed) > 1 { -1270 return; -1271 } -1272 -1273 let conn = &mut *self.lock_without_waking("drop"); -1274 -1275 if !conn.inner.is_closed() { -1276 // If the driver is alive, it's just it and us, so we'd better shut it down. If it's -1277 // not, we can't do any harm. If there were any streams being opened, then either -1278 // the connection will be closed for an unrelated reason or a fresh reference will -1279 // be constructed for the newly opened stream. -1280 conn.implicit_close(&self.shared); -1281 } -1282 } -1283} -1284 -1285impl std::ops::Deref for ConnectionRef { -1286 type Target = ConnectionInner; -1287 fn deref(&self) -> &Self::Target { -1288 &self.0 -1289 } +1159/// Future returned by [`Connection::on_closed`] +1160/// +1161/// Resolves to a tuple of ([`ConnectionError`], [`ConnectionStats`]). +1162pub struct OnClosed { +1163 rx: oneshot::Receiver<(ConnectionError, ConnectionStats)>, +1164 conn: WeakConnectionHandle, +1165} +1166 +1167impl Drop for OnClosed { +1168 fn drop(&mut self) { +1169 if self.rx.is_terminated() { +1170 return; +1171 }; +1172 if let Some(conn) = self.conn.upgrade() { +1173 self.rx.close(); +1174 conn.0 +1175 .lock_without_waking("OnClosed::drop") +1176 .on_closed +1177 .retain(|tx| !tx.is_closed()); +1178 } +1179 } +1180} +1181 +1182impl Future for OnClosed { +1183 type Output = (ConnectionError, ConnectionStats); +1184 +1185 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { +1186 let this = self.get_mut(); +1187 // The `expect` is safe because `State::drop` ensures that all senders are triggered +1188 // before being dropped. +1189 Pin::new(&mut this.rx) +1190 .poll(cx) +1191 .map(|x| x.expect("on_close sender is never dropped before sending")) +1192 } +1193} +1194 +1195#[derive(Debug)] +1196#[allow(clippy::redundant_allocation)] +1197pub(crate) struct ConnectionRef(Arc<Arc<ConnectionInner>>); +1198 +1199impl ConnectionRef { +1200 #[allow(clippy::redundant_allocation)] +1201 fn from_arc(inner: Arc<Arc<ConnectionInner>>) -> Self { +1202 inner.shared.ref_count.fetch_add(1, Ordering::Relaxed); +1203 Self(inner) +1204 } +1205 +1206 pub(crate) fn stable_id(&self) -> usize { +1207 &*self.0 as *const _ as usize +1208 } +1209 +1210 pub(crate) fn weak_handle(&self) -> WeakConnectionHandle { +1211 WeakConnectionHandle(Arc::downgrade(&self.0)) +1212 } +1213} +1214 +1215impl Clone for ConnectionRef { +1216 fn clone(&self) -> Self { +1217 Self::from_arc(Arc::clone(&self.0)) +1218 } +1219} +1220 +1221impl Drop for ConnectionRef { +1222 fn drop(&mut self) { +1223 if self.shared.ref_count.fetch_sub(1, Ordering::Relaxed) > 1 { +1224 return; +1225 } +1226 +1227 let conn = &mut *self.lock_without_waking("drop"); +1228 +1229 if !conn.inner.is_closed() { +1230 // If the driver is alive, it's just it and us, so we'd better shut it down. If it's +1231 // not, we can't do any harm. If there were any streams being opened, then either +1232 // the connection will be closed for an unrelated reason or a fresh reference will +1233 // be constructed for the newly opened stream. +1234 conn.implicit_close(&self.shared); +1235 } +1236 } +1237} +1238 +1239impl std::ops::Deref for ConnectionRef { +1240 type Target = ConnectionInner; +1241 fn deref(&self) -> &Self::Target { +1242 &self.0 +1243 } +1244} +1245 +1246#[derive(Debug)] +1247pub(crate) struct ConnectionInner { +1248 /// Kept private intentionally, use [`Self::lock_and_wake`]. +1249 state: Mutex<State>, +1250 pub(crate) shared: Shared, +1251} +1252 +1253impl ConnectionInner { +1254 /// Lock the state and return a guard that wakes the connection driver on drop. +1255 /// +1256 /// Use this for operations that may queue frames. The wake ensures the driver sends queued frames. +1257 /// If that's not needed, use [`Self::lock_without_waking`]. +1258 pub(crate) fn lock_and_wake(&self, purpose: &'static str) -> WakeGuard<'_> { +1259 WakeGuard { +1260 guard: self.state.lock(purpose), +1261 wake: true, +1262 } +1263 } +1264 +1265 /// Lock the state and return a guard that unlocks once dropped. +1266 /// +1267 /// Use this for operations that don't require any action from the connection driver. +1268 /// Otherwise, use [`Self::lock_and_wake`] instead. +1269 pub(crate) fn lock_without_waking(&self, purpose: &'static str) -> WakeGuard<'_> { +1270 WakeGuard { +1271 guard: self.state.lock(purpose), +1272 wake: false, +1273 } +1274 } +1275} +1276 +1277/// [`MutexGuard`] wrapper that calls [`State::wake`] on drop. +1278#[derive(derive_more::Deref, derive_more::DerefMut)] +1279pub(crate) struct WakeGuard<'a> { +1280 #[deref] +1281 #[deref_mut] +1282 guard: MutexGuard<'a, State>, +1283 wake: bool, +1284} +1285 +1286impl WakeGuard<'_> { +1287 pub(crate) fn skip_waking(&mut self) { +1288 self.wake = false; +1289 } 1290} 1291 -1292#[derive(Debug)] -1293pub(crate) struct ConnectionInner { -1294 /// Kept private intentionally, use [`Self::lock_and_wake`]. -1295 state: Mutex<State>, -1296 pub(crate) shared: Shared, -1297} -1298 -1299impl ConnectionInner { -1300 /// Lock the state and return a guard that wakes the connection driver on drop. -1301 /// -1302 /// Use this for operations that may queue frames. The wake ensures the driver sends queued frames. -1303 /// If that's not needed, use [`Self::lock_without_waking`]. -1304 pub(crate) fn lock_and_wake(&self, purpose: &'static str) -> WakeGuard<'_> { -1305 WakeGuard { -1306 guard: self.state.lock(purpose), -1307 wake: true, -1308 } -1309 } -1310 -1311 /// Lock the state and return a guard that unlocks once dropped. -1312 /// -1313 /// Use this for operations that don't require any action from the connection driver. -1314 /// Otherwise, use [`Self::lock_and_wake`] instead. -1315 pub(crate) fn lock_without_waking(&self, purpose: &'static str) -> WakeGuard<'_> { -1316 WakeGuard { -1317 guard: self.state.lock(purpose), -1318 wake: false, -1319 } +1292impl Drop for WakeGuard<'_> { +1293 fn drop(&mut self) { +1294 if self.wake { +1295 self.guard.wake(); +1296 } +1297 } +1298} +1299 +1300/// A handle to some connection internals, use with care. +1301/// +1302/// This contains a weak reference to the connection so will not itself keep the connection +1303/// alive. +1304#[derive(Debug, Clone)] +1305pub struct WeakConnectionHandle(Weak<Arc<ConnectionInner>>); +1306 +1307impl WeakConnectionHandle { +1308 /// Returns `true` if the [`Connection`] associated with this handle is still alive. +1309 pub fn is_alive(&self) -> bool { +1310 self.0.upgrade().is_some() +1311 } +1312 +1313 /// Upgrade the handle to a full `Connection` +1314 pub fn upgrade(&self) -> Option<Connection> { +1315 self.upgrade_to_ref().map(Connection) +1316 } +1317 +1318 pub(crate) fn upgrade_to_ref(&self) -> Option<ConnectionRef> { +1319 self.0.upgrade().map(ConnectionRef::from_arc) 1320 } -1321} -1322 -1323/// [`MutexGuard`] wrapper that calls [`State::wake`] on drop. -1324#[derive(derive_more::Deref, derive_more::DerefMut)] -1325pub(crate) struct WakeGuard<'a> { -1326 #[deref] -1327 #[deref_mut] -1328 guard: MutexGuard<'a, State>, -1329 wake: bool, -1330} -1331 -1332impl WakeGuard<'_> { -1333 pub(crate) fn skip_waking(&mut self) { -1334 self.wake = false; -1335 } -1336} -1337 -1338impl Drop for WakeGuard<'_> { -1339 fn drop(&mut self) { -1340 if self.wake { -1341 self.guard.wake(); -1342 } -1343 } -1344} -1345 -1346/// A handle to some connection internals, use with care. -1347/// -1348/// This contains a weak reference to the connection so will not itself keep the connection -1349/// alive. -1350#[derive(Debug, Clone)] -1351pub struct WeakConnectionHandle(Weak<Arc<ConnectionInner>>); -1352 -1353impl WeakConnectionHandle { -1354 /// Returns `true` if the [`Connection`] associated with this handle is still alive. -1355 pub fn is_alive(&self) -> bool { -1356 self.0.upgrade().is_some() -1357 } -1358 -1359 /// Upgrade the handle to a full `Connection` -1360 pub fn upgrade(&self) -> Option<Connection> { -1361 self.upgrade_to_ref().map(Connection) -1362 } -1363 -1364 pub(crate) fn upgrade_to_ref(&self) -> Option<ConnectionRef> { -1365 self.0.upgrade().map(ConnectionRef::from_arc) -1366 } -1367 -1368 /// Returns `true` if the two [`WeakConnectionHandle`] point at the same connection. -1369 pub fn is_same_connection(&self, other: &Self) -> bool { -1370 self.0.ptr_eq(&other.0) -1371 } -1372} -1373 -1374#[derive(Debug, Default)] -1375pub(crate) struct Shared { -1376 handshake_confirmed: Notify, -1377 /// Notified when new streams may be locally initiated due to an increase in stream ID flow -1378 /// control budget -1379 stream_budget_available: [Notify; 2], -1380 /// Notified when the peer has initiated a new stream -1381 stream_incoming: [Notify; 2], -1382 datagram_received: Notify, -1383 datagrams_unblocked: Notify, -1384 closed: Notify, -1385 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver -1386 ref_count: AtomicUsize, -1387} -1388 -1389pub(crate) struct State { -1390 pub(crate) inner: proto::Connection, -1391 driver: Option<Waker>, -1392 handle: ConnectionHandle, -1393 on_handshake_data: Option<oneshot::Sender<()>>, -1394 on_connected: Option<oneshot::Sender<bool>>, -1395 connected: bool, -1396 handshake_confirmed: bool, -1397 timer: Option<Pin<Box<dyn AsyncTimer>>>, -1398 timer_deadline: Option<Instant>, -1399 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, -1400 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -1401 pub(crate) blocked_writers: FxHashMap<StreamId, Waker>, -1402 pub(crate) blocked_readers: FxHashMap<StreamId, Waker>, -1403 pub(crate) stopped: FxHashMap<StreamId, Arc<Notify>>, -1404 /// Always set to Some before the connection becomes drained -1405 pub(crate) error: Option<ConnectionError>, -1406 /// Tracks paths being opened -1407 open_path: FxHashMap<PathId, watch::Sender<Result<(), PathError>>>, -1408 /// Tracks reference counts for paths. -1409 /// -1410 /// I.e. how many [`Path`] and [`WeakPathHandle`] structs are alive for a path. -1411 /// -1412 /// [`WeakPathHandle`]: crate::path::WeakPathHandle -1413 pub(crate) path_refs: FxHashMap<PathId, usize>, -1414 /// Final path stats for discarded paths. -1415 /// -1416 /// We only insert entries if the discarded path has a non-zero reference count in [`Self::path_refs`]. -1417 /// When the last reference to a path is dropped via [`Self::decrement_path_refs`] its value is cleared. -1418 pub(crate) final_path_stats: FxHashMap<PathId, PathStats>, -1419 pub(crate) path_events: tokio::sync::broadcast::Sender<PathEvent>, -1420 sender: Pin<Box<dyn UdpSender>>, -1421 pub(crate) runtime: Arc<dyn Runtime>, -1422 send_buffer: Vec<u8>, -1423 /// We buffer a transmit when the underlying I/O would block -1424 buffered_transmit: Option<proto::Transmit>, -1425 /// Our last external address reported by the peer. When multipath is enabled, this will be the -1426 /// last report across all paths. -1427 pub(crate) observed_external_addr: watch::Sender<Option<SocketAddr>>, -1428 pub(crate) nat_traversal_updates: tokio::sync::broadcast::Sender<n0_nat_traversal::Event>, -1429 on_closed: Vec<oneshot::Sender<(ConnectionError, ConnectionStats)>>, -1430} +1321 +1322 /// Returns `true` if the two [`WeakConnectionHandle`] point at the same connection. +1323 pub fn is_same_connection(&self, other: &Self) -> bool { +1324 self.0.ptr_eq(&other.0) +1325 } +1326} +1327 +1328#[derive(Debug, Default)] +1329pub(crate) struct Shared { +1330 handshake_confirmed: Notify, +1331 /// Notified when new streams may be locally initiated due to an increase in stream ID flow +1332 /// control budget +1333 stream_budget_available: [Notify; 2], +1334 /// Notified when the peer has initiated a new stream +1335 stream_incoming: [Notify; 2], +1336 datagram_received: Notify, +1337 datagrams_unblocked: Notify, +1338 closed: Notify, +1339 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver +1340 ref_count: AtomicUsize, +1341} +1342 +1343pub(crate) struct State { +1344 pub(crate) inner: proto::Connection, +1345 driver: Option<Waker>, +1346 handle: ConnectionHandle, +1347 on_handshake_data: Option<oneshot::Sender<()>>, +1348 on_connected: Option<oneshot::Sender<bool>>, +1349 connected: bool, +1350 handshake_confirmed: bool, +1351 timer: Option<Pin<Box<dyn AsyncTimer>>>, +1352 timer_deadline: Option<Instant>, +1353 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, +1354 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +1355 pub(crate) blocked_writers: FxHashMap<StreamId, Waker>, +1356 pub(crate) blocked_readers: FxHashMap<StreamId, Waker>, +1357 pub(crate) stopped: FxHashMap<StreamId, Arc<Notify>>, +1358 /// Always set to Some before the connection becomes drained +1359 pub(crate) error: Option<ConnectionError>, +1360 /// Tracks paths being opened +1361 open_path: FxHashMap<PathId, watch::Sender<Result<(), PathError>>>, +1362 /// Tracks reference counts for paths. +1363 /// +1364 /// I.e. how many [`Path`] and [`WeakPathHandle`] structs are alive for a path. +1365 /// +1366 /// [`WeakPathHandle`]: crate::path::WeakPathHandle +1367 pub(crate) path_refs: FxHashMap<PathId, usize>, +1368 /// Final path stats for discarded paths. +1369 /// +1370 /// We only insert entries if the discarded path has a non-zero reference count in [`Self::path_refs`]. +1371 /// When the last reference to a path is dropped via [`Self::decrement_path_refs`] its value is cleared. +1372 pub(crate) final_path_stats: FxHashMap<PathId, PathStats>, +1373 pub(crate) path_events: tokio::sync::broadcast::Sender<PathEvent>, +1374 sender: Pin<Box<dyn UdpSender>>, +1375 pub(crate) runtime: Arc<dyn Runtime>, +1376 send_buffer: Vec<u8>, +1377 /// We buffer a transmit when the underlying I/O would block +1378 buffered_transmit: Option<proto::Transmit>, +1379 /// Our last external address reported by the peer. When multipath is enabled, this will be the +1380 /// last report across all paths. +1381 pub(crate) observed_external_addr: watch::Sender<Option<SocketAddr>>, +1382 pub(crate) nat_traversal_updates: tokio::sync::broadcast::Sender<n0_nat_traversal::Event>, +1383 on_closed: Vec<oneshot::Sender<(ConnectionError, ConnectionStats)>>, +1384} +1385 +1386impl State { +1387 #[allow(clippy::too_many_arguments)] +1388 fn new( +1389 inner: proto::Connection, +1390 handle: ConnectionHandle, +1391 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +1392 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, +1393 on_handshake_data: oneshot::Sender<()>, +1394 on_connected: oneshot::Sender<bool>, +1395 sender: Pin<Box<dyn UdpSender>>, +1396 runtime: Arc<dyn Runtime>, +1397 ) -> Self { +1398 Self { +1399 inner, +1400 driver: None, +1401 handle, +1402 on_handshake_data: Some(on_handshake_data), +1403 on_connected: Some(on_connected), +1404 connected: false, +1405 handshake_confirmed: false, +1406 timer: None, +1407 timer_deadline: None, +1408 conn_events, +1409 endpoint_events, +1410 blocked_writers: FxHashMap::default(), +1411 blocked_readers: FxHashMap::default(), +1412 stopped: FxHashMap::default(), +1413 open_path: FxHashMap::default(), +1414 error: None, +1415 sender, +1416 runtime, +1417 send_buffer: Vec::new(), +1418 buffered_transmit: None, +1419 path_events: tokio::sync::broadcast::channel(32).0, +1420 observed_external_addr: watch::Sender::new(None), +1421 nat_traversal_updates: tokio::sync::broadcast::channel(32).0, +1422 on_closed: Vec::new(), +1423 final_path_stats: Default::default(), +1424 path_refs: Default::default(), +1425 } +1426 } +1427 +1428 fn drive_transmit(&mut self, cx: &mut Context<'_>) -> io::Result<bool> { +1429 let now = self.runtime.now(); +1430 let mut transmits = 0; 1431 -1432impl State { -1433 #[allow(clippy::too_many_arguments)] -1434 fn new( -1435 inner: proto::Connection, -1436 handle: ConnectionHandle, -1437 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -1438 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, -1439 on_handshake_data: oneshot::Sender<()>, -1440 on_connected: oneshot::Sender<bool>, -1441 sender: Pin<Box<dyn UdpSender>>, -1442 runtime: Arc<dyn Runtime>, -1443 ) -> Self { -1444 Self { -1445 inner, -1446 driver: None, -1447 handle, -1448 on_handshake_data: Some(on_handshake_data), -1449 on_connected: Some(on_connected), -1450 connected: false, -1451 handshake_confirmed: false, -1452 timer: None, -1453 timer_deadline: None, -1454 conn_events, -1455 endpoint_events, -1456 blocked_writers: FxHashMap::default(), -1457 blocked_readers: FxHashMap::default(), -1458 stopped: FxHashMap::default(), -1459 open_path: FxHashMap::default(), -1460 error: None, -1461 sender, -1462 runtime, -1463 send_buffer: Vec::new(), -1464 buffered_transmit: None, -1465 path_events: tokio::sync::broadcast::channel(32).0, -1466 observed_external_addr: watch::Sender::new(None), -1467 nat_traversal_updates: tokio::sync::broadcast::channel(32).0, -1468 on_closed: Vec::new(), -1469 final_path_stats: Default::default(), -1470 path_refs: Default::default(), -1471 } -1472 } -1473 -1474 fn drive_transmit(&mut self, cx: &mut Context<'_>) -> io::Result<bool> { -1475 let now = self.runtime.now(); -1476 let mut transmits = 0; -1477 -1478 let max_datagrams = self -1479 .sender -1480 .max_transmit_segments() -1481 .min(MAX_TRANSMIT_SEGMENTS); -1482 -1483 loop { -1484 // Retry the last transmit, or get a new one. -1485 let t = match self.buffered_transmit.take() { -1486 Some(t) => t, -1487 None => { -1488 self.send_buffer.clear(); -1489 match self -1490 .inner -1491 .poll_transmit(now, max_datagrams, &mut self.send_buffer) -1492 { -1493 Some(t) => { -1494 transmits += match t.segment_size { -1495 None => 1, -1496 Some(s) => t.size.div_ceil(s), // round up -1497 }; -1498 t -1499 } -1500 None => break, -1501 } -1502 } -1503 }; -1504 -1505 let len = t.size; -1506 match self -1507 .sender -1508 .as_mut() -1509 .poll_send(&udp_transmit(&t, &self.send_buffer[..len]), cx) -1510 { -1511 Poll::Pending => { -1512 self.buffered_transmit = Some(t); -1513 return Ok(false); -1514 } -1515 Poll::Ready(Err(e)) => return Err(e), -1516 Poll::Ready(Ok(())) => {} -1517 } -1518 -1519 if transmits >= MAX_TRANSMIT_DATAGRAMS { -1520 // TODO: What isn't ideal here yet is that if we don't poll all -1521 // datagrams that could be sent we don't go into the `app_limited` -1522 // state and CWND continues to grow until we get here the next time. -1523 // See https://github.com/quinn-rs/quinn/issues/1126 -1524 return Ok(true); -1525 } -1526 } -1527 -1528 Ok(false) -1529 } -1530 -1531 fn forward_endpoint_events(&mut self) { -1532 while let Some(event) = self.inner.poll_endpoint_events() { -1533 // If the endpoint driver is gone, noop. -1534 let _ = self.endpoint_events.send((self.handle, event)); -1535 } -1536 } -1537 -1538 /// If this returns `Err`, the endpoint is dead, so the driver should exit immediately. -1539 fn process_conn_events( -1540 &mut self, -1541 shared: &Shared, -1542 cx: &mut Context<'_>, -1543 ) -> Result<(), ConnectionError> { -1544 loop { -1545 match self.conn_events.poll_recv(cx) { -1546 Poll::Ready(Some(ConnectionEvent::Rebind(sender))) => { -1547 self.sender = sender; -1548 self.inner.handle_network_change(None, self.runtime.now()); +1432 let max_datagrams = self +1433 .sender +1434 .max_transmit_segments() +1435 .min(MAX_TRANSMIT_SEGMENTS); +1436 +1437 loop { +1438 // Retry the last transmit, or get a new one. +1439 let t = match self.buffered_transmit.take() { +1440 Some(t) => t, +1441 None => { +1442 self.send_buffer.clear(); +1443 match self +1444 .inner +1445 .poll_transmit(now, max_datagrams, &mut self.send_buffer) +1446 { +1447 Some(t) => { +1448 transmits += match t.segment_size { +1449 None => 1, +1450 Some(s) => t.size.div_ceil(s), // round up +1451 }; +1452 t +1453 } +1454 None => break, +1455 } +1456 } +1457 }; +1458 +1459 let len = t.size; +1460 match self +1461 .sender +1462 .as_mut() +1463 .poll_send(&udp_transmit(&t, &self.send_buffer[..len]), cx) +1464 { +1465 Poll::Pending => { +1466 self.buffered_transmit = Some(t); +1467 return Ok(false); +1468 } +1469 Poll::Ready(Err(e)) => return Err(e), +1470 Poll::Ready(Ok(())) => {} +1471 } +1472 +1473 if transmits >= MAX_TRANSMIT_DATAGRAMS { +1474 // TODO: What isn't ideal here yet is that if we don't poll all +1475 // datagrams that could be sent we don't go into the `app_limited` +1476 // state and CWND continues to grow until we get here the next time. +1477 // See https://github.com/quinn-rs/quinn/issues/1126 +1478 return Ok(true); +1479 } +1480 } +1481 +1482 Ok(false) +1483 } +1484 +1485 fn forward_endpoint_events(&mut self) { +1486 while let Some(event) = self.inner.poll_endpoint_events() { +1487 // If the endpoint driver is gone, noop. +1488 let _ = self.endpoint_events.send((self.handle, event)); +1489 } +1490 } +1491 +1492 /// If this returns `Err`, the endpoint is dead, so the driver should exit immediately. +1493 fn process_conn_events( +1494 &mut self, +1495 shared: &Shared, +1496 cx: &mut Context<'_>, +1497 ) -> Result<(), ConnectionError> { +1498 loop { +1499 match self.conn_events.poll_recv(cx) { +1500 Poll::Ready(Some(ConnectionEvent::Rebind(sender))) => { +1501 self.sender = sender; +1502 self.inner.handle_network_change(None, self.runtime.now()); +1503 } +1504 Poll::Ready(Some(ConnectionEvent::LocalAddressChanged(hint))) => { +1505 self.inner +1506 .handle_network_change(hint.as_deref().map(|x| x as _), self.runtime.now()); +1507 } +1508 Poll::Ready(Some(ConnectionEvent::Proto(event))) => { +1509 self.inner.handle_event(event); +1510 } +1511 Poll::Ready(Some(ConnectionEvent::Close { reason, error_code })) => { +1512 self.close(error_code, reason, shared); +1513 } +1514 Poll::Ready(None) => { +1515 return Err(ConnectionError::TransportError(TransportError::new( +1516 TransportErrorCode::INTERNAL_ERROR, +1517 "endpoint driver future was dropped".to_string(), +1518 ))); +1519 } +1520 Poll::Pending => { +1521 return Ok(()); +1522 } +1523 } +1524 } +1525 } +1526 +1527 fn forward_app_events(&mut self, shared: &Shared) { +1528 while let Some(event) = self.inner.poll() { +1529 use proto::Event::*; +1530 match event { +1531 HandshakeDataReady => { +1532 if let Some(x) = self.on_handshake_data.take() { +1533 let _ = x.send(()); +1534 } +1535 } +1536 Connected => { +1537 self.connected = true; +1538 if let Some(x) = self.on_connected.take() { +1539 // We don't care if the on-connected future was dropped +1540 let _ = x.send(self.inner.accepted_0rtt()); +1541 } +1542 if self.inner.side().is_client() && !self.inner.accepted_0rtt() { +1543 // Wake up rejected 0-RTT streams so they can fail immediately with +1544 // `ZeroRttRejected` errors. +1545 wake_all(&mut self.blocked_writers); +1546 wake_all(&mut self.blocked_readers); +1547 wake_all_notify(&mut self.stopped); +1548 } 1549 } -1550 Poll::Ready(Some(ConnectionEvent::LocalAddressChanged(hint))) => { -1551 self.inner -1552 .handle_network_change(hint.as_deref().map(|x| x as _), self.runtime.now()); +1550 HandshakeConfirmed => { +1551 self.handshake_confirmed = true; +1552 shared.handshake_confirmed.notify_waiters(); 1553 } -1554 Poll::Ready(Some(ConnectionEvent::Proto(event))) => { -1555 self.inner.handle_event(event); +1554 ConnectionLost { reason } => { +1555 self.terminate(reason, shared); 1556 } -1557 Poll::Ready(Some(ConnectionEvent::Close { reason, error_code })) => { -1558 self.close(error_code, reason, shared); -1559 } -1560 Poll::Ready(None) => { -1561 return Err(ConnectionError::TransportError(TransportError::new( -1562 TransportErrorCode::INTERNAL_ERROR, -1563 "endpoint driver future was dropped".to_string(), -1564 ))); -1565 } -1566 Poll::Pending => { -1567 return Ok(()); -1568 } -1569 } -1570 } -1571 } -1572 -1573 fn forward_app_events(&mut self, shared: &Shared) { -1574 while let Some(event) = self.inner.poll() { -1575 use proto::Event::*; -1576 match event { -1577 HandshakeDataReady => { -1578 if let Some(x) = self.on_handshake_data.take() { -1579 let _ = x.send(()); -1580 } -1581 } -1582 Connected => { -1583 self.connected = true; -1584 if let Some(x) = self.on_connected.take() { -1585 // We don't care if the on-connected future was dropped -1586 let _ = x.send(self.inner.accepted_0rtt()); -1587 } -1588 if self.inner.side().is_client() && !self.inner.accepted_0rtt() { -1589 // Wake up rejected 0-RTT streams so they can fail immediately with -1590 // `ZeroRttRejected` errors. -1591 wake_all(&mut self.blocked_writers); -1592 wake_all(&mut self.blocked_readers); -1593 wake_all_notify(&mut self.stopped); -1594 } -1595 } -1596 HandshakeConfirmed => { -1597 self.handshake_confirmed = true; -1598 shared.handshake_confirmed.notify_waiters(); -1599 } -1600 ConnectionLost { reason } => { -1601 self.terminate(reason, shared); -1602 } -1603 Stream(StreamEvent::Writable { id }) => wake_stream(id, &mut self.blocked_writers), -1604 Stream(StreamEvent::Opened { dir: Dir::Uni }) => { -1605 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); -1606 } -1607 Stream(StreamEvent::Opened { dir: Dir::Bi }) => { -1608 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); -1609 } -1610 DatagramReceived => { -1611 shared.datagram_received.notify_waiters(); -1612 } -1613 DatagramsUnblocked => { -1614 shared.datagrams_unblocked.notify_waiters(); -1615 } -1616 Stream(StreamEvent::Readable { id }) => wake_stream(id, &mut self.blocked_readers), -1617 Stream(StreamEvent::Available { dir }) => { -1618 // Might mean any number of streams are ready, so we wake up everyone -1619 shared.stream_budget_available[dir as usize].notify_waiters(); -1620 } -1621 Stream(StreamEvent::Finished { id }) => wake_stream_notify(id, &mut self.stopped), -1622 Stream(StreamEvent::Stopped { id, .. }) => { -1623 wake_stream_notify(id, &mut self.stopped); -1624 wake_stream(id, &mut self.blocked_writers); -1625 } -1626 Path(ref evt @ PathEvent::ObservedAddr { addr: observed, .. }) => { -1627 self.path_events.send(evt.clone()).ok(); -1628 self.observed_external_addr.send_if_modified(|addr| { -1629 let old = addr.replace(observed); -1630 old != *addr -1631 }); -1632 } -1633 Path(ref evt @ PathEvent::Opened { id }) => { -1634 self.path_events.send(evt.clone()).ok(); -1635 if let Some(sender) = self.open_path.remove(&id) { -1636 sender.send_modify(|value| *value = Ok(())); -1637 } -1638 } -1639 Path(ref evt @ PathEvent::Discarded { id, ref path_stats }) => { -1640 if self.path_refs.contains_key(&id) { -1641 self.final_path_stats.insert(id, *path_stats.clone()); -1642 } -1643 self.path_events.send(evt.clone()).ok(); -1644 } -1645 Path(ref evt @ PathEvent::Abandoned { id, .. }) => { -1646 if let Some(sender) = self.open_path.remove(&id) { -1647 // We don't care for the reason why this path was closed here, because semantically -1648 // all close reasons for a path that has not yet been opened equals to `ValidationFailed`. -1649 // With the noq API, there is no way to application-close a not-yet-opened path, so -1650 // `ApplicationClosed` cannot occur. And all other variants will only occur for paths -1651 // that have already been opened. -1652 // The previous iteration of this code had another event `PathEvent::LocallyClosed` which -1653 // contained a `PathError`, but that was only ever set to `ValidationFailed`. -1654 let error = PathError::ValidationFailed; -1655 sender.send_modify(|value| *value = Err(error)); -1656 } -1657 // this will happen also for already opened paths -1658 self.path_events.send(evt.clone()).ok(); -1659 } -1660 Path(evt @ PathEvent::RemoteStatus { .. }) => { -1661 self.path_events.send(evt).ok(); -1662 } -1663 NatTraversal(update) => { -1664 self.nat_traversal_updates.send(update).ok(); -1665 } -1666 } -1667 } -1668 } -1669 -1670 fn drive_timer(&mut self, cx: &mut Context<'_>) -> bool { -1671 // Check whether we need to (re)set the timer. If so, we must poll again to ensure the -1672 // timer is registered with the runtime (and check whether it's already -1673 // expired). -1674 match self.inner.poll_timeout() { -1675 Some(deadline) => { -1676 if let Some(delay) = &mut self.timer { -1677 // There is no need to reset the tokio timer if the deadline -1678 // did not change -1679 if self -1680 .timer_deadline -1681 .map(|current_deadline| current_deadline != deadline) -1682 .unwrap_or(true) -1683 { -1684 delay.as_mut().reset(deadline); -1685 } -1686 } else { -1687 self.timer = Some(self.runtime.new_timer(deadline)); -1688 } -1689 // Store the actual expiration time of the timer -1690 self.timer_deadline = Some(deadline); -1691 } -1692 None => { -1693 self.timer_deadline = None; -1694 return false; -1695 } -1696 } -1697 -1698 if self.timer_deadline.is_none() { -1699 return false; -1700 } +1557 Stream(StreamEvent::Writable { id }) => wake_stream(id, &mut self.blocked_writers), +1558 Stream(StreamEvent::Opened { dir: Dir::Uni }) => { +1559 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); +1560 } +1561 Stream(StreamEvent::Opened { dir: Dir::Bi }) => { +1562 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); +1563 } +1564 DatagramReceived => { +1565 shared.datagram_received.notify_waiters(); +1566 } +1567 DatagramsUnblocked => { +1568 shared.datagrams_unblocked.notify_waiters(); +1569 } +1570 Stream(StreamEvent::Readable { id }) => wake_stream(id, &mut self.blocked_readers), +1571 Stream(StreamEvent::Available { dir }) => { +1572 // Might mean any number of streams are ready, so we wake up everyone +1573 shared.stream_budget_available[dir as usize].notify_waiters(); +1574 } +1575 Stream(StreamEvent::Finished { id }) => wake_stream_notify(id, &mut self.stopped), +1576 Stream(StreamEvent::Stopped { id, .. }) => { +1577 wake_stream_notify(id, &mut self.stopped); +1578 wake_stream(id, &mut self.blocked_writers); +1579 } +1580 Path(ref evt @ PathEvent::ObservedAddr { addr: observed, .. }) => { +1581 self.path_events.send(evt.clone()).ok(); +1582 self.observed_external_addr.send_if_modified(|addr| { +1583 let old = addr.replace(observed); +1584 old != *addr +1585 }); +1586 } +1587 Path(ref evt @ PathEvent::Opened { id }) => { +1588 self.path_events.send(evt.clone()).ok(); +1589 if let Some(sender) = self.open_path.remove(&id) { +1590 sender.send_modify(|value| *value = Ok(())); +1591 } +1592 } +1593 Path(ref evt @ PathEvent::Discarded { id, ref path_stats }) => { +1594 if self.path_refs.contains_key(&id) { +1595 self.final_path_stats.insert(id, *path_stats.clone()); +1596 } +1597 self.path_events.send(evt.clone()).ok(); +1598 } +1599 Path(ref evt @ PathEvent::Abandoned { id, .. }) => { +1600 if let Some(sender) = self.open_path.remove(&id) { +1601 // We don't care for the reason why this path was closed here, because semantically +1602 // all close reasons for a path that has not yet been opened equals to `ValidationFailed`. +1603 // With the noq API, there is no way to application-close a not-yet-opened path, so +1604 // `ApplicationClosed` cannot occur. And all other variants will only occur for paths +1605 // that have already been opened. +1606 // The previous iteration of this code had another event `PathEvent::LocallyClosed` which +1607 // contained a `PathError`, but that was only ever set to `ValidationFailed`. +1608 let error = PathError::ValidationFailed; +1609 sender.send_modify(|value| *value = Err(error)); +1610 } +1611 // this will happen also for already opened paths +1612 self.path_events.send(evt.clone()).ok(); +1613 } +1614 Path(evt @ PathEvent::RemoteStatus { .. }) => { +1615 self.path_events.send(evt).ok(); +1616 } +1617 NatTraversal(update) => { +1618 self.nat_traversal_updates.send(update).ok(); +1619 } +1620 } +1621 } +1622 } +1623 +1624 fn drive_timer(&mut self, cx: &mut Context<'_>) -> bool { +1625 // Check whether we need to (re)set the timer. If so, we must poll again to ensure the +1626 // timer is registered with the runtime (and check whether it's already +1627 // expired). +1628 match self.inner.poll_timeout() { +1629 Some(deadline) => { +1630 if let Some(delay) = &mut self.timer { +1631 // There is no need to reset the tokio timer if the deadline +1632 // did not change +1633 if self +1634 .timer_deadline +1635 .map(|current_deadline| current_deadline != deadline) +1636 .unwrap_or(true) +1637 { +1638 delay.as_mut().reset(deadline); +1639 } +1640 } else { +1641 self.timer = Some(self.runtime.new_timer(deadline)); +1642 } +1643 // Store the actual expiration time of the timer +1644 self.timer_deadline = Some(deadline); +1645 } +1646 None => { +1647 self.timer_deadline = None; +1648 return false; +1649 } +1650 } +1651 +1652 if self.timer_deadline.is_none() { +1653 return false; +1654 } +1655 +1656 let delay = self +1657 .timer +1658 .as_mut() +1659 .expect("timer must exist in this state") +1660 .as_mut(); +1661 if delay.poll(cx).is_pending() { +1662 // Since there wasn't a timeout event, there is nothing new +1663 // for the connection to do +1664 return false; +1665 } +1666 +1667 // A timer expired, so the caller needs to check for +1668 // new transmits, which might cause new timers to be set. +1669 self.inner.handle_timeout(self.runtime.now()); +1670 self.timer_deadline = None; +1671 true +1672 } +1673 +1674 /// Wake up a blocked `Driver` task to process I/O +1675 pub(crate) fn wake(&mut self) { +1676 if let Some(x) = self.driver.take() { +1677 x.wake(); +1678 } +1679 } +1680 +1681 /// Used to wake up all blocked futures when the connection becomes closed for any reason +1682 fn terminate(&mut self, reason: ConnectionError, shared: &Shared) { +1683 self.error = Some(reason.clone()); +1684 if let Some(x) = self.on_handshake_data.take() { +1685 let _ = x.send(()); +1686 } +1687 wake_all(&mut self.blocked_writers); +1688 wake_all(&mut self.blocked_readers); +1689 shared.stream_budget_available[Dir::Uni as usize].notify_waiters(); +1690 shared.stream_budget_available[Dir::Bi as usize].notify_waiters(); +1691 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); +1692 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); +1693 shared.datagram_received.notify_waiters(); +1694 shared.datagrams_unblocked.notify_waiters(); +1695 if let Some(x) = self.on_connected.take() { +1696 let _ = x.send(false); +1697 } +1698 shared.handshake_confirmed.notify_waiters(); +1699 wake_all_notify(&mut self.stopped); +1700 shared.closed.notify_waiters(); 1701 -1702 let delay = self -1703 .timer -1704 .as_mut() -1705 .expect("timer must exist in this state") -1706 .as_mut(); -1707 if delay.poll(cx).is_pending() { -1708 // Since there wasn't a timeout event, there is nothing new -1709 // for the connection to do -1710 return false; -1711 } -1712 -1713 // A timer expired, so the caller needs to check for -1714 // new transmits, which might cause new timers to be set. -1715 self.inner.handle_timeout(self.runtime.now()); -1716 self.timer_deadline = None; -1717 true -1718 } +1702 // Send to the registered on_closed futures. +1703 let stats = self.inner.stats(); +1704 for tx in self.on_closed.drain(..) { +1705 tx.send((reason.clone(), stats.clone())).ok(); +1706 } +1707 } +1708 +1709 fn close(&mut self, error_code: VarInt, reason: Bytes, shared: &Shared) { +1710 self.inner.close(self.runtime.now(), error_code, reason); +1711 self.terminate(ConnectionError::LocallyClosed, shared); +1712 self.wake(); +1713 } +1714 +1715 /// Close for a reason other than the application's explicit request +1716 pub(crate) fn implicit_close(&mut self, shared: &Shared) { +1717 self.close(0u32.into(), Bytes::new(), shared); +1718 } 1719 -1720 /// Wake up a blocked `Driver` task to process I/O -1721 pub(crate) fn wake(&mut self) { -1722 if let Some(x) = self.driver.take() { -1723 x.wake(); -1724 } -1725 } -1726 -1727 /// Used to wake up all blocked futures when the connection becomes closed for any reason -1728 fn terminate(&mut self, reason: ConnectionError, shared: &Shared) { -1729 self.error = Some(reason.clone()); -1730 if let Some(x) = self.on_handshake_data.take() { -1731 let _ = x.send(()); -1732 } -1733 wake_all(&mut self.blocked_writers); -1734 wake_all(&mut self.blocked_readers); -1735 shared.stream_budget_available[Dir::Uni as usize].notify_waiters(); -1736 shared.stream_budget_available[Dir::Bi as usize].notify_waiters(); -1737 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); -1738 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); -1739 shared.datagram_received.notify_waiters(); -1740 shared.datagrams_unblocked.notify_waiters(); -1741 if let Some(x) = self.on_connected.take() { -1742 let _ = x.send(false); -1743 } -1744 shared.handshake_confirmed.notify_waiters(); -1745 wake_all_notify(&mut self.stopped); -1746 shared.closed.notify_waiters(); -1747 -1748 // Send to the registered on_closed futures. -1749 let stats = self.inner.stats(); -1750 for tx in self.on_closed.drain(..) { -1751 tx.send((reason.clone(), stats.clone())).ok(); -1752 } -1753 } -1754 -1755 fn close(&mut self, error_code: VarInt, reason: Bytes, shared: &Shared) { -1756 self.inner.close(self.runtime.now(), error_code, reason); -1757 self.terminate(ConnectionError::LocallyClosed, shared); -1758 self.wake(); -1759 } -1760 -1761 /// Close for a reason other than the application's explicit request -1762 pub(crate) fn implicit_close(&mut self, shared: &Shared) { -1763 self.close(0u32.into(), Bytes::new(), shared); -1764 } -1765 -1766 pub(crate) fn check_0rtt(&self) -> Result<(), ()> { -1767 if self.inner.is_handshaking() -1768 || self.inner.accepted_0rtt() -1769 || self.inner.side().is_server() -1770 { -1771 Ok(()) -1772 } else { -1773 Err(()) -1774 } -1775 } -1776 -1777 /// Returns [`PathStats`] for a path, if available. -1778 /// -1779 /// This gets the stats from [`proto::Connection`]. If that returns `None` -1780 /// it gets them from `Self::final_path_stats` instead. -1781 pub(crate) fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { -1782 self.inner -1783 .path_stats(path_id) -1784 .or_else(|| self.final_path_stats.get(&path_id).copied()) -1785 } -1786 -1787 /// Increment the reference counter for a path in this connection. -1788 /// -1789 /// This counts how many [`Path`] or [`WeakPathHandle`] structs exist for a path. -1790 /// Currently this is used to determine whether to store the final stats after a path is -1791 /// abandoned. -1792 /// -1793 /// [`WeakPathHandle`]: crate::path::WeakPathHandle -1794 pub(crate) fn increment_path_refs(&mut self, path_id: PathId) { -1795 *self.path_refs.entry(path_id).or_default() += 1; -1796 } -1797 -1798 /// Decrement the reference counter for a path in this connection. -1799 pub(crate) fn decrement_path_refs(&mut self, path_id: PathId) { -1800 if let Some(refs) = self.path_refs.get_mut(&path_id) { -1801 *refs = refs.saturating_sub(1); -1802 if *refs == 0 { -1803 self.path_refs.remove(&path_id); -1804 self.final_path_stats.remove(&path_id); -1805 } -1806 } -1807 } -1808} -1809 -1810impl Drop for State { -1811 fn drop(&mut self) { -1812 if !self.inner.is_drained() { -1813 // Ensure the endpoint can tidy up -1814 let _ = self -1815 .endpoint_events -1816 .send((self.handle, proto::EndpointEvent::drained())); -1817 } -1818 -1819 if !self.on_closed.is_empty() { -1820 // Ensure that all on_closed oneshot senders are triggered before dropping. -1821 let reason = self.error.as_ref().expect("closed without error reason"); -1822 let stats = self.inner.stats(); -1823 for tx in self.on_closed.drain(..) { -1824 tx.send((reason.clone(), stats.clone())).ok(); -1825 } -1826 } -1827 } -1828} -1829 -1830impl fmt::Debug for State { -1831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -1832 f.debug_struct("State").field("inner", &self.inner).finish() -1833 } -1834} -1835 -1836fn wake_stream(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Waker>) { -1837 if let Some(waker) = wakers.remove(&stream_id) { -1838 waker.wake(); -1839 } -1840} -1841 -1842fn wake_all(wakers: &mut FxHashMap<StreamId, Waker>) { -1843 wakers.drain().for_each(|(_, waker)| waker.wake()) -1844} -1845 -1846fn wake_stream_notify(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { -1847 if let Some(notify) = wakers.remove(&stream_id) { -1848 notify.notify_waiters() -1849 } -1850} -1851 -1852fn wake_all_notify(wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { -1853 wakers -1854 .drain() -1855 .for_each(|(_, notify)| notify.notify_waiters()) -1856} -1857 -1858/// Errors that can arise when sending a datagram -1859#[derive(Debug, Error, Clone, Eq, PartialEq)] -1860pub enum SendDatagramError { -1861 /// The peer does not support receiving datagram frames -1862 #[error("datagrams not supported by peer")] -1863 UnsupportedByPeer, -1864 /// Datagram support is disabled locally -1865 #[error("datagram support disabled")] -1866 Disabled, -1867 /// The datagram is larger than the connection can currently accommodate -1868 /// -1869 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been -1870 /// exceeded. -1871 #[error("datagram too large")] -1872 TooLarge, -1873 /// The connection was lost -1874 #[error("connection lost")] -1875 ConnectionLost(#[from] ConnectionError), -1876} -1877 -1878/// The maximum amount of datagrams which will be produced in a single `drive_transmit` call -1879/// -1880/// This limits the amount of CPU resources consumed by datagram generation, -1881/// and allows other tasks (like receiving ACKs) to run in between. -1882const MAX_TRANSMIT_DATAGRAMS: usize = 20; -1883 -1884/// The maximum amount of datagrams that are sent in a single transmit -1885/// -1886/// This can be lower than the maximum platform capabilities, to avoid excessive -1887/// memory allocations when calling `poll_transmit()`. Benchmarks have shown -1888/// that numbers around 10 are a good compromise. -1889const MAX_TRANSMIT_SEGMENTS: NonZeroUsize = NonZeroUsize::new(10).expect("known");

\ No newline at end of file +1720 pub(crate) fn check_0rtt(&self) -> Result<(), ()> { +1721 if self.inner.is_handshaking() +1722 || self.inner.accepted_0rtt() +1723 || self.inner.side().is_server() +1724 { +1725 Ok(()) +1726 } else { +1727 Err(()) +1728 } +1729 } +1730 +1731 /// Returns [`PathStats`] for a path, if available. +1732 /// +1733 /// This gets the stats from [`proto::Connection`]. If that returns `None` +1734 /// it gets them from `Self::final_path_stats` instead. +1735 pub(crate) fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { +1736 self.inner +1737 .path_stats(path_id) +1738 .or_else(|| self.final_path_stats.get(&path_id).copied()) +1739 } +1740 +1741 /// Increment the reference counter for a path in this connection. +1742 /// +1743 /// This counts how many [`Path`] or [`WeakPathHandle`] structs exist for a path. +1744 /// Currently this is used to determine whether to store the final stats after a path is +1745 /// abandoned. +1746 /// +1747 /// [`WeakPathHandle`]: crate::path::WeakPathHandle +1748 pub(crate) fn increment_path_refs(&mut self, path_id: PathId) { +1749 *self.path_refs.entry(path_id).or_default() += 1; +1750 } +1751 +1752 /// Decrement the reference counter for a path in this connection. +1753 pub(crate) fn decrement_path_refs(&mut self, path_id: PathId) { +1754 if let Some(refs) = self.path_refs.get_mut(&path_id) { +1755 *refs = refs.saturating_sub(1); +1756 if *refs == 0 { +1757 self.path_refs.remove(&path_id); +1758 self.final_path_stats.remove(&path_id); +1759 } +1760 } +1761 } +1762} +1763 +1764impl Drop for State { +1765 fn drop(&mut self) { +1766 if !self.inner.is_drained() { +1767 // Ensure the endpoint can tidy up +1768 let _ = self +1769 .endpoint_events +1770 .send((self.handle, proto::EndpointEvent::drained())); +1771 } +1772 +1773 if !self.on_closed.is_empty() { +1774 // Ensure that all on_closed oneshot senders are triggered before dropping. +1775 let reason = self.error.as_ref().expect("closed without error reason"); +1776 let stats = self.inner.stats(); +1777 for tx in self.on_closed.drain(..) { +1778 tx.send((reason.clone(), stats.clone())).ok(); +1779 } +1780 } +1781 } +1782} +1783 +1784impl fmt::Debug for State { +1785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +1786 f.debug_struct("State").field("inner", &self.inner).finish() +1787 } +1788} +1789 +1790fn wake_stream(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Waker>) { +1791 if let Some(waker) = wakers.remove(&stream_id) { +1792 waker.wake(); +1793 } +1794} +1795 +1796fn wake_all(wakers: &mut FxHashMap<StreamId, Waker>) { +1797 wakers.drain().for_each(|(_, waker)| waker.wake()) +1798} +1799 +1800fn wake_stream_notify(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { +1801 if let Some(notify) = wakers.remove(&stream_id) { +1802 notify.notify_waiters() +1803 } +1804} +1805 +1806fn wake_all_notify(wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { +1807 wakers +1808 .drain() +1809 .for_each(|(_, notify)| notify.notify_waiters()) +1810} +1811 +1812/// Errors that can arise when sending a datagram +1813#[derive(Debug, Error, Clone, Eq, PartialEq)] +1814pub enum SendDatagramError { +1815 /// The peer does not support receiving datagram frames +1816 #[error("datagrams not supported by peer")] +1817 UnsupportedByPeer, +1818 /// Datagram support is disabled locally +1819 #[error("datagram support disabled")] +1820 Disabled, +1821 /// The datagram is larger than the connection can currently accommodate +1822 /// +1823 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been +1824 /// exceeded. +1825 #[error("datagram too large")] +1826 TooLarge, +1827 /// The connection was lost +1828 #[error("connection lost")] +1829 ConnectionLost(#[from] ConnectionError), +1830} +1831 +1832/// The maximum amount of datagrams which will be produced in a single `drive_transmit` call +1833/// +1834/// This limits the amount of CPU resources consumed by datagram generation, +1835/// and allows other tasks (like receiving ACKs) to run in between. +1836const MAX_TRANSMIT_DATAGRAMS: usize = 20; +1837 +1838/// The maximum amount of datagrams that are sent in a single transmit +1839/// +1840/// This can be lower than the maximum platform capabilities, to avoid excessive +1841/// memory allocations when calling `poll_transmit()`. Benchmarks have shown +1842/// that numbers around 10 are a good compromise. +1843const MAX_TRANSMIT_SEGMENTS: NonZeroUsize = NonZeroUsize::new(10).expect("known");

\ No newline at end of file diff --git a/pr/619/docs/src/noq/path.rs.html b/pr/619/docs/src/noq/path.rs.html index 51350e088..43cd32330 100644 --- a/pr/619/docs/src/noq/path.rs.html +++ b/pr/619/docs/src/noq/path.rs.html @@ -1,5 +1,5 @@ path.rs - source

noq/
path.rs

1use std::future::Future;
-2use std::net::SocketAddr;
+2use std::net::{IpAddr, SocketAddr};
 3use std::pin::Pin;
 4use std::sync::Arc;
 5use std::task::{Context, Poll, ready};
@@ -275,140 +275,149 @@
 275        Ok(state.inner.network_path(self.id)?.remote())
 276    }
 277
-278    /// Ping the remote endpoint over this path.
-279    pub fn ping(&self) -> Result<(), ClosedPath> {
-280        let mut state = self.conn.lock_and_wake("ping");
-281        state.inner.ping_path(self.id)
-282    }
-283}
-284
-285impl PartialEq for Path {
-286    fn eq(&self, other: &Self) -> bool {
-287        self.id == other.id && self.conn.stable_id() == other.conn.stable_id()
-288    }
-289}
-290
-291/// Weak handle for a [`Path`] that does not keep the connection alive.
-292///
-293/// As long as a [`WeakPathHandle`] for a path exists, that path's final stats will not be dropped even if
-294/// the path was abandoned.
-295///
-296/// The [`WeakPathHandle`] can be upgraded to a [`Path`] as long as its [`Connection`] has not been dropped.
-297///
-298/// [`Connection`]: crate::Connection
-299#[derive(Debug)]
-300pub struct WeakPathHandle {
-301    id: PathId,
-302    conn: WeakConnectionHandle,
-303}
-304
-305impl Clone for WeakPathHandle {
-306    fn clone(&self) -> Self {
-307        if let Some(conn) = self.conn.upgrade_to_ref() {
-308            conn.lock_without_waking("WeakPathHandle::clone")
-309                .increment_path_refs(self.id);
-310        }
-311        Self {
-312            id: self.id,
-313            conn: self.conn.clone(),
-314        }
-315    }
-316}
-317
-318impl PartialEq for WeakPathHandle {
-319    fn eq(&self, other: &Self) -> bool {
-320        self.id == other.id && self.conn.is_same_connection(&other.conn)
-321    }
-322}
-323
-324impl Eq for WeakPathHandle {}
-325
-326impl Drop for WeakPathHandle {
-327    fn drop(&mut self) {
-328        if let Some(conn) = self.conn.upgrade_to_ref() {
-329            conn.lock_without_waking("WeakPathHandle::drop")
-330                .decrement_path_refs(self.id);
-331        }
-332    }
-333}
+278    /// The local IP used for this path, if known.
+279    ///
+280    /// Returns `Ok(None)` for clients or when the platform does not expose this information; see
+281    /// [`noq_udp::RecvMeta::dst_ip`](udp::RecvMeta::dst_ip) for supported platforms.
+282    pub fn local_ip(&self) -> Result<Option<IpAddr>, ClosedPath> {
+283        let state = self.conn.lock_without_waking("per_path_local_ip");
+284        Ok(state.inner.network_path(self.id)?.local_ip())
+285    }
+286
+287    /// Ping the remote endpoint over this path.
+288    pub fn ping(&self) -> Result<(), ClosedPath> {
+289        let mut state = self.conn.lock_and_wake("ping");
+290        state.inner.ping_path(self.id)
+291    }
+292}
+293
+294impl PartialEq for Path {
+295    fn eq(&self, other: &Self) -> bool {
+296        self.id == other.id && self.conn.stable_id() == other.conn.stable_id()
+297    }
+298}
+299
+300/// Weak handle for a [`Path`] that does not keep the connection alive.
+301///
+302/// As long as a [`WeakPathHandle`] for a path exists, that path's final stats will not be dropped even if
+303/// the path was abandoned.
+304///
+305/// The [`WeakPathHandle`] can be upgraded to a [`Path`] as long as its [`Connection`] has not been dropped.
+306///
+307/// [`Connection`]: crate::Connection
+308#[derive(Debug)]
+309pub struct WeakPathHandle {
+310    id: PathId,
+311    conn: WeakConnectionHandle,
+312}
+313
+314impl Clone for WeakPathHandle {
+315    fn clone(&self) -> Self {
+316        if let Some(conn) = self.conn.upgrade_to_ref() {
+317            conn.lock_without_waking("WeakPathHandle::clone")
+318                .increment_path_refs(self.id);
+319        }
+320        Self {
+321            id: self.id,
+322            conn: self.conn.clone(),
+323        }
+324    }
+325}
+326
+327impl PartialEq for WeakPathHandle {
+328    fn eq(&self, other: &Self) -> bool {
+329        self.id == other.id && self.conn.is_same_connection(&other.conn)
+330    }
+331}
+332
+333impl Eq for WeakPathHandle {}
 334
-335impl WeakPathHandle {
-336    /// Returns the [`PathId`] of this path.
-337    pub fn id(&self) -> PathId {
-338        self.id
-339    }
-340
-341    /// Upgrades to a [`Path`].
-342    ///
-343    /// Returns `None` if the connection was dropped.
-344    pub fn upgrade(&self) -> Option<Path> {
-345        let conn = self.conn.upgrade_to_ref()?;
-346        Some(Path::new_unchecked(conn, self.id))
-347    }
-348}
+335impl Drop for WeakPathHandle {
+336    fn drop(&mut self) {
+337        if let Some(conn) = self.conn.upgrade_to_ref() {
+338            conn.lock_without_waking("WeakPathHandle::drop")
+339                .decrement_path_refs(self.id);
+340        }
+341    }
+342}
+343
+344impl WeakPathHandle {
+345    /// Returns the [`PathId`] of this path.
+346    pub fn id(&self) -> PathId {
+347        self.id
+348    }
 349
-350/// Stream produced by [`Path::observed_external_addr`]
-351///
-352/// This will always return the external address most recently reported by the remote over this
-353/// path. If the extension is not negotiated, this stream will never return.
-354// TODO(@divma): provide a way to check if the extension is negotiated.
-355pub struct AddressDiscovery {
-356    watcher: WatchStream<SocketAddr>,
+350    /// Upgrades to a [`Path`].
+351    ///
+352    /// Returns `None` if the connection was dropped.
+353    pub fn upgrade(&self) -> Option<Path> {
+354        let conn = self.conn.upgrade_to_ref()?;
+355        Some(Path::new_unchecked(conn, self.id))
+356    }
 357}
 358
-359impl AddressDiscovery {
-360    pub(super) fn new(
-361        path_id: PathId,
-362        mut path_events: tokio::sync::broadcast::Receiver<PathEvent>,
-363        initial_value: Option<SocketAddr>,
-364        runtime: Arc<dyn Runtime>,
-365    ) -> Self {
-366        let (tx, rx) = watch::channel(initial_value.unwrap_or_else(||
-367                // if the dummy value is used, it will be ignored
-368                SocketAddr::new([0, 0, 0, 0].into(), 0)));
-369        let filter = async move {
-370            loop {
-371                match path_events.recv().await {
-372                    Ok(PathEvent::ObservedAddr { id, addr: observed }) if id == path_id => {
-373                        tx.send_if_modified(|addr| {
-374                            let old = std::mem::replace(addr, observed);
-375                            old != *addr
-376                        });
-377                    }
-378                    Ok(PathEvent::Discarded { id, .. }) if id == path_id => {
-379                        // If the path is closed, terminate the stream
-380                        break;
-381                    }
-382                    Ok(_) => {
-383                        // ignore any other event
-384                    }
-385                    Err(_) => {
-386                        // A lagged error should never happen since this (detached) task is
-387                        // constantly reading from the channel. Therefore, if an error does happen,
-388                        // the stream can terminate
+359/// Stream produced by [`Path::observed_external_addr`]
+360///
+361/// This will always return the external address most recently reported by the remote over this
+362/// path. If the extension is not negotiated, this stream will never return.
+363// TODO(@divma): provide a way to check if the extension is negotiated.
+364pub struct AddressDiscovery {
+365    watcher: WatchStream<SocketAddr>,
+366}
+367
+368impl AddressDiscovery {
+369    pub(super) fn new(
+370        path_id: PathId,
+371        mut path_events: tokio::sync::broadcast::Receiver<PathEvent>,
+372        initial_value: Option<SocketAddr>,
+373        runtime: Arc<dyn Runtime>,
+374    ) -> Self {
+375        let (tx, rx) = watch::channel(initial_value.unwrap_or_else(||
+376                // if the dummy value is used, it will be ignored
+377                SocketAddr::new([0, 0, 0, 0].into(), 0)));
+378        let filter = async move {
+379            loop {
+380                match path_events.recv().await {
+381                    Ok(PathEvent::ObservedAddr { id, addr: observed }) if id == path_id => {
+382                        tx.send_if_modified(|addr| {
+383                            let old = std::mem::replace(addr, observed);
+384                            old != *addr
+385                        });
+386                    }
+387                    Ok(PathEvent::Discarded { id, .. }) if id == path_id => {
+388                        // If the path is closed, terminate the stream
 389                        break;
 390                    }
-391                }
-392            }
-393        };
-394
-395        let watcher = if initial_value.is_some() {
-396            WatchStream::new(rx)
-397        } else {
-398            WatchStream::from_changes(rx)
-399        };
-400
-401        runtime.spawn(Box::pin(filter));
-402        // TODO(@divma): check if there's a way to ensure the future ends. AbortHandle is not an
-403        // option
-404        Self { watcher }
-405    }
-406}
-407
-408impl Stream for AddressDiscovery {
-409    type Item = SocketAddr;
-410
-411    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
-412        Pin::new(&mut self.watcher).poll_next(cx)
-413    }
-414}
\ No newline at end of file +391 Ok(_) => { +392 // ignore any other event +393 } +394 Err(_) => { +395 // A lagged error should never happen since this (detached) task is +396 // constantly reading from the channel. Therefore, if an error does happen, +397 // the stream can terminate +398 break; +399 } +400 } +401 } +402 }; +403 +404 let watcher = if initial_value.is_some() { +405 WatchStream::new(rx) +406 } else { +407 WatchStream::from_changes(rx) +408 }; +409 +410 runtime.spawn(Box::pin(filter)); +411 // TODO(@divma): check if there's a way to ensure the future ends. AbortHandle is not an +412 // option +413 Self { watcher } +414 } +415} +416 +417impl Stream for AddressDiscovery { +418 type Item = SocketAddr; +419 +420 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { +421 Pin::new(&mut self.watcher).poll_next(cx) +422 } +423}
\ No newline at end of file diff --git a/pr/619/docs/src/noq_proto/connection/mod.rs.html b/pr/619/docs/src/noq_proto/connection/mod.rs.html index 1775feb2f..5da093c89 100644 --- a/pr/619/docs/src/noq_proto/connection/mod.rs.html +++ b/pr/619/docs/src/noq_proto/connection/mod.rs.html @@ -1367,6299 +1367,6314 @@ 1367 if last_packet_number.is_some() || congestion_blocked { 1368 self.qlog.emit_recovery_metrics( 1369 path_id, -1370 &mut self.paths.get_mut(&path_id).unwrap().data, -1371 now, -1372 ); -1373 } -1374 -1375 self.path_data_mut(path_id).app_limited = -1376 last_packet_number.is_none() && !congestion_blocked; -1377 -1378 match last_packet_number { -1379 Some(last_packet_number) => { -1380 // Note that when sending in multiple spaces the last packet number will be -1381 // the one from the highest space. -1382 self.path_data_mut(path_id).congestion.on_sent( -1383 now, -1384 transmit.len() as u64, -1385 last_packet_number, -1386 ); -1387 Some(self.build_transmit(path_id, transmit)) -1388 } -1389 None => None, -1390 } -1391 } -1392 -1393 /// poll_transmit logic for a QUIC-MULTIPATH packet number space (PathID + SpaceId). -1394 #[must_use] -1395 fn poll_transmit_path_space( -1396 &mut self, -1397 now: Instant, -1398 transmit: &mut TransmitBuf<'_>, -1399 path_id: PathId, -1400 space_id: SpaceId, -1401 remote_cid: ConnectionId, -1402 scheduling_info: &PathSchedulingInfo, -1403 // If we need to send a CONNECTION_CLOSE frame. -1404 connection_close_pending: bool, -1405 // Whether the current datagram needs to be padded to a certain size. -1406 mut pad_datagram: PadDatagram, -1407 ) -> PollPathSpaceStatus { -1408 // Keep track of the last packet number we wrote. If None we did not write any -1409 // packets. -1410 let mut last_packet_number = None; -1411 -1412 // Each loop of this may build one packet. It works logically as follows: -1413 // -1414 // - Check if something *needs* to be sent in this space and *can* be sent. -1415 // - If not, return to the caller who will call us again for the next space. -1416 // - Start a new datagram. -1417 // - Unless coalescing the packet into an existing datagram. -1418 // - Write the packet header and payload. -1419 // - Check if coalescing a next packet into the datagram is possible. -1420 // - If coalescing, finish packet without padding to leave space in the datagram. -1421 // - If not coalescing, complete the datagram: -1422 // - Finish packet with padding. -1423 // - Set the transmit segment size if this is the first datagram. -1424 // - Loop: next iteration will exit the loop if nothing more to send in this -1425 // space. The TransmitBuf will contain a started datagram with space if -1426 // coalescing, or completely filled datagram if not coalescing. -1427 loop { -1428 // Determine if anything can be sent in this packet number space. -1429 let max_packet_size = if transmit.datagram_remaining_mut() > 0 { -1430 // A datagram is started already, we are coalescing another packet into it. -1431 transmit.datagram_remaining_mut() -1432 } else { -1433 // A new datagram needs to be started. -1434 transmit.segment_size() -1435 }; -1436 let can_send = -1437 self.space_can_send(space_id, path_id, max_packet_size, connection_close_pending); -1438 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; -1439 let space_will_send = { -1440 if scheduling_info.is_abandoned { -1441 // If this path is abandoned then we might still have to send -1442 // PATH_ABANDON itself on it if there was no better space -1443 // available. Otherwise we want to send the PATH_ABANDON as permitted by -1444 // may_send_data however. -1445 scheduling_info.may_self_abandon -1446 && self.spaces[space_id] -1447 .pending -1448 .path_abandon -1449 .contains_key(&path_id) -1450 } else if can_send.close && scheduling_info.may_send_close { -1451 // This is the best path to send a CONNECTION_CLOSE on. -1452 true -1453 } else if needs_loss_probe || can_send.space_specific { -1454 // We always send a loss probe or space-specific frames if the path is -1455 // not abandoned. +1370 &mut self +1371 .paths +1372 .get_mut(&path_id) +1373 .expect("path_id was iterated from self.paths above") +1374 .data, +1375 now, +1376 ); +1377 } +1378 +1379 self.path_data_mut(path_id).app_limited = +1380 last_packet_number.is_none() && !congestion_blocked; +1381 +1382 match last_packet_number { +1383 Some(last_packet_number) => { +1384 // Note that when sending in multiple spaces the last packet number will be +1385 // the one from the highest space. +1386 self.path_data_mut(path_id).congestion.on_sent( +1387 now, +1388 transmit.len() as u64, +1389 last_packet_number, +1390 ); +1391 Some(self.build_transmit(path_id, transmit)) +1392 } +1393 None => None, +1394 } +1395 } +1396 +1397 /// poll_transmit logic for a QUIC-MULTIPATH packet number space (PathID + SpaceId). +1398 #[must_use] +1399 fn poll_transmit_path_space( +1400 &mut self, +1401 now: Instant, +1402 transmit: &mut TransmitBuf<'_>, +1403 path_id: PathId, +1404 space_id: SpaceId, +1405 remote_cid: ConnectionId, +1406 scheduling_info: &PathSchedulingInfo, +1407 // If we need to send a CONNECTION_CLOSE frame. +1408 connection_close_pending: bool, +1409 // Whether the current datagram needs to be padded to a certain size. +1410 mut pad_datagram: PadDatagram, +1411 ) -> PollPathSpaceStatus { +1412 // Keep track of the last packet number we wrote. If None we did not write any +1413 // packets. +1414 let mut last_packet_number = None; +1415 +1416 // Each loop of this may build one packet. It works logically as follows: +1417 // +1418 // - Check if something *needs* to be sent in this space and *can* be sent. +1419 // - If not, return to the caller who will call us again for the next space. +1420 // - Start a new datagram. +1421 // - Unless coalescing the packet into an existing datagram. +1422 // - Write the packet header and payload. +1423 // - Check if coalescing a next packet into the datagram is possible. +1424 // - If coalescing, finish packet without padding to leave space in the datagram. +1425 // - If not coalescing, complete the datagram: +1426 // - Finish packet with padding. +1427 // - Set the transmit segment size if this is the first datagram. +1428 // - Loop: next iteration will exit the loop if nothing more to send in this +1429 // space. The TransmitBuf will contain a started datagram with space if +1430 // coalescing, or completely filled datagram if not coalescing. +1431 loop { +1432 // Determine if anything can be sent in this packet number space. +1433 let max_packet_size = if transmit.datagram_remaining_mut() > 0 { +1434 // A datagram is started already, we are coalescing another packet into it. +1435 transmit.datagram_remaining_mut() +1436 } else { +1437 // A new datagram needs to be started. +1438 transmit.segment_size() +1439 }; +1440 let can_send = +1441 self.space_can_send(space_id, path_id, max_packet_size, connection_close_pending); +1442 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; +1443 let space_will_send = { +1444 if scheduling_info.is_abandoned { +1445 // If this path is abandoned then we might still have to send +1446 // PATH_ABANDON itself on it if there was no better space +1447 // available. Otherwise we want to send the PATH_ABANDON as permitted by +1448 // may_send_data however. +1449 scheduling_info.may_self_abandon +1450 && self.spaces[space_id] +1451 .pending +1452 .path_abandon +1453 .contains_key(&path_id) +1454 } else if can_send.close && scheduling_info.may_send_close { +1455 // This is the best path to send a CONNECTION_CLOSE on. 1456 true -1457 } else { -1458 // Anything else we only send if we're the best path for SpaceKind::Data -1459 // frames. -1460 !can_send.is_empty() && scheduling_info.may_send_data -1461 } -1462 }; -1463 -1464 if !space_will_send { -1465 // Nothing more to send. Previous iterations of this loop may have built -1466 // packets already. -1467 return match last_packet_number { -1468 Some(pn) => PollPathSpaceStatus::WrotePacket { -1469 last_packet_number: pn, -1470 pad_datagram, -1471 }, -1472 None => { -1473 // Only log for spaces which have crypto. -1474 if self.crypto_state.has_keys(space_id.encryption_level()) -1475 || (space_id == SpaceId::Data -1476 && self.crypto_state.has_keys(EncryptionLevel::ZeroRtt)) -1477 { -1478 trace!(?space_id, %path_id, "nothing to send in space"); -1479 } -1480 PollPathSpaceStatus::NothingToSend { -1481 congestion_blocked: false, -1482 } -1483 } -1484 }; -1485 } -1486 -1487 // We want to send on this space, check congestion control if we can. But only -1488 // if we will need to start a new datagram. If we are coalescing into an already -1489 // started datagram we do not need to check congestion control again. -1490 if transmit.datagram_remaining_mut() == 0 { -1491 let congestion_blocked = -1492 self.path_congestion_check(space_id, path_id, transmit, &can_send, now); -1493 if congestion_blocked != PathBlocked::No { -1494 // Previous iterations of this loop may have built packets already. -1495 return match last_packet_number { -1496 Some(pn) => PollPathSpaceStatus::WrotePacket { -1497 last_packet_number: pn, -1498 pad_datagram, -1499 }, -1500 None => { -1501 return PollPathSpaceStatus::NothingToSend { -1502 congestion_blocked: true, -1503 }; -1504 } -1505 }; -1506 } -1507 -1508 // If the datagram is full (or there never was one started), we need to start a -1509 // new one. -1510 if transmit.num_datagrams() >= transmit.max_datagrams().get() { -1511 // No more datagrams allowed. -1512 // Previous iterations of this loop may have built packets already. -1513 return match last_packet_number { -1514 Some(pn) => PollPathSpaceStatus::WrotePacket { -1515 last_packet_number: pn, -1516 pad_datagram, -1517 }, -1518 None => { -1519 return PollPathSpaceStatus::NothingToSend { -1520 congestion_blocked: false, -1521 }; -1522 } -1523 }; -1524 } -1525 -1526 if needs_loss_probe { -1527 // Ensure we have something to send for a tail-loss probe. -1528 let request_immediate_ack = -1529 space_id == SpaceId::Data && self.peer_supports_ack_frequency(); -1530 self.spaces[space_id].queue_tail_loss_probe( -1531 path_id, -1532 request_immediate_ack, -1533 &self.streams, -1534 ); -1535 -1536 self.spaces[space_id].for_path(path_id).loss_probes -= 1; // needs_loss_probe ensures loss_probes > 0 -1537 -1538 // Clamp the datagram to at most the minimum MTU to ensure that loss -1539 // probes can get through and enable recovery even if the path MTU -1540 // has shrank unexpectedly. -1541 transmit.start_new_datagram_with_size(std::cmp::min( -1542 usize::from(INITIAL_MTU), -1543 transmit.segment_size(), -1544 )); -1545 } else { -1546 transmit.start_new_datagram(); -1547 } -1548 trace!(count = transmit.num_datagrams(), "new datagram started"); -1549 -1550 // We started a new datagram, we decide later if it needs padding. -1551 pad_datagram = PadDatagram::No; -1552 } +1457 } else if needs_loss_probe || can_send.space_specific { +1458 // We always send a loss probe or space-specific frames if the path is +1459 // not abandoned. +1460 true +1461 } else { +1462 // Anything else we only send if we're the best path for SpaceKind::Data +1463 // frames. +1464 !can_send.is_empty() && scheduling_info.may_send_data +1465 } +1466 }; +1467 +1468 if !space_will_send { +1469 // Nothing more to send. Previous iterations of this loop may have built +1470 // packets already. +1471 return match last_packet_number { +1472 Some(pn) => PollPathSpaceStatus::WrotePacket { +1473 last_packet_number: pn, +1474 pad_datagram, +1475 }, +1476 None => { +1477 // Only log for spaces which have crypto. +1478 if self.crypto_state.has_keys(space_id.encryption_level()) +1479 || (space_id == SpaceId::Data +1480 && self.crypto_state.has_keys(EncryptionLevel::ZeroRtt)) +1481 { +1482 trace!(?space_id, %path_id, "nothing to send in space"); +1483 } +1484 PollPathSpaceStatus::NothingToSend { +1485 congestion_blocked: false, +1486 } +1487 } +1488 }; +1489 } +1490 +1491 // We want to send on this space, check congestion control if we can. But only +1492 // if we will need to start a new datagram. If we are coalescing into an already +1493 // started datagram we do not need to check congestion control again. +1494 if transmit.datagram_remaining_mut() == 0 { +1495 let congestion_blocked = +1496 self.path_congestion_check(space_id, path_id, transmit, &can_send, now); +1497 if congestion_blocked != PathBlocked::No { +1498 // Previous iterations of this loop may have built packets already. +1499 return match last_packet_number { +1500 Some(pn) => PollPathSpaceStatus::WrotePacket { +1501 last_packet_number: pn, +1502 pad_datagram, +1503 }, +1504 None => { +1505 return PollPathSpaceStatus::NothingToSend { +1506 congestion_blocked: true, +1507 }; +1508 } +1509 }; +1510 } +1511 +1512 // If the datagram is full (or there never was one started), we need to start a +1513 // new one. +1514 if transmit.num_datagrams() >= transmit.max_datagrams().get() { +1515 // No more datagrams allowed. +1516 // Previous iterations of this loop may have built packets already. +1517 return match last_packet_number { +1518 Some(pn) => PollPathSpaceStatus::WrotePacket { +1519 last_packet_number: pn, +1520 pad_datagram, +1521 }, +1522 None => { +1523 return PollPathSpaceStatus::NothingToSend { +1524 congestion_blocked: false, +1525 }; +1526 } +1527 }; +1528 } +1529 +1530 if needs_loss_probe { +1531 // Ensure we have something to send for a tail-loss probe. +1532 let request_immediate_ack = +1533 space_id == SpaceId::Data && self.peer_supports_ack_frequency(); +1534 self.spaces[space_id].queue_tail_loss_probe( +1535 path_id, +1536 request_immediate_ack, +1537 &self.streams, +1538 ); +1539 +1540 self.spaces[space_id].for_path(path_id).loss_probes -= 1; // needs_loss_probe ensures loss_probes > 0 +1541 +1542 // Clamp the datagram to at most the minimum MTU to ensure that loss +1543 // probes can get through and enable recovery even if the path MTU +1544 // has shrank unexpectedly. +1545 transmit.start_new_datagram_with_size(std::cmp::min( +1546 usize::from(INITIAL_MTU), +1547 transmit.segment_size(), +1548 )); +1549 } else { +1550 transmit.start_new_datagram(); +1551 } +1552 trace!(count = transmit.num_datagrams(), "new datagram started"); 1553 -1554 // If coalescing another packet into the existing datagram, there should -1555 // still be enough space for a whole packet. -1556 if transmit.datagram_start_offset() < transmit.len() { -1557 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE); -1558 } -1559 -1560 // -1561 // From here on, we've determined that a packet will definitely be sent. -1562 // +1554 // We started a new datagram, we decide later if it needs padding. +1555 pad_datagram = PadDatagram::No; +1556 } +1557 +1558 // If coalescing another packet into the existing datagram, there should +1559 // still be enough space for a whole packet. +1560 if transmit.datagram_start_offset() < transmit.len() { +1561 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE); +1562 } 1563 -1564 if self.crypto_state.has_keys(EncryptionLevel::Initial) -1565 && space_id == SpaceId::Handshake -1566 && self.side.is_client() -1567 { -1568 // A client stops both sending and processing Initial packets when it -1569 // sends its first Handshake packet. -1570 self.discard_space(now, SpaceKind::Initial); -1571 } -1572 if let Some(ref mut prev) = self.crypto_state.prev_crypto { -1573 prev.update_unacked = false; -1574 } -1575 -1576 let Some(mut builder) = -1577 PacketBuilder::new(now, space_id, path_id, remote_cid, transmit, self) -1578 else { -1579 // Confidentiality limit is exceeded and the connection has been killed. We -1580 // should not send any other packets. This works in a roundabout way: We -1581 // have started a datagram but not written anything into it. So even if we -1582 // get called again for another space we will see an already started -1583 // datagram and try and start another packet here. Then be stopped by the -1584 // same confidentiality limit. -1585 return PollPathSpaceStatus::NothingToSend { -1586 congestion_blocked: false, -1587 }; -1588 }; -1589 last_packet_number = Some(builder.packet_number); -1590 -1591 if space_id == SpaceId::Initial -1592 && (self.side.is_client() || can_send.is_ack_eliciting()) -1593 { -1594 // https://www.rfc-editor.org/rfc/rfc9000.html#section-14.1 -1595 pad_datagram |= PadDatagram::ToMinMtu; -1596 } -1597 if space_id == SpaceId::Data && self.config.pad_to_mtu { -1598 pad_datagram |= PadDatagram::ToSegmentSize; -1599 } -1600 -1601 if scheduling_info.may_send_close && can_send.close { -1602 trace!("sending CONNECTION_CLOSE"); -1603 // Encode ACKs before the ConnectionClose message, to give the receiver -1604 // a better approximate on what data has been processed. This is -1605 // especially important with ack delay, since the peer might not -1606 // have gotten any other ACK for the data earlier on. -1607 let is_multipath_negotiated = self.is_multipath_negotiated(); -1608 for path_id in self.spaces[space_id] -1609 .number_spaces -1610 .iter() -1611 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty()) -1612 .map(|(&path_id, _)| path_id) -1613 .collect::<Vec<_>>() -1614 { -1615 Self::populate_acks( -1616 now, -1617 self.receiving_ecn, -1618 path_id, -1619 space_id, -1620 &mut self.spaces[space_id], -1621 is_multipath_negotiated, -1622 &mut builder, -1623 &mut self.path_stats.for_path(path_id).frame_tx, -1624 self.crypto_state.has_keys(space_id.encryption_level()), -1625 ); -1626 } -1627 -1628 // Since there only 64 ACK frames there will always be enough space -1629 // to encode the ConnectionClose frame too. However we still have the -1630 // check here to prevent crashes if something changes. +1564 // +1565 // From here on, we've determined that a packet will definitely be sent. +1566 // +1567 +1568 if self.crypto_state.has_keys(EncryptionLevel::Initial) +1569 && space_id == SpaceId::Handshake +1570 && self.side.is_client() +1571 { +1572 // A client stops both sending and processing Initial packets when it +1573 // sends its first Handshake packet. +1574 self.discard_space(now, SpaceKind::Initial); +1575 } +1576 if let Some(ref mut prev) = self.crypto_state.prev_crypto { +1577 prev.update_unacked = false; +1578 } +1579 +1580 let Some(mut builder) = +1581 PacketBuilder::new(now, space_id, path_id, remote_cid, transmit, self) +1582 else { +1583 // Confidentiality limit is exceeded and the connection has been killed. We +1584 // should not send any other packets. This works in a roundabout way: We +1585 // have started a datagram but not written anything into it. So even if we +1586 // get called again for another space we will see an already started +1587 // datagram and try and start another packet here. Then be stopped by the +1588 // same confidentiality limit. +1589 return PollPathSpaceStatus::NothingToSend { +1590 congestion_blocked: false, +1591 }; +1592 }; +1593 last_packet_number = Some(builder.packet_number); +1594 +1595 if space_id == SpaceId::Initial +1596 && (self.side.is_client() || can_send.is_ack_eliciting()) +1597 { +1598 // https://www.rfc-editor.org/rfc/rfc9000.html#section-14.1 +1599 pad_datagram |= PadDatagram::ToMinMtu; +1600 } +1601 if space_id == SpaceId::Data && self.config.pad_to_mtu { +1602 pad_datagram |= PadDatagram::ToSegmentSize; +1603 } +1604 +1605 if scheduling_info.may_send_close && can_send.close { +1606 trace!("sending CONNECTION_CLOSE"); +1607 // Encode ACKs before the ConnectionClose message, to give the receiver +1608 // a better approximate on what data has been processed. This is +1609 // especially important with ack delay, since the peer might not +1610 // have gotten any other ACK for the data earlier on. +1611 let is_multipath_negotiated = self.is_multipath_negotiated(); +1612 for path_id in self.spaces[space_id] +1613 .number_spaces +1614 .iter() +1615 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty()) +1616 .map(|(&path_id, _)| path_id) +1617 .collect::<Vec<_>>() +1618 { +1619 Self::populate_acks( +1620 now, +1621 self.receiving_ecn, +1622 path_id, +1623 space_id, +1624 &mut self.spaces[space_id], +1625 is_multipath_negotiated, +1626 &mut builder, +1627 &mut self.path_stats.for_path(path_id).frame_tx, +1628 self.crypto_state.has_keys(space_id.encryption_level()), +1629 ); +1630 } 1631 -1632 // TODO(flub): This needs fixing for multipath, to ensure we can always -1633 // write the CONNECTION_CLOSE even if we have many PATH_ACKs to send: -1634 // https://github.com/n0-computer/noq/issues/367. -1635 debug_assert!( -1636 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND, -1637 "ACKs should leave space for ConnectionClose" -1638 ); -1639 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -1640 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() { -1641 let max_frame_size = builder.frame_space_remaining(); -1642 let close: Close = match self.state.as_type() { -1643 StateType::Closed => { -1644 let reason: Close = -1645 self.state.as_closed().expect("checked").clone().into(); -1646 if space_id == SpaceId::Data || reason.is_transport_layer() { -1647 reason -1648 } else { -1649 TransportError::APPLICATION_ERROR("").into() -1650 } -1651 } -1652 StateType::Draining => TransportError::NO_ERROR("").into(), -1653 _ => unreachable!( -1654 "tried to make a close packet when the connection wasn't closed" -1655 ), -1656 }; -1657 builder.write_frame(close.encoder(max_frame_size), stats); -1658 } -1659 let last_pn = builder.packet_number; -1660 builder.finish_and_track(now, self, path_id, pad_datagram); -1661 if space_id.kind() == self.highest_space { -1662 // Don't send another close packet. Even with multipath we only send -1663 // CONNECTION_CLOSE on a single path since we expect our paths to work. -1664 self.connection_close_pending = false; -1665 } -1666 // Send a close frame in every possible space for robustness, per -1667 // RFC9000 "Immediate Close during the Handshake". Don't bother trying -1668 // to send anything else. -1669 // TODO(flub): This breaks during the handshake if we can not coalesce -1670 // packets due to space reasons: the next space would either fail a -1671 // debug_assert checking for enough packet space or produce an invalid -1672 // packet. We need to keep track of per-space pending CONNECTION_CLOSE to -1673 // be able to send these across multiple calls to poll_transmit. Then -1674 // check for coalescing space here because initial packets need to be in -1675 // padded datagrams. And also add space checks for CONNECTION_CLOSE in -1676 // space_can_send so it would stop a GSO batch if the datagram is too -1677 // small for another CONNECTION_CLOSE packet. -1678 return PollPathSpaceStatus::WrotePacket { -1679 last_packet_number: last_pn, -1680 pad_datagram, -1681 }; -1682 } -1683 -1684 self.populate_packet(now, space_id, path_id, scheduling_info, &mut builder); -1685 -1686 // ACK-only packets should only be sent when explicitly allowed. If we write them due to -1687 // any other reason, there is a bug which leads to one component announcing write -1688 // readiness while not writing any data. This degrades performance. The condition is -1689 // only checked if the full MTU is available and when potentially large fixed-size -1690 // frames aren't queued, so that lack of space in the datagram isn't the reason for just -1691 // writing ACKs. -1692 debug_assert!( -1693 !(builder.sent_frames().is_ack_only(&self.streams) -1694 && !can_send.acks -1695 && (can_send.other || can_send.space_specific) -1696 && builder.buf.segment_size() -1697 == self.path_data(path_id).current_mtu() as usize -1698 && self.datagrams.outgoing.is_empty()), -1699 "SendableFrames was {can_send:?}, but only ACKs have been written" -1700 ); -1701 if builder.sent_frames().requires_padding { -1702 pad_datagram |= PadDatagram::ToMinMtu; -1703 } -1704 -1705 for (path_id, _pn) in builder.sent_frames().largest_acked.iter() { -1706 self.spaces[space_id] -1707 .for_path(*path_id) -1708 .pending_acks -1709 .acks_sent(); -1710 self.timers.stop( -1711 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), -1712 self.qlog.with_time(now), -1713 ); -1714 } -1715 -1716 // Now we need to finish the packet. Before we do so we need to know if we will -1717 // be coalescing the next packet into this one, or will be ending the datagram -1718 // as well. Because if this is the last packet in the datagram more padding -1719 // might be needed because of the packet type, or to fill the GSO segment size. -1720 -1721 // Are we allowed to coalesce AND is there enough space for another *packet* in -1722 // this datagram AND will we definitely send another packet? -1723 if builder.can_coalesce && path_id == PathId::ZERO && { -1724 let max_packet_size = builder -1725 .buf -1726 .datagram_remaining_mut() -1727 .saturating_sub(builder.predict_packet_end()); -1728 max_packet_size > MIN_PACKET_SPACE -1729 && self.has_pending_packet(space_id, max_packet_size, connection_close_pending) -1730 } { -1731 // We can append/coalesce the next packet into the current -1732 // datagram. Finish the current packet without adding extra padding. -1733 trace!("will coalesce with next packet"); -1734 builder.finish_and_track(now, self, path_id, PadDatagram::No); -1735 } else { -1736 // We need a new datagram for the next packet. Finish the current -1737 // packet with padding. -1738 // TODO(flub): if there isn't any more data to be sent, this will still pad -1739 // to the segment size and only discover there is nothing to send before -1740 // starting the next packet. That is wasting up to 32 bytes. -1741 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) { -1742 // If too many padding bytes would be required to continue the -1743 // GSO batch after this packet, end the GSO batch here. Ensures -1744 // that fixed-size frames with heterogeneous sizes -1745 // (e.g. application datagrams) won't inadvertently waste large -1746 // amounts of bandwidth. The exact threshold is a bit arbitrary -1747 // and might benefit from further tuning, though there's no -1748 // universally optimal value. -1749 const MAX_PADDING: usize = 32; -1750 if builder.buf.datagram_remaining_mut() -1751 > builder.predict_packet_end() + MAX_PADDING -1752 { -1753 trace!( -1754 "GSO truncated by demand for {} padding bytes", -1755 builder.buf.datagram_remaining_mut() - builder.predict_packet_end() -1756 ); -1757 let last_pn = builder.packet_number; -1758 builder.finish_and_track(now, self, path_id, PadDatagram::No); -1759 return PollPathSpaceStatus::Send { -1760 last_packet_number: last_pn, -1761 }; -1762 } -1763 -1764 // Pad the current datagram to GSO segment size so it can be -1765 // included in the GSO batch. -1766 builder.finish_and_track(now, self, path_id, PadDatagram::ToSegmentSize); -1767 } else { -1768 builder.finish_and_track(now, self, path_id, pad_datagram); -1769 } -1770 -1771 // If this is the first datagram we set the segment size to the size of the -1772 // first datagram. -1773 if transmit.num_datagrams() == 1 { -1774 transmit.clip_segment_size(); -1775 } -1776 } -1777 } -1778 } -1779 -1780 fn poll_transmit_mtu_probe( -1781 &mut self, -1782 now: Instant, -1783 buf: &mut Vec<u8>, -1784 path_id: PathId, -1785 ) -> Option<Transmit> { -1786 let (active_cid, probe_size) = self.get_mtu_probe_data(now, path_id)?; -1787 -1788 // We are definitely sending a DPLPMTUD probe. -1789 let mut transmit = TransmitBuf::new(buf, NonZeroUsize::MIN, probe_size as usize); -1790 transmit.start_new_datagram_with_size(probe_size as usize); +1632 // Since there only 64 ACK frames there will always be enough space +1633 // to encode the ConnectionClose frame too. However we still have the +1634 // check here to prevent crashes if something changes. +1635 +1636 // TODO(flub): This needs fixing for multipath, to ensure we can always +1637 // write the CONNECTION_CLOSE even if we have many PATH_ACKs to send: +1638 // https://github.com/n0-computer/noq/issues/367. +1639 debug_assert!( +1640 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND, +1641 "ACKs should leave space for ConnectionClose" +1642 ); +1643 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +1644 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() { +1645 let max_frame_size = builder.frame_space_remaining(); +1646 let close: Close = match self.state.as_type() { +1647 StateType::Closed => { +1648 let reason: Close = +1649 self.state.as_closed().expect("checked").clone().into(); +1650 if space_id == SpaceId::Data || reason.is_transport_layer() { +1651 reason +1652 } else { +1653 TransportError::APPLICATION_ERROR("").into() +1654 } +1655 } +1656 StateType::Draining => TransportError::NO_ERROR("").into(), +1657 _ => unreachable!( +1658 "tried to make a close packet when the connection wasn't closed" +1659 ), +1660 }; +1661 builder.write_frame(close.encoder(max_frame_size), stats); +1662 } +1663 let last_pn = builder.packet_number; +1664 builder.finish_and_track(now, self, path_id, pad_datagram); +1665 if space_id.kind() == self.highest_space { +1666 // Don't send another close packet. Even with multipath we only send +1667 // CONNECTION_CLOSE on a single path since we expect our paths to work. +1668 self.connection_close_pending = false; +1669 } +1670 // Send a close frame in every possible space for robustness, per +1671 // RFC9000 "Immediate Close during the Handshake". Don't bother trying +1672 // to send anything else. +1673 // TODO(flub): This breaks during the handshake if we can not coalesce +1674 // packets due to space reasons: the next space would either fail a +1675 // debug_assert checking for enough packet space or produce an invalid +1676 // packet. We need to keep track of per-space pending CONNECTION_CLOSE to +1677 // be able to send these across multiple calls to poll_transmit. Then +1678 // check for coalescing space here because initial packets need to be in +1679 // padded datagrams. And also add space checks for CONNECTION_CLOSE in +1680 // space_can_send so it would stop a GSO batch if the datagram is too +1681 // small for another CONNECTION_CLOSE packet. +1682 return PollPathSpaceStatus::WrotePacket { +1683 last_packet_number: last_pn, +1684 pad_datagram, +1685 }; +1686 } +1687 +1688 self.populate_packet(now, space_id, path_id, scheduling_info, &mut builder); +1689 +1690 // ACK-only packets should only be sent when explicitly allowed. If we write them due to +1691 // any other reason, there is a bug which leads to one component announcing write +1692 // readiness while not writing any data. This degrades performance. The condition is +1693 // only checked if the full MTU is available and when potentially large fixed-size +1694 // frames aren't queued, so that lack of space in the datagram isn't the reason for just +1695 // writing ACKs. +1696 debug_assert!( +1697 !(builder.sent_frames().is_ack_only(&self.streams) +1698 && !can_send.acks +1699 && (can_send.other || can_send.space_specific) +1700 && builder.buf.segment_size() +1701 == self.path_data(path_id).current_mtu() as usize +1702 && self.datagrams.outgoing.is_empty()), +1703 "SendableFrames was {can_send:?}, but only ACKs have been written" +1704 ); +1705 if builder.sent_frames().requires_padding { +1706 pad_datagram |= PadDatagram::ToMinMtu; +1707 } +1708 +1709 for (path_id, _pn) in builder.sent_frames().largest_acked.iter() { +1710 self.spaces[space_id] +1711 .for_path(*path_id) +1712 .pending_acks +1713 .acks_sent(); +1714 self.timers.stop( +1715 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), +1716 self.qlog.with_time(now), +1717 ); +1718 } +1719 +1720 // Now we need to finish the packet. Before we do so we need to know if we will +1721 // be coalescing the next packet into this one, or will be ending the datagram +1722 // as well. Because if this is the last packet in the datagram more padding +1723 // might be needed because of the packet type, or to fill the GSO segment size. +1724 +1725 // Are we allowed to coalesce AND is there enough space for another *packet* in +1726 // this datagram AND will we definitely send another packet? +1727 if builder.can_coalesce && path_id == PathId::ZERO && { +1728 let max_packet_size = builder +1729 .buf +1730 .datagram_remaining_mut() +1731 .saturating_sub(builder.predict_packet_end()); +1732 max_packet_size > MIN_PACKET_SPACE +1733 && self.has_pending_packet(space_id, max_packet_size, connection_close_pending) +1734 } { +1735 // We can append/coalesce the next packet into the current +1736 // datagram. Finish the current packet without adding extra padding. +1737 trace!("will coalesce with next packet"); +1738 builder.finish_and_track(now, self, path_id, PadDatagram::No); +1739 } else { +1740 // We need a new datagram for the next packet. Finish the current +1741 // packet with padding. +1742 // TODO(flub): if there isn't any more data to be sent, this will still pad +1743 // to the segment size and only discover there is nothing to send before +1744 // starting the next packet. That is wasting up to 32 bytes. +1745 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) { +1746 // If too many padding bytes would be required to continue the +1747 // GSO batch after this packet, end the GSO batch here. Ensures +1748 // that fixed-size frames with heterogeneous sizes +1749 // (e.g. application datagrams) won't inadvertently waste large +1750 // amounts of bandwidth. The exact threshold is a bit arbitrary +1751 // and might benefit from further tuning, though there's no +1752 // universally optimal value. +1753 const MAX_PADDING: usize = 32; +1754 if builder.buf.datagram_remaining_mut() +1755 > builder.predict_packet_end() + MAX_PADDING +1756 { +1757 trace!( +1758 "GSO truncated by demand for {} padding bytes", +1759 builder.buf.datagram_remaining_mut() - builder.predict_packet_end() +1760 ); +1761 let last_pn = builder.packet_number; +1762 builder.finish_and_track(now, self, path_id, PadDatagram::No); +1763 return PollPathSpaceStatus::Send { +1764 last_packet_number: last_pn, +1765 }; +1766 } +1767 +1768 // Pad the current datagram to GSO segment size so it can be +1769 // included in the GSO batch. +1770 builder.finish_and_track(now, self, path_id, PadDatagram::ToSegmentSize); +1771 } else { +1772 builder.finish_and_track(now, self, path_id, pad_datagram); +1773 } +1774 +1775 // If this is the first datagram we set the segment size to the size of the +1776 // first datagram. +1777 if transmit.num_datagrams() == 1 { +1778 transmit.clip_segment_size(); +1779 } +1780 } +1781 } +1782 } +1783 +1784 fn poll_transmit_mtu_probe( +1785 &mut self, +1786 now: Instant, +1787 buf: &mut Vec<u8>, +1788 path_id: PathId, +1789 ) -> Option<Transmit> { +1790 let (active_cid, probe_size) = self.get_mtu_probe_data(now, path_id)?; 1791 -1792 let mut builder = -1793 PacketBuilder::new(now, SpaceId::Data, path_id, active_cid, &mut transmit, self)?; -1794 -1795 // We implement MTU probes as ping packets padded up to the probe size -1796 trace!(?probe_size, "writing MTUD probe"); -1797 builder.write_frame(frame::Ping, &mut self.path_stats.for_path(path_id).frame_tx); +1792 // We are definitely sending a DPLPMTUD probe. +1793 let mut transmit = TransmitBuf::new(buf, NonZeroUsize::MIN, probe_size as usize); +1794 transmit.start_new_datagram_with_size(probe_size as usize); +1795 +1796 let mut builder = +1797 PacketBuilder::new(now, SpaceId::Data, path_id, active_cid, &mut transmit, self)?; 1798 -1799 // If supported by the peer, we want no delays to the probe's ACK -1800 if self.peer_supports_ack_frequency() { -1801 builder.write_frame( -1802 frame::ImmediateAck, -1803 &mut self.path_stats.for_path(path_id).frame_tx, -1804 ); -1805 } -1806 -1807 builder.finish_and_track(now, self, path_id, PadDatagram::ToSize(probe_size)); -1808 -1809 self.path_stats.for_path(path_id).sent_plpmtud_probes += 1; +1799 // We implement MTU probes as ping packets padded up to the probe size +1800 trace!(?probe_size, "writing MTUD probe"); +1801 builder.write_frame(frame::Ping, &mut self.path_stats.for_path(path_id).frame_tx); +1802 +1803 // If supported by the peer, we want no delays to the probe's ACK +1804 if self.peer_supports_ack_frequency() { +1805 builder.write_frame( +1806 frame::ImmediateAck, +1807 &mut self.path_stats.for_path(path_id).frame_tx, +1808 ); +1809 } 1810 -1811 Some(self.build_transmit(path_id, transmit)) -1812 } -1813 -1814 /// Returns the CID and probe size if a DPLPMTUD probe is needed. -1815 /// -1816 /// We MTU probe all paths for which all of the following is true: -1817 /// - We have an active destination CID for the path. -1818 /// - The remote address *and* path are validated. -1819 /// - The path is not abandoned. -1820 /// - The MTU Discovery subsystem wants to probe the path. -1821 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> { -1822 let active_cid = self.remote_cids.get(&path_id).map(CidQueue::active)?; -1823 let is_eligible = self.path_data(path_id).validated -1824 && !self.path_data(path_id).is_validating_path() -1825 && !self.abandoned_paths.contains(&path_id); -1826 -1827 if !is_eligible { -1828 return None; -1829 } -1830 let next_pn = self.spaces[SpaceId::Data] -1831 .for_path(path_id) -1832 .peek_tx_number(); -1833 let probe_size = self -1834 .path_data_mut(path_id) -1835 .mtud -1836 .poll_transmit(now, next_pn)?; -1837 -1838 Some((active_cid, probe_size)) -1839 } -1840 -1841 /// Returns true if there is a further packet to send on [`PathId::ZERO`]. -1842 /// -1843 /// In other words this is predicting whether the next call to -1844 /// [`Connection::space_can_send`] issued will return some frames to be sent. Including -1845 /// having to predict which packet number space it will be invoked with. This depends on -1846 /// how both [`Connection::poll_transmit_on_path`] and -1847 /// [`Connection::poll_transmit_path_space`] behave. -1848 /// -1849 /// This is needed to determine if packet coalescing can happen. Because the last packet -1850 /// in a datagram may need to be padded and thus we must know if another packet will -1851 /// follow or not. +1811 builder.finish_and_track(now, self, path_id, PadDatagram::ToSize(probe_size)); +1812 +1813 self.path_stats.for_path(path_id).sent_plpmtud_probes += 1; +1814 +1815 Some(self.build_transmit(path_id, transmit)) +1816 } +1817 +1818 /// Returns the CID and probe size if a DPLPMTUD probe is needed. +1819 /// +1820 /// We MTU probe all paths for which all of the following is true: +1821 /// - We have an active destination CID for the path. +1822 /// - The remote address *and* path are validated. +1823 /// - The path is not abandoned. +1824 /// - The MTU Discovery subsystem wants to probe the path. +1825 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> { +1826 let active_cid = self.remote_cids.get(&path_id).map(CidQueue::active)?; +1827 let is_eligible = self.path_data(path_id).validated +1828 && !self.path_data(path_id).is_validating_path() +1829 && !self.abandoned_paths.contains(&path_id); +1830 +1831 if !is_eligible { +1832 return None; +1833 } +1834 let next_pn = self.spaces[SpaceId::Data] +1835 .for_path(path_id) +1836 .peek_tx_number(); +1837 let probe_size = self +1838 .path_data_mut(path_id) +1839 .mtud +1840 .poll_transmit(now, next_pn)?; +1841 +1842 Some((active_cid, probe_size)) +1843 } +1844 +1845 /// Returns true if there is a further packet to send on [`PathId::ZERO`]. +1846 /// +1847 /// In other words this is predicting whether the next call to +1848 /// [`Connection::space_can_send`] issued will return some frames to be sent. Including +1849 /// having to predict which packet number space it will be invoked with. This depends on +1850 /// how both [`Connection::poll_transmit_on_path`] and +1851 /// [`Connection::poll_transmit_path_space`] behave. 1852 /// -1853 /// The next packet can be either in the same space, or in one of the following spaces -1854 /// on the same path. Because a 0-RTT packet can be coalesced with a 1-RTT packet and -1855 /// both are in the Data(PathId::ZERO) space. Previous spaces are not checked, because -1856 /// packets are built from Initial to Handshake to Data spaces. -1857 fn has_pending_packet( -1858 &mut self, -1859 current_space_id: SpaceId, -1860 max_packet_size: usize, -1861 connection_close_pending: bool, -1862 ) -> bool { -1863 let mut space_id = current_space_id; -1864 loop { -1865 let can_send = self.space_can_send( -1866 space_id, -1867 PathId::ZERO, -1868 max_packet_size, -1869 connection_close_pending, -1870 ); -1871 if !can_send.is_empty() { -1872 return true; -1873 } -1874 match space_id.next() { -1875 Some(next_space_id) => space_id = next_space_id, -1876 None => break, +1853 /// This is needed to determine if packet coalescing can happen. Because the last packet +1854 /// in a datagram may need to be padded and thus we must know if another packet will +1855 /// follow or not. +1856 /// +1857 /// The next packet can be either in the same space, or in one of the following spaces +1858 /// on the same path. Because a 0-RTT packet can be coalesced with a 1-RTT packet and +1859 /// both are in the Data(PathId::ZERO) space. Previous spaces are not checked, because +1860 /// packets are built from Initial to Handshake to Data spaces. +1861 fn has_pending_packet( +1862 &mut self, +1863 current_space_id: SpaceId, +1864 max_packet_size: usize, +1865 connection_close_pending: bool, +1866 ) -> bool { +1867 let mut space_id = current_space_id; +1868 loop { +1869 let can_send = self.space_can_send( +1870 space_id, +1871 PathId::ZERO, +1872 max_packet_size, +1873 connection_close_pending, +1874 ); +1875 if !can_send.is_empty() { +1876 return true; 1877 } -1878 } -1879 false -1880 } -1881 -1882 /// Checks if creating a new datagram would be blocked by congestion control -1883 fn path_congestion_check( -1884 &mut self, -1885 space_id: SpaceId, -1886 path_id: PathId, -1887 transmit: &TransmitBuf<'_>, -1888 can_send: &SendableFrames, -1889 now: Instant, -1890 ) -> PathBlocked { -1891 // Anti-amplification is only based on `total_sent`, which gets updated after -1892 // the transmit is sent. Therefore we pass the amount of bytes for datagrams -1893 // that are already created, as well as 1 byte for starting another datagram. If -1894 // there is any anti-amplification budget left, we always allow a full MTU to be -1895 // sent (see https://github.com/quinn-rs/quinn/issues/1082). -1896 if self.side().is_server() -1897 && self -1898 .path_data(path_id) -1899 .anti_amplification_blocked(transmit.len() as u64 + 1) -1900 { -1901 trace!(?space_id, %path_id, "blocked by anti-amplification"); -1902 return PathBlocked::AntiAmplification; -1903 } -1904 -1905 // Congestion control check. -1906 // Tail loss probes must not be blocked by congestion, or a deadlock could arise. -1907 let bytes_to_send = transmit.segment_size() as u64; -1908 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; -1909 -1910 if can_send.other && !need_loss_probe && !can_send.close { -1911 let path = self.path_data(path_id); -1912 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() { -1913 trace!( -1914 ?space_id, -1915 %path_id, -1916 in_flight=%path.in_flight.bytes, -1917 congestion_window=%path.congestion.window(), -1918 "blocked by congestion control", -1919 ); -1920 return PathBlocked::Congestion; -1921 } -1922 } -1923 -1924 // Pacing check. -1925 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) { -1926 let resume_time = now + delay; -1927 self.timers.set( -1928 Timer::PerPath(path_id, PathTimer::Pacing), -1929 resume_time, -1930 self.qlog.with_time(now), -1931 ); -1932 // Loss probes and CONNECTION_CLOSE should be subject to pacing, even though -1933 // they are not congestion controlled. -1934 trace!(?space_id, %path_id, ?delay, "blocked by pacing"); -1935 return PathBlocked::Pacing; -1936 } -1937 -1938 PathBlocked::No -1939 } -1940 -1941 /// Send PATH_CHALLENGE for a previous path if necessary -1942 /// -1943 /// QUIC-TRANSPORT section 9.3.3 -1944 /// <https://www.rfc-editor.org/rfc/rfc9000.html#name-off-path-packet-forwarding> -1945 fn send_prev_path_challenge( -1946 &mut self, -1947 now: Instant, -1948 buf: &mut Vec<u8>, -1949 path_id: PathId, -1950 ) -> Option<Transmit> { -1951 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?; -1952 if !prev_path.pending_on_path_challenge { -1953 return None; -1954 }; -1955 prev_path.pending_on_path_challenge = false; -1956 let token = self.rng.random(); -1957 let network_path = prev_path.network_path; -1958 prev_path.record_path_challenge_sent(now, token, network_path); -1959 -1960 debug_assert_eq!( -1961 self.highest_space, -1962 SpaceKind::Data, -1963 "PATH_CHALLENGE queued without 1-RTT keys" -1964 ); -1965 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); -1966 buf.start_new_datagram(); -1967 -1968 // Use the previous CID to avoid linking the new path with the previous path. We -1969 // don't bother accounting for possible retirement of that prev_cid because this is -1970 // sent once, immediately after migration, when the CID is known to be valid. Even -1971 // if a post-migration packet caused the CID to be retired, it's fair to pretend -1972 // this is sent first. -1973 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, *prev_cid, buf, self)?; -1974 let challenge = frame::PathChallenge(token); -1975 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -1976 builder.write_frame_with_log_msg(challenge, stats, Some("validating previous path")); -1977 -1978 // An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame -1979 // to at least the smallest allowed maximum datagram size of 1200 bytes, -1980 // unless the anti-amplification limit for the path does not permit -1981 // sending a datagram of this size -1982 builder.pad_to(MIN_INITIAL_SIZE); -1983 -1984 builder.finish(self, now); -1985 self.path_stats -1986 .for_path(path_id) -1987 .udp_tx -1988 .on_sent(1, buf.len()); -1989 -1990 trace!( -1991 dst = ?network_path.remote, -1992 src = ?network_path.local_ip, -1993 len = buf.len(), -1994 "sending prev_path off-path challenge", -1995 ); -1996 Some(Transmit { -1997 destination: network_path.remote, -1998 size: buf.len(), -1999 ecn: None, -2000 segment_size: None, -2001 src_ip: network_path.local_ip, -2002 }) -2003 } -2004 -2005 fn send_off_path_path_response( -2006 &mut self, -2007 now: Instant, -2008 buf: &mut Vec<u8>, -2009 path_id: PathId, -2010 ) -> Option<Transmit> { -2011 let path = self.paths.get_mut(&path_id).map(|state| &mut state.data)?; -2012 let cid_queue = self.remote_cids.get_mut(&path_id)?; -2013 let (token, network_path) = path.path_responses.pop_off_path(path.network_path)?; -2014 -2015 // TODO: make off-path probes unlinkable. -2016 let cid = cid_queue.active(); -2017 -2018 let frame = frame::PathResponse(token); -2019 -2020 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); -2021 buf.start_new_datagram(); -2022 -2023 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, buf, self)?; -2024 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -2025 builder.write_frame_with_log_msg(frame, stats, Some("(off-path)")); +1878 match space_id.next() { +1879 Some(next_space_id) => space_id = next_space_id, +1880 None => break, +1881 } +1882 } +1883 false +1884 } +1885 +1886 /// Checks if creating a new datagram would be blocked by congestion control +1887 fn path_congestion_check( +1888 &mut self, +1889 space_id: SpaceId, +1890 path_id: PathId, +1891 transmit: &TransmitBuf<'_>, +1892 can_send: &SendableFrames, +1893 now: Instant, +1894 ) -> PathBlocked { +1895 // Anti-amplification is only based on `total_sent`, which gets updated after +1896 // the transmit is sent. Therefore we pass the amount of bytes for datagrams +1897 // that are already created, as well as 1 byte for starting another datagram. If +1898 // there is any anti-amplification budget left, we always allow a full MTU to be +1899 // sent (see https://github.com/quinn-rs/quinn/issues/1082). +1900 if self.side().is_server() +1901 && self +1902 .path_data(path_id) +1903 .anti_amplification_blocked(transmit.len() as u64 + 1) +1904 { +1905 trace!(?space_id, %path_id, "blocked by anti-amplification"); +1906 return PathBlocked::AntiAmplification; +1907 } +1908 +1909 // Congestion control check. +1910 // Tail loss probes must not be blocked by congestion, or a deadlock could arise. +1911 let bytes_to_send = transmit.segment_size() as u64; +1912 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; +1913 +1914 if can_send.other && !need_loss_probe && !can_send.close { +1915 let path = self.path_data(path_id); +1916 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() { +1917 trace!( +1918 ?space_id, +1919 %path_id, +1920 in_flight=%path.in_flight.bytes, +1921 congestion_window=%path.congestion.window(), +1922 "blocked by congestion control", +1923 ); +1924 return PathBlocked::Congestion; +1925 } +1926 } +1927 +1928 // Pacing check. +1929 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) { +1930 let resume_time = now + delay; +1931 self.timers.set( +1932 Timer::PerPath(path_id, PathTimer::Pacing), +1933 resume_time, +1934 self.qlog.with_time(now), +1935 ); +1936 // Loss probes and CONNECTION_CLOSE should be subject to pacing, even though +1937 // they are not congestion controlled. +1938 trace!(?space_id, %path_id, ?delay, "blocked by pacing"); +1939 return PathBlocked::Pacing; +1940 } +1941 +1942 PathBlocked::No +1943 } +1944 +1945 /// Send PATH_CHALLENGE for a previous path if necessary +1946 /// +1947 /// QUIC-TRANSPORT section 9.3.3 +1948 /// <https://www.rfc-editor.org/rfc/rfc9000.html#name-off-path-packet-forwarding> +1949 fn send_prev_path_challenge( +1950 &mut self, +1951 now: Instant, +1952 buf: &mut Vec<u8>, +1953 path_id: PathId, +1954 ) -> Option<Transmit> { +1955 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?; +1956 if !prev_path.pending_on_path_challenge { +1957 return None; +1958 }; +1959 prev_path.pending_on_path_challenge = false; +1960 let token = self.rng.random(); +1961 let network_path = prev_path.network_path; +1962 prev_path.record_path_challenge_sent(now, token, network_path); +1963 +1964 debug_assert_eq!( +1965 self.highest_space, +1966 SpaceKind::Data, +1967 "PATH_CHALLENGE queued without 1-RTT keys" +1968 ); +1969 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); +1970 buf.start_new_datagram(); +1971 +1972 // Use the previous CID to avoid linking the new path with the previous path. We +1973 // don't bother accounting for possible retirement of that prev_cid because this is +1974 // sent once, immediately after migration, when the CID is known to be valid. Even +1975 // if a post-migration packet caused the CID to be retired, it's fair to pretend +1976 // this is sent first. +1977 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, *prev_cid, buf, self)?; +1978 let challenge = frame::PathChallenge(token); +1979 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +1980 builder.write_frame_with_log_msg(challenge, stats, Some("validating previous path")); +1981 +1982 // An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame +1983 // to at least the smallest allowed maximum datagram size of 1200 bytes, +1984 // unless the anti-amplification limit for the path does not permit +1985 // sending a datagram of this size +1986 builder.pad_to(MIN_INITIAL_SIZE); +1987 +1988 builder.finish(self, now); +1989 self.path_stats +1990 .for_path(path_id) +1991 .udp_tx +1992 .on_sent(1, buf.len()); +1993 +1994 trace!( +1995 dst = ?network_path.remote, +1996 src = ?network_path.local_ip, +1997 len = buf.len(), +1998 "sending prev_path off-path challenge", +1999 ); +2000 Some(Transmit { +2001 destination: network_path.remote, +2002 size: buf.len(), +2003 ecn: None, +2004 segment_size: None, +2005 src_ip: network_path.local_ip, +2006 }) +2007 } +2008 +2009 fn send_off_path_path_response( +2010 &mut self, +2011 now: Instant, +2012 buf: &mut Vec<u8>, +2013 path_id: PathId, +2014 ) -> Option<Transmit> { +2015 let path = self.paths.get_mut(&path_id).map(|state| &mut state.data)?; +2016 let cid_queue = self.remote_cids.get_mut(&path_id)?; +2017 let (token, network_path) = path.path_responses.pop_off_path(path.network_path)?; +2018 +2019 // TODO: make off-path probes unlinkable. +2020 let cid = cid_queue.active(); +2021 +2022 let frame = frame::PathResponse(token); +2023 +2024 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); +2025 buf.start_new_datagram(); 2026 -2027 // If we are a client doing NAT traversal, always include a PATH_CHALLENGE with any -2028 // off-path PATH_RESPONSE. No need to schedule any retries for this, if NAT -2029 // traversal is taking place then this remote is already is being probed with -2030 // retries, this only speeds up a successful traversal. -2031 if self -2032 .find_validated_path_on_network_path(network_path) -2033 .is_none() -2034 && self.n0_nat_traversal.client_side().is_ok() -2035 { -2036 let token = self.rng.random(); -2037 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -2038 builder.write_frame(frame::PathChallenge(token), stats); -2039 let ip_port = (network_path.remote.ip(), network_path.remote.port()); -2040 self.n0_nat_traversal.mark_probe_sent(ip_port, token); -2041 } -2042 -2043 // Off-path: not tracked in congestion control. The packet is sent to a -2044 // different destination than path_id's network path. -2045 builder.pad_to(MIN_INITIAL_SIZE); -2046 builder.finish(self, now); -2047 -2048 let size = buf.len(); -2049 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size); -2050 -2051 trace!( -2052 dst = ?network_path.remote, -2053 src = ?network_path.local_ip, -2054 len = buf.len(), -2055 "sending off-path PATH_RESPONSE", -2056 ); -2057 Some(Transmit { -2058 destination: network_path.remote, -2059 size, -2060 ecn: None, -2061 segment_size: None, -2062 src_ip: network_path.local_ip, -2063 }) -2064 } -2065 -2066 /// Send a nat traversal challenge (off-path) on this path if possible. -2067 fn send_nat_traversal_path_challenge( -2068 &mut self, -2069 now: Instant, -2070 buf: &mut Vec<u8>, -2071 path_id: PathId, -2072 ) -> Option<Transmit> { -2073 let remote = self.n0_nat_traversal.next_probe_addr()?; -2074 -2075 if !self.paths.get(&path_id)?.data.validated { -2076 // Path is not usable for probing -2077 return None; -2078 } -2079 -2080 // TODO: Using the active CID here makes the paths linkable. This is a violation of -2081 // RFC9000 but something we want to accept in the short term. Eventually we aim -2082 // to fix up the supply of CIDs sufficiently so that we can keep paths unlinkable -2083 // again. -2084 let Some(cid) = self -2085 .remote_cids -2086 .get(&path_id) -2087 .map(|cid_queue| cid_queue.active()) -2088 else { -2089 trace!(%path_id, "Not sending NAT traversal probe for path with no CIDs"); -2090 return None; -2091 }; -2092 let token = self.rng.random(); -2093 -2094 let frame = frame::PathChallenge(token); -2095 -2096 let mut buf = TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); -2097 buf.start_new_datagram(); -2098 -2099 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, &mut buf, self)?; -2100 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -2101 builder.write_frame_with_log_msg(frame, stats, Some("(nat-traversal)")); -2102 // Off-path: not tracked in congestion control. The packet is sent to a -2103 // different destination than path_id's network path. -2104 builder.finish(self, now); -2105 -2106 // Mark as sent after packet build succeeds. -2107 self.n0_nat_traversal -2108 .mark_probe_sent((remote.ip(), remote.port()), token); +2027 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, buf, self)?; +2028 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +2029 builder.write_frame_with_log_msg(frame, stats, Some("(off-path)")); +2030 +2031 // If we are a client doing NAT traversal, always include a PATH_CHALLENGE with any +2032 // off-path PATH_RESPONSE. No need to schedule any retries for this, if NAT +2033 // traversal is taking place then this remote already is being probed with +2034 // retries, this only speeds up a successful traversal. +2035 if self +2036 .find_validated_path_on_network_path(network_path) +2037 .is_none() +2038 && self.n0_nat_traversal.client_side().is_ok() +2039 { +2040 let token = self.rng.random(); +2041 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +2042 builder.write_frame(frame::PathChallenge(token), stats); +2043 let ip_port = (network_path.remote.ip(), network_path.remote.port()); +2044 self.n0_nat_traversal.mark_probe_sent(ip_port, token); +2045 } +2046 +2047 // Off-path: not tracked in congestion control. The packet is sent to a +2048 // different destination than path_id's network path. +2049 builder.pad_to(MIN_INITIAL_SIZE); +2050 builder.finish(self, now); +2051 +2052 let size = buf.len(); +2053 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size); +2054 +2055 trace!( +2056 dst = ?network_path.remote, +2057 src = ?network_path.local_ip, +2058 len = buf.len(), +2059 "sending off-path PATH_RESPONSE", +2060 ); +2061 Some(Transmit { +2062 destination: network_path.remote, +2063 size, +2064 ecn: None, +2065 segment_size: None, +2066 src_ip: network_path.local_ip, +2067 }) +2068 } +2069 +2070 /// Send a nat traversal challenge (off-path) on this path if possible. +2071 fn send_nat_traversal_path_challenge( +2072 &mut self, +2073 now: Instant, +2074 buf: &mut Vec<u8>, +2075 path_id: PathId, +2076 ) -> Option<Transmit> { +2077 let remote = self.n0_nat_traversal.next_probe_addr()?; +2078 +2079 if !self.paths.get(&path_id)?.data.validated { +2080 // Path is not usable for probing +2081 return None; +2082 } +2083 +2084 // TODO: Using the active CID here makes the paths linkable. This is a violation of +2085 // RFC9000 but something we want to accept in the short term. Eventually we aim +2086 // to fix up the supply of CIDs sufficiently so that we can keep paths unlinkable +2087 // again. +2088 let Some(cid) = self +2089 .remote_cids +2090 .get(&path_id) +2091 .map(|cid_queue| cid_queue.active()) +2092 else { +2093 trace!(%path_id, "Not sending NAT traversal probe for path with no CIDs"); +2094 return None; +2095 }; +2096 let token = self.rng.random(); +2097 +2098 let frame = frame::PathChallenge(token); +2099 +2100 let mut buf = TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into()); +2101 buf.start_new_datagram(); +2102 +2103 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, &mut buf, self)?; +2104 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +2105 builder.write_frame_with_log_msg(frame, stats, Some("(nat-traversal)")); +2106 // Off-path: not tracked in congestion control. The packet is sent to a +2107 // different destination than path_id's network path. +2108 builder.finish(self, now); 2109 -2110 let size = buf.len(); -2111 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size); -2112 -2113 trace!(dst = ?remote, len = buf.len(), "sending off-path NAT probe"); -2114 Some(Transmit { -2115 destination: remote, -2116 size, -2117 ecn: None, -2118 segment_size: None, -2119 src_ip: None, -2120 }) -2121 } -2122 -2123 /// Indicate what types of frames are ready to send for the given space. -2124 /// -2125 /// Only for on-path data. -2126 /// -2127 /// *packet_size* is the number of bytes available to build the next packet. -2128 /// *connection_close_pending* indicates whether a CONNECTION_CLOSE frame needs to be -2129 /// sent. -2130 fn space_can_send( -2131 &mut self, -2132 space_id: SpaceId, -2133 path_id: PathId, -2134 packet_size: usize, -2135 connection_close_pending: bool, -2136 ) -> SendableFrames { -2137 let space = &mut self.spaces[space_id]; -2138 let space_has_crypto = self.crypto_state.has_keys(space_id.encryption_level()); -2139 -2140 if !space_has_crypto -2141 && (space_id != SpaceId::Data -2142 || !self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) -2143 || self.side.is_server()) -2144 { -2145 // Nothing to send in this space -2146 return SendableFrames::empty(); -2147 } -2148 -2149 let mut can_send = space.can_send(path_id, &self.streams); -2150 -2151 // Check for 1RTT space. -2152 if space_id == SpaceId::Data { -2153 let pn = space.for_path(path_id).peek_tx_number(); -2154 // Number of bytes available for frames if this is a 1-RTT packet. We're -2155 // guaranteed to be able to send an individual frame at least this large in the -2156 // next 1-RTT packet. This could be generalized to support every space, but it's -2157 // only needed to handle large fixed-size frames, which only exist in 1-RTT -2158 // (application datagrams). -2159 let frame_space_1rtt = -2160 packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id)); -2161 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt); -2162 } -2163 -2164 can_send.close = connection_close_pending && space_has_crypto; -2165 -2166 can_send -2167 } -2168 -2169 /// Process `ConnectionEvent`s generated by the associated `Endpoint` -2170 /// -2171 /// Will execute protocol logic upon receipt of a connection event, in turn preparing signals -2172 /// (including application `Event`s, `EndpointEvent`s and outgoing datagrams) that should be -2173 /// extracted through the relevant methods. -2174 pub fn handle_event(&mut self, event: ConnectionEvent) { -2175 use ConnectionEventInner::*; -2176 match event.0 { -2177 Datagram(DatagramConnectionEvent { -2178 now, -2179 network_path, -2180 path_id, -2181 ecn, -2182 first_decode, -2183 remaining, -2184 }) => { -2185 let span = trace_span!("pkt", %path_id); -2186 let _guard = span.enter(); -2187 -2188 if self.early_discard_packet(network_path, path_id) { -2189 // A return value of true indicates we should discard this packet. -2190 return; -2191 } -2192 -2193 let was_anti_amplification_blocked = self -2194 .path(path_id) -2195 .map(|path| path.anti_amplification_blocked(1)) -2196 // We never tried to send on an non-existing (new) path so have not been -2197 // anti-amplification blocked for it previously. -2198 .unwrap_or(false); -2199 -2200 let rx = &mut self.path_stats.for_path(path_id).udp_rx; -2201 rx.datagrams += 1; -2202 rx.bytes += first_decode.len() as u64; -2203 let data_len = first_decode.len(); -2204 -2205 self.handle_decode(now, network_path, path_id, ecn, first_decode); -2206 // The current `path` might have changed inside `handle_decode` since the packet -2207 // could have triggered a migration. The packet might also belong to an unknown -2208 // path and have been rejected. Make sure the data received is accounted for the -2209 // most recent path by accessing `path` after `handle_decode`. -2210 if let Some(path) = self.path_mut(path_id) { -2211 path.inc_total_recvd(data_len as u64); -2212 } -2213 -2214 if let Some(data) = remaining { -2215 self.path_stats.for_path(path_id).udp_rx.bytes += data.len() as u64; -2216 self.handle_coalesced(now, network_path, path_id, ecn, data); -2217 } -2218 -2219 if let Some(path) = self.paths.get_mut(&path_id) { -2220 self.qlog -2221 .emit_recovery_metrics(path_id, &mut path.data, now); -2222 } -2223 -2224 if was_anti_amplification_blocked { -2225 // A prior attempt to set the loss detection timer may have failed due to -2226 // anti-amplification, so ensure it's set now. Prevents a handshake deadlock if -2227 // the server's first flight is lost. -2228 self.set_loss_detection_timer(now, path_id); -2229 } -2230 } -2231 NewIdentifiers(ids, now, cid_len, cid_lifetime) => { -2232 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default(); -2233 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id)); -2234 let cid_state = self -2235 .local_cid_state -2236 .entry(path_id) -2237 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0)); -2238 cid_state.new_cids(&ids, now); -2239 -2240 ids.into_iter().rev().for_each(|frame| { -2241 self.spaces[SpaceId::Data].pending.new_cids.push(frame); -2242 }); -2243 // Always update Timer::PushNewCid -2244 self.reset_cid_retirement(now); -2245 } -2246 } -2247 } -2248 -2249 /// Returns whether a packet can be discarded early. -2250 /// -2251 /// Packets sent on the wrong network path can be entirely ignored, saving further -2252 /// processing. -2253 /// -2254 /// Returns true if a packet coming in for this `path_id` over given `network_path` -2255 /// should be discarded. -2256 fn early_discard_packet(&mut self, network_path: FourTuple, path_id: PathId) -> bool { -2257 if self.is_handshaking() && path_id != PathId::ZERO { -2258 debug!(%network_path, %path_id, "discarding multipath packet during handshake"); -2259 return true; -2260 } -2261 -2262 // TODO(flub): In RFC9000 the server is allowed to send off-path probing packets -2263 // once the client has been probing such a 4-tuple. These probes are currently -2264 // not yet recognised and discarded here. -2265 // See https://github.com/n0-computer/noq/issues/607. -2266 let remote_may_migrate = self.remote_may_migrate(); -2267 -2268 let local_ip_may_migrate = self.local_ip_may_migrate(); -2269 -2270 // If this packet could initiate a migration and we're a client or a server that -2271 // forbids migration, drop the datagram. This could be relaxed to heuristically -2272 // permit NAT-rebinding-like migration. -2273 if let Some(known_path) = self.path_mut(path_id) { -2274 if network_path.remote != known_path.network_path.remote && !remote_may_migrate { -2275 trace!( -2276 %path_id, -2277 %network_path, -2278 %known_path.network_path, -2279 "discarding packet from unrecognized peer" -2280 ); -2281 return true; -2282 } -2283 -2284 if known_path.network_path.local_ip.is_some() -2285 && network_path.local_ip.is_some() -2286 && known_path.network_path.local_ip != network_path.local_ip -2287 && !local_ip_may_migrate -2288 { -2289 trace!( -2290 %path_id, -2291 %network_path, -2292 %known_path.network_path, -2293 "discarding packet sent to incorrect interface" -2294 ); -2295 return true; -2296 } -2297 } -2298 false -2299 } -2300 -2301 /// Whether a remote is allowed to migrate. -2302 /// -2303 /// QUIC relies on stable endpoints during the handshake. So other than the server's -2304 /// preferred_address transport parameter no side may migrate before the handshake is -2305 /// completed. +2110 // Mark as sent after packet build succeeds. +2111 self.n0_nat_traversal +2112 .mark_probe_sent((remote.ip(), remote.port()), token); +2113 +2114 let size = buf.len(); +2115 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size); +2116 +2117 trace!(dst = ?remote, len = buf.len(), "sending off-path NAT probe"); +2118 Some(Transmit { +2119 destination: remote, +2120 size, +2121 ecn: None, +2122 segment_size: None, +2123 src_ip: None, +2124 }) +2125 } +2126 +2127 /// Indicate what types of frames are ready to send for the given space. +2128 /// +2129 /// Only for on-path data. +2130 /// +2131 /// *packet_size* is the number of bytes available to build the next packet. +2132 /// *connection_close_pending* indicates whether a CONNECTION_CLOSE frame needs to be +2133 /// sent. +2134 fn space_can_send( +2135 &mut self, +2136 space_id: SpaceId, +2137 path_id: PathId, +2138 packet_size: usize, +2139 connection_close_pending: bool, +2140 ) -> SendableFrames { +2141 let space = &mut self.spaces[space_id]; +2142 let space_has_crypto = self.crypto_state.has_keys(space_id.encryption_level()); +2143 +2144 if !space_has_crypto +2145 && (space_id != SpaceId::Data +2146 || !self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) +2147 || self.side.is_server()) +2148 { +2149 // Nothing to send in this space +2150 return SendableFrames::empty(); +2151 } +2152 +2153 let mut can_send = space.can_send(path_id, &self.streams); +2154 +2155 // Check for 1RTT space. +2156 if space_id == SpaceId::Data { +2157 let pn = space.for_path(path_id).peek_tx_number(); +2158 // Number of bytes available for frames if this is a 1-RTT packet. We're +2159 // guaranteed to be able to send an individual frame at least this large in the +2160 // next 1-RTT packet. This could be generalized to support every space, but it's +2161 // only needed to handle large fixed-size frames, which only exist in 1-RTT +2162 // (application datagrams). +2163 let frame_space_1rtt = +2164 packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id)); +2165 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt); +2166 } +2167 +2168 can_send.close = connection_close_pending && space_has_crypto; +2169 +2170 can_send +2171 } +2172 +2173 /// Process `ConnectionEvent`s generated by the associated `Endpoint` +2174 /// +2175 /// Will execute protocol logic upon receipt of a connection event, in turn preparing signals +2176 /// (including application `Event`s, `EndpointEvent`s and outgoing datagrams) that should be +2177 /// extracted through the relevant methods. +2178 pub fn handle_event(&mut self, event: ConnectionEvent) { +2179 use ConnectionEventInner::*; +2180 match event.0 { +2181 Datagram(DatagramConnectionEvent { +2182 now, +2183 network_path, +2184 path_id, +2185 ecn, +2186 first_decode, +2187 remaining, +2188 }) => { +2189 let span = trace_span!("pkt", %path_id); +2190 let _guard = span.enter(); +2191 +2192 if self.early_discard_packet(network_path, path_id) { +2193 // A return value of true indicates we should discard this packet. +2194 return; +2195 } +2196 +2197 let was_anti_amplification_blocked = self +2198 .path(path_id) +2199 .map(|path| path.anti_amplification_blocked(1)) +2200 // We never tried to send on an non-existing (new) path so have not been +2201 // anti-amplification blocked for it previously. +2202 .unwrap_or(false); +2203 +2204 let rx = &mut self.path_stats.for_path(path_id).udp_rx; +2205 rx.datagrams += 1; +2206 rx.bytes += first_decode.len() as u64; +2207 let data_len = first_decode.len(); +2208 +2209 self.handle_decode(now, network_path, path_id, ecn, first_decode); +2210 // The current `path` might have changed inside `handle_decode` since the packet +2211 // could have triggered a migration. The packet might also belong to an unknown +2212 // path and have been rejected. Make sure the data received is accounted for the +2213 // most recent path by accessing `path` after `handle_decode`. +2214 if let Some(path) = self.path_mut(path_id) { +2215 path.inc_total_recvd(data_len as u64); +2216 } +2217 +2218 if let Some(data) = remaining { +2219 self.path_stats.for_path(path_id).udp_rx.bytes += data.len() as u64; +2220 self.handle_coalesced(now, network_path, path_id, ecn, data); +2221 } +2222 +2223 if let Some(path) = self.paths.get_mut(&path_id) { +2224 self.qlog +2225 .emit_recovery_metrics(path_id, &mut path.data, now); +2226 } +2227 +2228 if was_anti_amplification_blocked { +2229 // A prior attempt to set the loss detection timer may have failed due to +2230 // anti-amplification, so ensure it's set now. Prevents a handshake deadlock if +2231 // the server's first flight is lost. +2232 self.set_loss_detection_timer(now, path_id); +2233 } +2234 } +2235 NewIdentifiers(ids, now, cid_len, cid_lifetime) => { +2236 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default(); +2237 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id)); +2238 let cid_state = self +2239 .local_cid_state +2240 .entry(path_id) +2241 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0)); +2242 cid_state.new_cids(&ids, now); +2243 +2244 ids.into_iter().rev().for_each(|frame| { +2245 self.spaces[SpaceId::Data].pending.new_cids.push(frame); +2246 }); +2247 // Always update Timer::PushNewCid +2248 self.reset_cid_retirement(now); +2249 } +2250 } +2251 } +2252 +2253 /// Returns whether a packet can be discarded early. +2254 /// +2255 /// Packets sent on the wrong network path can be entirely ignored, saving further +2256 /// processing. +2257 /// +2258 /// Returns true if a packet coming in for this `path_id` over given `network_path` +2259 /// should be discarded. +2260 fn early_discard_packet(&mut self, network_path: FourTuple, path_id: PathId) -> bool { +2261 if self.is_handshaking() && path_id != PathId::ZERO { +2262 debug!(%network_path, %path_id, "discarding multipath packet during handshake"); +2263 return true; +2264 } +2265 +2266 // TODO(flub): In RFC9000 the server is allowed to send off-path probing packets +2267 // once the client has been probing such a 4-tuple. These probes are currently +2268 // not yet recognised and discarded here. +2269 // See https://github.com/n0-computer/noq/issues/607. +2270 let remote_may_migrate = self.remote_may_migrate(); +2271 +2272 let local_ip_may_migrate = self.local_ip_may_migrate(); +2273 +2274 // If this packet could initiate a migration and we're a client or a server that +2275 // forbids migration, drop the datagram. This could be relaxed to heuristically +2276 // permit NAT-rebinding-like migration. +2277 if let Some(known_path) = self.path_mut(path_id) { +2278 if network_path.remote != known_path.network_path.remote && !remote_may_migrate { +2279 trace!( +2280 %path_id, +2281 %network_path, +2282 %known_path.network_path, +2283 "discarding packet from unrecognized peer" +2284 ); +2285 return true; +2286 } +2287 +2288 if known_path.network_path.local_ip.is_some() +2289 && network_path.local_ip.is_some() +2290 && known_path.network_path.local_ip != network_path.local_ip +2291 && !local_ip_may_migrate +2292 { +2293 trace!( +2294 %path_id, +2295 %network_path, +2296 %known_path.network_path, +2297 "discarding packet sent to incorrect interface" +2298 ); +2299 return true; +2300 } +2301 } +2302 false +2303 } +2304 +2305 /// Whether a remote is allowed to migrate. 2306 /// -2307 /// In RFC9000 only the client may migrate. If QNT is negotiated the server may migrate -2308 /// as well. -2309 /// -2310 /// Additionally for iroh we allow the server to migrate once during the handshake as -2311 /// long as the client has not received an authenticated Handshake packet. This allows -2312 /// us to duplicate client Initial packets to multiple destinations. See -2313 /// [`state::Handshake::allow_server_migration`]. -2314 fn remote_may_migrate(&self) -> bool { -2315 match &self.side { -2316 ConnectionSide::Server { server_config } => { -2317 server_config.migration && self.is_handshake_confirmed() -2318 } -2319 ConnectionSide::Client { .. } => { -2320 if let Some(hs) = self.state.as_handshake() { -2321 hs.allow_server_migration -2322 } else { -2323 self.n0_nat_traversal.is_negotiated() && self.is_handshake_confirmed() -2324 } -2325 } -2326 } -2327 } -2328 -2329 /// Whether our local IP address is allowed to change with new incoming packets. -2330 /// -2331 /// Incoming packets show us the local IP address we received a packet on, which could -2332 /// be different from what we thought due to e.g. NAT rebinding or moving from mobile -2333 /// data to WiFi without being notified of the network change. +2307 /// QUIC relies on stable endpoints during the handshake. So other than the server's +2308 /// preferred_address transport parameter no side may migrate before the handshake is +2309 /// completed. +2310 /// +2311 /// In RFC9000 only the client may migrate. If QNT is negotiated the server may migrate +2312 /// as well. +2313 /// +2314 /// Additionally for iroh we allow the server to migrate once during the handshake as +2315 /// long as the client has not received an authenticated Handshake packet. This allows +2316 /// us to duplicate client Initial packets to multiple destinations. See +2317 /// [`state::Handshake::allow_server_migration`]. +2318 fn remote_may_migrate(&self) -> bool { +2319 match &self.side { +2320 ConnectionSide::Server { server_config } => { +2321 server_config.migration && self.is_handshake_confirmed() +2322 } +2323 ConnectionSide::Client { .. } => { +2324 if let Some(hs) = self.state.as_handshake() { +2325 hs.allow_server_migration +2326 } else { +2327 self.n0_nat_traversal.is_negotiated() && self.is_handshake_confirmed() +2328 } +2329 } +2330 } +2331 } +2332 +2333 /// Whether our local IP address is allowed to change with new incoming packets. 2334 /// -2335 /// This is only allowed to happen after the handshake is confirmed and when we are the -2336 /// client. Unless QNT is negotiated in which case the server is also allowed to -2337 /// migrate. +2335 /// Incoming packets show us the local IP address we received a packet on, which could +2336 /// be different from what we thought due to e.g. NAT rebinding or moving from mobile +2337 /// data to WiFi without being notified of the network change. 2338 /// -2339 /// Be aware that probing packets, which do not exist in Multipath without QNT, are -2340 /// exempt from this. -2341 fn local_ip_may_migrate(&self) -> bool { -2342 (self.side.is_client() || self.n0_nat_traversal.is_negotiated()) -2343 && self.is_handshake_confirmed() -2344 } -2345 /// Process timer expirations -2346 /// -2347 /// Executes protocol logic, potentially preparing signals (including application `Event`s, -2348 /// `EndpointEvent`s and outgoing datagrams) that should be extracted through the relevant -2349 /// methods. +2339 /// This is only allowed to happen after the handshake is confirmed and when we are the +2340 /// client. Unless QNT is negotiated in which case the server is also allowed to +2341 /// migrate. +2342 /// +2343 /// Be aware that probing packets, which do not exist in Multipath without QNT, are +2344 /// exempt from this. +2345 fn local_ip_may_migrate(&self) -> bool { +2346 (self.side.is_client() || self.n0_nat_traversal.is_negotiated()) +2347 && self.is_handshake_confirmed() +2348 } +2349 /// Process timer expirations 2350 /// -2351 /// It is most efficient to call this immediately after the system clock reaches the latest -2352 /// `Instant` that was output by `poll_timeout`; however spurious extra calls will simply -2353 /// no-op and therefore are safe. -2354 pub fn handle_timeout(&mut self, now: Instant) { -2355 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) { -2356 let span = match timer { -2357 Timer::Conn(timer) => trace_span!("timeout", scope = "conn", ?timer), -2358 Timer::PerPath(path_id, timer) => { -2359 trace_span!("timer_fired", scope="path", %path_id, ?timer) -2360 } -2361 }; -2362 let _guard = span.enter(); -2363 trace!("timeout"); -2364 match timer { -2365 Timer::Conn(timer) => match timer { -2366 ConnTimer::Close => { -2367 self.state.move_to_drained(None); -2368 // move_to_drained checks that we weren't in drained before. -2369 // Adding events to endpoint_events is only legal if `Drained` was never queued before. -2370 self.endpoint_events.push_back(EndpointEventInner::Drained); -2371 } -2372 ConnTimer::Idle => { -2373 self.kill(ConnectionError::TimedOut); -2374 } -2375 ConnTimer::KeepAlive => { -2376 self.ping(); -2377 } -2378 ConnTimer::KeyDiscard => { -2379 self.crypto_state.discard_temporary_keys(); -2380 } -2381 ConnTimer::PushNewCid => { -2382 while let Some((path_id, when)) = self.next_cid_retirement() { -2383 if when > now { -2384 break; -2385 } -2386 match self.local_cid_state.get_mut(&path_id) { -2387 None => error!(%path_id, "No local CID state for path"), -2388 Some(cid_state) => { -2389 // Update `retire_prior_to` field in NEW_CONNECTION_ID frame -2390 let num_new_cid = cid_state.on_cid_timeout().into(); -2391 if !self.state.is_closed() { -2392 trace!( -2393 "push a new CID to peer RETIRE_PRIOR_TO field {}", -2394 cid_state.retire_prior_to() -2395 ); -2396 self.endpoint_events.push_back( -2397 EndpointEventInner::NeedIdentifiers( -2398 path_id, -2399 now, -2400 num_new_cid, -2401 ), -2402 ); -2403 } -2404 } -2405 } -2406 } -2407 } -2408 ConnTimer::NoAvailablePath => { -2409 // Grace period expired: all paths were abandoned and no new path -2410 // was opened. Close the connection. There are no paths left to -2411 // send CONNECTION_CLOSE on, so this is a silent close. -2412 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-21.html#section-3.4-8 -2413 if self.state.is_closed() || self.state.is_drained() { -2414 // Connection already closing/drained (e.g. application called -2415 // close() before the grace timer fired). Nothing to do. -2416 error!("no viable path timer fired, but connection already closing"); -2417 } else { -2418 trace!("no viable path grace period expired, closing connection"); -2419 let err = TransportError::NO_VIABLE_PATH( -2420 "last path abandoned, no new path opened", -2421 ); -2422 self.close_common(); -2423 self.set_close_timer(now); -2424 self.connection_close_pending = true; -2425 self.state.move_to_closed(err); -2426 } -2427 } -2428 ConnTimer::NatTraversalProbeRetry => { -2429 if self.n0_nat_traversal.queue_retries(self.is_ipv6()) { -2430 let delay = -2431 RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; -2432 self.timers.set( -2433 Timer::Conn(ConnTimer::NatTraversalProbeRetry), -2434 now + delay, -2435 self.qlog.with_time(now), -2436 ); -2437 trace!("re-queued NAT probes"); -2438 } else { -2439 trace!("no more NAT probes remaining"); -2440 } -2441 } -2442 }, -2443 Timer::PerPath(path_id, timer) => { -2444 match timer { -2445 PathTimer::PathIdle => { -2446 if let Err(err) = -2447 self.close_path_inner(now, path_id, PathAbandonReason::TimedOut) -2448 { -2449 warn!(?err, "failed closing path"); -2450 } -2451 } -2452 -2453 PathTimer::PathKeepAlive => { -2454 self.ping_path(path_id).ok(); +2351 /// Executes protocol logic, potentially preparing signals (including application `Event`s, +2352 /// `EndpointEvent`s and outgoing datagrams) that should be extracted through the relevant +2353 /// methods. +2354 /// +2355 /// It is most efficient to call this immediately after the system clock reaches the latest +2356 /// `Instant` that was output by `poll_timeout`; however spurious extra calls will simply +2357 /// no-op and therefore are safe. +2358 pub fn handle_timeout(&mut self, now: Instant) { +2359 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) { +2360 let span = match timer { +2361 Timer::Conn(timer) => trace_span!("timeout", scope = "conn", ?timer), +2362 Timer::PerPath(path_id, timer) => { +2363 trace_span!("timer_fired", scope="path", %path_id, ?timer) +2364 } +2365 }; +2366 let _guard = span.enter(); +2367 trace!("timeout"); +2368 match timer { +2369 Timer::Conn(timer) => match timer { +2370 ConnTimer::Close => { +2371 self.state.move_to_drained(None); +2372 // move_to_drained checks that we weren't in drained before. +2373 // Adding events to endpoint_events is only legal if `Drained` was never queued before. +2374 self.endpoint_events.push_back(EndpointEventInner::Drained); +2375 } +2376 ConnTimer::Idle => { +2377 self.kill(ConnectionError::TimedOut); +2378 } +2379 ConnTimer::KeepAlive => { +2380 self.ping(); +2381 } +2382 ConnTimer::KeyDiscard => { +2383 self.crypto_state.discard_temporary_keys(); +2384 } +2385 ConnTimer::PushNewCid => { +2386 while let Some((path_id, when)) = self.next_cid_retirement() { +2387 if when > now { +2388 break; +2389 } +2390 match self.local_cid_state.get_mut(&path_id) { +2391 None => error!(%path_id, "No local CID state for path"), +2392 Some(cid_state) => { +2393 // Update `retire_prior_to` field in NEW_CONNECTION_ID frame +2394 let num_new_cid = cid_state.on_cid_timeout().into(); +2395 if !self.state.is_closed() { +2396 trace!( +2397 "push a new CID to peer RETIRE_PRIOR_TO field {}", +2398 cid_state.retire_prior_to() +2399 ); +2400 self.endpoint_events.push_back( +2401 EndpointEventInner::NeedIdentifiers( +2402 path_id, +2403 now, +2404 num_new_cid, +2405 ), +2406 ); +2407 } +2408 } +2409 } +2410 } +2411 } +2412 ConnTimer::NoAvailablePath => { +2413 // Grace period expired: all paths were abandoned and no new path +2414 // was opened. Close the connection. There are no paths left to +2415 // send CONNECTION_CLOSE on, so this is a silent close. +2416 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-21.html#section-3.4-8 +2417 if self.state.is_closed() || self.state.is_drained() { +2418 // Connection already closing/drained (e.g. application called +2419 // close() before the grace timer fired). Nothing to do. +2420 error!("no viable path timer fired, but connection already closing"); +2421 } else { +2422 trace!("no viable path grace period expired, closing connection"); +2423 let err = TransportError::NO_VIABLE_PATH( +2424 "last path abandoned, no new path opened", +2425 ); +2426 self.close_common(); +2427 self.set_close_timer(now); +2428 self.connection_close_pending = true; +2429 self.state.move_to_closed(err); +2430 } +2431 } +2432 ConnTimer::NatTraversalProbeRetry => { +2433 if self.n0_nat_traversal.queue_retries(self.is_ipv6()) { +2434 let delay = +2435 RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; +2436 self.timers.set( +2437 Timer::Conn(ConnTimer::NatTraversalProbeRetry), +2438 now + delay, +2439 self.qlog.with_time(now), +2440 ); +2441 trace!("re-queued NAT probes"); +2442 } else { +2443 trace!("no more NAT probes remaining"); +2444 } +2445 } +2446 }, +2447 Timer::PerPath(path_id, timer) => { +2448 match timer { +2449 PathTimer::PathIdle => { +2450 if let Err(err) = +2451 self.close_path_inner(now, path_id, PathAbandonReason::TimedOut) +2452 { +2453 warn!(?err, "failed closing path"); +2454 } 2455 } -2456 PathTimer::LossDetection => { -2457 self.on_loss_detection_timeout(now, path_id); -2458 self.qlog.emit_recovery_metrics( -2459 path_id, -2460 &mut self.paths.get_mut(&path_id).unwrap().data, -2461 now, -2462 ); -2463 } -2464 PathTimer::PathValidationFailed => { -2465 let Some(path) = self.paths.get_mut(&path_id) else { -2466 continue; -2467 }; -2468 self.timers.stop( -2469 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -2470 self.qlog.with_time(now), -2471 ); -2472 debug!("path migration validation failed"); -2473 if let Some((_, prev)) = path.prev.take() { -2474 path.data = prev; -2475 } -2476 path.data.reset_on_path_challenges(); -2477 } -2478 PathTimer::PathChallengeLost => { -2479 let Some(path) = self.paths.get_mut(&path_id) else { -2480 continue; -2481 }; -2482 trace!("path challenge deemed lost"); -2483 path.data.pending_on_path_challenge = true; -2484 } -2485 PathTimer::AbandonFromValidation => { -2486 let Some(path) = self.paths.get_mut(&path_id) else { -2487 continue; -2488 }; -2489 path.data.reset_on_path_challenges(); -2490 self.timers.stop( -2491 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -2492 self.qlog.with_time(now), -2493 ); -2494 debug!("new path validation failed"); -2495 if let Err(err) = self.close_path_inner( -2496 now, -2497 path_id, -2498 PathAbandonReason::ValidationFailed, -2499 ) { -2500 warn!(?err, "failed closing path"); -2501 } -2502 } -2503 PathTimer::Pacing => {} -2504 PathTimer::MaxAckDelay => { -2505 // This timer is only armed in the Data space -2506 self.spaces[SpaceId::Data] -2507 .for_path(path_id) -2508 .pending_acks -2509 .on_max_ack_delay_timeout() +2456 +2457 PathTimer::PathKeepAlive => { +2458 self.ping_path(path_id).ok(); +2459 } +2460 PathTimer::LossDetection => { +2461 self.on_loss_detection_timeout(now, path_id); +2462 self.qlog.emit_recovery_metrics( +2463 path_id, +2464 &mut self +2465 .paths +2466 .get_mut(&path_id) +2467 .expect("loss-detection timer fires only on live paths") +2468 .data, +2469 now, +2470 ); +2471 } +2472 PathTimer::PathValidationFailed => { +2473 let Some(path) = self.paths.get_mut(&path_id) else { +2474 continue; +2475 }; +2476 self.timers.stop( +2477 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +2478 self.qlog.with_time(now), +2479 ); +2480 debug!("path migration validation failed"); +2481 if let Some((_, prev)) = path.prev.take() { +2482 path.data = prev; +2483 } +2484 path.data.reset_on_path_challenges(); +2485 } +2486 PathTimer::PathChallengeLost => { +2487 let Some(path) = self.paths.get_mut(&path_id) else { +2488 continue; +2489 }; +2490 trace!("path challenge deemed lost"); +2491 path.data.pending_on_path_challenge = true; +2492 } +2493 PathTimer::AbandonFromValidation => { +2494 let Some(path) = self.paths.get_mut(&path_id) else { +2495 continue; +2496 }; +2497 path.data.reset_on_path_challenges(); +2498 self.timers.stop( +2499 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +2500 self.qlog.with_time(now), +2501 ); +2502 debug!("new path validation failed"); +2503 if let Err(err) = self.close_path_inner( +2504 now, +2505 path_id, +2506 PathAbandonReason::ValidationFailed, +2507 ) { +2508 warn!(?err, "failed closing path"); +2509 } 2510 } -2511 PathTimer::PathDrained => { -2512 // The path was abandoned and 3*PTO has expired since. Clean up all -2513 // remaining state and install stateless reset token. -2514 self.timers.stop_per_path(path_id, self.qlog.with_time(now)); -2515 if let Some(local_cid_state) = self.local_cid_state.remove(&path_id) { -2516 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events. All timers should be cleared in drained connections. -2517 let (min_seq, max_seq) = local_cid_state.active_seq(); -2518 for seq in min_seq..=max_seq { -2519 self.endpoint_events.push_back( -2520 EndpointEventInner::RetireConnectionId( -2521 now, path_id, seq, false, -2522 ), -2523 ); -2524 } -2525 } -2526 self.discard_path(path_id, now); -2527 } -2528 } -2529 } -2530 } -2531 } -2532 } -2533 -2534 /// Close a connection immediately -2535 /// -2536 /// This does not ensure delivery of outstanding data. It is the application's responsibility to -2537 /// call this only when all important communications have been completed, e.g. by calling -2538 /// [`SendStream::finish`] on outstanding streams and waiting for the corresponding -2539 /// [`StreamEvent::Finished`] event. -2540 /// -2541 /// If [`Streams::send_streams`] returns 0, all outstanding stream data has been -2542 /// delivered. There may still be data from the peer that has not been received. +2511 PathTimer::Pacing => {} +2512 PathTimer::MaxAckDelay => { +2513 // This timer is only armed in the Data space +2514 self.spaces[SpaceId::Data] +2515 .for_path(path_id) +2516 .pending_acks +2517 .on_max_ack_delay_timeout() +2518 } +2519 PathTimer::PathDrained => { +2520 // The path was abandoned and 3*PTO has expired since. Clean up all +2521 // remaining state and install stateless reset token. +2522 self.timers.stop_per_path(path_id, self.qlog.with_time(now)); +2523 if let Some(local_cid_state) = self.local_cid_state.remove(&path_id) { +2524 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events. All timers should be cleared in drained connections. +2525 let (min_seq, max_seq) = local_cid_state.active_seq(); +2526 for seq in min_seq..=max_seq { +2527 self.endpoint_events.push_back( +2528 EndpointEventInner::RetireConnectionId( +2529 now, path_id, seq, false, +2530 ), +2531 ); +2532 } +2533 } +2534 self.discard_path(path_id, now); +2535 } +2536 } +2537 } +2538 } +2539 } +2540 } +2541 +2542 /// Close a connection immediately 2543 /// -2544 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished -2545 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) { -2546 self.close_inner( -2547 now, -2548 Close::Application(frame::ApplicationClose { error_code, reason }), -2549 ) -2550 } -2551 -2552 /// Close the connection immediately, initiated by an API call. -2553 /// -2554 /// This will not produce a [`ConnectionLost`] event propagated by the -2555 /// [`Connection::poll`] call, because the API call already propagated the error to the -2556 /// user. -2557 /// -2558 /// Not to be used when entering immediate close due to an internal state change based -2559 /// on an event. See [`State::move_to_closed_local`] for details. -2560 /// -2561 /// This initiates immediate close from -2562 /// <https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2>, moving to the closed -2563 /// state. -2564 /// -2565 /// [`ConnectionLost`]: crate::Event::ConnectionLost -2566 /// [`Connection::poll`]: super::Connection::poll -2567 fn close_inner(&mut self, now: Instant, reason: Close) { -2568 let was_closed = self.state.is_closed(); -2569 if !was_closed { -2570 self.close_common(); -2571 self.set_close_timer(now); -2572 self.connection_close_pending = true; -2573 self.state.move_to_closed_local(reason); -2574 } -2575 } -2576 -2577 /// Control datagrams -2578 pub fn datagrams(&mut self) -> Datagrams<'_> { -2579 Datagrams { conn: self } -2580 } -2581 -2582 /// Returns connection statistics -2583 pub fn stats(&mut self) -> ConnectionStats { -2584 let mut stats = self.partial_stats.clone(); -2585 -2586 for path_stats in self.path_stats.iter_stats() { -2587 // Self::path_stats() computes the path rtt, cwnd and current_mtu on access -2588 // because they are not simple counters. When computing the connection stats we -2589 // can skip that effort since those fields are not used in the `impl -2590 // Add<PathStats> for ConnectionStats`. -2591 stats += *path_stats; -2592 } +2544 /// This does not ensure delivery of outstanding data. It is the application's responsibility to +2545 /// call this only when all important communications have been completed, e.g. by calling +2546 /// [`SendStream::finish`] on outstanding streams and waiting for the corresponding +2547 /// [`StreamEvent::Finished`] event. +2548 /// +2549 /// If [`Streams::send_streams`] returns 0, all outstanding stream data has been +2550 /// delivered. There may still be data from the peer that has not been received. +2551 /// +2552 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished +2553 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) { +2554 self.close_inner( +2555 now, +2556 Close::Application(frame::ApplicationClose { error_code, reason }), +2557 ) +2558 } +2559 +2560 /// Close the connection immediately, initiated by an API call. +2561 /// +2562 /// This will not produce a [`ConnectionLost`] event propagated by the +2563 /// [`Connection::poll`] call, because the API call already propagated the error to the +2564 /// user. +2565 /// +2566 /// Not to be used when entering immediate close due to an internal state change based +2567 /// on an event. See [`State::move_to_closed_local`] for details. +2568 /// +2569 /// This initiates immediate close from +2570 /// <https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2>, moving to the closed +2571 /// state. +2572 /// +2573 /// [`ConnectionLost`]: crate::Event::ConnectionLost +2574 /// [`Connection::poll`]: super::Connection::poll +2575 fn close_inner(&mut self, now: Instant, reason: Close) { +2576 let was_closed = self.state.is_closed(); +2577 if !was_closed { +2578 self.close_common(); +2579 self.set_close_timer(now); +2580 self.connection_close_pending = true; +2581 self.state.move_to_closed_local(reason); +2582 } +2583 } +2584 +2585 /// Control datagrams +2586 pub fn datagrams(&mut self) -> Datagrams<'_> { +2587 Datagrams { conn: self } +2588 } +2589 +2590 /// Returns connection statistics +2591 pub fn stats(&mut self) -> ConnectionStats { +2592 let mut stats = self.partial_stats.clone(); 2593 -2594 stats -2595 } -2596 -2597 /// Returns path statistics -2598 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { -2599 let path = self.paths.get(&path_id)?; -2600 let stats = self.path_stats.for_path(path_id); -2601 stats.rtt = path.data.rtt.get(); -2602 stats.cwnd = path.data.congestion.window(); -2603 stats.current_mtu = path.data.mtud.current_mtu(); -2604 Some(*stats) -2605 } -2606 -2607 /// Ping the remote endpoint -2608 /// -2609 /// Causes an ACK-eliciting packet to be transmitted on the connection. -2610 pub fn ping(&mut self) { -2611 // TODO(flub): This is very brute-force: it pings *all* the paths. Instead it would -2612 // be nice if we could only send a single packet for this. -2613 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() { -2614 path_data.ping_pending = true; -2615 } -2616 } -2617 -2618 /// Ping the remote endpoint over a specific path -2619 /// -2620 /// Causes an ACK-eliciting packet to be transmitted on the path. -2621 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> { -2622 let path_data = self.spaces[self.highest_space] -2623 .number_spaces -2624 .get_mut(&path) -2625 .ok_or(ClosedPath { _private: () })?; -2626 path_data.ping_pending = true; -2627 Ok(()) -2628 } -2629 -2630 /// Update traffic keys spontaneously -2631 /// -2632 /// This can be useful for testing key updates, as they otherwise only happen infrequently. -2633 pub fn force_key_update(&mut self) { -2634 if !self.state.is_established() { -2635 debug!("ignoring forced key update in illegal state"); -2636 return; -2637 } -2638 if self.crypto_state.prev_crypto.is_some() { -2639 // We already just updated, or are currently updating, the keys. Concurrent key updates -2640 // are illegal. -2641 debug!("ignoring redundant forced key update"); -2642 return; -2643 } -2644 self.crypto_state.update_keys(None, false); -2645 } -2646 -2647 /// Get a session reference -2648 pub fn crypto_session(&self) -> &dyn crypto::Session { -2649 self.crypto_state.session.as_ref() -2650 } -2651 -2652 /// Whether the connection is in the process of being established -2653 /// -2654 /// If this returns `false`, the connection may be either established or closed, signaled by the -2655 /// emission of a [`Connected`](Event::Connected) or [`ConnectionLost`](Event::ConnectionLost) -2656 /// event respectively. Note that locally-initiated closes via [`close()`](Self::close) do not -2657 /// emit a `ConnectionLost` event. -2658 /// -2659 /// For an established connection this essentially means the handshake is **completed**, -2660 /// but not necessarily yet confirmed. -2661 pub fn is_handshaking(&self) -> bool { -2662 self.state.is_handshake() -2663 } -2664 -2665 /// Whether the connection is closed +2594 for path_stats in self.path_stats.iter_stats() { +2595 // Self::path_stats() computes the path rtt, cwnd and current_mtu on access +2596 // because they are not simple counters. When computing the connection stats we +2597 // can skip that effort since those fields are not used in the `impl +2598 // Add<PathStats> for ConnectionStats`. +2599 stats += *path_stats; +2600 } +2601 +2602 stats +2603 } +2604 +2605 /// Returns path statistics +2606 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { +2607 let path = self.paths.get(&path_id)?; +2608 let stats = self.path_stats.for_path(path_id); +2609 stats.rtt = path.data.rtt.get(); +2610 stats.cwnd = path.data.congestion.window(); +2611 stats.current_mtu = path.data.mtud.current_mtu(); +2612 Some(*stats) +2613 } +2614 +2615 /// Ping the remote endpoint +2616 /// +2617 /// Causes an ACK-eliciting packet to be transmitted on the connection. +2618 pub fn ping(&mut self) { +2619 // TODO(flub): This is very brute-force: it pings *all* the paths. Instead it would +2620 // be nice if we could only send a single packet for this. +2621 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() { +2622 path_data.ping_pending = true; +2623 } +2624 } +2625 +2626 /// Ping the remote endpoint over a specific path +2627 /// +2628 /// Causes an ACK-eliciting packet to be transmitted on the path. +2629 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> { +2630 let path_data = self.spaces[self.highest_space] +2631 .number_spaces +2632 .get_mut(&path) +2633 .ok_or(ClosedPath { _private: () })?; +2634 path_data.ping_pending = true; +2635 Ok(()) +2636 } +2637 +2638 /// Update traffic keys spontaneously +2639 /// +2640 /// This can be useful for testing key updates, as they otherwise only happen infrequently. +2641 pub fn force_key_update(&mut self) { +2642 if !self.state.is_established() { +2643 debug!("ignoring forced key update in illegal state"); +2644 return; +2645 } +2646 if self.crypto_state.prev_crypto.is_some() { +2647 // We already just updated, or are currently updating, the keys. Concurrent key updates +2648 // are illegal. +2649 debug!("ignoring redundant forced key update"); +2650 return; +2651 } +2652 self.crypto_state.update_keys(None, false); +2653 } +2654 +2655 /// Get a session reference +2656 pub fn crypto_session(&self) -> &dyn crypto::Session { +2657 self.crypto_state.session.as_ref() +2658 } +2659 +2660 /// Whether the connection is in the process of being established +2661 /// +2662 /// If this returns `false`, the connection may be either established or closed, signaled by the +2663 /// emission of a [`Connected`](Event::Connected) or [`ConnectionLost`](Event::ConnectionLost) +2664 /// event respectively. Note that locally-initiated closes via [`close()`](Self::close) do not +2665 /// emit a `ConnectionLost` event. 2666 /// -2667 /// Closed connections cannot transport any further data. A connection becomes closed when -2668 /// either peer application intentionally closes it, or when either transport layer detects an -2669 /// error such as a time-out or certificate validation failure. -2670 /// -2671 /// A [`ConnectionLost`](Event::ConnectionLost) event is emitted with details when the -2672 /// connection is closed by the peer or due to an error. When the local application closes -2673 /// the connection via [`close()`](Self::close), no `ConnectionLost` event is emitted; -2674 /// instead, pending operations fail with [`ConnectionError::LocallyClosed`]. -2675 pub fn is_closed(&self) -> bool { -2676 self.state.is_closed() -2677 } -2678 -2679 /// Whether there is no longer any need to keep the connection around -2680 /// -2681 /// Closed connections become drained after a brief timeout to absorb any remaining in-flight -2682 /// packets from the peer. All drained connections have been closed. -2683 pub fn is_drained(&self) -> bool { -2684 self.state.is_drained() +2667 /// For an established connection this essentially means the handshake is **completed**, +2668 /// but not necessarily yet confirmed. +2669 pub fn is_handshaking(&self) -> bool { +2670 self.state.is_handshake() +2671 } +2672 +2673 /// Whether the connection is closed +2674 /// +2675 /// Closed connections cannot transport any further data. A connection becomes closed when +2676 /// either peer application intentionally closes it, or when either transport layer detects an +2677 /// error such as a time-out or certificate validation failure. +2678 /// +2679 /// A [`ConnectionLost`](Event::ConnectionLost) event is emitted with details when the +2680 /// connection is closed by the peer or due to an error. When the local application closes +2681 /// the connection via [`close()`](Self::close), no `ConnectionLost` event is emitted; +2682 /// instead, pending operations fail with [`ConnectionError::LocallyClosed`]. +2683 pub fn is_closed(&self) -> bool { +2684 self.state.is_closed() 2685 } 2686 -2687 /// For clients, if the peer accepted the 0-RTT data packets +2687 /// Whether there is no longer any need to keep the connection around 2688 /// -2689 /// The value is meaningless until after the handshake completes. -2690 pub fn accepted_0rtt(&self) -> bool { -2691 self.crypto_state.accepted_0rtt -2692 } -2693 -2694 /// Whether 0-RTT is/was possible during the handshake -2695 pub fn has_0rtt(&self) -> bool { -2696 self.crypto_state.zero_rtt_enabled -2697 } -2698 -2699 /// Whether there are any pending retransmits -2700 pub fn has_pending_retransmits(&self) -> bool { -2701 !self.spaces[SpaceId::Data].pending.is_empty(&self.streams) -2702 } -2703 -2704 /// Look up whether we're the client or server of this Connection -2705 pub fn side(&self) -> Side { -2706 self.side.side() -2707 } -2708 -2709 /// Get the address observed by the remote over the given path -2710 pub fn path_observed_address(&self, path_id: PathId) -> Result<Option<SocketAddr>, ClosedPath> { -2711 self.path(path_id) -2712 .map(|path_data| { -2713 path_data -2714 .last_observed_addr_report -2715 .as_ref() -2716 .map(|observed| observed.socket_addr()) -2717 }) -2718 .ok_or(ClosedPath { _private: () }) -2719 } -2720 -2721 /// Current best estimate of this connection's latency (round-trip-time) -2722 pub fn rtt(&self, path_id: PathId) -> Option<Duration> { -2723 self.path(path_id).map(|d| d.rtt.get()) -2724 } -2725 -2726 /// Current state of this connection's congestion controller, for debugging purposes -2727 pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller> { -2728 self.path(path_id).map(|d| d.congestion.as_ref()) -2729 } -2730 -2731 /// Modify the number of remotely initiated streams that may be concurrently open -2732 /// -2733 /// No streams may be opened by the peer unless fewer than `count` are already open. Large -2734 /// `count`s increase both minimum and worst-case memory consumption. -2735 pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt) { -2736 self.streams.set_max_concurrent(dir, count); -2737 // If the limit was reduced, then a flow control update previously deemed insignificant may -2738 // now be significant. -2739 let pending = &mut self.spaces[SpaceId::Data].pending; -2740 self.streams.queue_max_stream_id(pending); -2741 } -2742 -2743 /// Modify the number of open paths allowed when multipath is enabled -2744 /// -2745 /// When reducing the number of concurrent paths this will only affect delaying sending -2746 /// new MAX_PATH_ID frames until fewer than this number of paths are possible. To -2747 /// actively reduce paths they must be closed using [`Connection::close_path`], which -2748 /// can also be used to close not-yet-opened paths. -2749 /// -2750 /// If multipath is not negotiated (see the [`TransportConfig`]) this can not enable -2751 /// multipath and will fail. -2752 pub fn set_max_concurrent_paths( -2753 &mut self, -2754 now: Instant, -2755 count: NonZeroU32, -2756 ) -> Result<(), MultipathNotNegotiated> { -2757 if !self.is_multipath_negotiated() { -2758 return Err(MultipathNotNegotiated { _private: () }); -2759 } -2760 self.max_concurrent_paths = count; -2761 -2762 let in_use_count = self -2763 .local_max_path_id -2764 .next() -2765 .saturating_sub(self.abandoned_paths.len() as u32) -2766 .as_u32(); -2767 let extra_needed = count.get().saturating_sub(in_use_count); -2768 let new_max_path_id = self.local_max_path_id.saturating_add(extra_needed); +2689 /// Closed connections become drained after a brief timeout to absorb any remaining in-flight +2690 /// packets from the peer. All drained connections have been closed. +2691 pub fn is_drained(&self) -> bool { +2692 self.state.is_drained() +2693 } +2694 +2695 /// For clients, if the peer accepted the 0-RTT data packets +2696 /// +2697 /// The value is meaningless until after the handshake completes. +2698 pub fn accepted_0rtt(&self) -> bool { +2699 self.crypto_state.accepted_0rtt +2700 } +2701 +2702 /// Whether 0-RTT is/was possible during the handshake +2703 pub fn has_0rtt(&self) -> bool { +2704 self.crypto_state.zero_rtt_enabled +2705 } +2706 +2707 /// Whether there are any pending retransmits +2708 pub fn has_pending_retransmits(&self) -> bool { +2709 !self.spaces[SpaceId::Data].pending.is_empty(&self.streams) +2710 } +2711 +2712 /// Look up whether we're the client or server of this Connection +2713 pub fn side(&self) -> Side { +2714 self.side.side() +2715 } +2716 +2717 /// Get the address observed by the remote over the given path +2718 pub fn path_observed_address(&self, path_id: PathId) -> Result<Option<SocketAddr>, ClosedPath> { +2719 self.path(path_id) +2720 .map(|path_data| { +2721 path_data +2722 .last_observed_addr_report +2723 .as_ref() +2724 .map(|observed| observed.socket_addr()) +2725 }) +2726 .ok_or(ClosedPath { _private: () }) +2727 } +2728 +2729 /// Current best estimate of this connection's latency (round-trip-time) +2730 pub fn rtt(&self, path_id: PathId) -> Option<Duration> { +2731 self.path(path_id).map(|d| d.rtt.get()) +2732 } +2733 +2734 /// Current state of this connection's congestion controller, for debugging purposes +2735 pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller> { +2736 self.path(path_id).map(|d| d.congestion.as_ref()) +2737 } +2738 +2739 /// Modify the number of remotely initiated streams that may be concurrently open +2740 /// +2741 /// No streams may be opened by the peer unless fewer than `count` are already open. Large +2742 /// `count`s increase both minimum and worst-case memory consumption. +2743 pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt) { +2744 self.streams.set_max_concurrent(dir, count); +2745 // If the limit was reduced, then a flow control update previously deemed insignificant may +2746 // now be significant. +2747 let pending = &mut self.spaces[SpaceId::Data].pending; +2748 self.streams.queue_max_stream_id(pending); +2749 } +2750 +2751 /// Modify the number of open paths allowed when multipath is enabled +2752 /// +2753 /// When reducing the number of concurrent paths this will only affect delaying sending +2754 /// new MAX_PATH_ID frames until fewer than this number of paths are possible. To +2755 /// actively reduce paths they must be closed using [`Connection::close_path`], which +2756 /// can also be used to close not-yet-opened paths. +2757 /// +2758 /// If multipath is not negotiated (see the [`TransportConfig`]) this can not enable +2759 /// multipath and will fail. +2760 pub fn set_max_concurrent_paths( +2761 &mut self, +2762 now: Instant, +2763 count: NonZeroU32, +2764 ) -> Result<(), MultipathNotNegotiated> { +2765 if !self.is_multipath_negotiated() { +2766 return Err(MultipathNotNegotiated { _private: () }); +2767 } +2768 self.max_concurrent_paths = count; 2769 -2770 self.set_max_path_id(now, new_max_path_id); -2771 -2772 Ok(()) -2773 } -2774 -2775 /// If needed, issues a new MAX_PATH_ID frame and new CIDs for any newly allowed paths -2776 fn set_max_path_id(&mut self, now: Instant, max_path_id: PathId) { -2777 if max_path_id <= self.local_max_path_id { -2778 return; -2779 } -2780 -2781 self.local_max_path_id = max_path_id; -2782 self.spaces[SpaceId::Data].pending.max_path_id = true; -2783 -2784 self.issue_first_path_cids(now); -2785 } -2786 -2787 /// Current number of remotely initiated streams that may be concurrently open -2788 /// -2789 /// If the target for this limit is reduced using [`set_max_concurrent_streams`](Self::set_max_concurrent_streams), -2790 /// it will not change immediately, even if fewer streams are open. Instead, it will -2791 /// decrement by one for each time a remotely initiated stream of matching directionality is closed. -2792 pub fn max_concurrent_streams(&self, dir: Dir) -> u64 { -2793 self.streams.max_concurrent(dir) -2794 } -2795 -2796 /// See [`TransportConfig::send_window()`] -2797 pub fn set_send_window(&mut self, send_window: u64) { -2798 self.streams.set_send_window(send_window); -2799 } -2800 -2801 /// See [`TransportConfig::receive_window()`] -2802 pub fn set_receive_window(&mut self, receive_window: VarInt) { -2803 if self.streams.set_receive_window(receive_window) { -2804 self.spaces[SpaceId::Data].pending.max_data = true; -2805 } -2806 } -2807 -2808 /// Whether the Multipath for QUIC extension is enabled. -2809 /// -2810 /// Multipath is only enabled after the handshake is completed and if it was enabled by both -2811 /// peers. -2812 pub fn is_multipath_negotiated(&self) -> bool { -2813 !self.is_handshaking() -2814 && self.config.max_concurrent_multipath_paths.is_some() -2815 && self.peer_params.initial_max_path_id.is_some() -2816 } -2817 -2818 fn on_ack_received( -2819 &mut self, -2820 now: Instant, -2821 space: SpaceId, -2822 ack: frame::Ack, -2823 ) -> Result<(), TransportError> { -2824 // All ACKs are referencing path 0 -2825 let path = PathId::ZERO; -2826 self.inner_on_ack_received(now, space, path, ack) -2827 } -2828 -2829 fn on_path_ack_received( -2830 &mut self, -2831 now: Instant, -2832 space: SpaceId, -2833 path_ack: frame::PathAck, -2834 ) -> Result<(), TransportError> { -2835 let (ack, path) = path_ack.into_ack(); -2836 self.inner_on_ack_received(now, space, path, ack) -2837 } -2838 -2839 /// Handles an ACK frame acknowledging packets sent on *path*. -2840 fn inner_on_ack_received( -2841 &mut self, -2842 now: Instant, -2843 space: SpaceId, -2844 path: PathId, -2845 ack: frame::Ack, -2846 ) -> Result<(), TransportError> { -2847 if !self.spaces[space].number_spaces.contains_key(&path) { -2848 if self.abandoned_paths.contains(&path) { -2849 // See also -2850 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-21.html#section-3.4.3-3 -2851 // > When an endpoint finally deletes all state associated with the path [...] -2852 // > PATH_ACK frames received with an abandoned path ID are silently ignored, -2853 // > as specified in Section 4. -2854 trace!("silently ignoring PATH_ACK on discarded path"); -2855 return Ok(()); -2856 } else { -2857 return Err(TransportError::PROTOCOL_VIOLATION( -2858 "received PATH_ACK with path ID never used", -2859 )); -2860 } -2861 } -2862 if ack.largest >= self.spaces[space].for_path(path).next_packet_number { -2863 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked")); -2864 } -2865 // `Some(pn)` if this ACK raised `largest_acked_packet_pn`. -2866 let new_largest_pn = { -2867 let space = &mut self.spaces[space].for_path(path); -2868 if space -2869 .largest_acked_packet_pn -2870 .is_none_or(|pn| ack.largest > pn) -2871 { -2872 space.largest_acked_packet_pn = Some(ack.largest); -2873 if let Some(info) = space.sent_packets.get(ack.largest) { -2874 // This should always succeed, but a misbehaving peer might ACK a packet we -2875 // haven't sent. At worst, that will result in us spuriously reducing the -2876 // congestion window. -2877 space.largest_acked_packet_send_time = info.time_sent; -2878 } -2879 Some(ack.largest) -2880 } else { -2881 None -2882 } -2883 }; -2884 -2885 if self.detect_spurious_loss(&ack, space, path) { -2886 self.path_stats.for_path(path).spurious_congestion_events += 1; -2887 self.path_data_mut(path) -2888 .congestion -2889 .on_spurious_congestion_event(); -2890 } -2891 -2892 // Avoid DoS from unreasonably huge ack ranges by filtering out just the new acks. -2893 let mut newly_acked = ArrayRangeSet::new(); -2894 for range in ack.iter() { -2895 self.spaces[space].for_path(path).check_ack(range.clone())?; -2896 for (pn, _) in self.spaces[space] -2897 .for_path(path) -2898 .sent_packets -2899 .iter_range(range) -2900 { -2901 newly_acked.insert_one(pn); -2902 } -2903 } -2904 -2905 if newly_acked.is_empty() { -2906 return Ok(()); -2907 } -2908 -2909 let mut ack_eliciting_acked = false; -2910 for packet in newly_acked.elts() { -2911 if let Some(info) = self.spaces[space].for_path(path).take(packet) { -2912 for (acked_path_id, acked_pn) in info.largest_acked.iter() { -2913 // Assume ACKs for all packets below the largest acknowledged in -2914 // `packet` have been received. This can cause the peer to spuriously -2915 // retransmit if some of our earlier ACKs were lost, but allows for -2916 // simpler state tracking. See discussion at -2917 // https://www.rfc-editor.org/rfc/rfc9000.html#name-limiting-ranges-by-tracking -2918 if let Some(pns) = self.spaces[space].path_space_mut(*acked_path_id) { -2919 pns.pending_acks.subtract_below(*acked_pn); -2920 } -2921 } -2922 ack_eliciting_acked |= info.ack_eliciting; -2923 -2924 // Notify MTU discovery that a packet was acked, because it might be an MTU probe -2925 let path_data = self.path_data_mut(path); -2926 let mtu_updated = path_data.mtud.on_acked(space.kind(), packet, info.size); -2927 if mtu_updated { -2928 path_data -2929 .congestion -2930 .on_mtu_update(path_data.mtud.current_mtu()); -2931 } -2932 -2933 // Notify ack frequency that a packet was acked, because it might contain an ACK_FREQUENCY frame -2934 self.ack_frequency.on_acked(path, packet); -2935 -2936 self.on_packet_acked(now, path, packet, info); -2937 } -2938 } -2939 -2940 let largest_ackd = self.spaces[space].for_path(path).largest_acked_packet_pn; -2941 let path_data = self.path_data_mut(path); -2942 let app_limited = path_data.app_limited; -2943 let in_flight = path_data.in_flight.bytes; -2944 -2945 path_data -2946 .congestion -2947 .on_end_acks(now, in_flight, app_limited, largest_ackd); -2948 -2949 if new_largest_pn.is_some() && ack_eliciting_acked { -2950 let ack_delay = if space != SpaceId::Data { -2951 Duration::from_micros(0) -2952 } else { -2953 cmp::min( -2954 self.ack_frequency.peer_max_ack_delay, -2955 Duration::from_micros(ack.delay << self.peer_params.ack_delay_exponent.0), -2956 ) -2957 }; -2958 let rtt = now.saturating_duration_since( -2959 self.spaces[space] -2960 .for_path(path) -2961 .largest_acked_packet_send_time, -2962 ); -2963 -2964 let next_pn = self.spaces[space].for_path(path).next_packet_number; -2965 let path_data = self.path_data_mut(path); -2966 // TODO(@divma): should be a method of path, should be contained in a single place -2967 path_data.rtt.update(ack_delay, rtt); -2968 if path_data.first_packet_after_rtt_sample.is_none() { -2969 path_data.first_packet_after_rtt_sample = Some((space.kind(), next_pn)); -2970 } -2971 } -2972 -2973 // Must be called before crypto/pto_count are clobbered -2974 self.detect_lost_packets(now, space, path, true); -2975 -2976 // If the peer did not complete the handshake address validation the ACK could be -2977 // spoofed, e.g. in the Initial space. Setting the pto_count back to 0 removes the -2978 // exponential backoff from the PTO timer and would result in too many tail-loss -2979 // probes being sent. -2980 if self.peer_completed_handshake_address_validation() { -2981 self.path_data_mut(path).pto_count = 0; -2982 } +2770 let in_use_count = self +2771 .local_max_path_id +2772 .next() +2773 .saturating_sub(self.abandoned_paths.len() as u32) +2774 .as_u32(); +2775 let extra_needed = count.get().saturating_sub(in_use_count); +2776 let new_max_path_id = self.local_max_path_id.saturating_add(extra_needed); +2777 +2778 self.set_max_path_id(now, new_max_path_id); +2779 +2780 Ok(()) +2781 } +2782 +2783 /// If needed, issues a new MAX_PATH_ID frame and new CIDs for any newly allowed paths +2784 fn set_max_path_id(&mut self, now: Instant, max_path_id: PathId) { +2785 if max_path_id <= self.local_max_path_id { +2786 return; +2787 } +2788 +2789 self.local_max_path_id = max_path_id; +2790 self.spaces[SpaceId::Data].pending.max_path_id = true; +2791 +2792 self.issue_first_path_cids(now); +2793 } +2794 +2795 /// Current number of remotely initiated streams that may be concurrently open +2796 /// +2797 /// If the target for this limit is reduced using [`set_max_concurrent_streams`](Self::set_max_concurrent_streams), +2798 /// it will not change immediately, even if fewer streams are open. Instead, it will +2799 /// decrement by one for each time a remotely initiated stream of matching directionality is closed. +2800 pub fn max_concurrent_streams(&self, dir: Dir) -> u64 { +2801 self.streams.max_concurrent(dir) +2802 } +2803 +2804 /// See [`TransportConfig::send_window()`] +2805 pub fn set_send_window(&mut self, send_window: u64) { +2806 self.streams.set_send_window(send_window); +2807 } +2808 +2809 /// See [`TransportConfig::receive_window()`] +2810 pub fn set_receive_window(&mut self, receive_window: VarInt) { +2811 if self.streams.set_receive_window(receive_window) { +2812 self.spaces[SpaceId::Data].pending.max_data = true; +2813 } +2814 } +2815 +2816 /// Whether the Multipath for QUIC extension is enabled. +2817 /// +2818 /// Multipath is only enabled after the handshake is completed and if it was enabled by both +2819 /// peers. +2820 pub fn is_multipath_negotiated(&self) -> bool { +2821 !self.is_handshaking() +2822 && self.config.max_concurrent_multipath_paths.is_some() +2823 && self.peer_params.initial_max_path_id.is_some() +2824 } +2825 +2826 fn on_ack_received( +2827 &mut self, +2828 now: Instant, +2829 space: SpaceId, +2830 ack: frame::Ack, +2831 ) -> Result<(), TransportError> { +2832 // All ACKs are referencing path 0 +2833 let path = PathId::ZERO; +2834 self.inner_on_ack_received(now, space, path, ack) +2835 } +2836 +2837 fn on_path_ack_received( +2838 &mut self, +2839 now: Instant, +2840 space: SpaceId, +2841 path_ack: frame::PathAck, +2842 ) -> Result<(), TransportError> { +2843 let (ack, path) = path_ack.into_ack(); +2844 self.inner_on_ack_received(now, space, path, ack) +2845 } +2846 +2847 /// Handles an ACK frame acknowledging packets sent on *path*. +2848 fn inner_on_ack_received( +2849 &mut self, +2850 now: Instant, +2851 space: SpaceId, +2852 path: PathId, +2853 ack: frame::Ack, +2854 ) -> Result<(), TransportError> { +2855 if !self.spaces[space].number_spaces.contains_key(&path) { +2856 if self.abandoned_paths.contains(&path) { +2857 // See also +2858 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-21.html#section-3.4.3-3 +2859 // > When an endpoint finally deletes all state associated with the path [...] +2860 // > PATH_ACK frames received with an abandoned path ID are silently ignored, +2861 // > as specified in Section 4. +2862 trace!("silently ignoring PATH_ACK on discarded path"); +2863 return Ok(()); +2864 } else { +2865 return Err(TransportError::PROTOCOL_VIOLATION( +2866 "received PATH_ACK with path ID never used", +2867 )); +2868 } +2869 } +2870 if ack.largest >= self.spaces[space].for_path(path).next_packet_number { +2871 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked")); +2872 } +2873 // `Some(pn)` if this ACK raised `largest_acked_packet_pn`. +2874 let new_largest_pn = { +2875 let space = &mut self.spaces[space].for_path(path); +2876 if space +2877 .largest_acked_packet_pn +2878 .is_none_or(|pn| ack.largest > pn) +2879 { +2880 space.largest_acked_packet_pn = Some(ack.largest); +2881 if let Some(info) = space.sent_packets.get(ack.largest) { +2882 // This should always succeed, but a misbehaving peer might ACK a packet we +2883 // haven't sent. At worst, that will result in us spuriously reducing the +2884 // congestion window. +2885 space.largest_acked_packet_send_time = info.time_sent; +2886 } +2887 Some(ack.largest) +2888 } else { +2889 None +2890 } +2891 }; +2892 +2893 if self.detect_spurious_loss(&ack, space, path) { +2894 self.path_stats.for_path(path).spurious_congestion_events += 1; +2895 self.path_data_mut(path) +2896 .congestion +2897 .on_spurious_congestion_event(); +2898 } +2899 +2900 // Avoid DoS from unreasonably huge ack ranges by filtering out just the new acks. +2901 let mut newly_acked = ArrayRangeSet::new(); +2902 for range in ack.iter() { +2903 self.spaces[space].for_path(path).check_ack(range.clone())?; +2904 for (pn, _) in self.spaces[space] +2905 .for_path(path) +2906 .sent_packets +2907 .iter_range(range) +2908 { +2909 newly_acked.insert_one(pn); +2910 } +2911 } +2912 +2913 if newly_acked.is_empty() { +2914 return Ok(()); +2915 } +2916 +2917 let mut ack_eliciting_acked = false; +2918 for packet in newly_acked.elts() { +2919 if let Some(info) = self.spaces[space].for_path(path).take(packet) { +2920 for (acked_path_id, acked_pn) in info.largest_acked.iter() { +2921 // Assume ACKs for all packets below the largest acknowledged in +2922 // `packet` have been received. This can cause the peer to spuriously +2923 // retransmit if some of our earlier ACKs were lost, but allows for +2924 // simpler state tracking. See discussion at +2925 // https://www.rfc-editor.org/rfc/rfc9000.html#name-limiting-ranges-by-tracking +2926 if let Some(pns) = self.spaces[space].path_space_mut(*acked_path_id) { +2927 pns.pending_acks.subtract_below(*acked_pn); +2928 } +2929 } +2930 ack_eliciting_acked |= info.ack_eliciting; +2931 +2932 // Notify MTU discovery that a packet was acked, because it might be an MTU probe +2933 let path_data = self.path_data_mut(path); +2934 let mtu_updated = path_data.mtud.on_acked(space.kind(), packet, info.size); +2935 if mtu_updated { +2936 path_data +2937 .congestion +2938 .on_mtu_update(path_data.mtud.current_mtu()); +2939 } +2940 +2941 // Notify ack frequency that a packet was acked, because it might contain an ACK_FREQUENCY frame +2942 self.ack_frequency.on_acked(path, packet); +2943 +2944 self.on_packet_acked(now, path, packet, info); +2945 } +2946 } +2947 +2948 let largest_ackd = self.spaces[space].for_path(path).largest_acked_packet_pn; +2949 let path_data = self.path_data_mut(path); +2950 let app_limited = path_data.app_limited; +2951 let in_flight = path_data.in_flight.bytes; +2952 +2953 path_data +2954 .congestion +2955 .on_end_acks(now, in_flight, app_limited, largest_ackd); +2956 +2957 if new_largest_pn.is_some() && ack_eliciting_acked { +2958 let ack_delay = if space != SpaceId::Data { +2959 Duration::from_micros(0) +2960 } else { +2961 cmp::min( +2962 self.ack_frequency.peer_max_ack_delay, +2963 Duration::from_micros(ack.delay << self.peer_params.ack_delay_exponent.0), +2964 ) +2965 }; +2966 let rtt = now.saturating_duration_since( +2967 self.spaces[space] +2968 .for_path(path) +2969 .largest_acked_packet_send_time, +2970 ); +2971 +2972 let next_pn = self.spaces[space].for_path(path).next_packet_number; +2973 let path_data = self.path_data_mut(path); +2974 // TODO(@divma): should be a method of path, should be contained in a single place +2975 path_data.rtt.update(ack_delay, rtt); +2976 if path_data.first_packet_after_rtt_sample.is_none() { +2977 path_data.first_packet_after_rtt_sample = Some((space.kind(), next_pn)); +2978 } +2979 } +2980 +2981 // Must be called before crypto/pto_count are clobbered +2982 self.detect_lost_packets(now, space, path, true); 2983 -2984 // Explicit congestion notification -2985 // TODO(@divma): this code is a good example of logic that should be contained in a single -2986 // place but it's split between the path data and the packet number space data, we should -2987 // find a way to make this work without two lookups -2988 if self.path_data(path).sending_ecn { -2989 if let Some(ecn) = ack.ecn { -2990 // We only examine ECN counters from ACKs that we are certain we received in transmit -2991 // order, allowing us to compute an increase in ECN counts to compare against the number -2992 // of newly acked packets that remains well-defined in the presence of arbitrary packet -2993 // reordering. -2994 if let Some(largest_sent_pn) = new_largest_pn { -2995 let sent = self.spaces[space] -2996 .for_path(path) -2997 .largest_acked_packet_send_time; -2998 self.process_ecn( -2999 now, -3000 space, -3001 path, -3002 newly_acked.len() as u64, -3003 ecn, -3004 sent, -3005 largest_sent_pn, -3006 ); -3007 } -3008 } else { -3009 // We always start out sending ECN, so any ack that doesn't acknowledge it disables it. -3010 debug!("ECN not acknowledged by peer"); -3011 self.path_data_mut(path).sending_ecn = false; -3012 } -3013 } -3014 -3015 self.set_loss_detection_timer(now, path); -3016 Ok(()) -3017 } -3018 -3019 fn detect_spurious_loss(&mut self, ack: &frame::Ack, space: SpaceId, path: PathId) -> bool { -3020 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets; -3021 -3022 if lost_packets.is_empty() { -3023 return false; -3024 } -3025 -3026 for range in ack.iter() { -3027 let spurious_losses: Vec<u64> = lost_packets -3028 .iter_range(range.clone()) -3029 .map(|(pn, _info)| pn) -3030 .collect(); -3031 -3032 for pn in spurious_losses { -3033 lost_packets.remove(pn); -3034 } -3035 } -3036 -3037 // If this ACK frame acknowledged all deemed lost packets, -3038 // then we have raised a spurious congestion event in the past. -3039 // We cannot conclude when there are remaining packets, -3040 // but future ACK frames might indicate a spurious loss detection. -3041 lost_packets.is_empty() -3042 } -3043 -3044 /// Drain lost packets that we reasonably think will never arrive -3045 /// -3046 /// The current criterion is copied from `msquic`: -3047 /// discard packets that were sent earlier than 2 probe timeouts ago. -3048 fn drain_lost_packets(&mut self, now: Instant, space: SpaceId, path: PathId) { -3049 let two_pto = 2 * self.path_data(path).rtt.pto_base(); -3050 -3051 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets; -3052 lost_packets.retain(|_pn, info| now.saturating_duration_since(info.time_sent) <= two_pto); -3053 } -3054 -3055 /// Process a new ECN block from an in-order ACK -3056 fn process_ecn( -3057 &mut self, -3058 now: Instant, -3059 space: SpaceId, -3060 path: PathId, -3061 newly_acked_pn: u64, -3062 ecn: frame::EcnCounts, -3063 largest_sent_time: Instant, -3064 largest_sent_pn: u64, -3065 ) { -3066 match self.spaces[space] -3067 .for_path(path) -3068 .detect_ecn(newly_acked_pn, ecn) -3069 { -3070 Err(e) => { -3071 debug!("halting ECN due to verification failure: {}", e); -3072 -3073 self.path_data_mut(path).sending_ecn = false; -3074 // Wipe out the existing value because it might be garbage and could interfere with -3075 // future attempts to use ECN on new paths. -3076 self.spaces[space].for_path(path).ecn_feedback = frame::EcnCounts::ZERO; -3077 } -3078 Ok(false) => {} -3079 Ok(true) => { -3080 self.path_stats.for_path(path).congestion_events += 1; -3081 self.path_data_mut(path).congestion.on_congestion_event( -3082 now, -3083 largest_sent_time, -3084 false, -3085 true, -3086 0, -3087 largest_sent_pn, -3088 ); -3089 } -3090 } -3091 } -3092 -3093 // Not timing-aware, so it's safe to call this for inferred acks, such as arise from -3094 // high-latency handshakes -3095 fn on_packet_acked(&mut self, now: Instant, path_id: PathId, pn: u64, info: SentPacket) { -3096 let path = self.path_data_mut(path_id); -3097 let app_limited = path.app_limited; -3098 path.remove_in_flight(&info); -3099 if info.ack_eliciting && info.path_generation == path.generation() { -3100 // Only pass ACKs to the congestion controller if it belongs to this exact -3101 // generation of the path. Otherwise we might be feeding ACKs from the previous -3102 // 4-tuple into our congestion controller. -3103 let rtt = path.rtt; -3104 path.congestion -3105 .on_ack(now, info.time_sent, info.size.into(), pn, app_limited, &rtt); -3106 } -3107 -3108 // Update state for confirmed delivery of frames -3109 if let Some(retransmits) = info.retransmits.get() { -3110 for (id, _) in retransmits.reset_stream.iter() { -3111 self.streams.reset_acked(*id); -3112 } -3113 } -3114 -3115 for frame in info.stream_frames { -3116 self.streams.received_ack_of(frame); -3117 } -3118 } -3119 -3120 fn set_key_discard_timer(&mut self, now: Instant, space: SpaceKind) { -3121 let start = if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) { -3122 now -3123 } else { -3124 self.crypto_state -3125 .prev_crypto -3126 .as_ref() -3127 .expect("no previous keys") -3128 .end_packet -3129 .as_ref() -3130 .expect("update not acknowledged yet") -3131 .1 -3132 }; -3133 -3134 // QUIC-MULTIPATH § 2.5 Key Phase Update Process: use largest PTO of all paths. -3135 self.timers.set( -3136 Timer::Conn(ConnTimer::KeyDiscard), -3137 start + self.max_pto_for_space(space) * 3, -3138 self.qlog.with_time(now), -3139 ); -3140 } +2984 // If the peer did not complete the handshake address validation the ACK could be +2985 // spoofed, e.g. in the Initial space. Setting the pto_count back to 0 removes the +2986 // exponential backoff from the PTO timer and would result in too many tail-loss +2987 // probes being sent. +2988 if self.peer_completed_handshake_address_validation() { +2989 self.path_data_mut(path).pto_count = 0; +2990 } +2991 +2992 // Explicit congestion notification +2993 // TODO(@divma): this code is a good example of logic that should be contained in a single +2994 // place but it's split between the path data and the packet number space data, we should +2995 // find a way to make this work without two lookups +2996 if self.path_data(path).sending_ecn { +2997 if let Some(ecn) = ack.ecn { +2998 // We only examine ECN counters from ACKs that we are certain we received in transmit +2999 // order, allowing us to compute an increase in ECN counts to compare against the number +3000 // of newly acked packets that remains well-defined in the presence of arbitrary packet +3001 // reordering. +3002 if let Some(largest_sent_pn) = new_largest_pn { +3003 let sent = self.spaces[space] +3004 .for_path(path) +3005 .largest_acked_packet_send_time; +3006 self.process_ecn( +3007 now, +3008 space, +3009 path, +3010 newly_acked.len() as u64, +3011 ecn, +3012 sent, +3013 largest_sent_pn, +3014 ); +3015 } +3016 } else { +3017 // We always start out sending ECN, so any ack that doesn't acknowledge it disables it. +3018 debug!("ECN not acknowledged by peer"); +3019 self.path_data_mut(path).sending_ecn = false; +3020 } +3021 } +3022 +3023 self.set_loss_detection_timer(now, path); +3024 Ok(()) +3025 } +3026 +3027 fn detect_spurious_loss(&mut self, ack: &frame::Ack, space: SpaceId, path: PathId) -> bool { +3028 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets; +3029 +3030 if lost_packets.is_empty() { +3031 return false; +3032 } +3033 +3034 for range in ack.iter() { +3035 let spurious_losses: Vec<u64> = lost_packets +3036 .iter_range(range.clone()) +3037 .map(|(pn, _info)| pn) +3038 .collect(); +3039 +3040 for pn in spurious_losses { +3041 lost_packets.remove(pn); +3042 } +3043 } +3044 +3045 // If this ACK frame acknowledged all deemed lost packets, +3046 // then we have raised a spurious congestion event in the past. +3047 // We cannot conclude when there are remaining packets, +3048 // but future ACK frames might indicate a spurious loss detection. +3049 lost_packets.is_empty() +3050 } +3051 +3052 /// Drain lost packets that we reasonably think will never arrive +3053 /// +3054 /// The current criterion is copied from `msquic`: +3055 /// discard packets that were sent earlier than 2 probe timeouts ago. +3056 fn drain_lost_packets(&mut self, now: Instant, space: SpaceId, path: PathId) { +3057 let two_pto = 2 * self.path_data(path).rtt.pto_base(); +3058 +3059 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets; +3060 lost_packets.retain(|_pn, info| now.saturating_duration_since(info.time_sent) <= two_pto); +3061 } +3062 +3063 /// Process a new ECN block from an in-order ACK +3064 fn process_ecn( +3065 &mut self, +3066 now: Instant, +3067 space: SpaceId, +3068 path: PathId, +3069 newly_acked_pn: u64, +3070 ecn: frame::EcnCounts, +3071 largest_sent_time: Instant, +3072 largest_sent_pn: u64, +3073 ) { +3074 match self.spaces[space] +3075 .for_path(path) +3076 .detect_ecn(newly_acked_pn, ecn) +3077 { +3078 Err(e) => { +3079 debug!("halting ECN due to verification failure: {}", e); +3080 +3081 self.path_data_mut(path).sending_ecn = false; +3082 // Wipe out the existing value because it might be garbage and could interfere with +3083 // future attempts to use ECN on new paths. +3084 self.spaces[space].for_path(path).ecn_feedback = frame::EcnCounts::ZERO; +3085 } +3086 Ok(false) => {} +3087 Ok(true) => { +3088 self.path_stats.for_path(path).congestion_events += 1; +3089 self.path_data_mut(path).congestion.on_congestion_event( +3090 now, +3091 largest_sent_time, +3092 false, +3093 true, +3094 0, +3095 largest_sent_pn, +3096 ); +3097 } +3098 } +3099 } +3100 +3101 // Not timing-aware, so it's safe to call this for inferred acks, such as arise from +3102 // high-latency handshakes +3103 fn on_packet_acked(&mut self, now: Instant, path_id: PathId, pn: u64, info: SentPacket) { +3104 let path = self.path_data_mut(path_id); +3105 let app_limited = path.app_limited; +3106 path.remove_in_flight(&info); +3107 if info.ack_eliciting && info.path_generation == path.generation() { +3108 // Only pass ACKs to the congestion controller if it belongs to this exact +3109 // generation of the path. Otherwise we might be feeding ACKs from the previous +3110 // 4-tuple into our congestion controller. +3111 let rtt = path.rtt; +3112 path.congestion +3113 .on_ack(now, info.time_sent, info.size.into(), pn, app_limited, &rtt); +3114 } +3115 +3116 // Update state for confirmed delivery of frames +3117 if let Some(retransmits) = info.retransmits.get() { +3118 for (id, _) in retransmits.reset_stream.iter() { +3119 self.streams.reset_acked(*id); +3120 } +3121 } +3122 +3123 for frame in info.stream_frames { +3124 self.streams.received_ack_of(frame); +3125 } +3126 } +3127 +3128 fn set_key_discard_timer(&mut self, now: Instant, space: SpaceKind) { +3129 let start = if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) { +3130 now +3131 } else { +3132 self.crypto_state +3133 .prev_crypto +3134 .as_ref() +3135 .expect("no previous keys") +3136 .end_packet +3137 .as_ref() +3138 .expect("update not acknowledged yet") +3139 .1 +3140 }; 3141 -3142 /// Handle a [`PathTimer::LossDetection`] timeout. -3143 /// -3144 /// This timer expires for two reasons: -3145 /// - An ACK-eliciting packet we sent should be considered lost. -3146 /// - The PTO may have expired and a tail-loss probe needs to be scheduled. -3147 /// -3148 /// The former needs us to schedule re-transmission of the lost data. -3149 /// -3150 /// The latter means we have not received an ACK for an ack-eliciting packet we sent -3151 /// within the PTO time-window. We need to schedule a tail-loss probe, an ack-eliciting -3152 /// packet, to try and elicit new acknowledgements. These new acknowledgements will -3153 /// indicate whether the previously sent packets were lost or not. -3154 fn on_loss_detection_timeout(&mut self, now: Instant, path_id: PathId) { -3155 if let Some((_, pn_space)) = self.loss_time_and_space(path_id) { -3156 // Time threshold loss Detection -3157 self.detect_lost_packets(now, pn_space, path_id, false); -3158 self.set_loss_detection_timer(now, path_id); -3159 return; -3160 } -3161 -3162 let Some((_, space)) = self.pto_time_and_space(now, path_id) else { -3163 error!(%path_id, "PTO expired while unset"); -3164 return; -3165 }; -3166 trace!( -3167 in_flight = self.path_data(path_id).in_flight.bytes, -3168 count = self.path_data(path_id).pto_count, -3169 ?space, -3170 %path_id, -3171 "PTO fired" -3172 ); -3173 -3174 let count = match self.path_data(path_id).in_flight.ack_eliciting { -3175 // A PTO when we're not expecting any ACKs must be due to handshake -3176 // anti-amplification deadlock prevention. -3177 0 => { -3178 debug_assert!(!self.peer_completed_handshake_address_validation()); -3179 1 -3180 } -3181 // Conventional loss probe -3182 _ => 2, -3183 }; -3184 let pns = self.spaces[space].for_path(path_id); -3185 pns.loss_probes = pns.loss_probes.saturating_add(count); -3186 let path_data = self.path_data_mut(path_id); -3187 path_data.pto_count = path_data.pto_count.saturating_add(1); -3188 self.set_loss_detection_timer(now, path_id); -3189 } -3190 -3191 /// Detect any lost packets -3192 /// -3193 /// There are two cases in which we detects lost packets: -3194 /// -3195 /// - We received an ACK packet. -3196 /// - The [`PathTimer::LossDetection`] timer expired. So there is an un-acknowledged packet -3197 /// that was followed by an acknowledged packet. The loss timer for this -3198 /// un-acknowledged packet expired and we need to detect that packet as lost. -3199 /// -3200 /// Packets are lost if they are both (See RFC9002 §6.1): -3201 /// -3202 /// - Unacknowledged, in flight and sent prior to an acknowledged packet. -3203 /// - Old enough by either: -3204 /// - Having a packet number [`TransportConfig::packet_threshold`] lower then the last -3205 /// acknowledged packet. -3206 /// - Being sent [`TransportConfig::time_threshold`] * RTT in the past. -3207 fn detect_lost_packets( -3208 &mut self, -3209 now: Instant, -3210 pn_space: SpaceId, -3211 path_id: PathId, -3212 due_to_ack: bool, -3213 ) { -3214 let mut lost_packets = Vec::<u64>::new(); -3215 let mut lost_mtu_probe = None; -3216 let mut in_persistent_congestion = false; -3217 let mut size_of_lost_packets = 0u64; -3218 self.spaces[pn_space].for_path(path_id).loss_time = None; -3219 -3220 // Find all the lost packets, populating all variables initialised above. -3221 -3222 let path = self.path_data(path_id); -3223 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe(); -3224 let loss_delay = path -3225 .rtt -3226 .conservative() -3227 .mul_f32(self.config.time_threshold) -3228 .max(TIMER_GRANULARITY); -3229 let first_packet_after_rtt_sample = path.first_packet_after_rtt_sample; -3230 -3231 let largest_acked_packet_pn = self.spaces[pn_space] -3232 .for_path(path_id) -3233 .largest_acked_packet_pn -3234 .expect("detect_lost_packets only to be called if path received at least one ACK"); -3235 let packet_threshold = self.config.packet_threshold as u64; -3236 -3237 // InPersistentCongestion: Determine if all packets in the time period before the newest -3238 // lost packet, including the edges, are marked lost. PTO computation must always -3239 // include max ACK delay, i.e. operate as if in Data space (see RFC9001 §7.6.1). -3240 let congestion_period = self -3241 .pto(SpaceKind::Data, path_id) -3242 .saturating_mul(self.config.persistent_congestion_threshold); -3243 let mut persistent_congestion_start: Option<Instant> = None; -3244 let mut prev_packet = None; -3245 let space = self.spaces[pn_space].for_path(path_id); -3246 -3247 for (packet, info) in space.sent_packets.iter_range(0..largest_acked_packet_pn) { -3248 if prev_packet != Some(packet.wrapping_sub(1)) { -3249 // An intervening packet was acknowledged -3250 persistent_congestion_start = None; -3251 } -3252 -3253 // Packets sent before now - loss_delay are deemed lost. -3254 // However, we avoid subtraction as it can panic and there's no -3255 // saturating equivalent of this subtraction operation with a Duration. -3256 let packet_too_old = now.saturating_duration_since(info.time_sent) >= loss_delay; -3257 if packet_too_old || largest_acked_packet_pn >= packet + packet_threshold { -3258 // The packet should be declared lost. -3259 if Some(packet) == in_flight_mtu_probe { -3260 // Lost MTU probes are not included in `lost_packets`, because they -3261 // should not trigger a congestion control response -3262 lost_mtu_probe = in_flight_mtu_probe; -3263 } else { -3264 lost_packets.push(packet); -3265 size_of_lost_packets += info.size as u64; -3266 if info.ack_eliciting && due_to_ack { -3267 match persistent_congestion_start { -3268 // Two ACK-eliciting packets lost more than -3269 // congestion_period apart, with no ACKed packets in between -3270 Some(start) if info.time_sent - start > congestion_period => { -3271 in_persistent_congestion = true; -3272 } -3273 // Persistent congestion must start after the first RTT sample -3274 None if first_packet_after_rtt_sample -3275 .is_some_and(|x| x < (pn_space.kind(), packet)) => -3276 { -3277 persistent_congestion_start = Some(info.time_sent); -3278 } -3279 _ => {} -3280 } -3281 } -3282 } -3283 } else { -3284 // The packet should not yet be declared lost. -3285 if space.loss_time.is_none() { -3286 // Since we iterate in order the lowest packet number's loss time will -3287 // always be the earliest. -3288 space.loss_time = Some(info.time_sent + loss_delay); -3289 } -3290 persistent_congestion_start = None; -3291 } -3292 -3293 prev_packet = Some(packet); -3294 } -3295 -3296 self.handle_lost_packets( -3297 pn_space, -3298 path_id, -3299 now, -3300 lost_packets, -3301 lost_mtu_probe, -3302 loss_delay, -3303 in_persistent_congestion, -3304 size_of_lost_packets, -3305 ); -3306 } -3307 -3308 /// Drops the path state, declaring any remaining in-flight packets as lost -3309 fn discard_path(&mut self, path_id: PathId, now: Instant) { -3310 trace!(%path_id, "dropping path state"); -3311 let path = self.path_data(path_id); -3312 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe(); -3313 -3314 let mut size_of_lost_packets = 0u64; // add to path_stats.lost_bytes; -3315 let lost_pns: Vec<_> = self.spaces[SpaceId::Data] -3316 .for_path(path_id) -3317 .sent_packets -3318 .iter() -3319 .filter(|(pn, _info)| Some(*pn) != in_flight_mtu_probe) -3320 .map(|(pn, info)| { -3321 size_of_lost_packets += info.size as u64; -3322 pn -3323 }) -3324 .collect(); -3325 -3326 if !lost_pns.is_empty() { -3327 trace!( -3328 %path_id, -3329 count = lost_pns.len(), -3330 lost_bytes = size_of_lost_packets, -3331 "packets lost on path abandon" -3332 ); -3333 self.handle_lost_packets( -3334 SpaceId::Data, -3335 path_id, -3336 now, -3337 lost_pns, -3338 in_flight_mtu_probe, -3339 Duration::ZERO, -3340 false, -3341 size_of_lost_packets, -3342 ); -3343 } -3344 // Before removing the path, we fetch the final path stats via `Self::path_stats`. -3345 // This updates some values for the last time. -3346 let path_stats = self.path_stats.discard(&path_id); -3347 self.partial_stats += path_stats; -3348 self.paths.remove(&path_id); -3349 self.spaces[SpaceId::Data].number_spaces.remove(&path_id); -3350 -3351 self.events.push_back( -3352 PathEvent::Discarded { -3353 id: path_id, -3354 path_stats: Box::new(path_stats), -3355 } -3356 .into(), -3357 ); -3358 } -3359 -3360 fn handle_lost_packets( -3361 &mut self, -3362 pn_space: SpaceId, -3363 path_id: PathId, -3364 now: Instant, -3365 lost_packets: Vec<u64>, -3366 lost_mtu_probe: Option<u64>, -3367 loss_delay: Duration, -3368 in_persistent_congestion: bool, -3369 size_of_lost_packets: u64, -3370 ) { -3371 debug_assert!(lost_packets.is_sorted(), "lost_packets must be sorted"); -3372 -3373 self.drain_lost_packets(now, pn_space, path_id); -3374 -3375 // OnPacketsLost -3376 if let Some(largest_lost) = lost_packets.last().cloned() { -3377 let old_bytes_in_flight = self.path_data_mut(path_id).in_flight.bytes; -3378 let largest_lost_sent = self.spaces[pn_space] -3379 .for_path(path_id) -3380 .sent_packets -3381 .get(largest_lost) -3382 .unwrap() -3383 .time_sent; -3384 let path_stats = self.path_stats.for_path(path_id); -3385 path_stats.lost_packets += lost_packets.len() as u64; -3386 path_stats.lost_bytes += size_of_lost_packets; -3387 trace!( -3388 %path_id, -3389 count = lost_packets.len(), -3390 lost_bytes = size_of_lost_packets, -3391 "packets lost", -3392 ); -3393 -3394 for &packet in &lost_packets { -3395 let Some(info) = self.spaces[pn_space].for_path(path_id).take(packet) else { -3396 continue; -3397 }; -3398 self.qlog -3399 .emit_packet_lost(packet, &info, loss_delay, pn_space.kind(), now); -3400 self.paths -3401 .get_mut(&path_id) -3402 .unwrap() -3403 .remove_in_flight(&info); -3404 -3405 for frame in info.stream_frames { -3406 self.streams.retransmit(frame); -3407 } -3408 self.spaces[pn_space].pending |= info.retransmits; -3409 let path = self.path_data_mut(path_id); -3410 path.mtud.on_non_probe_lost(packet, info.size); -3411 path.congestion.on_packet_lost(info.size, packet, now); +3142 // QUIC-MULTIPATH § 2.5 Key Phase Update Process: use largest PTO of all paths. +3143 self.timers.set( +3144 Timer::Conn(ConnTimer::KeyDiscard), +3145 start + self.max_pto_for_space(space) * 3, +3146 self.qlog.with_time(now), +3147 ); +3148 } +3149 +3150 /// Handle a [`PathTimer::LossDetection`] timeout. +3151 /// +3152 /// This timer expires for two reasons: +3153 /// - An ACK-eliciting packet we sent should be considered lost. +3154 /// - The PTO may have expired and a tail-loss probe needs to be scheduled. +3155 /// +3156 /// The former needs us to schedule re-transmission of the lost data. +3157 /// +3158 /// The latter means we have not received an ACK for an ack-eliciting packet we sent +3159 /// within the PTO time-window. We need to schedule a tail-loss probe, an ack-eliciting +3160 /// packet, to try and elicit new acknowledgements. These new acknowledgements will +3161 /// indicate whether the previously sent packets were lost or not. +3162 fn on_loss_detection_timeout(&mut self, now: Instant, path_id: PathId) { +3163 if let Some((_, pn_space)) = self.loss_time_and_space(path_id) { +3164 // Time threshold loss Detection +3165 self.detect_lost_packets(now, pn_space, path_id, false); +3166 self.set_loss_detection_timer(now, path_id); +3167 return; +3168 } +3169 +3170 let Some((_, space)) = self.pto_time_and_space(now, path_id) else { +3171 error!(%path_id, "PTO expired while unset"); +3172 return; +3173 }; +3174 trace!( +3175 in_flight = self.path_data(path_id).in_flight.bytes, +3176 count = self.path_data(path_id).pto_count, +3177 ?space, +3178 %path_id, +3179 "PTO fired" +3180 ); +3181 +3182 let count = match self.path_data(path_id).in_flight.ack_eliciting { +3183 // A PTO when we're not expecting any ACKs must be due to handshake +3184 // anti-amplification deadlock prevention. +3185 0 => { +3186 debug_assert!(!self.peer_completed_handshake_address_validation()); +3187 1 +3188 } +3189 // Conventional loss probe +3190 _ => 2, +3191 }; +3192 let pns = self.spaces[space].for_path(path_id); +3193 pns.loss_probes = pns.loss_probes.saturating_add(count); +3194 let path_data = self.path_data_mut(path_id); +3195 path_data.pto_count = path_data.pto_count.saturating_add(1); +3196 self.set_loss_detection_timer(now, path_id); +3197 } +3198 +3199 /// Detect any lost packets +3200 /// +3201 /// There are two cases in which we detects lost packets: +3202 /// +3203 /// - We received an ACK packet. +3204 /// - The [`PathTimer::LossDetection`] timer expired. So there is an un-acknowledged packet +3205 /// that was followed by an acknowledged packet. The loss timer for this +3206 /// un-acknowledged packet expired and we need to detect that packet as lost. +3207 /// +3208 /// Packets are lost if they are both (See RFC9002 §6.1): +3209 /// +3210 /// - Unacknowledged, in flight and sent prior to an acknowledged packet. +3211 /// - Old enough by either: +3212 /// - Having a packet number [`TransportConfig::packet_threshold`] lower then the last +3213 /// acknowledged packet. +3214 /// - Being sent [`TransportConfig::time_threshold`] * RTT in the past. +3215 fn detect_lost_packets( +3216 &mut self, +3217 now: Instant, +3218 pn_space: SpaceId, +3219 path_id: PathId, +3220 due_to_ack: bool, +3221 ) { +3222 let mut lost_packets = Vec::<u64>::new(); +3223 let mut lost_mtu_probe = None; +3224 let mut in_persistent_congestion = false; +3225 let mut size_of_lost_packets = 0u64; +3226 self.spaces[pn_space].for_path(path_id).loss_time = None; +3227 +3228 // Find all the lost packets, populating all variables initialised above. +3229 +3230 let path = self.path_data(path_id); +3231 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe(); +3232 let loss_delay = path +3233 .rtt +3234 .conservative() +3235 .mul_f32(self.config.time_threshold) +3236 .max(TIMER_GRANULARITY); +3237 let first_packet_after_rtt_sample = path.first_packet_after_rtt_sample; +3238 +3239 let largest_acked_packet_pn = self.spaces[pn_space] +3240 .for_path(path_id) +3241 .largest_acked_packet_pn +3242 .expect("detect_lost_packets only to be called if path received at least one ACK"); +3243 let packet_threshold = self.config.packet_threshold as u64; +3244 +3245 // InPersistentCongestion: Determine if all packets in the time period before the newest +3246 // lost packet, including the edges, are marked lost. PTO computation must always +3247 // include max ACK delay, i.e. operate as if in Data space (see RFC9001 §7.6.1). +3248 let congestion_period = self +3249 .pto(SpaceKind::Data, path_id) +3250 .saturating_mul(self.config.persistent_congestion_threshold); +3251 let mut persistent_congestion_start: Option<Instant> = None; +3252 let mut prev_packet = None; +3253 let space = self.spaces[pn_space].for_path(path_id); +3254 +3255 for (packet, info) in space.sent_packets.iter_range(0..largest_acked_packet_pn) { +3256 if prev_packet != Some(packet.wrapping_sub(1)) { +3257 // An intervening packet was acknowledged +3258 persistent_congestion_start = None; +3259 } +3260 +3261 // Packets sent before now - loss_delay are deemed lost. +3262 // However, we avoid subtraction as it can panic and there's no +3263 // saturating equivalent of this subtraction operation with a Duration. +3264 let packet_too_old = now.saturating_duration_since(info.time_sent) >= loss_delay; +3265 if packet_too_old || largest_acked_packet_pn >= packet + packet_threshold { +3266 // The packet should be declared lost. +3267 if Some(packet) == in_flight_mtu_probe { +3268 // Lost MTU probes are not included in `lost_packets`, because they +3269 // should not trigger a congestion control response +3270 lost_mtu_probe = in_flight_mtu_probe; +3271 } else { +3272 lost_packets.push(packet); +3273 size_of_lost_packets += info.size as u64; +3274 if info.ack_eliciting && due_to_ack { +3275 match persistent_congestion_start { +3276 // Two ACK-eliciting packets lost more than +3277 // congestion_period apart, with no ACKed packets in between +3278 Some(start) if info.time_sent - start > congestion_period => { +3279 in_persistent_congestion = true; +3280 } +3281 // Persistent congestion must start after the first RTT sample +3282 None if first_packet_after_rtt_sample +3283 .is_some_and(|x| x < (pn_space.kind(), packet)) => +3284 { +3285 persistent_congestion_start = Some(info.time_sent); +3286 } +3287 _ => {} +3288 } +3289 } +3290 } +3291 } else { +3292 // The packet should not yet be declared lost. +3293 if space.loss_time.is_none() { +3294 // Since we iterate in order the lowest packet number's loss time will +3295 // always be the earliest. +3296 space.loss_time = Some(info.time_sent + loss_delay); +3297 } +3298 persistent_congestion_start = None; +3299 } +3300 +3301 prev_packet = Some(packet); +3302 } +3303 +3304 self.handle_lost_packets( +3305 pn_space, +3306 path_id, +3307 now, +3308 lost_packets, +3309 lost_mtu_probe, +3310 loss_delay, +3311 in_persistent_congestion, +3312 size_of_lost_packets, +3313 ); +3314 } +3315 +3316 /// Drops the path state, declaring any remaining in-flight packets as lost +3317 fn discard_path(&mut self, path_id: PathId, now: Instant) { +3318 trace!(%path_id, "dropping path state"); +3319 let path = self.path_data(path_id); +3320 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe(); +3321 +3322 let mut size_of_lost_packets = 0u64; // add to path_stats.lost_bytes; +3323 let lost_pns: Vec<_> = self.spaces[SpaceId::Data] +3324 .for_path(path_id) +3325 .sent_packets +3326 .iter() +3327 .filter(|(pn, _info)| Some(*pn) != in_flight_mtu_probe) +3328 .map(|(pn, info)| { +3329 size_of_lost_packets += info.size as u64; +3330 pn +3331 }) +3332 .collect(); +3333 +3334 if !lost_pns.is_empty() { +3335 trace!( +3336 %path_id, +3337 count = lost_pns.len(), +3338 lost_bytes = size_of_lost_packets, +3339 "packets lost on path abandon" +3340 ); +3341 self.handle_lost_packets( +3342 SpaceId::Data, +3343 path_id, +3344 now, +3345 lost_pns, +3346 in_flight_mtu_probe, +3347 Duration::ZERO, +3348 false, +3349 size_of_lost_packets, +3350 ); +3351 } +3352 // Before removing the path, we fetch the final path stats via `Self::path_stats`. +3353 // This updates some values for the last time. +3354 let path_stats = self.path_stats.discard(&path_id); +3355 self.partial_stats += path_stats; +3356 self.paths.remove(&path_id); +3357 self.spaces[SpaceId::Data].number_spaces.remove(&path_id); +3358 +3359 self.events.push_back( +3360 PathEvent::Discarded { +3361 id: path_id, +3362 path_stats: Box::new(path_stats), +3363 } +3364 .into(), +3365 ); +3366 } +3367 +3368 fn handle_lost_packets( +3369 &mut self, +3370 pn_space: SpaceId, +3371 path_id: PathId, +3372 now: Instant, +3373 lost_packets: Vec<u64>, +3374 lost_mtu_probe: Option<u64>, +3375 loss_delay: Duration, +3376 in_persistent_congestion: bool, +3377 size_of_lost_packets: u64, +3378 ) { +3379 debug_assert!(lost_packets.is_sorted(), "lost_packets must be sorted"); +3380 +3381 self.drain_lost_packets(now, pn_space, path_id); +3382 +3383 // OnPacketsLost +3384 if let Some(largest_lost) = lost_packets.last().cloned() { +3385 let old_bytes_in_flight = self.path_data_mut(path_id).in_flight.bytes; +3386 let largest_lost_sent = self.spaces[pn_space] +3387 .for_path(path_id) +3388 .sent_packets +3389 .get(largest_lost) +3390 .unwrap() +3391 .time_sent; +3392 let path_stats = self.path_stats.for_path(path_id); +3393 path_stats.lost_packets += lost_packets.len() as u64; +3394 path_stats.lost_bytes += size_of_lost_packets; +3395 trace!( +3396 %path_id, +3397 count = lost_packets.len(), +3398 lost_bytes = size_of_lost_packets, +3399 "packets lost", +3400 ); +3401 +3402 for &packet in &lost_packets { +3403 let Some(info) = self.spaces[pn_space].for_path(path_id).take(packet) else { +3404 continue; +3405 }; +3406 self.qlog +3407 .emit_packet_lost(packet, &info, loss_delay, pn_space.kind(), now); +3408 self.paths +3409 .get_mut(&path_id) +3410 .unwrap() +3411 .remove_in_flight(&info); 3412 -3413 self.spaces[pn_space].for_path(path_id).lost_packets.insert( -3414 packet, -3415 LostPacket { -3416 time_sent: info.time_sent, -3417 }, -3418 ); -3419 } +3413 for frame in info.stream_frames { +3414 self.streams.retransmit(frame); +3415 } +3416 self.spaces[pn_space].pending |= info.retransmits; +3417 let path = self.path_data_mut(path_id); +3418 path.mtud.on_non_probe_lost(packet, info.size); +3419 path.congestion.on_packet_lost(info.size, packet, now); 3420 -3421 let path = self.path_data_mut(path_id); -3422 if path.mtud.black_hole_detected(now) { -3423 path.congestion.on_mtu_update(path.mtud.current_mtu()); -3424 if let Some(max_datagram_size) = self.datagrams().max_size() -3425 && self.datagrams.drop_oversized(max_datagram_size) -3426 && self.datagrams.send_blocked -3427 { -3428 self.datagrams.send_blocked = false; -3429 self.events.push_back(Event::DatagramsUnblocked); -3430 } -3431 self.path_stats.for_path(path_id).black_holes_detected += 1; -3432 } -3433 -3434 // Don't apply congestion penalty for lost ack-only packets -3435 let lost_ack_eliciting = -3436 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes; -3437 -3438 if lost_ack_eliciting { -3439 self.path_stats.for_path(path_id).congestion_events += 1; -3440 self.path_data_mut(path_id).congestion.on_congestion_event( -3441 now, -3442 largest_lost_sent, -3443 in_persistent_congestion, -3444 false, -3445 size_of_lost_packets, -3446 largest_lost, -3447 ); -3448 } -3449 } -3450 -3451 // Handle a lost MTU probe -3452 if let Some(packet) = lost_mtu_probe { -3453 let info = self.spaces[SpaceId::Data] -3454 .for_path(path_id) -3455 .take(packet) -3456 .unwrap(); // safe: lost_mtu_probe is omitted from lost_packets, and -3457 // therefore must not have been removed yet -3458 self.paths -3459 .get_mut(&path_id) -3460 .unwrap() -3461 .remove_in_flight(&info); -3462 self.path_data_mut(path_id).mtud.on_probe_lost(); -3463 self.path_stats.for_path(path_id).lost_plpmtud_probes += 1; -3464 } -3465 } -3466 -3467 /// Returns the earliest time packets should be declared lost for all spaces on a path. -3468 /// -3469 /// If a path has an acknowledged packet with any prior un-acknowledged packets, the -3470 /// earliest un-acknowledged packet can be declared lost after a timeout has elapsed. -3471 /// The time returned is when this packet should be declared lost. -3472 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> { -3473 SpaceId::iter() -3474 .filter_map(|id| { -3475 self.spaces[id] -3476 .number_spaces -3477 .get(&path_id) -3478 .and_then(|pns| pns.loss_time) -3479 .map(|time| (time, id)) -3480 }) -3481 .min_by_key(|&(time, _)| time) -3482 } -3483 -3484 /// Returns the earliest next PTO should fire for all spaces on a path. -3485 /// -3486 /// This needs to be fully deterministic because it is also used to determine the PTO -3487 /// that fired, not just to set the next timer. So if it fired in the past it needs to -3488 /// return the time from the past at which it fired. -3489 /// -3490 /// This is the next time a tail-loss probe should be sent. -3491 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> { -3492 let path = self.path(path_id)?; -3493 let pto_count = path.pto_count; -3494 -3495 // Cap the maximum interval between two tail-loss probes. -3496 let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD { -3497 // For slow links we want to increase the interval beyond 2s. -3498 (path.rtt.get() * 3) / 2 -3499 } else if let Some(idle) = path.idle_timeout.or(self.idle_timeout) -3500 && idle <= MIN_IDLE_FOR_FAST_PTO -3501 { -3502 // If the idle timeout is relatively low, cap at 1s so we get plenty of retries -3503 // before the idle timeout fires. -3504 MAX_PTO_FAST_INTERVAL -3505 } else { -3506 // Otherwise cap to 2s. -3507 MAX_PTO_INTERVAL -3508 }; -3509 -3510 if path_id == PathId::ZERO -3511 && path.in_flight.ack_eliciting == 0 -3512 && !self.peer_completed_handshake_address_validation() -3513 { -3514 // Address Validation during Connection Establishment: -3515 // https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1. To prevent a -3516 // deadlock if an Initial or Handshake packet from the server is lost and the -3517 // server can not send more due to its anti-amplification limit the client must -3518 // send another packet on PTO. -3519 let space = match self.highest_space { -3520 SpaceKind::Handshake => SpaceId::Handshake, -3521 _ => SpaceId::Initial, -3522 }; -3523 -3524 let backoff = 2u32.pow(path.pto_count.min(MAX_BACKOFF_EXPONENT)); -3525 let duration = path.rtt.pto_base() * backoff; -3526 let duration = duration.min(max_interval); -3527 return Some((now + duration, space)); -3528 } -3529 -3530 let mut result = None; -3531 for space in SpaceId::iter() { -3532 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else { -3533 continue; -3534 }; -3535 -3536 if space == SpaceId::Data && !self.is_handshake_confirmed() { -3537 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-7: -3538 // An endpoint MUST NOT set its PTO timer for the Application Data packet -3539 // number space until the handshake is confirmed. -3540 continue; -3541 } -3542 -3543 if !pns.has_in_flight() { -3544 continue; -3545 } -3546 -3547 // Compute the PTO duration for this space, we want to cap the maximum interval -3548 // between two tail-loss probes so to not do a simple exponential backoff but -3549 // rather iterate through the probes to compute the capped increment for an -3550 // exponential backoff at each step. -3551 let duration = { -3552 let max_ack_delay = if space == SpaceId::Data { -3553 self.ack_frequency.max_ack_delay_for_pto() -3554 } else { -3555 Duration::ZERO -3556 }; -3557 let pto_base = path.rtt.pto_base() + max_ack_delay; -3558 let mut duration = pto_base; -3559 for i in 1..=pto_count { -3560 let exponential_duration = pto_base * 2u32.pow(i.min(MAX_BACKOFF_EXPONENT)); -3561 let max_duration = duration + max_interval; -3562 duration = exponential_duration.min(max_duration); -3563 } -3564 duration -3565 }; -3566 -3567 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else { -3568 continue; -3569 }; -3570 // Base the deadline on when the last probe was sent, so the PTO -3571 // doesn't fire before the response has had time to arrive. -3572 let pto = last_ack_eliciting + duration; -3573 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) { -3574 if path.anti_amplification_blocked(1) { -3575 // Nothing would be able to be sent. -3576 continue; -3577 } -3578 if path.in_flight.ack_eliciting == 0 { -3579 // Nothing ack-eliciting, no PTO to arm/fire. -3580 continue; -3581 } -3582 result = Some((pto, space)); -3583 } -3584 } -3585 result -3586 } -3587 -3588 /// Whether the peer validated our address in the connection handshake. -3589 fn peer_completed_handshake_address_validation(&self) -> bool { -3590 if self.side.is_server() || self.state.is_closed() { -3591 return true; +3421 self.spaces[pn_space].for_path(path_id).lost_packets.insert( +3422 packet, +3423 LostPacket { +3424 time_sent: info.time_sent, +3425 }, +3426 ); +3427 } +3428 +3429 let path = self.path_data_mut(path_id); +3430 if path.mtud.black_hole_detected(now) { +3431 path.congestion.on_mtu_update(path.mtud.current_mtu()); +3432 if let Some(max_datagram_size) = self.datagrams().max_size() +3433 && self.datagrams.drop_oversized(max_datagram_size) +3434 && self.datagrams.send_blocked +3435 { +3436 self.datagrams.send_blocked = false; +3437 self.events.push_back(Event::DatagramsUnblocked); +3438 } +3439 self.path_stats.for_path(path_id).black_holes_detected += 1; +3440 } +3441 +3442 // Don't apply congestion penalty for lost ack-only packets +3443 let lost_ack_eliciting = +3444 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes; +3445 +3446 if lost_ack_eliciting { +3447 self.path_stats.for_path(path_id).congestion_events += 1; +3448 self.path_data_mut(path_id).congestion.on_congestion_event( +3449 now, +3450 largest_lost_sent, +3451 in_persistent_congestion, +3452 false, +3453 size_of_lost_packets, +3454 largest_lost, +3455 ); +3456 } +3457 } +3458 +3459 // Handle a lost MTU probe +3460 if let Some(packet) = lost_mtu_probe { +3461 let info = self.spaces[SpaceId::Data] +3462 .for_path(path_id) +3463 .take(packet) +3464 .unwrap(); // safe: lost_mtu_probe is omitted from lost_packets, and +3465 // therefore must not have been removed yet +3466 self.paths +3467 .get_mut(&path_id) +3468 .unwrap() +3469 .remove_in_flight(&info); +3470 self.path_data_mut(path_id).mtud.on_probe_lost(); +3471 self.path_stats.for_path(path_id).lost_plpmtud_probes += 1; +3472 } +3473 } +3474 +3475 /// Returns the earliest time packets should be declared lost for all spaces on a path. +3476 /// +3477 /// If a path has an acknowledged packet with any prior un-acknowledged packets, the +3478 /// earliest un-acknowledged packet can be declared lost after a timeout has elapsed. +3479 /// The time returned is when this packet should be declared lost. +3480 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> { +3481 SpaceId::iter() +3482 .filter_map(|id| { +3483 self.spaces[id] +3484 .number_spaces +3485 .get(&path_id) +3486 .and_then(|pns| pns.loss_time) +3487 .map(|time| (time, id)) +3488 }) +3489 .min_by_key(|&(time, _)| time) +3490 } +3491 +3492 /// Returns the earliest next PTO should fire for all spaces on a path. +3493 /// +3494 /// This needs to be fully deterministic because it is also used to determine the PTO +3495 /// that fired, not just to set the next timer. So if it fired in the past it needs to +3496 /// return the time from the past at which it fired. +3497 /// +3498 /// This is the next time a tail-loss probe should be sent. +3499 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> { +3500 let path = self.path(path_id)?; +3501 let pto_count = path.pto_count; +3502 +3503 // Cap the maximum interval between two tail-loss probes. +3504 let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD { +3505 // For slow links we want to increase the interval beyond 2s. +3506 (path.rtt.get() * 3) / 2 +3507 } else if let Some(idle) = path.idle_timeout.or(self.idle_timeout) +3508 && idle <= MIN_IDLE_FOR_FAST_PTO +3509 { +3510 // If the idle timeout is relatively low, cap at 1s so we get plenty of retries +3511 // before the idle timeout fires. +3512 MAX_PTO_FAST_INTERVAL +3513 } else { +3514 // Otherwise cap to 2s. +3515 MAX_PTO_INTERVAL +3516 }; +3517 +3518 if path_id == PathId::ZERO +3519 && path.in_flight.ack_eliciting == 0 +3520 && !self.peer_completed_handshake_address_validation() +3521 { +3522 // Address Validation during Connection Establishment: +3523 // https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1. To prevent a +3524 // deadlock if an Initial or Handshake packet from the server is lost and the +3525 // server can not send more due to its anti-amplification limit the client must +3526 // send another packet on PTO. +3527 let space = match self.highest_space { +3528 SpaceKind::Handshake => SpaceId::Handshake, +3529 _ => SpaceId::Initial, +3530 }; +3531 +3532 let backoff = 2u32.pow(path.pto_count.min(MAX_BACKOFF_EXPONENT)); +3533 let duration = path.rtt.pto_base() * backoff; +3534 let duration = duration.min(max_interval); +3535 return Some((now + duration, space)); +3536 } +3537 +3538 let mut result = None; +3539 for space in SpaceId::iter() { +3540 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else { +3541 continue; +3542 }; +3543 +3544 if space == SpaceId::Data && !self.is_handshake_confirmed() { +3545 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-7: +3546 // An endpoint MUST NOT set its PTO timer for the Application Data packet +3547 // number space until the handshake is confirmed. +3548 continue; +3549 } +3550 +3551 if !pns.has_in_flight() { +3552 continue; +3553 } +3554 +3555 // Compute the PTO duration for this space, we want to cap the maximum interval +3556 // between two tail-loss probes so to not do a simple exponential backoff but +3557 // rather iterate through the probes to compute the capped increment for an +3558 // exponential backoff at each step. +3559 let duration = { +3560 let max_ack_delay = if space == SpaceId::Data { +3561 self.ack_frequency.max_ack_delay_for_pto() +3562 } else { +3563 Duration::ZERO +3564 }; +3565 let pto_base = path.rtt.pto_base() + max_ack_delay; +3566 let mut duration = pto_base; +3567 for i in 1..=pto_count { +3568 let exponential_duration = pto_base * 2u32.pow(i.min(MAX_BACKOFF_EXPONENT)); +3569 let max_duration = duration + max_interval; +3570 duration = exponential_duration.min(max_duration); +3571 } +3572 duration +3573 }; +3574 +3575 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else { +3576 continue; +3577 }; +3578 // Base the deadline on when the last probe was sent, so the PTO +3579 // doesn't fire before the response has had time to arrive. +3580 let pto = last_ack_eliciting + duration; +3581 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) { +3582 if path.anti_amplification_blocked(1) { +3583 // Nothing would be able to be sent. +3584 continue; +3585 } +3586 if path.in_flight.ack_eliciting == 0 { +3587 // Nothing ack-eliciting, no PTO to arm/fire. +3588 continue; +3589 } +3590 result = Some((pto, space)); +3591 } 3592 } -3593 // The server is guaranteed to have validated our address if any of our handshake or -3594 // 1-RTT packets are acknowledged or we've seen HANDSHAKE_DONE and discarded -3595 // handshake keys. -3596 self.spaces[SpaceId::Handshake] -3597 .path_space(PathId::ZERO) -3598 .and_then(|pns| pns.largest_acked_packet_pn) -3599 .is_some() -3600 || self.spaces[SpaceId::Data] -3601 .path_space(PathId::ZERO) -3602 .and_then(|pns| pns.largest_acked_packet_pn) -3603 .is_some() -3604 || (self.crypto_state.has_keys(EncryptionLevel::OneRtt) -3605 && !self.crypto_state.has_keys(EncryptionLevel::Handshake)) -3606 } -3607 -3608 /// Resets the the [`PathTimer::LossDetection`] timer to the next instant it may be needed -3609 /// -3610 /// The timer must fire if either: -3611 /// - An ack-eliciting packet we sent needs to be declared lost. -3612 /// - A tail-loss probe needs to be sent. -3613 /// -3614 /// See [`Connection::on_loss_detection_timeout`] for details. -3615 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) { -3616 if self.state.is_closed() { -3617 // No loss detection takes place on closed connections, and `close_common` already -3618 // stopped time timer. Ensure we don't restart it inadvertently, e.g. in response to a -3619 // reordered packet being handled by state-insensitive code. -3620 return; -3621 } -3622 -3623 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) { -3624 // Time threshold loss detection. -3625 self.timers.set( -3626 Timer::PerPath(path_id, PathTimer::LossDetection), -3627 loss_time, -3628 self.qlog.with_time(now), -3629 ); -3630 return; -3631 } -3632 -3633 // Determine which PN space to arm PTO for. -3634 // We can only send tail-loss probes on paths that aren't abandoned yet. -3635 if !self.abandoned_paths.contains(&path_id) -3636 && let Some((timeout, _)) = self.pto_time_and_space(now, path_id) -3637 { -3638 self.timers.set( -3639 Timer::PerPath(path_id, PathTimer::LossDetection), -3640 timeout, -3641 self.qlog.with_time(now), -3642 ); -3643 } else { -3644 self.timers.stop( -3645 Timer::PerPath(path_id, PathTimer::LossDetection), -3646 self.qlog.with_time(now), -3647 ); -3648 } -3649 } -3650 -3651 /// The maximum probe timeout across all paths -3652 /// -3653 /// See [`Connection::pto`] -3654 fn max_pto_for_space(&self, space: SpaceKind) -> Duration { -3655 self.paths -3656 .keys() -3657 .map(|path_id| self.pto(space, *path_id)) -3658 .max() -3659 .unwrap_or_else(|| { -3660 // No paths remain (e.g. last path was abandoned and the NoAvailablePath grace timer -3661 // fired before any new path was opened). Fall back to a PTO derived from the -3662 // configured initial RTT, matching RFC 9002 §6.2.2 initial values. -3663 let rtt = self.config.initial_rtt; -3664 let max_ack_delay = match space { -3665 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO, -3666 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(), -3667 }; -3668 rtt + cmp::max(4 * (rtt / 2), TIMER_GRANULARITY) + max_ack_delay -3669 }) -3670 } -3671 -3672 /// Probe Timeout -3673 /// -3674 /// The PTO is logically the time in which you'd expect to receive an acknowledgement -3675 /// for a packet. So approximately RTT + max_ack_delay. -3676 fn pto(&self, space: SpaceKind, path_id: PathId) -> Duration { -3677 let max_ack_delay = match space { -3678 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO, -3679 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(), -3680 }; -3681 self.path_data(path_id).rtt.pto_base() + max_ack_delay -3682 } -3683 -3684 fn on_packet_authenticated( -3685 &mut self, -3686 now: Instant, -3687 space_id: SpaceKind, -3688 path_id: PathId, -3689 ecn: Option<EcnCodepoint>, -3690 packet_number: Option<u64>, -3691 spin: bool, -3692 is_1rtt: bool, -3693 remote: &FourTuple, -3694 ) { -3695 // During the handshake we already have discarded packets that do not match the path -3696 // remote. So any off-path packet here is either a probing packet or a -3697 // migration. Handling probing packets here means that the path's idle timeout will -3698 // be reset and will delay detecting the path as idle. However tail-loss probes -3699 // would still not get acknowledged if the path was broken so eventually the path -3700 // would still become idle. -3701 let is_on_path = *remote == self.path_data(path_id).network_path; -3702 -3703 self.total_authed_packets += 1; -3704 self.reset_keep_alive(path_id, now); -3705 self.reset_idle_timeout(now, space_id, path_id); -3706 self.path_data_mut(path_id).permit_idle_reset = true; -3707 -3708 // Do not process ECN for off-path packets. If this is a migration we'll get ECN -3709 // back once we've migrated. -3710 if is_on_path { -3711 self.receiving_ecn |= ecn.is_some(); -3712 if let Some(x) = ecn { -3713 let space = &mut self.spaces[space_id]; -3714 space.for_path(path_id).ecn_counters += x; +3593 result +3594 } +3595 +3596 /// Whether the peer validated our address in the connection handshake. +3597 fn peer_completed_handshake_address_validation(&self) -> bool { +3598 if self.side.is_server() || self.state.is_closed() { +3599 return true; +3600 } +3601 // The server is guaranteed to have validated our address if any of our handshake or +3602 // 1-RTT packets are acknowledged or we've seen HANDSHAKE_DONE and discarded +3603 // handshake keys. +3604 self.spaces[SpaceId::Handshake] +3605 .path_space(PathId::ZERO) +3606 .and_then(|pns| pns.largest_acked_packet_pn) +3607 .is_some() +3608 || self.spaces[SpaceId::Data] +3609 .path_space(PathId::ZERO) +3610 .and_then(|pns| pns.largest_acked_packet_pn) +3611 .is_some() +3612 || (self.crypto_state.has_keys(EncryptionLevel::OneRtt) +3613 && !self.crypto_state.has_keys(EncryptionLevel::Handshake)) +3614 } +3615 +3616 /// Resets the the [`PathTimer::LossDetection`] timer to the next instant it may be needed +3617 /// +3618 /// The timer must fire if either: +3619 /// - An ack-eliciting packet we sent needs to be declared lost. +3620 /// - A tail-loss probe needs to be sent. +3621 /// +3622 /// See [`Connection::on_loss_detection_timeout`] for details. +3623 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) { +3624 if self.state.is_closed() { +3625 // No loss detection takes place on closed connections, and `close_common` already +3626 // stopped time timer. Ensure we don't restart it inadvertently, e.g. in response to a +3627 // reordered packet being handled by state-insensitive code. +3628 return; +3629 } +3630 +3631 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) { +3632 // Time threshold loss detection. +3633 self.timers.set( +3634 Timer::PerPath(path_id, PathTimer::LossDetection), +3635 loss_time, +3636 self.qlog.with_time(now), +3637 ); +3638 return; +3639 } +3640 +3641 // Determine which PN space to arm PTO for. +3642 // We can only send tail-loss probes on paths that aren't abandoned yet. +3643 if !self.abandoned_paths.contains(&path_id) +3644 && let Some((timeout, _)) = self.pto_time_and_space(now, path_id) +3645 { +3646 self.timers.set( +3647 Timer::PerPath(path_id, PathTimer::LossDetection), +3648 timeout, +3649 self.qlog.with_time(now), +3650 ); +3651 } else { +3652 self.timers.stop( +3653 Timer::PerPath(path_id, PathTimer::LossDetection), +3654 self.qlog.with_time(now), +3655 ); +3656 } +3657 } +3658 +3659 /// The maximum probe timeout across all paths +3660 /// +3661 /// See [`Connection::pto`] +3662 fn max_pto_for_space(&self, space: SpaceKind) -> Duration { +3663 self.paths +3664 .keys() +3665 .map(|path_id| self.pto(space, *path_id)) +3666 .max() +3667 .unwrap_or_else(|| { +3668 // No paths remain (e.g. last path was abandoned and the NoAvailablePath grace timer +3669 // fired before any new path was opened). Fall back to a PTO derived from the +3670 // configured initial RTT, matching RFC 9002 §6.2.2 initial values. +3671 let rtt = self.config.initial_rtt; +3672 let max_ack_delay = match space { +3673 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO, +3674 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(), +3675 }; +3676 rtt + cmp::max(4 * (rtt / 2), TIMER_GRANULARITY) + max_ack_delay +3677 }) +3678 } +3679 +3680 /// Probe Timeout +3681 /// +3682 /// The PTO is logically the time in which you'd expect to receive an acknowledgement +3683 /// for a packet. So approximately RTT + max_ack_delay. +3684 fn pto(&self, space: SpaceKind, path_id: PathId) -> Duration { +3685 let max_ack_delay = match space { +3686 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO, +3687 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(), +3688 }; +3689 self.path_data(path_id).rtt.pto_base() + max_ack_delay +3690 } +3691 +3692 fn on_packet_authenticated( +3693 &mut self, +3694 now: Instant, +3695 space_id: SpaceKind, +3696 path_id: PathId, +3697 ecn: Option<EcnCodepoint>, +3698 packet_number: Option<u64>, +3699 spin: bool, +3700 is_1rtt: bool, +3701 remote: &FourTuple, +3702 ) { +3703 // During the handshake we already have discarded packets that do not match the path +3704 // remote. So any off-path packet here is either a probing packet or a +3705 // migration. Handling probing packets here means that the path's idle timeout will +3706 // be reset and will delay detecting the path as idle. However tail-loss probes +3707 // would still not get acknowledged if the path was broken so eventually the path +3708 // would still become idle. +3709 let is_on_path = *remote == self.path_data(path_id).network_path; +3710 +3711 self.total_authed_packets += 1; +3712 self.reset_keep_alive(path_id, now); +3713 self.reset_idle_timeout(now, space_id, path_id); +3714 self.path_data_mut(path_id).permit_idle_reset = true; 3715 -3716 if x.is_ce() { -3717 space -3718 .for_path(path_id) -3719 .pending_acks -3720 .set_immediate_ack_required(); -3721 } -3722 } -3723 } -3724 -3725 let Some(packet_number) = packet_number else { -3726 return; -3727 }; -3728 match &self.side { -3729 ConnectionSide::Client { .. } => { -3730 // If we received a handshake packet that authenticated, then we're talking to -3731 // the real server. From now on we should no longer allow the server to migrate -3732 // its address. -3733 if space_id == SpaceKind::Handshake -3734 && let Some(hs) = self.state.as_handshake_mut() -3735 { -3736 hs.allow_server_migration = false; -3737 } -3738 } -3739 ConnectionSide::Server { .. } => { -3740 if self.crypto_state.has_keys(EncryptionLevel::Initial) -3741 && space_id == SpaceKind::Handshake -3742 { -3743 // A server stops sending and processing Initial packets when it receives its first Handshake packet. -3744 self.discard_space(now, SpaceKind::Initial); +3716 // Do not process ECN for off-path packets. If this is a migration we'll get ECN +3717 // back once we've migrated. +3718 if is_on_path { +3719 self.receiving_ecn |= ecn.is_some(); +3720 if let Some(x) = ecn { +3721 let space = &mut self.spaces[space_id]; +3722 space.for_path(path_id).ecn_counters += x; +3723 +3724 if x.is_ce() { +3725 space +3726 .for_path(path_id) +3727 .pending_acks +3728 .set_immediate_ack_required(); +3729 } +3730 } +3731 } +3732 +3733 let Some(packet_number) = packet_number else { +3734 return; +3735 }; +3736 match &self.side { +3737 ConnectionSide::Client { .. } => { +3738 // If we received a handshake packet that authenticated, then we're talking to +3739 // the real server. From now on we should no longer allow the server to migrate +3740 // its address. +3741 if space_id == SpaceKind::Handshake +3742 && let Some(hs) = self.state.as_handshake_mut() +3743 { +3744 hs.allow_server_migration = false; 3745 } -3746 if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) && is_1rtt { -3747 // Discard 0-RTT keys soon after receiving a 1-RTT packet -3748 self.set_key_discard_timer(now, space_id) -3749 } -3750 } -3751 } -3752 let space = self.spaces[space_id].for_path(path_id); -3753 -3754 space.pending_acks.insert_one(packet_number, now); -3755 if packet_number >= space.largest_received_packet_number.unwrap_or_default() { -3756 space.largest_received_packet_number = Some(packet_number); -3757 -3758 // Update outgoing spin bit for on-path packets, inverting iff we're the client -3759 if is_on_path { -3760 self.spin = self.side.is_client() ^ spin; -3761 } -3762 } -3763 } -3764 -3765 /// Resets the idle timeout timers -3766 /// -3767 /// Without multipath there is only the connection-wide idle timeout. When multipath is -3768 /// enabled there is an additional per-path idle timeout. -3769 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) { -3770 // First reset the global idle timeout. -3771 if let Some(timeout) = self.idle_timeout { -3772 if self.state.is_closed() { -3773 self.timers -3774 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)); -3775 } else { -3776 let dt = cmp::max(timeout, 3 * self.max_pto_for_space(space)); -3777 self.timers.set( -3778 Timer::Conn(ConnTimer::Idle), -3779 now + dt, -3780 self.qlog.with_time(now), -3781 ); -3782 } -3783 } -3784 -3785 // Now handle the per-path state -3786 if let Some(timeout) = self.path_data(path_id).idle_timeout { -3787 if self.state.is_closed() { -3788 self.timers.stop( -3789 Timer::PerPath(path_id, PathTimer::PathIdle), -3790 self.qlog.with_time(now), -3791 ); -3792 } else { -3793 let dt = cmp::max(timeout, 3 * self.pto(space, path_id)); -3794 self.timers.set( -3795 Timer::PerPath(path_id, PathTimer::PathIdle), -3796 now + dt, -3797 self.qlog.with_time(now), -3798 ); -3799 } -3800 } -3801 } -3802 -3803 /// Resets both the [`ConnTimer::KeepAlive`] and [`PathTimer::PathKeepAlive`] timers -3804 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) { -3805 if !self.state.is_established() { -3806 return; -3807 } -3808 -3809 if let Some(interval) = self.config.keep_alive_interval { -3810 self.timers.set( -3811 Timer::Conn(ConnTimer::KeepAlive), -3812 now + interval, -3813 self.qlog.with_time(now), -3814 ); +3746 } +3747 ConnectionSide::Server { .. } => { +3748 if self.crypto_state.has_keys(EncryptionLevel::Initial) +3749 && space_id == SpaceKind::Handshake +3750 { +3751 // A server stops sending and processing Initial packets when it receives its first Handshake packet. +3752 self.discard_space(now, SpaceKind::Initial); +3753 } +3754 if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) && is_1rtt { +3755 // Discard 0-RTT keys soon after receiving a 1-RTT packet +3756 self.set_key_discard_timer(now, space_id) +3757 } +3758 } +3759 } +3760 let space = self.spaces[space_id].for_path(path_id); +3761 +3762 space.pending_acks.insert_one(packet_number, now); +3763 if packet_number >= space.largest_received_packet_number.unwrap_or_default() { +3764 space.largest_received_packet_number = Some(packet_number); +3765 +3766 // Update outgoing spin bit for on-path packets, inverting iff we're the client +3767 if is_on_path { +3768 self.spin = self.side.is_client() ^ spin; +3769 } +3770 } +3771 } +3772 +3773 /// Resets the idle timeout timers +3774 /// +3775 /// Without multipath there is only the connection-wide idle timeout. When multipath is +3776 /// enabled there is an additional per-path idle timeout. +3777 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) { +3778 // First reset the global idle timeout. +3779 if let Some(timeout) = self.idle_timeout { +3780 if self.state.is_closed() { +3781 self.timers +3782 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)); +3783 } else { +3784 let dt = cmp::max(timeout, 3 * self.max_pto_for_space(space)); +3785 self.timers.set( +3786 Timer::Conn(ConnTimer::Idle), +3787 now + dt, +3788 self.qlog.with_time(now), +3789 ); +3790 } +3791 } +3792 +3793 // Now handle the per-path state +3794 if let Some(timeout) = self.path_data(path_id).idle_timeout { +3795 if self.state.is_closed() { +3796 self.timers.stop( +3797 Timer::PerPath(path_id, PathTimer::PathIdle), +3798 self.qlog.with_time(now), +3799 ); +3800 } else { +3801 let dt = cmp::max(timeout, 3 * self.pto(space, path_id)); +3802 self.timers.set( +3803 Timer::PerPath(path_id, PathTimer::PathIdle), +3804 now + dt, +3805 self.qlog.with_time(now), +3806 ); +3807 } +3808 } +3809 } +3810 +3811 /// Resets both the [`ConnTimer::KeepAlive`] and [`PathTimer::PathKeepAlive`] timers +3812 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) { +3813 if !self.state.is_established() { +3814 return; 3815 } 3816 -3817 if let Some(interval) = self.path_data(path_id).keep_alive { +3817 if let Some(interval) = self.config.keep_alive_interval { 3818 self.timers.set( -3819 Timer::PerPath(path_id, PathTimer::PathKeepAlive), +3819 Timer::Conn(ConnTimer::KeepAlive), 3820 now + interval, 3821 self.qlog.with_time(now), 3822 ); 3823 } -3824 } -3825 -3826 /// Sets the timer for when a previously issued CID should be retired next -3827 fn reset_cid_retirement(&mut self, now: Instant) { -3828 if let Some((_path, t)) = self.next_cid_retirement() { -3829 self.timers.set( -3830 Timer::Conn(ConnTimer::PushNewCid), -3831 t, -3832 self.qlog.with_time(now), -3833 ); -3834 } -3835 } -3836 -3837 /// The next time when a previously issued CID should be retired -3838 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> { -3839 self.local_cid_state -3840 .iter() -3841 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t))) -3842 .min_by_key(|(_path_id, timeout)| *timeout) +3824 +3825 if let Some(interval) = self.path_data(path_id).keep_alive { +3826 self.timers.set( +3827 Timer::PerPath(path_id, PathTimer::PathKeepAlive), +3828 now + interval, +3829 self.qlog.with_time(now), +3830 ); +3831 } +3832 } +3833 +3834 /// Sets the timer for when a previously issued CID should be retired next +3835 fn reset_cid_retirement(&mut self, now: Instant) { +3836 if let Some((_path, t)) = self.next_cid_retirement() { +3837 self.timers.set( +3838 Timer::Conn(ConnTimer::PushNewCid), +3839 t, +3840 self.qlog.with_time(now), +3841 ); +3842 } 3843 } 3844 -3845 /// Handle the already-decrypted first packet from the client -3846 /// -3847 /// Decrypting the first packet in the `Endpoint` allows stateless packet handling to be more -3848 /// efficient. -3849 pub(crate) fn handle_first_packet( -3850 &mut self, -3851 now: Instant, -3852 network_path: FourTuple, -3853 ecn: Option<EcnCodepoint>, -3854 packet_number: u64, -3855 packet: InitialPacket, -3856 remaining: Option<BytesMut>, -3857 ) -> Result<(), ConnectionError> { -3858 let span = trace_span!("first recv"); -3859 let _guard = span.enter(); -3860 debug_assert!(self.side.is_server()); -3861 let len = packet.header_data.len() + packet.payload.len(); -3862 let path_id = PathId::ZERO; -3863 self.path_data_mut(path_id).total_recvd = len as u64; -3864 -3865 if let Some(hs) = self.state.as_handshake_mut() { -3866 hs.expected_token = packet.header.token.clone(); -3867 } else { -3868 unreachable!("first packet must be delivered in Handshake state"); -3869 } -3870 -3871 // The first packet is always on PathId::ZERO -3872 self.on_packet_authenticated( -3873 now, -3874 SpaceKind::Initial, -3875 path_id, -3876 ecn, -3877 Some(packet_number), -3878 false, -3879 false, -3880 &network_path, -3881 ); -3882 -3883 let packet: Packet = packet.into(); -3884 -3885 let mut qlog = QlogRecvPacket::new(len); -3886 qlog.header(&packet.header, Some(packet_number), path_id); -3887 -3888 self.process_decrypted_packet( -3889 now, -3890 network_path, -3891 path_id, -3892 Some(packet_number), -3893 packet, -3894 &mut qlog, -3895 )?; -3896 self.qlog.emit_packet_received(qlog, now); -3897 if let Some(data) = remaining { -3898 self.handle_coalesced(now, network_path, path_id, ecn, data); -3899 } -3900 -3901 self.qlog.emit_recovery_metrics( -3902 path_id, -3903 &mut self.paths.get_mut(&path_id).unwrap().data, -3904 now, -3905 ); -3906 -3907 Ok(()) -3908 } -3909 -3910 fn init_0rtt(&mut self, now: Instant) { -3911 let Some((header, packet)) = self.crypto_state.session.early_crypto() else { -3912 return; -3913 }; -3914 if self.side.is_client() { -3915 match self.crypto_state.session.transport_parameters() { -3916 Ok(params) => { -3917 let params = params -3918 .expect("crypto layer didn't supply transport parameters with ticket"); -3919 // Certain values must not be cached -3920 let params = TransportParameters { -3921 initial_src_cid: None, -3922 original_dst_cid: None, -3923 preferred_address: None, -3924 retry_src_cid: None, -3925 stateless_reset_token: None, -3926 min_ack_delay: None, -3927 ack_delay_exponent: TransportParameters::default().ack_delay_exponent, -3928 max_ack_delay: TransportParameters::default().max_ack_delay, -3929 initial_max_path_id: None, -3930 ..params -3931 }; -3932 self.set_peer_params(params); -3933 self.qlog.emit_peer_transport_params_restored(self, now); -3934 } -3935 Err(e) => { -3936 error!("session ticket has malformed transport parameters: {}", e); -3937 return; -3938 } -3939 } -3940 } -3941 trace!("0-RTT enabled"); -3942 self.crypto_state.enable_zero_rtt(header, packet); -3943 } -3944 -3945 fn read_crypto( -3946 &mut self, -3947 space: SpaceId, -3948 crypto: &frame::Crypto, -3949 payload_len: usize, -3950 ) -> Result<(), TransportError> { -3951 let expected = if !self.state.is_handshake() { -3952 SpaceId::Data -3953 } else if self.highest_space == SpaceKind::Initial { -3954 SpaceId::Initial -3955 } else { -3956 // On the server, self.highest_space can be Data after receiving the client's first -3957 // flight, but we expect Handshake CRYPTO until the handshake is complete. -3958 SpaceId::Handshake -3959 }; -3960 // We can't decrypt Handshake packets when highest_space is Initial, CRYPTO frames in 0-RTT -3961 // packets are illegal, and we don't process 1-RTT packets until the handshake is -3962 // complete. Therefore, we will never see CRYPTO data from a later-than-expected space. -3963 debug_assert!(space <= expected, "received out-of-order CRYPTO data"); -3964 -3965 let end = crypto.offset + crypto.data.len() as u64; -3966 if space < expected -3967 && end -3968 > self.crypto_state.spaces[space.kind()] -3969 .crypto_stream -3970 .bytes_read() -3971 { -3972 warn!( -3973 "received new {:?} CRYPTO data when expecting {:?}", -3974 space, expected -3975 ); -3976 return Err(TransportError::PROTOCOL_VIOLATION( -3977 "new data at unexpected encryption level", -3978 )); -3979 } -3980 -3981 let crypto_space = &mut self.crypto_state.spaces[space.kind()]; -3982 let max = end.saturating_sub(crypto_space.crypto_stream.bytes_read()); -3983 if max > self.config.crypto_buffer_size as u64 { -3984 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED("")); -3985 } -3986 -3987 crypto_space -3988 .crypto_stream -3989 .insert(crypto.offset, crypto.data.clone(), payload_len); -3990 while let Some(chunk) = crypto_space.crypto_stream.read(usize::MAX, true) { -3991 trace!("consumed {} CRYPTO bytes", chunk.bytes.len()); -3992 if self.crypto_state.session.read_handshake(&chunk.bytes)? { -3993 self.events.push_back(Event::HandshakeDataReady); -3994 } -3995 } -3996 -3997 Ok(()) -3998 } -3999 -4000 fn write_crypto(&mut self) { -4001 loop { -4002 let space = self.highest_space; -4003 let mut outgoing = Vec::new(); -4004 if let Some(crypto) = self.crypto_state.session.write_handshake(&mut outgoing) { -4005 match space { -4006 SpaceKind::Initial => { -4007 self.upgrade_crypto(SpaceKind::Handshake, crypto); -4008 } -4009 SpaceKind::Handshake => { -4010 self.upgrade_crypto(SpaceKind::Data, crypto); -4011 } -4012 SpaceKind::Data => unreachable!("got updated secrets during 1-RTT"), -4013 } -4014 } -4015 if outgoing.is_empty() { -4016 if space == self.highest_space { -4017 break; -4018 } else { -4019 // Keys updated, check for more data to send -4020 continue; -4021 } -4022 } -4023 let offset = self.crypto_state.spaces[space].crypto_offset; -4024 let outgoing = Bytes::from(outgoing); -4025 if let Some(hs) = self.state.as_handshake_mut() -4026 && space == SpaceKind::Initial -4027 && offset == 0 -4028 && self.side.is_client() -4029 { -4030 hs.client_hello = Some(outgoing.clone()); -4031 } -4032 self.crypto_state.spaces[space].crypto_offset += outgoing.len() as u64; -4033 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space); -4034 self.spaces[space].pending.crypto.push_back(frame::Crypto { -4035 offset, -4036 data: outgoing, -4037 }); -4038 } -4039 } -4040 -4041 /// Switch to stronger cryptography during handshake -4042 fn upgrade_crypto(&mut self, space: SpaceKind, crypto: Keys) { -4043 debug_assert!( -4044 !self.crypto_state.has_keys(space.encryption_level()), -4045 "already reached packet space {space:?}" -4046 ); -4047 trace!("{:?} keys ready", space); -4048 if space == SpaceKind::Data { -4049 // Precompute the first key update -4050 self.crypto_state.next_crypto = Some( -4051 self.crypto_state -4052 .session -4053 .next_1rtt_keys() -4054 .expect("handshake should be complete"), -4055 ); -4056 } -4057 -4058 self.crypto_state.spaces[space].keys = Some(crypto); -4059 debug_assert!(space > self.highest_space); -4060 self.highest_space = space; -4061 if space == SpaceKind::Data && self.side.is_client() { -4062 // Discard 0-RTT keys because 1-RTT keys are available. -4063 self.crypto_state.discard_zero_rtt(); -4064 } -4065 } -4066 -4067 fn discard_space(&mut self, now: Instant, space: SpaceKind) { -4068 debug_assert!(space != SpaceKind::Data); -4069 trace!("discarding {:?} keys", space); -4070 if space == SpaceKind::Initial { -4071 // No longer needed -4072 if let ConnectionSide::Client { token, .. } = &mut self.side { -4073 *token = Bytes::new(); -4074 } -4075 } -4076 self.crypto_state.spaces[space].keys = None; -4077 let space = &mut self.spaces[space]; -4078 let pns = space.for_path(PathId::ZERO); -4079 pns.time_of_last_ack_eliciting_packet = None; -4080 pns.loss_time = None; -4081 pns.loss_probes = 0; -4082 let sent_packets = mem::take(&mut pns.sent_packets); -4083 let path = self.paths.get_mut(&PathId::ZERO).unwrap(); -4084 for (_, packet) in sent_packets.into_iter() { -4085 path.data.remove_in_flight(&packet); -4086 } -4087 -4088 self.set_loss_detection_timer(now, PathId::ZERO) -4089 } -4090 -4091 fn handle_coalesced( -4092 &mut self, -4093 now: Instant, -4094 network_path: FourTuple, -4095 path_id: PathId, -4096 ecn: Option<EcnCodepoint>, -4097 data: BytesMut, -4098 ) { -4099 self.path_data_mut(path_id) -4100 .inc_total_recvd(data.len() as u64); -4101 let mut remaining = Some(data); -4102 let cid_len = self -4103 .local_cid_state -4104 .values() -4105 .map(|cid_state| cid_state.cid_len()) -4106 .next() -4107 .expect("one cid_state must exist"); -4108 while let Some(data) = remaining { -4109 match PartialDecode::new( -4110 data, -4111 &FixedLengthConnectionIdParser::new(cid_len), -4112 &[self.version], -4113 self.endpoint_config.grease_quic_bit, -4114 ) { -4115 Ok((partial_decode, rest)) => { -4116 remaining = rest; -4117 self.handle_decode(now, network_path, path_id, ecn, partial_decode); -4118 } -4119 Err(e) => { -4120 trace!("malformed header: {}", e); -4121 return; -4122 } -4123 } -4124 } -4125 } -4126 -4127 /// Decrypts the packet and processes the payload. -4128 /// -4129 /// Processes the entire packet, starting with removing header protection, then handling -4130 /// a stateless reset if needed, and decrypting and processing the frames in the payload -4131 /// if not a stateless reset. -4132 fn handle_decode( -4133 &mut self, -4134 now: Instant, -4135 network_path: FourTuple, -4136 path_id: PathId, -4137 ecn: Option<EcnCodepoint>, -4138 partial_decode: PartialDecode, -4139 ) { -4140 let qlog = QlogRecvPacket::new(partial_decode.len()); -4141 if let Some(decoded) = self -4142 .crypto_state -4143 .unprotect_header(partial_decode, self.peer_params.stateless_reset_token) -4144 { -4145 self.handle_packet( -4146 now, -4147 network_path, -4148 path_id, -4149 ecn, -4150 decoded.packet, -4151 decoded.stateless_reset, -4152 qlog, -4153 ); -4154 } -4155 } -4156 -4157 /// Handles a packet with header protection removed. -4158 /// -4159 /// The packet body is still encrypted at this point. -4160 /// -4161 /// If the datagram was a stateless reset we may have failed to remove header protection -4162 /// and thus `packet` may be `None`. -4163 fn handle_packet( -4164 &mut self, -4165 now: Instant, -4166 network_path: FourTuple, -4167 path_id: PathId, -4168 ecn: Option<EcnCodepoint>, -4169 packet: Option<Packet>, -4170 stateless_reset: bool, -4171 mut qlog: QlogRecvPacket, -4172 ) { -4173 self.path_stats.for_path(path_id).udp_rx.ios += 1; -4174 -4175 if let Some(ref packet) = packet { -4176 trace!( -4177 "got {:?} packet ({} bytes) from {} using id {}", -4178 packet.header.space(), -4179 packet.payload.len() + packet.header_data.len(), -4180 network_path, -4181 packet.header.dst_cid(), -4182 ); -4183 } -4184 -4185 let was_closed = self.state.is_closed(); -4186 let was_drained = self.state.is_drained(); -4187 -4188 // Now decrypt the packet payload in-place. -4189 let decrypted = match packet { -4190 None => Err(None), -4191 Some(mut packet) => self -4192 .decrypt_packet(now, path_id, &mut packet) -4193 .map(move |number| (packet, number)), -4194 }; -4195 let result = match decrypted { -4196 _ if stateless_reset => { -4197 debug!("got stateless reset"); -4198 Err(ConnectionError::Reset) -4199 } -4200 Err(Some(e)) => { -4201 warn!("illegal packet: {}", e); -4202 Err(e.into()) -4203 } -4204 Err(None) => { -4205 debug!("failed to authenticate packet"); -4206 self.authentication_failures += 1; -4207 let integrity_limit = self -4208 .crypto_state -4209 .integrity_limit(self.highest_space) -4210 .unwrap(); -4211 if self.authentication_failures > integrity_limit { -4212 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into()) -4213 } else { -4214 return; -4215 } -4216 } -4217 Ok((packet, number)) => { -4218 // We received an authenticated packet and decrypted it. -4219 qlog.header(&packet.header, number, path_id); -4220 let span = match number { -4221 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn), -4222 None => trace_span!("recv", space = ?packet.header.space()), -4223 }; -4224 let _guard = span.enter(); -4225 -4226 // Now the packet is authenticated we do the migration during the -4227 // handshake. See Handshake::allow_server_migration for details. -4228 if self.is_handshaking() && network_path != self.path_data_mut(path_id).network_path -4229 { -4230 if let Some(hs) = self.state.as_handshake() -4231 && hs.allow_server_migration -4232 { -4233 trace!( -4234 %network_path, -4235 prev = %self.path_data(path_id).network_path, -4236 "server migrated to new remote", -4237 ); -4238 self.path_data_mut(path_id).network_path = network_path; -4239 self.qlog.emit_tuple_assigned(path_id, network_path, now); -4240 } else { -4241 debug!("discarding packet with unexpected remote during handshake"); -4242 return; -4243 } -4244 } -4245 -4246 let dedup = self.spaces[packet.header.space()] -4247 .path_space_mut(path_id) -4248 .map(|pns| &mut pns.dedup); -4249 if number.zip(dedup).is_some_and(|(n, d)| d.insert(n)) { -4250 debug!("discarding possible duplicate packet"); -4251 self.qlog.emit_packet_received(qlog, now); -4252 return; -4253 } else if self.state.is_handshake() && packet.header.is_short() { -4254 // TODO: SHOULD buffer these to improve reordering tolerance. -4255 trace!("dropping short packet during handshake"); -4256 self.qlog.emit_packet_received(qlog, now); -4257 return; -4258 } else { -4259 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header -4260 && let Some(hs) = self.state.as_handshake() -4261 && self.side.is_server() -4262 && token != &hs.expected_token -4263 { -4264 // Clients must send the same retry token in every Initial. Initial -4265 // packets can be spoofed, so we discard rather than killing the -4266 // connection. -4267 warn!("discarding Initial with invalid retry token"); -4268 self.qlog.emit_packet_received(qlog, now); -4269 return; -4270 } -4271 -4272 if !self.state.is_closed() { -4273 let spin = match packet.header { -4274 Header::Short { spin, .. } => spin, -4275 _ => false, -4276 }; -4277 -4278 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) { -4279 // Only the client is allowed to open paths -4280 self.ensure_path(path_id, network_path, now, number); -4281 } -4282 if self.paths.contains_key(&path_id) { -4283 self.on_packet_authenticated( -4284 now, -4285 packet.header.space(), -4286 path_id, -4287 ecn, -4288 number, -4289 spin, -4290 packet.header.is_1rtt(), -4291 &network_path, -4292 ); -4293 } -4294 } -4295 -4296 let res = self.process_decrypted_packet( -4297 now, -4298 network_path, -4299 path_id, -4300 number, -4301 packet, -4302 &mut qlog, -4303 ); -4304 -4305 self.qlog.emit_packet_received(qlog, now); -4306 res -4307 } -4308 } -4309 }; +3845 /// The next time when a previously issued CID should be retired +3846 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> { +3847 self.local_cid_state +3848 .iter() +3849 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t))) +3850 .min_by_key(|(_path_id, timeout)| *timeout) +3851 } +3852 +3853 /// Handle the already-decrypted first packet from the client +3854 /// +3855 /// Decrypting the first packet in the `Endpoint` allows stateless packet handling to be more +3856 /// efficient. +3857 pub(crate) fn handle_first_packet( +3858 &mut self, +3859 now: Instant, +3860 network_path: FourTuple, +3861 ecn: Option<EcnCodepoint>, +3862 packet_number: u64, +3863 packet: InitialPacket, +3864 remaining: Option<BytesMut>, +3865 ) -> Result<(), ConnectionError> { +3866 let span = trace_span!("first recv"); +3867 let _guard = span.enter(); +3868 debug_assert!(self.side.is_server()); +3869 let len = packet.header_data.len() + packet.payload.len(); +3870 let path_id = PathId::ZERO; +3871 self.path_data_mut(path_id).total_recvd = len as u64; +3872 +3873 if let Some(hs) = self.state.as_handshake_mut() { +3874 hs.expected_token = packet.header.token.clone(); +3875 } else { +3876 unreachable!("first packet must be delivered in Handshake state"); +3877 } +3878 +3879 // The first packet is always on PathId::ZERO +3880 self.on_packet_authenticated( +3881 now, +3882 SpaceKind::Initial, +3883 path_id, +3884 ecn, +3885 Some(packet_number), +3886 false, +3887 false, +3888 &network_path, +3889 ); +3890 +3891 let packet: Packet = packet.into(); +3892 +3893 let mut qlog = QlogRecvPacket::new(len); +3894 qlog.header(&packet.header, Some(packet_number), path_id); +3895 +3896 self.process_decrypted_packet( +3897 now, +3898 network_path, +3899 path_id, +3900 Some(packet_number), +3901 packet, +3902 &mut qlog, +3903 )?; +3904 self.qlog.emit_packet_received(qlog, now); +3905 if let Some(data) = remaining { +3906 self.handle_coalesced(now, network_path, path_id, ecn, data); +3907 } +3908 +3909 self.qlog.emit_recovery_metrics( +3910 path_id, +3911 &mut self +3912 .paths +3913 .get_mut(&path_id) +3914 .expect("path_id was supplied by the caller for an active path") +3915 .data, +3916 now, +3917 ); +3918 +3919 Ok(()) +3920 } +3921 +3922 fn init_0rtt(&mut self, now: Instant) { +3923 let Some((header, packet)) = self.crypto_state.session.early_crypto() else { +3924 return; +3925 }; +3926 if self.side.is_client() { +3927 match self.crypto_state.session.transport_parameters() { +3928 Ok(params) => { +3929 let params = params +3930 .expect("crypto layer didn't supply transport parameters with ticket"); +3931 // Certain values must not be cached +3932 let params = TransportParameters { +3933 initial_src_cid: None, +3934 original_dst_cid: None, +3935 preferred_address: None, +3936 retry_src_cid: None, +3937 stateless_reset_token: None, +3938 min_ack_delay: None, +3939 ack_delay_exponent: TransportParameters::default().ack_delay_exponent, +3940 max_ack_delay: TransportParameters::default().max_ack_delay, +3941 initial_max_path_id: None, +3942 ..params +3943 }; +3944 self.set_peer_params(params); +3945 self.qlog.emit_peer_transport_params_restored(self, now); +3946 } +3947 Err(e) => { +3948 error!("session ticket has malformed transport parameters: {}", e); +3949 return; +3950 } +3951 } +3952 } +3953 trace!("0-RTT enabled"); +3954 self.crypto_state.enable_zero_rtt(header, packet); +3955 } +3956 +3957 fn read_crypto( +3958 &mut self, +3959 space: SpaceId, +3960 crypto: &frame::Crypto, +3961 payload_len: usize, +3962 ) -> Result<(), TransportError> { +3963 let expected = if !self.state.is_handshake() { +3964 SpaceId::Data +3965 } else if self.highest_space == SpaceKind::Initial { +3966 SpaceId::Initial +3967 } else { +3968 // On the server, self.highest_space can be Data after receiving the client's first +3969 // flight, but we expect Handshake CRYPTO until the handshake is complete. +3970 SpaceId::Handshake +3971 }; +3972 // We can't decrypt Handshake packets when highest_space is Initial, CRYPTO frames in 0-RTT +3973 // packets are illegal, and we don't process 1-RTT packets until the handshake is +3974 // complete. Therefore, we will never see CRYPTO data from a later-than-expected space. +3975 debug_assert!(space <= expected, "received out-of-order CRYPTO data"); +3976 +3977 let end = crypto.offset + crypto.data.len() as u64; +3978 if space < expected +3979 && end +3980 > self.crypto_state.spaces[space.kind()] +3981 .crypto_stream +3982 .bytes_read() +3983 { +3984 warn!( +3985 "received new {:?} CRYPTO data when expecting {:?}", +3986 space, expected +3987 ); +3988 return Err(TransportError::PROTOCOL_VIOLATION( +3989 "new data at unexpected encryption level", +3990 )); +3991 } +3992 +3993 let crypto_space = &mut self.crypto_state.spaces[space.kind()]; +3994 let max = end.saturating_sub(crypto_space.crypto_stream.bytes_read()); +3995 if max > self.config.crypto_buffer_size as u64 { +3996 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED("")); +3997 } +3998 +3999 crypto_space +4000 .crypto_stream +4001 .insert(crypto.offset, crypto.data.clone(), payload_len); +4002 while let Some(chunk) = crypto_space.crypto_stream.read(usize::MAX, true) { +4003 trace!("consumed {} CRYPTO bytes", chunk.bytes.len()); +4004 if self.crypto_state.session.read_handshake(&chunk.bytes)? { +4005 self.events.push_back(Event::HandshakeDataReady); +4006 } +4007 } +4008 +4009 Ok(()) +4010 } +4011 +4012 fn write_crypto(&mut self) { +4013 loop { +4014 let space = self.highest_space; +4015 let mut outgoing = Vec::new(); +4016 if let Some(crypto) = self.crypto_state.session.write_handshake(&mut outgoing) { +4017 match space { +4018 SpaceKind::Initial => { +4019 self.upgrade_crypto(SpaceKind::Handshake, crypto); +4020 } +4021 SpaceKind::Handshake => { +4022 self.upgrade_crypto(SpaceKind::Data, crypto); +4023 } +4024 SpaceKind::Data => unreachable!("got updated secrets during 1-RTT"), +4025 } +4026 } +4027 if outgoing.is_empty() { +4028 if space == self.highest_space { +4029 break; +4030 } else { +4031 // Keys updated, check for more data to send +4032 continue; +4033 } +4034 } +4035 let offset = self.crypto_state.spaces[space].crypto_offset; +4036 let outgoing = Bytes::from(outgoing); +4037 if let Some(hs) = self.state.as_handshake_mut() +4038 && space == SpaceKind::Initial +4039 && offset == 0 +4040 && self.side.is_client() +4041 { +4042 hs.client_hello = Some(outgoing.clone()); +4043 } +4044 self.crypto_state.spaces[space].crypto_offset += outgoing.len() as u64; +4045 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space); +4046 self.spaces[space].pending.crypto.push_back(frame::Crypto { +4047 offset, +4048 data: outgoing, +4049 }); +4050 } +4051 } +4052 +4053 /// Switch to stronger cryptography during handshake +4054 fn upgrade_crypto(&mut self, space: SpaceKind, crypto: Keys) { +4055 debug_assert!( +4056 !self.crypto_state.has_keys(space.encryption_level()), +4057 "already reached packet space {space:?}" +4058 ); +4059 trace!("{:?} keys ready", space); +4060 if space == SpaceKind::Data { +4061 // Precompute the first key update +4062 self.crypto_state.next_crypto = Some( +4063 self.crypto_state +4064 .session +4065 .next_1rtt_keys() +4066 .expect("handshake should be complete"), +4067 ); +4068 } +4069 +4070 self.crypto_state.spaces[space].keys = Some(crypto); +4071 debug_assert!(space > self.highest_space); +4072 self.highest_space = space; +4073 if space == SpaceKind::Data && self.side.is_client() { +4074 // Discard 0-RTT keys because 1-RTT keys are available. +4075 self.crypto_state.discard_zero_rtt(); +4076 } +4077 } +4078 +4079 fn discard_space(&mut self, now: Instant, space: SpaceKind) { +4080 debug_assert!(space != SpaceKind::Data); +4081 trace!("discarding {:?} keys", space); +4082 if space == SpaceKind::Initial { +4083 // No longer needed +4084 if let ConnectionSide::Client { token, .. } = &mut self.side { +4085 *token = Bytes::new(); +4086 } +4087 } +4088 self.crypto_state.spaces[space].keys = None; +4089 let space = &mut self.spaces[space]; +4090 let pns = space.for_path(PathId::ZERO); +4091 pns.time_of_last_ack_eliciting_packet = None; +4092 pns.loss_time = None; +4093 pns.loss_probes = 0; +4094 let sent_packets = mem::take(&mut pns.sent_packets); +4095 let path = self +4096 .paths +4097 .get_mut(&PathId::ZERO) +4098 .expect("PathId::ZERO is alive while Initial/Handshake spaces exist"); +4099 for (_, packet) in sent_packets.into_iter() { +4100 path.data.remove_in_flight(&packet); +4101 } +4102 +4103 self.set_loss_detection_timer(now, PathId::ZERO) +4104 } +4105 +4106 fn handle_coalesced( +4107 &mut self, +4108 now: Instant, +4109 network_path: FourTuple, +4110 path_id: PathId, +4111 ecn: Option<EcnCodepoint>, +4112 data: BytesMut, +4113 ) { +4114 self.path_data_mut(path_id) +4115 .inc_total_recvd(data.len() as u64); +4116 let mut remaining = Some(data); +4117 let cid_len = self +4118 .local_cid_state +4119 .values() +4120 .map(|cid_state| cid_state.cid_len()) +4121 .next() +4122 .expect("one cid_state must exist"); +4123 while let Some(data) = remaining { +4124 match PartialDecode::new( +4125 data, +4126 &FixedLengthConnectionIdParser::new(cid_len), +4127 &[self.version], +4128 self.endpoint_config.grease_quic_bit, +4129 ) { +4130 Ok((partial_decode, rest)) => { +4131 remaining = rest; +4132 self.handle_decode(now, network_path, path_id, ecn, partial_decode); +4133 } +4134 Err(e) => { +4135 trace!("malformed header: {}", e); +4136 return; +4137 } +4138 } +4139 } +4140 } +4141 +4142 /// Decrypts the packet and processes the payload. +4143 /// +4144 /// Processes the entire packet, starting with removing header protection, then handling +4145 /// a stateless reset if needed, and decrypting and processing the frames in the payload +4146 /// if not a stateless reset. +4147 fn handle_decode( +4148 &mut self, +4149 now: Instant, +4150 network_path: FourTuple, +4151 path_id: PathId, +4152 ecn: Option<EcnCodepoint>, +4153 partial_decode: PartialDecode, +4154 ) { +4155 let qlog = QlogRecvPacket::new(partial_decode.len()); +4156 if let Some(decoded) = self +4157 .crypto_state +4158 .unprotect_header(partial_decode, self.peer_params.stateless_reset_token) +4159 { +4160 self.handle_packet( +4161 now, +4162 network_path, +4163 path_id, +4164 ecn, +4165 decoded.packet, +4166 decoded.stateless_reset, +4167 qlog, +4168 ); +4169 } +4170 } +4171 +4172 /// Handles a packet with header protection removed. +4173 /// +4174 /// The packet body is still encrypted at this point. +4175 /// +4176 /// If the datagram was a stateless reset we may have failed to remove header protection +4177 /// and thus `packet` may be `None`. +4178 fn handle_packet( +4179 &mut self, +4180 now: Instant, +4181 network_path: FourTuple, +4182 path_id: PathId, +4183 ecn: Option<EcnCodepoint>, +4184 packet: Option<Packet>, +4185 stateless_reset: bool, +4186 mut qlog: QlogRecvPacket, +4187 ) { +4188 self.path_stats.for_path(path_id).udp_rx.ios += 1; +4189 +4190 if let Some(ref packet) = packet { +4191 trace!( +4192 "got {:?} packet ({} bytes) from {} using id {}", +4193 packet.header.space(), +4194 packet.payload.len() + packet.header_data.len(), +4195 network_path, +4196 packet.header.dst_cid(), +4197 ); +4198 } +4199 +4200 let was_closed = self.state.is_closed(); +4201 let was_drained = self.state.is_drained(); +4202 +4203 // Now decrypt the packet payload in-place. +4204 let decrypted = match packet { +4205 None => Err(None), +4206 Some(mut packet) => self +4207 .decrypt_packet(now, path_id, &mut packet) +4208 .map(move |number| (packet, number)), +4209 }; +4210 let result = match decrypted { +4211 _ if stateless_reset => { +4212 debug!("got stateless reset"); +4213 Err(ConnectionError::Reset) +4214 } +4215 Err(Some(e)) => { +4216 warn!("illegal packet: {}", e); +4217 Err(e.into()) +4218 } +4219 Err(None) => { +4220 debug!("failed to authenticate packet"); +4221 self.authentication_failures += 1; +4222 let integrity_limit = self +4223 .crypto_state +4224 .integrity_limit(self.highest_space) +4225 .unwrap(); +4226 if self.authentication_failures > integrity_limit { +4227 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into()) +4228 } else { +4229 return; +4230 } +4231 } +4232 Ok((packet, number)) => { +4233 // We received an authenticated packet and decrypted it. +4234 qlog.header(&packet.header, number, path_id); +4235 let span = match number { +4236 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn), +4237 None => trace_span!("recv", space = ?packet.header.space()), +4238 }; +4239 let _guard = span.enter(); +4240 +4241 // Now the packet is authenticated we do the migration during the +4242 // handshake. See Handshake::allow_server_migration for details. +4243 if self.is_handshaking() && network_path != self.path_data_mut(path_id).network_path +4244 { +4245 if let Some(hs) = self.state.as_handshake() +4246 && hs.allow_server_migration +4247 { +4248 trace!( +4249 %network_path, +4250 prev = %self.path_data(path_id).network_path, +4251 "server migrated to new remote", +4252 ); +4253 self.path_data_mut(path_id).network_path = network_path; +4254 self.qlog.emit_tuple_assigned(path_id, network_path, now); +4255 } else { +4256 debug!("discarding packet with unexpected remote during handshake"); +4257 return; +4258 } +4259 } +4260 +4261 let dedup = self.spaces[packet.header.space()] +4262 .path_space_mut(path_id) +4263 .map(|pns| &mut pns.dedup); +4264 if number.zip(dedup).is_some_and(|(n, d)| d.insert(n)) { +4265 debug!("discarding possible duplicate packet"); +4266 self.qlog.emit_packet_received(qlog, now); +4267 return; +4268 } else if self.state.is_handshake() && packet.header.is_short() { +4269 // TODO: SHOULD buffer these to improve reordering tolerance. +4270 trace!("dropping short packet during handshake"); +4271 self.qlog.emit_packet_received(qlog, now); +4272 return; +4273 } else { +4274 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header +4275 && let Some(hs) = self.state.as_handshake() +4276 && self.side.is_server() +4277 && token != &hs.expected_token +4278 { +4279 // Clients must send the same retry token in every Initial. Initial +4280 // packets can be spoofed, so we discard rather than killing the +4281 // connection. +4282 warn!("discarding Initial with invalid retry token"); +4283 self.qlog.emit_packet_received(qlog, now); +4284 return; +4285 } +4286 +4287 if !self.state.is_closed() { +4288 let spin = match packet.header { +4289 Header::Short { spin, .. } => spin, +4290 _ => false, +4291 }; +4292 +4293 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) { +4294 // Only the client is allowed to open paths +4295 self.ensure_path(path_id, network_path, now, number); +4296 } +4297 if self.paths.contains_key(&path_id) { +4298 self.on_packet_authenticated( +4299 now, +4300 packet.header.space(), +4301 path_id, +4302 ecn, +4303 number, +4304 spin, +4305 packet.header.is_1rtt(), +4306 &network_path, +4307 ); +4308 } +4309 } 4310 -4311 // State transitions for error cases -4312 if let Err(conn_err) = result { -4313 match conn_err { -4314 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason), -4315 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason), -4316 ConnectionError::Reset -4317 | ConnectionError::TransportError(TransportError { -4318 code: TransportErrorCode::AEAD_LIMIT_REACHED, -4319 .. -4320 }) => { -4321 self.state.move_to_drained(Some(conn_err)); +4311 let res = self.process_decrypted_packet( +4312 now, +4313 network_path, +4314 path_id, +4315 number, +4316 packet, +4317 &mut qlog, +4318 ); +4319 +4320 self.qlog.emit_packet_received(qlog, now); +4321 res 4322 } -4323 ConnectionError::TimedOut => { -4324 unreachable!("timeouts aren't generated by packet processing"); -4325 } -4326 ConnectionError::TransportError(err) => { -4327 debug!("closing connection due to transport error: {}", err); -4328 self.state.move_to_closed(err); -4329 } -4330 ConnectionError::VersionMismatch => { -4331 self.state.move_to_draining(Some(conn_err)); -4332 } -4333 ConnectionError::LocallyClosed => { -4334 unreachable!("LocallyClosed isn't generated by packet processing"); -4335 } -4336 ConnectionError::CidsExhausted => { -4337 unreachable!("CidsExhausted isn't generated by packet processing"); -4338 } -4339 }; -4340 } -4341 -4342 if !was_closed && self.state.is_closed() { -4343 self.close_common(); -4344 if !self.state.is_drained() { -4345 self.set_close_timer(now); -4346 } -4347 } -4348 if !was_drained && self.state.is_drained() { -4349 self.endpoint_events.push_back(EndpointEventInner::Drained); -4350 // Close timer may have been started previously, e.g. if we sent a close and got a -4351 // stateless reset in response -4352 self.timers -4353 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now)); -4354 } -4355 -4356 // Transmit CONNECTION_CLOSE if necessary. -4357 // -4358 // If we received a valid packet and we are in the closed state we should respond -4359 // with a CONNECTION_CLOSE frame. -4360 // TODO: This SHOULD be rate-limited according to §10.2.1 of QUIC-TRANSPORT, but -4361 // that does not yet happen. This is triggered by each received packet. -4362 if matches!(self.state.as_type(), StateType::Closed) { -4363 // From https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2.1-7 -4364 // -4365 // While in the closing state we must either: -4366 // - discard packets coming from an un-validated remote OR -4367 // - ensure we do not send more than 3 times the received data -4368 // -4369 // Doing the 2nd would mean we would be able to send CONNECTION_CLOSE to a peer -4370 // who was (involuntary) migrated just at the time we initiated immediate -4371 // close. It is a lot more work though. So while we would like to do this for -4372 // now we only do 1. -4373 // -4374 // Another shortcoming of the current implementation is that when we have a -4375 // previous PathData which is validated and the remote matches that path, we -4376 // should schedule CONNECTION_CLOSE on that path. However currently we can not -4377 // schedule such a packet. We should also fix this some day. This makes us -4378 // vulnerable to an attacker faking a migration at the right time and then we'd -4379 // be unable to send the CONNECTION_CLOSE to the real remote. -4380 if self -4381 .paths -4382 .get(&path_id) -4383 .map(|p| p.data.validated && p.data.network_path == network_path) -4384 .unwrap_or(false) -4385 { -4386 self.connection_close_pending = true; -4387 } -4388 } -4389 } -4390 -4391 fn process_decrypted_packet( -4392 &mut self, -4393 now: Instant, -4394 network_path: FourTuple, -4395 path_id: PathId, -4396 number: Option<u64>, -4397 packet: Packet, -4398 qlog: &mut QlogRecvPacket, -4399 ) -> Result<(), ConnectionError> { -4400 if !self.paths.contains_key(&path_id) { -4401 // There is a chance this is a server side, first (for this path) packet, which would -4402 // be a protocol violation. It's more likely, however, that this is a packet of a -4403 // pruned path -4404 trace!(%path_id, ?number, "discarding packet for unknown path"); -4405 return Ok(()); -4406 } -4407 let state = match self.state.as_type() { -4408 StateType::Established => { -4409 match packet.header.space() { -4410 SpaceKind::Data => self.process_payload( -4411 now, -4412 network_path, -4413 path_id, -4414 number.unwrap(), -4415 packet, -4416 qlog, -4417 )?, -4418 _ if packet.header.has_frames() => { -4419 self.process_early_payload(now, path_id, packet, qlog)? -4420 } -4421 _ => { -4422 trace!("discarding unexpected pre-handshake packet"); -4423 } -4424 } -4425 return Ok(()); -4426 } -4427 StateType::Closed => { -4428 for result in frame::Iter::new(packet.payload.freeze())? { -4429 let frame = match result { -4430 Ok(frame) => frame, -4431 Err(err) => { -4432 debug!("frame decoding error: {err:?}"); -4433 continue; -4434 } -4435 }; -4436 qlog.frame(&frame); -4437 -4438 if let Frame::Padding = frame { -4439 continue; -4440 }; -4441 -4442 self.path_stats -4443 .for_path(path_id) -4444 .frame_rx -4445 .record(frame.ty()); -4446 -4447 if let Frame::Close(_error) = frame { -4448 self.state.move_to_draining(None); -4449 break; -4450 } -4451 } -4452 return Ok(()); -4453 } -4454 StateType::Draining | StateType::Drained => return Ok(()), -4455 StateType::Handshake => self.state.as_handshake_mut().expect("checked"), -4456 }; -4457 -4458 match packet.header { -4459 Header::Retry { -4460 src_cid: remote_cid, -4461 .. -4462 } => { -4463 debug_assert_eq!(path_id, PathId::ZERO); -4464 if self.side.is_server() { -4465 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into()); +4323 } +4324 }; +4325 +4326 // State transitions for error cases +4327 if let Err(conn_err) = result { +4328 match conn_err { +4329 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason), +4330 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason), +4331 ConnectionError::Reset +4332 | ConnectionError::TransportError(TransportError { +4333 code: TransportErrorCode::AEAD_LIMIT_REACHED, +4334 .. +4335 }) => { +4336 self.state.move_to_drained(Some(conn_err)); +4337 } +4338 ConnectionError::TimedOut => { +4339 unreachable!("timeouts aren't generated by packet processing"); +4340 } +4341 ConnectionError::TransportError(err) => { +4342 debug!("closing connection due to transport error: {}", err); +4343 self.state.move_to_closed(err); +4344 } +4345 ConnectionError::VersionMismatch => { +4346 self.state.move_to_draining(Some(conn_err)); +4347 } +4348 ConnectionError::LocallyClosed => { +4349 unreachable!("LocallyClosed isn't generated by packet processing"); +4350 } +4351 ConnectionError::CidsExhausted => { +4352 unreachable!("CidsExhausted isn't generated by packet processing"); +4353 } +4354 }; +4355 } +4356 +4357 if !was_closed && self.state.is_closed() { +4358 self.close_common(); +4359 if !self.state.is_drained() { +4360 self.set_close_timer(now); +4361 } +4362 } +4363 if !was_drained && self.state.is_drained() { +4364 self.endpoint_events.push_back(EndpointEventInner::Drained); +4365 // Close timer may have been started previously, e.g. if we sent a close and got a +4366 // stateless reset in response +4367 self.timers +4368 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now)); +4369 } +4370 +4371 // Transmit CONNECTION_CLOSE if necessary. +4372 // +4373 // If we received a valid packet and we are in the closed state we should respond +4374 // with a CONNECTION_CLOSE frame. +4375 // TODO: This SHOULD be rate-limited according to §10.2.1 of QUIC-TRANSPORT, but +4376 // that does not yet happen. This is triggered by each received packet. +4377 if matches!(self.state.as_type(), StateType::Closed) { +4378 // From https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2.1-7 +4379 // +4380 // While in the closing state we must either: +4381 // - discard packets coming from an un-validated remote OR +4382 // - ensure we do not send more than 3 times the received data +4383 // +4384 // Doing the 2nd would mean we would be able to send CONNECTION_CLOSE to a peer +4385 // who was (involuntary) migrated just at the time we initiated immediate +4386 // close. It is a lot more work though. So while we would like to do this for +4387 // now we only do 1. +4388 // +4389 // Another shortcoming of the current implementation is that when we have a +4390 // previous PathData which is validated and the remote matches that path, we +4391 // should schedule CONNECTION_CLOSE on that path. However currently we can not +4392 // schedule such a packet. We should also fix this some day. This makes us +4393 // vulnerable to an attacker faking a migration at the right time and then we'd +4394 // be unable to send the CONNECTION_CLOSE to the real remote. +4395 if self +4396 .paths +4397 .get(&path_id) +4398 .map(|p| p.data.validated && p.data.network_path == network_path) +4399 .unwrap_or(false) +4400 { +4401 self.connection_close_pending = true; +4402 } +4403 } +4404 } +4405 +4406 fn process_decrypted_packet( +4407 &mut self, +4408 now: Instant, +4409 network_path: FourTuple, +4410 path_id: PathId, +4411 number: Option<u64>, +4412 packet: Packet, +4413 qlog: &mut QlogRecvPacket, +4414 ) -> Result<(), ConnectionError> { +4415 if !self.paths.contains_key(&path_id) { +4416 // There is a chance this is a server side, first (for this path) packet, which would +4417 // be a protocol violation. It's more likely, however, that this is a packet of a +4418 // pruned path +4419 trace!(%path_id, ?number, "discarding packet for unknown path"); +4420 return Ok(()); +4421 } +4422 let state = match self.state.as_type() { +4423 StateType::Established => { +4424 match packet.header.space() { +4425 SpaceKind::Data => self.process_payload( +4426 now, +4427 network_path, +4428 path_id, +4429 number.unwrap(), +4430 packet, +4431 qlog, +4432 )?, +4433 _ if packet.header.has_frames() => { +4434 self.process_early_payload(now, path_id, packet, qlog)? +4435 } +4436 _ => { +4437 trace!("discarding unexpected pre-handshake packet"); +4438 } +4439 } +4440 return Ok(()); +4441 } +4442 StateType::Closed => { +4443 for result in frame::Iter::new(packet.payload.freeze())? { +4444 let frame = match result { +4445 Ok(frame) => frame, +4446 Err(err) => { +4447 debug!("frame decoding error: {err:?}"); +4448 continue; +4449 } +4450 }; +4451 qlog.frame(&frame); +4452 +4453 if let Frame::Padding = frame { +4454 continue; +4455 }; +4456 +4457 self.path_stats +4458 .for_path(path_id) +4459 .frame_rx +4460 .record(frame.ty()); +4461 +4462 if let Frame::Close(_error) = frame { +4463 self.state.move_to_draining(None); +4464 break; +4465 } 4466 } -4467 -4468 let is_valid_retry = self -4469 .remote_cids -4470 .get(&path_id) -4471 .map(|cids| cids.active()) -4472 .map(|orig_dst_cid| { -4473 self.crypto_state.session.is_valid_retry( -4474 orig_dst_cid, -4475 &packet.header_data, -4476 &packet.payload, -4477 ) -4478 }) -4479 .unwrap_or_default(); -4480 if self.total_authed_packets > 1 -4481 || packet.payload.len() <= 16 // token + 16 byte tag -4482 || !is_valid_retry -4483 { -4484 trace!("discarding invalid Retry"); -4485 // - After the client has received and processed an Initial or Retry -4486 // packet from the server, it MUST discard any subsequent Retry -4487 // packets that it receives. -4488 // - A client MUST discard a Retry packet with a zero-length Retry Token -4489 // field. -4490 // - Clients MUST discard Retry packets that have a Retry Integrity Tag -4491 // that cannot be validated -4492 return Ok(()); -4493 } -4494 -4495 trace!("retrying with CID {}", remote_cid); -4496 let client_hello = state.client_hello.take().unwrap(); -4497 self.retry_src_cid = Some(remote_cid); -4498 self.remote_cids -4499 .get_mut(&path_id) -4500 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false") -4501 .update_initial_cid(remote_cid); -4502 self.remote_handshake_cid = remote_cid; -4503 -4504 let space = &mut self.spaces[SpaceId::Initial]; -4505 if let Some(info) = space.for_path(PathId::ZERO).take(0) { -4506 self.on_packet_acked(now, PathId::ZERO, 0, info); -4507 }; -4508 -4509 self.discard_space(now, SpaceKind::Initial); // Make sure we clean up after -4510 // any retransmitted Initials -4511 let crypto_space = &mut self.crypto_state.spaces[SpaceKind::Initial]; -4512 crypto_space.keys = Some( -4513 self.crypto_state -4514 .session -4515 .initial_keys(remote_cid, self.side.side()), -4516 ); -4517 crypto_space.crypto_offset = client_hello.len() as u64; +4467 return Ok(()); +4468 } +4469 StateType::Draining | StateType::Drained => return Ok(()), +4470 StateType::Handshake => self.state.as_handshake_mut().expect("checked"), +4471 }; +4472 +4473 match packet.header { +4474 Header::Retry { +4475 src_cid: remote_cid, +4476 .. +4477 } => { +4478 debug_assert_eq!(path_id, PathId::ZERO); +4479 if self.side.is_server() { +4480 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into()); +4481 } +4482 +4483 let is_valid_retry = self +4484 .remote_cids +4485 .get(&path_id) +4486 .map(|cids| cids.active()) +4487 .map(|orig_dst_cid| { +4488 self.crypto_state.session.is_valid_retry( +4489 orig_dst_cid, +4490 &packet.header_data, +4491 &packet.payload, +4492 ) +4493 }) +4494 .unwrap_or_default(); +4495 if self.total_authed_packets > 1 +4496 || packet.payload.len() <= 16 // token + 16 byte tag +4497 || !is_valid_retry +4498 { +4499 trace!("discarding invalid Retry"); +4500 // - After the client has received and processed an Initial or Retry +4501 // packet from the server, it MUST discard any subsequent Retry +4502 // packets that it receives. +4503 // - A client MUST discard a Retry packet with a zero-length Retry Token +4504 // field. +4505 // - Clients MUST discard Retry packets that have a Retry Integrity Tag +4506 // that cannot be validated +4507 return Ok(()); +4508 } +4509 +4510 trace!("retrying with CID {}", remote_cid); +4511 let client_hello = state.client_hello.take().unwrap(); +4512 self.retry_src_cid = Some(remote_cid); +4513 self.remote_cids +4514 .get_mut(&path_id) +4515 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false") +4516 .update_initial_cid(remote_cid); +4517 self.remote_handshake_cid = remote_cid; 4518 -4519 let next_pn = self.spaces[SpaceId::Initial] -4520 .for_path(path_id) -4521 .next_packet_number; -4522 self.spaces[SpaceId::Initial] = { -4523 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng); -4524 space.for_path(path_id).next_packet_number = next_pn; -4525 space.pending.crypto.push_back(frame::Crypto { -4526 offset: 0, -4527 data: client_hello, -4528 }); -4529 space -4530 }; -4531 -4532 // Retransmit all 0-RTT data -4533 let zero_rtt = mem::take( -4534 &mut self.spaces[SpaceId::Data] -4535 .for_path(PathId::ZERO) -4536 .sent_packets, -4537 ); -4538 for (_, info) in zero_rtt.into_iter() { -4539 self.paths -4540 .get_mut(&PathId::ZERO) -4541 .unwrap() -4542 .remove_in_flight(&info); -4543 self.spaces[SpaceId::Data].pending |= info.retransmits; -4544 } -4545 self.streams.retransmit_all_for_0rtt(); +4519 let space = &mut self.spaces[SpaceId::Initial]; +4520 if let Some(info) = space.for_path(PathId::ZERO).take(0) { +4521 self.on_packet_acked(now, PathId::ZERO, 0, info); +4522 }; +4523 +4524 self.discard_space(now, SpaceKind::Initial); // Make sure we clean up after +4525 // any retransmitted Initials +4526 let crypto_space = &mut self.crypto_state.spaces[SpaceKind::Initial]; +4527 crypto_space.keys = Some( +4528 self.crypto_state +4529 .session +4530 .initial_keys(remote_cid, self.side.side()), +4531 ); +4532 crypto_space.crypto_offset = client_hello.len() as u64; +4533 +4534 let next_pn = self.spaces[SpaceId::Initial] +4535 .for_path(path_id) +4536 .next_packet_number; +4537 self.spaces[SpaceId::Initial] = { +4538 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng); +4539 space.for_path(path_id).next_packet_number = next_pn; +4540 space.pending.crypto.push_back(frame::Crypto { +4541 offset: 0, +4542 data: client_hello, +4543 }); +4544 space +4545 }; 4546 -4547 let token_len = packet.payload.len() - 16; -4548 let ConnectionSide::Client { ref mut token, .. } = self.side else { -4549 unreachable!("we already short-circuited if we're server"); -4550 }; -4551 *token = packet.payload.freeze().split_to(token_len); -4552 -4553 self.state = State::handshake(state::Handshake { -4554 expected_token: Bytes::new(), -4555 remote_cid_set: false, -4556 client_hello: None, -4557 allow_server_migration: true, -4558 }); -4559 Ok(()) -4560 } -4561 Header::Long { -4562 ty: LongType::Handshake, -4563 src_cid: remote_cid, -4564 dst_cid: local_cid, -4565 .. -4566 } => { -4567 debug_assert_eq!(path_id, PathId::ZERO); -4568 if remote_cid != self.remote_handshake_cid { -4569 debug!( -4570 "discarding packet with mismatched remote CID: {} != {}", -4571 self.remote_handshake_cid, remote_cid -4572 ); -4573 return Ok(()); -4574 } -4575 self.on_path_validated(path_id); -4576 -4577 self.process_early_payload(now, path_id, packet, qlog)?; -4578 if self.state.is_closed() { -4579 return Ok(()); -4580 } -4581 -4582 if self.crypto_state.session.is_handshaking() { -4583 trace!("handshake ongoing"); -4584 return Ok(()); -4585 } -4586 -4587 if self.side.is_client() { -4588 // Client-only because server params were set from the client's Initial -4589 let params = self -4590 .crypto_state -4591 .session -4592 .transport_parameters()? -4593 .ok_or_else(|| { -4594 TransportError::new( -4595 TransportErrorCode::crypto(0x6d), -4596 "transport parameters missing".to_owned(), -4597 ) -4598 })?; -4599 -4600 if self.has_0rtt() { -4601 if !self.crypto_state.session.early_data_accepted().unwrap() { -4602 debug_assert!(self.side.is_client()); -4603 debug!("0-RTT rejected"); -4604 self.crypto_state.accepted_0rtt = false; -4605 self.streams.zero_rtt_rejected(); -4606 -4607 // Discard already-queued frames -4608 self.spaces[SpaceId::Data].pending = Retransmits::default(); -4609 -4610 // Discard 0-RTT packets -4611 let sent_packets = mem::take( -4612 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets, -4613 ); -4614 for (_, packet) in sent_packets.into_iter() { -4615 self.paths -4616 .get_mut(&path_id) -4617 .unwrap() -4618 .remove_in_flight(&packet); -4619 } -4620 } else { -4621 self.crypto_state.accepted_0rtt = true; -4622 params.validate_resumption_from(&self.peer_params)?; -4623 } -4624 } -4625 if let Some(token) = params.stateless_reset_token { -4626 let remote = self.path_data(path_id).network_path.remote; -4627 debug_assert!(!self.state.is_drained()); // requirement for endpoint events, checked above -4628 self.endpoint_events -4629 .push_back(EndpointEventInner::ResetToken(path_id, remote, token)); -4630 } -4631 self.handle_peer_params(params, local_cid, remote_cid, now)?; -4632 self.issue_first_cids(now); -4633 } else { -4634 // Server-only -4635 self.spaces[SpaceId::Data].pending.handshake_done = true; -4636 self.discard_space(now, SpaceKind::Handshake); -4637 self.events.push_back(Event::HandshakeConfirmed); -4638 trace!("handshake confirmed"); -4639 } -4640 -4641 self.events.push_back(Event::Connected); -4642 self.state.move_to_established(); -4643 trace!("established"); -4644 -4645 // Multipath can only be enabled after the state has reached Established. -4646 // So this can not happen any earlier. -4647 self.issue_first_path_cids(now); -4648 Ok(()) -4649 } -4650 Header::Initial(InitialHeader { -4651 src_cid: remote_cid, -4652 dst_cid: local_cid, -4653 .. -4654 }) => { -4655 debug_assert_eq!(path_id, PathId::ZERO); -4656 if !state.remote_cid_set { -4657 trace!("switching remote CID to {}", remote_cid); -4658 let mut state = state.clone(); -4659 self.remote_cids -4660 .get_mut(&path_id) -4661 .expect("PathId::ZERO not yet abandoned") -4662 .update_initial_cid(remote_cid); -4663 self.remote_handshake_cid = remote_cid; -4664 self.original_remote_cid = remote_cid; -4665 state.remote_cid_set = true; -4666 self.state.move_to_handshake(state); -4667 } else if remote_cid != self.remote_handshake_cid { -4668 debug!( -4669 "discarding packet with mismatched remote CID: {} != {}", -4670 self.remote_handshake_cid, remote_cid -4671 ); -4672 return Ok(()); -4673 } -4674 -4675 let starting_space = self.highest_space; -4676 self.process_early_payload(now, path_id, packet, qlog)?; -4677 -4678 if self.side.is_server() -4679 && starting_space == SpaceKind::Initial -4680 && self.highest_space != SpaceKind::Initial -4681 { -4682 let params = self -4683 .crypto_state -4684 .session -4685 .transport_parameters()? -4686 .ok_or_else(|| { -4687 TransportError::new( -4688 TransportErrorCode::crypto(0x6d), -4689 "transport parameters missing".to_owned(), -4690 ) -4691 })?; -4692 self.handle_peer_params(params, local_cid, remote_cid, now)?; -4693 self.issue_first_cids(now); -4694 self.init_0rtt(now); -4695 } -4696 Ok(()) -4697 } -4698 Header::Long { -4699 ty: LongType::ZeroRtt, -4700 .. -4701 } => { -4702 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?; -4703 Ok(()) -4704 } -4705 Header::VersionNegotiate { .. } => { -4706 if self.total_authed_packets > 1 { -4707 return Ok(()); -4708 } -4709 let supported = packet -4710 .payload -4711 .chunks(4) -4712 .any(|x| match <[u8; 4]>::try_from(x) { -4713 Ok(version) => self.version == u32::from_be_bytes(version), -4714 Err(_) => false, -4715 }); -4716 if supported { -4717 return Ok(()); -4718 } -4719 debug!("remote doesn't support our version"); -4720 Err(ConnectionError::VersionMismatch) -4721 } -4722 Header::Short { .. } => unreachable!( -4723 "short packets received during handshake are discarded in handle_packet" -4724 ), -4725 } -4726 } -4727 -4728 /// Process an Initial or Handshake packet payload -4729 fn process_early_payload( -4730 &mut self, -4731 now: Instant, -4732 path_id: PathId, -4733 packet: Packet, -4734 #[allow(unused)] qlog: &mut QlogRecvPacket, -4735 ) -> Result<(), TransportError> { -4736 debug_assert_ne!(packet.header.space(), SpaceKind::Data); -4737 debug_assert_eq!(path_id, PathId::ZERO); -4738 let payload_len = packet.payload.len(); -4739 let mut ack_eliciting = false; -4740 for result in frame::Iter::new(packet.payload.freeze())? { -4741 let frame = result?; -4742 qlog.frame(&frame); -4743 let span = match frame { -4744 Frame::Padding => continue, -4745 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)), -4746 }; -4747 -4748 self.path_stats -4749 .for_path(path_id) -4750 .frame_rx -4751 .record(frame.ty()); -4752 -4753 let _guard = span.as_ref().map(|x| x.enter()); -4754 ack_eliciting |= frame.is_ack_eliciting(); -4755 -4756 // Process frames -4757 if frame.is_1rtt() && packet.header.space() != SpaceKind::Data { -4758 return Err(TransportError::PROTOCOL_VIOLATION( -4759 "illegal frame type in handshake", -4760 )); -4761 } +4547 // Retransmit all 0-RTT data +4548 let zero_rtt = mem::take( +4549 &mut self.spaces[SpaceId::Data] +4550 .for_path(PathId::ZERO) +4551 .sent_packets, +4552 ); +4553 for (_, info) in zero_rtt.into_iter() { +4554 self.paths +4555 .get_mut(&PathId::ZERO) +4556 .unwrap() +4557 .remove_in_flight(&info); +4558 self.spaces[SpaceId::Data].pending |= info.retransmits; +4559 } +4560 self.streams.retransmit_all_for_0rtt(); +4561 +4562 let token_len = packet.payload.len() - 16; +4563 let ConnectionSide::Client { ref mut token, .. } = self.side else { +4564 unreachable!("we already short-circuited if we're server"); +4565 }; +4566 *token = packet.payload.freeze().split_to(token_len); +4567 +4568 self.state = State::handshake(state::Handshake { +4569 expected_token: Bytes::new(), +4570 remote_cid_set: false, +4571 client_hello: None, +4572 allow_server_migration: true, +4573 }); +4574 Ok(()) +4575 } +4576 Header::Long { +4577 ty: LongType::Handshake, +4578 src_cid: remote_cid, +4579 dst_cid: local_cid, +4580 .. +4581 } => { +4582 debug_assert_eq!(path_id, PathId::ZERO); +4583 if remote_cid != self.remote_handshake_cid { +4584 debug!( +4585 "discarding packet with mismatched remote CID: {} != {}", +4586 self.remote_handshake_cid, remote_cid +4587 ); +4588 return Ok(()); +4589 } +4590 self.on_path_validated(path_id); +4591 +4592 self.process_early_payload(now, path_id, packet, qlog)?; +4593 if self.state.is_closed() { +4594 return Ok(()); +4595 } +4596 +4597 if self.crypto_state.session.is_handshaking() { +4598 trace!("handshake ongoing"); +4599 return Ok(()); +4600 } +4601 +4602 if self.side.is_client() { +4603 // Client-only because server params were set from the client's Initial +4604 let params = self +4605 .crypto_state +4606 .session +4607 .transport_parameters()? +4608 .ok_or_else(|| { +4609 TransportError::new( +4610 TransportErrorCode::crypto(0x6d), +4611 "transport parameters missing".to_owned(), +4612 ) +4613 })?; +4614 +4615 if self.has_0rtt() { +4616 if !self.crypto_state.session.early_data_accepted().unwrap() { +4617 debug_assert!(self.side.is_client()); +4618 debug!("0-RTT rejected"); +4619 self.crypto_state.accepted_0rtt = false; +4620 self.streams.zero_rtt_rejected(); +4621 +4622 // Discard already-queued frames +4623 self.spaces[SpaceId::Data].pending = Retransmits::default(); +4624 +4625 // Discard 0-RTT packets +4626 let sent_packets = mem::take( +4627 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets, +4628 ); +4629 for (_, packet) in sent_packets.into_iter() { +4630 self.paths +4631 .get_mut(&path_id) +4632 .unwrap() +4633 .remove_in_flight(&packet); +4634 } +4635 } else { +4636 self.crypto_state.accepted_0rtt = true; +4637 params.validate_resumption_from(&self.peer_params)?; +4638 } +4639 } +4640 if let Some(token) = params.stateless_reset_token { +4641 let remote = self.path_data(path_id).network_path.remote; +4642 debug_assert!(!self.state.is_drained()); // requirement for endpoint events, checked above +4643 self.endpoint_events +4644 .push_back(EndpointEventInner::ResetToken(path_id, remote, token)); +4645 } +4646 self.handle_peer_params(params, local_cid, remote_cid, now)?; +4647 self.issue_first_cids(now); +4648 } else { +4649 // Server-only +4650 self.spaces[SpaceId::Data].pending.handshake_done = true; +4651 self.discard_space(now, SpaceKind::Handshake); +4652 self.events.push_back(Event::HandshakeConfirmed); +4653 trace!("handshake confirmed"); +4654 } +4655 +4656 self.events.push_back(Event::Connected); +4657 self.state.move_to_established(); +4658 trace!("established"); +4659 +4660 // Multipath can only be enabled after the state has reached Established. +4661 // So this can not happen any earlier. +4662 self.issue_first_path_cids(now); +4663 Ok(()) +4664 } +4665 Header::Initial(InitialHeader { +4666 src_cid: remote_cid, +4667 dst_cid: local_cid, +4668 .. +4669 }) => { +4670 debug_assert_eq!(path_id, PathId::ZERO); +4671 if !state.remote_cid_set { +4672 trace!("switching remote CID to {}", remote_cid); +4673 let mut state = state.clone(); +4674 self.remote_cids +4675 .get_mut(&path_id) +4676 .expect("PathId::ZERO not yet abandoned") +4677 .update_initial_cid(remote_cid); +4678 self.remote_handshake_cid = remote_cid; +4679 self.original_remote_cid = remote_cid; +4680 state.remote_cid_set = true; +4681 self.state.move_to_handshake(state); +4682 } else if remote_cid != self.remote_handshake_cid { +4683 debug!( +4684 "discarding packet with mismatched remote CID: {} != {}", +4685 self.remote_handshake_cid, remote_cid +4686 ); +4687 return Ok(()); +4688 } +4689 +4690 let starting_space = self.highest_space; +4691 self.process_early_payload(now, path_id, packet, qlog)?; +4692 +4693 if self.side.is_server() +4694 && starting_space == SpaceKind::Initial +4695 && self.highest_space != SpaceKind::Initial +4696 { +4697 let params = self +4698 .crypto_state +4699 .session +4700 .transport_parameters()? +4701 .ok_or_else(|| { +4702 TransportError::new( +4703 TransportErrorCode::crypto(0x6d), +4704 "transport parameters missing".to_owned(), +4705 ) +4706 })?; +4707 self.handle_peer_params(params, local_cid, remote_cid, now)?; +4708 self.issue_first_cids(now); +4709 self.init_0rtt(now); +4710 } +4711 Ok(()) +4712 } +4713 Header::Long { +4714 ty: LongType::ZeroRtt, +4715 .. +4716 } => { +4717 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?; +4718 Ok(()) +4719 } +4720 Header::VersionNegotiate { .. } => { +4721 if self.total_authed_packets > 1 { +4722 return Ok(()); +4723 } +4724 let supported = packet +4725 .payload +4726 .chunks(4) +4727 .any(|x| match <[u8; 4]>::try_from(x) { +4728 Ok(version) => self.version == u32::from_be_bytes(version), +4729 Err(_) => false, +4730 }); +4731 if supported { +4732 return Ok(()); +4733 } +4734 debug!("remote doesn't support our version"); +4735 Err(ConnectionError::VersionMismatch) +4736 } +4737 Header::Short { .. } => unreachable!( +4738 "short packets received during handshake are discarded in handle_packet" +4739 ), +4740 } +4741 } +4742 +4743 /// Process an Initial or Handshake packet payload +4744 fn process_early_payload( +4745 &mut self, +4746 now: Instant, +4747 path_id: PathId, +4748 packet: Packet, +4749 #[allow(unused)] qlog: &mut QlogRecvPacket, +4750 ) -> Result<(), TransportError> { +4751 debug_assert_ne!(packet.header.space(), SpaceKind::Data); +4752 debug_assert_eq!(path_id, PathId::ZERO); +4753 let payload_len = packet.payload.len(); +4754 let mut ack_eliciting = false; +4755 for result in frame::Iter::new(packet.payload.freeze())? { +4756 let frame = result?; +4757 qlog.frame(&frame); +4758 let span = match frame { +4759 Frame::Padding => continue, +4760 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)), +4761 }; 4762 -4763 match frame { -4764 Frame::Padding | Frame::Ping => {} -4765 Frame::Crypto(frame) => { -4766 self.read_crypto(packet.header.space().into(), &frame, payload_len)?; -4767 } -4768 Frame::Ack(ack) => { -4769 self.on_ack_received(now, packet.header.space().into(), ack)?; -4770 } -4771 Frame::PathAck(ack) => { -4772 span.as_ref() -4773 .map(|span| span.record("path", tracing::field::display(&ack.path_id))); -4774 self.on_path_ack_received(now, packet.header.space().into(), ack)?; -4775 } -4776 Frame::Close(reason) => { -4777 self.state.move_to_draining(Some(reason.into())); -4778 return Ok(()); -4779 } -4780 _ => { -4781 let mut err = -4782 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake"); -4783 err.frame = frame::MaybeFrame::Known(frame.ty()); -4784 return Err(err); +4763 self.path_stats +4764 .for_path(path_id) +4765 .frame_rx +4766 .record(frame.ty()); +4767 +4768 let _guard = span.as_ref().map(|x| x.enter()); +4769 ack_eliciting |= frame.is_ack_eliciting(); +4770 +4771 // Process frames +4772 if frame.is_1rtt() && packet.header.space() != SpaceKind::Data { +4773 return Err(TransportError::PROTOCOL_VIOLATION( +4774 "illegal frame type in handshake", +4775 )); +4776 } +4777 +4778 match frame { +4779 Frame::Padding | Frame::Ping => {} +4780 Frame::Crypto(frame) => { +4781 self.read_crypto(packet.header.space().into(), &frame, payload_len)?; +4782 } +4783 Frame::Ack(ack) => { +4784 self.on_ack_received(now, packet.header.space().into(), ack)?; 4785 } -4786 } -4787 } -4788 -4789 if ack_eliciting { -4790 // In the initial and handshake spaces, ACKs must be sent immediately -4791 self.spaces[packet.header.space()] -4792 .for_path(path_id) -4793 .pending_acks -4794 .set_immediate_ack_required(); -4795 } -4796 -4797 self.write_crypto(); -4798 Ok(()) -4799 } -4800 -4801 /// Processes the decrypted packet payload, always in the data space. -4802 fn process_payload( -4803 &mut self, -4804 now: Instant, -4805 network_path: FourTuple, -4806 path_id: PathId, -4807 number: u64, -4808 packet: Packet, -4809 #[allow(unused)] qlog: &mut QlogRecvPacket, -4810 ) -> Result<(), TransportError> { -4811 let is_multipath_negotiated = self.is_multipath_negotiated(); -4812 let payload = packet.payload.freeze(); -4813 let mut is_probing_packet = true; -4814 let mut close = None; -4815 let payload_len = payload.len(); -4816 let mut ack_eliciting = false; -4817 // if this packet triggers a path migration and includes a observed address frame, it's -4818 // stored here -4819 let mut migration_observed_addr = None; -4820 for result in frame::Iter::new(payload)? { -4821 let frame = result?; -4822 qlog.frame(&frame); -4823 let span = match frame { -4824 Frame::Padding => continue, -4825 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty), -4826 }; -4827 -4828 self.path_stats -4829 .for_path(path_id) -4830 .frame_rx -4831 .record(frame.ty()); -4832 // Crypto, Stream and Datagram frames are special cased in order no pollute -4833 // the log with payload data -4834 match &frame { -4835 Frame::Crypto(f) => { -4836 trace!(offset = f.offset, len = f.data.len(), "got frame CRYPTO"); -4837 } -4838 Frame::Stream(f) => { -4839 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got frame STREAM"); -4840 } -4841 Frame::Datagram(f) => { -4842 trace!(len = f.data.len(), "got frame DATAGRAM"); -4843 } -4844 f => { -4845 trace!("got frame {f}"); -4846 } -4847 } -4848 -4849 let _guard = span.enter(); -4850 if packet.header.is_0rtt() { -4851 match frame { -4852 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => { -4853 return Err(TransportError::PROTOCOL_VIOLATION( -4854 "illegal frame type in 0-RTT", -4855 )); -4856 } -4857 _ => { -4858 if frame.is_1rtt() { -4859 return Err(TransportError::PROTOCOL_VIOLATION( -4860 "illegal frame type in 0-RTT", -4861 )); -4862 } -4863 } -4864 } -4865 } -4866 ack_eliciting |= frame.is_ack_eliciting(); -4867 -4868 // Check whether this could be a probing packet -4869 match frame { -4870 Frame::Padding -4871 | Frame::PathChallenge(_) -4872 | Frame::PathResponse(_) -4873 | Frame::NewConnectionId(_) -4874 | Frame::ObservedAddr(_) => {} -4875 _ => { -4876 is_probing_packet = false; -4877 } -4878 } -4879 -4880 match frame { -4881 Frame::Crypto(frame) => { -4882 self.read_crypto(SpaceId::Data, &frame, payload_len)?; -4883 } -4884 Frame::Stream(frame) => { -4885 if self.streams.received(frame, payload_len)?.should_transmit() { -4886 self.spaces[SpaceId::Data].pending.max_data = true; -4887 } -4888 } -4889 Frame::Ack(ack) => { -4890 self.on_ack_received(now, SpaceId::Data, ack)?; -4891 } -4892 Frame::PathAck(ack) => { -4893 if !self.is_multipath_negotiated() { -4894 return Err(TransportError::PROTOCOL_VIOLATION( -4895 "received PATH_ACK frame when multipath was not negotiated", -4896 )); -4897 } -4898 span.record("path", tracing::field::display(&ack.path_id)); -4899 self.on_path_ack_received(now, SpaceId::Data, ack)?; -4900 } -4901 Frame::Padding | Frame::Ping => {} -4902 Frame::Close(reason) => { -4903 close = Some(reason); -4904 } -4905 Frame::PathChallenge(challenge) => { -4906 let path = &mut self -4907 .path_mut(path_id) -4908 .expect("payload is processed only after the path becomes known"); -4909 path.path_responses.push(number, challenge.0, network_path); -4910 // If we were passively migrated (e.g. NAT rebinding), our local_ip will -4911 // not match. Once we processed a non-probing packet the local_ip will -4912 // finally be updated. -4913 if network_path.remote == path.network_path.remote { -4914 // PATH_CHALLENGE on active path, possible off-path packet -4915 // forwarding attack. Send a non-probing packet to recover the -4916 // active path. See -4917 // https://www.rfc-editor.org/rfc/rfc9000.html#section-9.3.3-3. In -4918 // rare cases NAT probes might also appear on-path and would also -4919 // get a non-probing packet as response. There is little harm in -4920 // this. -4921 match self.peer_supports_ack_frequency() { -4922 true => self.immediate_ack(path_id), -4923 false => { -4924 self.ping_path(path_id).ok(); -4925 } -4926 } -4927 } -4928 } -4929 Frame::PathResponse(response) => { -4930 // First try to see if this is a NAT probe response. -4931 if self -4932 .n0_nat_traversal -4933 .handle_path_response(network_path, response.0) -4934 { -4935 self.open_nat_traversed_paths(now); -4936 } else { -4937 // Try to see if this is a response to an on-path PATH_CHALLENGE. -4938 -4939 let path = self -4940 .paths -4941 .get_mut(&path_id) -4942 .expect("payload is processed only after the path becomes known"); -4943 -4944 use PathTimer::*; -4945 use paths::OnPathResponseReceived::*; -4946 match path -4947 .data -4948 .on_path_response_received(now, response.0, network_path) -4949 { -4950 OnPath { was_open } => { -4951 let qlog = self.qlog.with_time(now); -4952 -4953 self.timers.stop( -4954 Timer::PerPath(path_id, PathValidationFailed), -4955 qlog.clone(), -4956 ); -4957 self.timers.stop( -4958 Timer::PerPath(path_id, AbandonFromValidation), -4959 qlog.clone(), -4960 ); -4961 -4962 let next_challenge = path -4963 .data -4964 .earliest_on_path_expiring_challenge() -4965 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); -4966 self.timers.set_or_stop( -4967 Timer::PerPath(path_id, PathChallengeLost), -4968 next_challenge, -4969 qlog, -4970 ); -4971 -4972 if !was_open { -4973 if is_multipath_negotiated { -4974 self.events.push_back(Event::Path(PathEvent::Opened { -4975 id: path_id, -4976 })); -4977 } -4978 if let Some(observed) = -4979 path.data.last_observed_addr_report.as_ref() -4980 { -4981 self.events.push_back(Event::Path( -4982 PathEvent::ObservedAddr { -4983 id: path_id, -4984 addr: observed.socket_addr(), -4985 }, -4986 )); -4987 } -4988 } -4989 if let Some((_, ref mut prev)) = path.prev { -4990 // If an on-path response was received while there is a -4991 // previous path from a migration, then the new path is -4992 // validated and we can stop sending challenges that try to -4993 // re-validate the previous path. -4994 prev.reset_on_path_challenges(); -4995 } -4996 } -4997 Ignored { -4998 sent_on, -4999 current_path, -5000 } => { -5001 debug!(%sent_on, %current_path, %response, "ignoring valid PATH_RESPONSE") -5002 } -5003 Unknown => debug!(%response, "ignoring invalid PATH_RESPONSE"), -5004 } -5005 } -5006 } -5007 Frame::MaxData(frame::MaxData(bytes)) => { -5008 self.streams.received_max_data(bytes); -5009 } -5010 Frame::MaxStreamData(frame::MaxStreamData { id, offset }) => { -5011 self.streams.received_max_stream_data(id, offset)?; -5012 } -5013 Frame::MaxStreams(frame::MaxStreams { dir, count }) => { -5014 self.streams.received_max_streams(dir, count)?; -5015 } -5016 Frame::ResetStream(frame) => { -5017 if self.streams.received_reset(frame)?.should_transmit() { -5018 self.spaces[SpaceId::Data].pending.max_data = true; -5019 } -5020 } -5021 Frame::DataBlocked(DataBlocked(offset)) => { -5022 debug!(offset, "peer claims to be blocked at connection level"); -5023 } -5024 Frame::StreamDataBlocked(StreamDataBlocked { id, offset }) => { -5025 if id.initiator() == self.side.side() && id.dir() == Dir::Uni { -5026 debug!("got STREAM_DATA_BLOCKED on send-only {}", id); -5027 return Err(TransportError::STREAM_STATE_ERROR( -5028 "STREAM_DATA_BLOCKED on send-only stream", -5029 )); -5030 } -5031 debug!( -5032 stream = %id, -5033 offset, "peer claims to be blocked at stream level" -5034 ); +4786 Frame::PathAck(ack) => { +4787 span.as_ref() +4788 .map(|span| span.record("path", tracing::field::display(&ack.path_id))); +4789 self.on_path_ack_received(now, packet.header.space().into(), ack)?; +4790 } +4791 Frame::Close(reason) => { +4792 self.state.move_to_draining(Some(reason.into())); +4793 return Ok(()); +4794 } +4795 _ => { +4796 let mut err = +4797 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake"); +4798 err.frame = frame::MaybeFrame::Known(frame.ty()); +4799 return Err(err); +4800 } +4801 } +4802 } +4803 +4804 if ack_eliciting { +4805 // In the initial and handshake spaces, ACKs must be sent immediately +4806 self.spaces[packet.header.space()] +4807 .for_path(path_id) +4808 .pending_acks +4809 .set_immediate_ack_required(); +4810 } +4811 +4812 self.write_crypto(); +4813 Ok(()) +4814 } +4815 +4816 /// Processes the decrypted packet payload, always in the data space. +4817 fn process_payload( +4818 &mut self, +4819 now: Instant, +4820 network_path: FourTuple, +4821 path_id: PathId, +4822 number: u64, +4823 packet: Packet, +4824 #[allow(unused)] qlog: &mut QlogRecvPacket, +4825 ) -> Result<(), TransportError> { +4826 let is_multipath_negotiated = self.is_multipath_negotiated(); +4827 let payload = packet.payload.freeze(); +4828 let mut is_probing_packet = true; +4829 let mut close = None; +4830 let payload_len = payload.len(); +4831 let mut ack_eliciting = false; +4832 // if this packet triggers a path migration and includes a observed address frame, it's +4833 // stored here +4834 let mut migration_observed_addr = None; +4835 for result in frame::Iter::new(payload)? { +4836 let frame = result?; +4837 qlog.frame(&frame); +4838 let span = match frame { +4839 Frame::Padding => continue, +4840 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty), +4841 }; +4842 +4843 self.path_stats +4844 .for_path(path_id) +4845 .frame_rx +4846 .record(frame.ty()); +4847 // Crypto, Stream and Datagram frames are special cased in order no pollute +4848 // the log with payload data +4849 match &frame { +4850 Frame::Crypto(f) => { +4851 trace!(offset = f.offset, len = f.data.len(), "got frame CRYPTO"); +4852 } +4853 Frame::Stream(f) => { +4854 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got frame STREAM"); +4855 } +4856 Frame::Datagram(f) => { +4857 trace!(len = f.data.len(), "got frame DATAGRAM"); +4858 } +4859 f => { +4860 trace!("got frame {f}"); +4861 } +4862 } +4863 +4864 let _guard = span.enter(); +4865 if packet.header.is_0rtt() { +4866 match frame { +4867 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => { +4868 return Err(TransportError::PROTOCOL_VIOLATION( +4869 "illegal frame type in 0-RTT", +4870 )); +4871 } +4872 _ => { +4873 if frame.is_1rtt() { +4874 return Err(TransportError::PROTOCOL_VIOLATION( +4875 "illegal frame type in 0-RTT", +4876 )); +4877 } +4878 } +4879 } +4880 } +4881 ack_eliciting |= frame.is_ack_eliciting(); +4882 +4883 // Check whether this could be a probing packet +4884 match frame { +4885 Frame::Padding +4886 | Frame::PathChallenge(_) +4887 | Frame::PathResponse(_) +4888 | Frame::NewConnectionId(_) +4889 | Frame::ObservedAddr(_) => {} +4890 _ => { +4891 is_probing_packet = false; +4892 } +4893 } +4894 +4895 match frame { +4896 Frame::Crypto(frame) => { +4897 self.read_crypto(SpaceId::Data, &frame, payload_len)?; +4898 } +4899 Frame::Stream(frame) => { +4900 if self.streams.received(frame, payload_len)?.should_transmit() { +4901 self.spaces[SpaceId::Data].pending.max_data = true; +4902 } +4903 } +4904 Frame::Ack(ack) => { +4905 self.on_ack_received(now, SpaceId::Data, ack)?; +4906 } +4907 Frame::PathAck(ack) => { +4908 if !self.is_multipath_negotiated() { +4909 return Err(TransportError::PROTOCOL_VIOLATION( +4910 "received PATH_ACK frame when multipath was not negotiated", +4911 )); +4912 } +4913 span.record("path", tracing::field::display(&ack.path_id)); +4914 self.on_path_ack_received(now, SpaceId::Data, ack)?; +4915 } +4916 Frame::Padding | Frame::Ping => {} +4917 Frame::Close(reason) => { +4918 close = Some(reason); +4919 } +4920 Frame::PathChallenge(challenge) => { +4921 let path = &mut self +4922 .path_mut(path_id) +4923 .expect("payload is processed only after the path becomes known"); +4924 path.path_responses.push(number, challenge.0, network_path); +4925 // If we were passively migrated (e.g. NAT rebinding), our local_ip will +4926 // not match. Once we processed a non-probing packet the local_ip will +4927 // finally be updated. +4928 if network_path.remote == path.network_path.remote { +4929 // PATH_CHALLENGE on active path, possible off-path packet +4930 // forwarding attack. Send a non-probing packet to recover the +4931 // active path. See +4932 // https://www.rfc-editor.org/rfc/rfc9000.html#section-9.3.3-3. In +4933 // rare cases NAT probes might also appear on-path and would also +4934 // get a non-probing packet as response. There is little harm in +4935 // this. +4936 match self.peer_supports_ack_frequency() { +4937 true => self.immediate_ack(path_id), +4938 false => { +4939 self.ping_path(path_id).ok(); +4940 } +4941 } +4942 } +4943 } +4944 Frame::PathResponse(response) => { +4945 // First try to see if this is a NAT probe response. +4946 if self +4947 .n0_nat_traversal +4948 .handle_path_response(network_path, response.0) +4949 { +4950 self.open_nat_traversed_paths(now); +4951 } else { +4952 // Try to see if this is a response to an on-path PATH_CHALLENGE. +4953 +4954 let path = self +4955 .paths +4956 .get_mut(&path_id) +4957 .expect("payload is processed only after the path becomes known"); +4958 +4959 use PathTimer::*; +4960 use paths::OnPathResponseReceived::*; +4961 match path +4962 .data +4963 .on_path_response_received(now, response.0, network_path) +4964 { +4965 OnPath { was_open } => { +4966 let qlog = self.qlog.with_time(now); +4967 +4968 self.timers.stop( +4969 Timer::PerPath(path_id, PathValidationFailed), +4970 qlog.clone(), +4971 ); +4972 self.timers.stop( +4973 Timer::PerPath(path_id, AbandonFromValidation), +4974 qlog.clone(), +4975 ); +4976 +4977 let next_challenge = path +4978 .data +4979 .earliest_on_path_expiring_challenge() +4980 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); +4981 self.timers.set_or_stop( +4982 Timer::PerPath(path_id, PathChallengeLost), +4983 next_challenge, +4984 qlog, +4985 ); +4986 +4987 if !was_open { +4988 if is_multipath_negotiated { +4989 self.events.push_back(Event::Path(PathEvent::Opened { +4990 id: path_id, +4991 })); +4992 } +4993 if let Some(observed) = +4994 path.data.last_observed_addr_report.as_ref() +4995 { +4996 self.events.push_back(Event::Path( +4997 PathEvent::ObservedAddr { +4998 id: path_id, +4999 addr: observed.socket_addr(), +5000 }, +5001 )); +5002 } +5003 } +5004 if let Some((_, ref mut prev)) = path.prev { +5005 // If an on-path response was received while there is a +5006 // previous path from a migration, then the new path is +5007 // validated and we can stop sending challenges that try to +5008 // re-validate the previous path. +5009 prev.reset_on_path_challenges(); +5010 } +5011 } +5012 Ignored { +5013 sent_on, +5014 current_path, +5015 } => { +5016 debug!(%sent_on, %current_path, %response, "ignoring valid PATH_RESPONSE") +5017 } +5018 Unknown => debug!(%response, "ignoring invalid PATH_RESPONSE"), +5019 } +5020 } +5021 } +5022 Frame::MaxData(frame::MaxData(bytes)) => { +5023 self.streams.received_max_data(bytes); +5024 } +5025 Frame::MaxStreamData(frame::MaxStreamData { id, offset }) => { +5026 self.streams.received_max_stream_data(id, offset)?; +5027 } +5028 Frame::MaxStreams(frame::MaxStreams { dir, count }) => { +5029 self.streams.received_max_streams(dir, count)?; +5030 } +5031 Frame::ResetStream(frame) => { +5032 if self.streams.received_reset(frame)?.should_transmit() { +5033 self.spaces[SpaceId::Data].pending.max_data = true; +5034 } 5035 } -5036 Frame::StreamsBlocked(StreamsBlocked { dir, limit }) => { -5037 if limit > MAX_STREAM_COUNT { -5038 return Err(TransportError::FRAME_ENCODING_ERROR( -5039 "unrepresentable stream limit", -5040 )); -5041 } -5042 debug!( -5043 "peer claims to be blocked opening more than {} {} streams", -5044 limit, dir -5045 ); -5046 } -5047 Frame::StopSending(frame::StopSending { id, error_code }) => { -5048 if id.initiator() != self.side.side() { -5049 if id.dir() == Dir::Uni { -5050 debug!("got STOP_SENDING on recv-only {}", id); -5051 return Err(TransportError::STREAM_STATE_ERROR( -5052 "STOP_SENDING on recv-only stream", -5053 )); -5054 } -5055 } else if self.streams.is_local_unopened(id) { -5056 return Err(TransportError::STREAM_STATE_ERROR( -5057 "STOP_SENDING on unopened stream", -5058 )); -5059 } -5060 self.streams.received_stop_sending(id, error_code); +5036 Frame::DataBlocked(DataBlocked(offset)) => { +5037 debug!(offset, "peer claims to be blocked at connection level"); +5038 } +5039 Frame::StreamDataBlocked(StreamDataBlocked { id, offset }) => { +5040 if id.initiator() == self.side.side() && id.dir() == Dir::Uni { +5041 debug!("got STREAM_DATA_BLOCKED on send-only {}", id); +5042 return Err(TransportError::STREAM_STATE_ERROR( +5043 "STREAM_DATA_BLOCKED on send-only stream", +5044 )); +5045 } +5046 debug!( +5047 stream = %id, +5048 offset, "peer claims to be blocked at stream level" +5049 ); +5050 } +5051 Frame::StreamsBlocked(StreamsBlocked { dir, limit }) => { +5052 if limit > MAX_STREAM_COUNT { +5053 return Err(TransportError::FRAME_ENCODING_ERROR( +5054 "unrepresentable stream limit", +5055 )); +5056 } +5057 debug!( +5058 "peer claims to be blocked opening more than {} {} streams", +5059 limit, dir +5060 ); 5061 } -5062 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => { -5063 if let Some(ref path_id) = path_id { -5064 span.record("path", tracing::field::display(&path_id)); -5065 } -5066 let path_id = path_id.unwrap_or_default(); -5067 match self.local_cid_state.get_mut(&path_id) { -5068 None => error!(?path_id, "RETIRE_CONNECTION_ID for unknown path"), -5069 Some(cid_state) => { -5070 let allow_more_cids = cid_state -5071 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?; -5072 -5073 // If the path has closed, we do not issue more CIDs for this path -5074 // For details see https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-3.2.2 -5075 // > an endpoint SHOULD provide new connection IDs for that path, if still open, using PATH_NEW_CONNECTION_ID frames. -5076 let has_path = !self.abandoned_paths.contains(&path_id); -5077 let allow_more_cids = allow_more_cids && has_path; -5078 -5079 debug_assert!(!self.state.is_drained()); // required for adding endpoint events, process_payload is never called for drained connections -5080 self.endpoint_events -5081 .push_back(EndpointEventInner::RetireConnectionId( -5082 now, -5083 path_id, -5084 sequence, -5085 allow_more_cids, -5086 )); -5087 } -5088 } -5089 } -5090 Frame::NewConnectionId(frame) => { -5091 let path_id = if let Some(path_id) = frame.path_id { -5092 if !self.is_multipath_negotiated() { -5093 return Err(TransportError::PROTOCOL_VIOLATION( -5094 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated", -5095 )); -5096 } -5097 if path_id > self.local_max_path_id { -5098 return Err(TransportError::PROTOCOL_VIOLATION( -5099 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max", -5100 )); -5101 } -5102 path_id -5103 } else { -5104 PathId::ZERO -5105 }; -5106 -5107 if let Some(ref path_id) = frame.path_id { -5108 span.record("path", tracing::field::display(&path_id)); -5109 } -5110 -5111 if self.abandoned_paths.contains(&path_id) { -5112 trace!("ignoring issued CID for abandoned path"); -5113 continue; -5114 } -5115 let remote_cids = self -5116 .remote_cids -5117 .entry(path_id) -5118 .or_insert_with(|| CidQueue::new(frame.id)); -5119 if remote_cids.active().is_empty() { -5120 return Err(TransportError::PROTOCOL_VIOLATION( -5121 "NEW_CONNECTION_ID when CIDs aren't in use", -5122 )); -5123 } -5124 if frame.retire_prior_to > frame.sequence { -5125 return Err(TransportError::PROTOCOL_VIOLATION( -5126 "NEW_CONNECTION_ID retiring unissued CIDs", -5127 )); -5128 } -5129 -5130 use crate::cid_queue::InsertError; -5131 match remote_cids.insert(frame) { -5132 Ok(None) => { -5133 self.open_nat_traversed_paths(now); -5134 } -5135 Ok(Some((retired, reset_token))) => { -5136 let pending_retired = -5137 &mut self.spaces[SpaceId::Data].pending.retire_cids; -5138 /// Ensure `pending_retired` cannot grow without bound. Limit is -5139 /// somewhat arbitrary but very permissive. -5140 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10; -5141 // We don't bother counting in-flight frames because those are bounded -5142 // by congestion control. -5143 if (pending_retired.len() as u64) -5144 .saturating_add(retired.end.saturating_sub(retired.start)) -5145 > MAX_PENDING_RETIRED_CIDS -5146 { -5147 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR( -5148 "queued too many retired CIDs", -5149 )); -5150 } -5151 pending_retired.extend(retired.map(|seq| (path_id, seq))); -5152 self.set_reset_token(path_id, network_path.remote, reset_token); -5153 self.open_nat_traversed_paths(now); -5154 } -5155 Err(InsertError::ExceedsLimit) => { -5156 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR("")); -5157 } -5158 Err(InsertError::Retired) => { -5159 trace!("discarding already-retired"); -5160 // RETIRE_CONNECTION_ID might not have been previously sent if e.g. a -5161 // range of connection IDs larger than the active connection ID limit -5162 // was retired all at once via retire_prior_to. -5163 self.spaces[SpaceId::Data] -5164 .pending -5165 .retire_cids -5166 .push((path_id, frame.sequence)); -5167 continue; -5168 } -5169 }; -5170 -5171 if self.side.is_server() -5172 && path_id == PathId::ZERO -5173 && self -5174 .remote_cids -5175 .get(&PathId::ZERO) -5176 .map(|cids| cids.active_seq() == 0) -5177 .unwrap_or_default() -5178 { -5179 // We're a server still using the initial remote CID for the client, so -5180 // let's switch immediately to enable clientside stateless resets. -5181 self.update_remote_cid(PathId::ZERO); -5182 } -5183 } -5184 Frame::NewToken(NewToken { token }) => { -5185 let ConnectionSide::Client { -5186 token_store, -5187 server_name, -5188 .. -5189 } = &self.side -5190 else { -5191 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN")); -5192 }; -5193 if token.is_empty() { -5194 return Err(TransportError::FRAME_ENCODING_ERROR("empty token")); -5195 } -5196 trace!("got new token"); -5197 token_store.insert(server_name, token); +5062 Frame::StopSending(frame::StopSending { id, error_code }) => { +5063 if id.initiator() != self.side.side() { +5064 if id.dir() == Dir::Uni { +5065 debug!("got STOP_SENDING on recv-only {}", id); +5066 return Err(TransportError::STREAM_STATE_ERROR( +5067 "STOP_SENDING on recv-only stream", +5068 )); +5069 } +5070 } else if self.streams.is_local_unopened(id) { +5071 return Err(TransportError::STREAM_STATE_ERROR( +5072 "STOP_SENDING on unopened stream", +5073 )); +5074 } +5075 self.streams.received_stop_sending(id, error_code); +5076 } +5077 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => { +5078 if let Some(ref path_id) = path_id { +5079 span.record("path", tracing::field::display(&path_id)); +5080 } +5081 let path_id = path_id.unwrap_or_default(); +5082 match self.local_cid_state.get_mut(&path_id) { +5083 None => error!(?path_id, "RETIRE_CONNECTION_ID for unknown path"), +5084 Some(cid_state) => { +5085 let allow_more_cids = cid_state +5086 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?; +5087 +5088 // If the path has closed, we do not issue more CIDs for this path +5089 // For details see https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-3.2.2 +5090 // > an endpoint SHOULD provide new connection IDs for that path, if still open, using PATH_NEW_CONNECTION_ID frames. +5091 let has_path = !self.abandoned_paths.contains(&path_id); +5092 let allow_more_cids = allow_more_cids && has_path; +5093 +5094 debug_assert!(!self.state.is_drained()); // required for adding endpoint events, process_payload is never called for drained connections +5095 self.endpoint_events +5096 .push_back(EndpointEventInner::RetireConnectionId( +5097 now, +5098 path_id, +5099 sequence, +5100 allow_more_cids, +5101 )); +5102 } +5103 } +5104 } +5105 Frame::NewConnectionId(frame) => { +5106 let path_id = if let Some(path_id) = frame.path_id { +5107 if !self.is_multipath_negotiated() { +5108 return Err(TransportError::PROTOCOL_VIOLATION( +5109 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated", +5110 )); +5111 } +5112 if path_id > self.local_max_path_id { +5113 return Err(TransportError::PROTOCOL_VIOLATION( +5114 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max", +5115 )); +5116 } +5117 path_id +5118 } else { +5119 PathId::ZERO +5120 }; +5121 +5122 if let Some(ref path_id) = frame.path_id { +5123 span.record("path", tracing::field::display(&path_id)); +5124 } +5125 +5126 if self.abandoned_paths.contains(&path_id) { +5127 trace!("ignoring issued CID for abandoned path"); +5128 continue; +5129 } +5130 let remote_cids = self +5131 .remote_cids +5132 .entry(path_id) +5133 .or_insert_with(|| CidQueue::new(frame.id)); +5134 if remote_cids.active().is_empty() { +5135 return Err(TransportError::PROTOCOL_VIOLATION( +5136 "NEW_CONNECTION_ID when CIDs aren't in use", +5137 )); +5138 } +5139 if frame.retire_prior_to > frame.sequence { +5140 return Err(TransportError::PROTOCOL_VIOLATION( +5141 "NEW_CONNECTION_ID retiring unissued CIDs", +5142 )); +5143 } +5144 +5145 use crate::cid_queue::InsertError; +5146 match remote_cids.insert(frame) { +5147 Ok(None) => { +5148 self.open_nat_traversed_paths(now); +5149 } +5150 Ok(Some((retired, reset_token))) => { +5151 let pending_retired = +5152 &mut self.spaces[SpaceId::Data].pending.retire_cids; +5153 /// Ensure `pending_retired` cannot grow without bound. Limit is +5154 /// somewhat arbitrary but very permissive. +5155 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10; +5156 // We don't bother counting in-flight frames because those are bounded +5157 // by congestion control. +5158 if (pending_retired.len() as u64) +5159 .saturating_add(retired.end.saturating_sub(retired.start)) +5160 > MAX_PENDING_RETIRED_CIDS +5161 { +5162 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR( +5163 "queued too many retired CIDs", +5164 )); +5165 } +5166 pending_retired.extend(retired.map(|seq| (path_id, seq))); +5167 self.set_reset_token(path_id, network_path.remote, reset_token); +5168 self.open_nat_traversed_paths(now); +5169 } +5170 Err(InsertError::ExceedsLimit) => { +5171 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR("")); +5172 } +5173 Err(InsertError::Retired) => { +5174 trace!("discarding already-retired"); +5175 // RETIRE_CONNECTION_ID might not have been previously sent if e.g. a +5176 // range of connection IDs larger than the active connection ID limit +5177 // was retired all at once via retire_prior_to. +5178 self.spaces[SpaceId::Data] +5179 .pending +5180 .retire_cids +5181 .push((path_id, frame.sequence)); +5182 continue; +5183 } +5184 }; +5185 +5186 if self.side.is_server() +5187 && path_id == PathId::ZERO +5188 && self +5189 .remote_cids +5190 .get(&PathId::ZERO) +5191 .map(|cids| cids.active_seq() == 0) +5192 .unwrap_or_default() +5193 { +5194 // We're a server still using the initial remote CID for the client, so +5195 // let's switch immediately to enable clientside stateless resets. +5196 self.update_remote_cid(PathId::ZERO); +5197 } 5198 } -5199 Frame::Datagram(datagram) => { -5200 if self -5201 .datagrams -5202 .received(datagram, &self.config.datagram_receive_buffer_size)? -5203 { -5204 self.events.push_back(Event::DatagramReceived); -5205 } -5206 } -5207 Frame::AckFrequency(ack_frequency) => { -5208 // This frame can only be sent in the Data space -5209 -5210 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? { -5211 // The AckFrequency frame is stale (we have already received a more -5212 // recent one) -5213 continue; -5214 } -5215 -5216 // Update the params for all of our paths -5217 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() { -5218 space.pending_acks.set_ack_frequency_params(&ack_frequency); -5219 -5220 // Our `max_ack_delay` has been updated, so we may need to adjust -5221 // its associated timeout. -5222 // Packets received on abandoned paths are always acknowledged immediately. -5223 if !self.abandoned_paths.contains(path_id) -5224 && let Some(timeout) = space -5225 .pending_acks -5226 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay) -5227 { -5228 self.timers.set( -5229 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), -5230 timeout, -5231 self.qlog.with_time(now), -5232 ); -5233 } -5234 } -5235 } -5236 Frame::ImmediateAck => { -5237 // This frame can only be sent in the Data space -5238 for pns in self.spaces[SpaceId::Data].iter_paths_mut() { -5239 pns.pending_acks.set_immediate_ack_required(); -5240 } -5241 } -5242 Frame::HandshakeDone => { -5243 if self.side.is_server() { -5244 return Err(TransportError::PROTOCOL_VIOLATION( -5245 "client sent HANDSHAKE_DONE", -5246 )); -5247 } -5248 if self.crypto_state.has_keys(EncryptionLevel::Handshake) { -5249 self.discard_space(now, SpaceKind::Handshake); -5250 self.events.push_back(Event::HandshakeConfirmed); -5251 trace!("handshake confirmed"); -5252 } -5253 } -5254 Frame::ObservedAddr(observed) => { -5255 // check if params allows the peer to send report and this node to receive it -5256 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port); -5257 if !self -5258 .peer_params -5259 .address_discovery_role -5260 .should_report(&self.config.address_discovery_role) -5261 { -5262 return Err(TransportError::PROTOCOL_VIOLATION( -5263 "received OBSERVED_ADDRESS frame when not negotiated", -5264 )); -5265 } -5266 // must only be sent in data space -5267 if packet.header.space() != SpaceKind::Data { -5268 return Err(TransportError::PROTOCOL_VIOLATION( -5269 "OBSERVED_ADDRESS frame outside data space", -5270 )); -5271 } -5272 -5273 let path = self.path_data_mut(path_id); -5274 if network_path == path.network_path { -5275 if let Some(updated) = path.update_observed_addr_report(observed) -5276 && path.open_status == paths::OpenStatus::Informed -5277 { -5278 self.events.push_back(Event::Path(PathEvent::ObservedAddr { -5279 id: path_id, -5280 addr: updated, -5281 })); -5282 // otherwise the event is reported when the path is deemed open -5283 } -5284 } else { -5285 // include in migration -5286 migration_observed_addr = Some(observed) -5287 } -5288 } -5289 Frame::PathAbandon(frame::PathAbandon { -5290 path_id, -5291 error_code, -5292 }) => { -5293 span.record("path", tracing::field::display(&path_id)); -5294 match self.close_path_inner( -5295 now, -5296 path_id, -5297 PathAbandonReason::RemoteAbandoned { -5298 error_code: error_code.into(), -5299 }, -5300 ) { -5301 Ok(()) => { -5302 trace!("peer abandoned path"); -5303 } -5304 Err(ClosePathError::ClosedPath) => { -5305 trace!("peer abandoned already closed path"); -5306 } -5307 Err(ClosePathError::MultipathNotNegotiated) => { -5308 return Err(TransportError::PROTOCOL_VIOLATION( -5309 "received PATH_ABANDON frame when multipath was not negotiated", -5310 )); -5311 } -5312 Err(ClosePathError::LastOpenPath) => { -5313 // Not reachable: close_path_inner allows remote abandons -5314 // for the last path. But handle gracefully just in case. -5315 error!( -5316 "peer abandoned last path but close_path_inner returned LastOpenPath" -5317 ); +5199 Frame::NewToken(NewToken { token }) => { +5200 let ConnectionSide::Client { +5201 token_store, +5202 server_name, +5203 .. +5204 } = &self.side +5205 else { +5206 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN")); +5207 }; +5208 if token.is_empty() { +5209 return Err(TransportError::FRAME_ENCODING_ERROR("empty token")); +5210 } +5211 trace!("got new token"); +5212 token_store.insert(server_name, token); +5213 } +5214 Frame::Datagram(datagram) => { +5215 if self +5216 .datagrams +5217 .received(datagram, &self.config.datagram_receive_buffer_size)? +5218 { +5219 self.events.push_back(Event::DatagramReceived); +5220 } +5221 } +5222 Frame::AckFrequency(ack_frequency) => { +5223 // This frame can only be sent in the Data space +5224 +5225 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? { +5226 // The AckFrequency frame is stale (we have already received a more +5227 // recent one) +5228 continue; +5229 } +5230 +5231 // Update the params for all of our paths +5232 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() { +5233 space.pending_acks.set_ack_frequency_params(&ack_frequency); +5234 +5235 // Our `max_ack_delay` has been updated, so we may need to adjust +5236 // its associated timeout. +5237 // Packets received on abandoned paths are always acknowledged immediately. +5238 if !self.abandoned_paths.contains(path_id) +5239 && let Some(timeout) = space +5240 .pending_acks +5241 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay) +5242 { +5243 self.timers.set( +5244 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), +5245 timeout, +5246 self.qlog.with_time(now), +5247 ); +5248 } +5249 } +5250 } +5251 Frame::ImmediateAck => { +5252 // This frame can only be sent in the Data space +5253 for pns in self.spaces[SpaceId::Data].iter_paths_mut() { +5254 pns.pending_acks.set_immediate_ack_required(); +5255 } +5256 } +5257 Frame::HandshakeDone => { +5258 if self.side.is_server() { +5259 return Err(TransportError::PROTOCOL_VIOLATION( +5260 "client sent HANDSHAKE_DONE", +5261 )); +5262 } +5263 if self.crypto_state.has_keys(EncryptionLevel::Handshake) { +5264 self.discard_space(now, SpaceKind::Handshake); +5265 self.events.push_back(Event::HandshakeConfirmed); +5266 trace!("handshake confirmed"); +5267 } +5268 } +5269 Frame::ObservedAddr(observed) => { +5270 // check if params allows the peer to send report and this node to receive it +5271 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port); +5272 if !self +5273 .peer_params +5274 .address_discovery_role +5275 .should_report(&self.config.address_discovery_role) +5276 { +5277 return Err(TransportError::PROTOCOL_VIOLATION( +5278 "received OBSERVED_ADDRESS frame when not negotiated", +5279 )); +5280 } +5281 // must only be sent in data space +5282 if packet.header.space() != SpaceKind::Data { +5283 return Err(TransportError::PROTOCOL_VIOLATION( +5284 "OBSERVED_ADDRESS frame outside data space", +5285 )); +5286 } +5287 +5288 let path = self.path_data_mut(path_id); +5289 if network_path == path.network_path { +5290 if let Some(updated) = path.update_observed_addr_report(observed) +5291 && path.open_status == paths::OpenStatus::Informed +5292 { +5293 self.events.push_back(Event::Path(PathEvent::ObservedAddr { +5294 id: path_id, +5295 addr: updated, +5296 })); +5297 // otherwise the event is reported when the path is deemed open +5298 } +5299 } else { +5300 // include in migration +5301 migration_observed_addr = Some(observed) +5302 } +5303 } +5304 Frame::PathAbandon(frame::PathAbandon { +5305 path_id, +5306 error_code, +5307 }) => { +5308 span.record("path", tracing::field::display(&path_id)); +5309 match self.close_path_inner( +5310 now, +5311 path_id, +5312 PathAbandonReason::RemoteAbandoned { +5313 error_code: error_code.into(), +5314 }, +5315 ) { +5316 Ok(()) => { +5317 trace!("peer abandoned path"); 5318 } -5319 }; -5320 -5321 // Start draining the path if it still exists and hasn't started draining yet. -5322 if let Some(path) = self.paths.get_mut(&path_id) -5323 && !mem::replace(&mut path.data.draining, true) -5324 { -5325 let ack_delay = self.ack_frequency.max_ack_delay_for_pto(); -5326 let pto = path.data.rtt.pto_base() + ack_delay; -5327 self.timers.set( -5328 Timer::PerPath(path_id, PathTimer::PathDrained), -5329 now + 3 * pto, -5330 self.qlog.with_time(now), -5331 ); -5332 -5333 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8)); -5334 } -5335 } -5336 Frame::PathStatusAvailable(info) => { -5337 span.record("path", tracing::field::display(&info.path_id)); -5338 if self.is_multipath_negotiated() { -5339 self.on_path_status( -5340 info.path_id, -5341 PathStatus::Available, -5342 info.status_seq_no, -5343 ); -5344 } else { -5345 return Err(TransportError::PROTOCOL_VIOLATION( -5346 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated", -5347 )); -5348 } -5349 } -5350 Frame::PathStatusBackup(info) => { -5351 span.record("path", tracing::field::display(&info.path_id)); -5352 if self.is_multipath_negotiated() { -5353 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no); -5354 } else { -5355 return Err(TransportError::PROTOCOL_VIOLATION( -5356 "received PATH_STATUS_BACKUP frame when multipath was not negotiated", -5357 )); -5358 } -5359 } -5360 Frame::MaxPathId(frame::MaxPathId(path_id)) => { -5361 span.record("path", tracing::field::display(&path_id)); -5362 if !self.is_multipath_negotiated() { -5363 return Err(TransportError::PROTOCOL_VIOLATION( -5364 "received MAX_PATH_ID frame when multipath was not negotiated", -5365 )); -5366 } -5367 // frames that do not increase the path id are ignored -5368 if path_id > self.remote_max_path_id { -5369 self.remote_max_path_id = path_id; -5370 self.issue_first_path_cids(now); -5371 self.open_nat_traversed_paths(now); -5372 } -5373 } -5374 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => { -5375 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST -5376 // be treated as a connection error of type PROTOCOL_VIOLATION. -5377 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> -5378 if self.is_multipath_negotiated() { -5379 if max_path_id > self.local_max_path_id { -5380 return Err(TransportError::PROTOCOL_VIOLATION( -5381 "PATHS_BLOCKED maximum path identifier was larger than local maximum", -5382 )); -5383 } -5384 debug!("received PATHS_BLOCKED({:?})", max_path_id); -5385 // TODO(@divma): ensure max concurrent paths -5386 } else { -5387 return Err(TransportError::PROTOCOL_VIOLATION( -5388 "received PATHS_BLOCKED frame when not multipath was not negotiated", -5389 )); -5390 } -5391 } -5392 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => { -5393 // Nothing to do. This is recorded in the frame stats, but otherwise we -5394 // always issue all CIDs we're allowed to issue, so either this is an -5395 // impatient peer or a bug on our side. -5396 -5397 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST -5398 // be treated as a connection error of type PROTOCOL_VIOLATION. -5399 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> -5400 if self.is_multipath_negotiated() { -5401 if path_id > self.local_max_path_id { -5402 return Err(TransportError::PROTOCOL_VIOLATION( -5403 "PATH_CIDS_BLOCKED path identifier was larger than local maximum", -5404 )); -5405 } -5406 if next_seq.0 -5407 > self -5408 .local_cid_state -5409 .get(&path_id) -5410 .map(|cid_state| cid_state.active_seq().1 + 1) -5411 .unwrap_or_default() -5412 { -5413 return Err(TransportError::PROTOCOL_VIOLATION( -5414 "PATH_CIDS_BLOCKED next sequence number larger than in local state", -5415 )); -5416 } -5417 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED"); -5418 } else { -5419 return Err(TransportError::PROTOCOL_VIOLATION( -5420 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated", -5421 )); -5422 } -5423 } -5424 Frame::AddAddress(addr) => { -5425 let client_state = match self.n0_nat_traversal.client_side_mut() { -5426 Ok(state) => state, -5427 Err(err) => { -5428 return Err(TransportError::PROTOCOL_VIOLATION(format!( -5429 "Nat traversal(ADD_ADDRESS): {err}" -5430 ))); +5319 Err(ClosePathError::ClosedPath) => { +5320 trace!("peer abandoned already closed path"); +5321 } +5322 Err(ClosePathError::MultipathNotNegotiated) => { +5323 return Err(TransportError::PROTOCOL_VIOLATION( +5324 "received PATH_ABANDON frame when multipath was not negotiated", +5325 )); +5326 } +5327 Err(ClosePathError::LastOpenPath) => { +5328 // Not reachable: close_path_inner allows remote abandons +5329 // for the last path. But handle gracefully just in case. +5330 error!( +5331 "peer abandoned last path but close_path_inner returned LastOpenPath" +5332 ); +5333 } +5334 }; +5335 +5336 // Start draining the path if it still exists and hasn't started draining yet. +5337 if let Some(path) = self.paths.get_mut(&path_id) +5338 && !mem::replace(&mut path.data.draining, true) +5339 { +5340 let ack_delay = self.ack_frequency.max_ack_delay_for_pto(); +5341 let pto = path.data.rtt.pto_base() + ack_delay; +5342 self.timers.set( +5343 Timer::PerPath(path_id, PathTimer::PathDrained), +5344 now + 3 * pto, +5345 self.qlog.with_time(now), +5346 ); +5347 +5348 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8)); +5349 } +5350 } +5351 Frame::PathStatusAvailable(info) => { +5352 span.record("path", tracing::field::display(&info.path_id)); +5353 if self.is_multipath_negotiated() { +5354 self.on_path_status( +5355 info.path_id, +5356 PathStatus::Available, +5357 info.status_seq_no, +5358 ); +5359 } else { +5360 return Err(TransportError::PROTOCOL_VIOLATION( +5361 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated", +5362 )); +5363 } +5364 } +5365 Frame::PathStatusBackup(info) => { +5366 span.record("path", tracing::field::display(&info.path_id)); +5367 if self.is_multipath_negotiated() { +5368 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no); +5369 } else { +5370 return Err(TransportError::PROTOCOL_VIOLATION( +5371 "received PATH_STATUS_BACKUP frame when multipath was not negotiated", +5372 )); +5373 } +5374 } +5375 Frame::MaxPathId(frame::MaxPathId(path_id)) => { +5376 span.record("path", tracing::field::display(&path_id)); +5377 if !self.is_multipath_negotiated() { +5378 return Err(TransportError::PROTOCOL_VIOLATION( +5379 "received MAX_PATH_ID frame when multipath was not negotiated", +5380 )); +5381 } +5382 // frames that do not increase the path id are ignored +5383 if path_id > self.remote_max_path_id { +5384 self.remote_max_path_id = path_id; +5385 self.issue_first_path_cids(now); +5386 self.open_nat_traversed_paths(now); +5387 } +5388 } +5389 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => { +5390 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST +5391 // be treated as a connection error of type PROTOCOL_VIOLATION. +5392 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> +5393 if self.is_multipath_negotiated() { +5394 if max_path_id > self.local_max_path_id { +5395 return Err(TransportError::PROTOCOL_VIOLATION( +5396 "PATHS_BLOCKED maximum path identifier was larger than local maximum", +5397 )); +5398 } +5399 debug!("received PATHS_BLOCKED({:?})", max_path_id); +5400 // TODO(@divma): ensure max concurrent paths +5401 } else { +5402 return Err(TransportError::PROTOCOL_VIOLATION( +5403 "received PATHS_BLOCKED frame when not multipath was not negotiated", +5404 )); +5405 } +5406 } +5407 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => { +5408 // Nothing to do. This is recorded in the frame stats, but otherwise we +5409 // always issue all CIDs we're allowed to issue, so either this is an +5410 // impatient peer or a bug on our side. +5411 +5412 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST +5413 // be treated as a connection error of type PROTOCOL_VIOLATION. +5414 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> +5415 if self.is_multipath_negotiated() { +5416 if path_id > self.local_max_path_id { +5417 return Err(TransportError::PROTOCOL_VIOLATION( +5418 "PATH_CIDS_BLOCKED path identifier was larger than local maximum", +5419 )); +5420 } +5421 if next_seq.0 +5422 > self +5423 .local_cid_state +5424 .get(&path_id) +5425 .map(|cid_state| cid_state.active_seq().1 + 1) +5426 .unwrap_or_default() +5427 { +5428 return Err(TransportError::PROTOCOL_VIOLATION( +5429 "PATH_CIDS_BLOCKED next sequence number larger than in local state", +5430 )); 5431 } -5432 }; -5433 -5434 if !client_state.check_remote_address(&addr) { -5435 // if the address is not valid we flag it, but update anyway -5436 warn!(?addr, "server sent illegal ADD_ADDRESS frame"); +5432 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED"); +5433 } else { +5434 return Err(TransportError::PROTOCOL_VIOLATION( +5435 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated", +5436 )); 5437 } -5438 -5439 match client_state.add_remote_address(addr) { -5440 Ok(maybe_added) => { -5441 if let Some(added) = maybe_added { -5442 self.events.push_back(Event::NatTraversal( -5443 n0_nat_traversal::Event::AddressAdded(added), -5444 )); -5445 } +5438 } +5439 Frame::AddAddress(addr) => { +5440 let client_state = match self.n0_nat_traversal.client_side_mut() { +5441 Ok(state) => state, +5442 Err(err) => { +5443 return Err(TransportError::PROTOCOL_VIOLATION(format!( +5444 "Nat traversal(ADD_ADDRESS): {err}" +5445 ))); 5446 } -5447 Err(e) => { -5448 warn!(%e, "failed to add remote address") -5449 } -5450 } -5451 } -5452 Frame::RemoveAddress(addr) => { -5453 let client_state = match self.n0_nat_traversal.client_side_mut() { -5454 Ok(state) => state, -5455 Err(err) => { -5456 return Err(TransportError::PROTOCOL_VIOLATION(format!( -5457 "Nat traversal(REMOVE_ADDRESS): {err}" -5458 ))); -5459 } -5460 }; -5461 if let Some(removed_addr) = client_state.remove_remote_address(addr) { -5462 self.events.push_back(Event::NatTraversal( -5463 n0_nat_traversal::Event::AddressRemoved(removed_addr), -5464 )); +5447 }; +5448 +5449 if !client_state.check_remote_address(&addr) { +5450 // if the address is not valid we flag it, but update anyway +5451 warn!(?addr, "server sent illegal ADD_ADDRESS frame"); +5452 } +5453 +5454 match client_state.add_remote_address(addr) { +5455 Ok(maybe_added) => { +5456 if let Some(added) = maybe_added { +5457 self.events.push_back(Event::NatTraversal( +5458 n0_nat_traversal::Event::AddressAdded(added), +5459 )); +5460 } +5461 } +5462 Err(e) => { +5463 warn!(%e, "failed to add remote address") +5464 } 5465 } 5466 } -5467 Frame::ReachOut(reach_out) => { -5468 let ipv6 = self.is_ipv6(); -5469 let server_state = match self.n0_nat_traversal.server_side_mut() { -5470 Ok(state) => state, -5471 Err(err) => { -5472 return Err(TransportError::PROTOCOL_VIOLATION(format!( -5473 "Nat traversal(REACH_OUT): {err}" -5474 ))); -5475 } -5476 }; -5477 -5478 let round_before = server_state.current_round(); -5479 -5480 if let Err(err) = server_state.handle_reach_out(reach_out, ipv6) { -5481 return Err(TransportError::PROTOCOL_VIOLATION(format!( -5482 "Nat traversal(REACH_OUT): {err}" -5483 ))); -5484 } -5485 -5486 if server_state.current_round() > round_before { -5487 // A new round was started, reset the NAT probe retry timer. -5488 let delay = RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; -5489 self.timers.set( -5490 Timer::Conn(ConnTimer::NatTraversalProbeRetry), -5491 now + delay, -5492 self.qlog.with_time(now), -5493 ); -5494 } -5495 } -5496 } -5497 } -5498 -5499 let space = self.spaces[SpaceId::Data].for_path(path_id); -5500 if space -5501 .pending_acks -5502 .packet_received(now, number, ack_eliciting, &space.dedup) -5503 { -5504 if self.abandoned_paths.contains(&path_id) { -5505 // § 3.4.3 QUIC-MULTIPATH: promptly send ACKs for packets received from -5506 // abandoned paths. -5507 space.pending_acks.set_immediate_ack_required(); -5508 } else { -5509 self.timers.set( -5510 Timer::PerPath(path_id, PathTimer::MaxAckDelay), -5511 now + self.ack_frequency.max_ack_delay, -5512 self.qlog.with_time(now), -5513 ); -5514 } -5515 } -5516 -5517 // Issue stream ID credit due to ACKs of outgoing finish/resets and incoming finish/resets -5518 // on stopped streams. Incoming finishes/resets on open streams are not handled here as they -5519 // are only freed, and hence only issue credit, once the application has been notified -5520 // during a read on the stream. -5521 let pending = &mut self.spaces[SpaceId::Data].pending; -5522 self.streams.queue_max_stream_id(pending); -5523 -5524 if let Some(reason) = close { -5525 self.state.move_to_draining(Some(reason.into())); -5526 self.connection_close_pending = true; -5527 } -5528 -5529 // For Multipath any packet triggers migration. For RFC9000 or QNT (+ Multipath) -5530 // only non-probing packets trigger migration. -5531 let migrate_on_any_packet = -5532 self.is_multipath_negotiated() && !self.n0_nat_traversal.is_negotiated(); -5533 -5534 // Only migrate if this is the largest packet number seen. -5535 let is_largest_received_pn = Some(number) -5536 == self.spaces[SpaceId::Data] -5537 .for_path(path_id) -5538 .largest_received_packet_number; -5539 -5540 // If we receive a non-probing packet on a new local IP that means we had a NAT -5541 // rebinding-like migration. We update our local address but do not otherwise -5542 // validate the new path, we only need to validate the path if the peer migrates per -5543 // RFC9000 §9: https://www.rfc-editor.org/rfc/rfc9000.html#section-9-4 -5544 if (migrate_on_any_packet || !is_probing_packet) -5545 && is_largest_received_pn -5546 && self.local_ip_may_migrate() -5547 && let Some(new_local_ip) = network_path.local_ip -5548 { -5549 let path_data = self.path_data_mut(path_id); -5550 if path_data -5551 .network_path -5552 .local_ip -5553 .is_some_and(|ip| ip != new_local_ip) -5554 { -5555 debug!( -5556 %path_id, -5557 new_4tuple = %network_path, -5558 prev_4tuple = %path_data.network_path, -5559 "local address passive migration" -5560 ); -5561 } -5562 path_data.network_path.local_ip = Some(new_local_ip) -5563 } -5564 -5565 // If the peer migrated to a new address, trigger migration. -5566 if (migrate_on_any_packet || !is_probing_packet) -5567 && is_largest_received_pn -5568 && network_path.remote != self.path_data(path_id).network_path.remote -5569 && self.remote_may_migrate() -5570 { -5571 self.migrate(path_id, now, network_path, migration_observed_addr); -5572 // Break linkability, if possible -5573 self.update_remote_cid(path_id); -5574 self.spin = false; -5575 } -5576 -5577 Ok(()) -5578 } +5467 Frame::RemoveAddress(addr) => { +5468 let client_state = match self.n0_nat_traversal.client_side_mut() { +5469 Ok(state) => state, +5470 Err(err) => { +5471 return Err(TransportError::PROTOCOL_VIOLATION(format!( +5472 "Nat traversal(REMOVE_ADDRESS): {err}" +5473 ))); +5474 } +5475 }; +5476 if let Some(removed_addr) = client_state.remove_remote_address(addr) { +5477 self.events.push_back(Event::NatTraversal( +5478 n0_nat_traversal::Event::AddressRemoved(removed_addr), +5479 )); +5480 } +5481 } +5482 Frame::ReachOut(reach_out) => { +5483 let ipv6 = self.is_ipv6(); +5484 let server_state = match self.n0_nat_traversal.server_side_mut() { +5485 Ok(state) => state, +5486 Err(err) => { +5487 return Err(TransportError::PROTOCOL_VIOLATION(format!( +5488 "Nat traversal(REACH_OUT): {err}" +5489 ))); +5490 } +5491 }; +5492 +5493 let round_before = server_state.current_round(); +5494 +5495 if let Err(err) = server_state.handle_reach_out(reach_out, ipv6) { +5496 return Err(TransportError::PROTOCOL_VIOLATION(format!( +5497 "Nat traversal(REACH_OUT): {err}" +5498 ))); +5499 } +5500 +5501 if server_state.current_round() > round_before { +5502 // A new round was started, reset the NAT probe retry timer. +5503 let delay = RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; +5504 self.timers.set( +5505 Timer::Conn(ConnTimer::NatTraversalProbeRetry), +5506 now + delay, +5507 self.qlog.with_time(now), +5508 ); +5509 } +5510 } +5511 } +5512 } +5513 +5514 let space = self.spaces[SpaceId::Data].for_path(path_id); +5515 if space +5516 .pending_acks +5517 .packet_received(now, number, ack_eliciting, &space.dedup) +5518 { +5519 if self.abandoned_paths.contains(&path_id) { +5520 // § 3.4.3 QUIC-MULTIPATH: promptly send ACKs for packets received from +5521 // abandoned paths. +5522 space.pending_acks.set_immediate_ack_required(); +5523 } else { +5524 self.timers.set( +5525 Timer::PerPath(path_id, PathTimer::MaxAckDelay), +5526 now + self.ack_frequency.max_ack_delay, +5527 self.qlog.with_time(now), +5528 ); +5529 } +5530 } +5531 +5532 // Issue stream ID credit due to ACKs of outgoing finish/resets and incoming finish/resets +5533 // on stopped streams. Incoming finishes/resets on open streams are not handled here as they +5534 // are only freed, and hence only issue credit, once the application has been notified +5535 // during a read on the stream. +5536 let pending = &mut self.spaces[SpaceId::Data].pending; +5537 self.streams.queue_max_stream_id(pending); +5538 +5539 if let Some(reason) = close { +5540 self.state.move_to_draining(Some(reason.into())); +5541 self.connection_close_pending = true; +5542 } +5543 +5544 // For Multipath any packet triggers migration. For RFC9000 or QNT (+ Multipath) +5545 // only non-probing packets trigger migration. +5546 let migrate_on_any_packet = +5547 self.is_multipath_negotiated() && !self.n0_nat_traversal.is_negotiated(); +5548 +5549 // Only migrate if this is the largest packet number seen. +5550 let is_largest_received_pn = Some(number) +5551 == self.spaces[SpaceId::Data] +5552 .for_path(path_id) +5553 .largest_received_packet_number; +5554 +5555 // If we receive a non-probing packet on a new local IP that means we had a NAT +5556 // rebinding-like migration. We update our local address but do not otherwise +5557 // validate the new path, we only need to validate the path if the peer migrates per +5558 // RFC9000 §9: https://www.rfc-editor.org/rfc/rfc9000.html#section-9-4 +5559 if (migrate_on_any_packet || !is_probing_packet) +5560 && is_largest_received_pn +5561 && self.local_ip_may_migrate() +5562 && let Some(new_local_ip) = network_path.local_ip +5563 { +5564 let path_data = self.path_data_mut(path_id); +5565 if path_data +5566 .network_path +5567 .local_ip +5568 .is_some_and(|ip| ip != new_local_ip) +5569 { +5570 debug!( +5571 %path_id, +5572 new_4tuple = %network_path, +5573 prev_4tuple = %path_data.network_path, +5574 "local address passive migration" +5575 ); +5576 } +5577 path_data.network_path.local_ip = Some(new_local_ip) +5578 } 5579 -5580 /// Opens any paths that have been successfully NAT traversed. -5581 fn open_nat_traversed_paths(&mut self, now: Instant) { -5582 while let Some(network_path) = self -5583 .n0_nat_traversal -5584 .client_side_mut() -5585 .ok() -5586 .and_then(|s| s.pop_pending_path_open()) -5587 { -5588 match self.open_path_ensure(network_path, PathStatus::Backup, now) { -5589 Ok((path_id, already_existed)) => { -5590 debug!( -5591 %path_id, -5592 ?network_path, -5593 new_path = !already_existed, -5594 "Opened NAT traversal path", -5595 ); -5596 } -5597 Err(err) => match err { -5598 PathError::MultipathNotNegotiated -5599 | PathError::ServerSideNotAllowed -5600 | PathError::ValidationFailed -5601 | PathError::InvalidRemoteAddress(_) => { -5602 error!( -5603 ?err, -5604 ?network_path, -5605 "Failed to open path for successful NAT traversal" -5606 ); -5607 } -5608 PathError::MaxPathIdReached | PathError::RemoteCidsExhausted => { -5609 // Temporary error, put back. -5610 self.n0_nat_traversal -5611 .client_side_mut() -5612 .map(|s| s.push_pending_path_open(network_path)) -5613 .ok(); -5614 debug!( -5615 ?err, -5616 ?network_path, -5617 "Blocked opening NAT traversal path, enqueued" -5618 ); -5619 return; -5620 } -5621 }, -5622 } -5623 } -5624 } -5625 -5626 /// Migrates the 4-tuple of the path. -5627 /// -5628 /// This creates a new [`PathData`] for the migrated path and stores the previous -5629 /// [`PathData`] in [`PathState::prev`]. -5630 fn migrate( -5631 &mut self, -5632 path_id: PathId, -5633 now: Instant, -5634 network_path: FourTuple, -5635 observed_addr: Option<ObservedAddr>, -5636 ) { -5637 trace!( -5638 new_4tuple = %network_path, -5639 prev_4tuple = %self.path_data(path_id).network_path, -5640 %path_id, -5641 "migration initiated", -5642 ); -5643 self.path_generation_counter = self.path_generation_counter.wrapping_add(1); -5644 // TODO(@divma): conditions for path migration in multipath are very specific, check them -5645 // again to prevent path migrations that should actually create a new path -5646 -5647 // Reset rtt/congestion state for new path unless it looks like a NAT rebinding. -5648 // Note that the congestion window will not grow until validation terminates. Helps mitigate -5649 // amplification attacks performed by spoofing source addresses. -5650 let prev_pto = self.pto(SpaceKind::Data, path_id); -5651 let path = self.paths.get_mut(&path_id).expect("known path"); -5652 let mut new_path_data = if network_path.remote.is_ipv4() -5653 && network_path.remote.ip() == path.data.network_path.remote.ip() -5654 { -5655 PathData::from_previous(network_path, &path.data, self.path_generation_counter, now) -5656 } else { -5657 let peer_max_udp_payload_size = -5658 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()) -5659 .unwrap_or(u16::MAX); -5660 PathData::new( -5661 network_path, -5662 self.allow_mtud, -5663 Some(peer_max_udp_payload_size), -5664 self.path_generation_counter, -5665 now, -5666 &self.config, -5667 ) -5668 }; -5669 new_path_data.last_observed_addr_report = path.data.last_observed_addr_report.clone(); -5670 if let Some(report) = observed_addr -5671 && let Some(updated) = new_path_data.update_observed_addr_report(report) -5672 { -5673 tracing::info!("adding observed addr event from migration"); -5674 self.events.push_back(Event::Path(PathEvent::ObservedAddr { -5675 id: path_id, -5676 addr: updated, -5677 })); -5678 } -5679 new_path_data.pending_on_path_challenge = true; -5680 -5681 let mut prev_path_data = mem::replace(&mut path.data, new_path_data); -5682 -5683 // Only store this as previous path if it was validated. For all we know there could -5684 // already be a previous path stored which might have been validated in the past, -5685 // which is more valuable than one that's not yet validated. -5686 // -5687 // With multipath it is possible that there are no remote CIDs for the path ID -5688 // yet. In this case we would never have sent on this path yet and would not be able -5689 // to send a PATH_CHALLENGE either, which is currently a fire-and-forget affair -5690 // anyway. So don't store such a path either. -5691 if !prev_path_data.validated -5692 && let Some(cid) = self.remote_cids.get(&path_id).map(CidQueue::active) -5693 { -5694 prev_path_data.pending_on_path_challenge = true; -5695 // We haven't updated the remote CID yet, this captures the remote CID we were using on -5696 // the previous path. -5697 path.prev = Some((cid, prev_path_data)); -5698 } -5699 -5700 // We need to re-assign the correct remote to this path in qlog -5701 self.qlog.emit_tuple_assigned(path_id, network_path, now); -5702 -5703 self.timers.set( -5704 Timer::PerPath(path_id, PathTimer::PathValidationFailed), -5705 now + 3 * cmp::max(self.pto(SpaceKind::Data, path_id), prev_pto), -5706 self.qlog.with_time(now), -5707 ); -5708 } -5709 -5710 /// Handle a change in the local address, i.e. an active migration -5711 /// -5712 /// In the general (non-multipath) case, paths will perform a RFC9000 migration and be pinged -5713 /// for a liveness check. This is the behaviour of a path assumed to be recoverable, even if -5714 /// this is not the case. -5715 /// -5716 /// Clients in a connection in which multipath has been negotiated should migrate paths to new -5717 /// [`PathId`]s. For paths that are known to be non-recoverable can be migrated to a new -5718 /// [`PathId`] by closing the current path, and opening a new one to the same remote. Treating -5719 /// paths as non recoverable when necessary accelerates connectivity re-establishment, or might -5720 /// allow it altogether. -5721 /// -5722 /// The optional `hint` allows callers to indicate when paths are non-recoverable and should be -5723 /// migrated to new a [`PathId`]. -5724 // NOTE: only clients are allowed to migrate, but generally dealing with RFC9000 migrations is -5725 // lacking <https://github.com/n0-computer/noq/issues/364> -5726 pub fn handle_network_change(&mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant) { -5727 debug!("network changed"); -5728 if self.state.is_drained() { -5729 return; -5730 } -5731 if self.highest_space < SpaceKind::Data { -5732 for path in self.paths.values_mut() { -5733 // Clear the local address for it to be obtained from the socket again. -5734 path.data.network_path.local_ip = None; -5735 } -5736 -5737 self.update_remote_cid(PathId::ZERO); -5738 self.ping(); -5739 -5740 return; -5741 } -5742 -5743 // Paths that can't recover so a new path should be open instead. If multipath is not -5744 // negotiated, this will be empty. -5745 let mut non_recoverable_paths = Vec::default(); -5746 let mut recoverable_paths = Vec::default(); -5747 let mut open_paths = 0; -5748 -5749 let is_multipath_negotiated = self.is_multipath_negotiated(); -5750 let is_client = self.side().is_client(); -5751 let immediate_ack_allowed = self.peer_supports_ack_frequency(); -5752 -5753 for (path_id, path) in self.paths.iter_mut() { -5754 if self.abandoned_paths.contains(path_id) { -5755 continue; -5756 } -5757 open_paths += 1; -5758 -5759 // Read the network path BEFORE clearing local_ip, so the hint can -5760 // check which interface the path was using. -5761 let network_path = path.data.network_path; -5762 -5763 // Clear the local address for it to be obtained from the socket again. This applies to -5764 // all paths, regardless of being considered recoverable or not -5765 path.data.network_path.local_ip = None; -5766 let remote = network_path.remote; +5580 // If the peer migrated to a new address, trigger migration. +5581 if (migrate_on_any_packet || !is_probing_packet) +5582 && is_largest_received_pn +5583 && network_path.remote != self.path_data(path_id).network_path.remote +5584 && self.remote_may_migrate() +5585 { +5586 self.migrate(path_id, now, network_path, migration_observed_addr); +5587 // Break linkability, if possible +5588 self.update_remote_cid(path_id); +5589 self.spin = false; +5590 } +5591 +5592 Ok(()) +5593 } +5594 +5595 /// Opens any paths that have been successfully NAT traversed. +5596 fn open_nat_traversed_paths(&mut self, now: Instant) { +5597 while let Some(network_path) = self +5598 .n0_nat_traversal +5599 .client_side_mut() +5600 .ok() +5601 .and_then(|s| s.pop_pending_path_open()) +5602 { +5603 match self.open_path_ensure(network_path, PathStatus::Backup, now) { +5604 Ok((path_id, already_existed)) => { +5605 debug!( +5606 %path_id, +5607 ?network_path, +5608 new_path = !already_existed, +5609 "Opened NAT traversal path", +5610 ); +5611 } +5612 Err(err) => match err { +5613 PathError::MultipathNotNegotiated +5614 | PathError::ServerSideNotAllowed +5615 | PathError::ValidationFailed +5616 | PathError::InvalidRemoteAddress(_) => { +5617 error!( +5618 ?err, +5619 ?network_path, +5620 "Failed to open path for successful NAT traversal" +5621 ); +5622 } +5623 PathError::MaxPathIdReached | PathError::RemoteCidsExhausted => { +5624 // Temporary error, put back. +5625 self.n0_nat_traversal +5626 .client_side_mut() +5627 .map(|s| s.push_pending_path_open(network_path)) +5628 .ok(); +5629 debug!( +5630 ?err, +5631 ?network_path, +5632 "Blocked opening NAT traversal path, enqueued" +5633 ); +5634 return; +5635 } +5636 }, +5637 } +5638 } +5639 } +5640 +5641 /// Migrates the 4-tuple of the path. +5642 /// +5643 /// This creates a new [`PathData`] for the migrated path and stores the previous +5644 /// [`PathData`] in [`PathState::prev`]. +5645 fn migrate( +5646 &mut self, +5647 path_id: PathId, +5648 now: Instant, +5649 network_path: FourTuple, +5650 observed_addr: Option<ObservedAddr>, +5651 ) { +5652 trace!( +5653 new_4tuple = %network_path, +5654 prev_4tuple = %self.path_data(path_id).network_path, +5655 %path_id, +5656 "migration initiated", +5657 ); +5658 self.path_generation_counter = self.path_generation_counter.wrapping_add(1); +5659 // TODO(@divma): conditions for path migration in multipath are very specific, check them +5660 // again to prevent path migrations that should actually create a new path +5661 +5662 // Reset rtt/congestion state for new path unless it looks like a NAT rebinding. +5663 // Note that the congestion window will not grow until validation terminates. Helps mitigate +5664 // amplification attacks performed by spoofing source addresses. +5665 let prev_pto = self.pto(SpaceKind::Data, path_id); +5666 let path = self.paths.get_mut(&path_id).expect("known path"); +5667 let mut new_path_data = if network_path.remote.is_ipv4() +5668 && network_path.remote.ip() == path.data.network_path.remote.ip() +5669 { +5670 PathData::from_previous(network_path, &path.data, self.path_generation_counter, now) +5671 } else { +5672 let peer_max_udp_payload_size = +5673 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()) +5674 .unwrap_or(u16::MAX); +5675 PathData::new( +5676 network_path, +5677 self.allow_mtud, +5678 Some(peer_max_udp_payload_size), +5679 self.path_generation_counter, +5680 now, +5681 &self.config, +5682 ) +5683 }; +5684 new_path_data.last_observed_addr_report = path.data.last_observed_addr_report.clone(); +5685 if let Some(report) = observed_addr +5686 && let Some(updated) = new_path_data.update_observed_addr_report(report) +5687 { +5688 tracing::info!("adding observed addr event from migration"); +5689 self.events.push_back(Event::Path(PathEvent::ObservedAddr { +5690 id: path_id, +5691 addr: updated, +5692 })); +5693 } +5694 new_path_data.pending_on_path_challenge = true; +5695 +5696 let mut prev_path_data = mem::replace(&mut path.data, new_path_data); +5697 +5698 // Only store this as previous path if it was validated. For all we know there could +5699 // already be a previous path stored which might have been validated in the past, +5700 // which is more valuable than one that's not yet validated. +5701 // +5702 // With multipath it is possible that there are no remote CIDs for the path ID +5703 // yet. In this case we would never have sent on this path yet and would not be able +5704 // to send a PATH_CHALLENGE either, which is currently a fire-and-forget affair +5705 // anyway. So don't store such a path either. +5706 if !prev_path_data.validated +5707 && let Some(cid) = self.remote_cids.get(&path_id).map(CidQueue::active) +5708 { +5709 prev_path_data.pending_on_path_challenge = true; +5710 // We haven't updated the remote CID yet, this captures the remote CID we were using on +5711 // the previous path. +5712 path.prev = Some((cid, prev_path_data)); +5713 } +5714 +5715 // We need to re-assign the correct remote to this path in qlog +5716 self.qlog.emit_tuple_assigned(path_id, network_path, now); +5717 +5718 self.timers.set( +5719 Timer::PerPath(path_id, PathTimer::PathValidationFailed), +5720 now + 3 * cmp::max(self.pto(SpaceKind::Data, path_id), prev_pto), +5721 self.qlog.with_time(now), +5722 ); +5723 } +5724 +5725 /// Handle a change in the local address, i.e. an active migration +5726 /// +5727 /// In the general (non-multipath) case, paths will perform a RFC9000 migration and be pinged +5728 /// for a liveness check. This is the behaviour of a path assumed to be recoverable, even if +5729 /// this is not the case. +5730 /// +5731 /// Clients in a connection in which multipath has been negotiated should migrate paths to new +5732 /// [`PathId`]s. For paths that are known to be non-recoverable can be migrated to a new +5733 /// [`PathId`] by closing the current path, and opening a new one to the same remote. Treating +5734 /// paths as non recoverable when necessary accelerates connectivity re-establishment, or might +5735 /// allow it altogether. +5736 /// +5737 /// The optional `hint` allows callers to indicate when paths are non-recoverable and should be +5738 /// migrated to new a [`PathId`]. +5739 // NOTE: only clients are allowed to migrate, but generally dealing with RFC9000 migrations is +5740 // lacking <https://github.com/n0-computer/noq/issues/364> +5741 pub fn handle_network_change(&mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant) { +5742 debug!("network changed"); +5743 if self.state.is_drained() { +5744 return; +5745 } +5746 if self.highest_space < SpaceKind::Data { +5747 for path in self.paths.values_mut() { +5748 // Clear the local address for it to be obtained from the socket again. +5749 path.data.network_path.local_ip = None; +5750 } +5751 +5752 self.update_remote_cid(PathId::ZERO); +5753 self.ping(); +5754 +5755 return; +5756 } +5757 +5758 // Paths that can't recover so a new path should be open instead. If multipath is not +5759 // negotiated, this will be empty. +5760 let mut non_recoverable_paths = Vec::default(); +5761 let mut recoverable_paths = Vec::default(); +5762 let mut open_paths = 0; +5763 +5764 let is_multipath_negotiated = self.is_multipath_negotiated(); +5765 let is_client = self.side().is_client(); +5766 let immediate_ack_allowed = self.peer_supports_ack_frequency(); 5767 -5768 // Without multipath, the connection tries to recover the single path, whereas with -5769 // multipath, even in a single-path scenario, we attempt to migrate the path to a new -5770 // PathId. -5771 let attempt_to_recover = if is_multipath_negotiated { -5772 // Use the hint to determine if the path can recover. When no hint is -5773 // provided, clients default to non-recoverable (abandon and re-open) -5774 // while servers default to recoverable (attempt in-place recovery). -5775 hint.map(|h| h.is_path_recoverable(*path_id, network_path)) -5776 .unwrap_or(!is_client) -5777 } else { -5778 // In the non multipath case, we try to recover the single active path -5779 true -5780 }; -5781 -5782 if attempt_to_recover { -5783 recoverable_paths.push((*path_id, remote)); -5784 } else { -5785 non_recoverable_paths.push((*path_id, remote, path.data.local_status())) -5786 } -5787 } -5788 -5789 /* NON RECOVERABLE PATHS */ -5790 // This are handled first, so that in case the treatment intended for these fails, we can -5791 // go the recoverable route instead. -5792 -5793 // Decide if we need to close first or open first in the multipath case. -5794 // - Opening first has a higher risk of getting limited by the negotiated MAX_PATH_ID. -5795 // - Closing first risks this being the only open path. -5796 // We prefer closing paths first unless we identify this is the last open path. -5797 let open_first = open_paths == non_recoverable_paths.len(); -5798 -5799 for (path_id, remote, status) in non_recoverable_paths.into_iter() { -5800 let network_path = FourTuple { -5801 remote, -5802 local_ip: None, /* allow the local ip to be discovered */ -5803 }; -5804 -5805 if open_first && let Err(e) = self.open_path(network_path, status, now) { -5806 if self.side().is_client() { -5807 debug!(%e, "Failed to open new path for network change"); -5808 } -5809 // if this fails, let the path try to recover itself -5810 recoverable_paths.push((path_id, remote)); -5811 continue; -5812 } +5768 for (path_id, path) in self.paths.iter_mut() { +5769 if self.abandoned_paths.contains(path_id) { +5770 continue; +5771 } +5772 open_paths += 1; +5773 +5774 // Read the network path BEFORE clearing local_ip, so the hint can +5775 // check which interface the path was using. +5776 let network_path = path.data.network_path; +5777 +5778 // Clear the local address for it to be obtained from the socket again. This applies to +5779 // all paths, regardless of being considered recoverable or not +5780 path.data.network_path.local_ip = None; +5781 let remote = network_path.remote; +5782 +5783 // Without multipath, the connection tries to recover the single path, whereas with +5784 // multipath, even in a single-path scenario, we attempt to migrate the path to a new +5785 // PathId. +5786 let attempt_to_recover = if is_multipath_negotiated { +5787 // Use the hint to determine if the path can recover. When no hint is +5788 // provided, clients default to non-recoverable (abandon and re-open) +5789 // while servers default to recoverable (attempt in-place recovery). +5790 hint.map(|h| h.is_path_recoverable(*path_id, network_path)) +5791 .unwrap_or(!is_client) +5792 } else { +5793 // In the non multipath case, we try to recover the single active path +5794 true +5795 }; +5796 +5797 if attempt_to_recover { +5798 recoverable_paths.push((*path_id, remote)); +5799 } else { +5800 non_recoverable_paths.push((*path_id, remote, path.data.local_status())) +5801 } +5802 } +5803 +5804 /* NON RECOVERABLE PATHS */ +5805 // This are handled first, so that in case the treatment intended for these fails, we can +5806 // go the recoverable route instead. +5807 +5808 // Decide if we need to close first or open first in the multipath case. +5809 // - Opening first has a higher risk of getting limited by the negotiated MAX_PATH_ID. +5810 // - Closing first risks this being the only open path. +5811 // We prefer closing paths first unless we identify this is the last open path. +5812 let open_first = open_paths == non_recoverable_paths.len(); 5813 -5814 if let Err(e) = -5815 self.close_path_inner(now, path_id, PathAbandonReason::UnusableAfterNetworkChange) -5816 { -5817 debug!(%e,"Failed to close unrecoverable path after network change"); -5818 recoverable_paths.push((path_id, remote)); -5819 continue; -5820 } -5821 -5822 if !open_first && let Err(e) = self.open_path(network_path, status, now) { -5823 // Path has already been closed if we got here. Since the path was not recoverable, -5824 // this might be desirable in any case, because other paths exist (!open_first) and -5825 // this was is considered non recoverable -5826 debug!(%e,"Failed to open new path for network change"); +5814 for (path_id, remote, status) in non_recoverable_paths.into_iter() { +5815 let network_path = FourTuple { +5816 remote, +5817 local_ip: None, /* allow the local ip to be discovered */ +5818 }; +5819 +5820 if open_first && let Err(e) = self.open_path(network_path, status, now) { +5821 if self.side().is_client() { +5822 debug!(%e, "Failed to open new path for network change"); +5823 } +5824 // if this fails, let the path try to recover itself +5825 recoverable_paths.push((path_id, remote)); +5826 continue; 5827 } -5828 } -5829 -5830 /* RECOVERABLE PATHS */ -5831 -5832 for (path_id, remote) in recoverable_paths.into_iter() { -5833 // Schedule a Ping for a liveness check. -5834 if let Some(path_space) = self.spaces[SpaceId::Data].number_spaces.get_mut(&path_id) { -5835 path_space.ping_pending = true; +5828 +5829 if let Err(e) = +5830 self.close_path_inner(now, path_id, PathAbandonReason::UnusableAfterNetworkChange) +5831 { +5832 debug!(%e,"Failed to close unrecoverable path after network change"); +5833 recoverable_paths.push((path_id, remote)); +5834 continue; +5835 } 5836 -5837 if immediate_ack_allowed { -5838 path_space.immediate_ack_pending = true; -5839 } -5840 } -5841 -5842 // Reset PTO backoff so retransmits resume promptly. Congestion controller and -5843 // RTT are intentionally preserved for recoverable paths. We explicitly allow -5844 // this reset also during the handshake, so do not check -5845 // Self::peer_competed_handshake_address_validation. -5846 if let Some(path) = self.paths.get_mut(&path_id) { -5847 path.data.pto_count = 0; -5848 } -5849 self.set_loss_detection_timer(now, path_id); -5850 -5851 let Some((reset_token, retired)) = -5852 self.remote_cids.get_mut(&path_id).and_then(CidQueue::next) -5853 else { -5854 continue; -5855 }; +5837 if !open_first && let Err(e) = self.open_path(network_path, status, now) { +5838 // Path has already been closed if we got here. Since the path was not recoverable, +5839 // this might be desirable in any case, because other paths exist (!open_first) and +5840 // this was is considered non recoverable +5841 debug!(%e,"Failed to open new path for network change"); +5842 } +5843 } +5844 +5845 /* RECOVERABLE PATHS */ +5846 +5847 for (path_id, remote) in recoverable_paths.into_iter() { +5848 // Schedule a Ping for a liveness check. +5849 if let Some(path_space) = self.spaces[SpaceId::Data].number_spaces.get_mut(&path_id) { +5850 path_space.ping_pending = true; +5851 +5852 if immediate_ack_allowed { +5853 path_space.immediate_ack_pending = true; +5854 } +5855 } 5856 -5857 // Retire the current remote CID and any CIDs we had to skip. -5858 self.spaces[SpaceId::Data] -5859 .pending -5860 .retire_cids -5861 .extend(retired.map(|seq| (path_id, seq))); -5862 -5863 debug_assert!(!self.state.is_drained()); // required for endpoint_events, checked above -5864 self.endpoint_events -5865 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); -5866 } -5867 } -5868 -5869 /// Switch to a previously unused remote connection ID, if possible -5870 fn update_remote_cid(&mut self, path_id: PathId) { -5871 let Some((reset_token, retired)) = self -5872 .remote_cids -5873 .get_mut(&path_id) -5874 .and_then(|cids| cids.next()) -5875 else { -5876 return; -5877 }; -5878 -5879 // Retire the current remote CID and any CIDs we had to skip. -5880 self.spaces[SpaceId::Data] -5881 .pending -5882 .retire_cids -5883 .extend(retired.map(|seq| (path_id, seq))); -5884 let remote = self.path_data(path_id).network_path.remote; -5885 self.set_reset_token(path_id, remote, reset_token); -5886 } -5887 -5888 /// Sends this reset token to the endpoint -5889 /// -5890 /// The endpoint needs to know the reset tokens issued by the peer, so that if the peer -5891 /// sends a reset token it knows to route it to this connection. See RFC 9000 section -5892 /// 10.3. Stateless Reset. -5893 /// -5894 /// Reset tokens are different for each path, the endpoint identifies paths by peer -5895 /// socket address however, not by path ID. -5896 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) { -5897 debug_assert!(!self.state.is_drained()); // required for endpoint events, set_reset_token is never called for drained connections -5898 self.endpoint_events -5899 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); -5900 -5901 // During the handshake the server sends a reset token in the transport -5902 // parameters. When we are the client and we receive the reset token during the -5903 // handshake we want this to affect our peer transport parameters. -5904 // TODO(flub): Pretty sure this is pointless, the entire params is overwritten -5905 // shortly after this was called. And then the params don't have this anymore. -5906 if path_id == PathId::ZERO { -5907 self.peer_params.stateless_reset_token = Some(reset_token); -5908 } -5909 } -5910 -5911 /// Issue an initial set of connection IDs to the peer upon connection -5912 fn issue_first_cids(&mut self, now: Instant) { -5913 if self -5914 .local_cid_state -5915 .get(&PathId::ZERO) -5916 .expect("PathId::ZERO exists when the connection is created") -5917 .cid_len() -5918 == 0 -5919 { -5920 return; -5921 } -5922 -5923 // Subtract 1 to account for the CID we supplied while handshaking -5924 let mut n = self.peer_params.issue_cids_limit() - 1; -5925 if let ConnectionSide::Server { server_config } = &self.side -5926 && server_config.has_preferred_address() -5927 { -5928 // We also sent a CID in the transport parameters -5929 n -= 1; -5930 } -5931 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events -5932 self.endpoint_events -5933 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); -5934 } -5935 -5936 /// Issues an initial set of CIDs for paths that have not yet had any CIDs issued -5937 /// -5938 /// Later CIDs are issued when CIDs expire or are retired by the peer. -5939 fn issue_first_path_cids(&mut self, now: Instant) { -5940 if let Some(max_path_id) = self.max_path_id() { -5941 let mut path_id = self.max_path_id_with_cids.next(); -5942 while path_id <= max_path_id { -5943 self.endpoint_events -5944 .push_back(EndpointEventInner::NeedIdentifiers( -5945 path_id, -5946 now, -5947 self.peer_params.issue_cids_limit(), -5948 )); -5949 path_id = path_id.next(); -5950 } -5951 self.max_path_id_with_cids = max_path_id; -5952 } -5953 } -5954 -5955 /// Populates a packet with frames -5956 /// -5957 /// This tries to fit as many frames as possible into the packet. -5958 /// -5959 /// *path_exclusive_only* means to only build frames which can only be sent on this -5960 /// *path. This is used in multipath for backup paths while there is still an active -5961 /// *path. -5962 fn populate_packet<'a, 'b>( -5963 &mut self, -5964 now: Instant, -5965 space_id: SpaceId, -5966 path_id: PathId, -5967 scheduling_info: &PathSchedulingInfo, -5968 builder: &mut PacketBuilder<'a, 'b>, -5969 ) { -5970 let is_multipath_negotiated = self.is_multipath_negotiated(); -5971 let space_has_keys = self.crypto_state.has_keys(space_id.encryption_level()); -5972 let is_0rtt = space_id == SpaceId::Data && !space_has_keys; -5973 let stats = &mut self.path_stats.for_path(path_id).frame_tx; -5974 let space = &mut self.spaces[space_id]; -5975 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; -5976 space -5977 .for_path(path_id) -5978 .pending_acks -5979 .maybe_ack_non_eliciting(); -5980 -5981 // HANDSHAKE_DONE -5982 if !is_0rtt -5983 && !scheduling_info.is_abandoned -5984 && scheduling_info.may_send_data -5985 && mem::replace(&mut space.pending.handshake_done, false) -5986 { -5987 builder.write_frame(frame::HandshakeDone, stats); -5988 } -5989 -5990 // PING -5991 if !scheduling_info.is_abandoned -5992 && mem::replace(&mut space.for_path(path_id).ping_pending, false) -5993 { -5994 builder.write_frame(frame::Ping, stats); -5995 } -5996 -5997 // IMMEDIATE_ACK -5998 if !scheduling_info.is_abandoned -5999 && mem::replace(&mut space.for_path(path_id).immediate_ack_pending, false) -6000 { -6001 debug_assert_eq!( -6002 space_id, -6003 SpaceId::Data, -6004 "immediate acks must be sent in the data space" -6005 ); -6006 builder.write_frame(frame::ImmediateAck, stats); -6007 } -6008 -6009 // ACK -6010 if !scheduling_info.is_abandoned && scheduling_info.may_send_data { -6011 for path_id in space -6012 .number_spaces -6013 .iter_mut() -6014 .filter(|(_, pns)| pns.pending_acks.can_send()) -6015 .map(|(&path_id, _)| path_id) -6016 .collect::<Vec<_>>() -6017 { -6018 Self::populate_acks( -6019 now, -6020 self.receiving_ecn, -6021 path_id, -6022 space_id, -6023 space, -6024 is_multipath_negotiated, -6025 builder, -6026 stats, -6027 space_has_keys, -6028 ); -6029 } -6030 } -6031 -6032 // ACK_FREQUENCY -6033 if !scheduling_info.is_abandoned -6034 && scheduling_info.may_send_data -6035 && mem::replace(&mut space.pending.ack_frequency, false) -6036 { -6037 let sequence_number = self.ack_frequency.next_sequence_number(); -6038 -6039 // Safe to unwrap because this is always provided when ACK frequency is enabled -6040 let config = self.config.ack_frequency_config.as_ref().unwrap(); -6041 -6042 // Ensure the delay is within bounds to avoid a PROTOCOL_VIOLATION error -6043 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay( -6044 path.rtt.get(), -6045 config, -6046 &self.peer_params, -6047 ); -6048 -6049 let frame = frame::AckFrequency { -6050 sequence: sequence_number, -6051 ack_eliciting_threshold: config.ack_eliciting_threshold, -6052 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX), -6053 reordering_threshold: config.reordering_threshold, -6054 }; -6055 builder.write_frame(frame, stats); +5857 // Reset PTO backoff so retransmits resume promptly. Congestion controller and +5858 // RTT are intentionally preserved for recoverable paths. We explicitly allow +5859 // this reset also during the handshake, so do not check +5860 // Self::peer_competed_handshake_address_validation. +5861 if let Some(path) = self.paths.get_mut(&path_id) { +5862 path.data.pto_count = 0; +5863 } +5864 self.set_loss_detection_timer(now, path_id); +5865 +5866 let Some((reset_token, retired)) = +5867 self.remote_cids.get_mut(&path_id).and_then(CidQueue::next) +5868 else { +5869 continue; +5870 }; +5871 +5872 // Retire the current remote CID and any CIDs we had to skip. +5873 self.spaces[SpaceId::Data] +5874 .pending +5875 .retire_cids +5876 .extend(retired.map(|seq| (path_id, seq))); +5877 +5878 debug_assert!(!self.state.is_drained()); // required for endpoint_events, checked above +5879 self.endpoint_events +5880 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); +5881 } +5882 } +5883 +5884 /// Switch to a previously unused remote connection ID, if possible +5885 fn update_remote_cid(&mut self, path_id: PathId) { +5886 let Some((reset_token, retired)) = self +5887 .remote_cids +5888 .get_mut(&path_id) +5889 .and_then(|cids| cids.next()) +5890 else { +5891 return; +5892 }; +5893 +5894 // Retire the current remote CID and any CIDs we had to skip. +5895 self.spaces[SpaceId::Data] +5896 .pending +5897 .retire_cids +5898 .extend(retired.map(|seq| (path_id, seq))); +5899 let remote = self.path_data(path_id).network_path.remote; +5900 self.set_reset_token(path_id, remote, reset_token); +5901 } +5902 +5903 /// Sends this reset token to the endpoint +5904 /// +5905 /// The endpoint needs to know the reset tokens issued by the peer, so that if the peer +5906 /// sends a reset token it knows to route it to this connection. See RFC 9000 section +5907 /// 10.3. Stateless Reset. +5908 /// +5909 /// Reset tokens are different for each path, the endpoint identifies paths by peer +5910 /// socket address however, not by path ID. +5911 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) { +5912 debug_assert!(!self.state.is_drained()); // required for endpoint events, set_reset_token is never called for drained connections +5913 self.endpoint_events +5914 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); +5915 +5916 // During the handshake the server sends a reset token in the transport +5917 // parameters. When we are the client and we receive the reset token during the +5918 // handshake we want this to affect our peer transport parameters. +5919 // TODO(flub): Pretty sure this is pointless, the entire params is overwritten +5920 // shortly after this was called. And then the params don't have this anymore. +5921 if path_id == PathId::ZERO { +5922 self.peer_params.stateless_reset_token = Some(reset_token); +5923 } +5924 } +5925 +5926 /// Issue an initial set of connection IDs to the peer upon connection +5927 fn issue_first_cids(&mut self, now: Instant) { +5928 if self +5929 .local_cid_state +5930 .get(&PathId::ZERO) +5931 .expect("PathId::ZERO exists when the connection is created") +5932 .cid_len() +5933 == 0 +5934 { +5935 return; +5936 } +5937 +5938 // Subtract 1 to account for the CID we supplied while handshaking +5939 let mut n = self.peer_params.issue_cids_limit() - 1; +5940 if let ConnectionSide::Server { server_config } = &self.side +5941 && server_config.has_preferred_address() +5942 { +5943 // We also sent a CID in the transport parameters +5944 n -= 1; +5945 } +5946 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events +5947 self.endpoint_events +5948 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); +5949 } +5950 +5951 /// Issues an initial set of CIDs for paths that have not yet had any CIDs issued +5952 /// +5953 /// Later CIDs are issued when CIDs expire or are retired by the peer. +5954 fn issue_first_path_cids(&mut self, now: Instant) { +5955 if let Some(max_path_id) = self.max_path_id() { +5956 let mut path_id = self.max_path_id_with_cids.next(); +5957 while path_id <= max_path_id { +5958 self.endpoint_events +5959 .push_back(EndpointEventInner::NeedIdentifiers( +5960 path_id, +5961 now, +5962 self.peer_params.issue_cids_limit(), +5963 )); +5964 path_id = path_id.next(); +5965 } +5966 self.max_path_id_with_cids = max_path_id; +5967 } +5968 } +5969 +5970 /// Populates a packet with frames +5971 /// +5972 /// This tries to fit as many frames as possible into the packet. +5973 /// +5974 /// *path_exclusive_only* means to only build frames which can only be sent on this +5975 /// *path. This is used in multipath for backup paths while there is still an active +5976 /// *path. +5977 fn populate_packet<'a, 'b>( +5978 &mut self, +5979 now: Instant, +5980 space_id: SpaceId, +5981 path_id: PathId, +5982 scheduling_info: &PathSchedulingInfo, +5983 builder: &mut PacketBuilder<'a, 'b>, +5984 ) { +5985 let is_multipath_negotiated = self.is_multipath_negotiated(); +5986 let space_has_keys = self.crypto_state.has_keys(space_id.encryption_level()); +5987 let is_0rtt = space_id == SpaceId::Data && !space_has_keys; +5988 let stats = &mut self.path_stats.for_path(path_id).frame_tx; +5989 let space = &mut self.spaces[space_id]; +5990 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; +5991 space +5992 .for_path(path_id) +5993 .pending_acks +5994 .maybe_ack_non_eliciting(); +5995 +5996 // HANDSHAKE_DONE +5997 if !is_0rtt +5998 && !scheduling_info.is_abandoned +5999 && scheduling_info.may_send_data +6000 && mem::replace(&mut space.pending.handshake_done, false) +6001 { +6002 builder.write_frame(frame::HandshakeDone, stats); +6003 } +6004 +6005 // PING +6006 if !scheduling_info.is_abandoned +6007 && mem::replace(&mut space.for_path(path_id).ping_pending, false) +6008 { +6009 builder.write_frame(frame::Ping, stats); +6010 } +6011 +6012 // IMMEDIATE_ACK +6013 if !scheduling_info.is_abandoned +6014 && mem::replace(&mut space.for_path(path_id).immediate_ack_pending, false) +6015 { +6016 debug_assert_eq!( +6017 space_id, +6018 SpaceId::Data, +6019 "immediate acks must be sent in the data space" +6020 ); +6021 builder.write_frame(frame::ImmediateAck, stats); +6022 } +6023 +6024 // ACK +6025 if !scheduling_info.is_abandoned && scheduling_info.may_send_data { +6026 for path_id in space +6027 .number_spaces +6028 .iter_mut() +6029 .filter(|(_, pns)| pns.pending_acks.can_send()) +6030 .map(|(&path_id, _)| path_id) +6031 .collect::<Vec<_>>() +6032 { +6033 Self::populate_acks( +6034 now, +6035 self.receiving_ecn, +6036 path_id, +6037 space_id, +6038 space, +6039 is_multipath_negotiated, +6040 builder, +6041 stats, +6042 space_has_keys, +6043 ); +6044 } +6045 } +6046 +6047 // ACK_FREQUENCY +6048 if !scheduling_info.is_abandoned +6049 && scheduling_info.may_send_data +6050 && mem::replace(&mut space.pending.ack_frequency, false) +6051 { +6052 let sequence_number = self.ack_frequency.next_sequence_number(); +6053 +6054 // Safe to unwrap because this is always provided when ACK frequency is enabled +6055 let config = self.config.ack_frequency_config.as_ref().unwrap(); 6056 -6057 self.ack_frequency -6058 .ack_frequency_sent(path_id, builder.packet_number, max_ack_delay); -6059 } -6060 -6061 // PATH_CHALLENGE -6062 if !scheduling_info.is_abandoned -6063 && space_id == SpaceId::Data -6064 && path.pending_on_path_challenge -6065 && !self.state.is_closed() -6066 && builder.frame_space_remaining() > frame::PathChallenge::SIZE_BOUND -6067 // we don't want to send new challenges if we are already closing -6068 { -6069 path.pending_on_path_challenge = false; -6070 -6071 let token = self.rng.random(); -6072 path.record_path_challenge_sent(now, token, path.network_path); -6073 // Generate a new challenge every time we send a new PATH_CHALLENGE -6074 let challenge = frame::PathChallenge(token); -6075 builder.write_frame(challenge, stats); -6076 builder.require_padding(); -6077 let pto = self.ack_frequency.max_ack_delay_for_pto() + path.rtt.pto_base(); -6078 match path.open_status { -6079 paths::OpenStatus::Sent | paths::OpenStatus::Informed => {} -6080 paths::OpenStatus::Pending => { -6081 path.open_status = paths::OpenStatus::Sent; -6082 self.timers.set( -6083 Timer::PerPath(path_id, PathTimer::AbandonFromValidation), -6084 now + 3 * pto, -6085 self.qlog.with_time(now), -6086 ); -6087 } -6088 } -6089 -6090 self.timers.set( -6091 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -6092 now + pto, -6093 self.qlog.with_time(now), -6094 ); -6095 -6096 if is_multipath_negotiated && !path.validated && path.pending_on_path_challenge { -6097 // queue informing the path status along with the challenge -6098 space.pending.path_status.insert(path_id); -6099 } -6100 -6101 // Always include an OBSERVED_ADDR frame with a PATH_CHALLENGE, regardless -6102 // of whether one has already been sent on this path. -6103 if space_id == SpaceId::Data -6104 && self -6105 .config -6106 .address_discovery_role -6107 .should_report(&self.peer_params.address_discovery_role) -6108 { -6109 let frame = frame::ObservedAddr::new( -6110 path.network_path.remote, -6111 self.next_observed_addr_seq_no, -6112 ); -6113 if builder.frame_space_remaining() > frame.size() { -6114 builder.write_frame(frame, stats); +6057 // Ensure the delay is within bounds to avoid a PROTOCOL_VIOLATION error +6058 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay( +6059 path.rtt.get(), +6060 config, +6061 &self.peer_params, +6062 ); +6063 +6064 let frame = frame::AckFrequency { +6065 sequence: sequence_number, +6066 ack_eliciting_threshold: config.ack_eliciting_threshold, +6067 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX), +6068 reordering_threshold: config.reordering_threshold, +6069 }; +6070 builder.write_frame(frame, stats); +6071 +6072 self.ack_frequency +6073 .ack_frequency_sent(path_id, builder.packet_number, max_ack_delay); +6074 } +6075 +6076 // PATH_CHALLENGE +6077 if !scheduling_info.is_abandoned +6078 && space_id == SpaceId::Data +6079 && path.pending_on_path_challenge +6080 && !self.state.is_closed() +6081 && builder.frame_space_remaining() > frame::PathChallenge::SIZE_BOUND +6082 // we don't want to send new challenges if we are already closing +6083 { +6084 path.pending_on_path_challenge = false; +6085 +6086 let token = self.rng.random(); +6087 path.record_path_challenge_sent(now, token, path.network_path); +6088 // Generate a new challenge every time we send a new PATH_CHALLENGE +6089 let challenge = frame::PathChallenge(token); +6090 builder.write_frame(challenge, stats); +6091 builder.require_padding(); +6092 let pto = self.ack_frequency.max_ack_delay_for_pto() + path.rtt.pto_base(); +6093 match path.open_status { +6094 paths::OpenStatus::Sent | paths::OpenStatus::Informed => {} +6095 paths::OpenStatus::Pending => { +6096 path.open_status = paths::OpenStatus::Sent; +6097 self.timers.set( +6098 Timer::PerPath(path_id, PathTimer::AbandonFromValidation), +6099 now + 3 * pto, +6100 self.qlog.with_time(now), +6101 ); +6102 } +6103 } +6104 +6105 self.timers.set( +6106 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +6107 now + pto, +6108 self.qlog.with_time(now), +6109 ); +6110 +6111 if is_multipath_negotiated && !path.validated && path.pending_on_path_challenge { +6112 // queue informing the path status along with the challenge +6113 space.pending.path_status.insert(path_id); +6114 } 6115 -6116 self.next_observed_addr_seq_no = -6117 self.next_observed_addr_seq_no.saturating_add(1u8); -6118 path.observed_addr_sent = true; -6119 -6120 space.pending.observed_addr = false; -6121 } -6122 } -6123 } -6124 -6125 // PATH_RESPONSE -6126 if !scheduling_info.is_abandoned -6127 && space_id == SpaceId::Data -6128 && builder.frame_space_remaining() > frame::PathResponse::SIZE_BOUND -6129 && let Some(token) = path.path_responses.pop_on_path(path.network_path) -6130 { -6131 let response = frame::PathResponse(token); -6132 builder.write_frame(response, stats); -6133 builder.require_padding(); +6116 // Always include an OBSERVED_ADDR frame with a PATH_CHALLENGE, regardless +6117 // of whether one has already been sent on this path. +6118 if space_id == SpaceId::Data +6119 && self +6120 .config +6121 .address_discovery_role +6122 .should_report(&self.peer_params.address_discovery_role) +6123 { +6124 let frame = frame::ObservedAddr::new( +6125 path.network_path.remote, +6126 self.next_observed_addr_seq_no, +6127 ); +6128 if builder.frame_space_remaining() > frame.size() { +6129 builder.write_frame(frame, stats); +6130 +6131 self.next_observed_addr_seq_no = +6132 self.next_observed_addr_seq_no.saturating_add(1u8); +6133 path.observed_addr_sent = true; 6134 -6135 // NOTE: this is technically not required but might be useful to ride the -6136 // request/response nature of path challenges to refresh an observation -6137 // Since PATH_RESPONSE is a probing frame, this is allowed by the spec. -6138 if space_id == SpaceId::Data -6139 && self -6140 .config -6141 .address_discovery_role -6142 .should_report(&self.peer_params.address_discovery_role) -6143 { -6144 let frame = frame::ObservedAddr::new( -6145 path.network_path.remote, -6146 self.next_observed_addr_seq_no, -6147 ); -6148 if builder.frame_space_remaining() > frame.size() { -6149 builder.write_frame(frame, stats); -6150 -6151 self.next_observed_addr_seq_no = -6152 self.next_observed_addr_seq_no.saturating_add(1u8); -6153 path.observed_addr_sent = true; -6154 -6155 space.pending.observed_addr = false; -6156 } -6157 } -6158 } -6159 -6160 // REACH_OUT -6161 while !scheduling_info.is_abandoned -6162 && scheduling_info.may_send_data -6163 && let Some(reach_out) = space -6164 .pending -6165 .reach_out -6166 .pop_if(|frame| builder.frame_space_remaining() >= frame.size()) -6167 { -6168 builder.write_frame(reach_out, stats); -6169 } -6170 -6171 // PATH_ABANDON -6172 if space_id == SpaceId::Data -6173 && scheduling_info.is_abandoned -6174 && scheduling_info.may_self_abandon -6175 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining() -6176 && let Some(error_code) = space.pending.path_abandon.remove(&path_id) -6177 { -6178 let frame = frame::PathAbandon { -6179 path_id, -6180 error_code, -6181 }; -6182 builder.write_frame(frame, stats); -6183 -6184 // Consider remotely issued CIDs as retired now that we have sent this frame at -6185 // least once. -6186 self.remote_cids.remove(&path_id); -6187 } -6188 while space_id == SpaceId::Data -6189 && scheduling_info.may_send_data +6135 space.pending.observed_addr = false; +6136 } +6137 } +6138 } +6139 +6140 // PATH_RESPONSE +6141 if !scheduling_info.is_abandoned +6142 && space_id == SpaceId::Data +6143 && builder.frame_space_remaining() > frame::PathResponse::SIZE_BOUND +6144 && let Some(token) = path.path_responses.pop_on_path(path.network_path) +6145 { +6146 let response = frame::PathResponse(token); +6147 builder.write_frame(response, stats); +6148 builder.require_padding(); +6149 +6150 // NOTE: this is technically not required but might be useful to ride the +6151 // request/response nature of path challenges to refresh an observation +6152 // Since PATH_RESPONSE is a probing frame, this is allowed by the spec. +6153 if space_id == SpaceId::Data +6154 && self +6155 .config +6156 .address_discovery_role +6157 .should_report(&self.peer_params.address_discovery_role) +6158 { +6159 let frame = frame::ObservedAddr::new( +6160 path.network_path.remote, +6161 self.next_observed_addr_seq_no, +6162 ); +6163 if builder.frame_space_remaining() > frame.size() { +6164 builder.write_frame(frame, stats); +6165 +6166 self.next_observed_addr_seq_no = +6167 self.next_observed_addr_seq_no.saturating_add(1u8); +6168 path.observed_addr_sent = true; +6169 +6170 space.pending.observed_addr = false; +6171 } +6172 } +6173 } +6174 +6175 // REACH_OUT +6176 while !scheduling_info.is_abandoned +6177 && scheduling_info.may_send_data +6178 && let Some(reach_out) = space +6179 .pending +6180 .reach_out +6181 .pop_if(|frame| builder.frame_space_remaining() >= frame.size()) +6182 { +6183 builder.write_frame(reach_out, stats); +6184 } +6185 +6186 // PATH_ABANDON +6187 if space_id == SpaceId::Data +6188 && scheduling_info.is_abandoned +6189 && scheduling_info.may_self_abandon 6190 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining() -6191 && let Some((abandoned_path_id, error_code)) = space.pending.path_abandon.pop_first() +6191 && let Some(error_code) = space.pending.path_abandon.remove(&path_id) 6192 { 6193 let frame = frame::PathAbandon { -6194 path_id: abandoned_path_id, +6194 path_id, 6195 error_code, 6196 }; 6197 builder.write_frame(frame, stats); 6198 6199 // Consider remotely issued CIDs as retired now that we have sent this frame at 6200 // least once. -6201 self.remote_cids.remove(&abandoned_path_id); +6201 self.remote_cids.remove(&path_id); 6202 } -6203 -6204 // OBSERVED_ADDR -6205 if !scheduling_info.is_abandoned -6206 && scheduling_info.may_send_data -6207 && space_id == SpaceId::Data -6208 && self -6209 .config -6210 .address_discovery_role -6211 .should_report(&self.peer_params.address_discovery_role) -6212 && (!path.observed_addr_sent || space.pending.observed_addr) -6213 { -6214 let frame = -6215 frame::ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no); -6216 if builder.frame_space_remaining() > frame.size() { -6217 builder.write_frame(frame, stats); +6203 while space_id == SpaceId::Data +6204 && scheduling_info.may_send_data +6205 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining() +6206 && let Some((abandoned_path_id, error_code)) = space.pending.path_abandon.pop_first() +6207 { +6208 let frame = frame::PathAbandon { +6209 path_id: abandoned_path_id, +6210 error_code, +6211 }; +6212 builder.write_frame(frame, stats); +6213 +6214 // Consider remotely issued CIDs as retired now that we have sent this frame at +6215 // least once. +6216 self.remote_cids.remove(&abandoned_path_id); +6217 } 6218 -6219 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8); -6220 path.observed_addr_sent = true; -6221 -6222 space.pending.observed_addr = false; -6223 } -6224 } -6225 -6226 // CRYPTO -6227 while !is_0rtt -6228 && !scheduling_info.is_abandoned -6229 && scheduling_info.may_send_data -6230 && builder.frame_space_remaining() > frame::Crypto::SIZE_BOUND -6231 { -6232 let Some(mut frame) = space.pending.crypto.pop_front() else { -6233 break; -6234 }; -6235 -6236 // Calculate the maximum amount of crypto data we can store in the buffer. -6237 // Since the offset is known, we can reserve the exact size required to encode it. -6238 // For length we reserve 2bytes which allows to encode up to 2^14, -6239 // which is more than what fits into normally sized QUIC frames. -6240 let max_crypto_data_size = builder.frame_space_remaining() -6241 - 1 // Frame Type -6242 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) }) -6243 - 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes -6244 -6245 let len = frame -6246 .data -6247 .len() -6248 .min(2usize.pow(14) - 1) -6249 .min(max_crypto_data_size); +6219 // OBSERVED_ADDR +6220 if !scheduling_info.is_abandoned +6221 && scheduling_info.may_send_data +6222 && space_id == SpaceId::Data +6223 && self +6224 .config +6225 .address_discovery_role +6226 .should_report(&self.peer_params.address_discovery_role) +6227 && (!path.observed_addr_sent || space.pending.observed_addr) +6228 { +6229 let frame = +6230 frame::ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no); +6231 if builder.frame_space_remaining() > frame.size() { +6232 builder.write_frame(frame, stats); +6233 +6234 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8); +6235 path.observed_addr_sent = true; +6236 +6237 space.pending.observed_addr = false; +6238 } +6239 } +6240 +6241 // CRYPTO +6242 while !is_0rtt +6243 && !scheduling_info.is_abandoned +6244 && scheduling_info.may_send_data +6245 && builder.frame_space_remaining() > frame::Crypto::SIZE_BOUND +6246 { +6247 let Some(mut frame) = space.pending.crypto.pop_front() else { +6248 break; +6249 }; 6250 -6251 let data = frame.data.split_to(len); -6252 let offset = frame.offset; -6253 let truncated = frame::Crypto { offset, data }; -6254 builder.write_frame(truncated, stats); -6255 -6256 if !frame.data.is_empty() { -6257 frame.offset += len as u64; -6258 space.pending.crypto.push_front(frame); -6259 } -6260 } -6261 -6262 // PATH_STATUS_AVAILABLE & PATH_STATUS_BACKUP -6263 while space_id == SpaceId::Data -6264 && !scheduling_info.is_abandoned -6265 && scheduling_info.may_send_data -6266 && frame::PathStatusAvailable::SIZE_BOUND <= builder.frame_space_remaining() -6267 { -6268 let Some(path_id) = space.pending.path_status.pop_first() else { -6269 break; -6270 }; -6271 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else { -6272 trace!(%path_id, "discarding queued path status for unknown path"); -6273 continue; -6274 }; -6275 -6276 let seq = path.status.seq(); -6277 match path.local_status() { -6278 PathStatus::Available => { -6279 let frame = frame::PathStatusAvailable { -6280 path_id, -6281 status_seq_no: seq, -6282 }; -6283 builder.write_frame(frame, stats); -6284 } -6285 PathStatus::Backup => { -6286 let frame = frame::PathStatusBackup { -6287 path_id, -6288 status_seq_no: seq, -6289 }; -6290 builder.write_frame(frame, stats); -6291 } -6292 } -6293 } -6294 -6295 // MAX_PATH_ID -6296 if space_id == SpaceId::Data -6297 && !scheduling_info.is_abandoned -6298 && scheduling_info.may_send_data -6299 && space.pending.max_path_id -6300 && frame::MaxPathId::SIZE_BOUND <= builder.frame_space_remaining() -6301 { -6302 let frame = frame::MaxPathId(self.local_max_path_id); -6303 builder.write_frame(frame, stats); -6304 space.pending.max_path_id = false; -6305 } -6306 -6307 // PATHS_BLOCKED -6308 if space_id == SpaceId::Data -6309 && !scheduling_info.is_abandoned -6310 && scheduling_info.may_send_data -6311 && space.pending.paths_blocked -6312 && frame::PathsBlocked::SIZE_BOUND <= builder.frame_space_remaining() -6313 { -6314 let frame = frame::PathsBlocked(self.remote_max_path_id); -6315 builder.write_frame(frame, stats); -6316 space.pending.paths_blocked = false; -6317 } -6318 -6319 // PATH_CIDS_BLOCKED -6320 while space_id == SpaceId::Data -6321 && !scheduling_info.is_abandoned -6322 && scheduling_info.may_send_data -6323 && frame::PathCidsBlocked::SIZE_BOUND <= builder.frame_space_remaining() -6324 { -6325 let Some(path_id) = space.pending.path_cids_blocked.pop_first() else { -6326 break; -6327 }; -6328 let next_seq = match self.remote_cids.get(&path_id) { -6329 Some(cid_queue) => VarInt(cid_queue.active_seq() + 1), -6330 None => VarInt(0), -6331 }; -6332 let frame = frame::PathCidsBlocked { path_id, next_seq }; -6333 builder.write_frame(frame, stats); -6334 } -6335 -6336 // RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS -6337 if space_id == SpaceId::Data -6338 && !scheduling_info.is_abandoned -6339 && scheduling_info.may_send_data -6340 { -6341 self.streams -6342 .write_control_frames(builder, &mut space.pending, stats); -6343 } -6344 -6345 // NEW_CONNECTION_ID -6346 let cid_len = self -6347 .local_cid_state -6348 .values() -6349 .map(|cid_state| cid_state.cid_len()) -6350 .max() -6351 .expect("some local CID state must exist"); -6352 let new_cid_size_bound = -6353 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len); -6354 while !scheduling_info.is_abandoned -6355 && scheduling_info.may_send_data -6356 && builder.frame_space_remaining() > new_cid_size_bound -6357 { -6358 let Some(issued) = space.pending.new_cids.pop() else { -6359 break; -6360 }; -6361 let retire_prior_to = self -6362 .local_cid_state -6363 .get(&issued.path_id) -6364 .map(|cid_state| cid_state.retire_prior_to()) -6365 .unwrap_or_else(|| panic!("missing local CID state for path={}", issued.path_id)); -6366 -6367 let cid_path_id = match is_multipath_negotiated { -6368 true => Some(issued.path_id), -6369 false => { -6370 debug_assert_eq!(issued.path_id, PathId::ZERO); -6371 None -6372 } -6373 }; -6374 let frame = frame::NewConnectionId { -6375 path_id: cid_path_id, -6376 sequence: issued.sequence, -6377 retire_prior_to, -6378 id: issued.id, -6379 reset_token: issued.reset_token, -6380 }; -6381 builder.write_frame(frame, stats); -6382 } -6383 -6384 // RETIRE_CONNECTION_ID -6385 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated); -6386 while !scheduling_info.is_abandoned -6387 && scheduling_info.may_send_data -6388 && builder.frame_space_remaining() > retire_cid_bound -6389 { -6390 let (path_id, sequence) = match space.pending.retire_cids.pop() { -6391 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => (None, seq), -6392 Some((path_id, seq)) => (Some(path_id), seq), -6393 None => break, -6394 }; -6395 let frame = frame::RetireConnectionId { path_id, sequence }; +6251 // Calculate the maximum amount of crypto data we can store in the buffer. +6252 // Since the offset is known, we can reserve the exact size required to encode it. +6253 // For length we reserve 2bytes which allows to encode up to 2^14, +6254 // which is more than what fits into normally sized QUIC frames. +6255 let max_crypto_data_size = builder.frame_space_remaining() +6256 - 1 // Frame Type +6257 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) }) +6258 - 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes +6259 +6260 let len = frame +6261 .data +6262 .len() +6263 .min(2usize.pow(14) - 1) +6264 .min(max_crypto_data_size); +6265 +6266 let data = frame.data.split_to(len); +6267 let offset = frame.offset; +6268 let truncated = frame::Crypto { offset, data }; +6269 builder.write_frame(truncated, stats); +6270 +6271 if !frame.data.is_empty() { +6272 frame.offset += len as u64; +6273 space.pending.crypto.push_front(frame); +6274 } +6275 } +6276 +6277 // PATH_STATUS_AVAILABLE & PATH_STATUS_BACKUP +6278 while space_id == SpaceId::Data +6279 && !scheduling_info.is_abandoned +6280 && scheduling_info.may_send_data +6281 && frame::PathStatusAvailable::SIZE_BOUND <= builder.frame_space_remaining() +6282 { +6283 let Some(path_id) = space.pending.path_status.pop_first() else { +6284 break; +6285 }; +6286 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else { +6287 trace!(%path_id, "discarding queued path status for unknown path"); +6288 continue; +6289 }; +6290 +6291 let seq = path.status.seq(); +6292 match path.local_status() { +6293 PathStatus::Available => { +6294 let frame = frame::PathStatusAvailable { +6295 path_id, +6296 status_seq_no: seq, +6297 }; +6298 builder.write_frame(frame, stats); +6299 } +6300 PathStatus::Backup => { +6301 let frame = frame::PathStatusBackup { +6302 path_id, +6303 status_seq_no: seq, +6304 }; +6305 builder.write_frame(frame, stats); +6306 } +6307 } +6308 } +6309 +6310 // MAX_PATH_ID +6311 if space_id == SpaceId::Data +6312 && !scheduling_info.is_abandoned +6313 && scheduling_info.may_send_data +6314 && space.pending.max_path_id +6315 && frame::MaxPathId::SIZE_BOUND <= builder.frame_space_remaining() +6316 { +6317 let frame = frame::MaxPathId(self.local_max_path_id); +6318 builder.write_frame(frame, stats); +6319 space.pending.max_path_id = false; +6320 } +6321 +6322 // PATHS_BLOCKED +6323 if space_id == SpaceId::Data +6324 && !scheduling_info.is_abandoned +6325 && scheduling_info.may_send_data +6326 && space.pending.paths_blocked +6327 && frame::PathsBlocked::SIZE_BOUND <= builder.frame_space_remaining() +6328 { +6329 let frame = frame::PathsBlocked(self.remote_max_path_id); +6330 builder.write_frame(frame, stats); +6331 space.pending.paths_blocked = false; +6332 } +6333 +6334 // PATH_CIDS_BLOCKED +6335 while space_id == SpaceId::Data +6336 && !scheduling_info.is_abandoned +6337 && scheduling_info.may_send_data +6338 && frame::PathCidsBlocked::SIZE_BOUND <= builder.frame_space_remaining() +6339 { +6340 let Some(path_id) = space.pending.path_cids_blocked.pop_first() else { +6341 break; +6342 }; +6343 let next_seq = match self.remote_cids.get(&path_id) { +6344 Some(cid_queue) => VarInt(cid_queue.active_seq() + 1), +6345 None => VarInt(0), +6346 }; +6347 let frame = frame::PathCidsBlocked { path_id, next_seq }; +6348 builder.write_frame(frame, stats); +6349 } +6350 +6351 // RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS +6352 if space_id == SpaceId::Data +6353 && !scheduling_info.is_abandoned +6354 && scheduling_info.may_send_data +6355 { +6356 self.streams +6357 .write_control_frames(builder, &mut space.pending, stats); +6358 } +6359 +6360 // NEW_CONNECTION_ID +6361 let cid_len = self +6362 .local_cid_state +6363 .values() +6364 .map(|cid_state| cid_state.cid_len()) +6365 .max() +6366 .expect("some local CID state must exist"); +6367 let new_cid_size_bound = +6368 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len); +6369 while !scheduling_info.is_abandoned +6370 && scheduling_info.may_send_data +6371 && builder.frame_space_remaining() > new_cid_size_bound +6372 { +6373 let Some(issued) = space.pending.new_cids.pop() else { +6374 break; +6375 }; +6376 let retire_prior_to = self +6377 .local_cid_state +6378 .get(&issued.path_id) +6379 .map(|cid_state| cid_state.retire_prior_to()) +6380 .unwrap_or_else(|| panic!("missing local CID state for path={}", issued.path_id)); +6381 +6382 let cid_path_id = match is_multipath_negotiated { +6383 true => Some(issued.path_id), +6384 false => { +6385 debug_assert_eq!(issued.path_id, PathId::ZERO); +6386 None +6387 } +6388 }; +6389 let frame = frame::NewConnectionId { +6390 path_id: cid_path_id, +6391 sequence: issued.sequence, +6392 retire_prior_to, +6393 id: issued.id, +6394 reset_token: issued.reset_token, +6395 }; 6396 builder.write_frame(frame, stats); 6397 } 6398 -6399 // DATAGRAM -6400 let mut sent_datagrams = false; +6399 // RETIRE_CONNECTION_ID +6400 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated); 6401 while !scheduling_info.is_abandoned 6402 && scheduling_info.may_send_data -6403 && builder.frame_space_remaining() > Datagram::SIZE_BOUND -6404 && space_id == SpaceId::Data -6405 { -6406 match self.datagrams.write(builder, stats) { -6407 true => { -6408 sent_datagrams = true; -6409 } -6410 false => break, -6411 } +6403 && builder.frame_space_remaining() > retire_cid_bound +6404 { +6405 let (path_id, sequence) = match space.pending.retire_cids.pop() { +6406 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => (None, seq), +6407 Some((path_id, seq)) => (Some(path_id), seq), +6408 None => break, +6409 }; +6410 let frame = frame::RetireConnectionId { path_id, sequence }; +6411 builder.write_frame(frame, stats); 6412 } -6413 if self.datagrams.send_blocked && sent_datagrams { -6414 self.events.push_back(Event::DatagramsUnblocked); -6415 self.datagrams.send_blocked = false; -6416 } -6417 -6418 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; -6419 -6420 // NEW_TOKEN -6421 if !scheduling_info.is_abandoned && scheduling_info.may_send_data { -6422 while let Some(network_path) = space.pending.new_tokens.pop() { -6423 debug_assert_eq!(space_id, SpaceId::Data); -6424 let ConnectionSide::Server { server_config } = &self.side else { -6425 panic!("NEW_TOKEN frames should not be enqueued by clients"); -6426 }; -6427 -6428 if !network_path.is_probably_same_path(&path.network_path) { -6429 // NEW_TOKEN frames contain tokens bound to a client's IP address, and are only -6430 // useful if used from the same IP address. Thus, we abandon enqueued NEW_TOKEN -6431 // frames upon an path change. Instead, when the new path becomes validated, -6432 // NEW_TOKEN frames may be enqueued for the new path instead. -6433 continue; -6434 } -6435 -6436 let token = Token::new( -6437 TokenPayload::Validation { -6438 ip: network_path.remote.ip(), -6439 issued: server_config.time_source.now(), -6440 }, -6441 &mut self.rng, -6442 ); -6443 let new_token = NewToken { -6444 token: token.encode(&*server_config.token_key).into(), -6445 }; -6446 -6447 if builder.frame_space_remaining() < new_token.size() { -6448 space.pending.new_tokens.push(network_path); -6449 break; -6450 } -6451 -6452 builder.write_frame(new_token, stats); -6453 builder.retransmits_mut().new_tokens.push(network_path); -6454 } -6455 } -6456 -6457 // ADD_ADDRESS -6458 while space_id == SpaceId::Data -6459 && !scheduling_info.is_abandoned -6460 && scheduling_info.may_send_data -6461 && frame::AddAddress::SIZE_BOUND <= builder.frame_space_remaining() -6462 { -6463 if let Some(added_address) = space.pending.add_address.pop_last() { -6464 builder.write_frame(added_address, stats); -6465 } else { -6466 break; -6467 } -6468 } -6469 -6470 // REMOVE_ADDRESS -6471 while space_id == SpaceId::Data -6472 && !scheduling_info.is_abandoned -6473 && scheduling_info.may_send_data -6474 && frame::RemoveAddress::SIZE_BOUND <= builder.frame_space_remaining() -6475 { -6476 if let Some(removed_address) = space.pending.remove_address.pop_last() { -6477 builder.write_frame(removed_address, stats); -6478 } else { -6479 break; -6480 } -6481 } -6482 -6483 // STREAM -6484 if !scheduling_info.is_abandoned -6485 && scheduling_info.may_send_data -6486 && space_id == SpaceId::Data -6487 { -6488 self.streams -6489 .write_stream_frames(builder, self.config.send_fairness, stats); -6490 } -6491 } -6492 -6493 /// Write pending ACKs into a buffer -6494 fn populate_acks<'a, 'b>( -6495 now: Instant, -6496 receiving_ecn: bool, -6497 path_id: PathId, -6498 space_id: SpaceId, -6499 space: &mut PacketSpace, -6500 is_multipath_negotiated: bool, -6501 builder: &mut PacketBuilder<'a, 'b>, -6502 stats: &mut FrameStats, -6503 space_has_keys: bool, -6504 ) { -6505 // 0-RTT packets must never carry acks (which would have to be of handshake packets) -6506 debug_assert!(space_has_keys, "tried to send ACK in 0-RTT"); +6413 +6414 // DATAGRAM +6415 let mut sent_datagrams = false; +6416 while !scheduling_info.is_abandoned +6417 && scheduling_info.may_send_data +6418 && builder.frame_space_remaining() > Datagram::SIZE_BOUND +6419 && space_id == SpaceId::Data +6420 { +6421 match self.datagrams.write(builder, stats) { +6422 true => { +6423 sent_datagrams = true; +6424 } +6425 false => break, +6426 } +6427 } +6428 if self.datagrams.send_blocked && sent_datagrams { +6429 self.events.push_back(Event::DatagramsUnblocked); +6430 self.datagrams.send_blocked = false; +6431 } +6432 +6433 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; +6434 +6435 // NEW_TOKEN +6436 if !scheduling_info.is_abandoned && scheduling_info.may_send_data { +6437 while let Some(network_path) = space.pending.new_tokens.pop() { +6438 debug_assert_eq!(space_id, SpaceId::Data); +6439 let ConnectionSide::Server { server_config } = &self.side else { +6440 panic!("NEW_TOKEN frames should not be enqueued by clients"); +6441 }; +6442 +6443 if !network_path.is_probably_same_path(&path.network_path) { +6444 // NEW_TOKEN frames contain tokens bound to a client's IP address, and are only +6445 // useful if used from the same IP address. Thus, we abandon enqueued NEW_TOKEN +6446 // frames upon an path change. Instead, when the new path becomes validated, +6447 // NEW_TOKEN frames may be enqueued for the new path instead. +6448 continue; +6449 } +6450 +6451 let token = Token::new( +6452 TokenPayload::Validation { +6453 ip: network_path.remote.ip(), +6454 issued: server_config.time_source.now(), +6455 }, +6456 &mut self.rng, +6457 ); +6458 let new_token = NewToken { +6459 token: token.encode(&*server_config.token_key).into(), +6460 }; +6461 +6462 if builder.frame_space_remaining() < new_token.size() { +6463 space.pending.new_tokens.push(network_path); +6464 break; +6465 } +6466 +6467 builder.write_frame(new_token, stats); +6468 builder.retransmits_mut().new_tokens.push(network_path); +6469 } +6470 } +6471 +6472 // ADD_ADDRESS +6473 while space_id == SpaceId::Data +6474 && !scheduling_info.is_abandoned +6475 && scheduling_info.may_send_data +6476 && frame::AddAddress::SIZE_BOUND <= builder.frame_space_remaining() +6477 { +6478 if let Some(added_address) = space.pending.add_address.pop_last() { +6479 builder.write_frame(added_address, stats); +6480 } else { +6481 break; +6482 } +6483 } +6484 +6485 // REMOVE_ADDRESS +6486 while space_id == SpaceId::Data +6487 && !scheduling_info.is_abandoned +6488 && scheduling_info.may_send_data +6489 && frame::RemoveAddress::SIZE_BOUND <= builder.frame_space_remaining() +6490 { +6491 if let Some(removed_address) = space.pending.remove_address.pop_last() { +6492 builder.write_frame(removed_address, stats); +6493 } else { +6494 break; +6495 } +6496 } +6497 +6498 // STREAM +6499 if !scheduling_info.is_abandoned +6500 && scheduling_info.may_send_data +6501 && space_id == SpaceId::Data +6502 { +6503 self.streams +6504 .write_stream_frames(builder, self.config.send_fairness, stats); +6505 } +6506 } 6507 -6508 debug_assert!( -6509 is_multipath_negotiated || path_id == PathId::ZERO, -6510 "Only PathId::ZERO allowed without multipath (have {path_id:?})" -6511 ); -6512 if is_multipath_negotiated { -6513 debug_assert!( -6514 space_id == SpaceId::Data || path_id == PathId::ZERO, -6515 "path acks must be sent in 1RTT space (have {space_id:?})" -6516 ); -6517 } -6518 -6519 let pns = space.for_path(path_id); -6520 let ranges = pns.pending_acks.ranges(); -6521 debug_assert!(!ranges.is_empty(), "can not send empty ACK range"); -6522 let ecn = if receiving_ecn { -6523 Some(&pns.ecn_counters) -6524 } else { -6525 None -6526 }; -6527 -6528 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64; -6529 // TODO: This should come from `TransportConfig` if that gets configurable. -6530 let ack_delay_exp = TransportParameters::default().ack_delay_exponent; -6531 let delay = delay_micros >> ack_delay_exp.into_inner(); -6532 -6533 if is_multipath_negotiated && space_id == SpaceId::Data { -6534 if !ranges.is_empty() { -6535 let frame = frame::PathAck::encoder(path_id, delay, ranges, ecn); -6536 builder.write_frame(frame, stats); -6537 } -6538 } else { -6539 builder.write_frame(frame::Ack::encoder(delay, ranges, ecn), stats); -6540 } -6541 } +6508 /// Write pending ACKs into a buffer +6509 fn populate_acks<'a, 'b>( +6510 now: Instant, +6511 receiving_ecn: bool, +6512 path_id: PathId, +6513 space_id: SpaceId, +6514 space: &mut PacketSpace, +6515 is_multipath_negotiated: bool, +6516 builder: &mut PacketBuilder<'a, 'b>, +6517 stats: &mut FrameStats, +6518 space_has_keys: bool, +6519 ) { +6520 // 0-RTT packets must never carry acks (which would have to be of handshake packets) +6521 debug_assert!(space_has_keys, "tried to send ACK in 0-RTT"); +6522 +6523 debug_assert!( +6524 is_multipath_negotiated || path_id == PathId::ZERO, +6525 "Only PathId::ZERO allowed without multipath (have {path_id:?})" +6526 ); +6527 if is_multipath_negotiated { +6528 debug_assert!( +6529 space_id == SpaceId::Data || path_id == PathId::ZERO, +6530 "path acks must be sent in 1RTT space (have {space_id:?})" +6531 ); +6532 } +6533 +6534 let pns = space.for_path(path_id); +6535 let ranges = pns.pending_acks.ranges(); +6536 debug_assert!(!ranges.is_empty(), "can not send empty ACK range"); +6537 let ecn = if receiving_ecn { +6538 Some(&pns.ecn_counters) +6539 } else { +6540 None +6541 }; 6542 -6543 fn close_common(&mut self) { -6544 trace!("connection closed"); -6545 self.timers.reset(); -6546 } +6543 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64; +6544 // TODO: This should come from `TransportConfig` if that gets configurable. +6545 let ack_delay_exp = TransportParameters::default().ack_delay_exponent; +6546 let delay = delay_micros >> ack_delay_exp.into_inner(); 6547 -6548 fn set_close_timer(&mut self, now: Instant) { -6549 // QUIC-MULTIPATH § 2.6 Connection Closure: draining for 3*PTO using the max PTO of -6550 // all paths. -6551 let pto_max = self.max_pto_for_space(self.highest_space); -6552 self.timers.set( -6553 Timer::Conn(ConnTimer::Close), -6554 now + 3 * pto_max, -6555 self.qlog.with_time(now), -6556 ); -6557 } -6558 -6559 /// Handle transport parameters received from the peer -6560 /// -6561 /// *remote_cid* and *local_cid* are the source and destination CIDs respectively of the -6562 /// *packet into which the transport parameters arrived. -6563 fn handle_peer_params( -6564 &mut self, -6565 params: TransportParameters, -6566 local_cid: ConnectionId, -6567 remote_cid: ConnectionId, -6568 now: Instant, -6569 ) -> Result<(), TransportError> { -6570 if Some(self.original_remote_cid) != params.initial_src_cid -6571 || (self.side.is_client() -6572 && (Some(self.initial_dst_cid) != params.original_dst_cid -6573 || self.retry_src_cid != params.retry_src_cid)) -6574 { -6575 return Err(TransportError::TRANSPORT_PARAMETER_ERROR( -6576 "CID authentication failure", -6577 )); -6578 } -6579 if params.initial_max_path_id.is_some() && (local_cid.is_empty() || remote_cid.is_empty()) { -6580 return Err(TransportError::PROTOCOL_VIOLATION( -6581 "multipath must not use zero-length CIDs", -6582 )); -6583 } -6584 -6585 self.set_peer_params(params); -6586 self.qlog.emit_peer_transport_params_received(self, now); -6587 -6588 Ok(()) -6589 } -6590 -6591 fn set_peer_params(&mut self, params: TransportParameters) { -6592 self.streams.set_params(&params); -6593 self.idle_timeout = -6594 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout)); -6595 trace!("negotiated max idle timeout {:?}", self.idle_timeout); -6596 -6597 if let Some(ref info) = params.preferred_address { -6598 // During the handshake PathId::ZERO exists. -6599 self.remote_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId { -6600 path_id: None, -6601 sequence: 1, -6602 id: info.connection_id, -6603 reset_token: info.stateless_reset_token, -6604 retire_prior_to: 0, -6605 }) -6606 .expect( -6607 "preferred address CID is the first received, and hence is guaranteed to be legal", -6608 ); -6609 let remote = self.path_data(PathId::ZERO).network_path.remote; -6610 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token); -6611 } -6612 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(&params); -6613 -6614 let mut multipath_enabled = None; -6615 if let (Some(local_max_path_id), Some(remote_max_path_id)) = ( -6616 self.config.get_initial_max_path_id(), -6617 params.initial_max_path_id, -6618 ) { -6619 // multipath is enabled, register the local and remote maximums -6620 self.local_max_path_id = local_max_path_id; -6621 self.remote_max_path_id = remote_max_path_id; -6622 let initial_max_path_id = local_max_path_id.min(remote_max_path_id); -6623 debug!(%initial_max_path_id, "multipath negotiated"); -6624 multipath_enabled = Some(initial_max_path_id); -6625 } -6626 -6627 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) = -6628 self.config -6629 .max_remote_nat_traversal_addresses -6630 .zip(params.max_remote_nat_traversal_addresses) -6631 { -6632 if let Some(max_initial_paths) = -6633 multipath_enabled.map(|path_id| path_id.saturating_add(1u8)) -6634 { -6635 let max_local_addresses = max_remotely_allowed_remote_addresses.get(); -6636 let max_remote_addresses = max_locally_allowed_remote_addresses.get(); -6637 self.n0_nat_traversal = n0_nat_traversal::State::new( -6638 max_remote_addresses, -6639 max_local_addresses, -6640 self.side(), -6641 ); -6642 debug!( -6643 %max_remote_addresses, %max_local_addresses, -6644 "n0's nat traversal negotiated" -6645 ); -6646 -6647 match self.side() { -6648 Side::Client => { -6649 if max_initial_paths.as_u32() < max_remote_addresses as u32 + 1 { -6650 // in this case the client might try to open `max_remote_addresses` new -6651 // paths, but the current multipath configuration will not allow it -6652 debug!(%max_initial_paths, %max_remote_addresses, "local client configuration might cause nat traversal issues") -6653 } else if max_local_addresses as u64 -6654 > params.active_connection_id_limit.into_inner() -6655 { -6656 // the server allows us to send at most `params.active_connection_id_limit` -6657 // but they might need at least `max_local_addresses` to effectively send -6658 // `PATH_CHALLENGE` frames to each advertised local address -6659 debug!(%max_local_addresses, remote_cid_limit=%params.active_connection_id_limit.into_inner(), "remote server configuration might cause nat traversal issues") -6660 } -6661 } -6662 Side::Server => { -6663 if (max_initial_paths.as_u32() as u64) < crate::LOCAL_CID_COUNT { -6664 debug!(%max_initial_paths, local_cid_limit=%crate::LOCAL_CID_COUNT, "local server configuration might cause nat traversal issues") -6665 } -6666 } -6667 } -6668 } else { -6669 debug!("n0 nat traversal enabled for both endpoints, but multipath is missing") -6670 } -6671 } -6672 -6673 self.peer_params = params; -6674 let peer_max_udp_payload_size = -6675 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); -6676 self.path_data_mut(PathId::ZERO) -6677 .mtud -6678 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size); -6679 } -6680 -6681 /// Decrypts a packet, returning the packet number on success -6682 fn decrypt_packet( -6683 &mut self, -6684 now: Instant, -6685 path_id: PathId, -6686 packet: &mut Packet, -6687 ) -> Result<Option<u64>, Option<TransportError>> { -6688 let result = self -6689 .crypto_state -6690 .decrypt_packet_body(packet, path_id, &self.spaces)?; -6691 -6692 let Some(result) = result else { -6693 return Ok(None); -6694 }; +6548 if is_multipath_negotiated && space_id == SpaceId::Data { +6549 if !ranges.is_empty() { +6550 let frame = frame::PathAck::encoder(path_id, delay, ranges, ecn); +6551 builder.write_frame(frame, stats); +6552 } +6553 } else { +6554 builder.write_frame(frame::Ack::encoder(delay, ranges, ecn), stats); +6555 } +6556 } +6557 +6558 fn close_common(&mut self) { +6559 trace!("connection closed"); +6560 self.timers.reset(); +6561 } +6562 +6563 fn set_close_timer(&mut self, now: Instant) { +6564 // QUIC-MULTIPATH § 2.6 Connection Closure: draining for 3*PTO using the max PTO of +6565 // all paths. +6566 let pto_max = self.max_pto_for_space(self.highest_space); +6567 self.timers.set( +6568 Timer::Conn(ConnTimer::Close), +6569 now + 3 * pto_max, +6570 self.qlog.with_time(now), +6571 ); +6572 } +6573 +6574 /// Handle transport parameters received from the peer +6575 /// +6576 /// *remote_cid* and *local_cid* are the source and destination CIDs respectively of the +6577 /// *packet into which the transport parameters arrived. +6578 fn handle_peer_params( +6579 &mut self, +6580 params: TransportParameters, +6581 local_cid: ConnectionId, +6582 remote_cid: ConnectionId, +6583 now: Instant, +6584 ) -> Result<(), TransportError> { +6585 if Some(self.original_remote_cid) != params.initial_src_cid +6586 || (self.side.is_client() +6587 && (Some(self.initial_dst_cid) != params.original_dst_cid +6588 || self.retry_src_cid != params.retry_src_cid)) +6589 { +6590 return Err(TransportError::TRANSPORT_PARAMETER_ERROR( +6591 "CID authentication failure", +6592 )); +6593 } +6594 if params.initial_max_path_id.is_some() && (local_cid.is_empty() || remote_cid.is_empty()) { +6595 return Err(TransportError::PROTOCOL_VIOLATION( +6596 "multipath must not use zero-length CIDs", +6597 )); +6598 } +6599 +6600 self.set_peer_params(params); +6601 self.qlog.emit_peer_transport_params_received(self, now); +6602 +6603 Ok(()) +6604 } +6605 +6606 fn set_peer_params(&mut self, params: TransportParameters) { +6607 self.streams.set_params(&params); +6608 self.idle_timeout = +6609 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout)); +6610 trace!("negotiated max idle timeout {:?}", self.idle_timeout); +6611 +6612 if let Some(ref info) = params.preferred_address { +6613 // During the handshake PathId::ZERO exists. +6614 self.remote_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId { +6615 path_id: None, +6616 sequence: 1, +6617 id: info.connection_id, +6618 reset_token: info.stateless_reset_token, +6619 retire_prior_to: 0, +6620 }) +6621 .expect( +6622 "preferred address CID is the first received, and hence is guaranteed to be legal", +6623 ); +6624 let remote = self.path_data(PathId::ZERO).network_path.remote; +6625 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token); +6626 } +6627 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(&params); +6628 +6629 let mut multipath_enabled = None; +6630 if let (Some(local_max_path_id), Some(remote_max_path_id)) = ( +6631 self.config.get_initial_max_path_id(), +6632 params.initial_max_path_id, +6633 ) { +6634 // multipath is enabled, register the local and remote maximums +6635 self.local_max_path_id = local_max_path_id; +6636 self.remote_max_path_id = remote_max_path_id; +6637 let initial_max_path_id = local_max_path_id.min(remote_max_path_id); +6638 debug!(%initial_max_path_id, "multipath negotiated"); +6639 multipath_enabled = Some(initial_max_path_id); +6640 } +6641 +6642 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) = +6643 self.config +6644 .max_remote_nat_traversal_addresses +6645 .zip(params.max_remote_nat_traversal_addresses) +6646 { +6647 if let Some(max_initial_paths) = +6648 multipath_enabled.map(|path_id| path_id.saturating_add(1u8)) +6649 { +6650 let max_local_addresses = max_remotely_allowed_remote_addresses.get(); +6651 let max_remote_addresses = max_locally_allowed_remote_addresses.get(); +6652 self.n0_nat_traversal = n0_nat_traversal::State::new( +6653 max_remote_addresses, +6654 max_local_addresses, +6655 self.side(), +6656 ); +6657 debug!( +6658 %max_remote_addresses, %max_local_addresses, +6659 "n0's nat traversal negotiated" +6660 ); +6661 +6662 match self.side() { +6663 Side::Client => { +6664 if max_initial_paths.as_u32() < max_remote_addresses as u32 + 1 { +6665 // in this case the client might try to open `max_remote_addresses` new +6666 // paths, but the current multipath configuration will not allow it +6667 debug!(%max_initial_paths, %max_remote_addresses, "local client configuration might cause nat traversal issues") +6668 } else if max_local_addresses as u64 +6669 > params.active_connection_id_limit.into_inner() +6670 { +6671 // the server allows us to send at most `params.active_connection_id_limit` +6672 // but they might need at least `max_local_addresses` to effectively send +6673 // `PATH_CHALLENGE` frames to each advertised local address +6674 debug!(%max_local_addresses, remote_cid_limit=%params.active_connection_id_limit.into_inner(), "remote server configuration might cause nat traversal issues") +6675 } +6676 } +6677 Side::Server => { +6678 if (max_initial_paths.as_u32() as u64) < crate::LOCAL_CID_COUNT { +6679 debug!(%max_initial_paths, local_cid_limit=%crate::LOCAL_CID_COUNT, "local server configuration might cause nat traversal issues") +6680 } +6681 } +6682 } +6683 } else { +6684 debug!("n0 nat traversal enabled for both endpoints, but multipath is missing") +6685 } +6686 } +6687 +6688 self.peer_params = params; +6689 let peer_max_udp_payload_size = +6690 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); +6691 self.path_data_mut(PathId::ZERO) +6692 .mtud +6693 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size); +6694 } 6695 -6696 if result.outgoing_key_update_acked -6697 && let Some(prev) = self.crypto_state.prev_crypto.as_mut() -6698 { -6699 prev.end_packet = Some((result.packet_number, now)); -6700 self.set_key_discard_timer(now, packet.header.space()); -6701 } -6702 -6703 if result.incoming_key_update { -6704 trace!("key update authenticated"); -6705 self.crypto_state -6706 .update_keys(Some((result.packet_number, now)), true); -6707 self.set_key_discard_timer(now, packet.header.space()); -6708 } -6709 -6710 Ok(Some(result.packet_number)) -6711 } -6712 -6713 fn peer_supports_ack_frequency(&self) -> bool { -6714 self.peer_params.min_ack_delay.is_some() -6715 } -6716 -6717 /// Send an IMMEDIATE_ACK frame to the remote endpoint -6718 /// -6719 /// According to the spec, this will result in an error if the remote endpoint does not support -6720 /// the Acknowledgement Frequency extension -6721 pub(crate) fn immediate_ack(&mut self, path_id: PathId) { -6722 debug_assert_eq!( -6723 self.highest_space, -6724 SpaceKind::Data, -6725 "immediate ack must be written in the data space" -6726 ); -6727 self.spaces[SpaceId::Data] -6728 .for_path(path_id) -6729 .immediate_ack_pending = true; +6696 /// Decrypts a packet, returning the packet number on success +6697 fn decrypt_packet( +6698 &mut self, +6699 now: Instant, +6700 path_id: PathId, +6701 packet: &mut Packet, +6702 ) -> Result<Option<u64>, Option<TransportError>> { +6703 let result = self +6704 .crypto_state +6705 .decrypt_packet_body(packet, path_id, &self.spaces)?; +6706 +6707 let Some(result) = result else { +6708 return Ok(None); +6709 }; +6710 +6711 if result.outgoing_key_update_acked +6712 && let Some(prev) = self.crypto_state.prev_crypto.as_mut() +6713 { +6714 prev.end_packet = Some((result.packet_number, now)); +6715 self.set_key_discard_timer(now, packet.header.space()); +6716 } +6717 +6718 if result.incoming_key_update { +6719 trace!("key update authenticated"); +6720 self.crypto_state +6721 .update_keys(Some((result.packet_number, now)), true); +6722 self.set_key_discard_timer(now, packet.header.space()); +6723 } +6724 +6725 Ok(Some(result.packet_number)) +6726 } +6727 +6728 fn peer_supports_ack_frequency(&self) -> bool { +6729 self.peer_params.min_ack_delay.is_some() 6730 } 6731 -6732 /// Decodes a packet, returning its decrypted payload, so it can be inspected in tests -6733 #[cfg(test)] -6734 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> { -6735 let ConnectionEventInner::Datagram(DatagramConnectionEvent { -6736 path_id, -6737 first_decode, -6738 remaining, -6739 .. -6740 }) = &event.0 -6741 else { -6742 return None; -6743 }; -6744 -6745 if remaining.is_some() { -6746 panic!("Packets should never be coalesced in tests"); -6747 } -6748 -6749 let decrypted_header = self -6750 .crypto_state -6751 .unprotect_header(first_decode.clone(), self.peer_params.stateless_reset_token)?; -6752 -6753 let mut packet = decrypted_header.packet?; -6754 self.crypto_state -6755 .decrypt_packet_body(&mut packet, *path_id, &self.spaces) -6756 .ok()?; -6757 -6758 Some(packet.payload.to_vec()) -6759 } -6760 -6761 /// The number of bytes of packets containing retransmittable frames that have not been -6762 /// acknowledged or declared lost. -6763 #[cfg(test)] -6764 pub(crate) fn bytes_in_flight(&self) -> u64 { -6765 // TODO(@divma): consider including for multipath? -6766 self.path_data(PathId::ZERO).in_flight.bytes -6767 } -6768 -6769 /// Number of bytes worth of non-ack-only packets that may be sent -6770 #[cfg(test)] -6771 pub(crate) fn congestion_window(&self) -> u64 { -6772 let path = self.path_data(PathId::ZERO); -6773 path.congestion -6774 .window() -6775 .saturating_sub(path.in_flight.bytes) -6776 } -6777 -6778 /// Whether no timers but keepalive, idle, rtt, pushnewcid, and key discard are running -6779 #[cfg(test)] -6780 pub(crate) fn is_idle(&self) -> bool { -6781 let current_timers = self.timers.values(); -6782 current_timers -6783 .into_iter() -6784 .filter(|(timer, _)| { -6785 !matches!( -6786 timer, -6787 Timer::Conn(ConnTimer::KeepAlive) -6788 | Timer::PerPath(_, PathTimer::PathKeepAlive) -6789 | Timer::Conn(ConnTimer::PushNewCid) -6790 | Timer::Conn(ConnTimer::KeyDiscard) -6791 ) -6792 }) -6793 .min_by_key(|(_, time)| *time) -6794 .is_none_or(|(timer, _)| { -6795 matches!( -6796 timer, -6797 Timer::Conn(ConnTimer::Idle) | Timer::PerPath(_, PathTimer::PathIdle) -6798 ) -6799 }) -6800 } -6801 -6802 /// Whether explicit congestion notification is in use on outgoing packets. -6803 #[cfg(test)] -6804 pub(crate) fn using_ecn(&self) -> bool { -6805 self.path_data(PathId::ZERO).sending_ecn -6806 } -6807 -6808 /// The number of received bytes in the current path -6809 #[cfg(test)] -6810 pub(crate) fn total_recvd(&self) -> u64 { -6811 self.path_data(PathId::ZERO).total_recvd -6812 } -6813 -6814 #[cfg(test)] -6815 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) { -6816 self.local_cid_state -6817 .get(&PathId::ZERO) -6818 .unwrap() -6819 .active_seq() -6820 } -6821 -6822 #[cfg(test)] -6823 #[track_caller] -6824 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) { -6825 self.local_cid_state -6826 .get(&PathId(path_id)) -6827 .unwrap() -6828 .active_seq() -6829 } -6830 -6831 /// Instruct the peer to replace previously issued CIDs by sending a NEW_CONNECTION_ID frame -6832 /// with updated `retire_prior_to` field set to `v` -6833 #[cfg(test)] -6834 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) { -6835 let n = self -6836 .local_cid_state -6837 .get_mut(&PathId::ZERO) -6838 .unwrap() -6839 .assign_retire_seq(v); -6840 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events -6841 self.endpoint_events -6842 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); -6843 } -6844 -6845 /// Check the current active remote CID sequence for `PathId::ZERO` -6846 #[cfg(test)] -6847 pub(crate) fn active_remote_cid_seq(&self) -> u64 { -6848 self.remote_cids.get(&PathId::ZERO).unwrap().active_seq() -6849 } -6850 -6851 /// Returns the detected maximum udp payload size for the current path -6852 #[cfg(test)] -6853 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 { -6854 self.path_data(path_id).current_mtu() -6855 } -6856 -6857 /// Triggers path validation on all paths -6858 #[cfg(test)] -6859 pub(crate) fn trigger_path_validation(&mut self) { -6860 for path in self.paths.values_mut() { -6861 path.data.pending_on_path_challenge = true; -6862 } -6863 } -6864 -6865 /// Simulates a protocol violation error for test purposes. -6866 #[cfg(test)] -6867 pub fn simulate_protocol_violation(&mut self, now: Instant) { -6868 if !self.state.is_closed() { -6869 self.state -6870 .move_to_closed(TransportError::PROTOCOL_VIOLATION("simulated violation")); -6871 self.close_common(); -6872 if !self.state.is_drained() { -6873 self.set_close_timer(now); -6874 } -6875 self.connection_close_pending = true; -6876 } -6877 } -6878 -6879 /// Whether we have on-path 1-RTT data to send. -6880 /// -6881 /// This checks for frames that can only be sent in the data space (1-RTT): -6882 /// - Pending PATH_CHALLENGE frames on the active and previous path if just migrated. -6883 /// - Pending PATH_RESPONSE frames. -6884 /// - Pending data to send in STREAM frames. -6885 /// - Pending DATAGRAM frames to send. -6886 /// -6887 /// See also [`PacketSpace::can_send`] which keeps track of all other frame types that -6888 /// may need to be sent. -6889 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames { -6890 let space_specific = self.paths.get(&path_id).is_some_and(|path| { -6891 path.data.pending_on_path_challenge || !path.data.path_responses.is_empty() -6892 }); +6732 /// Send an IMMEDIATE_ACK frame to the remote endpoint +6733 /// +6734 /// According to the spec, this will result in an error if the remote endpoint does not support +6735 /// the Acknowledgement Frequency extension +6736 pub(crate) fn immediate_ack(&mut self, path_id: PathId) { +6737 debug_assert_eq!( +6738 self.highest_space, +6739 SpaceKind::Data, +6740 "immediate ack must be written in the data space" +6741 ); +6742 self.spaces[SpaceId::Data] +6743 .for_path(path_id) +6744 .immediate_ack_pending = true; +6745 } +6746 +6747 /// Decodes a packet, returning its decrypted payload, so it can be inspected in tests +6748 #[cfg(test)] +6749 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> { +6750 let ConnectionEventInner::Datagram(DatagramConnectionEvent { +6751 path_id, +6752 first_decode, +6753 remaining, +6754 .. +6755 }) = &event.0 +6756 else { +6757 return None; +6758 }; +6759 +6760 if remaining.is_some() { +6761 panic!("Packets should never be coalesced in tests"); +6762 } +6763 +6764 let decrypted_header = self +6765 .crypto_state +6766 .unprotect_header(first_decode.clone(), self.peer_params.stateless_reset_token)?; +6767 +6768 let mut packet = decrypted_header.packet?; +6769 self.crypto_state +6770 .decrypt_packet_body(&mut packet, *path_id, &self.spaces) +6771 .ok()?; +6772 +6773 Some(packet.payload.to_vec()) +6774 } +6775 +6776 /// The number of bytes of packets containing retransmittable frames that have not been +6777 /// acknowledged or declared lost. +6778 #[cfg(test)] +6779 pub(crate) fn bytes_in_flight(&self) -> u64 { +6780 // TODO(@divma): consider including for multipath? +6781 self.path_data(PathId::ZERO).in_flight.bytes +6782 } +6783 +6784 /// Number of bytes worth of non-ack-only packets that may be sent +6785 #[cfg(test)] +6786 pub(crate) fn congestion_window(&self) -> u64 { +6787 let path = self.path_data(PathId::ZERO); +6788 path.congestion +6789 .window() +6790 .saturating_sub(path.in_flight.bytes) +6791 } +6792 +6793 /// Whether no timers but keepalive, idle, rtt, pushnewcid, and key discard are running +6794 #[cfg(test)] +6795 pub(crate) fn is_idle(&self) -> bool { +6796 let current_timers = self.timers.values(); +6797 current_timers +6798 .into_iter() +6799 .filter(|(timer, _)| { +6800 !matches!( +6801 timer, +6802 Timer::Conn(ConnTimer::KeepAlive) +6803 | Timer::PerPath(_, PathTimer::PathKeepAlive) +6804 | Timer::Conn(ConnTimer::PushNewCid) +6805 | Timer::Conn(ConnTimer::KeyDiscard) +6806 ) +6807 }) +6808 .min_by_key(|(_, time)| *time) +6809 .is_none_or(|(timer, _)| { +6810 matches!( +6811 timer, +6812 Timer::Conn(ConnTimer::Idle) | Timer::PerPath(_, PathTimer::PathIdle) +6813 ) +6814 }) +6815 } +6816 +6817 /// Whether explicit congestion notification is in use on outgoing packets. +6818 #[cfg(test)] +6819 pub(crate) fn using_ecn(&self) -> bool { +6820 self.path_data(PathId::ZERO).sending_ecn +6821 } +6822 +6823 /// The number of received bytes in the current path +6824 #[cfg(test)] +6825 pub(crate) fn total_recvd(&self) -> u64 { +6826 self.path_data(PathId::ZERO).total_recvd +6827 } +6828 +6829 #[cfg(test)] +6830 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) { +6831 self.local_cid_state +6832 .get(&PathId::ZERO) +6833 .unwrap() +6834 .active_seq() +6835 } +6836 +6837 #[cfg(test)] +6838 #[track_caller] +6839 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) { +6840 self.local_cid_state +6841 .get(&PathId(path_id)) +6842 .unwrap() +6843 .active_seq() +6844 } +6845 +6846 /// Instruct the peer to replace previously issued CIDs by sending a NEW_CONNECTION_ID frame +6847 /// with updated `retire_prior_to` field set to `v` +6848 #[cfg(test)] +6849 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) { +6850 let n = self +6851 .local_cid_state +6852 .get_mut(&PathId::ZERO) +6853 .unwrap() +6854 .assign_retire_seq(v); +6855 debug_assert!(!self.state.is_drained()); // requirement for endpoint_events +6856 self.endpoint_events +6857 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); +6858 } +6859 +6860 /// Check the current active remote CID sequence for `PathId::ZERO` +6861 #[cfg(test)] +6862 pub(crate) fn active_remote_cid_seq(&self) -> u64 { +6863 self.remote_cids.get(&PathId::ZERO).unwrap().active_seq() +6864 } +6865 +6866 /// Returns the detected maximum udp payload size for the current path +6867 #[cfg(test)] +6868 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 { +6869 self.path_data(path_id).current_mtu() +6870 } +6871 +6872 /// Triggers path validation on all paths +6873 #[cfg(test)] +6874 pub(crate) fn trigger_path_validation(&mut self) { +6875 for path in self.paths.values_mut() { +6876 path.data.pending_on_path_challenge = true; +6877 } +6878 } +6879 +6880 /// Simulates a protocol violation error for test purposes. +6881 #[cfg(test)] +6882 pub fn simulate_protocol_violation(&mut self, now: Instant) { +6883 if !self.state.is_closed() { +6884 self.state +6885 .move_to_closed(TransportError::PROTOCOL_VIOLATION("simulated violation")); +6886 self.close_common(); +6887 if !self.state.is_drained() { +6888 self.set_close_timer(now); +6889 } +6890 self.connection_close_pending = true; +6891 } +6892 } 6893 -6894 // Stream control frames are checked in PacketSpace::can_send, only check data here. -6895 let other = self.streams.can_send_stream_data() -6896 || self -6897 .datagrams -6898 .outgoing -6899 .front() -6900 .is_some_and(|x| x.size(true) <= max_size); -6901 -6902 // All `false` fields are set in PacketSpace::can_send. -6903 SendableFrames { -6904 acks: false, -6905 close: false, -6906 space_specific, -6907 other, -6908 } -6909 } -6910 -6911 /// Terminate the connection instantly, without sending a close packet -6912 fn kill(&mut self, reason: ConnectionError) { -6913 self.close_common(); -6914 self.state.move_to_drained(Some(reason)); -6915 // move_to_drained checks that we were never in drained before, so we -6916 // never sent a `Drained` event before (it's illegal to send more events after drained). -6917 self.endpoint_events.push_back(EndpointEventInner::Drained); -6918 } -6919 -6920 /// Storage size required for the largest packet that can be transmitted on all currently -6921 /// available paths -6922 /// -6923 /// Buffers passed to [`Connection::poll_transmit`] should be at least this large. -6924 /// -6925 /// When multipath is enabled, this value is the minimum MTU across all available paths. -6926 pub fn current_mtu(&self) -> u16 { -6927 self.paths -6928 .iter() -6929 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id)) -6930 .map(|(_path_id, path_state)| path_state.data.current_mtu()) -6931 .min() -6932 .unwrap_or(INITIAL_MTU) +6894 /// Whether we have on-path 1-RTT data to send. +6895 /// +6896 /// This checks for frames that can only be sent in the data space (1-RTT): +6897 /// - Pending PATH_CHALLENGE frames on the active and previous path if just migrated. +6898 /// - Pending PATH_RESPONSE frames. +6899 /// - Pending data to send in STREAM frames. +6900 /// - Pending DATAGRAM frames to send. +6901 /// +6902 /// See also [`PacketSpace::can_send`] which keeps track of all other frame types that +6903 /// may need to be sent. +6904 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames { +6905 let space_specific = self.paths.get(&path_id).is_some_and(|path| { +6906 path.data.pending_on_path_challenge || !path.data.path_responses.is_empty() +6907 }); +6908 +6909 // Stream control frames are checked in PacketSpace::can_send, only check data here. +6910 let other = self.streams.can_send_stream_data() +6911 || self +6912 .datagrams +6913 .outgoing +6914 .front() +6915 .is_some_and(|x| x.size(true) <= max_size); +6916 +6917 // All `false` fields are set in PacketSpace::can_send. +6918 SendableFrames { +6919 acks: false, +6920 close: false, +6921 space_specific, +6922 other, +6923 } +6924 } +6925 +6926 /// Terminate the connection instantly, without sending a close packet +6927 fn kill(&mut self, reason: ConnectionError) { +6928 self.close_common(); +6929 self.state.move_to_drained(Some(reason)); +6930 // move_to_drained checks that we were never in drained before, so we +6931 // never sent a `Drained` event before (it's illegal to send more events after drained). +6932 self.endpoint_events.push_back(EndpointEventInner::Drained); 6933 } 6934 -6935 /// Size of non-frame data for a 1-RTT packet -6936 /// -6937 /// Quantifies space consumed by the QUIC header and AEAD tag. All other bytes in a packet are -6938 /// frames. Changes if the length of the remote connection ID changes, which is expected to be -6939 /// rare. If `pn` is specified, may additionally change unpredictably due to variations in -6940 /// latency and packet loss. -6941 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize { -6942 let pn_len = PacketNumber::new( -6943 pn, -6944 self.spaces[SpaceId::Data] -6945 .for_path(path) -6946 .largest_acked_packet_pn -6947 .unwrap_or(0), -6948 ) -6949 .len(); -6950 -6951 // 1 byte for flags -6952 1 + self -6953 .remote_cids -6954 .get(&path) -6955 .map(|cids| cids.active().len()) -6956 .unwrap_or(20) // Max CID len in QUIC v1 -6957 + pn_len -6958 + self.tag_len_1rtt() -6959 } -6960 -6961 fn predict_1rtt_overhead_no_pn(&self) -> usize { -6962 let pn_len = 4; -6963 -6964 let cid_len = self -6965 .remote_cids -6966 .values() -6967 .map(|cids| cids.active().len()) -6968 .max() -6969 .unwrap_or(20); // Max CID len in QUIC v1 -6970 -6971 // 1 byte for flags -6972 1 + cid_len + pn_len + self.tag_len_1rtt() -6973 } -6974 -6975 fn tag_len_1rtt(&self) -> usize { -6976 // encryption_keys for Data space returns 1-RTT keys if available, otherwise 0-RTT keys -6977 let packet_crypto = self -6978 .crypto_state -6979 .encryption_keys(SpaceKind::Data, self.side.side()) -6980 .map(|(_header, packet, _level)| packet); -6981 // If neither Data nor 0-RTT keys are available, make a reasonable tag length guess. As of -6982 // this writing, all QUIC cipher suites use 16-byte tags. We could return `None` instead, -6983 // but that would needlessly prevent sending datagrams during 0-RTT. -6984 packet_crypto.map_or(16, |x| x.tag_len()) -6985 } -6986 -6987 /// Mark the path as validated, and enqueue NEW_TOKEN frames to be sent as appropriate -6988 fn on_path_validated(&mut self, path_id: PathId) { -6989 self.path_data_mut(path_id).validated = true; -6990 let ConnectionSide::Server { server_config } = &self.side else { -6991 return; -6992 }; -6993 let network_path = self.path_data(path_id).network_path; -6994 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens; -6995 new_tokens.clear(); -6996 for _ in 0..server_config.validation_token.sent { -6997 new_tokens.push(network_path); -6998 } -6999 } -7000 -7001 /// Handle new path status information: PATH_STATUS_AVAILABLE, PATH_STATUS_BACKUP -7002 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) { -7003 if let Some(path) = self.paths.get_mut(&path_id) { -7004 path.data.status.remote_update(status, status_seq_no); -7005 } else { -7006 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id); -7007 } -7008 self.events.push_back( -7009 PathEvent::RemoteStatus { -7010 id: path_id, -7011 status, -7012 } -7013 .into(), -7014 ); -7015 } -7016 -7017 /// Returns the maximum [`PathId`] to be used for sending in this connection. -7018 /// -7019 /// This is calculated as minimum between the local and remote's maximums when multipath is -7020 /// enabled, or `None` when disabled. -7021 /// -7022 /// For data that's received, we should use [`Self::local_max_path_id`] instead. -7023 /// The reasoning is that the remote might already have updated to its own newer -7024 /// [`Self::max_path_id`] after sending out a `MAX_PATH_ID` frame, but it got re-ordered. -7025 fn max_path_id(&self) -> Option<PathId> { -7026 if self.is_multipath_negotiated() { -7027 Some(self.remote_max_path_id.min(self.local_max_path_id)) -7028 } else { -7029 None -7030 } -7031 } -7032 -7033 /// Returns whether this connection has a socket that supports IPv6. -7034 /// -7035 /// TODO(matheus23): This is related to noq endpoint state's `ipv6` bool. We should move that info -7036 /// here instead of trying to hack around not knowing it exactly. -7037 fn is_ipv6(&self) -> bool { -7038 self.paths -7039 .values() -7040 .any(|p| p.data.network_path.remote.is_ipv6()) -7041 } -7042 -7043 /// Add addresses the local endpoint considers are reachable for nat traversal. -7044 pub fn add_nat_traversal_address( -7045 &mut self, -7046 address: SocketAddr, -7047 ) -> Result<(), n0_nat_traversal::Error> { -7048 if let Some(added) = self.n0_nat_traversal.add_local_address(address)? { -7049 self.spaces[SpaceId::Data].pending.add_address.insert(added); -7050 }; -7051 Ok(()) -7052 } -7053 -7054 /// Removes an address the endpoing no longer considers reachable for nat traversal -7055 /// -7056 /// Addresses not present in the set will be silently ignored. -7057 pub fn remove_nat_traversal_address( -7058 &mut self, -7059 address: SocketAddr, -7060 ) -> Result<(), n0_nat_traversal::Error> { -7061 if let Some(removed) = self.n0_nat_traversal.remove_local_address(address)? { -7062 self.spaces[SpaceId::Data] -7063 .pending -7064 .remove_address -7065 .insert(removed); -7066 } -7067 Ok(()) -7068 } -7069 -7070 /// Get the current local nat traversal addresses -7071 pub fn get_local_nat_traversal_addresses( -7072 &self, -7073 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -7074 self.n0_nat_traversal.get_local_nat_traversal_addresses() -7075 } -7076 -7077 /// Get the currently advertised nat traversal addresses by the server -7078 pub fn get_remote_nat_traversal_addresses( -7079 &self, -7080 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -7081 Ok(self -7082 .n0_nat_traversal -7083 .client_side()? -7084 .get_remote_nat_traversal_addresses()) -7085 } -7086 -7087 /// Initiates a new nat traversal round -7088 /// -7089 /// A nat traversal round involves advertising the client's local addresses in -7090 /// `REACH_OUT` frames, and initiating probing of the known remote addresses. When a new -7091 /// round is initiated, the previous one is cancelled. -7092 /// -7093 /// For all probes that succeed, if any, a new path will be opened on the successful -7094 /// 4-tuple. -7095 /// -7096 /// Returns the server addresses that are now being probed. If addresses fail due to -7097 /// spurious errors, these might succeed later and not be returned in this set. -7098 pub fn initiate_nat_traversal_round( -7099 &mut self, -7100 now: Instant, -7101 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { -7102 if self.state.is_closed() { -7103 return Err(n0_nat_traversal::Error::Closed); -7104 } -7105 -7106 let ipv6 = self.is_ipv6(); -7107 let client_state = self.n0_nat_traversal.client_side_mut()?; -7108 let (mut reach_out_frames, probed_addrs) = -7109 client_state.initiate_nat_traversal_round(ipv6)?; -7110 if !probed_addrs.is_empty() { -7111 let delay = RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; -7112 self.timers.set( -7113 Timer::Conn(ConnTimer::NatTraversalProbeRetry), -7114 now + delay, -7115 self.qlog.with_time(now), -7116 ); -7117 } -7118 -7119 self.spaces[SpaceId::Data] -7120 .pending -7121 .reach_out -7122 .append(&mut reach_out_frames); -7123 -7124 Ok(probed_addrs) -7125 } -7126 -7127 /// Whether the handshake is considered **confirmed**. -7128 /// -7129 /// <https://www.rfc-editor.org/rfc/rfc9001#section-4.1.2> defines a handshake to be -7130 /// confirmed when you know the peer successfully received and successfully processed -7131 /// your TLS Finished message. -7132 /// -7133 /// Implementation-wise this is the point at which the handshake crypto keys are -7134 /// discarded. So we can use this to know if the handshake is confirmed. -7135 fn is_handshake_confirmed(&self) -> bool { -7136 !self.is_handshaking() && !self.crypto_state.has_keys(EncryptionLevel::Handshake) -7137 } -7138} -7139 -7140impl fmt::Debug for Connection { -7141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -7142 f.debug_struct("Connection") -7143 .field("handshake_cid", &self.handshake_cid) -7144 .finish() -7145 } -7146} -7147 -7148/// Hints when the caller identifies a network change. -7149pub trait NetworkChangeHint: std::fmt::Debug + 'static { -7150 /// Inform the connection if a path may recover after a network change. -7151 /// -7152 /// After network changes, paths may not be recoverable. In this case, waiting for the path to -7153 /// become idle may take longer than what is desirable. If [`Self::is_path_recoverable`] -7154 /// returns `false`, a multipath-enabled, client-side connection will establish a new path to -7155 /// the same remote, closing the current one, instead of migrating the path. -7156 /// -7157 /// Paths that are deemed recoverable will simply be sent a PING for a liveness check. -7158 fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool; -7159} -7160 -7161/// Return value for [`Connection::poll_transmit_path_space`]. -7162#[derive(Debug)] -7163enum PollPathSpaceStatus { -7164 /// Nothing to send in the space, nothing was written into the [`TransmitBuf`]. -7165 NothingToSend { -7166 /// If true there was data to send but congestion control did not allow so. -7167 congestion_blocked: bool, -7168 }, -7169 /// One or more packets have been written into the [`TransmitBuf`]. -7170 WrotePacket { -7171 /// The highest packet number. -7172 last_packet_number: u64, -7173 /// Whether to pad an already started datagram in the next packet. -7174 /// -7175 /// When packets in Initial, 0-RTT or Handshake packet do not fill the entire -7176 /// datagram they may decide to coalesce with the next packet from a higher -7177 /// encryption level on the same path. But the earlier packet may require specific -7178 /// size requirements for the datagram they are sent in. -7179 /// -7180 /// If a space did not complete the datagram, they use this to request the correct -7181 /// padding in the final packet of the datagram so that the final datagram will have -7182 /// the correct size. -7183 /// -7184 /// If a space did fill an entire datagram, it leaves this to the default of -7185 /// [`PadDatagram::No`]. -7186 pad_datagram: PadDatagram, -7187 }, -7188 /// Send the contents of the transmit immediately. -7189 /// -7190 /// Packets were written and the GSO batch must end now, regardless from whether higher -7191 /// spaces still have frames to write. This is used when the last datagram written would -7192 /// require too much padding to continue a GSO batch, which would waste space on the -7193 /// wire. -7194 Send { -7195 /// The highest packet number written into the transmit. -7196 last_packet_number: u64, -7197 }, -7198} -7199 -7200/// Information used to decide what frames to schedule into which packets. -7201/// -7202/// Primarily used by [`Connection::poll_transmit_on_path`] and the functions that help -7203/// building packets for it: [`Connection::poll_transmit_path_space`] and -7204/// [`Connection::populate_packet`]. -7205#[derive(Debug, Copy, Clone)] -7206struct PathSchedulingInfo { -7207 /// Whether the path is abandoned. -7208 /// -7209 /// Note that a path that is abandoned but still has CIDs can still send a packet. After -7210 /// sending that packet the CIDs issued by the remote have to be considered retired as -7211 /// well. -7212 is_abandoned: bool, -7213 /// Whether the path may send [`SpaceKind::Data`] frames. -7214 /// -7215 /// Some paths should only send frames from [`SendableFrames::space_specific`]. All other -7216 /// frames are essentially frames that can be sent on any [`SpaceKind::Data`] space. For -7217 /// those we want to respect packet scheduling rules however. -7218 /// -7219 /// Roughly speaking data frames are only sent on spaces that have CIDs, are not -7220 /// abandoned and have no *better* spaces. However see to comments where this is -7221 /// populated for the exact packet scheduling implementation. -7222 /// -7223 /// This essentially marks this paths as the best validated space ID. Except during -7224 /// the handshake in which case it does not need to be validated. Several paths could be -7225 /// equally good and all have this set to `true`, in that case packet scheduling can -7226 /// choose which path to use. Currently it chooses the lowest path that is not -7227 /// congestion blocked. -7228 /// -7229 /// Note that once in the closed or draining states this will never be true. -7230 may_send_data: bool, -7231 /// Whether the path may send a CONNECTION_CLOSE frame. -7232 /// -7233 /// This essentially marks this path as the best validated space ID with a fallback -7234 /// to unvalidated spaces if there are no validated spaces. Like for -7235 /// [`Self::may_send_data`] other paths could be equally good. -7236 may_send_close: bool, -7237 may_self_abandon: bool, -7238} -7239 -7240#[derive(Debug, Copy, Clone, PartialEq, Eq)] -7241enum PathBlocked { -7242 No, -7243 AntiAmplification, -7244 Congestion, -7245 Pacing, -7246} -7247 -7248/// Fields of `Connection` specific to it being client-side or server-side -7249enum ConnectionSide { -7250 Client { -7251 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded -7252 token: Bytes, -7253 token_store: Arc<dyn TokenStore>, -7254 server_name: String, -7255 }, -7256 Server { -7257 server_config: Arc<ServerConfig>, -7258 }, -7259} -7260 -7261impl ConnectionSide { -7262 fn is_client(&self) -> bool { -7263 self.side().is_client() -7264 } -7265 -7266 fn is_server(&self) -> bool { -7267 self.side().is_server() -7268 } -7269 -7270 fn side(&self) -> Side { -7271 match *self { -7272 Self::Client { .. } => Side::Client, -7273 Self::Server { .. } => Side::Server, -7274 } -7275 } -7276} -7277 -7278impl From<SideArgs> for ConnectionSide { -7279 fn from(side: SideArgs) -> Self { -7280 match side { -7281 SideArgs::Client { -7282 token_store, -7283 server_name, -7284 } => Self::Client { -7285 token: token_store.take(&server_name).unwrap_or_default(), -7286 token_store, -7287 server_name, -7288 }, -7289 SideArgs::Server { -7290 server_config, -7291 pref_addr_cid: _, -7292 path_validated: _, -7293 } => Self::Server { server_config }, -7294 } -7295 } -7296} -7297 -7298/// Parameters to `Connection::new` specific to it being client-side or server-side -7299pub(crate) enum SideArgs { -7300 Client { -7301 token_store: Arc<dyn TokenStore>, -7302 server_name: String, -7303 }, -7304 Server { -7305 server_config: Arc<ServerConfig>, -7306 pref_addr_cid: Option<ConnectionId>, -7307 path_validated: bool, -7308 }, -7309} -7310 -7311impl SideArgs { -7312 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> { -7313 match *self { -7314 Self::Client { .. } => None, -7315 Self::Server { pref_addr_cid, .. } => pref_addr_cid, -7316 } -7317 } -7318 -7319 pub(crate) fn path_validated(&self) -> bool { -7320 match *self { -7321 Self::Client { .. } => true, -7322 Self::Server { path_validated, .. } => path_validated, -7323 } -7324 } +6935 /// Storage size required for the largest packet that can be transmitted on all currently +6936 /// available paths +6937 /// +6938 /// Buffers passed to [`Connection::poll_transmit`] should be at least this large. +6939 /// +6940 /// When multipath is enabled, this value is the minimum MTU across all available paths. +6941 pub fn current_mtu(&self) -> u16 { +6942 self.paths +6943 .iter() +6944 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id)) +6945 .map(|(_path_id, path_state)| path_state.data.current_mtu()) +6946 .min() +6947 .unwrap_or(INITIAL_MTU) +6948 } +6949 +6950 /// Size of non-frame data for a 1-RTT packet +6951 /// +6952 /// Quantifies space consumed by the QUIC header and AEAD tag. All other bytes in a packet are +6953 /// frames. Changes if the length of the remote connection ID changes, which is expected to be +6954 /// rare. If `pn` is specified, may additionally change unpredictably due to variations in +6955 /// latency and packet loss. +6956 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize { +6957 let pn_len = PacketNumber::new( +6958 pn, +6959 self.spaces[SpaceId::Data] +6960 .for_path(path) +6961 .largest_acked_packet_pn +6962 .unwrap_or(0), +6963 ) +6964 .len(); +6965 +6966 // 1 byte for flags +6967 1 + self +6968 .remote_cids +6969 .get(&path) +6970 .map(|cids| cids.active().len()) +6971 .unwrap_or(20) // Max CID len in QUIC v1 +6972 + pn_len +6973 + self.tag_len_1rtt() +6974 } +6975 +6976 fn predict_1rtt_overhead_no_pn(&self) -> usize { +6977 let pn_len = 4; +6978 +6979 let cid_len = self +6980 .remote_cids +6981 .values() +6982 .map(|cids| cids.active().len()) +6983 .max() +6984 .unwrap_or(20); // Max CID len in QUIC v1 +6985 +6986 // 1 byte for flags +6987 1 + cid_len + pn_len + self.tag_len_1rtt() +6988 } +6989 +6990 fn tag_len_1rtt(&self) -> usize { +6991 // encryption_keys for Data space returns 1-RTT keys if available, otherwise 0-RTT keys +6992 let packet_crypto = self +6993 .crypto_state +6994 .encryption_keys(SpaceKind::Data, self.side.side()) +6995 .map(|(_header, packet, _level)| packet); +6996 // If neither Data nor 0-RTT keys are available, make a reasonable tag length guess. As of +6997 // this writing, all QUIC cipher suites use 16-byte tags. We could return `None` instead, +6998 // but that would needlessly prevent sending datagrams during 0-RTT. +6999 packet_crypto.map_or(16, |x| x.tag_len()) +7000 } +7001 +7002 /// Mark the path as validated, and enqueue NEW_TOKEN frames to be sent as appropriate +7003 fn on_path_validated(&mut self, path_id: PathId) { +7004 self.path_data_mut(path_id).validated = true; +7005 let ConnectionSide::Server { server_config } = &self.side else { +7006 return; +7007 }; +7008 let network_path = self.path_data(path_id).network_path; +7009 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens; +7010 new_tokens.clear(); +7011 for _ in 0..server_config.validation_token.sent { +7012 new_tokens.push(network_path); +7013 } +7014 } +7015 +7016 /// Handle new path status information: PATH_STATUS_AVAILABLE, PATH_STATUS_BACKUP +7017 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) { +7018 if let Some(path) = self.paths.get_mut(&path_id) { +7019 path.data.status.remote_update(status, status_seq_no); +7020 } else { +7021 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id); +7022 } +7023 self.events.push_back( +7024 PathEvent::RemoteStatus { +7025 id: path_id, +7026 status, +7027 } +7028 .into(), +7029 ); +7030 } +7031 +7032 /// Returns the maximum [`PathId`] to be used for sending in this connection. +7033 /// +7034 /// This is calculated as minimum between the local and remote's maximums when multipath is +7035 /// enabled, or `None` when disabled. +7036 /// +7037 /// For data that's received, we should use [`Self::local_max_path_id`] instead. +7038 /// The reasoning is that the remote might already have updated to its own newer +7039 /// [`Self::max_path_id`] after sending out a `MAX_PATH_ID` frame, but it got re-ordered. +7040 fn max_path_id(&self) -> Option<PathId> { +7041 if self.is_multipath_negotiated() { +7042 Some(self.remote_max_path_id.min(self.local_max_path_id)) +7043 } else { +7044 None +7045 } +7046 } +7047 +7048 /// Returns whether this connection has a socket that supports IPv6. +7049 /// +7050 /// TODO(matheus23): This is related to noq endpoint state's `ipv6` bool. We should move that info +7051 /// here instead of trying to hack around not knowing it exactly. +7052 fn is_ipv6(&self) -> bool { +7053 self.paths +7054 .values() +7055 .any(|p| p.data.network_path.remote.is_ipv6()) +7056 } +7057 +7058 /// Add addresses the local endpoint considers are reachable for nat traversal. +7059 pub fn add_nat_traversal_address( +7060 &mut self, +7061 address: SocketAddr, +7062 ) -> Result<(), n0_nat_traversal::Error> { +7063 if let Some(added) = self.n0_nat_traversal.add_local_address(address)? { +7064 self.spaces[SpaceId::Data].pending.add_address.insert(added); +7065 }; +7066 Ok(()) +7067 } +7068 +7069 /// Removes an address the endpoing no longer considers reachable for nat traversal +7070 /// +7071 /// Addresses not present in the set will be silently ignored. +7072 pub fn remove_nat_traversal_address( +7073 &mut self, +7074 address: SocketAddr, +7075 ) -> Result<(), n0_nat_traversal::Error> { +7076 if let Some(removed) = self.n0_nat_traversal.remove_local_address(address)? { +7077 self.spaces[SpaceId::Data] +7078 .pending +7079 .remove_address +7080 .insert(removed); +7081 } +7082 Ok(()) +7083 } +7084 +7085 /// Get the current local nat traversal addresses +7086 pub fn get_local_nat_traversal_addresses( +7087 &self, +7088 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +7089 self.n0_nat_traversal.get_local_nat_traversal_addresses() +7090 } +7091 +7092 /// Get the currently advertised nat traversal addresses by the server +7093 pub fn get_remote_nat_traversal_addresses( +7094 &self, +7095 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +7096 Ok(self +7097 .n0_nat_traversal +7098 .client_side()? +7099 .get_remote_nat_traversal_addresses()) +7100 } +7101 +7102 /// Initiates a new nat traversal round +7103 /// +7104 /// A nat traversal round involves advertising the client's local addresses in +7105 /// `REACH_OUT` frames, and initiating probing of the known remote addresses. When a new +7106 /// round is initiated, the previous one is cancelled. +7107 /// +7108 /// For all probes that succeed, if any, a new path will be opened on the successful +7109 /// 4-tuple. +7110 /// +7111 /// Returns the server addresses that are now being probed. If addresses fail due to +7112 /// spurious errors, these might succeed later and not be returned in this set. +7113 pub fn initiate_nat_traversal_round( +7114 &mut self, +7115 now: Instant, +7116 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> { +7117 if self.state.is_closed() { +7118 return Err(n0_nat_traversal::Error::Closed); +7119 } +7120 +7121 let ipv6 = self.is_ipv6(); +7122 let client_state = self.n0_nat_traversal.client_side_mut()?; +7123 let (mut reach_out_frames, probed_addrs) = +7124 client_state.initiate_nat_traversal_round(ipv6)?; +7125 if !probed_addrs.is_empty() { +7126 let delay = RttEstimator::new(self.config.initial_rtt).pto_base() * 2 / 3; +7127 self.timers.set( +7128 Timer::Conn(ConnTimer::NatTraversalProbeRetry), +7129 now + delay, +7130 self.qlog.with_time(now), +7131 ); +7132 } +7133 +7134 self.spaces[SpaceId::Data] +7135 .pending +7136 .reach_out +7137 .append(&mut reach_out_frames); +7138 +7139 Ok(probed_addrs) +7140 } +7141 +7142 /// Whether the handshake is considered **confirmed**. +7143 /// +7144 /// <https://www.rfc-editor.org/rfc/rfc9001#section-4.1.2> defines a handshake to be +7145 /// confirmed when you know the peer successfully received and successfully processed +7146 /// your TLS Finished message. +7147 /// +7148 /// Implementation-wise this is the point at which the handshake crypto keys are +7149 /// discarded. So we can use this to know if the handshake is confirmed. +7150 fn is_handshake_confirmed(&self) -> bool { +7151 !self.is_handshaking() && !self.crypto_state.has_keys(EncryptionLevel::Handshake) +7152 } +7153} +7154 +7155impl fmt::Debug for Connection { +7156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +7157 f.debug_struct("Connection") +7158 .field("handshake_cid", &self.handshake_cid) +7159 .finish() +7160 } +7161} +7162 +7163/// Hints when the caller identifies a network change. +7164pub trait NetworkChangeHint: std::fmt::Debug + 'static { +7165 /// Inform the connection if a path may recover after a network change. +7166 /// +7167 /// After network changes, paths may not be recoverable. In this case, waiting for the path to +7168 /// become idle may take longer than what is desirable. If [`Self::is_path_recoverable`] +7169 /// returns `false`, a multipath-enabled, client-side connection will establish a new path to +7170 /// the same remote, closing the current one, instead of migrating the path. +7171 /// +7172 /// Paths that are deemed recoverable will simply be sent a PING for a liveness check. +7173 fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool; +7174} +7175 +7176/// Return value for [`Connection::poll_transmit_path_space`]. +7177#[derive(Debug)] +7178enum PollPathSpaceStatus { +7179 /// Nothing to send in the space, nothing was written into the [`TransmitBuf`]. +7180 NothingToSend { +7181 /// If true there was data to send but congestion control did not allow so. +7182 congestion_blocked: bool, +7183 }, +7184 /// One or more packets have been written into the [`TransmitBuf`]. +7185 WrotePacket { +7186 /// The highest packet number. +7187 last_packet_number: u64, +7188 /// Whether to pad an already started datagram in the next packet. +7189 /// +7190 /// When packets in Initial, 0-RTT or Handshake packet do not fill the entire +7191 /// datagram they may decide to coalesce with the next packet from a higher +7192 /// encryption level on the same path. But the earlier packet may require specific +7193 /// size requirements for the datagram they are sent in. +7194 /// +7195 /// If a space did not complete the datagram, they use this to request the correct +7196 /// padding in the final packet of the datagram so that the final datagram will have +7197 /// the correct size. +7198 /// +7199 /// If a space did fill an entire datagram, it leaves this to the default of +7200 /// [`PadDatagram::No`]. +7201 pad_datagram: PadDatagram, +7202 }, +7203 /// Send the contents of the transmit immediately. +7204 /// +7205 /// Packets were written and the GSO batch must end now, regardless from whether higher +7206 /// spaces still have frames to write. This is used when the last datagram written would +7207 /// require too much padding to continue a GSO batch, which would waste space on the +7208 /// wire. +7209 Send { +7210 /// The highest packet number written into the transmit. +7211 last_packet_number: u64, +7212 }, +7213} +7214 +7215/// Information used to decide what frames to schedule into which packets. +7216/// +7217/// Primarily used by [`Connection::poll_transmit_on_path`] and the functions that help +7218/// building packets for it: [`Connection::poll_transmit_path_space`] and +7219/// [`Connection::populate_packet`]. +7220#[derive(Debug, Copy, Clone)] +7221struct PathSchedulingInfo { +7222 /// Whether the path is abandoned. +7223 /// +7224 /// Note that a path that is abandoned but still has CIDs can still send a packet. After +7225 /// sending that packet the CIDs issued by the remote have to be considered retired as +7226 /// well. +7227 is_abandoned: bool, +7228 /// Whether the path may send [`SpaceKind::Data`] frames. +7229 /// +7230 /// Some paths should only send frames from [`SendableFrames::space_specific`]. All other +7231 /// frames are essentially frames that can be sent on any [`SpaceKind::Data`] space. For +7232 /// those we want to respect packet scheduling rules however. +7233 /// +7234 /// Roughly speaking data frames are only sent on spaces that have CIDs, are not +7235 /// abandoned and have no *better* spaces. However see to comments where this is +7236 /// populated for the exact packet scheduling implementation. +7237 /// +7238 /// This essentially marks this paths as the best validated space ID. Except during +7239 /// the handshake in which case it does not need to be validated. Several paths could be +7240 /// equally good and all have this set to `true`, in that case packet scheduling can +7241 /// choose which path to use. Currently it chooses the lowest path that is not +7242 /// congestion blocked. +7243 /// +7244 /// Note that once in the closed or draining states this will never be true. +7245 may_send_data: bool, +7246 /// Whether the path may send a CONNECTION_CLOSE frame. +7247 /// +7248 /// This essentially marks this path as the best validated space ID with a fallback +7249 /// to unvalidated spaces if there are no validated spaces. Like for +7250 /// [`Self::may_send_data`] other paths could be equally good. +7251 may_send_close: bool, +7252 may_self_abandon: bool, +7253} +7254 +7255#[derive(Debug, Copy, Clone, PartialEq, Eq)] +7256enum PathBlocked { +7257 No, +7258 AntiAmplification, +7259 Congestion, +7260 Pacing, +7261} +7262 +7263/// Fields of `Connection` specific to it being client-side or server-side +7264enum ConnectionSide { +7265 Client { +7266 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded +7267 token: Bytes, +7268 token_store: Arc<dyn TokenStore>, +7269 server_name: String, +7270 }, +7271 Server { +7272 server_config: Arc<ServerConfig>, +7273 }, +7274} +7275 +7276impl ConnectionSide { +7277 fn is_client(&self) -> bool { +7278 self.side().is_client() +7279 } +7280 +7281 fn is_server(&self) -> bool { +7282 self.side().is_server() +7283 } +7284 +7285 fn side(&self) -> Side { +7286 match *self { +7287 Self::Client { .. } => Side::Client, +7288 Self::Server { .. } => Side::Server, +7289 } +7290 } +7291} +7292 +7293impl From<SideArgs> for ConnectionSide { +7294 fn from(side: SideArgs) -> Self { +7295 match side { +7296 SideArgs::Client { +7297 token_store, +7298 server_name, +7299 } => Self::Client { +7300 token: token_store.take(&server_name).unwrap_or_default(), +7301 token_store, +7302 server_name, +7303 }, +7304 SideArgs::Server { +7305 server_config, +7306 pref_addr_cid: _, +7307 path_validated: _, +7308 } => Self::Server { server_config }, +7309 } +7310 } +7311} +7312 +7313/// Parameters to `Connection::new` specific to it being client-side or server-side +7314pub(crate) enum SideArgs { +7315 Client { +7316 token_store: Arc<dyn TokenStore>, +7317 server_name: String, +7318 }, +7319 Server { +7320 server_config: Arc<ServerConfig>, +7321 pref_addr_cid: Option<ConnectionId>, +7322 path_validated: bool, +7323 }, +7324} 7325 -7326 pub(crate) fn side(&self) -> Side { -7327 match *self { -7328 Self::Client { .. } => Side::Client, -7329 Self::Server { .. } => Side::Server, -7330 } -7331 } -7332} +7326impl SideArgs { +7327 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> { +7328 match *self { +7329 Self::Client { .. } => None, +7330 Self::Server { pref_addr_cid, .. } => pref_addr_cid, +7331 } +7332 } 7333 -7334/// Reasons why a connection might be lost -7335#[derive(Debug, Error, Clone, PartialEq, Eq)] -7336pub enum ConnectionError { -7337 /// The peer doesn't implement any supported version -7338 #[error("peer doesn't implement any supported version")] -7339 VersionMismatch, -7340 /// The peer violated the QUIC specification as understood by this implementation -7341 #[error(transparent)] -7342 TransportError(#[from] TransportError), -7343 /// The peer's QUIC stack aborted the connection automatically -7344 #[error("aborted by peer: {0}")] -7345 ConnectionClosed(frame::ConnectionClose), -7346 /// The peer closed the connection -7347 #[error("closed by peer: {0}")] -7348 ApplicationClosed(frame::ApplicationClose), -7349 /// The peer is unable to continue processing this connection, usually due to having restarted -7350 #[error("reset by peer")] -7351 Reset, -7352 /// Communication with the peer has lapsed for longer than the negotiated idle timeout -7353 /// -7354 /// If neither side is sending keep-alives, a connection will time out after a long enough idle -7355 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`] -7356 /// and [`TransportConfig::keep_alive_interval()`]. -7357 #[error("timed out")] -7358 TimedOut, -7359 /// The local application closed the connection -7360 #[error("closed")] -7361 LocallyClosed, -7362 /// The connection could not be created because not enough of the CID space is available -7363 /// -7364 /// Try using longer connection IDs. -7365 #[error("CIDs exhausted")] -7366 CidsExhausted, -7367} -7368 -7369impl From<Close> for ConnectionError { -7370 fn from(x: Close) -> Self { -7371 match x { -7372 Close::Connection(reason) => Self::ConnectionClosed(reason), -7373 Close::Application(reason) => Self::ApplicationClosed(reason), -7374 } -7375 } -7376} -7377 -7378// For compatibility with API consumers -7379impl From<ConnectionError> for io::Error { -7380 fn from(x: ConnectionError) -> Self { -7381 use ConnectionError::*; -7382 let kind = match x { -7383 TimedOut => io::ErrorKind::TimedOut, -7384 Reset => io::ErrorKind::ConnectionReset, -7385 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted, -7386 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => { -7387 io::ErrorKind::Other -7388 } -7389 }; -7390 Self::new(kind, x) -7391 } -7392} -7393 -7394/// Errors that might trigger a path being closed -7395// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API -7396#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)] -7397pub enum PathError { -7398 /// The extension was not negotiated with the peer -7399 #[error("multipath extension not negotiated")] -7400 MultipathNotNegotiated, -7401 /// Paths can only be opened client-side -7402 #[error("the server side may not open a path")] -7403 ServerSideNotAllowed, -7404 /// Current limits do not allow us to open more paths -7405 #[error("maximum number of concurrent paths reached")] -7406 MaxPathIdReached, -7407 /// No remote CIDs available to open a new path -7408 #[error("remoted CIDs exhausted")] -7409 RemoteCidsExhausted, -7410 /// Path could not be validated and will be abandoned -7411 #[error("path validation failed")] -7412 ValidationFailed, -7413 /// The remote address for the path is not supported by the endpoint -7414 #[error("invalid remote address")] -7415 InvalidRemoteAddress(SocketAddr), -7416} -7417 -7418/// Errors triggered when abandoning a path -7419#[derive(Debug, Error, Clone, Eq, PartialEq)] -7420pub enum ClosePathError { -7421 /// Multipath is not negotiated -7422 #[error("Multipath extension not negotiated")] -7423 MultipathNotNegotiated, -7424 /// The path is already closed or was never opened -7425 #[error("closed path")] -7426 ClosedPath, -7427 /// Cannot close the last remaining open path via the local API. -7428 /// -7429 /// Use [`Connection::close`] to end the connection instead. -7430 #[error("last open path")] -7431 LastOpenPath, -7432} -7433 -7434/// Error when the multipath extension was not negotiated, but attempted to be used. -7435#[derive(Debug, Error, Clone, Copy)] -7436#[error("Multipath extension not negotiated")] -7437pub struct MultipathNotNegotiated { -7438 _private: (), -7439} -7440 -7441/// Events of interest to the application -7442#[derive(Debug)] -7443pub enum Event { -7444 /// The connection's handshake data is ready -7445 HandshakeDataReady, -7446 /// The connection was successfully established -7447 Connected, -7448 /// The TLS handshake was confirmed -7449 HandshakeConfirmed, -7450 /// The connection was lost -7451 /// -7452 /// Emitted when the connection is closed due to an error, a timeout, or the peer closing it. -7453 /// This is **not** emitted when the local application closes the connection via -7454 /// [`Connection::close()`](crate::Connection::close). In that case, pending operations will -7455 /// fail with [`ConnectionError::LocallyClosed`]. -7456 ConnectionLost { -7457 /// Reason that the connection was closed -7458 reason: ConnectionError, -7459 }, -7460 /// Stream events -7461 Stream(StreamEvent), -7462 /// One or more application datagrams have been received -7463 DatagramReceived, -7464 /// One or more application datagrams have been sent after blocking -7465 DatagramsUnblocked, -7466 /// (Multi)Path events -7467 Path(PathEvent), -7468 /// n0's nat traversal events -7469 NatTraversal(n0_nat_traversal::Event), -7470} -7471 -7472impl From<PathEvent> for Event { -7473 fn from(source: PathEvent) -> Self { -7474 Self::Path(source) -7475 } -7476} -7477 -7478fn get_max_ack_delay(params: &TransportParameters) -> Duration { -7479 Duration::from_micros(params.max_ack_delay.0 * 1000) -7480} -7481 -7482/// Prevents overflow and improves behavior in extreme circumstances. -7483const MAX_BACKOFF_EXPONENT: u32 = 16; -7484 -7485/// The max interval between successive tail-loss probes. -7486/// -7487/// This is the "normal" value we use. -7488const MAX_PTO_INTERVAL: Duration = Duration::from_secs(2); -7489 -7490/// The idle time, below which we use the shorter [`MAX_PTO_FAST_INTERVAL`]. -7491const MIN_IDLE_FOR_FAST_PTO: Duration = Duration::from_secs(25); +7334 pub(crate) fn path_validated(&self) -> bool { +7335 match *self { +7336 Self::Client { .. } => true, +7337 Self::Server { path_validated, .. } => path_validated, +7338 } +7339 } +7340 +7341 pub(crate) fn side(&self) -> Side { +7342 match *self { +7343 Self::Client { .. } => Side::Client, +7344 Self::Server { .. } => Side::Server, +7345 } +7346 } +7347} +7348 +7349/// Reasons why a connection might be lost +7350#[derive(Debug, Error, Clone, PartialEq, Eq)] +7351pub enum ConnectionError { +7352 /// The peer doesn't implement any supported version +7353 #[error("peer doesn't implement any supported version")] +7354 VersionMismatch, +7355 /// The peer violated the QUIC specification as understood by this implementation +7356 #[error(transparent)] +7357 TransportError(#[from] TransportError), +7358 /// The peer's QUIC stack aborted the connection automatically +7359 #[error("aborted by peer: {0}")] +7360 ConnectionClosed(frame::ConnectionClose), +7361 /// The peer closed the connection +7362 #[error("closed by peer: {0}")] +7363 ApplicationClosed(frame::ApplicationClose), +7364 /// The peer is unable to continue processing this connection, usually due to having restarted +7365 #[error("reset by peer")] +7366 Reset, +7367 /// Communication with the peer has lapsed for longer than the negotiated idle timeout +7368 /// +7369 /// If neither side is sending keep-alives, a connection will time out after a long enough idle +7370 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`] +7371 /// and [`TransportConfig::keep_alive_interval()`]. +7372 #[error("timed out")] +7373 TimedOut, +7374 /// The local application closed the connection +7375 #[error("closed")] +7376 LocallyClosed, +7377 /// The connection could not be created because not enough of the CID space is available +7378 /// +7379 /// Try using longer connection IDs. +7380 #[error("CIDs exhausted")] +7381 CidsExhausted, +7382} +7383 +7384impl From<Close> for ConnectionError { +7385 fn from(x: Close) -> Self { +7386 match x { +7387 Close::Connection(reason) => Self::ConnectionClosed(reason), +7388 Close::Application(reason) => Self::ApplicationClosed(reason), +7389 } +7390 } +7391} +7392 +7393// For compatibility with API consumers +7394impl From<ConnectionError> for io::Error { +7395 fn from(x: ConnectionError) -> Self { +7396 use ConnectionError::*; +7397 let kind = match x { +7398 TimedOut => io::ErrorKind::TimedOut, +7399 Reset => io::ErrorKind::ConnectionReset, +7400 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted, +7401 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => { +7402 io::ErrorKind::Other +7403 } +7404 }; +7405 Self::new(kind, x) +7406 } +7407} +7408 +7409/// Errors that might trigger a path being closed +7410// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API +7411#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)] +7412pub enum PathError { +7413 /// The extension was not negotiated with the peer +7414 #[error("multipath extension not negotiated")] +7415 MultipathNotNegotiated, +7416 /// Paths can only be opened client-side +7417 #[error("the server side may not open a path")] +7418 ServerSideNotAllowed, +7419 /// Current limits do not allow us to open more paths +7420 #[error("maximum number of concurrent paths reached")] +7421 MaxPathIdReached, +7422 /// No remote CIDs available to open a new path +7423 #[error("remoted CIDs exhausted")] +7424 RemoteCidsExhausted, +7425 /// Path could not be validated and will be abandoned +7426 #[error("path validation failed")] +7427 ValidationFailed, +7428 /// The remote address for the path is not supported by the endpoint +7429 #[error("invalid remote address")] +7430 InvalidRemoteAddress(SocketAddr), +7431} +7432 +7433/// Errors triggered when abandoning a path +7434#[derive(Debug, Error, Clone, Eq, PartialEq)] +7435pub enum ClosePathError { +7436 /// Multipath is not negotiated +7437 #[error("Multipath extension not negotiated")] +7438 MultipathNotNegotiated, +7439 /// The path is already closed or was never opened +7440 #[error("closed path")] +7441 ClosedPath, +7442 /// Cannot close the last remaining open path via the local API. +7443 /// +7444 /// Use [`Connection::close`] to end the connection instead. +7445 #[error("last open path")] +7446 LastOpenPath, +7447} +7448 +7449/// Error when the multipath extension was not negotiated, but attempted to be used. +7450#[derive(Debug, Error, Clone, Copy)] +7451#[error("Multipath extension not negotiated")] +7452pub struct MultipathNotNegotiated { +7453 _private: (), +7454} +7455 +7456/// Events of interest to the application +7457#[derive(Debug)] +7458pub enum Event { +7459 /// The connection's handshake data is ready +7460 HandshakeDataReady, +7461 /// The connection was successfully established +7462 Connected, +7463 /// The TLS handshake was confirmed +7464 HandshakeConfirmed, +7465 /// The connection was lost +7466 /// +7467 /// Emitted when the connection is closed due to an error, a timeout, or the peer closing it. +7468 /// This is **not** emitted when the local application closes the connection via +7469 /// [`Connection::close()`](crate::Connection::close). In that case, pending operations will +7470 /// fail with [`ConnectionError::LocallyClosed`]. +7471 ConnectionLost { +7472 /// Reason that the connection was closed +7473 reason: ConnectionError, +7474 }, +7475 /// Stream events +7476 Stream(StreamEvent), +7477 /// One or more application datagrams have been received +7478 DatagramReceived, +7479 /// One or more application datagrams have been sent after blocking +7480 DatagramsUnblocked, +7481 /// (Multi)Path events +7482 Path(PathEvent), +7483 /// n0's nat traversal events +7484 NatTraversal(n0_nat_traversal::Event), +7485} +7486 +7487impl From<PathEvent> for Event { +7488 fn from(source: PathEvent) -> Self { +7489 Self::Path(source) +7490 } +7491} 7492 -7493/// The max interval between successive tail-loss probes with short idle times. -7494/// -7495/// If the path or connection idle time is less than [`MIN_IDLE_FOR_FAST_PTO`] then we use -7496/// this value to ensure we have plenty of retransmits before we reach the idle time. -7497const MAX_PTO_FAST_INTERVAL: Duration = Duration::from_secs(1); -7498 -7499/// The RTT threshold above which we cap the PTO interval to 1.5 * smoothed_rtt -7500/// -7501/// This is RTT time above which 1.5 * RTT > [`MAX_PTO_INTERVAL`], for these links we want -7502/// to extend the interval between tail-loss probes to not fill the entire pipe with them. -7503const SLOW_RTT_THRESHOLD: Duration = -7504 Duration::from_millis((MAX_PTO_INTERVAL.as_millis() as u64 * 2) / 3); -7505 -7506/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag -7507/// -7508/// This must be at least as large as the header for a well-formed empty packet to be coalesced, -7509/// plus some space for frames. We only care about handshake headers because short header packets -7510/// necessarily have smaller headers, and initial packets are only ever the first packet in a -7511/// datagram (because we coalesce in ascending packet space order and the only reason to split a -7512/// packet is when packet space changes). -7513const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32; -7514 -7515/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header -7516/// -7517/// Excludes packet-type-specific fields such as packet number or Initial token -7518// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid + -7519// scid len + scid + length + pn -7520const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize = -7521 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4; -7522 -7523#[derive(Default)] -7524struct SentFrames { -7525 retransmits: ThinRetransmits, -7526 /// The packet number of the largest acknowledged packet for each path -7527 largest_acked: FxHashMap<PathId, u64>, -7528 stream_frames: StreamMetaVec, -7529 /// Whether the packet contains non-retransmittable frames (like datagrams) -7530 non_retransmits: bool, -7531 /// If the datagram containing these frames should be padded to the min MTU -7532 requires_padding: bool, -7533} -7534 -7535impl SentFrames { -7536 /// Returns whether the packet contains only ACKs -7537 fn is_ack_only(&self, streams: &StreamsState) -> bool { -7538 !self.largest_acked.is_empty() -7539 && !self.non_retransmits -7540 && self.stream_frames.is_empty() -7541 && self.retransmits.is_empty(streams) -7542 } -7543 -7544 fn retransmits_mut(&mut self) -> &mut Retransmits { -7545 self.retransmits.get_or_create() -7546 } -7547 -7548 fn record_sent_frame(&mut self, frame: frame::EncodableFrame<'_>) { -7549 use frame::EncodableFrame::*; -7550 match frame { -7551 PathAck(path_ack_encoder) => { -7552 if let Some(max) = path_ack_encoder.ranges.max() { -7553 self.largest_acked.insert(path_ack_encoder.path_id, max); -7554 } -7555 } -7556 Ack(ack_encoder) => { -7557 if let Some(max) = ack_encoder.ranges.max() { -7558 self.largest_acked.insert(PathId::ZERO, max); -7559 } -7560 } -7561 Close(_) => { /* non retransmittable, but after this we don't really care */ } -7562 PathResponse(_) => self.non_retransmits = true, -7563 HandshakeDone(_) => self.retransmits_mut().handshake_done = true, -7564 ReachOut(frame) => self.retransmits_mut().reach_out.push(frame), -7565 ObservedAddr(_) => self.retransmits_mut().observed_addr = true, -7566 Ping(_) => self.non_retransmits = true, -7567 ImmediateAck(_) => self.non_retransmits = true, -7568 AckFrequency(_) => self.retransmits_mut().ack_frequency = true, -7569 PathChallenge(_) => self.non_retransmits = true, -7570 Crypto(crypto) => self.retransmits_mut().crypto.push_back(crypto), -7571 PathAbandon(path_abandon) => { -7572 self.retransmits_mut() -7573 .path_abandon -7574 .entry(path_abandon.path_id) -7575 .or_insert(path_abandon.error_code); -7576 } -7577 PathStatusAvailable(frame::PathStatusAvailable { path_id, .. }) -7578 | PathStatusBackup(frame::PathStatusBackup { path_id, .. }) => { -7579 self.retransmits_mut().path_status.insert(path_id); -7580 } -7581 MaxPathId(_) => self.retransmits_mut().max_path_id = true, -7582 PathsBlocked(_) => self.retransmits_mut().paths_blocked = true, -7583 PathCidsBlocked(path_cids_blocked) => { -7584 self.retransmits_mut() -7585 .path_cids_blocked -7586 .insert(path_cids_blocked.path_id); -7587 } -7588 ResetStream(reset) => self -7589 .retransmits_mut() -7590 .reset_stream -7591 .push((reset.id, reset.error_code)), -7592 StopSending(stop_sending) => self.retransmits_mut().stop_sending.push(stop_sending), -7593 NewConnectionId(new_cid) => self.retransmits_mut().new_cids.push(new_cid.issued()), -7594 RetireConnectionId(retire_cid) => self -7595 .retransmits_mut() -7596 .retire_cids -7597 .push((retire_cid.path_id.unwrap_or_default(), retire_cid.sequence)), -7598 Datagram(_) => self.non_retransmits = true, -7599 NewToken(_) => {} -7600 AddAddress(add_address) => { -7601 self.retransmits_mut().add_address.insert(add_address); +7493fn get_max_ack_delay(params: &TransportParameters) -> Duration { +7494 Duration::from_micros(params.max_ack_delay.0 * 1000) +7495} +7496 +7497/// Prevents overflow and improves behavior in extreme circumstances. +7498const MAX_BACKOFF_EXPONENT: u32 = 16; +7499 +7500/// The max interval between successive tail-loss probes. +7501/// +7502/// This is the "normal" value we use. +7503const MAX_PTO_INTERVAL: Duration = Duration::from_secs(2); +7504 +7505/// The idle time, below which we use the shorter [`MAX_PTO_FAST_INTERVAL`]. +7506const MIN_IDLE_FOR_FAST_PTO: Duration = Duration::from_secs(25); +7507 +7508/// The max interval between successive tail-loss probes with short idle times. +7509/// +7510/// If the path or connection idle time is less than [`MIN_IDLE_FOR_FAST_PTO`] then we use +7511/// this value to ensure we have plenty of retransmits before we reach the idle time. +7512const MAX_PTO_FAST_INTERVAL: Duration = Duration::from_secs(1); +7513 +7514/// The RTT threshold above which we cap the PTO interval to 1.5 * smoothed_rtt +7515/// +7516/// This is RTT time above which 1.5 * RTT > [`MAX_PTO_INTERVAL`], for these links we want +7517/// to extend the interval between tail-loss probes to not fill the entire pipe with them. +7518const SLOW_RTT_THRESHOLD: Duration = +7519 Duration::from_millis((MAX_PTO_INTERVAL.as_millis() as u64 * 2) / 3); +7520 +7521/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag +7522/// +7523/// This must be at least as large as the header for a well-formed empty packet to be coalesced, +7524/// plus some space for frames. We only care about handshake headers because short header packets +7525/// necessarily have smaller headers, and initial packets are only ever the first packet in a +7526/// datagram (because we coalesce in ascending packet space order and the only reason to split a +7527/// packet is when packet space changes). +7528const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32; +7529 +7530/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header +7531/// +7532/// Excludes packet-type-specific fields such as packet number or Initial token +7533// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid + +7534// scid len + scid + length + pn +7535const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize = +7536 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4; +7537 +7538#[derive(Default)] +7539struct SentFrames { +7540 retransmits: ThinRetransmits, +7541 /// The packet number of the largest acknowledged packet for each path +7542 largest_acked: FxHashMap<PathId, u64>, +7543 stream_frames: StreamMetaVec, +7544 /// Whether the packet contains non-retransmittable frames (like datagrams) +7545 non_retransmits: bool, +7546 /// If the datagram containing these frames should be padded to the min MTU +7547 requires_padding: bool, +7548} +7549 +7550impl SentFrames { +7551 /// Returns whether the packet contains only ACKs +7552 fn is_ack_only(&self, streams: &StreamsState) -> bool { +7553 !self.largest_acked.is_empty() +7554 && !self.non_retransmits +7555 && self.stream_frames.is_empty() +7556 && self.retransmits.is_empty(streams) +7557 } +7558 +7559 fn retransmits_mut(&mut self) -> &mut Retransmits { +7560 self.retransmits.get_or_create() +7561 } +7562 +7563 fn record_sent_frame(&mut self, frame: frame::EncodableFrame<'_>) { +7564 use frame::EncodableFrame::*; +7565 match frame { +7566 PathAck(path_ack_encoder) => { +7567 if let Some(max) = path_ack_encoder.ranges.max() { +7568 self.largest_acked.insert(path_ack_encoder.path_id, max); +7569 } +7570 } +7571 Ack(ack_encoder) => { +7572 if let Some(max) = ack_encoder.ranges.max() { +7573 self.largest_acked.insert(PathId::ZERO, max); +7574 } +7575 } +7576 Close(_) => { /* non retransmittable, but after this we don't really care */ } +7577 PathResponse(_) => self.non_retransmits = true, +7578 HandshakeDone(_) => self.retransmits_mut().handshake_done = true, +7579 ReachOut(frame) => self.retransmits_mut().reach_out.push(frame), +7580 ObservedAddr(_) => self.retransmits_mut().observed_addr = true, +7581 Ping(_) => self.non_retransmits = true, +7582 ImmediateAck(_) => self.non_retransmits = true, +7583 AckFrequency(_) => self.retransmits_mut().ack_frequency = true, +7584 PathChallenge(_) => self.non_retransmits = true, +7585 Crypto(crypto) => self.retransmits_mut().crypto.push_back(crypto), +7586 PathAbandon(path_abandon) => { +7587 self.retransmits_mut() +7588 .path_abandon +7589 .entry(path_abandon.path_id) +7590 .or_insert(path_abandon.error_code); +7591 } +7592 PathStatusAvailable(frame::PathStatusAvailable { path_id, .. }) +7593 | PathStatusBackup(frame::PathStatusBackup { path_id, .. }) => { +7594 self.retransmits_mut().path_status.insert(path_id); +7595 } +7596 MaxPathId(_) => self.retransmits_mut().max_path_id = true, +7597 PathsBlocked(_) => self.retransmits_mut().paths_blocked = true, +7598 PathCidsBlocked(path_cids_blocked) => { +7599 self.retransmits_mut() +7600 .path_cids_blocked +7601 .insert(path_cids_blocked.path_id); 7602 } -7603 RemoveAddress(remove_address) => { -7604 self.retransmits_mut().remove_address.insert(remove_address); -7605 } -7606 StreamMeta(stream_meta_encoder) => self.stream_frames.push(stream_meta_encoder.meta), -7607 MaxData(_) => self.retransmits_mut().max_data = true, -7608 MaxStreamData(max) => { -7609 self.retransmits_mut().max_stream_data.insert(max.id); -7610 } -7611 MaxStreams(max_streams) => { -7612 self.retransmits_mut().max_stream_id[max_streams.dir as usize] = true -7613 } -7614 StreamsBlocked(streams_blocked) => { -7615 self.retransmits_mut().streams_blocked[streams_blocked.dir as usize] = true -7616 } -7617 } -7618 } -7619} -7620 -7621/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters. -7622/// -7623/// According to the definition of max_idle_timeout, a value of `0` means the timeout is disabled; see <https://www.rfc-editor.org/rfc/rfc9000#section-18.2-4.4.1.> -7624/// -7625/// According to the negotiation procedure, either the minimum of the timeouts or one specified is used as the negotiated value; see <https://www.rfc-editor.org/rfc/rfc9000#section-10.1-2.> -7626/// -7627/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout. -7628fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> { -7629 match (x, y) { -7630 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None, -7631 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)), -7632 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)), -7633 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)), -7634 } -7635} -7636 -7637#[cfg(test)] -7638mod tests { -7639 use super::*; -7640 -7641 #[test] -7642 fn negotiate_max_idle_timeout_commutative() { -7643 let test_params = [ -7644 (None, None, None), -7645 (None, Some(VarInt(0)), None), -7646 (None, Some(VarInt(2)), Some(Duration::from_millis(2))), -7647 (Some(VarInt(0)), Some(VarInt(0)), None), -7648 ( -7649 Some(VarInt(2)), -7650 Some(VarInt(0)), -7651 Some(Duration::from_millis(2)), -7652 ), -7653 ( -7654 Some(VarInt(1)), -7655 Some(VarInt(4)), -7656 Some(Duration::from_millis(1)), -7657 ), -7658 ]; -7659 -7660 for (left, right, result) in test_params { -7661 assert_eq!(negotiate_max_idle_timeout(left, right), result); -7662 assert_eq!(negotiate_max_idle_timeout(right, left), result); -7663 } -7664 } -7665} \ No newline at end of file +7603 ResetStream(reset) => self +7604 .retransmits_mut() +7605 .reset_stream +7606 .push((reset.id, reset.error_code)), +7607 StopSending(stop_sending) => self.retransmits_mut().stop_sending.push(stop_sending), +7608 NewConnectionId(new_cid) => self.retransmits_mut().new_cids.push(new_cid.issued()), +7609 RetireConnectionId(retire_cid) => self +7610 .retransmits_mut() +7611 .retire_cids +7612 .push((retire_cid.path_id.unwrap_or_default(), retire_cid.sequence)), +7613 Datagram(_) => self.non_retransmits = true, +7614 NewToken(_) => {} +7615 AddAddress(add_address) => { +7616 self.retransmits_mut().add_address.insert(add_address); +7617 } +7618 RemoveAddress(remove_address) => { +7619 self.retransmits_mut().remove_address.insert(remove_address); +7620 } +7621 StreamMeta(stream_meta_encoder) => self.stream_frames.push(stream_meta_encoder.meta), +7622 MaxData(_) => self.retransmits_mut().max_data = true, +7623 MaxStreamData(max) => { +7624 self.retransmits_mut().max_stream_data.insert(max.id); +7625 } +7626 MaxStreams(max_streams) => { +7627 self.retransmits_mut().max_stream_id[max_streams.dir as usize] = true +7628 } +7629 StreamsBlocked(streams_blocked) => { +7630 self.retransmits_mut().streams_blocked[streams_blocked.dir as usize] = true +7631 } +7632 } +7633 } +7634} +7635 +7636/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters. +7637/// +7638/// According to the definition of max_idle_timeout, a value of `0` means the timeout is disabled; see <https://www.rfc-editor.org/rfc/rfc9000#section-18.2-4.4.1.> +7639/// +7640/// According to the negotiation procedure, either the minimum of the timeouts or one specified is used as the negotiated value; see <https://www.rfc-editor.org/rfc/rfc9000#section-10.1-2.> +7641/// +7642/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout. +7643fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> { +7644 match (x, y) { +7645 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None, +7646 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)), +7647 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)), +7648 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)), +7649 } +7650} +7651 +7652#[cfg(test)] +7653mod tests { +7654 use super::*; +7655 +7656 #[test] +7657 fn negotiate_max_idle_timeout_commutative() { +7658 let test_params = [ +7659 (None, None, None), +7660 (None, Some(VarInt(0)), None), +7661 (None, Some(VarInt(2)), Some(Duration::from_millis(2))), +7662 (Some(VarInt(0)), Some(VarInt(0)), None), +7663 ( +7664 Some(VarInt(2)), +7665 Some(VarInt(0)), +7666 Some(Duration::from_millis(2)), +7667 ), +7668 ( +7669 Some(VarInt(1)), +7670 Some(VarInt(4)), +7671 Some(Duration::from_millis(1)), +7672 ), +7673 ]; +7674 +7675 for (left, right, result) in test_params { +7676 assert_eq!(negotiate_max_idle_timeout(left, right), result); +7677 assert_eq!(negotiate_max_idle_timeout(right, left), result); +7678 } +7679 } +7680} \ No newline at end of file diff --git a/pr/619/docs/src/perf/server.rs.html b/pr/619/docs/src/perf/server.rs.html index ef6348b3f..ea8fd4c49 100644 --- a/pr/619/docs/src/perf/server.rs.html +++ b/pr/619/docs/src/perf/server.rs.html @@ -101,102 +101,109 @@ 101async fn handle(handshake: noq::Incoming, opt: Arc<Opt>) -> Result<()> { 102 let connection = handshake.await.context("handshake failed")?; 103 -104 debug!("{} connected", connection.remote_address()); -105 tokio::try_join!( -106 drive_uni(connection.clone()), -107 drive_bi(connection.clone()), -108 conn_stats(connection, opt) -109 )?; -110 Ok(()) -111} -112 -113async fn conn_stats(connection: noq::Connection, opt: Arc<Opt>) -> Result<()> { -114 if opt.common.conn_stats { -115 loop { -116 tokio::time::sleep(Duration::from_secs(2)).await; -117 println!("{:?}\n", connection.stats()); -118 } -119 } -120 -121 Ok(()) -122} -123 -124async fn drive_uni(connection: noq::Connection) -> Result<()> { -125 while let Ok(stream) = connection.accept_uni().await { -126 let connection = connection.clone(); -127 tokio::spawn(async move { -128 if let Err(e) = handle_uni(connection, stream).await { -129 error!("request failed: {:#}", e); -130 } -131 }); -132 } -133 Ok(()) -134} -135 -136async fn handle_uni(connection: noq::Connection, stream: noq::RecvStream) -> Result<()> { -137 let bytes = read_req(stream).await?; -138 let response = connection.open_uni().await?; -139 respond(bytes, response).await?; +104 debug!( +105 "{} connected", +106 connection +107 .path(noq::PathId::ZERO) +108 .expect("path open after connect") +109 .remote_address() +110 .expect("path is alive") +111 ); +112 tokio::try_join!( +113 drive_uni(connection.clone()), +114 drive_bi(connection.clone()), +115 conn_stats(connection, opt) +116 )?; +117 Ok(()) +118} +119 +120async fn conn_stats(connection: noq::Connection, opt: Arc<Opt>) -> Result<()> { +121 if opt.common.conn_stats { +122 loop { +123 tokio::time::sleep(Duration::from_secs(2)).await; +124 println!("{:?}\n", connection.stats()); +125 } +126 } +127 +128 Ok(()) +129} +130 +131async fn drive_uni(connection: noq::Connection) -> Result<()> { +132 while let Ok(stream) = connection.accept_uni().await { +133 let connection = connection.clone(); +134 tokio::spawn(async move { +135 if let Err(e) = handle_uni(connection, stream).await { +136 error!("request failed: {:#}", e); +137 } +138 }); +139 } 140 Ok(()) 141} 142 -143async fn drive_bi(connection: noq::Connection) -> Result<()> { -144 while let Ok((send, recv)) = connection.accept_bi().await { -145 tokio::spawn(async move { -146 if let Err(e) = handle_bi(send, recv).await { -147 error!("request failed: {:#}", e); -148 } -149 }); -150 } -151 Ok(()) -152} -153 -154async fn handle_bi(send: noq::SendStream, recv: noq::RecvStream) -> Result<()> { -155 let bytes = read_req(recv).await?; -156 respond(bytes, send).await?; -157 Ok(()) -158} -159 -160async fn read_req(mut stream: noq::RecvStream) -> Result<u64> { -161 let mut buf = [0; 8]; -162 stream -163 .read_exact(&mut buf) -164 .await -165 .context("reading request")?; -166 let n = u64::from_be_bytes(buf); -167 debug!("got req for {} bytes on {}", n, stream.id()); -168 drain_stream(stream).await?; -169 Ok(n) -170} -171 -172async fn drain_stream(mut stream: noq::RecvStream) -> Result<()> { -173 #[rustfmt::skip] -174 let mut bufs = [ -175 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -176 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -177 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -178 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -179 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -180 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -181 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +143async fn handle_uni(connection: noq::Connection, stream: noq::RecvStream) -> Result<()> { +144 let bytes = read_req(stream).await?; +145 let response = connection.open_uni().await?; +146 respond(bytes, response).await?; +147 Ok(()) +148} +149 +150async fn drive_bi(connection: noq::Connection) -> Result<()> { +151 while let Ok((send, recv)) = connection.accept_bi().await { +152 tokio::spawn(async move { +153 if let Err(e) = handle_bi(send, recv).await { +154 error!("request failed: {:#}", e); +155 } +156 }); +157 } +158 Ok(()) +159} +160 +161async fn handle_bi(send: noq::SendStream, recv: noq::RecvStream) -> Result<()> { +162 let bytes = read_req(recv).await?; +163 respond(bytes, send).await?; +164 Ok(()) +165} +166 +167async fn read_req(mut stream: noq::RecvStream) -> Result<u64> { +168 let mut buf = [0; 8]; +169 stream +170 .read_exact(&mut buf) +171 .await +172 .context("reading request")?; +173 let n = u64::from_be_bytes(buf); +174 debug!("got req for {} bytes on {}", n, stream.id()); +175 drain_stream(stream).await?; +176 Ok(n) +177} +178 +179async fn drain_stream(mut stream: noq::RecvStream) -> Result<()> { +180 #[rustfmt::skip] +181 let mut bufs = [ 182 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), -183 ]; -184 while stream.read_chunks(&mut bufs[..]).await?.is_some() {} -185 debug!("finished reading {}", stream.id()); -186 Ok(()) -187} -188 -189async fn respond(mut bytes: u64, mut stream: noq::SendStream) -> Result<()> { -190 static DATA: [u8; 1024 * 1024] = [42; 1024 * 1024]; -191 -192 while bytes > 0 { -193 let chunk_len = bytes.min(DATA.len() as u64); -194 stream -195 .write_chunk(Bytes::from_static(&DATA[..chunk_len as usize])) -196 .await -197 .context("sending response")?; -198 bytes -= chunk_len; -199 } -200 debug!("finished responding on {}", stream.id()); -201 Ok(()) -202} \ No newline at end of file +183 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +184 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +185 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +186 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +187 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +188 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +189 Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), +190 ]; +191 while stream.read_chunks(&mut bufs[..]).await?.is_some() {} +192 debug!("finished reading {}", stream.id()); +193 Ok(()) +194} +195 +196async fn respond(mut bytes: u64, mut stream: noq::SendStream) -> Result<()> { +197 static DATA: [u8; 1024 * 1024] = [42; 1024 * 1024]; +198 +199 while bytes > 0 { +200 let chunk_len = bytes.min(DATA.len() as u64); +201 stream +202 .write_chunk(Bytes::from_static(&DATA[..chunk_len as usize])) +203 .await +204 .context("sending response")?; +205 bytes -= chunk_len; +206 } +207 debug!("finished responding on {}", stream.id()); +208 Ok(()) +209} \ No newline at end of file