From 28c8f7265dcd133f1fe7e9fdae950dfe094b5d8e Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 13 Jan 2026 15:43:06 +0000 Subject: [PATCH] deploy: 1450ade5ed33c5f6debc05f98ddaa36d351f2f14 --- pr/255/docs/bulk/struct.ClientStats.html | 2 +- pr/255/docs/iroh_quinn/all.html | 2 +- pr/255/docs/iroh_quinn/congestion/index.html | 2 +- .../iroh_quinn/congestion/struct.Bbr.html | 8 +- .../congestion/struct.BbrConfig.html | 8 +- .../congestion/trait.Controller.html | 2 +- .../congestion/trait.ControllerFactory.html | 2 +- .../rustls/struct.QuicClientConfig.html | 2 +- pr/255/docs/iroh_quinn/enum.ConfigError.html | 6 +- pr/255/docs/iroh_quinn/enum.ConnectError.html | 6 +- .../docs/iroh_quinn/enum.ConnectionError.html | 6 +- pr/255/docs/iroh_quinn/enum.Dir.html | 16 +- pr/255/docs/iroh_quinn/enum.FrameType.html | 10 +- pr/255/docs/iroh_quinn/enum.Side.html | 20 +- pr/255/docs/iroh_quinn/enum.StoppedError.html | 6 +- pr/255/docs/iroh_quinn/enum.WriteError.html | 6 +- pr/255/docs/iroh_quinn/index.html | 4 +- .../path/struct.AddressDiscovery.html | 11 + .../iroh_quinn/path/struct.ClosePath.html | 11 + pr/255/docs/iroh_quinn/sidebar-items.js | 2 +- pr/255/docs/iroh_quinn/struct.Accept.html | 6 +- .../iroh_quinn/struct.AddressDiscovery.html | 173 + .../iroh_quinn/struct.ApplicationClose.html | 6 +- .../docs/iroh_quinn/struct.ClientConfig.html | 9 +- pr/255/docs/iroh_quinn/struct.ClosePath.html | 53 + .../docs/iroh_quinn/struct.ClosedStream.html | 2 +- .../iroh_quinn/struct.ConnectionClose.html | 10 +- pr/255/docs/iroh_quinn/struct.Endpoint.html | 34 +- .../docs/iroh_quinn/struct.EndpointStats.html | 4 +- pr/255/docs/iroh_quinn/struct.InvalidCid.html | 27 + pr/255/docs/iroh_quinn/struct.Path.html | 4 +- pr/255/docs/iroh_quinn/struct.SendStream.html | 30 +- .../docs/iroh_quinn/struct.StdSystemTime.html | 4 +- pr/255/docs/iroh_quinn/struct.StreamId.html | 30 +- pr/255/docs/iroh_quinn/struct.Transmit.html | 4 +- pr/255/docs/iroh_quinn/struct.VarInt.html | 2 +- .../struct.VarIntBoundsExceeded.html | 2 +- .../trait.ConnectionIdGenerator.html | 4 +- pr/255/docs/iroh_quinn/trait.TimeSource.html | 6 +- pr/255/docs/iroh_quinn_proto/all.html | 2 +- .../iroh_quinn_proto/bench_exports/index.html | 2 +- .../coding/trait.Decodable.html | 2 +- .../coding/trait.Encodable.html | 2 +- .../congestion/struct.Bbr.html | 10 +- .../congestion/struct.BbrConfig.html | 8 +- .../congestion/trait.Controller.html | 2 +- .../congestion/trait.ControllerFactory.html | 2 +- .../struct.MultipathNotNegotiated.html | 11 + .../constant.DEFAULT_SUPPORTED_VERSIONS.html | 2 +- .../rustls/struct.QuicClientConfig.html | 2 +- .../iroh_quinn_proto/enum.ClosePathError.html | 6 +- .../iroh_quinn_proto/enum.ConfigError.html | 6 +- .../iroh_quinn_proto/enum.ConnectError.html | 6 +- .../enum.ConnectionError.html | 6 +- .../iroh_quinn_proto/enum.DatagramEvent.html | 2 +- pr/255/docs/iroh_quinn_proto/enum.Dir.html | 16 +- pr/255/docs/iroh_quinn_proto/enum.Event.html | 4 +- .../docs/iroh_quinn_proto/enum.FrameType.html | 8 +- .../iroh_quinn_proto/enum.MaybeFrame.html | 40 + .../docs/iroh_quinn_proto/enum.PathError.html | 6 +- .../docs/iroh_quinn_proto/enum.PathEvent.html | 2 +- .../enum.SendDatagramError.html | 12 +- pr/255/docs/iroh_quinn_proto/enum.Side.html | 20 +- .../frame/enum.MaybeFrame.html | 11 + .../frame/struct.DatagramInfo.html | 11 + .../frame/struct.InvalidFrameId.html | 11 + .../frame/struct.StreamInfo.html | 11 + pr/255/docs/iroh_quinn_proto/index.html | 8 +- pr/255/docs/iroh_quinn_proto/sidebar-items.js | 2 +- .../iroh_quinn_proto/struct.AcceptError.html | 4 +- .../struct.ApplicationClose.html | 6 +- .../iroh_quinn_proto/struct.ClientConfig.html | 9 +- .../iroh_quinn_proto/struct.Connection.html | 72 +- .../struct.ConnectionClose.html | 10 +- .../struct.ConnectionHandle.html | 12 +- .../iroh_quinn_proto/struct.Datagram.html | 4 +- .../iroh_quinn_proto/struct.DatagramInfo.html | 32 + .../iroh_quinn_proto/struct.Endpoint.html | 31 +- .../iroh_quinn_proto/struct.FourTuple.html | 12 +- .../iroh_quinn_proto/struct.Incoming.html | 14 +- .../struct.InvalidFrameId.html | 30 + .../struct.MultipathNotNegotiated.html | 28 + .../iroh_quinn_proto/struct.RetryError.html | 6 +- .../struct.StdSystemTime.html | 4 +- .../iroh_quinn_proto/struct.StreamId.html | 26 +- .../iroh_quinn_proto/struct.StreamInfo.html | 32 + .../iroh_quinn_proto/struct.Transmit.html | 4 +- .../struct.TransportError.html | 6 +- .../docs/iroh_quinn_proto/struct.VarInt.html | 2 +- .../struct.VarIntBoundsExceeded.html | 2 +- .../iroh_quinn_proto/trait.TimeSource.html | 6 +- .../transport_parameters/index.html | 2 +- .../struct.TransportParameters.html | 4 +- .../iroh_quinn_udp/enum.EcnCodepoint.html | 8 +- pr/255/docs/iroh_quinn_udp/index.html | 2 +- .../iroh_quinn_udp/struct.UdpSockRef.html | 6 +- .../iroh_quinn_udp/struct.UdpSocketState.html | 24 +- pr/255/docs/search.index/00037727d41b.js | 1 + pr/255/docs/search.index/001277e366cd.js | 1 + pr/255/docs/search.index/0095923ba754.js | 1 + pr/255/docs/search.index/00c07f35c6ce.js | 1 - pr/255/docs/search.index/00f09416a63d.js | 1 + pr/255/docs/search.index/00f55497d47e.js | 1 + pr/255/docs/search.index/01806ef5b5d6.js | 1 - pr/255/docs/search.index/01d48ddd05cf.js | 1 - pr/255/docs/search.index/01f5bffda89c.js | 1 - pr/255/docs/search.index/024f75b34b20.js | 1 + pr/255/docs/search.index/02f80e846705.js | 1 - pr/255/docs/search.index/030aa7192f47.js | 1 - pr/255/docs/search.index/030abe455d20.js | 1 - pr/255/docs/search.index/035c9d3c036b.js | 1 - pr/255/docs/search.index/04219d6c5f1f.js | 1 - pr/255/docs/search.index/045e5265a54f.js | 1 - pr/255/docs/search.index/04786c4690da.js | 1 - pr/255/docs/search.index/054086f1f577.js | 1 - pr/255/docs/search.index/05c72ebeb6e8.js | 1 + pr/255/docs/search.index/05cf24e46b23.js | 1 + pr/255/docs/search.index/05e417058650.js | 1 + pr/255/docs/search.index/05f4c9420eb7.js | 1 - pr/255/docs/search.index/0615a2bf5050.js | 1 - pr/255/docs/search.index/06a55ef026d4.js | 1 + pr/255/docs/search.index/0773c651efc1.js | 1 + pr/255/docs/search.index/07b12fe46ce8.js | 1 - pr/255/docs/search.index/07bca17b1c6a.js | 1 - pr/255/docs/search.index/081380447331.js | 1 - pr/255/docs/search.index/082c33a78589.js | 1 + pr/255/docs/search.index/0842ec51c54a.js | 1 + pr/255/docs/search.index/08b434a15736.js | 1 + pr/255/docs/search.index/0933b5050388.js | 1 - pr/255/docs/search.index/096a32f3fb06.js | 1 - pr/255/docs/search.index/09c6ace039aa.js | 1 - pr/255/docs/search.index/09f0b7b1cb10.js | 1 + pr/255/docs/search.index/0adb0f113264.js | 1 + pr/255/docs/search.index/0aebd591215a.js | 1 - pr/255/docs/search.index/0b049d31f2d1.js | 1 + pr/255/docs/search.index/0b8810d9f049.js | 1 + pr/255/docs/search.index/0b9da5e00812.js | 1 - pr/255/docs/search.index/0bfb65fd762c.js | 1 + pr/255/docs/search.index/0c4100bc39d6.js | 1 + pr/255/docs/search.index/0cad63531c89.js | 1 + pr/255/docs/search.index/0d24876322d0.js | 1 - pr/255/docs/search.index/0d377ac14863.js | 1 - pr/255/docs/search.index/0d5508bf0207.js | 1 - pr/255/docs/search.index/0dbe969ddebd.js | 1 + pr/255/docs/search.index/0dd31cbab4cc.js | 1 - pr/255/docs/search.index/0e34ce7f7192.js | 1 + pr/255/docs/search.index/0e61017bc68b.js | 1 - pr/255/docs/search.index/0f103fffad43.js | 1 + pr/255/docs/search.index/0f1e1d1cc48f.js | 1 + pr/255/docs/search.index/0f434453b623.js | 1 + pr/255/docs/search.index/0f835c2828ff.js | 1 + pr/255/docs/search.index/0fa74a34d33c.js | 1 - pr/255/docs/search.index/1017c7914851.js | 1 + pr/255/docs/search.index/103f1ba9c2d5.js | 1 - pr/255/docs/search.index/10e19c9358f8.js | 1 - pr/255/docs/search.index/1119c1193e11.js | 1 + pr/255/docs/search.index/118928699d86.js | 1 + pr/255/docs/search.index/1198e3f6eeb3.js | 1 - pr/255/docs/search.index/11ac60f101c2.js | 1 + pr/255/docs/search.index/125b8dc7d658.js | 1 - pr/255/docs/search.index/125c69e2afa8.js | 1 + pr/255/docs/search.index/12aab9d7ac8d.js | 1 + pr/255/docs/search.index/1323b5cdf876.js | 1 + pr/255/docs/search.index/1344897c571c.js | 1 - pr/255/docs/search.index/138a5af4d179.js | 1 + pr/255/docs/search.index/1409f2140ee5.js | 1 + pr/255/docs/search.index/1455b2c199cd.js | 1 + pr/255/docs/search.index/1499361f517d.js | 1 - pr/255/docs/search.index/1511e66727f1.js | 1 + pr/255/docs/search.index/1552619586d7.js | 1 + pr/255/docs/search.index/1566e3c31611.js | 1 - pr/255/docs/search.index/16045633eb64.js | 1 + pr/255/docs/search.index/16681f81c6a9.js | 1 - pr/255/docs/search.index/16e43e96c3f0.js | 1 + pr/255/docs/search.index/16f90e0495ca.js | 1 - pr/255/docs/search.index/17747f0de527.js | 1 - pr/255/docs/search.index/182d04459856.js | 1 - pr/255/docs/search.index/18c051295b43.js | 1 + pr/255/docs/search.index/18e4b0fb83df.js | 1 - pr/255/docs/search.index/19476e380db8.js | 1 + pr/255/docs/search.index/19c9a628ac91.js | 1 - pr/255/docs/search.index/19f55295ffb7.js | 1 - pr/255/docs/search.index/1a01681e7d77.js | 1 - pr/255/docs/search.index/1a59836e6e94.js | 1 + pr/255/docs/search.index/1a6a4539ae89.js | 1 + pr/255/docs/search.index/1a6b9bf2988f.js | 1 + pr/255/docs/search.index/1b5a76a5a4b0.js | 1 + pr/255/docs/search.index/1b6ac9e761aa.js | 1 - pr/255/docs/search.index/1b82b05116c9.js | 1 - pr/255/docs/search.index/1b97b26c3ac1.js | 1 - pr/255/docs/search.index/1bf5442726c7.js | 1 + pr/255/docs/search.index/1c84f4d721b0.js | 1 + pr/255/docs/search.index/1ce4c2454b0a.js | 1 - pr/255/docs/search.index/1cf369215e3f.js | 1 + pr/255/docs/search.index/1e602721a639.js | 1 + pr/255/docs/search.index/1ea1f2d3747a.js | 1 - pr/255/docs/search.index/1f0367152a3f.js | 1 + pr/255/docs/search.index/1f11eee293c6.js | 1 + pr/255/docs/search.index/1f1d2b61eca6.js | 1 + pr/255/docs/search.index/1f6d06e60df8.js | 1 + pr/255/docs/search.index/1f850a139dfa.js | 1 + pr/255/docs/search.index/1fb072ef9a66.js | 1 + pr/255/docs/search.index/2025f39bb570.js | 1 + pr/255/docs/search.index/2098306f4d34.js | 1 - pr/255/docs/search.index/20b4057caa1a.js | 1 + pr/255/docs/search.index/21a899f4f99b.js | 1 - pr/255/docs/search.index/21bd1e52c0f9.js | 1 + pr/255/docs/search.index/21f7fe292e8a.js | 1 + pr/255/docs/search.index/225a0e027688.js | 1 + pr/255/docs/search.index/24eee7d39d3b.js | 1 + pr/255/docs/search.index/252df03c9a7b.js | 1 + pr/255/docs/search.index/254b4b1e845b.js | 1 + pr/255/docs/search.index/25a54c1ab6e0.js | 1 - pr/255/docs/search.index/25b74d0e760c.js | 1 + pr/255/docs/search.index/266311e2892f.js | 1 - pr/255/docs/search.index/266827f9a2f0.js | 1 - pr/255/docs/search.index/266afabfc690.js | 1 + pr/255/docs/search.index/2670b688dca6.js | 1 + pr/255/docs/search.index/267d2567696a.js | 1 - pr/255/docs/search.index/26e84f065723.js | 1 + pr/255/docs/search.index/27198464c776.js | 1 + pr/255/docs/search.index/271cda0a044e.js | 1 + pr/255/docs/search.index/27677e8fce37.js | 1 + pr/255/docs/search.index/278470046fa3.js | 1 + pr/255/docs/search.index/27bc89bd5eae.js | 1 + pr/255/docs/search.index/27f8ec34bd1f.js | 1 - pr/255/docs/search.index/281cb83843d4.js | 1 - pr/255/docs/search.index/28827f9488f7.js | 1 - pr/255/docs/search.index/28d0ee3283f9.js | 1 + pr/255/docs/search.index/29912ff817d4.js | 1 + pr/255/docs/search.index/29ffaf5f711f.js | 1 + pr/255/docs/search.index/2a2e9d6f638a.js | 1 + pr/255/docs/search.index/2adb3d0bf2d8.js | 1 - pr/255/docs/search.index/2b09faf5f111.js | 1 + pr/255/docs/search.index/2b35726b25dd.js | 1 + pr/255/docs/search.index/2b92810a6565.js | 1 - pr/255/docs/search.index/2bed9cec1d26.js | 1 - pr/255/docs/search.index/2ce4b4057c53.js | 1 + pr/255/docs/search.index/2d2960f9b8d4.js | 1 + pr/255/docs/search.index/2e7d78ea0cfe.js | 1 - pr/255/docs/search.index/2e882e6bf78f.js | 1 - pr/255/docs/search.index/2eb9123a10fd.js | 1 + pr/255/docs/search.index/2f0bd76574d0.js | 1 - pr/255/docs/search.index/2f2a8a6c3151.js | 1 - pr/255/docs/search.index/2fac3831697f.js | 1 + pr/255/docs/search.index/2fd891c7dddc.js | 1 + pr/255/docs/search.index/30399b5c8304.js | 1 - pr/255/docs/search.index/30a16458d826.js | 1 - pr/255/docs/search.index/30d311112226.js | 1 + pr/255/docs/search.index/30e9b37f1a9e.js | 1 - pr/255/docs/search.index/311e77def7dc.js | 1 - pr/255/docs/search.index/312e80bd916b.js | 1 + pr/255/docs/search.index/3161d4c1c9e3.js | 1 - pr/255/docs/search.index/325f77b8029e.js | 1 - pr/255/docs/search.index/32c27beceb5f.js | 1 - pr/255/docs/search.index/33aa643b366e.js | 1 + pr/255/docs/search.index/33b38805b1c6.js | 1 + pr/255/docs/search.index/3407cc8b99a3.js | 1 - pr/255/docs/search.index/34726ae306d9.js | 1 - pr/255/docs/search.index/348567575911.js | 1 + pr/255/docs/search.index/34bb2b1a0ab9.js | 1 - pr/255/docs/search.index/34e0c30a19a6.js | 1 + pr/255/docs/search.index/35cd5d54f947.js | 1 - pr/255/docs/search.index/36de07894256.js | 1 - pr/255/docs/search.index/3748eeff0c66.js | 1 - pr/255/docs/search.index/378531389b4a.js | 1 - pr/255/docs/search.index/37cfa41c8509.js | 1 - pr/255/docs/search.index/3872754cddc0.js | 1 - pr/255/docs/search.index/38ae726b5e74.js | 1 - pr/255/docs/search.index/38cb6e24cf5d.js | 1 + pr/255/docs/search.index/3922a16454e0.js | 1 + pr/255/docs/search.index/392fb1700c95.js | 1 + pr/255/docs/search.index/393da311e403.js | 1 + pr/255/docs/search.index/39c20340df78.js | 1 - pr/255/docs/search.index/3a529860f4ab.js | 1 + pr/255/docs/search.index/3a6bd631205f.js | 1 + pr/255/docs/search.index/3a74000719ff.js | 1 - pr/255/docs/search.index/3a74061c4f9f.js | 1 + pr/255/docs/search.index/3adb9518fd74.js | 1 + pr/255/docs/search.index/3afe7bef2754.js | 1 + pr/255/docs/search.index/3b1e455f5b16.js | 1 + pr/255/docs/search.index/3b786721c45c.js | 1 - pr/255/docs/search.index/3bd565fd40d0.js | 1 - pr/255/docs/search.index/3ce49910eea7.js | 1 + pr/255/docs/search.index/3d41efe337a8.js | 1 - pr/255/docs/search.index/3d4983faf394.js | 1 - pr/255/docs/search.index/3eb044d68081.js | 1 - pr/255/docs/search.index/3f16c6444948.js | 1 + pr/255/docs/search.index/3f1d867bdbec.js | 1 - pr/255/docs/search.index/3f2790b84249.js | 1 - pr/255/docs/search.index/3f76acc9c4c0.js | 1 - pr/255/docs/search.index/3fe667d21e90.js | 1 - pr/255/docs/search.index/402127170d10.js | 1 - pr/255/docs/search.index/40672655bcf1.js | 1 - pr/255/docs/search.index/4083ed670548.js | 1 - pr/255/docs/search.index/409b3322db69.js | 1 + pr/255/docs/search.index/40d03efa707b.js | 1 + pr/255/docs/search.index/40d41dda421f.js | 1 - pr/255/docs/search.index/40e5df003d92.js | 1 - pr/255/docs/search.index/40fc47699d53.js | 1 - pr/255/docs/search.index/40fcfec120bb.js | 1 + pr/255/docs/search.index/4154473306f6.js | 1 - pr/255/docs/search.index/4165ec97becb.js | 1 + pr/255/docs/search.index/4179e32fae1c.js | 1 + pr/255/docs/search.index/4204d4b478b6.js | 1 + pr/255/docs/search.index/4296b91ec07a.js | 1 + pr/255/docs/search.index/42b912b0d8d6.js | 1 + pr/255/docs/search.index/43625da5722d.js | 1 + pr/255/docs/search.index/4365fc23c2e2.js | 1 - pr/255/docs/search.index/440ac285a659.js | 1 + pr/255/docs/search.index/442799c14c6f.js | 1 - pr/255/docs/search.index/44630589167e.js | 1 + pr/255/docs/search.index/44a3f431018f.js | 1 + pr/255/docs/search.index/44a79dbac07c.js | 1 - pr/255/docs/search.index/44f8510a4206.js | 1 + pr/255/docs/search.index/4508fe205566.js | 1 + pr/255/docs/search.index/4599163a6a37.js | 1 + pr/255/docs/search.index/45caa4397354.js | 1 - pr/255/docs/search.index/45d12af4ff3b.js | 1 + pr/255/docs/search.index/45e872f24307.js | 1 - pr/255/docs/search.index/45f4fbda75f7.js | 1 - pr/255/docs/search.index/4682f9d07fab.js | 1 + pr/255/docs/search.index/46b30dba3752.js | 1 + pr/255/docs/search.index/47b13875e45c.js | 1 + pr/255/docs/search.index/47cdb0491b20.js | 1 + pr/255/docs/search.index/47d3233d790f.js | 1 + pr/255/docs/search.index/47fa58ac1f7e.js | 1 - pr/255/docs/search.index/481e68f578df.js | 1 - pr/255/docs/search.index/4821942f57b5.js | 1 - pr/255/docs/search.index/48917fd6b226.js | 1 + pr/255/docs/search.index/48b3ceed3817.js | 1 + pr/255/docs/search.index/48b9c2df65c3.js | 1 - pr/255/docs/search.index/48d55f753fb7.js | 1 + pr/255/docs/search.index/4909652ee282.js | 1 + pr/255/docs/search.index/49d47034aeca.js | 1 - pr/255/docs/search.index/49f51c99ba82.js | 1 - pr/255/docs/search.index/4a10d1b50063.js | 1 + pr/255/docs/search.index/4a662a061b37.js | 1 - pr/255/docs/search.index/4a809c839d91.js | 1 - pr/255/docs/search.index/4a869b28035c.js | 1 + pr/255/docs/search.index/4ac32d6f5fe0.js | 1 - pr/255/docs/search.index/4b168eb35e34.js | 1 - pr/255/docs/search.index/4b2753b82fcd.js | 1 - pr/255/docs/search.index/4b3a70d5ace1.js | 1 - pr/255/docs/search.index/4b88b05de3be.js | 1 + pr/255/docs/search.index/4bc2f7dbadf5.js | 1 - pr/255/docs/search.index/4bf42a7ae759.js | 1 + pr/255/docs/search.index/4bf63ac4398b.js | 1 - pr/255/docs/search.index/4c291219c272.js | 1 - pr/255/docs/search.index/4c96afa0c0be.js | 1 - pr/255/docs/search.index/4d1ba35b8882.js | 1 + pr/255/docs/search.index/4d63d12f11e5.js | 1 - pr/255/docs/search.index/4d826694c35e.js | 1 + pr/255/docs/search.index/4e0c6b87a738.js | 1 - pr/255/docs/search.index/4e3799776c96.js | 1 + pr/255/docs/search.index/4e4aaeeb80ed.js | 1 + pr/255/docs/search.index/4e720ea46bc3.js | 1 - pr/255/docs/search.index/4eb88f9761c0.js | 1 + pr/255/docs/search.index/4f2436d925ad.js | 1 + pr/255/docs/search.index/4f554ad18979.js | 1 - pr/255/docs/search.index/4fa3a94ba9bc.js | 1 + pr/255/docs/search.index/4fab115143ff.js | 1 + pr/255/docs/search.index/5037f3c0b285.js | 1 - pr/255/docs/search.index/50c4c9dd70c1.js | 1 - pr/255/docs/search.index/512cfed374c5.js | 1 - pr/255/docs/search.index/5161b276f515.js | 1 - pr/255/docs/search.index/520fc5a0c8db.js | 1 - pr/255/docs/search.index/5259902f1872.js | 1 + pr/255/docs/search.index/52a47b654b95.js | 1 - pr/255/docs/search.index/52a660a476b8.js | 1 - pr/255/docs/search.index/53206e8cf266.js | 1 - pr/255/docs/search.index/53369ac5a189.js | 1 + pr/255/docs/search.index/5347b986d048.js | 1 + pr/255/docs/search.index/53c1218b1076.js | 1 - pr/255/docs/search.index/53d3e59dd54f.js | 1 - pr/255/docs/search.index/5452a8cd2f09.js | 1 - pr/255/docs/search.index/5456fb44b43c.js | 1 - pr/255/docs/search.index/547e81c6465c.js | 1 + pr/255/docs/search.index/54c99bfc02b4.js | 1 - pr/255/docs/search.index/550f9f8ba786.js | 1 - pr/255/docs/search.index/5535895d7e1a.js | 1 - pr/255/docs/search.index/556039691422.js | 1 + pr/255/docs/search.index/55eb9c789f72.js | 1 - pr/255/docs/search.index/56fbecce9190.js | 1 + pr/255/docs/search.index/570e64122582.js | 1 - pr/255/docs/search.index/5726b451fa74.js | 1 - pr/255/docs/search.index/574d932e9c29.js | 1 + pr/255/docs/search.index/577580cd62c1.js | 1 + pr/255/docs/search.index/57f124ccc65e.js | 1 + pr/255/docs/search.index/57fa81511bf9.js | 1 + pr/255/docs/search.index/5833b407ef6d.js | 1 + pr/255/docs/search.index/58539c8b579b.js | 1 + pr/255/docs/search.index/587c8d82fabf.js | 1 - pr/255/docs/search.index/588805b23add.js | 1 + pr/255/docs/search.index/590f4c9d8e22.js | 1 + pr/255/docs/search.index/59c419e706d0.js | 1 - pr/255/docs/search.index/5a23f547788d.js | 1 + pr/255/docs/search.index/5a45b3b18493.js | 1 + pr/255/docs/search.index/5a5100ed4a84.js | 1 - pr/255/docs/search.index/5a6385e2310f.js | 1 + pr/255/docs/search.index/5a77bebba663.js | 1 - pr/255/docs/search.index/5a813a4820e0.js | 1 + pr/255/docs/search.index/5ae4a918d2e4.js | 1 + pr/255/docs/search.index/5c2e611e8037.js | 1 - pr/255/docs/search.index/5c64021fc741.js | 1 + pr/255/docs/search.index/5cc356801927.js | 1 - pr/255/docs/search.index/5d03104f5b36.js | 1 - pr/255/docs/search.index/5d359e55eab7.js | 1 + pr/255/docs/search.index/5dcae36ab7a9.js | 1 - pr/255/docs/search.index/5dd964887ac3.js | 1 + pr/255/docs/search.index/5e27fec6e119.js | 1 - pr/255/docs/search.index/5e990d199296.js | 1 - pr/255/docs/search.index/5f3aaa0e45e4.js | 1 - pr/255/docs/search.index/5f5fc12a19de.js | 1 - pr/255/docs/search.index/602d50ba42fc.js | 1 - pr/255/docs/search.index/6043b7b1f86b.js | 1 - pr/255/docs/search.index/60bbd1af8668.js | 1 - pr/255/docs/search.index/611bcb3d4014.js | 1 + pr/255/docs/search.index/6133a24a21bd.js | 1 - pr/255/docs/search.index/61b0c88b9449.js | 1 - pr/255/docs/search.index/61d6cf934531.js | 1 - pr/255/docs/search.index/61e64371195c.js | 1 - pr/255/docs/search.index/61e80bc02385.js | 1 - pr/255/docs/search.index/62030eb677af.js | 1 + pr/255/docs/search.index/6373129d4310.js | 1 - pr/255/docs/search.index/6383b6d7c4f5.js | 1 - pr/255/docs/search.index/63a6d2637da3.js | 1 - pr/255/docs/search.index/64129e8e0e98.js | 1 - pr/255/docs/search.index/642a5cb13021.js | 1 + pr/255/docs/search.index/6465615c7c4e.js | 1 + pr/255/docs/search.index/64816476bdd2.js | 1 + pr/255/docs/search.index/648a36bbbcb1.js | 1 + pr/255/docs/search.index/64a47a036ee9.js | 1 + pr/255/docs/search.index/64d11c8fb329.js | 1 + pr/255/docs/search.index/64e752cb7ef8.js | 1 + pr/255/docs/search.index/64eb9b668729.js | 1 + pr/255/docs/search.index/65694b9e3122.js | 1 + pr/255/docs/search.index/657321230ec5.js | 1 - pr/255/docs/search.index/659cd1b8f458.js | 1 - pr/255/docs/search.index/65b95eb2cbb1.js | 1 - pr/255/docs/search.index/65e587e4fe56.js | 1 + pr/255/docs/search.index/65f055028fa9.js | 1 + pr/255/docs/search.index/66080551a4d4.js | 1 - pr/255/docs/search.index/660ac0c7b41d.js | 1 - pr/255/docs/search.index/663d3ccd45e8.js | 1 - pr/255/docs/search.index/672d94eeb5ad.js | 1 - pr/255/docs/search.index/678443ae36ae.js | 1 + pr/255/docs/search.index/679d38ece98b.js | 1 + pr/255/docs/search.index/679f4284e04c.js | 1 - pr/255/docs/search.index/67d96877f75a.js | 1 - pr/255/docs/search.index/67f7a312869a.js | 1 - pr/255/docs/search.index/681c1ab8da48.js | 1 - pr/255/docs/search.index/681f74d11d66.js | 1 + pr/255/docs/search.index/682a70b084b3.js | 1 - pr/255/docs/search.index/69247c51b33f.js | 1 - pr/255/docs/search.index/6977b4c99668.js | 1 + pr/255/docs/search.index/6978b4ea0875.js | 1 - pr/255/docs/search.index/69bf077966ff.js | 1 + pr/255/docs/search.index/6a74a6193ac1.js | 1 - pr/255/docs/search.index/6a91ed0cfbc4.js | 1 + pr/255/docs/search.index/6adf1d99a4d5.js | 1 + pr/255/docs/search.index/6b465541ac5c.js | 1 + pr/255/docs/search.index/6b51a243b1b9.js | 1 + pr/255/docs/search.index/6b5ec36867cc.js | 1 + pr/255/docs/search.index/6bc821d036fc.js | 1 - pr/255/docs/search.index/6bcf985f9cc0.js | 1 - pr/255/docs/search.index/6bdb48f6e8fe.js | 1 + pr/255/docs/search.index/6c11604302a6.js | 1 + pr/255/docs/search.index/6c19dc66c62e.js | 1 - pr/255/docs/search.index/6c2ea040f627.js | 1 + pr/255/docs/search.index/6c5b31781505.js | 1 - pr/255/docs/search.index/6c6bec7a76cc.js | 1 + pr/255/docs/search.index/6c87bbe255e2.js | 1 - pr/255/docs/search.index/6ca19f0a3313.js | 1 + pr/255/docs/search.index/6cc490e2f6c0.js | 1 - pr/255/docs/search.index/6ccad3bd4a7d.js | 1 + pr/255/docs/search.index/6da9782962b9.js | 1 + pr/255/docs/search.index/6e48f0d21453.js | 1 - pr/255/docs/search.index/6e4b7a20ef6a.js | 1 + pr/255/docs/search.index/6ee2f712ff40.js | 1 + pr/255/docs/search.index/6fcb853616ae.js | 1 + pr/255/docs/search.index/70212e5b30bb.js | 1 - pr/255/docs/search.index/711db6f37c54.js | 1 + pr/255/docs/search.index/713ea441eaa3.js | 1 + pr/255/docs/search.index/71646ec45998.js | 1 - pr/255/docs/search.index/71e93f057075.js | 1 - pr/255/docs/search.index/72352df403a5.js | 1 + pr/255/docs/search.index/729a3ef57c7a.js | 1 - pr/255/docs/search.index/729ca138be4c.js | 1 - pr/255/docs/search.index/731dde1dce82.js | 1 + pr/255/docs/search.index/734aaab2a00b.js | 1 + pr/255/docs/search.index/7489318a49dc.js | 1 + pr/255/docs/search.index/74c41d060fa6.js | 1 - pr/255/docs/search.index/75b83b34138f.js | 1 + pr/255/docs/search.index/7601f1395e7f.js | 1 - pr/255/docs/search.index/76f46ceef4bd.js | 1 - pr/255/docs/search.index/7707a0af636d.js | 1 + pr/255/docs/search.index/77281c5ced0c.js | 1 - pr/255/docs/search.index/77607e6e8760.js | 1 - pr/255/docs/search.index/77f373856497.js | 1 + pr/255/docs/search.index/78318d6c832f.js | 1 + pr/255/docs/search.index/7861667f4a43.js | 1 + pr/255/docs/search.index/789bd808f118.js | 1 - pr/255/docs/search.index/78e2e859c206.js | 1 - pr/255/docs/search.index/78f080218498.js | 1 + pr/255/docs/search.index/7a4fbb02a71b.js | 1 - pr/255/docs/search.index/7b1c227ec211.js | 1 - pr/255/docs/search.index/7b387f9a1467.js | 1 + pr/255/docs/search.index/7b6c1a81028e.js | 1 - pr/255/docs/search.index/7bb9d7afc6de.js | 1 - pr/255/docs/search.index/7bc6215ea521.js | 1 - pr/255/docs/search.index/7c19fbc10374.js | 1 - pr/255/docs/search.index/7c3ea2f4edb6.js | 1 - pr/255/docs/search.index/7c6d85f865c7.js | 1 - pr/255/docs/search.index/7c7b9eca657f.js | 1 - pr/255/docs/search.index/7ca0ef420c00.js | 1 - pr/255/docs/search.index/7cada5462b17.js | 1 - pr/255/docs/search.index/7ce0db9b2df8.js | 1 - pr/255/docs/search.index/7da0e5fc56e2.js | 1 - pr/255/docs/search.index/7de8caeba04a.js | 1 - pr/255/docs/search.index/7e247cb6de94.js | 1 + pr/255/docs/search.index/7e614ec002b9.js | 1 + pr/255/docs/search.index/7ebc0d37a846.js | 1 + pr/255/docs/search.index/7f51efe5046e.js | 1 + pr/255/docs/search.index/7fbcc8b0cc40.js | 1 - pr/255/docs/search.index/7fc1150b9f0e.js | 1 - pr/255/docs/search.index/7fc1930a76ba.js | 1 + pr/255/docs/search.index/desc/d59362727558.js | 1 + pr/255/docs/search.index/desc/ee2830ff879e.js | 1 - .../docs/search.index/entry/23e89d8be7e8.js | 1 + .../docs/search.index/entry/ebf157109a27.js | 1 - .../search.index/function/0a18a7c168e3.js | 1 + .../search.index/function/e0bd020fee7e.js | 1 - .../generic_inverted_index/76f3213be5b5.js | 1 + .../generic_inverted_index/770510825e02.js | 1 - pr/255/docs/search.index/name/52ee5dc5acb9.js | 1 + pr/255/docs/search.index/name/8263a00c4c8a.js | 1 - .../normalizedName/479d9533fdd1.js | 1 - .../normalizedName/9cdde8eea858.js | 1 + pr/255/docs/search.index/path/3e0347ff70ce.js | 1 + pr/255/docs/search.index/path/8f03486c42f1.js | 1 - pr/255/docs/search.index/root.js | 2 +- pr/255/docs/search.index/type/23b66083c01c.js | 1 - pr/255/docs/search.index/type/ccb5a8e6883b.js | 1 + pr/255/docs/src/bench/lib.rs.html | 12 +- pr/255/docs/src/bench/stats.rs.html | 2 +- pr/255/docs/src/bulk/bulk.rs.html | 2 +- pr/255/docs/src/iroh_quinn/connection.rs.html | 14 +- pr/255/docs/src/iroh_quinn/endpoint.rs.html | 1739 ++- pr/255/docs/src/iroh_quinn/incoming.rs.html | 2 +- pr/255/docs/src/iroh_quinn/lib.rs.html | 196 +- .../docs/src/iroh_quinn/recv_stream.rs.html | 24 +- .../docs/src/iroh_quinn/runtime/mod.rs.html | 14 +- .../docs/src/iroh_quinn/runtime/smol.rs.html | 6 +- .../docs/src/iroh_quinn/runtime/tokio.rs.html | 6 +- .../docs/src/iroh_quinn/send_stream.rs.html | 612 +- .../src/iroh_quinn_proto/config/mod.rs.html | 141 +- .../congestion/bbr/mod.rs.html | 802 +- .../connection/assembler.rs.html | 2 +- .../connection/datagrams.rs.html | 137 +- .../iroh_quinn_proto/connection/mod.rs.html | 11922 ++++++++-------- .../iroh_quinn_proto/connection/paths.rs.html | 4 +- .../connection/spaces.rs.html | 4 +- .../iroh_quinn_proto/crypto/rustls.rs.html | 6 +- .../src/iroh_quinn_proto/endpoint.rs.html | 2563 ++-- .../docs/src/iroh_quinn_proto/frame.rs.html | 4277 +++--- pr/255/docs/src/iroh_quinn_proto/lib.rs.html | 693 +- .../docs/src/iroh_quinn_proto/packet.rs.html | 6 +- .../range_set/array_range_set.rs.html | 307 +- .../iroh_quinn_proto/transport_error.rs.html | 8 +- .../transport_parameters.rs.html | 1299 +- pr/255/docs/src/iroh_quinn_udp/lib.rs.html | 236 +- pr/255/docs/src/iroh_quinn_udp/unix.rs.html | 2013 ++- pr/255/docs/src/perf/lib.rs.html | 6 +- .../docs/trait.impl/core/clone/trait.Clone.js | 4 +- pr/255/docs/trait.impl/core/cmp/trait.Eq.js | 4 +- .../trait.impl/core/cmp/trait.PartialEq.js | 4 +- .../docs/trait.impl/core/error/trait.Error.js | 4 +- .../docs/trait.impl/core/fmt/trait.Debug.js | 4 +- .../docs/trait.impl/core/fmt/trait.Display.js | 4 +- .../core/future/future/trait.Future.js | 4 +- .../docs/trait.impl/core/marker/trait.Copy.js | 4 +- .../trait.impl/core/marker/trait.Freeze.js | 4 +- .../docs/trait.impl/core/marker/trait.Send.js | 4 +- .../core/marker/trait.StructuralPartialEq.js | 4 +- .../docs/trait.impl/core/marker/trait.Sync.js | 4 +- .../trait.impl/core/marker/trait.Unpin.js | 4 +- .../core/marker/trait.UnsafeUnpin.js | 4 +- .../panic/unwind_safe/trait.RefUnwindSafe.js | 4 +- .../panic/unwind_safe/trait.UnwindSafe.js | 4 +- .../futures_core/stream/trait.Stream.js | 9 + 591 files changed, 14647 insertions(+), 14102 deletions(-) create mode 100644 pr/255/docs/iroh_quinn/path/struct.AddressDiscovery.html create mode 100644 pr/255/docs/iroh_quinn/path/struct.ClosePath.html create mode 100644 pr/255/docs/iroh_quinn/struct.AddressDiscovery.html create mode 100644 pr/255/docs/iroh_quinn/struct.ClosePath.html create mode 100644 pr/255/docs/iroh_quinn/struct.InvalidCid.html create mode 100644 pr/255/docs/iroh_quinn_proto/connection/struct.MultipathNotNegotiated.html create mode 100644 pr/255/docs/iroh_quinn_proto/enum.MaybeFrame.html create mode 100644 pr/255/docs/iroh_quinn_proto/frame/enum.MaybeFrame.html create mode 100644 pr/255/docs/iroh_quinn_proto/frame/struct.DatagramInfo.html create mode 100644 pr/255/docs/iroh_quinn_proto/frame/struct.InvalidFrameId.html create mode 100644 pr/255/docs/iroh_quinn_proto/frame/struct.StreamInfo.html create mode 100644 pr/255/docs/iroh_quinn_proto/struct.DatagramInfo.html create mode 100644 pr/255/docs/iroh_quinn_proto/struct.InvalidFrameId.html create mode 100644 pr/255/docs/iroh_quinn_proto/struct.MultipathNotNegotiated.html create mode 100644 pr/255/docs/iroh_quinn_proto/struct.StreamInfo.html create mode 100644 pr/255/docs/search.index/00037727d41b.js create mode 100644 pr/255/docs/search.index/001277e366cd.js create mode 100644 pr/255/docs/search.index/0095923ba754.js delete mode 100644 pr/255/docs/search.index/00c07f35c6ce.js create mode 100644 pr/255/docs/search.index/00f09416a63d.js create mode 100644 pr/255/docs/search.index/00f55497d47e.js delete mode 100644 pr/255/docs/search.index/01806ef5b5d6.js delete mode 100644 pr/255/docs/search.index/01d48ddd05cf.js delete mode 100644 pr/255/docs/search.index/01f5bffda89c.js create mode 100644 pr/255/docs/search.index/024f75b34b20.js delete mode 100644 pr/255/docs/search.index/02f80e846705.js delete mode 100644 pr/255/docs/search.index/030aa7192f47.js delete mode 100644 pr/255/docs/search.index/030abe455d20.js delete mode 100644 pr/255/docs/search.index/035c9d3c036b.js delete mode 100644 pr/255/docs/search.index/04219d6c5f1f.js delete mode 100644 pr/255/docs/search.index/045e5265a54f.js delete mode 100644 pr/255/docs/search.index/04786c4690da.js delete mode 100644 pr/255/docs/search.index/054086f1f577.js create mode 100644 pr/255/docs/search.index/05c72ebeb6e8.js create mode 100644 pr/255/docs/search.index/05cf24e46b23.js create mode 100644 pr/255/docs/search.index/05e417058650.js delete mode 100644 pr/255/docs/search.index/05f4c9420eb7.js delete mode 100644 pr/255/docs/search.index/0615a2bf5050.js create mode 100644 pr/255/docs/search.index/06a55ef026d4.js create mode 100644 pr/255/docs/search.index/0773c651efc1.js delete mode 100644 pr/255/docs/search.index/07b12fe46ce8.js delete mode 100644 pr/255/docs/search.index/07bca17b1c6a.js delete mode 100644 pr/255/docs/search.index/081380447331.js create mode 100644 pr/255/docs/search.index/082c33a78589.js create mode 100644 pr/255/docs/search.index/0842ec51c54a.js create mode 100644 pr/255/docs/search.index/08b434a15736.js delete mode 100644 pr/255/docs/search.index/0933b5050388.js delete mode 100644 pr/255/docs/search.index/096a32f3fb06.js delete mode 100644 pr/255/docs/search.index/09c6ace039aa.js create mode 100644 pr/255/docs/search.index/09f0b7b1cb10.js create mode 100644 pr/255/docs/search.index/0adb0f113264.js delete mode 100644 pr/255/docs/search.index/0aebd591215a.js create mode 100644 pr/255/docs/search.index/0b049d31f2d1.js create mode 100644 pr/255/docs/search.index/0b8810d9f049.js delete mode 100644 pr/255/docs/search.index/0b9da5e00812.js create mode 100644 pr/255/docs/search.index/0bfb65fd762c.js create mode 100644 pr/255/docs/search.index/0c4100bc39d6.js create mode 100644 pr/255/docs/search.index/0cad63531c89.js delete mode 100644 pr/255/docs/search.index/0d24876322d0.js delete mode 100644 pr/255/docs/search.index/0d377ac14863.js delete mode 100644 pr/255/docs/search.index/0d5508bf0207.js create mode 100644 pr/255/docs/search.index/0dbe969ddebd.js delete mode 100644 pr/255/docs/search.index/0dd31cbab4cc.js create mode 100644 pr/255/docs/search.index/0e34ce7f7192.js delete mode 100644 pr/255/docs/search.index/0e61017bc68b.js create mode 100644 pr/255/docs/search.index/0f103fffad43.js create mode 100644 pr/255/docs/search.index/0f1e1d1cc48f.js create mode 100644 pr/255/docs/search.index/0f434453b623.js create mode 100644 pr/255/docs/search.index/0f835c2828ff.js delete mode 100644 pr/255/docs/search.index/0fa74a34d33c.js create mode 100644 pr/255/docs/search.index/1017c7914851.js delete mode 100644 pr/255/docs/search.index/103f1ba9c2d5.js delete mode 100644 pr/255/docs/search.index/10e19c9358f8.js create mode 100644 pr/255/docs/search.index/1119c1193e11.js create mode 100644 pr/255/docs/search.index/118928699d86.js delete mode 100644 pr/255/docs/search.index/1198e3f6eeb3.js create mode 100644 pr/255/docs/search.index/11ac60f101c2.js delete mode 100644 pr/255/docs/search.index/125b8dc7d658.js create mode 100644 pr/255/docs/search.index/125c69e2afa8.js create mode 100644 pr/255/docs/search.index/12aab9d7ac8d.js create mode 100644 pr/255/docs/search.index/1323b5cdf876.js delete mode 100644 pr/255/docs/search.index/1344897c571c.js create mode 100644 pr/255/docs/search.index/138a5af4d179.js create mode 100644 pr/255/docs/search.index/1409f2140ee5.js create mode 100644 pr/255/docs/search.index/1455b2c199cd.js delete mode 100644 pr/255/docs/search.index/1499361f517d.js create mode 100644 pr/255/docs/search.index/1511e66727f1.js create mode 100644 pr/255/docs/search.index/1552619586d7.js delete mode 100644 pr/255/docs/search.index/1566e3c31611.js create mode 100644 pr/255/docs/search.index/16045633eb64.js delete mode 100644 pr/255/docs/search.index/16681f81c6a9.js create mode 100644 pr/255/docs/search.index/16e43e96c3f0.js delete mode 100644 pr/255/docs/search.index/16f90e0495ca.js delete mode 100644 pr/255/docs/search.index/17747f0de527.js delete mode 100644 pr/255/docs/search.index/182d04459856.js create mode 100644 pr/255/docs/search.index/18c051295b43.js delete mode 100644 pr/255/docs/search.index/18e4b0fb83df.js create mode 100644 pr/255/docs/search.index/19476e380db8.js delete mode 100644 pr/255/docs/search.index/19c9a628ac91.js delete mode 100644 pr/255/docs/search.index/19f55295ffb7.js delete mode 100644 pr/255/docs/search.index/1a01681e7d77.js create mode 100644 pr/255/docs/search.index/1a59836e6e94.js create mode 100644 pr/255/docs/search.index/1a6a4539ae89.js create mode 100644 pr/255/docs/search.index/1a6b9bf2988f.js create mode 100644 pr/255/docs/search.index/1b5a76a5a4b0.js delete mode 100644 pr/255/docs/search.index/1b6ac9e761aa.js delete mode 100644 pr/255/docs/search.index/1b82b05116c9.js delete mode 100644 pr/255/docs/search.index/1b97b26c3ac1.js create mode 100644 pr/255/docs/search.index/1bf5442726c7.js create mode 100644 pr/255/docs/search.index/1c84f4d721b0.js delete mode 100644 pr/255/docs/search.index/1ce4c2454b0a.js create mode 100644 pr/255/docs/search.index/1cf369215e3f.js create mode 100644 pr/255/docs/search.index/1e602721a639.js delete mode 100644 pr/255/docs/search.index/1ea1f2d3747a.js create mode 100644 pr/255/docs/search.index/1f0367152a3f.js create mode 100644 pr/255/docs/search.index/1f11eee293c6.js create mode 100644 pr/255/docs/search.index/1f1d2b61eca6.js create mode 100644 pr/255/docs/search.index/1f6d06e60df8.js create mode 100644 pr/255/docs/search.index/1f850a139dfa.js create mode 100644 pr/255/docs/search.index/1fb072ef9a66.js create mode 100644 pr/255/docs/search.index/2025f39bb570.js delete mode 100644 pr/255/docs/search.index/2098306f4d34.js create mode 100644 pr/255/docs/search.index/20b4057caa1a.js delete mode 100644 pr/255/docs/search.index/21a899f4f99b.js create mode 100644 pr/255/docs/search.index/21bd1e52c0f9.js create mode 100644 pr/255/docs/search.index/21f7fe292e8a.js create mode 100644 pr/255/docs/search.index/225a0e027688.js create mode 100644 pr/255/docs/search.index/24eee7d39d3b.js create mode 100644 pr/255/docs/search.index/252df03c9a7b.js create mode 100644 pr/255/docs/search.index/254b4b1e845b.js delete mode 100644 pr/255/docs/search.index/25a54c1ab6e0.js create mode 100644 pr/255/docs/search.index/25b74d0e760c.js delete mode 100644 pr/255/docs/search.index/266311e2892f.js delete mode 100644 pr/255/docs/search.index/266827f9a2f0.js create mode 100644 pr/255/docs/search.index/266afabfc690.js create mode 100644 pr/255/docs/search.index/2670b688dca6.js delete mode 100644 pr/255/docs/search.index/267d2567696a.js create mode 100644 pr/255/docs/search.index/26e84f065723.js create mode 100644 pr/255/docs/search.index/27198464c776.js create mode 100644 pr/255/docs/search.index/271cda0a044e.js create mode 100644 pr/255/docs/search.index/27677e8fce37.js create mode 100644 pr/255/docs/search.index/278470046fa3.js create mode 100644 pr/255/docs/search.index/27bc89bd5eae.js delete mode 100644 pr/255/docs/search.index/27f8ec34bd1f.js delete mode 100644 pr/255/docs/search.index/281cb83843d4.js delete mode 100644 pr/255/docs/search.index/28827f9488f7.js create mode 100644 pr/255/docs/search.index/28d0ee3283f9.js create mode 100644 pr/255/docs/search.index/29912ff817d4.js create mode 100644 pr/255/docs/search.index/29ffaf5f711f.js create mode 100644 pr/255/docs/search.index/2a2e9d6f638a.js delete mode 100644 pr/255/docs/search.index/2adb3d0bf2d8.js create mode 100644 pr/255/docs/search.index/2b09faf5f111.js create mode 100644 pr/255/docs/search.index/2b35726b25dd.js delete mode 100644 pr/255/docs/search.index/2b92810a6565.js delete mode 100644 pr/255/docs/search.index/2bed9cec1d26.js create mode 100644 pr/255/docs/search.index/2ce4b4057c53.js create mode 100644 pr/255/docs/search.index/2d2960f9b8d4.js delete mode 100644 pr/255/docs/search.index/2e7d78ea0cfe.js delete mode 100644 pr/255/docs/search.index/2e882e6bf78f.js create mode 100644 pr/255/docs/search.index/2eb9123a10fd.js delete mode 100644 pr/255/docs/search.index/2f0bd76574d0.js delete mode 100644 pr/255/docs/search.index/2f2a8a6c3151.js create mode 100644 pr/255/docs/search.index/2fac3831697f.js create mode 100644 pr/255/docs/search.index/2fd891c7dddc.js delete mode 100644 pr/255/docs/search.index/30399b5c8304.js delete mode 100644 pr/255/docs/search.index/30a16458d826.js create mode 100644 pr/255/docs/search.index/30d311112226.js delete mode 100644 pr/255/docs/search.index/30e9b37f1a9e.js delete mode 100644 pr/255/docs/search.index/311e77def7dc.js create mode 100644 pr/255/docs/search.index/312e80bd916b.js delete mode 100644 pr/255/docs/search.index/3161d4c1c9e3.js delete mode 100644 pr/255/docs/search.index/325f77b8029e.js delete mode 100644 pr/255/docs/search.index/32c27beceb5f.js create mode 100644 pr/255/docs/search.index/33aa643b366e.js create mode 100644 pr/255/docs/search.index/33b38805b1c6.js delete mode 100644 pr/255/docs/search.index/3407cc8b99a3.js delete mode 100644 pr/255/docs/search.index/34726ae306d9.js create mode 100644 pr/255/docs/search.index/348567575911.js delete mode 100644 pr/255/docs/search.index/34bb2b1a0ab9.js create mode 100644 pr/255/docs/search.index/34e0c30a19a6.js delete mode 100644 pr/255/docs/search.index/35cd5d54f947.js delete mode 100644 pr/255/docs/search.index/36de07894256.js delete mode 100644 pr/255/docs/search.index/3748eeff0c66.js delete mode 100644 pr/255/docs/search.index/378531389b4a.js delete mode 100644 pr/255/docs/search.index/37cfa41c8509.js delete mode 100644 pr/255/docs/search.index/3872754cddc0.js delete mode 100644 pr/255/docs/search.index/38ae726b5e74.js create mode 100644 pr/255/docs/search.index/38cb6e24cf5d.js create mode 100644 pr/255/docs/search.index/3922a16454e0.js create mode 100644 pr/255/docs/search.index/392fb1700c95.js create mode 100644 pr/255/docs/search.index/393da311e403.js delete mode 100644 pr/255/docs/search.index/39c20340df78.js create mode 100644 pr/255/docs/search.index/3a529860f4ab.js create mode 100644 pr/255/docs/search.index/3a6bd631205f.js delete mode 100644 pr/255/docs/search.index/3a74000719ff.js create mode 100644 pr/255/docs/search.index/3a74061c4f9f.js create mode 100644 pr/255/docs/search.index/3adb9518fd74.js create mode 100644 pr/255/docs/search.index/3afe7bef2754.js create mode 100644 pr/255/docs/search.index/3b1e455f5b16.js delete mode 100644 pr/255/docs/search.index/3b786721c45c.js delete mode 100644 pr/255/docs/search.index/3bd565fd40d0.js create mode 100644 pr/255/docs/search.index/3ce49910eea7.js delete mode 100644 pr/255/docs/search.index/3d41efe337a8.js delete mode 100644 pr/255/docs/search.index/3d4983faf394.js delete mode 100644 pr/255/docs/search.index/3eb044d68081.js create mode 100644 pr/255/docs/search.index/3f16c6444948.js delete mode 100644 pr/255/docs/search.index/3f1d867bdbec.js delete mode 100644 pr/255/docs/search.index/3f2790b84249.js delete mode 100644 pr/255/docs/search.index/3f76acc9c4c0.js delete mode 100644 pr/255/docs/search.index/3fe667d21e90.js delete mode 100644 pr/255/docs/search.index/402127170d10.js delete mode 100644 pr/255/docs/search.index/40672655bcf1.js delete mode 100644 pr/255/docs/search.index/4083ed670548.js create mode 100644 pr/255/docs/search.index/409b3322db69.js create mode 100644 pr/255/docs/search.index/40d03efa707b.js delete mode 100644 pr/255/docs/search.index/40d41dda421f.js delete mode 100644 pr/255/docs/search.index/40e5df003d92.js delete mode 100644 pr/255/docs/search.index/40fc47699d53.js create mode 100644 pr/255/docs/search.index/40fcfec120bb.js delete mode 100644 pr/255/docs/search.index/4154473306f6.js create mode 100644 pr/255/docs/search.index/4165ec97becb.js create mode 100644 pr/255/docs/search.index/4179e32fae1c.js create mode 100644 pr/255/docs/search.index/4204d4b478b6.js create mode 100644 pr/255/docs/search.index/4296b91ec07a.js create mode 100644 pr/255/docs/search.index/42b912b0d8d6.js create mode 100644 pr/255/docs/search.index/43625da5722d.js delete mode 100644 pr/255/docs/search.index/4365fc23c2e2.js create mode 100644 pr/255/docs/search.index/440ac285a659.js delete mode 100644 pr/255/docs/search.index/442799c14c6f.js create mode 100644 pr/255/docs/search.index/44630589167e.js create mode 100644 pr/255/docs/search.index/44a3f431018f.js delete mode 100644 pr/255/docs/search.index/44a79dbac07c.js create mode 100644 pr/255/docs/search.index/44f8510a4206.js create mode 100644 pr/255/docs/search.index/4508fe205566.js create mode 100644 pr/255/docs/search.index/4599163a6a37.js delete mode 100644 pr/255/docs/search.index/45caa4397354.js create mode 100644 pr/255/docs/search.index/45d12af4ff3b.js delete mode 100644 pr/255/docs/search.index/45e872f24307.js delete mode 100644 pr/255/docs/search.index/45f4fbda75f7.js create mode 100644 pr/255/docs/search.index/4682f9d07fab.js create mode 100644 pr/255/docs/search.index/46b30dba3752.js create mode 100644 pr/255/docs/search.index/47b13875e45c.js create mode 100644 pr/255/docs/search.index/47cdb0491b20.js create mode 100644 pr/255/docs/search.index/47d3233d790f.js delete mode 100644 pr/255/docs/search.index/47fa58ac1f7e.js delete mode 100644 pr/255/docs/search.index/481e68f578df.js delete mode 100644 pr/255/docs/search.index/4821942f57b5.js create mode 100644 pr/255/docs/search.index/48917fd6b226.js create mode 100644 pr/255/docs/search.index/48b3ceed3817.js delete mode 100644 pr/255/docs/search.index/48b9c2df65c3.js create mode 100644 pr/255/docs/search.index/48d55f753fb7.js create mode 100644 pr/255/docs/search.index/4909652ee282.js delete mode 100644 pr/255/docs/search.index/49d47034aeca.js delete mode 100644 pr/255/docs/search.index/49f51c99ba82.js create mode 100644 pr/255/docs/search.index/4a10d1b50063.js delete mode 100644 pr/255/docs/search.index/4a662a061b37.js delete mode 100644 pr/255/docs/search.index/4a809c839d91.js create mode 100644 pr/255/docs/search.index/4a869b28035c.js delete mode 100644 pr/255/docs/search.index/4ac32d6f5fe0.js delete mode 100644 pr/255/docs/search.index/4b168eb35e34.js delete mode 100644 pr/255/docs/search.index/4b2753b82fcd.js delete mode 100644 pr/255/docs/search.index/4b3a70d5ace1.js create mode 100644 pr/255/docs/search.index/4b88b05de3be.js delete mode 100644 pr/255/docs/search.index/4bc2f7dbadf5.js create mode 100644 pr/255/docs/search.index/4bf42a7ae759.js delete mode 100644 pr/255/docs/search.index/4bf63ac4398b.js delete mode 100644 pr/255/docs/search.index/4c291219c272.js delete mode 100644 pr/255/docs/search.index/4c96afa0c0be.js create mode 100644 pr/255/docs/search.index/4d1ba35b8882.js delete mode 100644 pr/255/docs/search.index/4d63d12f11e5.js create mode 100644 pr/255/docs/search.index/4d826694c35e.js delete mode 100644 pr/255/docs/search.index/4e0c6b87a738.js create mode 100644 pr/255/docs/search.index/4e3799776c96.js create mode 100644 pr/255/docs/search.index/4e4aaeeb80ed.js delete mode 100644 pr/255/docs/search.index/4e720ea46bc3.js create mode 100644 pr/255/docs/search.index/4eb88f9761c0.js create mode 100644 pr/255/docs/search.index/4f2436d925ad.js delete mode 100644 pr/255/docs/search.index/4f554ad18979.js create mode 100644 pr/255/docs/search.index/4fa3a94ba9bc.js create mode 100644 pr/255/docs/search.index/4fab115143ff.js delete mode 100644 pr/255/docs/search.index/5037f3c0b285.js delete mode 100644 pr/255/docs/search.index/50c4c9dd70c1.js delete mode 100644 pr/255/docs/search.index/512cfed374c5.js delete mode 100644 pr/255/docs/search.index/5161b276f515.js delete mode 100644 pr/255/docs/search.index/520fc5a0c8db.js create mode 100644 pr/255/docs/search.index/5259902f1872.js delete mode 100644 pr/255/docs/search.index/52a47b654b95.js delete mode 100644 pr/255/docs/search.index/52a660a476b8.js delete mode 100644 pr/255/docs/search.index/53206e8cf266.js create mode 100644 pr/255/docs/search.index/53369ac5a189.js create mode 100644 pr/255/docs/search.index/5347b986d048.js delete mode 100644 pr/255/docs/search.index/53c1218b1076.js delete mode 100644 pr/255/docs/search.index/53d3e59dd54f.js delete mode 100644 pr/255/docs/search.index/5452a8cd2f09.js delete mode 100644 pr/255/docs/search.index/5456fb44b43c.js create mode 100644 pr/255/docs/search.index/547e81c6465c.js delete mode 100644 pr/255/docs/search.index/54c99bfc02b4.js delete mode 100644 pr/255/docs/search.index/550f9f8ba786.js delete mode 100644 pr/255/docs/search.index/5535895d7e1a.js create mode 100644 pr/255/docs/search.index/556039691422.js delete mode 100644 pr/255/docs/search.index/55eb9c789f72.js create mode 100644 pr/255/docs/search.index/56fbecce9190.js delete mode 100644 pr/255/docs/search.index/570e64122582.js delete mode 100644 pr/255/docs/search.index/5726b451fa74.js create mode 100644 pr/255/docs/search.index/574d932e9c29.js create mode 100644 pr/255/docs/search.index/577580cd62c1.js create mode 100644 pr/255/docs/search.index/57f124ccc65e.js create mode 100644 pr/255/docs/search.index/57fa81511bf9.js create mode 100644 pr/255/docs/search.index/5833b407ef6d.js create mode 100644 pr/255/docs/search.index/58539c8b579b.js delete mode 100644 pr/255/docs/search.index/587c8d82fabf.js create mode 100644 pr/255/docs/search.index/588805b23add.js create mode 100644 pr/255/docs/search.index/590f4c9d8e22.js delete mode 100644 pr/255/docs/search.index/59c419e706d0.js create mode 100644 pr/255/docs/search.index/5a23f547788d.js create mode 100644 pr/255/docs/search.index/5a45b3b18493.js delete mode 100644 pr/255/docs/search.index/5a5100ed4a84.js create mode 100644 pr/255/docs/search.index/5a6385e2310f.js delete mode 100644 pr/255/docs/search.index/5a77bebba663.js create mode 100644 pr/255/docs/search.index/5a813a4820e0.js create mode 100644 pr/255/docs/search.index/5ae4a918d2e4.js delete mode 100644 pr/255/docs/search.index/5c2e611e8037.js create mode 100644 pr/255/docs/search.index/5c64021fc741.js delete mode 100644 pr/255/docs/search.index/5cc356801927.js delete mode 100644 pr/255/docs/search.index/5d03104f5b36.js create mode 100644 pr/255/docs/search.index/5d359e55eab7.js delete mode 100644 pr/255/docs/search.index/5dcae36ab7a9.js create mode 100644 pr/255/docs/search.index/5dd964887ac3.js delete mode 100644 pr/255/docs/search.index/5e27fec6e119.js delete mode 100644 pr/255/docs/search.index/5e990d199296.js delete mode 100644 pr/255/docs/search.index/5f3aaa0e45e4.js delete mode 100644 pr/255/docs/search.index/5f5fc12a19de.js delete mode 100644 pr/255/docs/search.index/602d50ba42fc.js delete mode 100644 pr/255/docs/search.index/6043b7b1f86b.js delete mode 100644 pr/255/docs/search.index/60bbd1af8668.js create mode 100644 pr/255/docs/search.index/611bcb3d4014.js delete mode 100644 pr/255/docs/search.index/6133a24a21bd.js delete mode 100644 pr/255/docs/search.index/61b0c88b9449.js delete mode 100644 pr/255/docs/search.index/61d6cf934531.js delete mode 100644 pr/255/docs/search.index/61e64371195c.js delete mode 100644 pr/255/docs/search.index/61e80bc02385.js create mode 100644 pr/255/docs/search.index/62030eb677af.js delete mode 100644 pr/255/docs/search.index/6373129d4310.js delete mode 100644 pr/255/docs/search.index/6383b6d7c4f5.js delete mode 100644 pr/255/docs/search.index/63a6d2637da3.js delete mode 100644 pr/255/docs/search.index/64129e8e0e98.js create mode 100644 pr/255/docs/search.index/642a5cb13021.js create mode 100644 pr/255/docs/search.index/6465615c7c4e.js create mode 100644 pr/255/docs/search.index/64816476bdd2.js create mode 100644 pr/255/docs/search.index/648a36bbbcb1.js create mode 100644 pr/255/docs/search.index/64a47a036ee9.js create mode 100644 pr/255/docs/search.index/64d11c8fb329.js create mode 100644 pr/255/docs/search.index/64e752cb7ef8.js create mode 100644 pr/255/docs/search.index/64eb9b668729.js create mode 100644 pr/255/docs/search.index/65694b9e3122.js delete mode 100644 pr/255/docs/search.index/657321230ec5.js delete mode 100644 pr/255/docs/search.index/659cd1b8f458.js delete mode 100644 pr/255/docs/search.index/65b95eb2cbb1.js create mode 100644 pr/255/docs/search.index/65e587e4fe56.js create mode 100644 pr/255/docs/search.index/65f055028fa9.js delete mode 100644 pr/255/docs/search.index/66080551a4d4.js delete mode 100644 pr/255/docs/search.index/660ac0c7b41d.js delete mode 100644 pr/255/docs/search.index/663d3ccd45e8.js delete mode 100644 pr/255/docs/search.index/672d94eeb5ad.js create mode 100644 pr/255/docs/search.index/678443ae36ae.js create mode 100644 pr/255/docs/search.index/679d38ece98b.js delete mode 100644 pr/255/docs/search.index/679f4284e04c.js delete mode 100644 pr/255/docs/search.index/67d96877f75a.js delete mode 100644 pr/255/docs/search.index/67f7a312869a.js delete mode 100644 pr/255/docs/search.index/681c1ab8da48.js create mode 100644 pr/255/docs/search.index/681f74d11d66.js delete mode 100644 pr/255/docs/search.index/682a70b084b3.js delete mode 100644 pr/255/docs/search.index/69247c51b33f.js create mode 100644 pr/255/docs/search.index/6977b4c99668.js delete mode 100644 pr/255/docs/search.index/6978b4ea0875.js create mode 100644 pr/255/docs/search.index/69bf077966ff.js delete mode 100644 pr/255/docs/search.index/6a74a6193ac1.js create mode 100644 pr/255/docs/search.index/6a91ed0cfbc4.js create mode 100644 pr/255/docs/search.index/6adf1d99a4d5.js create mode 100644 pr/255/docs/search.index/6b465541ac5c.js create mode 100644 pr/255/docs/search.index/6b51a243b1b9.js create mode 100644 pr/255/docs/search.index/6b5ec36867cc.js delete mode 100644 pr/255/docs/search.index/6bc821d036fc.js delete mode 100644 pr/255/docs/search.index/6bcf985f9cc0.js create mode 100644 pr/255/docs/search.index/6bdb48f6e8fe.js create mode 100644 pr/255/docs/search.index/6c11604302a6.js delete mode 100644 pr/255/docs/search.index/6c19dc66c62e.js create mode 100644 pr/255/docs/search.index/6c2ea040f627.js delete mode 100644 pr/255/docs/search.index/6c5b31781505.js create mode 100644 pr/255/docs/search.index/6c6bec7a76cc.js delete mode 100644 pr/255/docs/search.index/6c87bbe255e2.js create mode 100644 pr/255/docs/search.index/6ca19f0a3313.js delete mode 100644 pr/255/docs/search.index/6cc490e2f6c0.js create mode 100644 pr/255/docs/search.index/6ccad3bd4a7d.js create mode 100644 pr/255/docs/search.index/6da9782962b9.js delete mode 100644 pr/255/docs/search.index/6e48f0d21453.js create mode 100644 pr/255/docs/search.index/6e4b7a20ef6a.js create mode 100644 pr/255/docs/search.index/6ee2f712ff40.js create mode 100644 pr/255/docs/search.index/6fcb853616ae.js delete mode 100644 pr/255/docs/search.index/70212e5b30bb.js create mode 100644 pr/255/docs/search.index/711db6f37c54.js create mode 100644 pr/255/docs/search.index/713ea441eaa3.js delete mode 100644 pr/255/docs/search.index/71646ec45998.js delete mode 100644 pr/255/docs/search.index/71e93f057075.js create mode 100644 pr/255/docs/search.index/72352df403a5.js delete mode 100644 pr/255/docs/search.index/729a3ef57c7a.js delete mode 100644 pr/255/docs/search.index/729ca138be4c.js create mode 100644 pr/255/docs/search.index/731dde1dce82.js create mode 100644 pr/255/docs/search.index/734aaab2a00b.js create mode 100644 pr/255/docs/search.index/7489318a49dc.js delete mode 100644 pr/255/docs/search.index/74c41d060fa6.js create mode 100644 pr/255/docs/search.index/75b83b34138f.js delete mode 100644 pr/255/docs/search.index/7601f1395e7f.js delete mode 100644 pr/255/docs/search.index/76f46ceef4bd.js create mode 100644 pr/255/docs/search.index/7707a0af636d.js delete mode 100644 pr/255/docs/search.index/77281c5ced0c.js delete mode 100644 pr/255/docs/search.index/77607e6e8760.js create mode 100644 pr/255/docs/search.index/77f373856497.js create mode 100644 pr/255/docs/search.index/78318d6c832f.js create mode 100644 pr/255/docs/search.index/7861667f4a43.js delete mode 100644 pr/255/docs/search.index/789bd808f118.js delete mode 100644 pr/255/docs/search.index/78e2e859c206.js create mode 100644 pr/255/docs/search.index/78f080218498.js delete mode 100644 pr/255/docs/search.index/7a4fbb02a71b.js delete mode 100644 pr/255/docs/search.index/7b1c227ec211.js create mode 100644 pr/255/docs/search.index/7b387f9a1467.js delete mode 100644 pr/255/docs/search.index/7b6c1a81028e.js delete mode 100644 pr/255/docs/search.index/7bb9d7afc6de.js delete mode 100644 pr/255/docs/search.index/7bc6215ea521.js delete mode 100644 pr/255/docs/search.index/7c19fbc10374.js delete mode 100644 pr/255/docs/search.index/7c3ea2f4edb6.js delete mode 100644 pr/255/docs/search.index/7c6d85f865c7.js delete mode 100644 pr/255/docs/search.index/7c7b9eca657f.js delete mode 100644 pr/255/docs/search.index/7ca0ef420c00.js delete mode 100644 pr/255/docs/search.index/7cada5462b17.js delete mode 100644 pr/255/docs/search.index/7ce0db9b2df8.js delete mode 100644 pr/255/docs/search.index/7da0e5fc56e2.js delete mode 100644 pr/255/docs/search.index/7de8caeba04a.js create mode 100644 pr/255/docs/search.index/7e247cb6de94.js create mode 100644 pr/255/docs/search.index/7e614ec002b9.js create mode 100644 pr/255/docs/search.index/7ebc0d37a846.js create mode 100644 pr/255/docs/search.index/7f51efe5046e.js delete mode 100644 pr/255/docs/search.index/7fbcc8b0cc40.js delete mode 100644 pr/255/docs/search.index/7fc1150b9f0e.js create mode 100644 pr/255/docs/search.index/7fc1930a76ba.js create mode 100644 pr/255/docs/search.index/desc/d59362727558.js delete mode 100644 pr/255/docs/search.index/desc/ee2830ff879e.js create mode 100644 pr/255/docs/search.index/entry/23e89d8be7e8.js delete mode 100644 pr/255/docs/search.index/entry/ebf157109a27.js create mode 100644 pr/255/docs/search.index/function/0a18a7c168e3.js delete mode 100644 pr/255/docs/search.index/function/e0bd020fee7e.js create mode 100644 pr/255/docs/search.index/generic_inverted_index/76f3213be5b5.js delete mode 100644 pr/255/docs/search.index/generic_inverted_index/770510825e02.js create mode 100644 pr/255/docs/search.index/name/52ee5dc5acb9.js delete mode 100644 pr/255/docs/search.index/name/8263a00c4c8a.js delete mode 100644 pr/255/docs/search.index/normalizedName/479d9533fdd1.js create mode 100644 pr/255/docs/search.index/normalizedName/9cdde8eea858.js create mode 100644 pr/255/docs/search.index/path/3e0347ff70ce.js delete mode 100644 pr/255/docs/search.index/path/8f03486c42f1.js delete mode 100644 pr/255/docs/search.index/type/23b66083c01c.js create mode 100644 pr/255/docs/search.index/type/ccb5a8e6883b.js create mode 100644 pr/255/docs/trait.impl/futures_core/stream/trait.Stream.js diff --git a/pr/255/docs/bulk/struct.ClientStats.html b/pr/255/docs/bulk/struct.ClientStats.html index 91c85df24..7f78e9897 100644 --- a/pr/255/docs/bulk/struct.ClientStats.html +++ b/pr/255/docs/bulk/struct.ClientStats.html @@ -1,7 +1,7 @@ ClientStats in bulk - Rust

ClientStats

Struct ClientStats 

Source
pub(crate) struct ClientStats {
     pub(crate) upload_stats: Stats,
     pub(crate) download_stats: Stats,
-}

Fields§

§upload_stats: Stats§download_stats: Stats

Implementations§

Source§

impl ClientStats

Source

pub fn print(&self, client_id: usize)

Trait Implementations§

Source§

impl Default for ClientStats

Source§

fn default() -> ClientStats

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +}

Fields§

§upload_stats: Stats§download_stats: Stats

Implementations§

Source§

impl ClientStats

Source

pub(crate) fn print(&self, client_id: usize)

Trait Implementations§

Source§

impl Default for ClientStats

Source§

fn default() -> ClientStats

Returns the “default value” for a type. 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/255/docs/iroh_quinn/all.html b/pr/255/docs/iroh_quinn/all.html index 9efe65aca..4ca955f58 100644 --- a/pr/255/docs/iroh_quinn/all.html +++ b/pr/255/docs/iroh_quinn/all.html @@ -1 +1 @@ -List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

\ No newline at end of file +List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/congestion/index.html b/pr/255/docs/iroh_quinn/congestion/index.html index 2216af227..8873423fc 100644 --- a/pr/255/docs/iroh_quinn/congestion/index.html +++ b/pr/255/docs/iroh_quinn/congestion/index.html @@ -1,2 +1,2 @@ -iroh_quinn::congestion - Rust

Module congestion

Module congestion 

Source
Expand description

Logic for controlling the rate at which data is sent

+iroh_quinn::congestion - Rust

Module congestion

Module congestion 

Source
Expand description

Logic for controlling the rate at which data is sent

Structs§

Bbr
Experimental! Use at your own risk.
BbrConfig
Configuration for the Bbr congestion controller
ControllerMetrics
Common congestion controller metrics
Cubic
The RFC8312 congestion controller, as widely used for TCP
CubicConfig
Configuration for the Cubic congestion controller
NewReno
A simple, standard congestion controller
NewRenoConfig
Configuration for the NewReno congestion controller

Traits§

Controller
Common interface for different congestion controllers
ControllerFactory
Constructs controllers on demand
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html b/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html index 630fc0fa4..a2f2eaedc 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html @@ -4,27 +4,27 @@ Based on google’s quiche implementation https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control. More discussion and links at https://groups.google.com/g/bbr-dev.

Implementations§

Source§

impl Bbr

Source

pub fn new(config: Arc<BbrConfig>, current_mtu: u16) -> Bbr

Construct a state using the given config and current time now

-

Trait Implementations§

Source§

impl Clone for Bbr

Source§

fn clone(&self) -> Bbr

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 Controller for Bbr

Source§

fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64)

One or more packets were just sent
Source§

fn on_ack( +

Trait Implementations§

Source§

impl Clone for Bbr

Source§

fn clone(&self) -> Bbr

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 Controller for Bbr

Source§

fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64)

One or more packets were just sent
Source§

fn on_ack( &mut self, now: Instant, sent: Instant, bytes: u64, app_limited: bool, rtt: &RttEstimator, -)

Packet deliveries were confirmed Read more
Source§

fn on_end_acks( +)

Packet deliveries were confirmed Read more
Source§

fn on_end_acks( &mut self, now: Instant, in_flight: u64, app_limited: bool, largest_packet_num_acked: Option<u64>, -)

Packets are acked in batches, all with the same now argument. This indicates one of those batches has completed.
Source§

fn on_congestion_event( +)

Packets are acked in batches, all with the same now argument. This indicates one of those batches has completed.
Source§

fn on_congestion_event( &mut self, _now: Instant, _sent: Instant, _is_persistent_congestion: bool, _is_ecn: bool, lost_bytes: u64, -)

Packets were deemed lost or marked congested Read more
Source§

fn on_mtu_update(&mut self, new_mtu: u16)

The known MTU for the current network path has been updated
Source§

fn window(&self) -> u64

Number of ack-eliciting bytes that may be in flight
Source§

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled
Source§

fn clone_box(&self) -> Box<dyn Controller>

Duplicate the controller’s state
Source§

fn initial_window(&self) -> u64

Initial congestion window
Source§

fn into_any(self: Box<Bbr>) -> Box<dyn Any>

Returns Self for use in down-casting to extract implementation details
Source§

fn on_spurious_congestion_event(&mut self)

Packets were incorrectly deemed lost Read more
Source§

impl Debug for Bbr

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Bbr

§

impl RefUnwindSafe for Bbr

§

impl Send for Bbr

§

impl Sync for Bbr

§

impl Unpin for Bbr

§

impl UnwindSafe for Bbr

Blanket Implementations§

Source§

impl<T> Any for T
where +)

Packets were deemed lost or marked congested Read more
Source§

fn on_mtu_update(&mut self, new_mtu: u16)

The known MTU for the current network path has been updated
Source§

fn window(&self) -> u64

Number of ack-eliciting bytes that may be in flight
Source§

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled
Source§

fn clone_box(&self) -> Box<dyn Controller>

Duplicate the controller’s state
Source§

fn initial_window(&self) -> u64

Initial congestion window
Source§

fn into_any(self: Box<Bbr>) -> Box<dyn Any>

Returns Self for use in down-casting to extract implementation details
Source§

fn on_spurious_congestion_event(&mut self)

Packets were incorrectly deemed lost Read more
Source§

impl Debug for Bbr

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Bbr

§

impl RefUnwindSafe for Bbr

§

impl Send for Bbr

§

impl Sync for Bbr

§

impl Unpin for Bbr

§

impl UnwindSafe for Bbr

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/255/docs/iroh_quinn/congestion/struct.BbrConfig.html b/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html index f340fb3e2..c931fff20 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html @@ -1,11 +1,11 @@ -BbrConfig in iroh_quinn::congestion - Rust

BbrConfig

Struct BbrConfig 

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

Configuration for the Bbr congestion controller

-

Implementations§

Source§

impl BbrConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut BbrConfig

Default limit on the amount of outstanding data in bytes.

+BbrConfig in iroh_quinn::congestion - Rust

BbrConfig

Struct BbrConfig 

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

Configuration for the Bbr congestion controller

+

Implementations§

Source§

impl BbrConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut BbrConfig

Default limit on the amount of outstanding data in bytes.

Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

-

Trait Implementations§

Source§

impl Clone for BbrConfig

Source§

fn clone(&self) -> BbrConfig

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 ControllerFactory for BbrConfig

Trait Implementations§

Source§

impl Clone for BbrConfig

Source§

fn clone(&self) -> BbrConfig

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 ControllerFactory for BbrConfig

Source§

fn build( self: Arc<BbrConfig>, _now: Instant, current_mtu: u16, -) -> Box<dyn Controller>

Construct a fresh Controller
Source§

impl Debug for BbrConfig

Source§

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

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

impl Default for BbrConfig

Source§

fn default() -> BbrConfig

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +) -> Box<dyn Controller>

Construct a fresh Controller
Source§

impl Debug for BbrConfig

Source§

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

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

impl Default for BbrConfig

Source§

fn default() -> BbrConfig

Returns the “default value” for a type. 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/255/docs/iroh_quinn/congestion/trait.Controller.html b/pr/255/docs/iroh_quinn/congestion/trait.Controller.html index 6fd6a4943..c582370df 100644 --- a/pr/255/docs/iroh_quinn/congestion/trait.Controller.html +++ b/pr/255/docs/iroh_quinn/congestion/trait.Controller.html @@ -76,4 +76,4 @@ application data prior to receiving these acknowledgements.

This function is called when all packets that were deemed lost (for instance because of packet reordering) are acknowledged after the congestion event was raised.

Source

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled

-

Implementors§

\ No newline at end of file +

Implementors§

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html b/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html index 056571893..5f8ab4fc4 100644 --- a/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html +++ b/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html @@ -7,4 +7,4 @@ ) -> Box<dyn Controller>; }
Expand description

Constructs controllers on demand

Required Methods§

Source

fn build(self: Arc<Self>, now: Instant, current_mtu: u16) -> Box<dyn Controller>

Construct a fresh Controller

-

Implementors§

Source§

impl ControllerFactory for BbrConfig

Source§

impl ControllerFactory for CubicConfig

Source§

impl ControllerFactory for NewRenoConfig

\ No newline at end of file +

Implementors§

Source§

impl ControllerFactory for BbrConfig

Source§

impl ControllerFactory for CubicConfig

Source§

impl ControllerFactory for NewRenoConfig

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html index 00fbff019..228863942 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html @@ -1,6 +1,6 @@ QuicClientConfig in iroh_quinn::crypto::rustls - Rust

QuicClientConfig

Struct QuicClientConfig 

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

A QUIC-compatible TLS client configuration

Quinn implicitly constructs a QuicClientConfig with reasonable defaults within -ClientConfig::with_root_certificates() and ClientConfig::with_platform_verifier(). +ClientConfig::with_root_certificates() and ClientConfig::try_with_platform_verifier(). Alternatively, QuicClientConfig’s TryFrom implementation can be used to wrap around a custom [rustls::ClientConfig], in which case care should be taken around certain points:

Source§

impl PartialEq for Side

Source§

fn eq(&self, other: &Side) -> 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 PartialOrd for Side

Source§

fn partial_cmp(&self, other: &Side) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
Source§

impl Copy for Side

Source§

impl Eq for Side

Source§

impl StructuralPartialEq for Side

Auto Trait Implementations§

§

impl Freeze for Side

§

impl RefUnwindSafe for Side

§

impl Send for Side

§

impl Sync for Side

§

impl Unpin for Side

§

impl UnwindSafe for Side

Blanket Implementations§

Source§

impl<T> Any for T
where +the >= operator. Read more

Source§

impl Copy for Side

Source§

impl Eq for Side

Source§

impl StructuralPartialEq for Side

Auto Trait Implementations§

§

impl Freeze for Side

§

impl RefUnwindSafe for Side

§

impl Send for Side

§

impl Sync for Side

§

impl Unpin for Side

§

impl UnwindSafe for Side

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/255/docs/iroh_quinn/enum.StoppedError.html b/pr/255/docs/iroh_quinn/enum.StoppedError.html index 42ac78ed6..ca10923e6 100644 --- a/pr/255/docs/iroh_quinn/enum.StoppedError.html +++ b/pr/255/docs/iroh_quinn/enum.StoppedError.html @@ -1,4 +1,4 @@ -StoppedError in iroh_quinn - Rust

StoppedError

Enum StoppedError 

Source
pub enum StoppedError {
+StoppedError in iroh_quinn - Rust

StoppedError

Enum StoppedError 

Source
pub enum StoppedError {
     ConnectionLost(ConnectionError),
     ZeroRttRejected,
 }
Expand description

Errors that arise while monitoring for a send stream stop from the peer

@@ -6,8 +6,8 @@
§

ZeroRttRejected

This was a 0-RTT stream and the server rejected it

Can only occur on clients for 0-RTT streams, which can be opened using Connecting::into_0rtt().

-

Trait Implementations§

Source§

impl Clone for StoppedError

Source§

fn clone(&self) -> StoppedError

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 StoppedError

Source§

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

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

impl Display for StoppedError

Source§

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

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

impl Error for StoppedError

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 StoppedError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<StoppedError> for Error

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl From<StoppedError> for WriteError

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for StoppedError

Source§

fn eq(&self, other: &StoppedError) -> 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 StoppedError

Source§

impl StructuralPartialEq for StoppedError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for StoppedError

Source§

fn clone(&self) -> StoppedError

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 StoppedError

Source§

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

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

impl Display for StoppedError

Source§

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

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

impl Error for StoppedError

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 StoppedError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl From<StoppedError> for Error

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl From<StoppedError> for WriteError

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for StoppedError

Source§

fn eq(&self, other: &StoppedError) -> 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 StoppedError

Source§

impl StructuralPartialEq for StoppedError

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/255/docs/iroh_quinn/enum.WriteError.html b/pr/255/docs/iroh_quinn/enum.WriteError.html index 48fd44e36..ea02311ac 100644 --- a/pr/255/docs/iroh_quinn/enum.WriteError.html +++ b/pr/255/docs/iroh_quinn/enum.WriteError.html @@ -1,4 +1,4 @@ -WriteError in iroh_quinn - Rust

WriteError

Enum WriteError 

Source
pub enum WriteError {
+WriteError in iroh_quinn - Rust

WriteError

Enum WriteError 

Source
pub enum WriteError {
     Stopped(VarInt),
     ConnectionLost(ConnectionError),
     ClosedStream,
@@ -11,8 +11,8 @@
 
§

ZeroRttRejected

This was a 0-RTT stream and the server rejected it

Can only occur on clients for 0-RTT streams, which can be opened using Connecting::into_0rtt().

-

Trait Implementations§

Source§

impl Clone for WriteError

Source§

fn clone(&self) -> WriteError

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 WriteError

Source§

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

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

impl Display for WriteError

Source§

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

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

impl Error for WriteError

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<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> 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<StoppedError> for WriteError

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl From<WriteError> for Error

Source§

fn from(x: WriteError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for WriteError

Source§

fn eq(&self, other: &WriteError) -> 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 WriteError

Source§

impl StructuralPartialEq for WriteError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for WriteError

Source§

fn clone(&self) -> WriteError

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 WriteError

Source§

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

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

impl Display for WriteError

Source§

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

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

impl Error for WriteError

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<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> 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<StoppedError> for WriteError

Source§

fn from(x: StoppedError) -> Self

Converts to this type from the input type.
Source§

impl From<WriteError> for Error

Source§

fn from(x: WriteError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for WriteError

Source§

fn eq(&self, other: &WriteError) -> 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 WriteError

Source§

impl StructuralPartialEq for WriteError

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/255/docs/iroh_quinn/index.html b/pr/255/docs/iroh_quinn/index.html index 281df6ef6..f0adc5bb4 100644 --- a/pr/255/docs/iroh_quinn/index.html +++ b/pr/255/docs/iroh_quinn/index.html @@ -1,4 +1,4 @@ -iroh_quinn - Rust

Crate iroh_quinn

Crate iroh_quinn 

Source
Expand description

QUIC transport protocol implementation

+iroh_quinn - Rust

Crate iroh_quinn

Crate iroh_quinn 

Source
Expand description

QUIC transport protocol implementation

QUIC is a modern transport protocol addressing shortcomings of TCP, such as head-of-line blocking, poor security, slow handshakes, and inefficient congestion control. This crate provides a portable userspace implementation. It @@ -29,6 +29,6 @@ server, it is useful for a QUIC server to be identified by a certificate signed authority. If this is infeasible–for example, if servers are short-lived or not associated with a domain name–then as with TLS, self-signed certificates can be used to provide encryption alone.

-

Re-exports§

pub use rustls;
pub use udp;

Modules§

congestion
Logic for controlling the rate at which data is sent
crypto
Traits and implementations for the QUIC cryptography protocol

Structs§

Accept
Future produced by Endpoint::accept
AcceptBi
Future produced by Connection::accept_bi
AcceptUni
Future produced by Connection::accept_uni
AckFrequencyConfig
Parameters for controlling the peer’s acknowledgement frequency
ApplicationClose
Reason given by an application for closing the connection
BloomTokenLog
Bloom filter-based TokenLog
Chunk
A chunk of data from the receive stream
ClientConfig
Configuration for outgoing connections
ClosedStream
Error indicating that a stream has not been opened or has already been finished or reset
Connecting
In-progress connection attempt future
Connection
A QUIC connection.
ConnectionClose
Reason given by the transport for closing the connection
ConnectionId
Protocol-level identifier for a connection.
ConnectionStats
Connection statistics
Endpoint
A QUIC endpoint.
EndpointConfig
Global configuration for the endpoint, affecting all connections
EndpointStats
Statistics on Endpoint activity
FrameStats
Number of frames transmitted or received of each frame type
IdleTimeout
Maximum duration of inactivity to accept before timing out the connection
Incoming
An incoming connection for which the server has not yet begun its part of the handshake
IncomingFuture
Basic adapter to let Incoming be await-ed like a Connecting
MtuDiscoveryConfig
Parameters governing MTU discovery.
NoneTokenLog
Null implementation of TokenLog, which never accepts tokens
NoneTokenStore
Null implementation of TokenStore, which does not store any tokens
OnClosed
Future returned by Connection::on_closed
OpenBi
Future produced by Connection::open_bi
OpenPath
Future produced by crate::Connection::open_path
OpenUni
Future produced by Connection::open_uni
Path
An open (Multi)Path
PathId
Id representing different paths when using multipath extension
PathStats
Statistics related to a transmission path
QlogConfig
Configuration for qlog trace logging.
QlogFileFactory
Enables writing qlog traces to a directory.
ReadDatagram
Future produced by Connection::read_datagram
RecvStream
A stream that can only be used to receive data
RetryError
Error for attempting to retry an Incoming which already bears a token from a previous retry
SendDatagram
Future produced by Connection::send_datagram_wait
SendStream
A stream that can only be used to send data
ServerConfig
Parameters governing incoming connections
SmolRuntime
A Quinn runtime for smol
StdSystemTime
Default implementation of TimeSource
StreamId
Identifier for a stream within a particular connection
TokenMemoryCache
TokenStore implementation that stores up to N tokens per server name for up to a +

Re-exports§

pub use rustls;
pub use udp;

Modules§

congestion
Logic for controlling the rate at which data is sent
crypto
Traits and implementations for the QUIC cryptography protocol

Structs§

Accept
Future produced by Endpoint::accept
AcceptBi
Future produced by Connection::accept_bi
AcceptUni
Future produced by Connection::accept_uni
AckFrequencyConfig
Parameters for controlling the peer’s acknowledgement frequency
AddressDiscovery
Stream produced by Path::observed_external_addr
ApplicationClose
Reason given by an application for closing the connection
BloomTokenLog
Bloom filter-based TokenLog
Chunk
A chunk of data from the receive stream
ClientConfig
Configuration for outgoing connections
ClosePath
Future produced by Path::close
ClosedStream
Error indicating that a stream has not been opened or has already been finished or reset
Connecting
In-progress connection attempt future
Connection
A QUIC connection.
ConnectionClose
Reason given by the transport for closing the connection
ConnectionId
Protocol-level identifier for a connection.
ConnectionStats
Connection statistics
Endpoint
A QUIC endpoint.
EndpointConfig
Global configuration for the endpoint, affecting all connections
EndpointStats
Statistics on Endpoint activity
FrameStats
Number of frames transmitted or received of each frame type
IdleTimeout
Maximum duration of inactivity to accept before timing out the connection
Incoming
An incoming connection for which the server has not yet begun its part of the handshake
IncomingFuture
Basic adapter to let Incoming be await-ed like a Connecting
InvalidCid
The connection ID was not recognized by the ConnectionIdGenerator
MtuDiscoveryConfig
Parameters governing MTU discovery.
NoneTokenLog
Null implementation of TokenLog, which never accepts tokens
NoneTokenStore
Null implementation of TokenStore, which does not store any tokens
OnClosed
Future returned by Connection::on_closed
OpenBi
Future produced by Connection::open_bi
OpenPath
Future produced by crate::Connection::open_path
OpenUni
Future produced by Connection::open_uni
Path
An open (Multi)Path
PathId
Id representing different paths when using multipath extension
PathStats
Statistics related to a transmission path
QlogConfig
Configuration for qlog trace logging.
QlogFileFactory
Enables writing qlog traces to a directory.
ReadDatagram
Future produced by Connection::read_datagram
RecvStream
A stream that can only be used to receive data
RetryError
Error for attempting to retry an Incoming which already bears a token from a previous retry
SendDatagram
Future produced by Connection::send_datagram_wait
SendStream
A stream that can only be used to send data
ServerConfig
Parameters governing incoming connections
SmolRuntime
A Quinn runtime for smol
StdSystemTime
Default implementation of TimeSource
StreamId
Identifier for a stream within a particular connection
TokenMemoryCache
TokenStore implementation that stores up to N tokens per server name for up to a limited number of server names, in-memory
TokenReuseError
Error for when a validation token may have been reused
TokioRuntime
A Quinn runtime for Tokio
Transmit
An outgoing packet
TransportConfig
Parameters governing the core QUIC state machine
TransportErrorCode
Transport-level error code
UdpStats
Statistics about UDP datagrams transmitted or received on a connection
UnorderedRecvStream
A stream that can be used to receive data out-of-order.
ValidationTokenConfig
Configuration for sending and handling validation tokens in incoming connections
VarInt
An integer less than 2^62
VarIntBoundsExceeded
Error returned when constructing a VarInt from a value >= 2^62
WeakConnectionHandle
A handle to some connection internals, use with care.
Written
Indicates how many bytes and chunks had been transferred in a write operation
ZeroRttAccepted
Future that completes when a connection is fully established

Enums§

ConfigError
Errors in the configuration of an endpoint
ConnectError
Errors in the parameters being used to create a new connection
ConnectionError
Reasons why a connection might be lost
Dir
Whether a stream communicates data in both directions or only from the initiator
EcnCodepoint
Explicit congestion notification codepoint
FrameType
ReadError
Errors that arise from reading from a stream.
ReadExactError
Errors that arise from reading from a stream.
ReadToEndError
Errors from RecvStream::read_to_end
ResetError
Errors that arise while waiting for a stream to be reset
SendDatagramError
Errors that can arise when sending a datagram
Side
Whether an endpoint was the initiator of a connection
StoppedError
Errors that arise while monitoring for a send stream stop from the peer
WriteError
Errors that arise from writing to a stream

Traits§

AsyncTimer
Abstract implementation of an async timer for runtime independence
AsyncUdpSocket
Abstract implementation of a UDP socket for runtime independence
ConnectionIdGenerator
Generates connection IDs for incoming connections
QlogFactory
Constructs a QlogConfig for individual connections.
Runtime
Abstracts I/O and timer operations for runtime independence
TimeSource
Object to get current SystemTime
TokenLog
Responsible for limiting clients’ ability to reuse validation tokens
TokenStore
Responsible for storing validation tokens received from servers and retrieving them for use in subsequent connections
UdpSender
An object for asynchronously writing to an associated AsyncUdpSocket.

Functions§

default_runtime
Automatically select an appropriate runtime from those enabled at compile time
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/path/struct.AddressDiscovery.html b/pr/255/docs/iroh_quinn/path/struct.AddressDiscovery.html new file mode 100644 index 000000000..e4476ec35 --- /dev/null +++ b/pr/255/docs/iroh_quinn/path/struct.AddressDiscovery.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn/struct.AddressDiscovery.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/path/struct.ClosePath.html b/pr/255/docs/iroh_quinn/path/struct.ClosePath.html new file mode 100644 index 000000000..56c3283bf --- /dev/null +++ b/pr/255/docs/iroh_quinn/path/struct.ClosePath.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn/struct.ClosePath.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/sidebar-items.js b/pr/255/docs/iroh_quinn/sidebar-items.js index ae9bffc7f..2af1c653a 100644 --- a/pr/255/docs/iroh_quinn/sidebar-items.js +++ b/pr/255/docs/iroh_quinn/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"enum":["ConfigError","ConnectError","ConnectionError","Dir","EcnCodepoint","FrameType","ReadError","ReadExactError","ReadToEndError","ResetError","SendDatagramError","Side","StoppedError","WriteError"],"fn":["default_runtime"],"mod":["congestion","crypto"],"struct":["Accept","AcceptBi","AcceptUni","AckFrequencyConfig","ApplicationClose","BloomTokenLog","Chunk","ClientConfig","ClosedStream","Connecting","Connection","ConnectionClose","ConnectionId","ConnectionStats","Endpoint","EndpointConfig","EndpointStats","FrameStats","IdleTimeout","Incoming","IncomingFuture","MtuDiscoveryConfig","NoneTokenLog","NoneTokenStore","OnClosed","OpenBi","OpenPath","OpenUni","Path","PathId","PathStats","QlogConfig","QlogFileFactory","ReadDatagram","RecvStream","RetryError","SendDatagram","SendStream","ServerConfig","SmolRuntime","StdSystemTime","StreamId","TokenMemoryCache","TokenReuseError","TokioRuntime","Transmit","TransportConfig","TransportErrorCode","UdpStats","UnorderedRecvStream","ValidationTokenConfig","VarInt","VarIntBoundsExceeded","WeakConnectionHandle","Written","ZeroRttAccepted"],"trait":["AsyncTimer","AsyncUdpSocket","ConnectionIdGenerator","QlogFactory","Runtime","TimeSource","TokenLog","TokenStore","UdpSender"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"enum":["ConfigError","ConnectError","ConnectionError","Dir","EcnCodepoint","FrameType","ReadError","ReadExactError","ReadToEndError","ResetError","SendDatagramError","Side","StoppedError","WriteError"],"fn":["default_runtime"],"mod":["congestion","crypto"],"struct":["Accept","AcceptBi","AcceptUni","AckFrequencyConfig","AddressDiscovery","ApplicationClose","BloomTokenLog","Chunk","ClientConfig","ClosePath","ClosedStream","Connecting","Connection","ConnectionClose","ConnectionId","ConnectionStats","Endpoint","EndpointConfig","EndpointStats","FrameStats","IdleTimeout","Incoming","IncomingFuture","InvalidCid","MtuDiscoveryConfig","NoneTokenLog","NoneTokenStore","OnClosed","OpenBi","OpenPath","OpenUni","Path","PathId","PathStats","QlogConfig","QlogFileFactory","ReadDatagram","RecvStream","RetryError","SendDatagram","SendStream","ServerConfig","SmolRuntime","StdSystemTime","StreamId","TokenMemoryCache","TokenReuseError","TokioRuntime","Transmit","TransportConfig","TransportErrorCode","UdpStats","UnorderedRecvStream","ValidationTokenConfig","VarInt","VarIntBoundsExceeded","WeakConnectionHandle","Written","ZeroRttAccepted"],"trait":["AsyncTimer","AsyncUdpSocket","ConnectionIdGenerator","QlogFactory","Runtime","TimeSource","TokenLog","TokenStore","UdpSender"]}; \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/struct.Accept.html b/pr/255/docs/iroh_quinn/struct.Accept.html index 6e17e11a0..896bcd39f 100644 --- a/pr/255/docs/iroh_quinn/struct.Accept.html +++ b/pr/255/docs/iroh_quinn/struct.Accept.html @@ -1,6 +1,6 @@ -Accept in iroh_quinn - Rust

Accept

Struct Accept 

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

Future produced by Endpoint::accept

-

Trait Implementations§

Source§

impl Future for Accept<'_>

Source§

type Output = Option<Incoming>

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 Accept<'a>
where +Accept in iroh_quinn - Rust

Accept

Struct Accept 

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

Future produced by Endpoint::accept

+

Trait Implementations§

Source§

impl Future for Accept<'_>

Source§

type Output = Option<Incoming>

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 Accept<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

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

§

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

§

impl<'a> Send for Accept<'a>

§

impl<'a> Sync for Accept<'a>

§

impl<'a> !UnwindSafe for Accept<'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/255/docs/iroh_quinn/struct.AddressDiscovery.html b/pr/255/docs/iroh_quinn/struct.AddressDiscovery.html new file mode 100644 index 000000000..5bde10466 --- /dev/null +++ b/pr/255/docs/iroh_quinn/struct.AddressDiscovery.html @@ -0,0 +1,173 @@ +AddressDiscovery in iroh_quinn - 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( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Option<Self::Item>>

Attempt to pull out the next value of this stream, registering the +current task for wakeup if the value is not yet available, and returning +None if the stream is exhausted. Read more
§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the stream. 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.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
§

impl<S> StreamExt for S
where + S: Stream + ?Sized,

§

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

A convenience for calling [Stream::poll_next()] on !Unpin types.
§

fn next(&mut self) -> NextFuture<'_, Self>
where + Self: Unpin,

Retrieves the next item in the stream. Read more
§

fn try_next<T, E>(&mut self) -> TryNextFuture<'_, Self>
where + Self: Stream<Item = Result<T, E>> + Unpin,

Retrieves the next item in the stream. Read more
§

fn count(self) -> CountFuture<Self>
where + Self: Sized,

Counts the number of items in the stream. Read more
§

fn map<T, F>(self, f: F) -> Map<Self, F>
where + Self: Sized, + F: FnMut(Self::Item) -> T,

Maps items of the stream to new values using a closure. Read more
§

fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
where + Self: Sized, + U: Stream, + F: FnMut(Self::Item) -> U,

Maps items to streams and then concatenates them. Read more
§

fn flatten(self) -> Flatten<Self>
where + Self: Sized, + Self::Item: Stream,

Concatenates inner streams. Read more
§

fn then<F, Fut>(self, f: F) -> Then<Self, F, Fut>
where + Self: Sized, + F: FnMut(Self::Item) -> Fut, + Fut: Future,

Maps items of the stream to new values using an async closure. Read more
§

fn filter<P>(self, predicate: P) -> Filter<Self, P>
where + Self: Sized, + P: FnMut(&Self::Item) -> bool,

Keeps items of the stream for which predicate returns true. Read more
§

fn filter_map<T, F>(self, f: F) -> FilterMap<Self, F>
where + Self: Sized, + F: FnMut(Self::Item) -> Option<T>,

Filters and maps items of the stream using a closure. Read more
§

fn take(self, n: usize) -> Take<Self>
where + Self: Sized,

Takes only the first n items of the stream. Read more
§

fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
where + Self: Sized, + P: FnMut(&Self::Item) -> bool,

Takes items while predicate returns true. Read more
§

fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
where + Self: Sized, + P: FnMut(Self::Item) -> Option<B>,

Maps items while predicate returns Some. Read more
§

fn skip(self, n: usize) -> Skip<Self>
where + Self: Sized,

Skips the first n items of the stream. Read more
§

fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where + Self: Sized, + P: FnMut(&Self::Item) -> bool,

Skips items while predicate returns true. Read more
§

fn step_by(self, step: usize) -> StepBy<Self>
where + Self: Sized,

Yields every stepth item. Read more
§

fn chain<U>(self, other: U) -> Chain<Self, U>
where + Self: Sized, + U: Stream<Item = Self::Item>,

Appends another stream to the end of this one. Read more
§

fn cloned<'a, T>(self) -> Cloned<Self>
where + Self: Sized + Stream<Item = &'a T>, + T: Clone + 'a,

Clones all items. Read more
§

fn copied<'a, T>(self) -> Copied<Self>
where + Self: Sized + Stream<Item = &'a T>, + T: Copy + 'a,

Copies all items. Read more
§

fn collect<C>(self) -> CollectFuture<Self, C>
where + Self: Sized, + C: Default + Extend<Self::Item>,

Collects all items in the stream into a collection. Read more
§

fn try_collect<T, E, C>(self) -> TryCollectFuture<Self, C>
where + Self: Sized + Stream<Item = Result<T, E>>, + C: Default + Extend<T>,

Collects all items in the fallible stream into a collection. Read more
§

fn partition<B, P>(self, predicate: P) -> PartitionFuture<Self, P, B>
where + Self: Sized, + B: Default + Extend<Self::Item>, + P: FnMut(&Self::Item) -> bool,

Partitions items into those for which predicate is true and those for which it is +false, and then collects them into two collections. Read more
§

fn fold<T, F>(self, init: T, f: F) -> FoldFuture<Self, F, T>
where + Self: Sized, + F: FnMut(T, Self::Item) -> T,

Accumulates a computation over the stream. Read more
§

fn try_fold<T, E, F, B>( + &mut self, + init: B, + f: F, +) -> TryFoldFuture<'_, Self, F, B>
where + Self: Sized + Stream<Item = Result<T, E>> + Unpin, + F: FnMut(B, T) -> Result<B, E>,

Accumulates a fallible computation over the stream. Read more
§

fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
where + Self: Sized, + F: FnMut(&mut St, Self::Item) -> Option<B>,

Maps items of the stream to new values using a state value and a closure. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Fuses the stream so that it stops yielding items after the first None. Read more
§

fn cycle(self) -> Cycle<Self>
where + Self: Sized + Clone,

Repeats the stream from beginning to end, forever. Read more
§

fn enumerate(self) -> Enumerate<Self>
where + Self: Sized,

Enumerates items, mapping them to (index, item). Read more
§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where + Self: Sized, + F: FnMut(&Self::Item),

Calls a closure on each item and passes it on. Read more
§

fn nth(&mut self, n: usize) -> NthFuture<'_, Self>
where + Self: Unpin,

Gets the nth item of the stream. Read more
§

fn last(self) -> LastFuture<Self>
where + Self: Sized,

Returns the last item in the stream. Read more
§

fn find<P>(&mut self, predicate: P) -> FindFuture<'_, Self, P>
where + Self: Unpin, + P: FnMut(&Self::Item) -> bool,

Finds the first item of the stream for which predicate returns true. Read more
§

fn find_map<F, B>(&mut self, f: F) -> FindMapFuture<'_, Self, F>
where + Self: Unpin, + F: FnMut(Self::Item) -> Option<B>,

Applies a closure to items in the stream and returns the first Some result. Read more
§

fn position<P>(&mut self, predicate: P) -> PositionFuture<'_, Self, P>
where + Self: Unpin, + P: FnMut(Self::Item) -> bool,

Finds the index of the first item of the stream for which predicate returns true. Read more
§

fn all<P>(&mut self, predicate: P) -> AllFuture<'_, Self, P>
where + Self: Unpin, + P: FnMut(Self::Item) -> bool,

Tests if predicate returns true for all items in the stream. Read more
§

fn any<P>(&mut self, predicate: P) -> AnyFuture<'_, Self, P>
where + Self: Unpin, + P: FnMut(Self::Item) -> bool,

Tests if predicate returns true for any item in the stream. Read more
§

fn for_each<F>(self, f: F) -> ForEachFuture<Self, F>
where + Self: Sized, + F: FnMut(Self::Item),

Calls a closure on each item of the stream. Read more
§

fn try_for_each<F, E>(&mut self, f: F) -> TryForEachFuture<'_, Self, F>
where + Self: Unpin, + F: FnMut(Self::Item) -> Result<(), E>,

Calls a fallible closure on each item of the stream, stopping on first error. Read more
§

fn zip<U>(self, other: U) -> Zip<Self, U>
where + Self: Sized, + U: Stream,

Zips up two streams into a single stream of pairs. Read more
§

fn unzip<A, B, FromA, FromB>(self) -> UnzipFuture<Self, FromA, FromB>
where + FromA: Default + Extend<A>, + FromB: Default + Extend<B>, + Self: Sized + Stream<Item = (A, B)>,

Collects a stream of pairs into a pair of collections. Read more
§

fn or<S>(self, other: S) -> Or<Self, S>
where + Self: Sized, + S: Stream<Item = Self::Item>,

Merges with other stream, preferring items from self whenever both streams are ready. Read more
§

fn race<S>(self, other: S) -> Race<Self, S>
where + Self: Sized, + S: Stream<Item = Self::Item>,

Merges with other stream, with no preference for either stream when both are ready. Read more
§

fn drain(&mut self) -> Drain<'_, Self>

Yields all immediately available values from a stream. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Stream<Item = Self::Item> + Send + 'a>>
where + Self: Sized + Send + 'a,

Boxes the stream and changes its type to dyn Stream + Send + 'a. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Stream<Item = Self::Item> + 'a>>
where + Self: Sized + 'a,

Boxes the stream and changes its type to dyn Stream + 'a. Read more
§

impl<St> StreamExt for St
where + St: Stream + ?Sized,

§

fn next(&mut self) -> Next<'_, Self>
where + Self: Unpin,

Consumes and returns the next value in the stream or None if the +stream is finished. Read more
§

fn try_next<T, E>(&mut self) -> TryNext<'_, Self>
where + Self: Stream<Item = Result<T, E>> + Unpin,

Consumes and returns the next item in the stream. If an error is +encountered before the next item, the error is returned instead. Read more
§

fn map<T, F>(self, f: F) -> Map<Self, F>
where + F: FnMut(Self::Item) -> T, + Self: Sized,

Maps this stream’s items to a different type, returning a new stream of +the resulting type. Read more
§

fn map_while<T, F>(self, f: F) -> MapWhile<Self, F>
where + F: FnMut(Self::Item) -> Option<T>, + Self: Sized,

Map this stream’s items to a different type for as long as determined by +the provided closure. A stream of the target type will be returned, +which will yield elements until the closure returns None. Read more
§

fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized,

Maps this stream’s items asynchronously to a different type, returning a +new stream of the resulting type. Read more
§

fn merge<U>(self, other: U) -> Merge<Self, U>
where + U: Stream<Item = Self::Item>, + Self: Sized,

Combine two streams into one by interleaving the output of both as it +is produced. Read more
§

fn filter<F>(self, f: F) -> Filter<Self, F>
where + F: FnMut(&Self::Item) -> bool, + Self: Sized,

Filters the values produced by this stream according to the provided +predicate. Read more
§

fn filter_map<T, F>(self, f: F) -> FilterMap<Self, F>
where + F: FnMut(Self::Item) -> Option<T>, + Self: Sized,

Filters the values produced by this stream while simultaneously mapping +them to a different type according to the provided closure. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Creates a stream which ends after the first None. Read more
§

fn take(self, n: usize) -> Take<Self>
where + Self: Sized,

Creates a new stream of at most n items of the underlying stream. Read more
§

fn take_while<F>(self, f: F) -> TakeWhile<Self, F>
where + F: FnMut(&Self::Item) -> bool, + Self: Sized,

Take elements from this stream while the provided predicate +resolves to true. Read more
§

fn skip(self, n: usize) -> Skip<Self>
where + Self: Sized,

Creates a new stream that will skip the n first items of the +underlying stream. Read more
§

fn skip_while<F>(self, f: F) -> SkipWhile<Self, F>
where + F: FnMut(&Self::Item) -> bool, + Self: Sized,

Skip elements from the underlying stream while the provided predicate +resolves to true. Read more
§

fn all<F>(&mut self, f: F) -> AllFuture<'_, Self, F>
where + Self: Unpin, + F: FnMut(Self::Item) -> bool,

Tests if every element of the stream matches a predicate. Read more
§

fn any<F>(&mut self, f: F) -> AnyFuture<'_, Self, F>
where + Self: Unpin, + F: FnMut(Self::Item) -> bool,

Tests if any element of the stream matches a predicate. Read more
§

fn chain<U>(self, other: U) -> Chain<Self, U>
where + U: Stream<Item = Self::Item>, + Self: Sized,

Combine two streams into one by first returning all values from the +first stream then all values from the second stream. Read more
§

fn fold<B, F>(self, init: B, f: F) -> FoldFuture<Self, B, F>
where + Self: Sized, + F: FnMut(B, Self::Item) -> B,

A combinator that applies a function to every element in a stream +producing a single, final value. Read more
§

fn collect<T>(self) -> Collect<Self, T>
where + T: FromStream<Self::Item>, + Self: Sized,

Drain stream pushing all emitted values into a collection. Read more
§

fn timeout(self, duration: Duration) -> Timeout<Self>
where + Self: Sized,

Applies a per-item timeout to the passed stream. Read more
§

fn timeout_repeating(self, interval: Interval) -> TimeoutRepeating<Self>
where + Self: Sized,

Applies a per-item timeout to the passed stream. Read more
§

fn throttle(self, duration: Duration) -> Throttle<Self>
where + Self: Sized,

Slows down a stream by enforcing a delay between items. Read more
§

fn chunks_timeout( + self, + max_size: usize, + duration: Duration, +) -> ChunksTimeout<Self>
where + Self: Sized,

Batches the items in the given stream using a maximum duration and size for each batch. Read more
§

fn peekable(self) -> Peekable<Self>
where + Self: Sized,

Turns the stream into a peekable stream, whose next element can be peeked at without being +consumed. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/struct.ApplicationClose.html b/pr/255/docs/iroh_quinn/struct.ApplicationClose.html index c6ccb9e8e..bb5b19c66 100644 --- a/pr/255/docs/iroh_quinn/struct.ApplicationClose.html +++ b/pr/255/docs/iroh_quinn/struct.ApplicationClose.html @@ -1,11 +1,11 @@ -ApplicationClose in iroh_quinn - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
+ApplicationClose in iroh_quinn - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
     pub error_code: VarInt,
     pub reason: Bytes,
 }
Expand description

Reason given by an application for closing the connection

Fields§

§error_code: VarInt

Application-specific reason code

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

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 ApplicationClose

Source§

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

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

impl Display for ApplicationClose

Source§

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

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

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> 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 ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

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 ApplicationClose

Source§

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

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

impl Display for ApplicationClose

Source§

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

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

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> 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 ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

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/255/docs/iroh_quinn/struct.ClientConfig.html b/pr/255/docs/iroh_quinn/struct.ClientConfig.html index 990a35909..32e5eca5a 100644 --- a/pr/255/docs/iroh_quinn/struct.ClientConfig.html +++ b/pr/255/docs/iroh_quinn/struct.ClientConfig.html @@ -1,4 +1,4 @@ -ClientConfig in iroh_quinn - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

+ClientConfig in iroh_quinn - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

Default values should be suitable for most internet applications.

Implementations§

Source§

impl ClientConfig

Source

pub fn new(crypto: Arc<dyn ClientConfig>) -> ClientConfig

Create a default config with a particular cryptographic config

Source

pub fn initial_dst_cid_provider( @@ -17,12 +17,11 @@ at least 8 bytes long and unpredictable, as per section 7.2 of RFC 9000.

Source

pub fn token_store(&mut self, store: Arc<dyn TokenStore>) -> &mut ClientConfig

Set a custom TokenStore

Defaults to TokenMemoryCache, which is suitable for most internet applications.

Source

pub fn version(&mut self, version: u32) -> &mut ClientConfig

Set the QUIC version to use

-
Source§

impl ClientConfig

Source

pub fn with_platform_verifier() -> ClientConfig

👎Deprecated since 0.11.13: use try_with_platform_verifier() instead

Create a client configuration that trusts the platform’s native roots

-
Source

pub fn try_with_platform_verifier() -> Result<ClientConfig, Error>

Create a client configuration that trusts the platform’s native roots

-
Source

pub fn with_root_certificates( +

Source§

impl ClientConfig

Source

pub fn try_with_platform_verifier() -> Result<ClientConfig, Error>

Create a client configuration that trusts the platform’s native roots

+
Source

pub fn with_root_certificates( roots: Arc<RootCertStore>, ) -> Result<ClientConfig, VerifierBuilderError>

Create a client configuration that trusts specified trust anchors

-

Trait Implementations§

Source§

impl Clone for ClientConfig

Source§

fn clone(&self) -> ClientConfig

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 ClientConfig

Source§

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

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 ClientConfig

Source§

fn clone(&self) -> ClientConfig

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 ClientConfig

Source§

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

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/255/docs/iroh_quinn/struct.ClosePath.html b/pr/255/docs/iroh_quinn/struct.ClosePath.html new file mode 100644 index 000000000..346435f36 --- /dev/null +++ b/pr/255/docs/iroh_quinn/struct.ClosePath.html @@ -0,0 +1,53 @@ +ClosePath in iroh_quinn - Rust

ClosePath

Struct ClosePath 

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

Future produced by Path::close

+

Trait Implementations§

Source§

impl Future for ClosePath

Source§

type Output = Result<VarInt, 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

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.

+
§

impl<F> FutureExt for F
where + F: Future + ?Sized,

§

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

A convenience for calling Future::poll() on !Unpin types.
§

fn or<F>(self, other: F) -> Or<Self, F>
where + Self: Sized, + F: Future<Output = Self::Output>,

Returns the result of self or other future, preferring self if both are ready. Read more
§

fn race<F>(self, other: F) -> Race<Self, F>
where + Self: Sized, + F: Future<Output = Self::Output>,

Returns the result of self or other future, with no preference if both are ready. Read more
§

fn catch_unwind(self) -> CatchUnwind<Self>
where + Self: Sized + UnwindSafe,

Catches panics while polling the future. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where + Self: Sized + Send + 'a,

Boxes the future and changes its type to dyn Future + Send + 'a. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where + Self: Sized + 'a,

Boxes the future and changes its type to dyn Future + 'a. Read more
§

impl<T> FutureExt for T
where + T: Future + ?Sized,

§

fn with_cancellation_token( + self, + cancellation_token: &CancellationToken, +) -> WithCancellationTokenFuture<'_, Self>
where + Self: Sized,

Similar to [CancellationToken::run_until_cancelled], +but with the advantage that it is easier to write fluent call chains, +and biased towards waiting for [CancellationToken] to complete. Read more
§

fn with_cancellation_token_owned( + self, + cancellation_token: CancellationToken, +) -> WithCancellationTokenFutureOwned<Self>
where + Self: Sized,

Similar to [CancellationToken::run_until_cancelled_owned], +but with the advantage that it is easier to write fluent call chains, +and biased towards waiting for [CancellationToken] to complete. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<F> IntoFuture for F
where + F: Future,

Source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
Source§

type IntoFuture = F

Which kind of future are we turning this into?
Source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<F, T, E> TryFuture for F
where + F: Future<Output = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll( + self: Pin<&mut F>, + cx: &mut Context<'_>, +) -> Poll<<F as Future>::Output>

Poll this TryFuture as if it were a Future. Read more
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/struct.ClosedStream.html b/pr/255/docs/iroh_quinn/struct.ClosedStream.html index c9021984a..7d402dfa5 100644 --- a/pr/255/docs/iroh_quinn/struct.ClosedStream.html +++ b/pr/255/docs/iroh_quinn/struct.ClosedStream.html @@ -1,5 +1,5 @@ ClosedStream in iroh_quinn - Rust

ClosedStream

Struct ClosedStream 

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

Error indicating that a stream has not been opened or has already been finished or reset

-

Trait Implementations§

Source§

impl Clone for ClosedStream

Source§

fn clone(&self) -> ClosedStream

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 ClosedStream

Source§

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

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

impl Default for ClosedStream

Source§

fn default() -> ClosedStream

Returns the “default value” for a type. Read more
Source§

impl Display for ClosedStream

Source§

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

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

impl Error for ClosedStream

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<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ClosedStream

Source§

fn eq(&self, other: &ClosedStream) -> 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 ClosedStream

Source§

fn clone(&self) -> ClosedStream

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 ClosedStream

Source§

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

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

impl Default for ClosedStream

Source§

fn default() -> ClosedStream

Returns the “default value” for a type. Read more
Source§

impl Display for ClosedStream

Source§

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

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

impl Error for ClosedStream

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<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ClosedStream

Source§

fn eq(&self, other: &ClosedStream) -> 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 ClosedStream

Source§

impl StructuralPartialEq for ClosedStream

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/255/docs/iroh_quinn/struct.ConnectionClose.html b/pr/255/docs/iroh_quinn/struct.ConnectionClose.html index babfc951e..853926ce5 100644 --- a/pr/255/docs/iroh_quinn/struct.ConnectionClose.html +++ b/pr/255/docs/iroh_quinn/struct.ConnectionClose.html @@ -1,13 +1,13 @@ -ConnectionClose in iroh_quinn - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
+ConnectionClose in iroh_quinn - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
     pub error_code: Code,
-    pub frame_type: MaybeFrame,
+    pub frame_type: MaybeFrame,
     pub reason: Bytes,
 }
Expand description

Reason given by the transport for closing the connection

Fields§

§error_code: Code

Class of error as encoded in the specification

-
§frame_type: MaybeFrame

Type of frame that caused the close

+
§frame_type: MaybeFrame

Type of frame that caused the close

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

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 ConnectionClose

Source§

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

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

impl Display for ConnectionClose

Source§

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

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

impl From<Error> for ConnectionClose

Source§

fn from(x: Error) -> ConnectionClose

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> 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 ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

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 ConnectionClose

Source§

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

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

impl Display for ConnectionClose

Source§

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

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

impl From<Error> for ConnectionClose

Source§

fn from(x: Error) -> ConnectionClose

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> 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 ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

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/255/docs/iroh_quinn/struct.Endpoint.html b/pr/255/docs/iroh_quinn/struct.Endpoint.html index df16aa143..d023d3a0a 100644 --- a/pr/255/docs/iroh_quinn/struct.Endpoint.html +++ b/pr/255/docs/iroh_quinn/struct.Endpoint.html @@ -1,8 +1,8 @@ -Endpoint in iroh_quinn - Rust

Endpoint

Struct Endpoint 

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

A QUIC endpoint.

+Endpoint in iroh_quinn - Rust

Endpoint

Struct Endpoint 

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

A QUIC endpoint.

An endpoint corresponds to a single UDP socket, may host many connections, and may act as both client and server for different connections.

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

-

Implementations§

Source§

impl Endpoint

Source

pub fn client(addr: SocketAddr) -> Result<Self>

Helper to construct an endpoint for use with outgoing connections only

+

Implementations§

Source§

impl Endpoint

Source

pub fn client(addr: SocketAddr) -> Result<Self>

Helper to construct an endpoint for use with outgoing connections only

Note that addr is the local address to bind to, which should usually be a wildcard address like 0.0.0.0:0 or [::]:0, which allow communication with any reachable IPv4 or IPv6 address respectively from an OS-assigned port.

@@ -14,19 +14,19 @@ address. For example:

iroh_quinn::Endpoint::client((std::net::Ipv6Addr::UNSPECIFIED, 0).into());

Some environments may not allow creation of dual-stack sockets, in which case an IPv6 client will only be able to connect to IPv6 servers. An IPv4 client is never dual-stack.

-
Source

pub fn stats(&self) -> EndpointStats

Returns relevant stats from this Endpoint

-
Source

pub fn server(config: ServerConfig, addr: SocketAddr) -> Result<Self>

Helper to construct an endpoint for use with both incoming and outgoing connections

+
Source

pub fn stats(&self) -> EndpointStats

Returns relevant stats from this Endpoint

+
Source

pub fn server(config: ServerConfig, addr: SocketAddr) -> Result<Self>

Helper to construct an endpoint for use with both incoming and outgoing connections

Platform defaults for dual-stack sockets vary. For example, any socket bound to a wildcard IPv6 address on Windows will not by default be able to communicate with IPv4 addresses. Portable applications should bind an address that matches the family they wish to communicate within.

-
Source

pub fn new( +

Source

pub fn new( config: EndpointConfig, server_config: Option<ServerConfig>, socket: UdpSocket, runtime: Arc<dyn Runtime>, ) -> Result<Self>

Construct an endpoint with arbitrary configuration and socket

-
Source

pub fn new_with_abstract_socket( +

Source

pub fn new_with_abstract_socket( config: EndpointConfig, server_config: Option<ServerConfig>, socket: Box<dyn AsyncUdpSocket>, @@ -34,13 +34,13 @@ communicate within.

) -> Result<Self>

Construct an endpoint with arbitrary configuration and pre-constructed abstract socket

Useful when socket has additional state (e.g. sidechannels) attached for which shared ownership is needed.

-
Source

pub fn accept(&self) -> Accept<'_>

Get the next incoming connection attempt from a client

+
Source

pub fn accept(&self) -> Accept<'_>

Get the next incoming connection attempt from a client

Yields Incomings, or None if the endpoint is closed. Incoming can be awaited to obtain the final Connection, or used to e.g. filter connection attempts or force address validation, or converted into an intermediate Connecting future which can be used to e.g. send 0.5-RTT data.

-
Source

pub fn set_default_client_config(&mut self, config: ClientConfig)

Set the client configuration used by connect

-
Source

pub fn connect( +

Source

pub fn set_default_client_config(&self, config: ClientConfig)

Set the client configuration used by connect

+
Source

pub fn connect( &self, addr: SocketAddr, server_name: &str, @@ -50,26 +50,26 @@ connection from being intercepted by an attacker with a valid certificate for so server.

May fail immediately due to configuration errors, or in the future if the connection could not be established.

-

Source

pub fn connect_with( +

Source

pub fn connect_with( &self, config: ClientConfig, addr: SocketAddr, server_name: &str, ) -> Result<Connecting, ConnectError>

Connect to a remote endpoint using a custom configuration.

See connect() for details.

-
Source

pub fn rebind(&self, socket: UdpSocket) -> Result<()>

Switch to a new UDP socket

+
Source

pub fn rebind(&self, socket: UdpSocket) -> Result<()>

Switch to a new UDP socket

See Endpoint::rebind_abstract() for details.

-
Source

pub fn rebind_abstract(&self, socket: Box<dyn AsyncUdpSocket>) -> Result<()>

Switch to a new UDP socket

+
Source

pub fn rebind_abstract(&self, socket: Box<dyn AsyncUdpSocket>) -> Result<()>

Switch to a new UDP socket

Allows the endpoint’s address to be updated live, affecting all active connections. Incoming connections and connections to servers unreachable from the new address will be lost.

On error, the old UDP socket is retained.

-
Source

pub fn set_server_config(&self, server_config: Option<ServerConfig>)

Replace the server configuration, affecting new incoming connections only

+
Source

pub fn set_server_config(&self, server_config: Option<ServerConfig>)

Replace the server configuration, affecting new incoming connections only

Useful for e.g. refreshing TLS certificates without disrupting existing connections.

-
Source

pub fn local_addr(&self) -> Result<SocketAddr>

Get the local SocketAddr the underlying socket is bound to

-
Source

pub fn open_connections(&self) -> usize

Get the number of connections that are currently open

-
Source

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

Close all of this endpoint’s connections immediately and cease accepting new connections.

+
Source

pub fn local_addr(&self) -> Result<SocketAddr>

Get the local SocketAddr the underlying socket is bound to

+
Source

pub fn open_connections(&self) -> usize

Get the number of connections that are currently open

+
Source

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

Close all of this endpoint’s connections immediately and cease accepting new connections.

See Connection::close() for details.

-
Source

pub async fn wait_idle(&self)

Wait for all connections on the endpoint to be cleanly shut down

+
Source

pub async fn wait_idle(&self)

Wait for all connections on the endpoint to be cleanly shut down

Waiting for this condition before exiting ensures that a good-faith effort is made to notify peers of recent connection closes, whereas exiting immediately could force them to wait out the idle timeout period.

diff --git a/pr/255/docs/iroh_quinn/struct.EndpointStats.html b/pr/255/docs/iroh_quinn/struct.EndpointStats.html index 4500b994a..efaa12c4b 100644 --- a/pr/255/docs/iroh_quinn/struct.EndpointStats.html +++ b/pr/255/docs/iroh_quinn/struct.EndpointStats.html @@ -1,4 +1,4 @@ -EndpointStats in iroh_quinn - Rust

EndpointStats

Struct EndpointStats 

Source
#[non_exhaustive]
pub struct EndpointStats { +EndpointStats in iroh_quinn - Rust

EndpointStats

Struct EndpointStats 

Source
#[non_exhaustive]
pub struct EndpointStats { pub accepted_handshakes: u64, pub outgoing_handshakes: u64, pub refused_handshakes: u64, @@ -8,7 +8,7 @@
§outgoing_handshakes: u64

Cumulative number of Quic handshakes sent from this Endpoint

§refused_handshakes: u64

Cumulative number of Quic handshakes refused on this Endpoint

§ignored_handshakes: u64

Cumulative number of Quic handshakes ignored on this Endpoint

-

Trait Implementations§

Source§

impl Clone for EndpointStats

Source§

fn clone(&self) -> EndpointStats

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 EndpointStats

Source§

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

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

impl Default for EndpointStats

Source§

fn default() -> EndpointStats

Returns the “default value” for a type. Read more
Source§

impl Copy for EndpointStats

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for EndpointStats

Source§

fn clone(&self) -> EndpointStats

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 EndpointStats

Source§

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

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

impl Default for EndpointStats

Source§

fn default() -> EndpointStats

Returns the “default value” for a type. Read more
Source§

impl Copy for EndpointStats

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/255/docs/iroh_quinn/struct.InvalidCid.html b/pr/255/docs/iroh_quinn/struct.InvalidCid.html new file mode 100644 index 000000000..8cc09d0a5 --- /dev/null +++ b/pr/255/docs/iroh_quinn/struct.InvalidCid.html @@ -0,0 +1,27 @@ +InvalidCid in iroh_quinn - Rust

InvalidCid

Struct InvalidCid 

Source
pub struct InvalidCid;
Expand description

The connection ID was not recognized by the ConnectionIdGenerator

+

Trait Implementations§

Source§

impl Clone for InvalidCid

Source§

fn clone(&self) -> InvalidCid

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 InvalidCid

Source§

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

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

impl Copy for InvalidCid

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 + T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<T> ToOwned for T
where + T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/struct.Path.html b/pr/255/docs/iroh_quinn/struct.Path.html index 5602610f3..e00724478 100644 --- a/pr/255/docs/iroh_quinn/struct.Path.html +++ b/pr/255/docs/iroh_quinn/struct.Path.html @@ -2,7 +2,7 @@

Implementations§

Source§

impl Path

Source

pub fn id(&self) -> PathId

The PathId of this path.

Source

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

The current local PathStatus of this path.

Source

pub fn set_status(&self, status: PathStatus) -> Result<(), SetPathStatusError>

Sets the PathStatus of this path.

-
Source

pub fn close(&self) -> Result<ClosePath, ClosePathError>

Closes this path

+
Source

pub fn close(&self) -> Result<ClosePath, ClosePathError>

Closes this path

The future will resolve when all the path state is dropped. This only happens after the remote has confirmed the path as closed and after an additional timeout to give any in-flight packets the time to arrive.

@@ -18,7 +18,7 @@ give any in-flight packets the time to arrive.

) -> Result<Option<Duration>, ClosedPath>

Sets the keep_alive_interval for a specific path

See TransportConfig::default_path_keep_alive_interval for details.

Returns the previous value of the setting.

-
Source

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

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

+
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.

diff --git a/pr/255/docs/iroh_quinn/struct.SendStream.html b/pr/255/docs/iroh_quinn/struct.SendStream.html index 069c8def7..0ec06cb61 100644 --- a/pr/255/docs/iroh_quinn/struct.SendStream.html +++ b/pr/255/docs/iroh_quinn/struct.SendStream.html @@ -8,7 +8,7 @@ ready will always result in no data being written to the stream. This is true of succeed immediately when any progress is made, and is not true of methods which might need to perform multiple writes internally before succeeding. Each write method documents whether it is cancel-safe.

-

Implementations§

Source§

impl SendStream

Source

pub async fn write(&mut self, buf: &[u8]) -> Result<usize, WriteError>

Write a buffer into this stream, returning how many bytes were written

+

Implementations§

Source§

impl SendStream

Source

pub async fn write(&mut self, buf: &[u8]) -> Result<usize, WriteError>

Write a buffer into this stream, returning how many bytes were written

Unless this method errors, it waits until some amount of buf can be written into this stream, and then writes as much as it can without waiting again. Due to congestion and flow control, this may be shorter than buf.len(). On success this yields the length of the @@ -58,7 +58,7 @@ or an error occurs. This method mutates bufs by mutating all chunks

§Cancel safety

This method is not cancellation safe. Even if this does not resolve, some bytes may have been written when previously polled.

-
Source

pub fn finish(&mut self) -> Result<(), ClosedStream>

Notify the peer that no more data will ever be written to this stream

+
Source

pub fn finish(&mut self) -> Result<(), ClosedStream>

Notify the peer that no more data will ever be written to this stream

It is an error to write to a SendStream after finish()ing it. reset() may still be called after finish to abandon transmission of any stream data that might still be buffered.

@@ -66,21 +66,21 @@ still be buffered.

May fail if finish() or reset() was previously called. This error is harmless and serves only to indicate that the caller may have incorrect assumptions about the stream’s state.

-
Source

pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream>

Close the send stream immediately.

+
Source

pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream>

Close the send stream immediately.

No new data can be written after calling this method. Locally buffered data is dropped, and previously transmitted data will no longer be retransmitted if lost. If an attempt has already been made to finish the stream, the peer may still receive all written data.

May fail if finish() or reset() was previously called. This error is harmless and serves only to indicate that the caller may have incorrect assumptions about the stream’s state.

-
Source

pub fn set_priority(&self, priority: i32) -> Result<(), ClosedStream>

Set the priority of the send stream

+
Source

pub fn set_priority(&self, priority: i32) -> Result<(), ClosedStream>

Set the priority of the send stream

Every send stream has an initial priority of 0. Locally buffered data from streams with higher priority will be transmitted before data from streams with lower priority. Changing the priority of a stream with pending data may only take effect after that data has been transmitted. Using many different priority levels per connection may have a negative impact on performance.

-
Source

pub fn priority(&self) -> Result<i32, ClosedStream>

Get the priority of the send stream

-
Source

pub fn stopped( +

Source

pub fn priority(&self) -> Result<i32, ClosedStream>

Get the priority of the send stream

+
Source

pub fn stopped( &self, ) -> impl Future<Output = Result<Option<VarInt>, StoppedError>> + Send + Sync + 'static

Completes when the peer stops the stream or reads the stream to completion

Yields Some with the stop error code if the peer stops the stream. Yields None if the @@ -90,8 +90,8 @@ closing the stream is no longer meaningful.

For a variety of reasons, the peer may not send acknowledgements immediately upon receiving data. As such, relying on stopped to know when the peer has read a stream to completion may introduce more latency than using an application-level response of some sort.

-
Source

pub fn id(&self) -> StreamId

Get the identity of this stream

-
Source

pub fn poll_write( +

Source

pub fn id(&self) -> StreamId

Get the identity of this stream

+
Source

pub fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], @@ -100,22 +100,22 @@ may introduce more latency than using an application-level response of some sort

If the stream is not ready for writing, the method returns Poll::Pending and arranges for the current task (via cx.waker().wake_by_ref()) to receive a notification when the stream becomes writable or is closed.

-

Trait Implementations§

Source§

impl AsyncWrite for SendStream

Available on crate feature futures-io only.

Trait Implementations§

Source§

impl AsyncWrite for SendStream

Available on crate feature futures-io only.
Source§

fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], -) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
Source§

fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to flush the object, ensuring that any buffered data reach -their destination. Read more
Source§

fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to close the object. Read more
§

fn poll_write_vectored( +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
Source§

fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to flush the object, ensuring that any buffered data reach +their destination. Read more
Source§

fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to close the object. Read more
§

fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize, Error>>

Attempt to write bytes from bufs into the object using vectored -IO operations. Read more
Source§

impl AsyncWrite for SendStream

Source§

fn poll_write( +IO operations. Read more

Source§

impl AsyncWrite for SendStream

Source§

fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], -) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
Source§

fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach -their destination. Read more
Source§

fn poll_shutdown( +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
Source§

fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
Source§

fn poll_shutdown( self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when @@ -124,7 +124,7 @@ the I/O connection has completely shut down. Read more
Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored -implementation. Read more

Source§

impl Debug for SendStream

Source§

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

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

impl Drop for SendStream

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +implementation. Read more

Source§

impl Debug for SendStream

Source§

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

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

impl Drop for SendStream

Source§

fn drop(&mut self)

Executes the destructor for this type. 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
§

impl<W> AsyncWriteExt for W
where W: AsyncWrite + ?Sized,

§

fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where Self: Unpin,

Writes a buffer into this writer, returning how many bytes were diff --git a/pr/255/docs/iroh_quinn/struct.StdSystemTime.html b/pr/255/docs/iroh_quinn/struct.StdSystemTime.html index 601433e0b..75e3b81a5 100644 --- a/pr/255/docs/iroh_quinn/struct.StdSystemTime.html +++ b/pr/255/docs/iroh_quinn/struct.StdSystemTime.html @@ -1,6 +1,6 @@ -StdSystemTime in iroh_quinn - Rust

StdSystemTime

Struct StdSystemTime 

Source
pub struct StdSystemTime;
Expand description

Default implementation of TimeSource

+StdSystemTime in iroh_quinn - Rust

StdSystemTime

Struct StdSystemTime 

Source
pub struct StdSystemTime;
Expand description

Default implementation of TimeSource

Implements now by calling SystemTime::now().

-

Trait Implementations§

Source§

impl TimeSource for StdSystemTime

Source§

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl TimeSource for StdSystemTime

Source§

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

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/255/docs/iroh_quinn/struct.StreamId.html b/pr/255/docs/iroh_quinn/struct.StreamId.html index 7d288c046..cd7352208 100644 --- a/pr/255/docs/iroh_quinn/struct.StreamId.html +++ b/pr/255/docs/iroh_quinn/struct.StreamId.html @@ -1,26 +1,26 @@ -StreamId in iroh_quinn - Rust

StreamId

Struct StreamId 

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

Identifier for a stream within a particular connection

-

Implementations§

Source§

impl StreamId

Source

pub fn new(initiator: Side, dir: Dir, index: u64) -> StreamId

Create a new StreamId

-
Source

pub fn initiator(self) -> Side

Which side of a connection initiated the stream

-
Source

pub fn dir(self) -> Dir

Which directions data flows in

-
Source

pub fn index(self) -> u64

Distinguishes streams of the same initiator and directionality

-

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for StreamId

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<StreamId, Error>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<StreamId, Error>

Generate an arbitrary value of Self from the entirety of the given -unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

fn try_size_hint( +StreamId in iroh_quinn - Rust

StreamId

Struct StreamId 

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

Identifier for a stream within a particular connection

+

Implementations§

Source§

impl StreamId

Source

pub fn new(initiator: Side, dir: Dir, index: u64) -> StreamId

Create a new StreamId

+
Source

pub fn initiator(self) -> Side

Which side of a connection initiated the stream

+
Source

pub fn dir(self) -> Dir

Which directions data flows in

+
Source

pub fn index(self) -> u64

Distinguishes streams of the same initiator and directionality

+

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for StreamId

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<StreamId, Error>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<StreamId, Error>

Generate an arbitrary value of Self from the entirety of the given +unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type +needs to construct itself. Read more
Source§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

impl Clone for StreamId

Source§

fn clone(&self) -> StreamId

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 StreamId

Source§

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

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

impl Decodable for StreamId

Source§

fn decode<B>(buf: &mut B) -> Result<StreamId, UnexpectedEnd>
where - B: Buf,

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for StreamId

Source§

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

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

impl Encodable for StreamId

Source§

fn encode<B>(&self, buf: &mut B)
where - B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> VarInt

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> StreamId

Converts to this type from the input type.
Source§

impl Hash for StreamId

Source§

fn hash<__H>(&self, state: &mut __H)
where +needs to construct itself. Read more

Source§

impl Clone for StreamId

Source§

fn clone(&self) -> StreamId

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 StreamId

Source§

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

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

impl Decodable for StreamId

Source§

fn decode<B>(buf: &mut B) -> Result<StreamId, UnexpectedEnd>
where + B: Buf,

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for StreamId

Source§

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

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

impl Encodable for StreamId

Source§

fn encode<B>(&self, buf: &mut B)
where + B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> VarInt

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> StreamId

Converts to this type from the input type.
Source§

impl Hash for StreamId

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for StreamId

Source§

fn cmp(&self, other: &StreamId) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for StreamId

Source§

fn cmp(&self, other: &StreamId) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for StreamId

Source§

fn eq(&self, other: &StreamId) -> 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 PartialOrd for StreamId

Source§

fn partial_cmp(&self, other: &StreamId) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the + Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for StreamId

Source§

fn eq(&self, other: &StreamId) -> 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 PartialOrd for StreamId

Source§

fn partial_cmp(&self, other: &StreamId) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
Source§

impl Copy for StreamId

Source§

impl Eq for StreamId

Source§

impl StructuralPartialEq for StreamId

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +the >= operator. Read more

Source§

impl Copy for StreamId

Source§

impl Eq for StreamId

Source§

impl StructuralPartialEq for StreamId

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/255/docs/iroh_quinn/struct.Transmit.html b/pr/255/docs/iroh_quinn/struct.Transmit.html index c36db78b0..10970ac6e 100644 --- a/pr/255/docs/iroh_quinn/struct.Transmit.html +++ b/pr/255/docs/iroh_quinn/struct.Transmit.html @@ -1,4 +1,4 @@ -Transmit in iroh_quinn - Rust

Transmit

Struct Transmit 

Source
pub struct Transmit {
+Transmit in iroh_quinn - Rust

Transmit

Struct Transmit 

Source
pub struct Transmit {
     pub destination: SocketAddr,
     pub ecn: Option<EcnCodepoint>,
     pub size: usize,
@@ -11,7 +11,7 @@
 
§segment_size: Option<usize>

The segment size if this transmission contains multiple datagrams. This is None if the transmit only contains a single datagram

§src_ip: Option<IpAddr>

Optional source IP address for the datagram

-

Trait Implementations§

Source§

impl Debug for Transmit

Source§

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

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 Transmit

Source§

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

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/255/docs/iroh_quinn/struct.VarInt.html b/pr/255/docs/iroh_quinn/struct.VarInt.html index d70a9303d..ea97f5f75 100644 --- a/pr/255/docs/iroh_quinn/struct.VarInt.html +++ b/pr/255/docs/iroh_quinn/struct.VarInt.html @@ -17,7 +17,7 @@ needs to construct itself. Read more
Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
Source§

impl Clone for VarInt

Source§

fn clone(&self) -> VarInt

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 VarInt

Source§

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

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

impl Decodable for VarInt

Source§

fn decode<B>(r: &mut B) -> Result<VarInt, UnexpectedEnd>
where B: Buf,

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Default for VarInt

Source§

fn default() -> VarInt

Returns the “default value” for a type. Read more
Source§

impl Display for VarInt

Source§

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

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

impl Encodable for VarInt

Source§

fn encode<B>(&self, w: &mut B)
where - B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> VarInt

Converts to this type from the input type.
Source§

impl From<Code> for VarInt

Source§

fn from(value: Code) -> VarInt

Converts to this type from the input type.
Source§

impl From<VarInt> for IdleTimeout

Source§

fn from(inner: VarInt) -> IdleTimeout

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> StreamId

Converts to this type from the input type.
Source§

impl From<VarInt> for Code

Source§

fn from(value: VarInt) -> Code

Converts to this type from the input type.
Source§

impl From<u16> for VarInt

Source§

fn from(x: u16) -> VarInt

Converts to this type from the input type.
Source§

impl From<u32> for VarInt

Source§

fn from(x: u32) -> VarInt

Converts to this type from the input type.
Source§

impl From<u8> for VarInt

Source§

fn from(x: u8) -> VarInt

Converts to this type from the input type.
Source§

impl Hash for VarInt

Source§

fn hash<__H>(&self, state: &mut __H)
where + B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> VarInt

Converts to this type from the input type.
Source§

impl From<Code> for VarInt

Source§

fn from(value: Code) -> VarInt

Converts to this type from the input type.
Source§

impl From<VarInt> for IdleTimeout

Source§

fn from(inner: VarInt) -> IdleTimeout

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> StreamId

Converts to this type from the input type.
Source§

impl From<VarInt> for Code

Source§

fn from(value: VarInt) -> Code

Converts to this type from the input type.
Source§

impl From<u16> for VarInt

Source§

fn from(x: u16) -> VarInt

Converts to this type from the input type.
Source§

impl From<u32> for VarInt

Source§

fn from(x: u32) -> VarInt

Converts to this type from the input type.
Source§

impl From<u8> for VarInt

Source§

fn from(x: u8) -> VarInt

Converts to this type from the input type.
Source§

impl Hash for VarInt

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for VarInt

Source§

fn cmp(&self, other: &VarInt) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where diff --git a/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html b/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html index 85bde9bc7..60c1362ff 100644 --- a/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html +++ b/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html @@ -1,5 +1,5 @@ VarIntBoundsExceeded in iroh_quinn - Rust

VarIntBoundsExceeded

Struct VarIntBoundsExceeded 

Source
pub struct VarIntBoundsExceeded;
Expand description

Error returned when constructing a VarInt from a value >= 2^62

-

Trait Implementations§

Source§

impl Clone for VarIntBoundsExceeded

Source§

fn clone(&self) -> VarIntBoundsExceeded

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 VarIntBoundsExceeded

Source§

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

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

impl Display for VarIntBoundsExceeded

Source§

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

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

impl Error for VarIntBoundsExceeded

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<VarIntBoundsExceeded> for ConfigError

Source§

fn from(_: VarIntBoundsExceeded) -> ConfigError

Converts to this type from the input type.
Source§

impl PartialEq for VarIntBoundsExceeded

Source§

fn eq(&self, other: &VarIntBoundsExceeded) -> 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 VarIntBoundsExceeded

Source§

fn clone(&self) -> VarIntBoundsExceeded

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 VarIntBoundsExceeded

Source§

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

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

impl Display for VarIntBoundsExceeded

Source§

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

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

impl Error for VarIntBoundsExceeded

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<VarIntBoundsExceeded> for ConfigError

Source§

fn from(_: VarIntBoundsExceeded) -> ConfigError

Converts to this type from the input type.
Source§

impl PartialEq for VarIntBoundsExceeded

Source§

fn eq(&self, other: &VarIntBoundsExceeded) -> 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 VarIntBoundsExceeded

Source§

impl Eq for VarIntBoundsExceeded

Source§

impl StructuralPartialEq for VarIntBoundsExceeded

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/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html b/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html index c3b18e385..0ce4f3b6e 100644 --- a/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html +++ b/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html @@ -5,7 +5,7 @@ fn cid_lifetime(&self) -> Option<Duration>; // Provided method - fn validate(&self, _cid: ConnectionId) -> Result<(), InvalidCid> { ... } + fn validate(&self, _cid: ConnectionId) -> Result<(), InvalidCid> { ... } }
Expand description

Generates connection IDs for incoming connections

Required Methods§

Source

fn generate_cid(&mut self) -> ConnectionId

Generates a new CID

Connection IDs MUST NOT contain any information that can be used by @@ -16,6 +16,6 @@ or cryptographic-grade random data.

Source

fn cid_len(&self) -> usize

Returns the length of a CID for connections created by this generator

Source

fn cid_lifetime(&self) -> Option<Duration>

Returns the lifetime of generated Connection IDs

Connection IDs will be retired after the returned Duration, if any. Assumed to be constant.

-

Provided Methods§

Source

fn validate(&self, _cid: ConnectionId) -> Result<(), InvalidCid>

Quickly determine whether cid could have been generated by this generator

+

Provided Methods§

Source

fn validate(&self, _cid: ConnectionId) -> Result<(), InvalidCid>

Quickly determine whether cid could have been generated by this generator

False positives are permitted, but increase the cost of handling invalid packets.

Implementors§

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/trait.TimeSource.html b/pr/255/docs/iroh_quinn/trait.TimeSource.html index 1aaca55c7..97e42fc68 100644 --- a/pr/255/docs/iroh_quinn/trait.TimeSource.html +++ b/pr/255/docs/iroh_quinn/trait.TimeSource.html @@ -1,7 +1,7 @@ -TimeSource in iroh_quinn - Rust

TimeSource

Trait TimeSource 

Source
pub trait TimeSource: Send + Sync {
+TimeSource in iroh_quinn - Rust

TimeSource

Trait TimeSource 

Source
pub trait TimeSource: Send + Sync {
     // Required method
     fn now(&self) -> SystemTime;
 }
Expand description

Object to get current SystemTime

This exists to allow system time to be mocked in tests, or wherever else desired.

-

Required Methods§

Source

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

-

Implementors§

\ No newline at end of file +

Required Methods§

Source

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

+

Implementors§

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/all.html b/pr/255/docs/iroh_quinn_proto/all.html index 2928c6b59..262fb18d7 100644 --- a/pr/255/docs/iroh_quinn_proto/all.html +++ b/pr/255/docs/iroh_quinn_proto/all.html @@ -1 +1 @@ -List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

Type Aliases

Constants

\ No newline at end of file +List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

Type Aliases

Constants

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/bench_exports/index.html b/pr/255/docs/iroh_quinn_proto/bench_exports/index.html index 5a171899b..b3b2f477d 100644 --- a/pr/255/docs/iroh_quinn_proto/bench_exports/index.html +++ b/pr/255/docs/iroh_quinn_proto/bench_exports/index.html @@ -1,2 +1,2 @@ -iroh_quinn_proto::bench_exports - Rust

Module bench_exports

Module bench_exports 

Source
Expand description

Exports for benchmarks

+iroh_quinn_proto::bench_exports - Rust

Module bench_exports

Module bench_exports 

Source
Expand description

Exports for benchmarks

Modules§

send_buffer_benches
Bench fns for SendBuffer
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html b/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html index 59d7c14f1..0549a2287 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html +++ b/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html @@ -3,4 +3,4 @@ fn decode<B: Buf>(buf: &mut B) -> Result<Self>; }
Expand description

Decoding of QUIC primitives.

Required Methods§

Source

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Decode a Self from the provided buffer, if the buffer is large enough

-

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Decodable for u8

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u16

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u32

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u64

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for Ipv4Addr

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for Ipv6Addr

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Implementors§

\ No newline at end of file +

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Decodable for u8

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u16

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u32

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for u64

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for Ipv4Addr

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Source§

impl Decodable for Ipv6Addr

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Implementors§

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html b/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html index 30d1d9852..63c896148 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html +++ b/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html @@ -3,4 +3,4 @@ fn encode<B: BufMut>(&self, buf: &mut B); }
Expand description

Infallible encoding of QUIC primitives.

Required Methods§

Source

fn encode<B: BufMut>(&self, buf: &mut B)

Append the encoding of self to the provided buffer.

-

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Encodable for u8

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u16

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u32

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u64

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv4Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv6Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Implementors§

Source§

impl Encodable for FrameType

Source§

impl Encodable for Datagram

Source§

impl Encodable for PathId

Source§

impl Encodable for StreamId

Source§

impl Encodable for Code

Source§

impl Encodable for VarInt

\ No newline at end of file +

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Encodable for u8

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u16

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u32

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for u64

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv4Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Source§

impl Encodable for Ipv6Addr

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Implementors§

Source§

impl Encodable for FrameType

Source§

impl Encodable for MaybeFrame

Source§

impl Encodable for Datagram

Source§

impl Encodable for PathId

Source§

impl Encodable for StreamId

Source§

impl Encodable for Code

Source§

impl Encodable for VarInt

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html index ba96feffe..fcd0ce8fd 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html @@ -3,28 +3,28 @@ Based on google’s quiche implementation https://source.chromium.org/chromium/chromium/src/+/master:net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc of BBR https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control. More discussion and links at https://groups.google.com/g/bbr-dev.

-

Implementations§

Source§

impl Bbr

Source

pub fn new(config: Arc<BbrConfig>, current_mtu: u16) -> Self

Construct a state using the given config and current time now

-

Trait Implementations§

Source§

impl Clone for Bbr

Source§

fn clone(&self) -> Bbr

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 Controller for Bbr

Source§

fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64)

One or more packets were just sent
Source§

fn on_ack( +

Implementations§

Source§

impl Bbr

Source

pub fn new(config: Arc<BbrConfig>, current_mtu: u16) -> Self

Construct a state using the given config and current time now

+

Trait Implementations§

Source§

impl Clone for Bbr

Source§

fn clone(&self) -> Bbr

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 Controller for Bbr

Source§

fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64)

One or more packets were just sent
Source§

fn on_ack( &mut self, now: Instant, sent: Instant, bytes: u64, app_limited: bool, rtt: &RttEstimator, -)

Packet deliveries were confirmed Read more
Source§

fn on_end_acks( +)

Packet deliveries were confirmed Read more
Source§

fn on_end_acks( &mut self, now: Instant, in_flight: u64, app_limited: bool, largest_packet_num_acked: Option<u64>, -)

Packets are acked in batches, all with the same now argument. This indicates one of those batches has completed.
Source§

fn on_congestion_event( +)

Packets are acked in batches, all with the same now argument. This indicates one of those batches has completed.
Source§

fn on_congestion_event( &mut self, _now: Instant, _sent: Instant, _is_persistent_congestion: bool, _is_ecn: bool, lost_bytes: u64, -)

Packets were deemed lost or marked congested Read more
Source§

fn on_mtu_update(&mut self, new_mtu: u16)

The known MTU for the current network path has been updated
Source§

fn window(&self) -> u64

Number of ack-eliciting bytes that may be in flight
Source§

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled
Source§

fn clone_box(&self) -> Box<dyn Controller>

Duplicate the controller’s state
Source§

fn initial_window(&self) -> u64

Initial congestion window
Source§

fn into_any(self: Box<Self>) -> Box<dyn Any>

Returns Self for use in down-casting to extract implementation details
Source§

fn on_spurious_congestion_event(&mut self)

Packets were incorrectly deemed lost Read more
Source§

impl Debug for Bbr

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Bbr

§

impl RefUnwindSafe for Bbr

§

impl Send for Bbr

§

impl Sync for Bbr

§

impl Unpin for Bbr

§

impl UnwindSafe for Bbr

Blanket Implementations§

Source§

impl<T> Any for T
where +)

Packets were deemed lost or marked congested Read more
Source§

fn on_mtu_update(&mut self, new_mtu: u16)

The known MTU for the current network path has been updated
Source§

fn window(&self) -> u64

Number of ack-eliciting bytes that may be in flight
Source§

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled
Source§

fn clone_box(&self) -> Box<dyn Controller>

Duplicate the controller’s state
Source§

fn initial_window(&self) -> u64

Initial congestion window
Source§

fn into_any(self: Box<Self>) -> Box<dyn Any>

Returns Self for use in down-casting to extract implementation details
Source§

fn on_spurious_congestion_event(&mut self)

Packets were incorrectly deemed lost Read more
Source§

impl Debug for Bbr

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Bbr

§

impl RefUnwindSafe for Bbr

§

impl Send for Bbr

§

impl Sync for Bbr

§

impl Unpin for Bbr

§

impl UnwindSafe for Bbr

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/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html index 999923d27..57f459714 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html @@ -1,11 +1,11 @@ -BbrConfig in iroh_quinn_proto::congestion - Rust

BbrConfig

Struct BbrConfig 

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

Configuration for the Bbr congestion controller

-

Implementations§

Source§

impl BbrConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut Self

Default limit on the amount of outstanding data in bytes.

+BbrConfig in iroh_quinn_proto::congestion - Rust

BbrConfig

Struct BbrConfig 

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

Configuration for the Bbr congestion controller

+

Implementations§

Source§

impl BbrConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut Self

Default limit on the amount of outstanding data in bytes.

Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

-

Trait Implementations§

Source§

impl Clone for BbrConfig

Source§

fn clone(&self) -> BbrConfig

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 ControllerFactory for BbrConfig

Trait Implementations§

Source§

impl Clone for BbrConfig

Source§

fn clone(&self) -> BbrConfig

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 ControllerFactory for BbrConfig

Source§

fn build( self: Arc<Self>, _now: Instant, current_mtu: u16, -) -> Box<dyn Controller>

Construct a fresh Controller
Source§

impl Debug for BbrConfig

Source§

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

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

impl Default for BbrConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +) -> Box<dyn Controller>

Construct a fresh Controller
Source§

impl Debug for BbrConfig

Source§

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

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

impl Default for BbrConfig

Source§

fn default() -> Self

Returns the “default value” for a type. 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/255/docs/iroh_quinn_proto/congestion/trait.Controller.html b/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html index f4888d696..decb6ef2a 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html @@ -76,4 +76,4 @@ application data prior to receiving these acknowledgements.

This function is called when all packets that were deemed lost (for instance because of packet reordering) are acknowledged after the congestion event was raised.

Source

fn metrics(&self) -> ControllerMetrics

Retrieve implementation-specific metrics used to populate qlog traces when they are enabled

-

Implementors§

\ No newline at end of file +

Implementors§

Source§

impl Controller for Bbr

Source§

impl Controller for Cubic

Source§

impl Controller for NewReno

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html b/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html index cddde05fd..b7aa911f6 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html @@ -7,4 +7,4 @@ ) -> Box<dyn Controller>; }
Expand description

Constructs controllers on demand

Required Methods§

Source

fn build(self: Arc<Self>, now: Instant, current_mtu: u16) -> Box<dyn Controller>

Construct a fresh Controller

-

Implementors§

Source§

impl ControllerFactory for BbrConfig

Source§

impl ControllerFactory for CubicConfig

Source§

impl ControllerFactory for NewRenoConfig

\ No newline at end of file +

Implementors§

Source§

impl ControllerFactory for BbrConfig

Source§

impl ControllerFactory for CubicConfig

Source§

impl ControllerFactory for NewRenoConfig

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/connection/struct.MultipathNotNegotiated.html b/pr/255/docs/iroh_quinn_proto/connection/struct.MultipathNotNegotiated.html new file mode 100644 index 000000000..797cb208f --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/connection/struct.MultipathNotNegotiated.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn_proto/struct.MultipathNotNegotiated.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html index dbcd33bd3..a237419ca 100644 --- a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html +++ b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html @@ -1,2 +1,2 @@ -DEFAULT_SUPPORTED_VERSIONS in iroh_quinn_proto - Rust

DEFAULT_SUPPORTED_VERSIONS

Constant DEFAULT_SUPPORTED_VERSIONS 

Source
pub const DEFAULT_SUPPORTED_VERSIONS: &[u32];
Expand description

The QUIC protocol version implemented.

+DEFAULT_SUPPORTED_VERSIONS in iroh_quinn_proto - Rust

DEFAULT_SUPPORTED_VERSIONS

Constant DEFAULT_SUPPORTED_VERSIONS 

Source
pub const DEFAULT_SUPPORTED_VERSIONS: &[u32];
Expand description

The QUIC protocol version implemented.

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html index 56d8327b9..655796bdb 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html @@ -1,6 +1,6 @@ QuicClientConfig in iroh_quinn_proto::crypto::rustls - Rust

QuicClientConfig

Struct QuicClientConfig 

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

A QUIC-compatible TLS client configuration

Quinn implicitly constructs a QuicClientConfig with reasonable defaults within -ClientConfig::with_root_certificates() and ClientConfig::with_platform_verifier(). +ClientConfig::with_root_certificates() and ClientConfig::try_with_platform_verifier(). Alternatively, QuicClientConfig’s TryFrom implementation can be used to wrap around a custom [rustls::ClientConfig], in which case care should be taken around certain points:

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/255/docs/iroh_quinn_proto/enum.Side.html b/pr/255/docs/iroh_quinn_proto/enum.Side.html index 1d2227792..0454f347d 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.Side.html +++ b/pr/255/docs/iroh_quinn_proto/enum.Side.html @@ -1,26 +1,26 @@ -Side in iroh_quinn_proto - Rust

Side

Enum Side 

Source
pub enum Side {
+Side in iroh_quinn_proto - Rust

Side

Enum Side 

Source
pub enum Side {
     Client = 0,
     Server = 1,
 }
Expand description

Whether an endpoint was the initiator of a connection

Variants§

§

Client = 0

The initiator of a connection

§

Server = 1

The acceptor of a connection

-

Implementations§

Source§

impl Side

Source

pub fn is_client(self) -> bool

Shorthand for self == Side::Client

-
Source

pub fn is_server(self) -> bool

Shorthand for self == Side::Server

-

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for Side

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the entirety of the given -unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type +

Implementations§

Source§

impl Side

Source

pub fn is_client(self) -> bool

Shorthand for self == Side::Client

+
Source

pub fn is_server(self) -> bool

Shorthand for self == Side::Server

+

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for Side

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the entirety of the given +unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

impl Clone for Side

Source§

fn clone(&self) -> Side

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 Side

Source§

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

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

impl From<Side> for Side

Source§

fn from(s: Side) -> Self

Converts to this type from the input type.
Source§

impl Hash for Side

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +needs to construct itself. Read more

Source§

impl Clone for Side

Source§

fn clone(&self) -> Side

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 Side

Source§

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

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

impl From<Side> for Side

Source§

fn from(s: Side) -> Self

Converts to this type from the input type.
Source§

impl Hash for Side

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Not for Side

Source§

type Output = Side

The resulting type after applying the ! operator.
Source§

fn not(self) -> Self

Performs the unary ! operation. Read more
Source§

impl Ord for Side

Source§

fn cmp(&self, other: &Side) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Not for Side

Source§

type Output = Side

The resulting type after applying the ! operator.
Source§

fn not(self) -> Self

Performs the unary ! operation. Read more
Source§

impl Ord for Side

Source§

fn cmp(&self, other: &Side) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Side

Source§

fn eq(&self, other: &Side) -> 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 PartialOrd for Side

Source§

fn partial_cmp(&self, other: &Side) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the + Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Side

Source§

fn eq(&self, other: &Side) -> 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 PartialOrd for Side

Source§

fn partial_cmp(&self, other: &Side) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
Source§

impl Copy for Side

Source§

impl Eq for Side

Source§

impl StructuralPartialEq for Side

Auto Trait Implementations§

§

impl Freeze for Side

§

impl RefUnwindSafe for Side

§

impl Send for Side

§

impl Sync for Side

§

impl Unpin for Side

§

impl UnwindSafe for Side

Blanket Implementations§

Source§

impl<T> Any for T
where +the >= operator. Read more

Source§

impl Copy for Side

Source§

impl Eq for Side

Source§

impl StructuralPartialEq for Side

Auto Trait Implementations§

§

impl Freeze for Side

§

impl RefUnwindSafe for Side

§

impl Send for Side

§

impl Sync for Side

§

impl Unpin for Side

§

impl UnwindSafe for Side

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/255/docs/iroh_quinn_proto/frame/enum.MaybeFrame.html b/pr/255/docs/iroh_quinn_proto/frame/enum.MaybeFrame.html new file mode 100644 index 000000000..7b537bd88 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/frame/enum.MaybeFrame.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn_proto/enum.MaybeFrame.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/frame/struct.DatagramInfo.html b/pr/255/docs/iroh_quinn_proto/frame/struct.DatagramInfo.html new file mode 100644 index 000000000..afde3edc2 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/frame/struct.DatagramInfo.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn_proto/struct.DatagramInfo.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/frame/struct.InvalidFrameId.html b/pr/255/docs/iroh_quinn_proto/frame/struct.InvalidFrameId.html new file mode 100644 index 000000000..7f96a888b --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/frame/struct.InvalidFrameId.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn_proto/struct.InvalidFrameId.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/frame/struct.StreamInfo.html b/pr/255/docs/iroh_quinn_proto/frame/struct.StreamInfo.html new file mode 100644 index 000000000..ec4678daa --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/frame/struct.StreamInfo.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../iroh_quinn_proto/struct.StreamInfo.html...

+ + + \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/index.html b/pr/255/docs/iroh_quinn_proto/index.html index 7d9ff3932..c3f3703e1 100644 --- a/pr/255/docs/iroh_quinn_proto/index.html +++ b/pr/255/docs/iroh_quinn_proto/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto - Rust

Crate iroh_quinn_proto

Crate iroh_quinn_proto 

Source
Expand description

Low-level protocol logic for the QUIC protoocol

+iroh_quinn_proto - Rust

Crate iroh_quinn_proto

Crate iroh_quinn_proto 

Source
Expand description

Low-level protocol logic for the QUIC protoocol

quinn-proto contains a fully deterministic implementation of QUIC protocol logic. It contains no networking code and does not get any relevant timestamps from the operating system. Most users may want to use the futures-based quinn API instead.

@@ -8,7 +8,7 @@ through C bindings or if you want to use a different event loop than the one tok a single socket and mostly manages configuration and dispatches incoming datagrams to the related Connection. Connection types contain the bulk of the protocol logic related to managing a single connection and all the related state (such as streams).

-

Re-exports§

pub use rustls;

Modules§

bench_exports
Exports for benchmarks
coding
Coding related traits.
congestion
Logic for controlling the rate at which data is sent
crypto
Traits and implementations for the QUIC cryptography protocol
iroh_hp
iroh NAT Traversal
transport_parameters
QUIC connection transport parameters

Structs§

AcceptError
Error type for attempting to accept an Incoming
AckFrequencyConfig
Parameters for controlling the peer’s acknowledgement frequency
ApplicationClose
Reason given by an application for closing the connection
BloomTokenLog
Bloom filter-based TokenLog
Chunk
A chunk of data from the receive stream
Chunks
Chunks returned from RecvStream::read().
ClientConfig
Configuration for outgoing connections
ClosedPath
Error indicating that a path has not been opened or has already been abandoned
ClosedStream
Error indicating that a stream has not been opened or has already been finished or reset
Connection
Protocol state and logic for a single QUIC connection
ConnectionClose
Reason given by the transport for closing the connection
ConnectionEvent
Events sent from an Endpoint to a Connection
ConnectionHandle
Internal identifier for a Connection currently associated with an endpoint
ConnectionId
Protocol-level identifier for a connection.
ConnectionStats
Connection statistics
Datagram
An unreliable datagram
Datagrams
API to control datagram traffic
Endpoint
The main entry point to the library
EndpointConfig
Global configuration for the endpoint, affecting all connections
EndpointEvent
Events sent from a Connection to an Endpoint
FixedLengthConnectionIdParser
A ConnectionIdParser implementation that assumes the connection ID is of fixed length
FourTuple
Identifies a network path by the combination of remote and local addresses
FrameStats
Number of frames transmitted or received of each frame type
HashedConnectionIdGenerator
Generates 8-byte connection IDs that can be efficiently -validated
IdleTimeout
Maximum duration of inactivity to accept before timing out the connection
Incoming
An incoming connection for which the server has not yet begun its part of the handshake.
InvalidCid
The connection ID was not recognized by the ConnectionIdGenerator
MtuDiscoveryConfig
Parameters governing MTU discovery.
NoneTokenLog
Null implementation of TokenLog, which never accepts tokens
NoneTokenStore
Null implementation of TokenStore, which does not store any tokens
PartialDecode
Decodes a QUIC packet’s invariant header
PathId
Id representing different paths when using multipath extension
PathStats
Statistics related to a transmission path
ProtectedInitialHeader
Header of an Initial packet, before decryption
QlogConfig
Configuration for qlog trace logging.
QlogFileFactory
Enables writing qlog traces to a directory.
RandomConnectionIdGenerator
Generates purely random connection IDs of a specified length
RecvStream
Access to streams
RetryError
Error for attempting to retry an Incoming which already bears a token from a previous retry
RttEstimator
RTT estimation for a particular network path
SendStream
Access to streams
ServerConfig
Parameters governing incoming connections
ShouldTransmit
Indicates whether a frame needs to be transmitted
StdSystemTime
Default implementation of TimeSource
StreamId
Identifier for a stream within a particular connection
Streams
Access to streams
TokenMemoryCache
TokenStore implementation that stores up to N tokens per server name for up to a -limited number of server names, in-memory
TokenReuseError
Error for when a validation token may have been reused
Transmit
An outgoing packet
TransportConfig
Parameters governing the core QUIC state machine
TransportError
Transport-level errors occur when a peer violates the protocol specification
TransportErrorCode
Transport-level error code
UdpStats
Statistics about UDP datagrams transmitted or received on a connection
ValidationTokenConfig
Configuration for sending and handling validation tokens in incoming connections
VarInt
An integer less than 2^62
VarIntBoundsExceeded
Error returned when constructing a VarInt from a value >= 2^62
Written
Indicates how many bytes and chunks had been transferred in a write operation

Enums§

ClosePathError
Errors triggered when abandoning a path
ConfigError
Errors in the configuration of an endpoint
ConnectError
Errors in the parameters being used to create a new connection
ConnectionError
Reasons why a connection might be lost
DatagramEvent
Event resulting from processing a single datagram
Dir
Whether a stream communicates data in both directions or only from the initiator
EcnCodepoint
Explicit congestion notification codepoint
Event
Events of interest to the application
FinishError
Reasons why attempting to finish a stream might fail
FrameType
LongType
Long packet types with uniform header structure
PacketDecodeError
Packet decode error
PathError
Errors that might trigger a path being closed
PathEvent
Application events about paths
PathStatus
The QUIC-MULTIPATH path status
ProtectedHeader
Plain packet header
ReadError
Errors triggered when reading from a recv stream
ReadableError
Errors triggered when opening a recv stream for reading
SendDatagramError
Errors that can arise when sending a datagram
SetPathStatusError
Error from setting path status
Side
Whether an endpoint was the initiator of a connection
StreamEvent
Application events about streams
WriteError
Errors triggered while writing to a send stream

Constants§

DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED
When multipath is required and has not been explicitly enabled, this value will be used for
DEFAULT_SUPPORTED_VERSIONS
The QUIC protocol version implemented.

Traits§

ConnectionIdGenerator
Generates connection IDs for incoming connections
ConnectionIdParser
Parse connection id in short header packet
QlogFactory
Constructs a QlogConfig for individual connections.
TimeSource
Object to get current SystemTime
TokenLog
Responsible for limiting clients’ ability to reuse validation tokens
TokenStore
Responsible for storing validation tokens received from servers and retrieving them for use in +

Re-exports§

pub use rustls;

Modules§

bench_exports
Exports for benchmarks
coding
Coding related traits.
congestion
Logic for controlling the rate at which data is sent
crypto
Traits and implementations for the QUIC cryptography protocol
iroh_hp
iroh NAT Traversal
transport_parameters
QUIC connection transport parameters

Structs§

AcceptError
Error type for attempting to accept an Incoming
AckFrequencyConfig
Parameters for controlling the peer’s acknowledgement frequency
ApplicationClose
Reason given by an application for closing the connection
BloomTokenLog
Bloom filter-based TokenLog
Chunk
A chunk of data from the receive stream
Chunks
Chunks returned from RecvStream::read().
ClientConfig
Configuration for outgoing connections
ClosedPath
Error indicating that a path has not been opened or has already been abandoned
ClosedStream
Error indicating that a stream has not been opened or has already been finished or reset
Connection
Protocol state and logic for a single QUIC connection
ConnectionClose
Reason given by the transport for closing the connection
ConnectionEvent
Events sent from an Endpoint to a Connection
ConnectionHandle
Internal identifier for a Connection currently associated with an endpoint
ConnectionId
Protocol-level identifier for a connection.
ConnectionStats
Connection statistics
Datagram
An unreliable datagram
DatagramInfo
Datagrams
API to control datagram traffic
Endpoint
The main entry point to the library
EndpointConfig
Global configuration for the endpoint, affecting all connections
EndpointEvent
Events sent from a Connection to an Endpoint
FixedLengthConnectionIdParser
A ConnectionIdParser implementation that assumes the connection ID is of fixed length
FourTuple
Identifies a network path by the combination of remote and local addresses
FrameStats
Number of frames transmitted or received of each frame type
HashedConnectionIdGenerator
Generates 8-byte connection IDs that can be efficiently +validated
IdleTimeout
Maximum duration of inactivity to accept before timing out the connection
Incoming
An incoming connection for which the server has not yet begun its part of the handshake.
InvalidCid
The connection ID was not recognized by the ConnectionIdGenerator
InvalidFrameId
Encounter a frame ID that was not valid.
MtuDiscoveryConfig
Parameters governing MTU discovery.
MultipathNotNegotiated
Error when the multipath extension was not negotiated, but attempted to be used.
NoneTokenLog
Null implementation of TokenLog, which never accepts tokens
NoneTokenStore
Null implementation of TokenStore, which does not store any tokens
PartialDecode
Decodes a QUIC packet’s invariant header
PathId
Id representing different paths when using multipath extension
PathStats
Statistics related to a transmission path
ProtectedInitialHeader
Header of an Initial packet, before decryption
QlogConfig
Configuration for qlog trace logging.
QlogFileFactory
Enables writing qlog traces to a directory.
RandomConnectionIdGenerator
Generates purely random connection IDs of a specified length
RecvStream
Access to streams
RetryError
Error for attempting to retry an Incoming which already bears a token from a previous retry
RttEstimator
RTT estimation for a particular network path
SendStream
Access to streams
ServerConfig
Parameters governing incoming connections
ShouldTransmit
Indicates whether a frame needs to be transmitted
StdSystemTime
Default implementation of TimeSource
StreamId
Identifier for a stream within a particular connection
StreamInfo
Streams
Access to streams
TokenMemoryCache
TokenStore implementation that stores up to N tokens per server name for up to a +limited number of server names, in-memory
TokenReuseError
Error for when a validation token may have been reused
Transmit
An outgoing packet
TransportConfig
Parameters governing the core QUIC state machine
TransportError
Transport-level errors occur when a peer violates the protocol specification
TransportErrorCode
Transport-level error code
UdpStats
Statistics about UDP datagrams transmitted or received on a connection
ValidationTokenConfig
Configuration for sending and handling validation tokens in incoming connections
VarInt
An integer less than 2^62
VarIntBoundsExceeded
Error returned when constructing a VarInt from a value >= 2^62
Written
Indicates how many bytes and chunks had been transferred in a write operation

Enums§

ClosePathError
Errors triggered when abandoning a path
ConfigError
Errors in the configuration of an endpoint
ConnectError
Errors in the parameters being used to create a new connection
ConnectionError
Reasons why a connection might be lost
DatagramEvent
Event resulting from processing a single datagram
Dir
Whether a stream communicates data in both directions or only from the initiator
EcnCodepoint
Explicit congestion notification codepoint
Event
Events of interest to the application
FinishError
Reasons why attempting to finish a stream might fail
FrameType
LongType
Long packet types with uniform header structure
MaybeFrame
The type used to refer to FrameTypes in closing and transport errors.
PacketDecodeError
Packet decode error
PathError
Errors that might trigger a path being closed
PathEvent
Application events about paths
PathStatus
The QUIC-MULTIPATH path status
ProtectedHeader
Plain packet header
ReadError
Errors triggered when reading from a recv stream
ReadableError
Errors triggered when opening a recv stream for reading
SendDatagramError
Errors that can arise when sending a datagram
SetPathStatusError
Error from setting path status
Side
Whether an endpoint was the initiator of a connection
StreamEvent
Application events about streams
WriteError
Errors triggered while writing to a send stream

Constants§

DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED
When multipath is required and has not been explicitly enabled, this value will be used for
DEFAULT_SUPPORTED_VERSIONS
The QUIC protocol version implemented.

Traits§

ConnectionIdGenerator
Generates connection IDs for incoming connections
ConnectionIdParser
Parse connection id in short header packet
QlogFactory
Constructs a QlogConfig for individual connections.
TimeSource
Object to get current SystemTime
TokenLog
Responsible for limiting clients’ ability to reuse validation tokens
TokenStore
Responsible for storing validation tokens received from servers and retrieving them for use in subsequent connections
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/sidebar-items.js b/pr/255/docs/iroh_quinn_proto/sidebar-items.js index 4c6d9f4fa..146401cef 100644 --- a/pr/255/docs/iroh_quinn_proto/sidebar-items.js +++ b/pr/255/docs/iroh_quinn_proto/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"constant":["DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED","DEFAULT_SUPPORTED_VERSIONS"],"enum":["ClosePathError","ConfigError","ConnectError","ConnectionError","DatagramEvent","Dir","EcnCodepoint","Event","FinishError","FrameType","LongType","PacketDecodeError","PathError","PathEvent","PathStatus","ProtectedHeader","ReadError","ReadableError","SendDatagramError","SetPathStatusError","Side","StreamEvent","WriteError"],"mod":["bench_exports","coding","congestion","crypto","iroh_hp","transport_parameters"],"struct":["AcceptError","AckFrequencyConfig","ApplicationClose","BloomTokenLog","Chunk","Chunks","ClientConfig","ClosedPath","ClosedStream","Connection","ConnectionClose","ConnectionEvent","ConnectionHandle","ConnectionId","ConnectionStats","Datagram","Datagrams","Endpoint","EndpointConfig","EndpointEvent","FixedLengthConnectionIdParser","FourTuple","FrameStats","HashedConnectionIdGenerator","IdleTimeout","Incoming","InvalidCid","MtuDiscoveryConfig","NoneTokenLog","NoneTokenStore","PartialDecode","PathId","PathStats","ProtectedInitialHeader","QlogConfig","QlogFileFactory","RandomConnectionIdGenerator","RecvStream","RetryError","RttEstimator","SendStream","ServerConfig","ShouldTransmit","StdSystemTime","StreamId","Streams","TokenMemoryCache","TokenReuseError","Transmit","TransportConfig","TransportError","TransportErrorCode","UdpStats","ValidationTokenConfig","VarInt","VarIntBoundsExceeded","Written"],"trait":["ConnectionIdGenerator","ConnectionIdParser","QlogFactory","TimeSource","TokenLog","TokenStore"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"constant":["DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED","DEFAULT_SUPPORTED_VERSIONS"],"enum":["ClosePathError","ConfigError","ConnectError","ConnectionError","DatagramEvent","Dir","EcnCodepoint","Event","FinishError","FrameType","LongType","MaybeFrame","PacketDecodeError","PathError","PathEvent","PathStatus","ProtectedHeader","ReadError","ReadableError","SendDatagramError","SetPathStatusError","Side","StreamEvent","WriteError"],"mod":["bench_exports","coding","congestion","crypto","iroh_hp","transport_parameters"],"struct":["AcceptError","AckFrequencyConfig","ApplicationClose","BloomTokenLog","Chunk","Chunks","ClientConfig","ClosedPath","ClosedStream","Connection","ConnectionClose","ConnectionEvent","ConnectionHandle","ConnectionId","ConnectionStats","Datagram","DatagramInfo","Datagrams","Endpoint","EndpointConfig","EndpointEvent","FixedLengthConnectionIdParser","FourTuple","FrameStats","HashedConnectionIdGenerator","IdleTimeout","Incoming","InvalidCid","InvalidFrameId","MtuDiscoveryConfig","MultipathNotNegotiated","NoneTokenLog","NoneTokenStore","PartialDecode","PathId","PathStats","ProtectedInitialHeader","QlogConfig","QlogFileFactory","RandomConnectionIdGenerator","RecvStream","RetryError","RttEstimator","SendStream","ServerConfig","ShouldTransmit","StdSystemTime","StreamId","StreamInfo","Streams","TokenMemoryCache","TokenReuseError","Transmit","TransportConfig","TransportError","TransportErrorCode","UdpStats","ValidationTokenConfig","VarInt","VarIntBoundsExceeded","Written"],"trait":["ConnectionIdGenerator","ConnectionIdParser","QlogFactory","TimeSource","TokenLog","TokenStore"]}; \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html b/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html index 20891dda1..184e90b3f 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html @@ -1,10 +1,10 @@ -AcceptError in iroh_quinn_proto - Rust

AcceptError

Struct AcceptError 

Source
pub struct AcceptError {
+AcceptError in iroh_quinn_proto - Rust

AcceptError

Struct AcceptError 

Source
pub struct AcceptError {
     pub cause: ConnectionError,
     pub response: Option<Transmit>,
 }
Expand description

Error type for attempting to accept an Incoming

Fields§

§cause: ConnectionError

Underlying error describing reason for failure

§response: Option<Transmit>

Optional response to transmit back

-

Trait Implementations§

Source§

impl Debug for AcceptError

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 AcceptError

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/255/docs/iroh_quinn_proto/struct.ApplicationClose.html b/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html index 54540d008..380fe3169 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html @@ -1,11 +1,11 @@ -ApplicationClose in iroh_quinn_proto - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
+ApplicationClose in iroh_quinn_proto - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
     pub error_code: VarInt,
     pub reason: Bytes,
 }
Expand description

Reason given by an application for closing the connection

Fields§

§error_code: VarInt

Application-specific reason code

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

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 ApplicationClose

Source§

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

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

impl Display for ApplicationClose

Source§

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

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

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> 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 ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

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 ApplicationClose

Source§

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

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

impl Display for ApplicationClose

Source§

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

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

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> 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 ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

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/255/docs/iroh_quinn_proto/struct.ClientConfig.html b/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html index 108a34dee..d67fbdef1 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html @@ -1,4 +1,4 @@ -ClientConfig in iroh_quinn_proto - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

+ClientConfig in iroh_quinn_proto - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

Default values should be suitable for most internet applications.

Implementations§

Source§

impl ClientConfig

Source

pub fn new(crypto: Arc<dyn ClientConfig>) -> Self

Create a default config with a particular cryptographic config

Source

pub fn initial_dst_cid_provider( @@ -14,12 +14,11 @@ at least 8 bytes long and unpredictable, as per section 7.2 of RFC 9000.

Source

pub fn token_store(&mut self, store: Arc<dyn TokenStore>) -> &mut Self

Set a custom TokenStore

Defaults to TokenMemoryCache, which is suitable for most internet applications.

Source

pub fn version(&mut self, version: u32) -> &mut Self

Set the QUIC version to use

-
Source§

impl ClientConfig

Source

pub fn with_platform_verifier() -> Self

👎Deprecated since 0.11.13: use try_with_platform_verifier() instead

Create a client configuration that trusts the platform’s native roots

-
Source

pub fn try_with_platform_verifier() -> Result<Self, Error>

Create a client configuration that trusts the platform’s native roots

-
Source

pub fn with_root_certificates( +

Source§

impl ClientConfig

Source

pub fn try_with_platform_verifier() -> Result<Self, Error>

Create a client configuration that trusts the platform’s native roots

+
Source

pub fn with_root_certificates( roots: Arc<RootCertStore>, ) -> Result<Self, VerifierBuilderError>

Create a client configuration that trusts specified trust anchors

-

Trait Implementations§

Source§

impl Clone for ClientConfig

Source§

fn clone(&self) -> ClientConfig

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 ClientConfig

Source§

fn fmt(&self, fmt: &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 ClientConfig

Source§

fn clone(&self) -> ClientConfig

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 ClientConfig

Source§

fn fmt(&self, fmt: &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/255/docs/iroh_quinn_proto/struct.Connection.html b/pr/255/docs/iroh_quinn_proto/struct.Connection.html index 38be109b3..5b2ebe947 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Connection.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Connection.html @@ -1,4 +1,4 @@ -Connection in iroh_quinn_proto - Rust

Connection

Struct Connection 

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

Protocol state and logic for a single QUIC connection

+Connection in iroh_quinn_proto - Rust

Connection

Struct Connection 

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

Protocol state and logic for a single QUIC connection

Objects of this type receive ConnectionEvents and emit EndpointEvents and application Events to make progress. To handle timeouts, a Connection returns timer updates and expects timeouts through various methods. A number of simple getter methods are exposed @@ -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
  • @@ -41,17 +41,17 @@ events or timeouts with different instants must not be interleaved.

  • a call to poll_transmit returned Some
  • a call was made to handle_timeout
-
Source

pub fn poll(&mut self) -> Option<Event>

Returns application-facing events

+
Source

pub fn poll(&mut self) -> Option<Event>

Returns application-facing events

Connections should be polled for events after:

  • a call was made to handle_event
  • a call was made to handle_timeout
-
Source

pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent>

Return endpoint-facing events

-
Source

pub fn streams(&mut self) -> Streams<'_>

Provide control over streams

-
Source

pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_>

Provide control over streams

-
Source

pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_>

Provide control over streams

-
Source

pub fn open_path_ensure( +

Source

pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent>

Return endpoint-facing events

+
Source

pub fn streams(&mut self) -> Streams<'_>

Provide control over streams

+
Source

pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_>

Provide control over streams

+
Source

pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_>

Provide control over streams

+
Source

pub fn open_path_ensure( &mut self, network_path: FourTuple, initial_status: PathStatus, @@ -65,7 +65,7 @@ remote addresses.

remote, should it not be known yet. We assume that if we already have a path to the remote, the OS is likely to use the same interface to talk to said remote.

See also open_path. Returns (path_id, true) if the path already existed. (path_id, false) if was opened.

-

Source

pub fn open_path( +

Source

pub fn open_path( &mut self, network_path: FourTuple, initial_status: PathStatus, @@ -73,7 +73,7 @@ the OS is likely to use the same interface to talk to said remote.

) -> Result<PathId, PathError>

Opens a new path

Further errors might occur and they will be emitted in PathEvent::LocallyClosed events. When the path is opened it will be reported as an PathEvent::Opened.

-
Source

pub fn close_path( +

Source

pub fn close_path( &mut self, now: Instant, path_id: PathId, @@ -82,32 +82,32 @@ When the path is opened it will be reported as an
Source

pub fn paths(&self) -> Vec<PathId>

Returns all known paths.

+

Source

pub fn paths(&self) -> Vec<PathId>

Returns all known paths.

There is no guarantee any of these paths are open or usable.

-
Source

pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath>

Gets the local PathStatus for a known PathId

-
Source

pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath>

Returns the path’s network path represented as a 4-tuple.

-
Source

pub fn set_path_status( +

Source

pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath>

Gets the local PathStatus for a known PathId

+
Source

pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath>

Returns the path’s network path represented as a 4-tuple.

+
Source

pub fn set_path_status( &mut self, path_id: PathId, status: PathStatus, ) -> Result<PathStatus, SetPathStatusError>

Sets the PathStatus for a known PathId

Returns the previous path status on success.

-
Source

pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus>

Returns the remote path status

-
Source

pub fn set_path_max_idle_timeout( +

Source

pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus>

Returns the remote path status

+
Source

pub fn set_path_max_idle_timeout( &mut self, path_id: PathId, timeout: Option<Duration>, ) -> Result<Option<Duration>, ClosedPath>

Sets the max_idle_timeout for a specific path

See TransportConfig::default_path_max_idle_timeout for details.

Returns the previous value of the setting.

-
Source

pub fn set_path_keep_alive_interval( +

Source

pub fn set_path_keep_alive_interval( &mut self, path_id: PathId, interval: Option<Duration>, ) -> Result<Option<Duration>, ClosedPath>

Sets the keep_alive_interval for a specific path

See TransportConfig::default_path_keep_alive_interval for details.

Returns the previous value of the setting.

-
Source

pub fn poll_transmit( +

Source

pub fn poll_transmit( &mut self, now: Instant, max_datagrams: NonZeroUsize, @@ -121,32 +121,32 @@ for a path that was never opened locally.

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

@@ -178,7 +178,7 @@ packets from the peer. All drained connections have been closed.

&mut self, now: Instant, count: NonZeroU32, -) -> Result<(), MultipathNotNegotiated>

Modify the number of open paths allowed when multipath is enabled

+) -> Result<(), MultipathNotNegotiated>

Modify the number of open paths allowed when multipath is enabled

When reducing the number of concurrent paths this will only affect delaying sending new MAX_PATH_ID frames until fewer than this number of paths are possible. To actively reduce paths they must be closed using Connection::close_path, which @@ -194,27 +194,27 @@ decrement by one for each time a remotely initiated stream of matching direction

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 local_address_changed(&mut self)

Handle a change in the local address, i.e. an active migration

-
Source

pub fn current_mtu(&self) -> u16

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

Source

pub fn local_address_changed(&mut self)

Handle a change in the local address, i.e. an active migration

+
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

@@ -224,7 +224,7 @@ initiated, the previous one is cancelled, and paths that have not been opened ar

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/255/docs/iroh_quinn_proto/struct.ConnectionClose.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html index 35ff90299..1fd411a26 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html @@ -1,13 +1,13 @@ -ConnectionClose in iroh_quinn_proto - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
+ConnectionClose in iroh_quinn_proto - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
     pub error_code: TransportErrorCode,
-    pub frame_type: MaybeFrame,
+    pub frame_type: MaybeFrame,
     pub reason: Bytes,
 }
Expand description

Reason given by the transport for closing the connection

Fields§

§error_code: TransportErrorCode

Class of error as encoded in the specification

-
§frame_type: MaybeFrame

Type of frame that caused the close

+
§frame_type: MaybeFrame

Type of frame that caused the close

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

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 ConnectionClose

Source§

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

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

impl Display for ConnectionClose

Source§

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

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

impl From<Error> for ConnectionClose

Source§

fn from(x: TransportError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> 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 ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

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 ConnectionClose

Source§

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

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

impl Display for ConnectionClose

Source§

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

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

impl From<Error> for ConnectionClose

Source§

fn from(x: TransportError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> 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 ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

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/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html index 38330352c..4228a8ae2 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html @@ -1,14 +1,14 @@ -ConnectionHandle in iroh_quinn_proto - Rust

ConnectionHandle

Struct ConnectionHandle 

Source
pub struct ConnectionHandle(pub usize);
Expand description

Internal identifier for a Connection currently associated with an endpoint

-

Tuple Fields§

§0: usize

Trait Implementations§

Source§

impl Clone for ConnectionHandle

Source§

fn clone(&self) -> ConnectionHandle

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 ConnectionHandle

Source§

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

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

impl From<ConnectionHandle> for usize

Source§

fn from(x: ConnectionHandle) -> Self

Converts to this type from the input type.
Source§

impl Hash for ConnectionHandle

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +ConnectionHandle in iroh_quinn_proto - Rust

ConnectionHandle

Struct ConnectionHandle 

Source
pub struct ConnectionHandle(pub usize);
Expand description

Internal identifier for a Connection currently associated with an endpoint

+

Tuple Fields§

§0: usize

Trait Implementations§

Source§

impl Clone for ConnectionHandle

Source§

fn clone(&self) -> ConnectionHandle

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 ConnectionHandle

Source§

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

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

impl From<ConnectionHandle> for usize

Source§

fn from(x: ConnectionHandle) -> Self

Converts to this type from the input type.
Source§

impl Hash for ConnectionHandle

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Index<ConnectionHandle> for Slab<ConnectionMeta>

Source§

type Output = ConnectionMeta

The returned type after indexing.
Source§

fn index(&self, ch: ConnectionHandle) -> &ConnectionMeta

Performs the indexing (container[index]) operation. Read more
Source§

impl IndexMut<ConnectionHandle> for Slab<ConnectionMeta>

Source§

fn index_mut(&mut self, ch: ConnectionHandle) -> &mut ConnectionMeta

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl Ord for ConnectionHandle

Source§

fn cmp(&self, other: &ConnectionHandle) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Index<ConnectionHandle> for Slab<ConnectionMeta>

Source§

type Output = ConnectionMeta

The returned type after indexing.
Source§

fn index(&self, ch: ConnectionHandle) -> &ConnectionMeta

Performs the indexing (container[index]) operation. Read more
Source§

impl IndexMut<ConnectionHandle> for Slab<ConnectionMeta>

Source§

fn index_mut(&mut self, ch: ConnectionHandle) -> &mut ConnectionMeta

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl Ord for ConnectionHandle

Source§

fn cmp(&self, other: &ConnectionHandle) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for ConnectionHandle

Source§

fn eq(&self, other: &ConnectionHandle) -> 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 PartialOrd for ConnectionHandle

Source§

fn partial_cmp(&self, other: &ConnectionHandle) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the + Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for ConnectionHandle

Source§

fn eq(&self, other: &ConnectionHandle) -> 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 PartialOrd for ConnectionHandle

Source§

fn partial_cmp(&self, other: &ConnectionHandle) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
Source§

impl Copy for ConnectionHandle

Source§

impl Eq for ConnectionHandle

Source§

impl StructuralPartialEq for ConnectionHandle

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +the >= operator. Read more

Source§

impl Copy for ConnectionHandle

Source§

impl Eq for ConnectionHandle

Source§

impl StructuralPartialEq for ConnectionHandle

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/255/docs/iroh_quinn_proto/struct.Datagram.html b/pr/255/docs/iroh_quinn_proto/struct.Datagram.html index 739eade7c..1ffdec640 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Datagram.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Datagram.html @@ -1,8 +1,8 @@ -Datagram in iroh_quinn_proto - Rust

Datagram

Struct Datagram 

Source
pub struct Datagram {
+Datagram in iroh_quinn_proto - Rust

Datagram

Struct Datagram 

Source
pub struct Datagram {
     pub data: Bytes,
 }
Expand description

An unreliable datagram

Fields§

§data: Bytes

Payload

-

Trait Implementations§

Source§

impl Clone for Datagram

Source§

fn clone(&self) -> Datagram

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 Datagram

Source§

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

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

impl Encodable for Datagram

Source§

fn encode<B: BufMut>(&self, out: &mut B)

Append the encoding of self to the provided buffer.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for Datagram

Source§

fn clone(&self) -> Datagram

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 Datagram

Source§

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

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

impl Encodable for Datagram

Source§

fn encode<B: BufMut>(&self, out: &mut B)

Append the encoding of self to the provided buffer.

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/255/docs/iroh_quinn_proto/struct.DatagramInfo.html b/pr/255/docs/iroh_quinn_proto/struct.DatagramInfo.html new file mode 100644 index 000000000..4f9a0d6e9 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/struct.DatagramInfo.html @@ -0,0 +1,32 @@ +DatagramInfo in iroh_quinn_proto - Rust

DatagramInfo

Struct DatagramInfo 

Source
pub struct DatagramInfo(/* private fields */);

Trait Implementations§

Source§

impl Clone for DatagramInfo

Source§

fn clone(&self) -> DatagramInfo

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 DatagramInfo

Source§

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

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

impl Display for DatagramInfo

Source§

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

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

impl PartialEq for DatagramInfo

Source§

fn eq(&self, other: &DatagramInfo) -> 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 DatagramInfo

Source§

impl Eq for DatagramInfo

Source§

impl StructuralPartialEq for DatagramInfo

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 + T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<T> ToOwned for T
where + T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where + T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html b/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html index 52f7d5d5e..ea31834e8 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html @@ -1,27 +1,22 @@ Endpoint in iroh_quinn_proto - Rust

Endpoint

Struct Endpoint 

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

The main entry point to the library

This object performs no I/O whatsoever. Instead, it consumes incoming packets and connection-generated events via handle and handle_event.

-

Implementations§

Source§

impl Endpoint

Source

pub fn new( +

Implementations§

Source§

impl Endpoint

Source

pub fn new( config: Arc<EndpointConfig>, server_config: Option<Arc<ServerConfig>>, allow_mtud: bool, - rng_seed: Option<[u8; 32]>, ) -> Self

Create a new endpoint

allow_mtud enables path MTU detection when requested by Connection configuration for better performance. This requires that outgoing packets are never fragmented, which can be achieved via e.g. the IPV6_DONTFRAG socket option.

-

If rng_seed is provided, it will be used to initialize the endpoint’s rng (having priority -over the rng seed configured in EndpointConfig). Note that the rng_seed parameter will -be removed in a future release, so prefer setting it to None and configuring rng seeds -using EndpointConfig::rng_seed.

-
Source

pub fn set_server_config(&mut self, server_config: Option<Arc<ServerConfig>>)

Replace the server configuration, affecting new incoming connections only

-
Source

pub fn handle_event( +

Source

pub fn set_server_config(&mut self, server_config: Option<Arc<ServerConfig>>)

Replace the server configuration, affecting new incoming connections only

+
Source

pub fn handle_event( &mut self, ch: ConnectionHandle, event: EndpointEvent, ) -> Option<ConnectionEvent>

Process EndpointEvents emitted from related Connections

In turn, processing this event may return a ConnectionEvent for the same Connection.

-
Source

pub fn handle( +

Source

pub fn handle( &mut self, now: Instant, network_path: FourTuple, @@ -29,35 +24,35 @@ using Vec<u8>, ) -> Option<DatagramEvent>

Process an incoming UDP datagram

-
Source

pub fn connect( +

Source

pub fn connect( &mut self, now: Instant, config: ClientConfig, remote: SocketAddr, server_name: &str, ) -> Result<(ConnectionHandle, Connection), ConnectError>

Initiate a connection

-
Source

pub fn accept( +

Source

pub fn accept( &mut self, incoming: Incoming, now: Instant, buf: &mut Vec<u8>, server_config: Option<Arc<ServerConfig>>, ) -> Result<(ConnectionHandle, Connection), Box<AcceptError>>

Attempt to accept this incoming connection (an error may still occur)

-
Source

pub fn refuse(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Transmit

Reject this incoming connection attempt

-
Source

pub fn retry( +

Source

pub fn refuse(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Transmit

Reject this incoming connection attempt

+
Source

pub fn retry( &mut self, incoming: Incoming, buf: &mut Vec<u8>, ) -> Result<Transmit, RetryError>

Respond with a retry packet, requiring the client to retry with address validation

Errors if incoming.may_retry() is false.

-
Source

pub fn ignore(&mut self, incoming: Incoming)

Ignore this incoming connection attempt, not sending any packet in response

+
Source

pub fn ignore(&mut self, incoming: Incoming)

Ignore this incoming connection attempt, not sending any packet in response

Doing this actively, rather than merely dropping the Incoming, is necessary to prevent memory leaks due to state within Endpoint tracking the incoming connection.

-
Source

pub fn config(&self) -> &EndpointConfig

Access the configuration used by this endpoint

-
Source

pub fn open_connections(&self) -> usize

Number of connections that are currently open

-
Source

pub fn incoming_buffer_bytes(&self) -> u64

Counter for the number of bytes currently used +

Source

pub fn config(&self) -> &EndpointConfig

Access the configuration used by this endpoint

+
Source

pub fn open_connections(&self) -> usize

Number of connections that are currently open

+
Source

pub fn incoming_buffer_bytes(&self) -> u64

Counter for the number of bytes currently used in the buffers for Initial and 0-RTT messages for pending incoming connections

-

Trait Implementations§

Source§

impl Debug for Endpoint

Source§

fn fmt(&self, fmt: &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 Endpoint

Source§

fn fmt(&self, fmt: &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/255/docs/iroh_quinn_proto/struct.FourTuple.html b/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html index f5ede5851..cf754191d 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html +++ b/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html @@ -1,4 +1,4 @@ -FourTuple in iroh_quinn_proto - Rust

FourTuple

Struct FourTuple 

Source
pub struct FourTuple {
+FourTuple in iroh_quinn_proto - Rust

FourTuple

Struct FourTuple 

Source
pub struct FourTuple {
     pub remote: SocketAddr,
     pub local_ip: Option<IpAddr>,
 }
Expand description

Identifies a network path by the combination of remote and local addresses

@@ -10,22 +10,22 @@ paths exist with the same remote, but different local IP interfaces.

The socket is irrelevant for our intents and purposes: When we send, we can only specify the src_ip, not the source port. So even if we track the port, we won’t be able to make use of it.

-

Implementations§

Source§

impl FourTuple

Source

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

Returns whether we think the other address probably represents the same path +

Implementations§

Source§

impl FourTuple

Source

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

Returns whether we think the other address probably represents the same path as ours.

If we have a local IP set, then we’re exact and only match if the 4-tuples are exactly equal. If we don’t have a local IP set, then we only check the remote addresses for equality.

-
Source

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

Updates this tuple’s local address iff

+
Source

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

Updates this tuple’s local address iff

  • it was unset before,
  • the other tuple has the same remote, and
  • the other tuple has a local address set.

Returns whether this and the other remote are now fully equal.

-

Trait Implementations§

Source§

impl Clone for FourTuple

Source§

fn clone(&self) -> FourTuple

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 FourTuple

Source§

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

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

impl Display for FourTuple

Source§

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

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

impl Hash for FourTuple

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

Source§

impl Clone for FourTuple

Source§

fn clone(&self) -> FourTuple

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 FourTuple

Source§

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

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

impl Display for FourTuple

Source§

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

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

impl Hash for FourTuple

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for FourTuple

Source§

fn eq(&self, other: &FourTuple) -> 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 FourTuple

Source§

impl Eq for FourTuple

Source§

impl StructuralPartialEq for FourTuple

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for FourTuple

Source§

fn eq(&self, other: &FourTuple) -> 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 FourTuple

Source§

impl Eq for FourTuple

Source§

impl StructuralPartialEq for FourTuple

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/255/docs/iroh_quinn_proto/struct.Incoming.html b/pr/255/docs/iroh_quinn_proto/struct.Incoming.html index bf7a5e8fe..83b7cf347 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Incoming.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Incoming.html @@ -1,17 +1,17 @@ -Incoming in iroh_quinn_proto - Rust

Incoming

Struct Incoming 

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

An incoming connection for which the server has not yet begun its part of the handshake.

-

Implementations§

Source§

impl Incoming

Source

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

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

+Incoming in iroh_quinn_proto - Rust

Incoming

Struct Incoming 

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

An incoming connection for which the server has not yet begun its part of the handshake.

+

Implementations§

Source§

impl Incoming

Source

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

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

This has the same behavior as [Connection::local_ip].

-
Source

pub fn remote_address(&self) -> SocketAddr

The peer’s UDP address

-
Source

pub fn remote_address_validated(&self) -> bool

Whether the socket address that is initiating this connection has been validated

+
Source

pub fn remote_address(&self) -> SocketAddr

The peer’s UDP address

+
Source

pub fn remote_address_validated(&self) -> bool

Whether the socket address that is initiating this connection has been validated

This means that the sender of the initial packet has proved that they can receive traffic sent to self.remote_address().

If self.remote_address_validated() is false, self.may_retry() is guaranteed to be true. The inverse is not guaranteed.

-
Source

pub fn may_retry(&self) -> bool

Whether it is legal to respond with a retry packet

+
Source

pub fn may_retry(&self) -> bool

Whether it is legal to respond with a retry packet

If self.remote_address_validated() is false, self.may_retry() is guaranteed to be true. The inverse is not guaranteed.

-
Source

pub fn orig_dst_cid(&self) -> ConnectionId

The original destination connection ID sent by the client

-

Trait Implementations§

Source§

impl Debug for Incoming

Source§

fn fmt(&self, __derive_more_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 +

Source

pub fn orig_dst_cid(&self) -> ConnectionId

The original destination connection ID sent by the client

+

Trait Implementations§

Source§

impl Debug for Incoming

Source§

fn fmt(&self, __derive_more_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/255/docs/iroh_quinn_proto/struct.InvalidFrameId.html b/pr/255/docs/iroh_quinn_proto/struct.InvalidFrameId.html new file mode 100644 index 000000000..80b456be4 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/struct.InvalidFrameId.html @@ -0,0 +1,30 @@ +InvalidFrameId in iroh_quinn_proto - Rust

InvalidFrameId

Struct InvalidFrameId 

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

Encounter a frame ID that was not valid.

+

Trait Implementations§

Source§

impl Debug for InvalidFrameId

Source§

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

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

impl PartialEq for InvalidFrameId

Source§

fn eq(&self, other: &InvalidFrameId) -> 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 InvalidFrameId

Source§

impl StructuralPartialEq for InvalidFrameId

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
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.MultipathNotNegotiated.html b/pr/255/docs/iroh_quinn_proto/struct.MultipathNotNegotiated.html new file mode 100644 index 000000000..9ed49e237 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/struct.MultipathNotNegotiated.html @@ -0,0 +1,28 @@ +MultipathNotNegotiated in iroh_quinn_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 + T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<T> ToOwned for T
where + T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where + T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.RetryError.html b/pr/255/docs/iroh_quinn_proto/struct.RetryError.html index 109e951de..eaeb3c212 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.RetryError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.RetryError.html @@ -1,6 +1,6 @@ -RetryError in iroh_quinn_proto - Rust

RetryError

Struct RetryError 

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

Error for attempting to retry an Incoming which already bears a token from a previous retry

-

Implementations§

Trait Implementations§

Source§

impl Debug for RetryError

Source§

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

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

impl Display for RetryError

Source§

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

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

impl Error for RetryError

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

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +RetryError in iroh_quinn_proto - Rust

RetryError

Struct RetryError 

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

Error for attempting to retry an Incoming which already bears a token from a previous retry

+

Implementations§

Trait Implementations§

Source§

impl Debug for RetryError

Source§

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

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

impl Display for RetryError

Source§

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

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

impl Error for RetryError

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

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/255/docs/iroh_quinn_proto/struct.StdSystemTime.html b/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html index 6f84e29b1..6cc29193d 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html +++ b/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html @@ -1,6 +1,6 @@ -StdSystemTime in iroh_quinn_proto - Rust

StdSystemTime

Struct StdSystemTime 

Source
pub struct StdSystemTime;
Expand description

Default implementation of TimeSource

+StdSystemTime in iroh_quinn_proto - Rust

StdSystemTime

Struct StdSystemTime 

Source
pub struct StdSystemTime;
Expand description

Default implementation of TimeSource

Implements now by calling SystemTime::now().

-

Trait Implementations§

Source§

impl TimeSource for StdSystemTime

Source§

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl TimeSource for StdSystemTime

Source§

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

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/255/docs/iroh_quinn_proto/struct.StreamId.html b/pr/255/docs/iroh_quinn_proto/struct.StreamId.html index a80e12039..fec6be645 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.StreamId.html +++ b/pr/255/docs/iroh_quinn_proto/struct.StreamId.html @@ -1,23 +1,23 @@ -StreamId in iroh_quinn_proto - Rust

StreamId

Struct StreamId 

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

Identifier for a stream within a particular connection

-

Implementations§

Source§

impl StreamId

Source

pub fn new(initiator: Side, dir: Dir, index: u64) -> Self

Create a new StreamId

-
Source

pub fn initiator(self) -> Side

Which side of a connection initiated the stream

-
Source

pub fn dir(self) -> Dir

Which directions data flows in

-
Source

pub fn index(self) -> u64

Distinguishes streams of the same initiator and directionality

-

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for StreamId

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the entirety of the given -unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

fn try_size_hint( +StreamId in iroh_quinn_proto - Rust

StreamId

Struct StreamId 

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

Identifier for a stream within a particular connection

+

Implementations§

Source§

impl StreamId

Source

pub fn new(initiator: Side, dir: Dir, index: u64) -> Self

Create a new StreamId

+
Source

pub fn initiator(self) -> Side

Which side of a connection initiated the stream

+
Source

pub fn dir(self) -> Dir

Which directions data flows in

+
Source

pub fn index(self) -> u64

Distinguishes streams of the same initiator and directionality

+

Trait Implementations§

Source§

impl<'arbitrary> Arbitrary<'arbitrary> for StreamId

Source§

fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'arbitrary>) -> Result<Self>

Generate an arbitrary value of Self from the entirety of the given +unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type +needs to construct itself. Read more
Source§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

impl Clone for StreamId

Source§

fn clone(&self) -> StreamId

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 StreamId

Source§

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

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

impl Decodable for StreamId

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for StreamId

Source§

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

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

impl Encodable for StreamId

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<StreamId> for u64

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> Self

Converts to this type from the input type.
Source§

impl Hash for StreamId

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +needs to construct itself. Read more

Source§

impl Clone for StreamId

Source§

fn clone(&self) -> StreamId

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 StreamId

Source§

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

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

impl Decodable for StreamId

Source§

fn decode<B: Buf>(buf: &mut B) -> Result<Self>

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for StreamId

Source§

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

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

impl Encodable for StreamId

Source§

fn encode<B: BufMut>(&self, buf: &mut B)

Append the encoding of self to the provided buffer.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<StreamId> for u64

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> Self

Converts to this type from the input type.
Source§

impl Hash for StreamId

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for StreamId

Source§

fn cmp(&self, other: &StreamId) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for StreamId

Source§

fn cmp(&self, other: &StreamId) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for StreamId

Source§

fn eq(&self, other: &StreamId) -> 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 PartialOrd for StreamId

Source§

fn partial_cmp(&self, other: &StreamId) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the + Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for StreamId

Source§

fn eq(&self, other: &StreamId) -> 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 PartialOrd for StreamId

Source§

fn partial_cmp(&self, other: &StreamId) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
Source§

impl Copy for StreamId

Source§

impl Eq for StreamId

Source§

impl StructuralPartialEq for StreamId

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +the >= operator. Read more

Source§

impl Copy for StreamId

Source§

impl Eq for StreamId

Source§

impl StructuralPartialEq for StreamId

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/255/docs/iroh_quinn_proto/struct.StreamInfo.html b/pr/255/docs/iroh_quinn_proto/struct.StreamInfo.html new file mode 100644 index 000000000..149c06098 --- /dev/null +++ b/pr/255/docs/iroh_quinn_proto/struct.StreamInfo.html @@ -0,0 +1,32 @@ +StreamInfo in iroh_quinn_proto - Rust

StreamInfo

Struct StreamInfo 

Source
pub struct StreamInfo(/* private fields */);

Trait Implementations§

Source§

impl Clone for StreamInfo

Source§

fn clone(&self) -> StreamInfo

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 StreamInfo

Source§

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

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

impl Display for StreamInfo

Source§

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

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

impl PartialEq for StreamInfo

Source§

fn eq(&self, other: &StreamInfo) -> 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 StreamInfo

Source§

impl Eq for StreamInfo

Source§

impl StructuralPartialEq for StreamInfo

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 + T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where + U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
Source§

impl<T> ToOwned for T
where + T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where + T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.Transmit.html b/pr/255/docs/iroh_quinn_proto/struct.Transmit.html index db16e71f7..df6a993c4 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Transmit.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Transmit.html @@ -1,4 +1,4 @@ -Transmit in iroh_quinn_proto - Rust

Transmit

Struct Transmit 

Source
pub struct Transmit {
+Transmit in iroh_quinn_proto - Rust

Transmit

Struct Transmit 

Source
pub struct Transmit {
     pub destination: SocketAddr,
     pub ecn: Option<EcnCodepoint>,
     pub size: usize,
@@ -11,7 +11,7 @@
 
§segment_size: Option<usize>

The segment size if this transmission contains multiple datagrams. This is None if the transmit only contains a single datagram

§src_ip: Option<IpAddr>

Optional source IP address for the datagram

-

Trait Implementations§

Source§

impl Debug for Transmit

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 Transmit

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/255/docs/iroh_quinn_proto/struct.TransportError.html b/pr/255/docs/iroh_quinn_proto/struct.TransportError.html index a881a3952..9f9372dda 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.TransportError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.TransportError.html @@ -1,17 +1,17 @@ TransportError in iroh_quinn_proto - Rust

TransportError

Struct TransportError 

Source
#[non_exhaustive]
pub struct TransportError { pub code: Code, - pub frame: MaybeFrame, + pub frame: MaybeFrame, pub reason: String, pub crypto: Option<Arc<dyn Error + Send + Sync>>, }
Expand description

Transport-level errors occur when a peer violates the protocol specification

§Note

The PartialEq implementation for this type performs comparison on the code field only

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§code: Code

Type of error

-
§frame: MaybeFrame

Frame type that triggered the error

+
§frame: MaybeFrame

Frame type that triggered the error

§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§

§

impl Freeze for Error

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

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/255/docs/iroh_quinn_proto/struct.VarInt.html b/pr/255/docs/iroh_quinn_proto/struct.VarInt.html index 816caf26b..fcde0ae9b 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.VarInt.html +++ b/pr/255/docs/iroh_quinn_proto/struct.VarInt.html @@ -15,7 +15,7 @@ unstructured data. Read more

§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type -needs to construct itself. Read more
Source§

impl Clone for VarInt

Source§

fn clone(&self) -> VarInt

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 VarInt

Source§

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

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

impl Decodable for VarInt

Source§

fn decode<B: Buf>(r: &mut B) -> Result<Self>

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Default for VarInt

Source§

fn default() -> VarInt

Returns the “default value” for a type. Read more
Source§

impl Display for VarInt

Source§

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

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

impl Encodable for VarInt

Source§

fn encode<B: BufMut>(&self, w: &mut B)

Append the encoding of self to the provided buffer.
Source§

impl From<Code> for VarInt

Source§

fn from(value: Code) -> Self

Converts to this type from the input type.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for Code

Source§

fn from(value: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for IdleTimeout

Source§

fn from(inner: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for u64

Source§

fn from(x: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<u16> for VarInt

Source§

fn from(x: u16) -> Self

Converts to this type from the input type.
Source§

impl From<u32> for VarInt

Source§

fn from(x: u32) -> Self

Converts to this type from the input type.
Source§

impl From<u8> for VarInt

Source§

fn from(x: u8) -> Self

Converts to this type from the input type.
Source§

impl Hash for VarInt

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +needs to construct itself. Read more

Source§

impl Clone for VarInt

Source§

fn clone(&self) -> VarInt

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 VarInt

Source§

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

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

impl Decodable for VarInt

Source§

fn decode<B: Buf>(r: &mut B) -> Result<Self>

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Default for VarInt

Source§

fn default() -> VarInt

Returns the “default value” for a type. Read more
Source§

impl Display for VarInt

Source§

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

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

impl Encodable for VarInt

Source§

fn encode<B: BufMut>(&self, w: &mut B)

Append the encoding of self to the provided buffer.
Source§

impl From<Code> for VarInt

Source§

fn from(value: Code) -> Self

Converts to this type from the input type.
Source§

impl From<StreamId> for VarInt

Source§

fn from(x: StreamId) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for Code

Source§

fn from(value: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for IdleTimeout

Source§

fn from(inner: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for StreamId

Source§

fn from(v: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<VarInt> for u64

Source§

fn from(x: VarInt) -> Self

Converts to this type from the input type.
Source§

impl From<u16> for VarInt

Source§

fn from(x: u16) -> Self

Converts to this type from the input type.
Source§

impl From<u32> for VarInt

Source§

fn from(x: u32) -> Self

Converts to this type from the input type.
Source§

impl From<u8> for VarInt

Source§

fn from(x: u8) -> Self

Converts to this type from the input type.
Source§

impl Hash for VarInt

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for VarInt

Source§

fn cmp(&self, other: &VarInt) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where diff --git a/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html b/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html index 26affd0ac..af353841e 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html +++ b/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html @@ -1,5 +1,5 @@ VarIntBoundsExceeded in iroh_quinn_proto - Rust

VarIntBoundsExceeded

Struct VarIntBoundsExceeded 

Source
pub struct VarIntBoundsExceeded;
Expand description

Error returned when constructing a VarInt from a value >= 2^62

-

Trait Implementations§

Source§

impl Clone for VarIntBoundsExceeded

Source§

fn clone(&self) -> VarIntBoundsExceeded

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 VarIntBoundsExceeded

Source§

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

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

impl Display for VarIntBoundsExceeded

Source§

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

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

impl Error for VarIntBoundsExceeded

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<VarIntBoundsExceeded> for ConfigError

Source§

fn from(_: VarIntBoundsExceeded) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for VarIntBoundsExceeded

Source§

fn eq(&self, other: &VarIntBoundsExceeded) -> 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 VarIntBoundsExceeded

Source§

fn clone(&self) -> VarIntBoundsExceeded

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 VarIntBoundsExceeded

Source§

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

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

impl Display for VarIntBoundsExceeded

Source§

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

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

impl Error for VarIntBoundsExceeded

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<VarIntBoundsExceeded> for ConfigError

Source§

fn from(_: VarIntBoundsExceeded) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for VarIntBoundsExceeded

Source§

fn eq(&self, other: &VarIntBoundsExceeded) -> 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 VarIntBoundsExceeded

Source§

impl Eq for VarIntBoundsExceeded

Source§

impl StructuralPartialEq for VarIntBoundsExceeded

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/255/docs/iroh_quinn_proto/trait.TimeSource.html b/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html index 009a32eb4..e2f215a4c 100644 --- a/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html +++ b/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html @@ -1,7 +1,7 @@ -TimeSource in iroh_quinn_proto - Rust

TimeSource

Trait TimeSource 

Source
pub trait TimeSource: Send + Sync {
+TimeSource in iroh_quinn_proto - Rust

TimeSource

Trait TimeSource 

Source
pub trait TimeSource: Send + Sync {
     // Required method
     fn now(&self) -> SystemTime;
 }
Expand description

Object to get current SystemTime

This exists to allow system time to be mocked in tests, or wherever else desired.

-

Required Methods§

Source

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

-

Implementors§

\ No newline at end of file +

Required Methods§

Source

fn now(&self) -> SystemTime

Get SystemTime::now() or the mocked equivalent

+

Implementors§

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html b/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html index 922be4498..a32a1faa0 100644 --- a/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html +++ b/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto::transport_parameters - Rust

Module transport_parameters

Module transport_parameters 

Source
Expand description

QUIC connection transport parameters

+iroh_quinn_proto::transport_parameters - Rust

Module transport_parameters

Module transport_parameters 

Source
Expand description

QUIC connection transport parameters

The TransportParameters type is used to represent the transport parameters negotiated by peers while establishing a QUIC connection. This process happens as part of the establishment of the TLS session. As such, the types diff --git a/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html b/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html index e71df8b2f..df00e7097 100644 --- a/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html +++ b/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html @@ -3,8 +3,8 @@ /* private fields */ }

Expand description

Transport parameters used to negotiate connection-level preferences between peers

Fields§

§max_remote_nat_traversal_addresses: Option<NonZeroU8>

Nat traversal draft

-

Implementations§

Source§

impl TransportParameters

Source

pub fn write<W: BufMut>(&self, w: &mut W)

Encode TransportParameters into buffer

-
Source

pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error>

Decode TransportParameters from buffer

+

Implementations§

Source§

impl TransportParameters

Source

pub fn write<W: BufMut>(&self, w: &mut W)

Encode TransportParameters into buffer

+
Source

pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error>

Decode TransportParameters from buffer

Trait Implementations§

Source§

impl Clone for TransportParameters

Source§

fn clone(&self) -> TransportParameters

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 TransportParameters

Source§

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

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

impl PartialEq for TransportParameters

Source§

fn eq(&self, other: &TransportParameters) -> 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 TransportParameters

Source§

impl Eq for TransportParameters

Source§

impl StructuralPartialEq for TransportParameters

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 diff --git a/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html b/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html index a7fa2b6bf..1399a3fc8 100644 --- a/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html +++ b/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html @@ -1,4 +1,4 @@ -EcnCodepoint in iroh_quinn_udp - Rust

EcnCodepoint

Enum EcnCodepoint 

Source
#[repr(u8)]
pub enum EcnCodepoint { +EcnCodepoint in iroh_quinn_udp - Rust

EcnCodepoint

Enum EcnCodepoint 

Source
#[repr(u8)]
pub enum EcnCodepoint { Ect0 = 2, Ect1 = 1, Ce = 3, @@ -6,9 +6,9 @@

Variants§

§

Ect0 = 2

The ECT(0) codepoint, indicating that an endpoint is ECN-capable

§

Ect1 = 1

The ECT(1) codepoint, indicating that an endpoint is ECN-capable

§

Ce = 3

The CE codepoint, signalling that congestion was experienced

-

Implementations§

Source§

impl EcnCodepoint

Source

pub fn from_bits(x: u8) -> Option<Self>

Create new object from the given bits

-

Trait Implementations§

Source§

impl Clone for EcnCodepoint

Source§

fn clone(&self) -> EcnCodepoint

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 EcnCodepoint

Source§

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

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

impl PartialEq for EcnCodepoint

Source§

fn eq(&self, other: &EcnCodepoint) -> 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 EcnCodepoint

Source§

impl Eq for EcnCodepoint

Source§

impl StructuralPartialEq for EcnCodepoint

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Implementations§

Source§

impl EcnCodepoint

Source

pub fn from_bits(x: u8) -> Option<Self>

Create new object from the given bits

+

Trait Implementations§

Source§

impl Clone for EcnCodepoint

Source§

fn clone(&self) -> EcnCodepoint

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 EcnCodepoint

Source§

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

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

impl PartialEq for EcnCodepoint

Source§

fn eq(&self, other: &EcnCodepoint) -> 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 EcnCodepoint

Source§

impl Eq for EcnCodepoint

Source§

impl StructuralPartialEq for EcnCodepoint

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/255/docs/iroh_quinn_udp/index.html b/pr/255/docs/iroh_quinn_udp/index.html index 249f5cb53..9b08b1a23 100644 --- a/pr/255/docs/iroh_quinn_udp/index.html +++ b/pr/255/docs/iroh_quinn_udp/index.html @@ -1,4 +1,4 @@ -iroh_quinn_udp - Rust

Crate iroh_quinn_udp

Crate iroh_quinn_udp 

Source
Expand description

Uniform interface to send and receive UDP packets with advanced features useful for QUIC

+iroh_quinn_udp - Rust

Crate iroh_quinn_udp

Crate iroh_quinn_udp 

Source
Expand description

Uniform interface to send and receive UDP packets with advanced features useful for QUIC

This crate exposes kernel UDP stack features available on most modern systems which are required for an efficient and conformant QUIC implementation. As of this writing, these are not available in std or major async runtimes, and their niche character and complexity are a barrier to adding diff --git a/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html b/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html index 80cd3bbb1..600c9453d 100644 --- a/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html +++ b/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html @@ -1,7 +1,7 @@ -UdpSockRef in iroh_quinn_udp - Rust

UdpSockRef

Struct UdpSockRef 

Source
pub struct UdpSockRef<'a>(/* private fields */);
Expand description

A borrowed UDP socket

+UdpSockRef in iroh_quinn_udp - Rust

UdpSockRef

Struct UdpSockRef 

Source
pub struct UdpSockRef<'a>(/* private fields */);
Expand description

A borrowed UDP socket

On Unix, constructible via From<T: AsFd>. On Windows, constructible via From<T: AsSocket>.

-

Trait Implementations§

Source§

impl<'s, S> From<&'s S> for UdpSockRef<'s>
where - S: AsFd,

Available on Unix only.
Source§

fn from(socket: &'s S) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'a> Freeze for UdpSockRef<'a>

§

impl<'a> RefUnwindSafe for UdpSockRef<'a>

§

impl<'a> Send for UdpSockRef<'a>

§

impl<'a> Sync for UdpSockRef<'a>

§

impl<'a> Unpin for UdpSockRef<'a>

§

impl<'a> UnwindSafe for UdpSockRef<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl<'s, S> From<&'s S> for UdpSockRef<'s>
where + S: AsFd,

Available on Unix only.
Source§

fn from(socket: &'s S) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'a> Freeze for UdpSockRef<'a>

§

impl<'a> RefUnwindSafe for UdpSockRef<'a>

§

impl<'a> Send for UdpSockRef<'a>

§

impl<'a> Sync for UdpSockRef<'a>

§

impl<'a> Unpin for UdpSockRef<'a>

§

impl<'a> UnwindSafe for UdpSockRef<'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 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/255/docs/iroh_quinn_udp/struct.UdpSocketState.html b/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html index 08b27feb1..237ada1d2 100644 --- a/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html +++ b/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html @@ -1,7 +1,7 @@ -UdpSocketState in iroh_quinn_udp - Rust

UdpSocketState

Struct UdpSocketState 

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

Tokio-compatible UDP socket with some useful specializations.

+UdpSocketState in iroh_quinn_udp - Rust

UdpSocketState

Struct UdpSocketState 

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

Tokio-compatible UDP socket with some useful specializations.

Unlike a standard tokio UDP socket, this allows ECN bits to be read and written on some platforms.

-

Implementations§

Source§

impl UdpSocketState

Source

pub fn new(sock: UdpSockRef<'_>) -> Result<Self>

Source

pub fn send( +

Implementations§

Source§

impl UdpSocketState

Source

pub fn new(sock: UdpSockRef<'_>) -> Result<Self>

Source

pub fn send( &self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>, @@ -13,38 +13,38 @@ employ retransmits and timeouts anyway in order to deal with UDP’s unreliable Thus, logging is most likely the only thing you can do with these errors.

If you would like to handle these errors yourself, use UdpSocketState::try_send instead.

-

Source

pub fn try_send( +

Source

pub fn try_send( &self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>, ) -> Result<()>

Sends a Transmit on the given socket without any additional error handling.

-
Source

pub fn recv( +

Source

pub fn recv( &self, socket: UdpSockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta], -) -> Result<usize>

Source

pub fn max_gso_segments(&self) -> NonZeroUsize

The maximum amount of segments which can be transmitted if a platform +) -> Result<usize>

Source

pub fn max_gso_segments(&self) -> NonZeroUsize

The maximum amount of segments which can be transmitted if a platform supports Generic Send Offload (GSO).

This is 1 if the platform doesn’t support GSO. Subject to change if errors are detected while using GSO.

-
Source

pub fn gro_segments(&self) -> NonZeroUsize

The number of segments to read when GRO is enabled. Used as a factor to +

Source

pub fn gro_segments(&self) -> NonZeroUsize

The number of segments to read when GRO is enabled. Used as a factor to compute the receive buffer size.

Returns 1 if the platform doesn’t support GRO.

-
Source

pub fn set_send_buffer_size( +

Source

pub fn set_send_buffer_size( &self, socket: UdpSockRef<'_>, bytes: usize, ) -> Result<()>

Resize the send buffer of socket to bytes

-
Source

pub fn set_recv_buffer_size( +

Source

pub fn set_recv_buffer_size( &self, socket: UdpSockRef<'_>, bytes: usize, ) -> Result<()>

Resize the receive buffer of socket to bytes

-
Source

pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> Result<usize>

Get the size of the socket send buffer

-
Source

pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> Result<usize>

Get the size of the socket receive buffer

-
Source

pub fn may_fragment(&self) -> bool

Whether transmitted datagrams might get fragmented by the IP layer

+
Source

pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> Result<usize>

Get the size of the socket send buffer

+
Source

pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> Result<usize>

Get the size of the socket receive buffer

+
Source

pub fn may_fragment(&self) -> bool

Whether transmitted datagrams might get fragmented by the IP layer

Returns false on targets which employ e.g. the IPV6_DONTFRAG socket option.

-

Trait Implementations§

Source§

impl Debug for UdpSocketState

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 UdpSocketState

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/255/docs/search.index/00037727d41b.js b/pr/255/docs/search.index/00037727d41b.js new file mode 100644 index 000000000..8837e0256 --- /dev/null +++ b/pr/255/docs/search.index/00037727d41b.js @@ -0,0 +1 @@ +rn_("AQkA8+YTAAABADUAAQ0BoKAAABQqd/IaFAAAAQABgQKwgBP0AAGgYAAAFBhkczcBAIWFoEAAABPKsGATngBLApAK") \ No newline at end of file diff --git a/pr/255/docs/search.index/001277e366cd.js b/pr/255/docs/search.index/001277e366cd.js new file mode 100644 index 000000000..6d710e4f0 --- /dev/null +++ b/pr/255/docs/search.index/001277e366cd.js @@ -0,0 +1 @@ +rn_("AQsBoEAAABOnZfLREwAAAQABBQD0nxEAAAEAAQABAAGDArAAEJEAAbBQEvMAAWR3E4ACoKAAABNjZXYBAgD0rBAAAAEAewEBAAEAAPSgDwAAAQDoAAQBI4ICsFAS0AABZXMBAgD0ohIAAAEAiQABAAEDAPTWEgAAAQCOAAEA84UCYnUBAgD0GBEAAAEAYAEBAPOAAmls8wADYnR1OjAAAAEAAAAAAA8AEAAAANMHXwhgCGEIYgjHD4AQIxOeE+YT5xPpE/QT9RMYFBwUAQwA84UTAAABAAEAAYACsAAJbQABoCAAAA0GZG4BBgD0oBIAAAEAiQABAPMDAWL0qhAAAAEAewEBAJcGAACHsEAPngABoHAAABIysJASzgABOAkDOzAAAAEAACIAEQA4BgMAmAcBAPsMAgABDQIAlw8BAOkPAQDuDwEACxAGAE4QAAB7EAEAAxMAACcTAABLEwAA3RMAAOgTAAAGFAAAFRQAAAEDAPS0EgAAAQA6AQEA84ACY213AQCAxbGAFCUAAUCBBAg=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0095923ba754.js b/pr/255/docs/search.index/0095923ba754.js new file mode 100644 index 000000000..55192160c --- /dev/null +++ b/pr/255/docs/search.index/0095923ba754.js @@ -0,0 +1 @@ +rn_("AQIA9KISAAABAIkAAQABAgD0oBAAAAEAnAABAAEDAPTWEgAAAQCOAAEAAQIBoEAAABLBcjswAAABAAAHAAIAnhABADcRBQDzAIQDQAg6MAAAAQAAAAAAFQAQAAAArAetB64Hiw+MDy0QLhBMEE0Q3xDgEI4RjxGgEqESrRKuEr0S5xLoEioTKxM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/00c07f35c6ce.js b/pr/255/docs/search.index/00c07f35c6ce.js deleted file mode 100644 index 63033b1b5..000000000 --- a/pr/255/docs/search.index/00c07f35c6ce.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ0A9c8SAAABAAEAcQABAAECAPQxEAAAAQB1AQEAAQMA9JwQAAABAFoBAQDzAAJidQFNDwAAAQMA9C8QAAABAHUBAQDzhAJkcwECAPMcCQAAAQBUAPOAAml0ARgA86YTAAABAAEAAYACsLASzQABoMAAABJ6ZXXzgQJjbQEFAaBgAAARzHL03QsAAAEAbQMBAAEJAPb1EQAAAQDqAIAAMAABABOAArBgD/AAAWRuAQMBoHAAABIoZ/SEBwAAAQDqAQEAAQkA82UTAAABADUAAYECsIATcwABoGAAABOXZHMXAQCJhbDQE5kAAaBAAAATSbBgExsATQKQCmdeAACLsHAQVAABsLASNgABoKAAABH0sPAS/QABbYEP9HMAAAABAAEAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/00f09416a63d.js b/pr/255/docs/search.index/00f09416a63d.js new file mode 100644 index 000000000..7215dbc7c --- /dev/null +++ b/pr/255/docs/search.index/00f09416a63d.js @@ -0,0 +1 @@ +rn_("AQIA9YQSAAABAN8AdgABABOAArAwEq8BNGlwAQYA8yQTAAABAAEA8wICYnMB7Q8AAPMBAWbyyAcAAB4JAQIA9NYSAAABAI4AAQAzgAOwQBKkAAFpdXk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/00f55497d47e.js b/pr/255/docs/search.index/00f55497d47e.js new file mode 100644 index 000000000..461b51cd7 --- /dev/null +++ b/pr/255/docs/search.index/00f55497d47e.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAHwAAgDUBwAAwQl7AAGEArBwE6UAAaBAAAAQumlzAQcA85MQAAABAA8BI4ACoLAAABJeYXQBAAOwMAl0AAGwMBMPAAGgIAAAB9VhZG8B6gEAADcDAICGoMAAABOdsAATdAABAJgV") \ No newline at end of file diff --git a/pr/255/docs/search.index/01806ef5b5d6.js b/pr/255/docs/search.index/01806ef5b5d6.js deleted file mode 100644 index 16ac96cb5..000000000 --- a/pr/255/docs/search.index/01806ef5b5d6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsCAQqwEFoJAAABMTbXABgAKgMAAAEDegUAAAEr1jcpcAAACFsCASjQABsMATRAABoGAAABECEEAOOzAAAAEAABIABgApBQgAABEBAP0RAQDaEgEALBMBAJwTAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/01d48ddd05cf.js b/pr/255/docs/search.index/01d48ddd05cf.js deleted file mode 100644 index d42dba854..000000000 --- a/pr/255/docs/search.index/01d48ddd05cf.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoFAAABNGcwGqEQAAAYICsEARzQABsEARzwABNDYBBgD0lRMAAAEACgABAPMCAXIBABMAAPMDAWX0rg8AAAEAqAABAFOEA7CwExwAAWFlaWOAA6BQAAATfGNldA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/01f5bffda89c.js b/pr/255/docs/search.index/01f5bffda89c.js deleted file mode 100644 index 4ec2a0c22..000000000 --- a/pr/255/docs/search.index/01f5bffda89c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDsEAIAcRIBAAMTAgABBADz7xAAAAEAAQAjAAKgYAAAEf9hcvMWEAAAAQCrAQGAAqEQAAAThbCAE30AAWl1NwQAgYexUBOgAAGACScAFs6wcBLNAAGhMAAAE5QKQBsjgAKgMAAAEaRudg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/024f75b34b20.js b/pr/255/docs/search.index/024f75b34b20.js new file mode 100644 index 000000000..fc0587fc7 --- /dev/null +++ b/pr/255/docs/search.index/024f75b34b20.js @@ -0,0 +1 @@ +rn_("AQUA9AkNAAABAOsCAQABAAD0cQwAAAEAAQBlAAECADowAAABAAAAAAAJABAAAACOD48PeBA2EXcSeBJiE+ETERQSFMcBAACGsDAJbwABoEAAABGVsIARfAABGEAHOjAAAAEAAAAAABcAEAAAAMoHywdXCHsJqgmrCQgNew98D5sPPhBFEEYQRxBIEIMQhBC7ELwQIBJgE2ETixOMEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/02f80e846705.js b/pr/255/docs/search.index/02f80e846705.js deleted file mode 100644 index 329dbb0e2..000000000 --- a/pr/255/docs/search.index/02f80e846705.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAABYACQCLDwUAkxABABwRAgDWEQEABBIEAPASAQATEwAAQBMAAF8TAAAjgAOh8AAAE6mw8BOcAAFjZmcjgAKwUBKuAAFtbgEFAPPwEgAAAQBuAPMEAWMBsxAAAAEBAbBwE0QAAXA7MAAAAQAACQACAPwHBwD5DwEAAQIAOzAAAAEAAAsAAgDDEgUAdRMFAPMBAW07MAAAAQAADQAEAHkMAACVEAAA7REFADYTBQATAAKgMAAADH1lc/IgEQAAAQABggKwcBMkAAGgQAAAED9pc/cBAICGsJATCQABkEkI") \ No newline at end of file diff --git a/pr/255/docs/search.index/030aa7192f47.js b/pr/255/docs/search.index/030aa7192f47.js deleted file mode 100644 index 5c82d3ffe..000000000 --- a/pr/255/docs/search.index/030aa7192f47.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAYAAgABBgUArBAAAAEEAbAAEiQAAXM7MAAAAQAACwACAJgSBwCBEwMARwAAAYaggAAAEnmxABOOAAGwQBHnAAGwgBOcAAGwUBImAAEVABb0Aw4AAAEAAQABAAEFAPM0DwAAAQABAGOAA7BAD7cAAW1ubwGBArAADIsAAbAQD7UAAXN18wACYWk7MAAAAQAACQAEAJAHAAAXDwAA7A8BAIYSBQABgAOwABLVAAGwABLXAAGwcBNHAAE0NmEBBAD0lRMAAAEACgABACOBAqBAAAAQhm1wAQIAOzAAAAEAAA4ABACTBwEAqwwBAHYQCQC0EAAAAQEAOzAAAAEAAAgAAwDcEQAARRIAAKITBgABAQA7MAAAAQAACgADAJkQAgCwEgMAihMDACOAAqAwAAAPimRn1wMAAMagYAAAEvpARYAIOzAAAAEAABgACQArDwEAPRABAHIQAQCCEAMA8hAGALQSAgAAEwAAVxMBAIYTAQABAwD2KgkAAFAANgYBALEAAQATgAKwcBMoAAFvcgEEAbCwE24AAWz0qQwAAAEA0QIBAAECADswAAABAAAMAAMACQkAAMMSBQB1EwUAAQEA83EPAAABADcCI4ACoLAAABMnZ3oBAgA6MAAAAQAAAAAACQAQAAAAABEBEf0R/hHaEtsSLBMtE5wTnRPzAAFv8n0JAAABAAEFAPQeDwAAAQDhAAEAgwCEoEAAAAyfsHASaAABsCAMKwABEAUCOzAAAAEAAAkAAwAaBQMAyAUCAO8QAgABgAKgIAAAEEywIBMoAAFkdAGEArCwE3EAAbAAEs0AAWFz04CEoLAAABNbQCgEAYACoDAAABEYsGAPMgABaHJH/wEAzaAgAAAF5qAgAAAF57BwEsEAAQNnNAc7MAAAAQAANwAYAP4EAAAyBQUAcwkAAHkMAADuDgEA2A8DAJUQAADcEQAA7REFAEUSAQBnEgAAbhIAAIUSAACWEgEAoBIAAKISAgCmEgEA+BIAAP8SAAALEwEAJBMBADYTBQBKEwAAohMGAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/030abe455d20.js b/pr/255/docs/search.index/030abe455d20.js deleted file mode 100644 index 8d3ecf49e..000000000 --- a/pr/255/docs/search.index/030abe455d20.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9dQQAAABAAEAAQABAAGAArBgEhYAAaAgAAAQJ295AQABoMAAABMnafRnEgAABwAXABsAAQMAOzAAAAEAAAUAAQCGEgUAAQYA9IoTAAABAAEAAQABAgD0JRAAAAEAmwABAAECAaBAAAASP3I7MAAAAQAABwACACMQAQC7EAUA84ACYW9nBwAAh7CAEj4AVbCgEq4AAQwwBzswAAABAAAOAAQAJAQFANgLAADnEAMAthEDAKOAhKDwAAASvqBQAAAPgpQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/035c9d3c036b.js b/pr/255/docs/search.index/035c9d3c036b.js deleted file mode 100644 index 985c921ac..000000000 --- a/pr/255/docs/search.index/035c9d3c036b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoDAAABBDoJAAABKFMGj1IhEAAG0BAQABAAEAE4ACoDAAAA8GZHIjAISwEAkIAuiwIAvEAO6gMAAADyoSABj14wUAAC4AAQABAAEAAQIA9JUTAAABAAoAAQABAgDzoA8AAAEAAQDzgAJpcgEBArBAEIkAAaBQAAASb2Vz9AIOAACcAgEAWgIBCwD2lBIAAAEAoABTABYAAQDzgAJsdNOAhKCQAAASSQFEBA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/04219d6c5f1f.js b/pr/255/docs/search.index/04219d6c5f1f.js deleted file mode 100644 index 1dc778fb3..000000000 --- a/pr/255/docs/search.index/04219d6c5f1f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBsEAQiQABZQECDgAAAQUAOzAAAAEAAAYAAQCRDwYAAQMA9H4MAAABAAEAAQDzAAJwczowAAABAAAAAAAOABAAAADvBfAF8QXzBiIJEQwdDCsQLBAtEC4QvxHAERASERIzAAOwUA8KAMRkcHI7MAAAAQAADwAGAAIFAACwBQMA9g4AAAQRAwC6EQMA6REBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/045e5265a54f.js b/pr/255/docs/search.index/045e5265a54f.js deleted file mode 100644 index 972497ccf..000000000 --- a/pr/255/docs/search.index/045e5265a54f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoEAAABEZZfOoDAAAmAMBAAEGAPQ9EAAAAQC5AAEAE4EDoAAAABCGsSAThgABYWRuARQA9aQTAAABAAEAAQABAAEGAbCAE0cAAXY7MAAAAQAABwACAPIQBAC0EgIAVwAAAYagwAAAEn+goAAAEqGgkAAAEm+wUA+1AAEF4AL0QgcAAAEAAQA3DAEGAPPaEQAAAQCaAPOAA3J0dgEDADswAAABAAAHAAIAsBIDAIoTAwDzAAFzAUoTAADzAAFzARgRAABnAQCAhqAwAAAL+rAAEmoAAaAQAAAMkBJADg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/04786c4690da.js b/pr/255/docs/search.index/04786c4690da.js deleted file mode 100644 index 7262a982c..000000000 --- a/pr/255/docs/search.index/04786c4690da.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsIASRwABdvR3CQAAAQB2CQEA8wABYwHzEQAAAQICoLAAABNAoLAAABNBY3Pz9w8AAAEAXgABgQKwUBEUAAGgwAAAExFoafOCAmVp84ACZW8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/054086f1f577.js b/pr/255/docs/search.index/054086f1f577.js deleted file mode 100644 index 1da5a2a67..000000000 --- a/pr/255/docs/search.index/054086f1f577.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBsAASJAABczswAAABAAALAAIAmBIHAIETAwBHAAAFhqCAAAASebEAE44AAbBAEecAAbCAE5wAAbBQEiYAARUAFvQDDgAAAQABAAEAQwCEoCAAAAk8oNAAABKEoDAAAAkbFQAE88cBAAABANQF") \ No newline at end of file diff --git a/pr/255/docs/search.index/05c72ebeb6e8.js b/pr/255/docs/search.index/05c72ebeb6e8.js new file mode 100644 index 000000000..75f1b10fb --- /dev/null +++ b/pr/255/docs/search.index/05c72ebeb6e8.js @@ -0,0 +1 @@ +rn_("AQABoDAAAAzVaQHyEgAAAQABsDAQ7QABbvK6BwAAAQABAQDzNQgAAC4HAQATAAKgUAAAEE5lc/ULBAAAAQABAAEAAQABhAKwoBOLAAGwoBONAAFjcvMBAXTyihEAANUAAQMBsGAT0wABZjswAAABAAAGAAMAIAwCAP8SAQCDEwEA84ACYWXzgIQAKAU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/05cf24e46b23.js b/pr/255/docs/search.index/05cf24e46b23.js new file mode 100644 index 000000000..e63c08949 --- /dev/null +++ b/pr/255/docs/search.index/05cf24e46b23.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAOIAAgDnDAEAdw7gAAEBAaAAAAASyHP1TgUAADMKuAMBAAIAAYACoCAAAA92oDAAABJ1ZXITAQKgIAAAEU9wdQFiDwAAAQECoGAAABM/oOAAABOWZXQ7MAAAAQAACAABAFIFCAABgAOwIBIhAAGwsBJYAAGwsBJaAAFiY3PzgMUAAQoK") \ No newline at end of file diff --git a/pr/255/docs/search.index/05e417058650.js b/pr/255/docs/search.index/05e417058650.js new file mode 100644 index 000000000..4a3d3a6b8 --- /dev/null +++ b/pr/255/docs/search.index/05e417058650.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAHwAAgCZEAAApBF7AAEAAbBwEz0AAWXykQ8AAAEA8wABc/T6DwAAAQAFBAEAM4ADoGAAABFOZGlv") \ No newline at end of file diff --git a/pr/255/docs/search.index/05f4c9420eb7.js b/pr/255/docs/search.index/05f4c9420eb7.js deleted file mode 100644 index 102e06240..000000000 --- a/pr/255/docs/search.index/05f4c9420eb7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9NERAAABAJoAAQABCAD0fRIAAAEAgwABADMAA7BAElIAAWFiZTowAAABAAAAAAAJABAAAABdB14HmAyZDAEPbA+1D7YPrRFvEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0615a2bf5050.js b/pr/255/docs/search.index/0615a2bf5050.js deleted file mode 100644 index 39844b80e..000000000 --- a/pr/255/docs/search.index/0615a2bf5050.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAANYAAgDNCwAAtQzVAPMAAW07MAAAAQAA1gACAOkFAAAVBtUAAQMAOzAAAAEAAAcAAgDfDgUAVhIBAPMAAWM7MAAAAQAAVwAmAAgFCwC3BQEAHgkBAOMLAADpCwIAlAwAAJ8MAgCwDAEABg8AAAsPAQAODwEAFA8AAJgPAgCeDwEAow8BAMIPAAA2EAAAPBAAAIkQAQCWEAEAqRABAK0QAgAIEQEAGRECAB8RAAC+EQAAxREBAMoRAQAOEgEAGhIDADwSAQBMEgMAUhIBAKwSAQC9EgAAJhMAAEsTBABUEwIA84ACcncBCQDzZRMAAAEANQABDAGgoAAAE6l38pkTAAABAAEBAPMvDwAAAQABAPOAAnR1AYECsIATcwABoGAAABOXZHM3AgCBhqBAAAATSbBgExsATbAwEwkAAQKQDgGIArAAEtUAAbAAEtcAATQ2M4ADoDAAABCsZG5zYwADoBAAAAUnYWVvAXIAAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/06a55ef026d4.js b/pr/255/docs/search.index/06a55ef026d4.js new file mode 100644 index 000000000..c595ee0f1 --- /dev/null +++ b/pr/255/docs/search.index/06a55ef026d4.js @@ -0,0 +1 @@ +rn_("AQEA9eEQAAABAAEAAQABACOBArCQE3gAAWF0Q4ADsRAT7QABoIAAABM7Y290EwACsAATxQABbnL24AEAAAEAVwIBAGEDbAs=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0773c651efc1.js b/pr/255/docs/search.index/0773c651efc1.js new file mode 100644 index 000000000..3c2f369c1 --- /dev/null +++ b/pr/255/docs/search.index/0773c651efc1.js @@ -0,0 +1 @@ +rn_("AYACsHASIwABsCAUEwABaW8BAAGw8BQTAAFr9YoTAAAFAAEAAQAkAPMFAWTyYBIAAAEAAQIA830QAAABAAEA8wABaTowAAABAAAAAAAHABAAAABbEHYSTxNQE38TgBOcE50TI4MCsLAT8gABYXMBgQKgoAAAEsKgQAAAECBvdvOAhAFQAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/07b12fe46ce8.js b/pr/255/docs/search.index/07b12fe46ce8.js deleted file mode 100644 index 3d079a1e2..000000000 --- a/pr/255/docs/search.index/07b12fe46ce8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQECoCAAABD/oDAAABGyYmgBBA8AAAEOAPQiEwAAAQBGAAEAAQMBoKAAABOpd/KZEwAAAQCzAISwQA+FAAEBCAnyCAgAAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/07bca17b1c6a.js b/pr/255/docs/search.index/07bca17b1c6a.js deleted file mode 100644 index 24640c29e..000000000 --- a/pr/255/docs/search.index/07bca17b1c6a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsCAQqwEFoJAAABMTbXABggKwoBMJAAGwoBMLAAFjcgECAaBAAAAQqmUBbg8AADOAhLAgECgAAbAgDvEAAVAUAPOAAm9y") \ No newline at end of file diff --git a/pr/255/docs/search.index/081380447331.js b/pr/255/docs/search.index/081380447331.js deleted file mode 100644 index f2ec3699e..000000000 --- a/pr/255/docs/search.index/081380447331.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9q0MAAABAM8CAQAiAQEAAQoA89oRAAABAJoAAQEA9zAJAAABAHsGAQBrAAEADgEjgAKwYBLeAAFpbwECAPRxDAAAAQCkBQEAAQUA9PQSAAABAEcAAQD3CAAAiLCQEq4AAaAgAAAMc7CQERoAAQTcAzowAAABAAAAAAAIABAAAADcBSAJIQkbDBwMKBApEAkSChI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/082c33a78589.js b/pr/255/docs/search.index/082c33a78589.js new file mode 100644 index 000000000..af46271c3 --- /dev/null +++ b/pr/255/docs/search.index/082c33a78589.js @@ -0,0 +1 @@ +rn_("AYACsFATiAABoAAAAAlcY3QBAQA7MAAAAQAABQABAAgTBQABAwD08wwAAEwGlgABAAGAAqAQAAAMhKBQAAASLWNkAQIA81EJAAAPAwEA8wABbfMvBQAAtAABAAGBAqAQAAASwqBwAAATA2Fj8wABcvO8BwAAkgkZAGcPAICIsDAPgwDGoDAAABP8KTAj") \ No newline at end of file diff --git a/pr/255/docs/search.index/0842ec51c54a.js b/pr/255/docs/search.index/0842ec51c54a.js new file mode 100644 index 000000000..fdbed2683 --- /dev/null +++ b/pr/255/docs/search.index/0842ec51c54a.js @@ -0,0 +1 @@ +rn_("AQYAOzAAAAEAAAkAAQDxEAkAAQIAOzAAAAEAABMAAQDRDxMAE4GEoFAAABCyoBAAAAw7oCAAAAz0HEAAE4ACsFAS+QABYW4zgAOwMA97AAFpc3Q=") \ No newline at end of file diff --git a/pr/255/docs/search.index/08b434a15736.js b/pr/255/docs/search.index/08b434a15736.js new file mode 100644 index 000000000..7f551bd42 --- /dev/null +++ b/pr/255/docs/search.index/08b434a15736.js @@ -0,0 +1 @@ +rn_("AYMCsQAUHwABsNAUEQABa20BBAGgoAAAFCp38hoUAAABAAELAPOPEwAAAQABACOAAqCAAAATtWVvYwQDoGAAABNOZW5wATgMAAABCgDzchMAAAEAbQATgAKiEAAAFCpsb3cAAACFoGAAABIgoQAAABPiBIEDOzAAAAEAADsABAAvBgUAsQcAAAEIMwAoEQAAQ4ADsIARJwEKoAAAAAHrZGt0") \ No newline at end of file diff --git a/pr/255/docs/search.index/0933b5050388.js b/pr/255/docs/search.index/0933b5050388.js deleted file mode 100644 index 851a30844..000000000 --- a/pr/255/docs/search.index/0933b5050388.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9KkMAAABANECAQABAAD0GAwAAAEAAQBgAAECADowAAABAAAAAAAJABAAAAAVDxYP/Q+6EPUR9hHgEmATkBORE8cBAACGsDAJLQABoEAAABEZsIARAAABGEAHOjAAAAEAAAAAABcAEAAAAJEHkgcdCDkJaAlpCagMAg8DDyIPww/KD8sPzA/NDwgQCRBAEEEQnxHeEt8SCRMKEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/096a32f3fb06.js b/pr/255/docs/search.index/096a32f3fb06.js deleted file mode 100644 index 06b8b93a7..000000000 --- a/pr/255/docs/search.index/096a32f3fb06.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoCAAAA79oDAAABHzZXIBAAKgIAAAEoSwMBEMAAFpdPL5EQAAAQABAwA7MAAAAQAABgABAIwQBgABCAD06xIAAAEAfwAFABMBA7CQE0sAAbBQEjoBT2dscDswAAABAAASAAkAmw8CAA8RAQApEgEAShIBAHsSAQDcEgEADxMBAB4TAQBdEwEAAYACsDARCAABsDARCgABcnYBBAGwABG/AAFkOzAAAAEAAAUAAgAEEQMA6REBALcFAAGHsFARwQD9sGASOAABlAkDOzAAAAEAAAoABQCEDAIACA4BADMQAAC2EAMAMBIAACOAAqAQAAAMg25vAQMA85gPAAABAAEAI4ACoAAAAAvPZHJjAYSgUAAAELOgMAAAD88UARDywQcAAAEAE4ADsGAR3gABsAAO5wABY2dyVwAAAIWgsAAAEwigQAAADgegIAAAENMQwAoB6Q4AAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/09c6ace039aa.js b/pr/255/docs/search.index/09c6ace039aa.js deleted file mode 100644 index 0d96cdf22..000000000 --- a/pr/255/docs/search.index/09c6ace039aa.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CASAAABAIkAAQABAwD0VBIAAAEAjgABAPMCAmJ1OjAAAAEAAAAAABMAEAAAAHMHdAd1BxIPEw+yD7MP0Q/SD2QQZRASERMRHhIfEisSLBI7EqgSqRI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/09f0b7b1cb10.js b/pr/255/docs/search.index/09f0b7b1cb10.js new file mode 100644 index 000000000..5c6f17131 --- /dev/null +++ b/pr/255/docs/search.index/09f0b7b1cb10.js @@ -0,0 +1 @@ +rn_("AQ0A9VETAAABAAEAcAABAAGAAqEQAAATirBwE58AAW5yAQcA9FsRAAABAAEAAQAzAASgIAAACXuw4BN/AAExZWly9BAEAACgA6wBIAMBAgD0rBAAAAEAewEBAAEDAPQYEQAAAQBgAQEA8wACYnUBxw8AAAEDAPSqEAAAAQB7AQEA84QCZHMBAgDzXgkAAAEAVADzgAJpdAEYAPMnFAAAAQABAAGAArCwE08AAaDAAAAS/GV184ECY20BDQGwQBPPAAFl9ZcTAAABAAEAAQABABOCArAAEMIAAWtzAQQA9FMQAAABAAEAAQABgQKgIAAAEL2wQBLsAAFlafOCAmV0AQQBoGAAABJOcvQ2DAAAAQCOAwEA84ADYWVvAQkA9ncSAAABAOoAfwAwAAEAE4ACsGAQawABZG4BBgD1lRAAAAEAAQABAGkCAQMBoHAAABKqZ/S9BwAAAQDzAQEAAQkA8+YTAAABADUAAYECsIAT9AABoGAAABQYZHMXAQCIhbDQFBoAAaBAAAATyrBgE54ASwKQCgEEAPQ9EwAAAQBKAAEAU4ADsJAUEwABZWhvAQABoEAAABElZQF5DwAAI4ECsFAQzwABa3R3/AEAjaGQAAAUCrCwErgAAaCgAAASdv2BDzswAAABAAAZAAgAcQAAAHcAAwDpBQEAmwcDAIYJAwBUDAcA/w8BACUSAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0adb0f113264.js b/pr/255/docs/search.index/0adb0f113264.js new file mode 100644 index 000000000..9194f6887 --- /dev/null +++ b/pr/255/docs/search.index/0adb0f113264.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAAkABACqCQEARRADAIMQAQBgEwEAAQIBsEAT5AABdDswAAABAAANAAYAghIDAOUSAQBMEwEAYxMBANoTAQD+EwEAE4ACsDASrwE0aXABiAKwABNXAAGwABNZAAE0NhOBAqAwAAARKGRzAYACoCAAAAyEsGATiAABbngBBQDzJBMAAAEAAQATgAKgMAAAE3plefMAhBIAA/LtDwAA2wDzgAJydA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0aebd591215a.js b/pr/255/docs/search.index/0aebd591215a.js deleted file mode 100644 index 24412bcf9..000000000 --- a/pr/255/docs/search.index/0aebd591215a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoCAAAAyQbQHNBQAAAQQBsAASEAABZPS6EQAAAQABAAEAI4SEsKATPgABsEASDgABsHAS7gABFYAAM4ADsNATLAABYWVp") \ No newline at end of file diff --git a/pr/255/docs/search.index/0b049d31f2d1.js b/pr/255/docs/search.index/0b049d31f2d1.js new file mode 100644 index 000000000..4eb697192 --- /dev/null +++ b/pr/255/docs/search.index/0b049d31f2d1.js @@ -0,0 +1 @@ +rn_("AQADsCAQ7wABoFAAABGUoEAAABOobHN28qMTAAABAAECAPR1EQAAAQABAAEAE4QCsCAReQABYXPzgAJhZROAAmzK071KfXJzAQEAOzAAAAEAAAYAAQAjFAYA8wYBZfTYEwAAAQAuAAEAEwcDsEAUAAABoGAAABOBYXJ1ASUQAAAjgAKgEAAADC1lcgEAADswAAABAAAeAA4ATAUBAP8FCAB5CQEAQAwBAOkMAQB0DgAAbA8CAIIPAACgDwEAiRABAJwQAAAxEQAAiBEBAI0RAAABAQA6MAAAAQAAAAAACgAQAAAAZQxmDDIQMxDEEMUQxhBtE24T7BPxEwGBArAAESEAAbAAESMAATQ2AQUA9HYTAAABAEYAAQDzBAFj8osSAAABAAEDAaBAAAATp2Xy0RMAAAEAAQQA85ASAAABAEYBAQQBsAASkgABZPQ8EgAAAQABAAEAZxIAAYmwoBO/AAGgUAAAEl+gMAAAEMqwYBPyAAGwcBNwAAG1yAQ6MAAAAQAAAAAACgAQAAAAVAmCCW8McAytD64Prw9+EckSyhKVExGBAhCwIBF5AAFhcwECAPNVEgAAAQABAPcAAIDFoBAAABBLgAA4CAEFAPRTEgAAAQCaAAEAAQgA9P8SAAABAIMAAQAzAQOwQBLUAAFhYmX19wwAAAEA7gJIAsMAAQAA9UAMAAABACsDAQABAPOCAnN1AQYA9C0QAAABALEAAQAzAAOgoAAAFCpidHf18QUAAAEA2A1QAAEAAQ8A9JITAAABAEsAAQABBAD0KxAAAAEAsQABACOAArEAE+8AAW9w84ECc3QBBAGgoAAAFCp38hoUAAABAAELAPOPEwAAAQABAAEMAPT9EgAAAQCjAAEAI4ACoHAAABO1Z3fzgAJlbwENAPPhEwAAMAABAAEQAPMJFAAAFgABAAEBAaBgAAASTnL3LQYAAAEAJwLhAwEAjgMBAAEDAaAAAAAP5XPzPQwAAAEAAQABAwDzPAwAAMgEAQABgAKgQAAAE06wMBJ9AAFhc/OAA25ydgEJAPSOEQAAAQAeAQEAAQcA9LMQAAABAKsAAQDzgAJoaQEBArAgDPUAAbAADHkAAWVz8sUHAAABAAEFAPSTDwAAAQDiAAEA84ACYmPX7wAAjaAgAAAHx6DgAAATgrDQE3QAARf1CzowAAABAAAAAAAaABAAAADYAdkB2gEUBBUEZQkmDDgMdwx4DHsM3AzdDN4M3wxvDiQQcBAaERsRYRFiEXsTvxPAE9MT1BMBgAKgsAAAE9ygMAAAEMdsbhMAArCAE6kAAWVw84ETAAAkAAEAAQMBsEATzwABZfWXEwAAAQABAAEAAQABBgD0MhMAAAEAAQABAAEPAPQLFAAAAQABAAEAAQIAOzAAAAEAAAUAAQD2EwUA8w0BbTswAAABAAAFAAEAtxMFAAEEAPVAEgAADAABAIMAAQABAAKgEAAAEQOw8BQTAAFla/eKEwAABQABAAEAJAATAAEAAQIA9FcQAAABAAEAAQABAgD0IRAAAAEAqQABAPeTAQCNoFAAABC2oQAAABP8sQAUAAABoKAAABLLvbwDOzAAAAEAACIADAAWDAMApw8AAM8PAQDVEAcALBEAAGASAQBpEgEAbRIBAMMSAQDgEgQArxMEABkUAAABAgA7MAAAAQAACwACAEUTBQD2EwUA8wEBbTswAAABAAANAAQA1wwAABARAABvEgUAtxMFABMBAqAwAAAM22Vz8pwRAAABAAGJArAgE9oAAaAwAAAT42lwEwADoCAAABKqoIAAABK9ZWl19SoMAAAyAAEAAQABAAGGArCQE/4AAaAAAAASRGJkAYACsDASngABoDAAABCacnbXAAADhaAwAAAQGKAwAAAS8hABEzowAAABAAAAAAAJABAAAABOCU8JUAmACYEJLxA0EOsQ7BCBEgEGADowAAABAAAAAAAHABAAAACLD4wPTBBNEKASoRIqEysTAQcA9BETAAABAAEAAQB3AAAAhqBwAAATJ6BAAAASwaBwAAAQyENABTswAAABAAAQAAcA7wEAAL0HAQCxCQEAnhABAKoQAQA3EQUAJhIBAHd3AICLsLAT6gABoGAAABDItUEP") \ No newline at end of file diff --git a/pr/255/docs/search.index/0b8810d9f049.js b/pr/255/docs/search.index/0b8810d9f049.js new file mode 100644 index 000000000..23997d348 --- /dev/null +++ b/pr/255/docs/search.index/0b8810d9f049.js @@ -0,0 +1 @@ +rn_("AQEBoEAAABPOZfLtEwAAAQABgAOgMAAAEiyw4BOtAAGwkBPvAAFhY22HAQCAhrAQEM8AAbAQEO8AAaCgAAAT3KDwAAAT/DFJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0b9da5e00812.js b/pr/255/docs/search.index/0b9da5e00812.js deleted file mode 100644 index 20e0f009e..000000000 --- a/pr/255/docs/search.index/0b9da5e00812.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9LYQAAABAAEAAQABAgA7MAAAAQAADAAFAMsLAQC6DwUA2BEBAC4SAQBBEwAA84ACZm4BAQA7MAAAAQAABwACAN8OBQBWEgEA84ACZG4BAQDzWgcAAAEAAQABhgKgAAAAElCgAAAAElFkcvMBAXYBdhIAAEMAA7CAEesAAbCwE24AAWtscjswAAABAAAMAAMAUQcIAKkMAQB7DwEAAQIA9R4IAAABAAEAAQABAPMAhBRBAAFpAAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/0bfb65fd762c.js b/pr/255/docs/search.index/0bfb65fd762c.js new file mode 100644 index 000000000..a9bf99a9a --- /dev/null +++ b/pr/255/docs/search.index/0bfb65fd762c.js @@ -0,0 +1 @@ +rn_("AQABsGATfwABZQG0EwAAAQYA9LQSAAABADoBAQABBAD0zhIAAAEA/QABAPMAA2VyczowAAABAAAAAAAJABAAAAB2CXcJeAnoECcRIxIkEjESeBN5Ew==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0c4100bc39d6.js b/pr/255/docs/search.index/0c4100bc39d6.js new file mode 100644 index 000000000..2a7ad97e5 --- /dev/null +++ b/pr/255/docs/search.index/0c4100bc39d6.js @@ -0,0 +1 @@ +rn_("AYACsEAS6gABoMAAABOcZW8BAgD0dREAAAEAAQABABMAA7AgEXkAAbCAE60AAWFzdAHhDAAAAQQA860PAAABAAEAs4CEsEAS+QABQQAG") \ No newline at end of file diff --git a/pr/255/docs/search.index/0cad63531c89.js b/pr/255/docs/search.index/0cad63531c89.js new file mode 100644 index 000000000..73c79daf9 --- /dev/null +++ b/pr/255/docs/search.index/0cad63531c89.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAUAAQAIEwUAAQAA9YcMAAABAAEAAQABAPOAAmdrE4ACsLATYAABYW8BgAKgIAAADBWwYBD7AAFlaQGFArBwE4gAAbAwEuUAAWVzEwADsEAPhwABoGAAABEwYmVzOzAAAAEAABIABAAgBgEALwcKAP0PAQBPEAMAAQMA9BkQAAABAAQAAQABCwGgQAAAE85l8u0TAAABAPOAAmRy8wACZW87MAAAAQAABwACAP0HAwA+CAMAAQIAOzAAAAEAAAkAAQALDAkA84ACb3QBAwA7MAAAAQAA3gACANcHAAAtC90AAQIBoHAAABGbaTswAAABAADwAAIA1gcAAD0K7wATgAKgQAAADEVydQEEAPTFEgAAAQCOAAEAAQMA81wSAAABAJoA84ACYW/XBwAAiLBADP8AAbEwE+oAATSBFjswAAABAAAeAA0ARwUBAPkFAQAdDAAASgwHAG0MAQCVDwEAeRABAAYRAABVEQMAkhEBADsSAACUEgEADxQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0d24876322d0.js b/pr/255/docs/search.index/0d24876322d0.js deleted file mode 100644 index 832460a70..000000000 --- a/pr/255/docs/search.index/0d24876322d0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA90kQAAABAAEAoAIBAH8ABQABAgD03A8AAAEAAQABABOAAqDQAAATW2Nz84ACZW8jgQKwAAd7AAFsdAEAAPT5BQAAAQABAAEAU4ADoFAAABOpZG5y") \ No newline at end of file diff --git a/pr/255/docs/search.index/0d377ac14863.js b/pr/255/docs/search.index/0d377ac14863.js deleted file mode 100644 index cfe321ec0..000000000 --- a/pr/255/docs/search.index/0d377ac14863.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9CMRAAABAAEAAQAjAAKgcAAAESJhcgGhBwAAAQAA9kcQAAABAE0DAQAKAAEAAQAAOzAAAAEAAAYAAgCAEgAA5RIFACOIArBAE1QAAWVzAQ0BsEATTgABZfUUEwAAAQABAAEAAQABBQA7MAAAAQAACAADABwRAgAEEgQAExMAANcDAACGeJvYCPEYFIQG9SAFAAABAFMHAQABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0d5508bf0207.js b/pr/255/docs/search.index/0d5508bf0207.js deleted file mode 100644 index df8240998..000000000 --- a/pr/255/docs/search.index/0d5508bf0207.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoDAAABBDoJAAABKFMGj1IhEAAG0BAQABAAEAE4ACoDAAAA8GZHIjAYSwEAkIAuiwIAvEAO6gMAAADyoSABj14wUAAC4AAQABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/0dbe969ddebd.js b/pr/255/docs/search.index/0dbe969ddebd.js new file mode 100644 index 000000000..4465f2500 --- /dev/null +++ b/pr/255/docs/search.index/0dbe969ddebd.js @@ -0,0 +1 @@ +rn_("AQkA8+YTAAABADUAAQ0BoKAAABQqd/IaFAAAAQABgQKwgBP0AAGgYAAAFBhkczcBAIaFoEAAABPKsGATngBLApAK") \ No newline at end of file diff --git a/pr/255/docs/search.index/0dd31cbab4cc.js b/pr/255/docs/search.index/0dd31cbab4cc.js deleted file mode 100644 index dad532e22..000000000 --- a/pr/255/docs/search.index/0dd31cbab4cc.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCATWQABoDAAABNiaXATAAOgIAAAEiiggAAAEjtlaXX10QsAADIAAQABAAEAAYYCsJATfQABoAAAABHCYmQBAgD01gsAAAEADgMBAAEAADswAAABAAAGAAIAgBIAAOUSBQAjgQKwQBNUAAFlc1OAA7AACUYAAWV4eQGAArAgEhwAAbAACUQAAXJ4pwAAAMWwwBKsAAGwQAyLAAGgMAAAEB8ABIAL87kFAAABANcGcwCEoDAAABJwEAATOjAAAAEAAAAAAAoAEAAAAAwJDQkOCT4JPwnbC7QPuQ9wEHEQ/xE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0e34ce7f7192.js b/pr/255/docs/search.index/0e34ce7f7192.js new file mode 100644 index 000000000..89cc8858c --- /dev/null +++ b/pr/255/docs/search.index/0e34ce7f7192.js @@ -0,0 +1 @@ +rn_("AQQAOjAAAAEAAAAAAAcAEAAAAIsPjA9MEE0QoBKhEioTKxMBAAD0UgkAAAEA+wncABcAAACHoEAAABC3sGAT0wABoBAAAAySsFATdAABsDARGgABsSAT8gABOMECOjAAAAEAAAAAAA4AEAAAAGcJaAl8CX0JIAwhDCIMKwwsDOAMLBL/EgATgxOEEzOAA6CAAAATe2VveQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/0e61017bc68b.js b/pr/255/docs/search.index/0e61017bc68b.js deleted file mode 100644 index 75e128870..000000000 --- a/pr/255/docs/search.index/0e61017bc68b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9QgRAAABAAUBAQBHAQEBAPdJEAAAAQABAKACAQB/AAUAAQIA9NwPAAABAAEAAQATgAKg0AAAE1tjc/OAAmVvI4ACsAAHewABbHTzAAJhcvLnDgAAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0f103fffad43.js b/pr/255/docs/search.index/0f103fffad43.js new file mode 100644 index 000000000..bbfdee40a --- /dev/null +++ b/pr/255/docs/search.index/0f103fffad43.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAN4AAgAlDAAAFQ3dAPMAAW07MAAAAQAA3gACABcGAABEBt0AAQMAOzAAAAEAAAcAAgBYDwUA2BIBAPMAAWM7MAAAAQAAVwAmADAFCwDlBQEAYAkBADwMAABCDAIA8wwAAP4MAgAQDQEAfw8AAIQPAQCHDwEAjQ8AABIQAgAZEAEAHhABAD0QAACxEAAAtxAAAAQRAQAREQEAJREBACkRAgCEEQEAlRECAJsRAABAEgAARxIBAEwSAQCQEgEAnBIDAL4SAQDOEgMA1BIBAC4TAQA/EwAApxMAAMwTBADVEwIA84ACcncBCQDz5hMAAAEANQABDAGgoAAAFCp38hoUAAABAAEBAPOoDwAAAQABAPOAAnR1AYECsIAT9AABoGAAABQYZHM3AgCBhqBAAAATyrBgE54AS7AwE4sAAQKQDgGIArAAE1cAAbAAE1kAATQ2M4ADoDAAABEoZG5zYwADoBAAAAVQYWVvAXYAAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0f1e1d1cc48f.js b/pr/255/docs/search.index/0f1e1d1cc48f.js new file mode 100644 index 000000000..cfb291d06 --- /dev/null +++ b/pr/255/docs/search.index/0f1e1d1cc48f.js @@ -0,0 +1 @@ +rn_("AQMA9gQNAACWAlkAAQCmAgEAAQQAOzAAAAEAAAoABAA1EAUAWhIBALASAQDCEwAAAYYCoAAAABLSoAAAABLTZHLzAgF2AfgSAADzgAJlbycBAADHoDAAAA+ZoHAAABItoIAAABOVoNAAABM7oLAAABOVQEUICTswAAABAAAJAAMANQYCAIQHBABrDAEAI4ACaXe0yZZoZHIBAAA6MAAAAQAAAAAACgAQAAAAnwmgCc4P6hLrEhYTFxO2EwkUHxQgFBOAAqAwAAAQS2x084ACYWU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0f434453b623.js b/pr/255/docs/search.index/0f434453b623.js new file mode 100644 index 000000000..5ab61309b --- /dev/null +++ b/pr/255/docs/search.index/0f434453b623.js @@ -0,0 +1 @@ +rn_("AQAA9sIQAAABAFMDAQAKAAEAAQAAOzAAAAEAAAYAAgACEwAAZxMFACOIArBAE9UAAWVzAQ0BsEATzwABZfWXEwAAAQABAAEAAQABBQA7MAAAAQAACAADAJgRAgCGEgQAlhMAANcBAACFa9tI9uj+FIQC89IMAAABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/0f835c2828ff.js b/pr/255/docs/search.index/0f835c2828ff.js new file mode 100644 index 000000000..fa7063a06 --- /dev/null +++ b/pr/255/docs/search.index/0f835c2828ff.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAUAAQD2EwUA8w0BbTswAAABAAAFAAEAtxMFACMDhLBAEkwAAaEAAAAT/KAAAAATgTAIAjswAAABAAAUAAUA1RAHAG0SAQDgEgQArxMEABkUAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/0fa74a34d33c.js b/pr/255/docs/search.index/0fa74a34d33c.js deleted file mode 100644 index e2de71d3a..000000000 --- a/pr/255/docs/search.index/0fa74a34d33c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQADoKAAABNBoCAAABKEsDARDAABZWl08vkRAAABAAEDADswAAABAAAGAAEAjBAGAAEIAPTrEgAAAQB/AAUAEwEDsJATSwABsFASOgFPZ2xwOzAAAAEAABIACQCbDwIADxEBACkSAQBKEgEAexIBANwSAQAPEwEAHhMBAF0TAQABgAKwMBEIAAGwMBEKAAFydgECAbAAEb8AAWQ7MAAAAQAABQACAAQRAwDpEQEAI4ECoJAAABNAaW8BBwD0XBMAAAsAHgAPAHcWAACJsFAS+wABsFARwQD9sGASOAABtQkDOjAAAAEAAAAAAA0AEAAAAIQMhQyGDAgOCQ73D/gPMxBWELYQtxC4ELkQMBI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1017c7914851.js b/pr/255/docs/search.index/1017c7914851.js new file mode 100644 index 000000000..98c62887e --- /dev/null +++ b/pr/255/docs/search.index/1017c7914851.js @@ -0,0 +1 @@ +rn_("AQAEoAAAABA/sCAQ7wABoFAAABGUoEAAABOoZGxzdjswAAABAAATAAYAIwYAAEUMAADrDAAAtw8NABMRAACjEwEAAQIA9HURAAABAAEAAQAThAKwIBF5AAFhc/OAAmFl") \ No newline at end of file diff --git a/pr/255/docs/search.index/103f1ba9c2d5.js b/pr/255/docs/search.index/103f1ba9c2d5.js deleted file mode 100644 index 797424c92..000000000 --- a/pr/255/docs/search.index/103f1ba9c2d5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsCAQbgABsDAQ5QABZXABBQD0HA8AAAEA4QABAFOAA7CQERYAAWFpcgGBArCgEwkAAbCgEwsAAWNyxwAAAIWwUAyaAAGgIAAACXmgIAAAC9s8AAE6MAAAAQAAAAAACgAQAAAAfQF+AQoEKgcwCTEJrA+tDxgQGRAnEQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/10e19c9358f8.js b/pr/255/docs/search.index/10e19c9358f8.js deleted file mode 100644 index 416058e06..000000000 --- a/pr/255/docs/search.index/10e19c9358f8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABJGc/QIDwAArwMBAAIAAQECsGATKgABsEATYwABZHQ7MAAAAQAADQAGAAASAwBjEgEAyhIBAOESAQBZEwEAfRMBAAEBhLBwESAAAbCAEd4AAaBgAAASeoAScwAQ7QAwAzswAAABAAALAAIAAgkFAFgSBQCjgISgsAAAErmxcBOcAAEIQIIBAISgcAAAEamgcAAAEDaxABMqAAGwABI6AU8CIQHywQUAAAEAAQEAOzAAAAEAAAYAAQCiEwYA8wYBZfRXEwAAAQAuAAEAEwEDsEATfwABoGAAABL/YXJ1AaoPAAB3BAAAh6AQAAAF9LAwEi0BNaBAAAAQWRHBDDswAAABAAAGAAIAgBIAAOUSBQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1119c1193e11.js b/pr/255/docs/search.index/1119c1193e11.js new file mode 100644 index 000000000..0801cce6b --- /dev/null +++ b/pr/255/docs/search.index/1119c1193e11.js @@ -0,0 +1 @@ +rn_("AQAA9KwQAAABAHsBAQAjgQKgYAAAEr1iaQEAAPSgDwAAAQDoAAQBI4ICsFAS0AABZXMBiQKwIBPaAAGgMAAAE+NpcAECAPSiEgAAAQCJAAEAAQMA9NYSAAABAI4AAQDzhQJidQECAPQYEQAAAQBgAQEA84ACaWy3AQAAhaAgAAASqhIBDDowAAABAAAAAAAUABAAAADTB18IYAhhCGIIKgxcDF0MXgxfDMcPgBAjE54T5hPnE+kT9BP1ExgUHBQBBQDzhRMAAAEAAQBDhgOwkBP+AAGgAAAAEkRiZHcBgAKwAAltAAGwIA0GAxJkbgEDAPOeDwAAAQD7AAECAPYvDAAAAQAuAwEApQMBAAEAADswAAABAAAGAAIAAhMAAGcTBQAjgQKwQBPVAAFlc1OAA7AACYgAAWV4eQGAA6BAAAAT/LAgEp4AAbAACYYAAWVyeAGAAqBAAAAM8bBAD8gAAWdsFw0AAMiwwBMuAAGgEAAAERSgMAAAE3uwQAzpAAEARqALOjAAAAEAAAAAAAkAEAAAAOcF6AXvDPAMBA2aD/MP9A+aEpsSAQYA9KASAAABAIkAAQDzAwFi9KoQAAABAHsBAQC3DAAAiaBwAAASMrCQEs4AAbBgD+sAAaAwAAAS8jiJEzowAAABAAAAAAAtABAAAAA4BjkGOgY7BpgHmQdOCU8JUAmACYEJNAz7DPwM/QwBDQINAw2XD5gP6Q/qD+4P7w8LEAwQDRAOEA8QEBAREC8QNBBOEHsQfBDrEOwQgRIDEycTSxPdE+gTBhQVFA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/118928699d86.js b/pr/255/docs/search.index/118928699d86.js new file mode 100644 index 000000000..68e961e0e --- /dev/null +++ b/pr/255/docs/search.index/118928699d86.js @@ -0,0 +1 @@ +rn_("AQYA9JQSAAABAHoBAQATAgKwYBKWAAFmbfLlDAAAAQAjggKwQBK+AAFlbAEFAPR2EwAAAQBGAAEA8wMBY/KLEgAAAQABgQKgAAAACX+gMAAAD4ZzdBOAAqAQAAAHsG5404CEsHAUHQABkEAB") \ No newline at end of file diff --git a/pr/255/docs/search.index/1198e3f6eeb3.js b/pr/255/docs/search.index/1198e3f6eeb3.js deleted file mode 100644 index b501b703f..000000000 --- a/pr/255/docs/search.index/1198e3f6eeb3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAHcAAgCbBwAAfwl2AAGEArBwEyQAAaBAAAAQP2lzAQcA8xgQAAABAA4BI4ACoLAAABHcYXQBAAOwMAkyAAGwMBKNAAGgIAAAB5xhZG8B2wEAADcDAICGoMAAABMasAAS8gABAJgV") \ No newline at end of file diff --git a/pr/255/docs/search.index/11ac60f101c2.js b/pr/255/docs/search.index/11ac60f101c2.js new file mode 100644 index 000000000..30f5e9f51 --- /dev/null +++ b/pr/255/docs/search.index/11ac60f101c2.js @@ -0,0 +1 @@ +rn_("AQUA9KYQAAABAAEAAQATgAKgsAAAE29jcwEEAPNyDwAAAQABAAGAAqBQAAAQeKBgAAAQ6GlyAYACoCAAAAyBoGAAABDnZWgBAQGgIAAAEOZi830MAAABAAEAE4ECoBAAAAyAYWMBgAKgEAAAEzuwMA0TAAFlcyMAAqBAAAATzmV38u0TAAABAAEGAPSUEgAAAQB6AQEAEwACsGASlgABZm3y5QwAAAEAAQEA9LMQAAABAKsAAQAjgAKgsAAAE1ZkZwGCAqCgAAASwqBAAAAQIG9284ADZ25yAYACoEAAABKPoDAAAA9vaGw3PwAAirBAD3AAAaAwAAAMfDRgVzswAAABAAAaAAQA3QEAABsEDgALDAkA1gwAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/125b8dc7d658.js b/pr/255/docs/search.index/125b8dc7d658.js deleted file mode 100644 index c243fb2c3..000000000 --- a/pr/255/docs/search.index/125b8dc7d658.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsIAS2gABdAEkCQAAAQkA89MRAAABAAEA84ACY2cBgwKgkAAAEyCgkAAAEyEyMwGAAqBQAAATSqCAAAASdmNl8wACc3TyZwcAAAEAAQABoLAAABK9YvVREgAA0QABAEYAAQAjgAKgAAAAElBkciOAAqBQAAATEmNl84ACaXkBBgD1ZhAAAAEAAQABAAEAAQEBsEATTgABZfUUEwAAAQABAAEAAQD3AACAhaAQAAAL0ClgAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/125c69e2afa8.js b/pr/255/docs/search.index/125c69e2afa8.js new file mode 100644 index 000000000..35fc3c1d3 --- /dev/null +++ b/pr/255/docs/search.index/125c69e2afa8.js @@ -0,0 +1 @@ +rn_("AYQCsAARIQABsAARIwABNDbzAAFh8oIMAAABACOAArCQEScBCmx0AYACsHATDwABsIATQwABY3MBAAA6MAAAAQAAAAAACQAQAAAAfBF9EX8SgBJcE10TrROuEx0UHhTzgAJkZScBAICFoNAAABOCsBAFSQABoDAAABAjAggL") \ No newline at end of file diff --git a/pr/255/docs/search.index/12aab9d7ac8d.js b/pr/255/docs/search.index/12aab9d7ac8d.js new file mode 100644 index 000000000..e7ca80d91 --- /dev/null +++ b/pr/255/docs/search.index/12aab9d7ac8d.js @@ -0,0 +1 @@ +rn_("AQEBoEAAABEsc/VHDAAAuwQyAQEAAQATggKgIAAADQ9lciOAA6BAAAAMRrAwCXkAAWVvdAECAPQYEwAAAQAPAAEAE4ACsEATxQABYnYTgAKwAAebAAFveAEKAPVREwAAAQABAHAAAQABgQKgIAAAEJywUBJFAAFhbwEEAaAAAAATVnMBmxAAAGMDA7BQEQ4AAWNlc/ZVCQAAAQABACwAAQCpCAEBAPTcDAAAAQABAAEAI4ACsDASvAFOcnT3AQAAhrAQB50AAQHAB/LGAQAAiQ8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1323b5cdf876.js b/pr/255/docs/search.index/1323b5cdf876.js new file mode 100644 index 000000000..78f586d58 --- /dev/null +++ b/pr/255/docs/search.index/1323b5cdf876.js @@ -0,0 +1 @@ +rn_("AQEAOzAAAAEAAAcAAQChCQcAAQIA9/kPAADQAIgCAQABAHAAAQATgAKwMBCKAKdpdPMAAXPy8hMAAAEAM4ADsRATcAABZG5w") \ No newline at end of file diff --git a/pr/255/docs/search.index/1344897c571c.js b/pr/255/docs/search.index/1344897c571c.js deleted file mode 100644 index 171da9503..000000000 --- a/pr/255/docs/search.index/1344897c571c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CASAAABAIkAAQABAgD0JRAAAAEAmwABAAEDAPRUEgAAAQCOAAEAAQIBoEAAABI/cjswAAABAAAHAAIAIxABALsQBQDzAIQDQAg6MAAAAQAAAAAAFQAQAAAAcwd0B3UHEg8TD7IPsw/RD9IPZBBlEBIRExEeEh8SKxIsEjsSZRJmEqgSqRI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/138a5af4d179.js b/pr/255/docs/search.index/138a5af4d179.js new file mode 100644 index 000000000..e1d80a36f --- /dev/null +++ b/pr/255/docs/search.index/138a5af4d179.js @@ -0,0 +1 @@ +rn_("AQABoDAAABEsdPRpEAAAAQAXAAEAAYACoAAAABA7oAAAABA8NDbzAwF2AQUNAAAXAQAAh7CgEpwAAbAgDDkAAbBgEpgAAbCAEn8AAaAgAAAQoglERjowAAABAAAAAAAJABAAAABuB28HcAdHDKYPAhE0EjUSNhLHEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1409f2140ee5.js b/pr/255/docs/search.index/1409f2140ee5.js new file mode 100644 index 000000000..f33056f42 --- /dev/null +++ b/pr/255/docs/search.index/1409f2140ee5.js @@ -0,0 +1 @@ +rn_("AQkBoEAAABPOZfLtEwAAAQABgAKwAAzsAAGggAAAEzxkcAEDAaAAAAAP53Pydw8AAAEAAQIDsGASwwABsNAT0QABoIAAABNbaXJzAdwTAAD3AACAhaEwAAAT7JBJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1455b2c199cd.js b/pr/255/docs/search.index/1455b2c199cd.js new file mode 100644 index 000000000..6e7ac3768 --- /dev/null +++ b/pr/255/docs/search.index/1455b2c199cd.js @@ -0,0 +1 @@ +rn_("AQQA9FMQAAABAAEAAQABAAA6MAAAAQAAAAAACgAQAAAAlQ+WD3kQehAGEZIRkxGUEpUSDxQQFPMBAXnyfRMAAAEAAQADoKAAABPCoCAAABMGsDARiAABZWl08nsSAAABAAEDADswAAABAAAGAAEABxEGAAEIAPRtEwAAAQB+AAUAEwEDsJATzAABsFASvAFOZ2xwOzAAAAEAABIACQAVEAIAixEBAKsSAQDMEgEA/RIBAF4TAQCSEwEAoRMBAN4TAQABgAKwMBGEAAGwMBGGAAFydgECAbAAEkEAAWQ7MAAAAQAABQACAIARAwBrEgEAI4ECoJAAABPBaW8BBwD03RMAAAsAHgAPAHcWAAGJsFATfQABsFASQwD9sGASugABtQkDOjAAAAEAAAAAAA0AEAAAAOIM4wzkDHUOdg5yEHMQrhDREDIRMxE0ETURshJDgAOgIAAADNigEAAADOFtbm8BAwD0EhAAAAEAAQARAQGAAqCwAAATlLAwEuwAAW50QwADoCAAABC9sFARkAABZWhpOzAAAAEAAAYAAwAoDAAAnxEDAEMTAQDzgAJkcocLAAAKgAHKABABgAHNABABoFAAABEvoFAAABPHoDAAABA/oDAAABBKMDFjZWlvc3R1d/X7BwAAAQB9B7ICRAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1499361f517d.js b/pr/255/docs/search.index/1499361f517d.js deleted file mode 100644 index 57ad35af1..000000000 --- a/pr/255/docs/search.index/1499361f517d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9KYPAAABAKkAAQABAAGggAAAE5hm8gsJAACBCQEHAPVeEgAAAQABAAEAAQAjgAKgUAAAEIthb/MCAmZzOzAAAAEAAAgABAB2BwAApwcFAKcMAADDEAAAM4ADoEAAAAvOYWVv") \ No newline at end of file diff --git a/pr/255/docs/search.index/1511e66727f1.js b/pr/255/docs/search.index/1511e66727f1.js new file mode 100644 index 000000000..7fd289146 --- /dev/null +++ b/pr/255/docs/search.index/1511e66727f1.js @@ -0,0 +1 @@ +rn_("AQMBgBL1ABDsczswAAABAAAFAAEA2hIFACOCAqCQAAATy2lzAQEA9KISAAABAIkAAQAjgAKwoBN9AAFjbgGEArCgE4sAAbCgE40AAWNyAQIAOzAAAAEAAAYAAQALEAYAE4ICoCAAABNvZXUBAgDzaxEAAAEAAQABgAKwIBOrAAGgYAAAEwNvdmOBA6AQAAASwmFjcwEDAPTcDAAAAQABAAEAAQEA9KAQAAABAJwAAQATgAOgwAAAE9ewEAlvAAFucHUBgAKwMA/IAAGhYAAAFAphZQGBArBAEk8AAbBAElEAATQ2AQUA9CEQAAABAKkAAQBTgISgsAAAE5SwMBLsAAEBoAQBCADz6RIAAAcAFwATgAKwQBGQAAFhZQEAAaAgAAAQPXIBAxEAAAEAAPQ9EwAAAQBKAAEApwAAgIWgMAAAEJ2gEAAAEL2woBOfAAEJICEBCQGgQAAAE85l8u0TAAABAEOAhKAgAAAT3KCQAAATPKEwAAAT7BBJAAECAPTWEgAAAQCOAAEAE4ACsEASpAABaXkBAQKgMAAAEoGgQAAAEsFncjswAAABAAAHAAIAnhABADcRBQABgAKwABNXAAGwABNZAAE0NgEGAPQWFAAAAQAKAAEA8wICcnYBghMAAPMCAWX0KRAAAAEAqAABAPOAAmR0560/ABKgMAAAEL6gQAAADPGw8BQTAAGwcBMEAAEwYWJjZWdoaWtsbm9wcnN0dXY7MAAAAQAA9wBFAEsFAAAdBgIAJwYDACoHAACJBwAArAcCALwHAADOBwQA1AcAADUIAABdCAEAUgkBAFgJAQBkCQAAvQkBAMEJewAaDAEAKAwAADUMAABqDAAAdgwAAGMPAQCLDwEAog8AAAQQAAAtEAEAPxAAAEwQAQCREAEAlRADAKYQAwDfEAEAAREAAB4RAgBOEQAAZxEAAIoRAACOEQEAnhEEADISAABBEgEARBIAAE4SAABfEgAAkhIBAKASAQCtEgEAtBIBALoSAQC9EgAAwBIAANISAADnEgEA/BIAAAETAAAREwQAKhMBADsTAAA9EwEAQxMBAE4TAAB8EwAAiBMCAI8TAgCpEwEAtRMAAMgTAQDvEwEAKhQAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1552619586d7.js b/pr/255/docs/search.index/1552619586d7.js new file mode 100644 index 000000000..1630d8ae6 --- /dev/null +++ b/pr/255/docs/search.index/1552619586d7.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAABYACQAFEAUADhEBAJgRAgBYEgEAhhIEAHITAQCWEwAAwRMAAOATAAAjgAOh8AAAFCqw8BQdAAFjZmcjgAKwUBMwAAFtbgEFAPNyEwAAAQBtAPMEAWMBLxEAAAEBAbBwE8UAAXA7MAAAAQAACQACADYIBwB0EAEAAQIAOzAAAAEAAAsAAgBFEwUA9hMFAPMBAW07MAAAAQAADQAEANcMAAAQEQAAbxIFALcTBQATAAKgMAAADNtlc/KcEQAAAQABggKwcBOlAAGgQAAAELppc/cBAICGsJATiwABkEkI") \ No newline at end of file diff --git a/pr/255/docs/search.index/1566e3c31611.js b/pr/255/docs/search.index/1566e3c31611.js deleted file mode 100644 index 157f4338d..000000000 --- a/pr/255/docs/search.index/1566e3c31611.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQwBoKAAABOpd/KZEwAAAQABAQDzLw8AAAEAAQABiYSggAAAE5egQAAAE0mgYAAAE2igkAAAE5sCgAoTgYSgoAAAEuCxoBOnAAGw0BNCAAEEAQnzgANhdHU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/16045633eb64.js b/pr/255/docs/search.index/16045633eb64.js new file mode 100644 index 000000000..1fddcf8e3 --- /dev/null +++ b/pr/255/docs/search.index/16045633eb64.js @@ -0,0 +1 @@ +rn_("AQUA9FMSAAABAJoAAQABCAD0/xIAAAEAgwABADMBA7BAEtQAAWFiZfX3DAAAAQDuAkgCwwABAAD1QAwAAAEAKwMBAAEA84ACc3UjgQKwgBL5AAFydAEGAPQtEAAAAQCxAAEAUwCEsIASjQABoKAAABQqAgEU9fEFAAABANgNUAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/16681f81c6a9.js b/pr/255/docs/search.index/16681f81c6a9.js deleted file mode 100644 index 96ab257f7..000000000 --- a/pr/255/docs/search.index/16681f81c6a9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEATYwABdDswAAABAAANAAYAABIDAGMSAQDKEgEA4RIBAFkTAQB9EwEAE4ACsDASLQE1aXABBQDzohIAAAEAAQATgAKgMAAAEvhleVMCA7BwEwYAAWJlcwFzDwAAEwACoCAAAAXqZm32bgAAACAHAQC5AQEAIgc=") \ No newline at end of file diff --git a/pr/255/docs/search.index/16e43e96c3f0.js b/pr/255/docs/search.index/16e43e96c3f0.js new file mode 100644 index 000000000..0aaba5b88 --- /dev/null +++ b/pr/255/docs/search.index/16e43e96c3f0.js @@ -0,0 +1 @@ +rn_("AYICoFAAABJooQAAABP9Y3QjAAKwQA+EAAFldTswAAABAAA3ABYALQcBACMMAQD5DAEAiQ8BAAUQBQA1EAUArxABAA4RAQCYEQIAWBIDAIYSBACwEgEAthIBAMUSAQBBEwEAVBMBAHITAQB2EwEAlhMAAL0TAQDBEwEA4BMAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/16f90e0495ca.js b/pr/255/docs/search.index/16f90e0495ca.js deleted file mode 100644 index cf72b1f02..000000000 --- a/pr/255/docs/search.index/16f90e0495ca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAAUAAQDgEQUAAQACsEASrAABoKAAABMzZXI6MAAAAQAAAAAABwAQAAAA9Ab1BooHiwcjDyQPDBANEFOAA6CgAAATEWdpcw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/17747f0de527.js b/pr/255/docs/search.index/17747f0de527.js deleted file mode 100644 index 4ab4e6bbb..000000000 --- a/pr/255/docs/search.index/17747f0de527.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECoBAAABJAoHAAABKBYWMBhwKwABLVAAGwABLXAAE0NlMAhKCQAAASZ7CwEvsAAYEACfVQBwAAMwBBCA4BGQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/182d04459856.js b/pr/255/docs/search.index/182d04459856.js deleted file mode 100644 index 9d910131f..000000000 --- a/pr/255/docs/search.index/182d04459856.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQsA9JYSAAABAA8AAQABBAGwQBJSAAFlAa0RAADzAAF0AUkTAAABDQDzYBMAADAAAQABEADziBMAABYAAQDzgQNrbXMBAAA7MAAAAQAABgACAIASAADlEgUAI4YCsEATVAABZXMBBAD07g8AAAEAFwABAPOAA2NydDOAhLBgEAoAAaAQAAAF/gEICQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/18c051295b43.js b/pr/255/docs/search.index/18c051295b43.js new file mode 100644 index 000000000..3129c7ab0 --- /dev/null +++ b/pr/255/docs/search.index/18c051295b43.js @@ -0,0 +1 @@ +rn_("AQEBsIAS5wABdfKSCQAAAQAjgAKwEAmQAAEzNgECAPSMCQAAAQBcBwEAAQIA82IMAAABAAEAE4ACsBAJigABaXUBAgA7MAAAAQAACwACAEUTBQD2EwUA8wkBbTswAAABAAAMAAMAEBEAAG8SBQC3EwUAdyAAAIqgMAAAE1uwMBEtAAGgcAAAEZugIAAACY6wMBFhAAGwIAezAdyzhQo7MAAAAQAAFAIEANABAAD1ASIB1gcAAD0K7wA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/18e4b0fb83df.js b/pr/255/docs/search.index/18e4b0fb83df.js deleted file mode 100644 index 0d451aeb0..000000000 --- a/pr/255/docs/search.index/18e4b0fb83df.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgDfEAMAxxECAAEKAbBAE04AAWX1FBMAAAEAAQABAAEA8wACaXP04AsAAAEASgABACOBAqDgAAATNWV5") \ No newline at end of file diff --git a/pr/255/docs/search.index/19476e380db8.js b/pr/255/docs/search.index/19476e380db8.js new file mode 100644 index 000000000..02a49233c --- /dev/null +++ b/pr/255/docs/search.index/19476e380db8.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAADwAAgBxCQAAkww7AAGAArBQEGkAAbCwExgAAWFsYwAEsEAPZwABoBAAABAjYnBydjswAAABAAAGAAEABxEGAAGAArCAELUB/rDgE30AAWlyAQMBsEARBAABZfImDAAASQIBBQA7MAAAAQAABgABAAsQBgABAwD03AwAAAEAAQABAPMAAnBzOjAAAAEAAAAAAA4AEAAAAB0GHgYfBioHZAlqDHYMphCnEKgQqRBBEkISkhKTElcAAACFsFAQWwIbsFAPgwDGoEAAABEwSIADOzAAAAEAAA8ABgAqBQAA3gUDAG8PAACAEQMAPBIDAGsSAQDTAISgYAAADO4QCAbzhQEAAAEASws=") \ No newline at end of file diff --git a/pr/255/docs/search.index/19c9a628ac91.js b/pr/255/docs/search.index/19c9a628ac91.js deleted file mode 100644 index 908fd1d4b..000000000 --- a/pr/255/docs/search.index/19c9a628ac91.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoEAAABNNZfJsEwAAAQABgAOgMAAAEauw4BMsAAGwkBNuAAFhY22HAQCAhrAQEFQAAbAQEHQAAaCgAAATW6DwAAATezFJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/19f55295ffb7.js b/pr/255/docs/search.index/19f55295ffb7.js deleted file mode 100644 index f340452b9..000000000 --- a/pr/255/docs/search.index/19f55295ffb7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA85gPAAABAAEAAYACoLAAABMRsDASagABbnRDAAOgIAAAEEKwUBEUAAFlaGk7MAAAAQAABgADAM8LAAAjEQMAwRIBAPOAAmRy") \ No newline at end of file diff --git a/pr/255/docs/search.index/1a01681e7d77.js b/pr/255/docs/search.index/1a01681e7d77.js deleted file mode 100644 index 601b840e9..000000000 --- a/pr/255/docs/search.index/1a01681e7d77.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA82UTAAABADUAAQ0BoKAAABOpd/KZEwAAAQABgQKwgBNzAAGgYAAAE5dkczcBAIaFoEAAABNJsGATGwBNApAK") \ No newline at end of file diff --git a/pr/255/docs/search.index/1a59836e6e94.js b/pr/255/docs/search.index/1a59836e6e94.js new file mode 100644 index 000000000..6813a4a57 --- /dev/null +++ b/pr/255/docs/search.index/1a59836e6e94.js @@ -0,0 +1 @@ +rn_("AYQCsCARJwEKoJAAABOWbXABgAKgMAAAELKgUAAAEz9jcpcAAACFsCATDwABsMATxQABoGAAABF+EEAOOzAAAAEAABIABgBSBQgAfBEBAH8SAQBcEwEArRMBAB0UAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1a6a4539ae89.js b/pr/255/docs/search.index/1a6a4539ae89.js new file mode 100644 index 000000000..1c0568ed1 --- /dev/null +++ b/pr/255/docs/search.index/1a6a4539ae89.js @@ -0,0 +1 @@ +rn_("AQQBsEATzwABZfWXEwAAAQABAAEAAQABAgA7MAAAAQAACwACAEUTBQD2EwUA8wEBbTswAAABAAANAAQA1wwAABARAABvEgUAtxMFAPMBAWXynBEAAAEAM4CEsBAQMgABoCAAAAwtFEAE") \ No newline at end of file diff --git a/pr/255/docs/search.index/1a6b9bf2988f.js b/pr/255/docs/search.index/1a6b9bf2988f.js new file mode 100644 index 000000000..69faa8d94 --- /dev/null +++ b/pr/255/docs/search.index/1a6b9bf2988f.js @@ -0,0 +1 @@ +rn_("AQIA9KISAAABAIkAAQABAwD01hIAAAEAjgABAPMFAmJ1OjAAAAEAAAAAAAcAEAAAAC0QLhDfEOAQjhGPEa0SrhIBAgD0GBEAAAEAYAEBAAEFAPMeEQAAAQABAAEEAPRTEgAAAQCaAAEA84CEEQkA") \ No newline at end of file diff --git a/pr/255/docs/search.index/1b5a76a5a4b0.js b/pr/255/docs/search.index/1b5a76a5a4b0.js new file mode 100644 index 000000000..285b14ced --- /dev/null +++ b/pr/255/docs/search.index/1b5a76a5a4b0.js @@ -0,0 +1 @@ +rn_("AQMBoAAAAA/lc/M9DAAAAQABAAECAPM8DAAAyAQBACMAAqBAAAAM82Vy8kAFAAABAAGAAqBAAAATTrAwEn0AAWFzAQIBoEAAABPOZfLtEwAAAQDzgARsbnJ2") \ No newline at end of file diff --git a/pr/255/docs/search.index/1b6ac9e761aa.js b/pr/255/docs/search.index/1b6ac9e761aa.js deleted file mode 100644 index 8487ef942..000000000 --- a/pr/255/docs/search.index/1b6ac9e761aa.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoJAAABJuaPI4EgAAAQDzAgFk8kAHAAABAAECADswAAABAAAFAAEAdRMFAPMLAW07MAAAAQAABQABADYTBQAjgAKgIAAADJFhbwECAPMPCQAA+AIBAAGKArAAEtUAAbAAEtcAATQ2I4ECoDAAAAwqZXIBgAKwQBEWAAFXDmQSJYJjdbcGAACHsBAPhQABsFATUgABEVEJ9f0EAAAKAK4AAQD5Bg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1b82b05116c9.js b/pr/255/docs/search.index/1b82b05116c9.js deleted file mode 100644 index e48f7b2fa..000000000 --- a/pr/255/docs/search.index/1b82b05116c9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoLAAABK9YvVREgAA0QABAEYAAQABgAKgIAAADwmgMAAAEslhcvMAAXQBpgcAAAEEAaBAAAATTWXybBMAAAEAAQUAOzAAAAEAAAsABQCLDwUA1hEBAPASAQBAEwAAXxMAAOMBhKAwAAAPB4UAAjswAAABAAALAAUA7AUCAO4GBAAPDAEAsxAAAOYRAABjgAOwAA8pAydkbnI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1b97b26c3ac1.js b/pr/255/docs/search.index/1b97b26c3ac1.js deleted file mode 100644 index d7219e3ac..000000000 --- a/pr/255/docs/search.index/1b97b26c3ac1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHARogABsCATkgABaW8BAAGw8BOSAAFr9AgTAAAFAAEAJgDzBQFk8t4RAAABAAECAPMCEAAAAQABAPMAAWk6MAAAAQAAAAAABwAQAAAA4A/0Ec0SzhL9Ev4SGRMaEyODArCwE3EAAWFzAYECoKAAABJAoEAAAA+lb3bzgIQBUAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1bf5442726c7.js b/pr/255/docs/search.index/1bf5442726c7.js new file mode 100644 index 000000000..fc035aa46 --- /dev/null +++ b/pr/255/docs/search.index/1bf5442726c7.js @@ -0,0 +1 @@ +rn_("AQQA83IPAAABAAEAAYACoFAAABB4oGAAABDoaXIBgAKgIAAADIGgYAAAEOdlaAEBAaAgAAAQ5mLzfQwAAAEAAQATgQKgEAAADIBhYwEGAPSUEgAAAQB6AQEAEwACsGASlgABZm3y5QwAAAEAI4ACoMAAABNWbnInDwAAiKBAAAAPb7BAD3AAAaAwAAAMfDQgFzswAAABAAAZAAMA3QEAABsEDgALDAkAAYADsHATDwABsDASvgABsIATQwABY3JzAQABsCATDwABbzowAAABAAAAAAAJABAAAAB8EX0RfxKAElwTXROtE64THRQeFAGAArAgCXQAAbAwEskAAXJ09wAAAMegIAAAB9WgYAAAD5uwgBLJAAFABpII9uoBAABVAnoFAQC2CQEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/1c84f4d721b0.js b/pr/255/docs/search.index/1c84f4d721b0.js new file mode 100644 index 000000000..c83e01cc7 --- /dev/null +++ b/pr/255/docs/search.index/1c84f4d721b0.js @@ -0,0 +1 @@ +rn_("AQIBsEATLgABZfIrBwAAAQABBADzGxAAAAEAAQBDAAOwQBKcAAGxABNyAAFlZnA7MAAAAQAAIwAGAOwBAAA6BwwASAcMAFgPBQCyEAAA2BIBAGOAA7AwDCsAAWFlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1ce4c2454b0a.js b/pr/255/docs/search.index/1ce4c2454b0a.js deleted file mode 100644 index a333bda2d..000000000 --- a/pr/255/docs/search.index/1ce4c2454b0a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9CASAAABAIkAAQABAwD0VBIAAAEAjgABAPMFAmJ1OjAAAAEAAAAAAAcAEAAAALIPsw9kEGUQEhETESsSLBIBAgD0nBAAAAEAWgEBAAEFAPOiEAAAAQABAAEEAPTREQAAAQCaAAEA84CEEQkA") \ No newline at end of file diff --git a/pr/255/docs/search.index/1cf369215e3f.js b/pr/255/docs/search.index/1cf369215e3f.js new file mode 100644 index 000000000..2e5273b3b --- /dev/null +++ b/pr/255/docs/search.index/1cf369215e3f.js @@ -0,0 +1 @@ +rn_("AYkCsCAT2gABoDAAABPjaXATAAOgIAAAEqqggAAAEr1laXX1KgwAADIAAQABAAEAAYYCsJAT/gABoAAAABJEYmQBgAKwMBKeAAGgMAAAEJpydtcAAACFoDAAABAYoDAAABLyEAETOjAAAAEAAAAAAAkAEAAAAE4JTwlQCYAJgQkvEDQQ6xDsEIES") \ No newline at end of file diff --git a/pr/255/docs/search.index/1e602721a639.js b/pr/255/docs/search.index/1e602721a639.js new file mode 100644 index 000000000..9bf417261 --- /dev/null +++ b/pr/255/docs/search.index/1e602721a639.js @@ -0,0 +1 @@ +rn_("AQMA9gQNAACWAlkAAQCmAgEAAQQAOzAAAAEAAAoABAA1EAUAWhIBALASAQDCEwAAAYYCoAAAABLSoAAAABLTZHLzAgF2AfgSAADzgAJlbycBAADHoDAAAA+ZoHAAABItoIAAABOVoNAAABM7oLAAABOVQEUICTswAAABAAAJAAMANQYCAIQHBABrDAEAI4ACaXe0yZZoZHIBAAA6MAAAAQAAAAAACgAQAAAAnwmgCc4P6hLrEhYTFxO2EwkUHxQgFBOAAqAwAAAQS2x0w4AEoAAAABA7oAAAABA8NDZhZQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1ea1f2d3747a.js b/pr/255/docs/search.index/1ea1f2d3747a.js deleted file mode 100644 index 215722f56..000000000 --- a/pr/255/docs/search.index/1ea1f2d3747a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9OsSAAABAH8ABQATAAOwkBNLAAGwUBI6AU9nbHA7MAAAAQAAEgAJAJsPAgAPEQEAKRIBAEoSAQB7EgEA3BIBAA8TAQAeEwEAXRMBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1f0367152a3f.js b/pr/255/docs/search.index/1f0367152a3f.js new file mode 100644 index 000000000..4c2a42d7b --- /dev/null +++ b/pr/255/docs/search.index/1f0367152a3f.js @@ -0,0 +1 @@ +rn_("AYECoCAAABCcsFASRQABYW8BAwGgAAAAE1ZzAZsQAAAjgAKgAAAACFZydmMAA7BQEQ4AAWNlczswAAABAAAIAAQAVQkCAIMJAQAbEAIALRIAAAcBAICFsFAQzQABoKAAABMisPATOQABsCAPYAABRCEE") \ No newline at end of file diff --git a/pr/255/docs/search.index/1f11eee293c6.js b/pr/255/docs/search.index/1f11eee293c6.js new file mode 100644 index 000000000..cf4b780f5 --- /dev/null +++ b/pr/255/docs/search.index/1f11eee293c6.js @@ -0,0 +1 @@ +rn_("AYECoCAAABP9sEAPqwABYnABBQD0xRIAAAEAjgABAPMDAWMBOxIAAAEMAPQCFAAAAQABAAEA84ACbnYBgAKwMAxoAAGgMAAADGppbwECAaAAAAATy3MBlBEAACOAAqBAAAATfGFl5wEAgIWwAAXrAAGQSAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/1f1d2b61eca6.js b/pr/255/docs/search.index/1f1d2b61eca6.js new file mode 100644 index 000000000..d38c8f3de --- /dev/null +++ b/pr/255/docs/search.index/1f1d2b61eca6.js @@ -0,0 +1 @@ +rn_("AYYCoAAAABLSoAAAABLTZHIBgAKgcAAAE1ugMAAAELpmdAELAaBAAAATp2Xy0RMAAAEAI4ECsFAQkQABY3YBAAGwgBOpAAFw8qUTAAABAEMGA6AgAAARA6BAAAASQGRlc/OnDwAAHAMBAPMABGlyc3Y7MAAAAQAADwAFAF0HBQBiEgUAjRIBAPgSAADcEwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/1f6d06e60df8.js b/pr/255/docs/search.index/1f6d06e60df8.js new file mode 100644 index 000000000..ac1a22a0c --- /dev/null +++ b/pr/255/docs/search.index/1f6d06e60df8.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgBbEQMASRICAAEKAbBAE88AAWX1lxMAAAEAAQABAAEA8wACaXP0OQwAAAEASwABACOBAqDgAAATtmV5") \ No newline at end of file diff --git a/pr/255/docs/search.index/1f850a139dfa.js b/pr/255/docs/search.index/1f850a139dfa.js new file mode 100644 index 000000000..50cc94896 --- /dev/null +++ b/pr/255/docs/search.index/1f850a139dfa.js @@ -0,0 +1 @@ +rn_("AQYAOzAAAAEAAAUAAQDaEgUAg4YEsFASpAABsHATBAABoNAAABPXYm5vdhOAArAQEn0AAXByAQABoDAAABGNdAEjEwAA8wIBc/JOEAAA2QITgAKgYAAAED9ldQECAPYNDQAAAQDpAgEAJAEBAAGAArAAEmkAAYAOdDFAAWVzAQEA87kHAABACwEAY4ADsIATdAABYm5084ADYW9yARQA9AIUAAABAAEAAQABAAA7MAAAAQAABgACAAITAABnEwUAI4gCsEAT1QABZXMBBAGwMBLYAAFj8ykRAAABAAEAAQUAOzAAAAEAAAgAAwCYEQIAhhIEAJYTAADzAgNjZXDz0gwAAAEAAQBjgAOgYAAAD6Jlb3UBAAGwYBN/AAFlAbQTAADzAgFz9nYJAAABAAEAcAc/AAoBAQgA80kSAAABAAEAQ4ADoBAAABMGoOAAABOKZG9zAQIBoFAAABEocgHIEAAAAYACoEAAABBLoHAAABPCYWUBAAA7MAAAAQAACwACAF0HBQBiEgUA84ACdHYBAQD0UAgAAAEAAQABAPMAAm5y9mwJAABQAG8GAQCxAAEA8wCHMJEM9XsSAAABAHkAAQDsAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/1fb072ef9a66.js b/pr/255/docs/search.index/1fb072ef9a66.js new file mode 100644 index 000000000..b247e00d2 --- /dev/null +++ b/pr/255/docs/search.index/1fb072ef9a66.js @@ -0,0 +1 @@ +rn_("AQEAOzAAAAEAAAYAAQAjFAYA8wYBZfTYEwAAAQAuAAEAEwMDsEAUAAABoGAAABOBYXJ1ASUQAAAjgAKAER4AEAFkcg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2025f39bb570.js b/pr/255/docs/search.index/2025f39bb570.js new file mode 100644 index 000000000..3070be59c --- /dev/null +++ b/pr/255/docs/search.index/2025f39bb570.js @@ -0,0 +1 @@ +rn_("AYICsCAQ6QABsDARYQABZXABBQD0lQ8AAAEA4wABAFOAA7CQEZIAAWFpcgGBArCgE4sAAbCgE40AAWNyxwAAAIWwUAz5AAGgIAAACbugIAAADDQ8AAE6MAAAAQAAAAAACgAQAAAAiwGMASoEYwdyCXMJJxAoEJMQlBCjEQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2098306f4d34.js b/pr/255/docs/search.index/2098306f4d34.js deleted file mode 100644 index cdc87eb43..000000000 --- a/pr/255/docs/search.index/2098306f4d34.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOjAAAAEAAAAAAAoAEAAAABwPHQ/+D/8PixAWERcREhITEo4TjxPzAQF58vsSAAABACMAA6BAAAAQqaBQAAATRmVvc/IADwAAqgI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/20b4057caa1a.js b/pr/255/docs/search.index/20b4057caa1a.js new file mode 100644 index 000000000..487635417 --- /dev/null +++ b/pr/255/docs/search.index/20b4057caa1a.js @@ -0,0 +1 @@ +rn_("AQIA9FURAAABAAEAAQABAQDzaxEAAAEAAQATgAJBeeMvrhxlcwEKAPM2EwAAAQABAAGAArAgE6sAAaBgAAATA292AYACoDAAABJOoAAAABLCY2TzgIUFEAY=") \ No newline at end of file diff --git a/pr/255/docs/search.index/21a899f4f99b.js b/pr/255/docs/search.index/21a899f4f99b.js deleted file mode 100644 index b4a853591..000000000 --- a/pr/255/docs/search.index/21a899f4f99b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAUAAQB1EwUA8w0BbTswAAABAAAFAAEANhMFACMDhLBAEcoAAaEAAAATe6AAAAAS/zAIAjswAAABAAAUAAUAWhAHAOsRAQBeEgQALhMEAJgTAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/21bd1e52c0f9.js b/pr/255/docs/search.index/21bd1e52c0f9.js new file mode 100644 index 000000000..fac8935a2 --- /dev/null +++ b/pr/255/docs/search.index/21bd1e52c0f9.js @@ -0,0 +1 @@ +rn_("AQEA9MkHAADHB9cAAQABBQD0thIAAAEAigABAPMCAWP1AhAAAAEAvAABAAEAYwAEoDAAAAxIoHAAABF/ZW5zdvMgEAAAlQD+AQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/21f7fe292e8a.js b/pr/255/docs/search.index/21f7fe292e8a.js new file mode 100644 index 000000000..963ec6d10 --- /dev/null +++ b/pr/255/docs/search.index/21f7fe292e8a.js @@ -0,0 +1 @@ +rn_("AQUA9FMSAAABAJoAAQABCAD0/xIAAAEAgwABADMBA7BAEtQAAWFiZTowAAABAAAAAAAJABAAAACWB5cH9wz4DHoP5g8wEDEQLhLxEgEAADswAAABAAAeAA4ATAUBAP8FCAB5CQEAQAwBAOkMAQB0DgAAbA8CAIIPAACgDwEAiRABAJwQAAAxEQAAiBEBAI0RAAABgQKwABEhAAGwABEjAAE0NiOAArCAE/IAAW9wAQABsEAS0AABZfMsEQAAPQEBALcBAICFoGAAABDIEAEL") \ No newline at end of file diff --git a/pr/255/docs/search.index/225a0e027688.js b/pr/255/docs/search.index/225a0e027688.js new file mode 100644 index 000000000..a9dd0c6e5 --- /dev/null +++ b/pr/255/docs/search.index/225a0e027688.js @@ -0,0 +1 @@ +rn_("AQACoDAAABC+oJAAABMHMGj1nhEAAHMBAQABAAEAE4ACoDAAAA9/ZHIjAISwEAlKAv+wIAwcAPagMAAAD6MSABj1EQYAAC8AAQABAAEAAQIA9BYUAAABAAoAAQABAgDzGxAAAAEAAQDzgAJpcgEBArBAEQQAAaBQAAAS8WVz9SYMAABJAqsCAQBgAgELAPYWEwAAAQCfAFMAFgABAPOAAmx004CEoJAAABLLAUQE") \ No newline at end of file diff --git a/pr/255/docs/search.index/24eee7d39d3b.js b/pr/255/docs/search.index/24eee7d39d3b.js new file mode 100644 index 000000000..f7a5b128e --- /dev/null +++ b/pr/255/docs/search.index/24eee7d39d3b.js @@ -0,0 +1 @@ +rn_("AQQBsAASpgABczswAAABAAALAAIAGhMHAAIUAwBHAAAFhqCAAAAS+7EAFA8AAbBAEmkAAbCAFB0AAbBQEqgAARUAFvRwDgAAAQABAAEAQwCEoCAAAAl+oNAAABMGoDAAAAldFQAE89UBAAABAP8F") \ No newline at end of file diff --git a/pr/255/docs/search.index/252df03c9a7b.js b/pr/255/docs/search.index/252df03c9a7b.js new file mode 100644 index 000000000..75508c4b3 --- /dev/null +++ b/pr/255/docs/search.index/252df03c9a7b.js @@ -0,0 +1 @@ +rn_("AQAA9IwJAAABAFwHAQABCQGggAAAFBlmAQ4TAAABAgD1fRAAAAEAAQA5AgEA8wACaXU6MAAAAQAAAAAABwAQAAAAWxB2Ek8TUBN/E4ATnBOdEwEIAPWvEwAAAQABAAEAAQDzAgFm9UAQAAABAAEAAQABABOAArCgE/IAAXJ08wACYXPzbRAAAAEAAQDzgAJ0dg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/254b4b1e845b.js b/pr/255/docs/search.index/254b4b1e845b.js new file mode 100644 index 000000000..07da323bd --- /dev/null +++ b/pr/255/docs/search.index/254b4b1e845b.js @@ -0,0 +1 @@ +rn_("AQABsIATqQABcPKlEwAAAQBDBQOgIAAAEQOgQAAAEkBkZXPzpw8AABwDAQABAgA7MAAAAQAAEwABANEPEwATgYSgUAAAELKgEAAADDugIAAADPQcQAAzgAOwUBL5AAFhZm4=") \ No newline at end of file diff --git a/pr/255/docs/search.index/25a54c1ab6e0.js b/pr/255/docs/search.index/25a54c1ab6e0.js deleted file mode 100644 index d4ad746ab..000000000 --- a/pr/255/docs/search.index/25a54c1ab6e0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9KYPAAABAKkAAQABhAKwABClAAGwABCnAAE0NvMCAWHyKAwAAAEAAQEA9swRAABmAAEARwD0AAEA84ACZW/zgAJoaw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/25b74d0e760c.js b/pr/255/docs/search.index/25b74d0e760c.js new file mode 100644 index 000000000..35f1aad82 --- /dev/null +++ b/pr/255/docs/search.index/25b74d0e760c.js @@ -0,0 +1 @@ +rn_("AQcAOzAAAAEAAHwAAgCZEAAApBF7AAEDADswAAABAAB7AAEA8w17AAECADswAAABAAAHAAEAVAwHAPMAA2JpdDswAAABAAB8AAIAKQUAAGIFewA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/266311e2892f.js b/pr/255/docs/search.index/266311e2892f.js deleted file mode 100644 index e589e6467..000000000 --- a/pr/255/docs/search.index/266311e2892f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9BAJAAABALsJ3QAXAAAAyaBAAAAQPLBgE1IAAaAQAAAMOLBQEvIAAbAwEJ4AAaAAAAAL+rEgE3EAAbBAEDoB9wBOsAk6MAAAAQAAAAAAEQAQAAAAJQkmCToJOwnIC8kLygvSC9MLggyrEdMR1BHVEX0SfhIBEwIT") \ No newline at end of file diff --git a/pr/255/docs/search.index/266827f9a2f0.js b/pr/255/docs/search.index/266827f9a2f0.js deleted file mode 100644 index d9c5f8c7f..000000000 --- a/pr/255/docs/search.index/266827f9a2f0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOjAAAAEAAAAAAAoAEAAAABwPHQ/+D/8PixAWERcREhITEo4TjxMBBADzFw8AANUAAQDzAAFx960MAAABAM8CAQDBAGEAAQDzAAJleTowAAABAAAAAAAMABAAAAAMDA0Mtw+4D0kQShBLEOsS7BL7EvwSaxNwEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/266afabfc690.js b/pr/255/docs/search.index/266afabfc690.js new file mode 100644 index 000000000..95677b044 --- /dev/null +++ b/pr/255/docs/search.index/266afabfc690.js @@ -0,0 +1 @@ +rn_("AQkBoIAAABQZZgEOEwAAAQIA9X0QAAABAAEAOQIBAPMAAml1OjAAAAEAAAAAAAcAEAAAAFsQdhJPE1ATfxOAE5wTnRMBCAD1rxMAAAEAAQABAAEA8wIBZvVAEAAAAQABAAEAAQATgAKwoBPyAAFydPMCAmFz820QAAABAAEAAQQBsEATzwABZfWXEwAAAQABAAEAAQABAgA7MAAAAQAACwACAEUTBQD2EwUA8wMBbTswAAABAAANAAQA1wwAABARAABvEgUAtxMFAPOBAmNl84ACYWU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/2670b688dca6.js b/pr/255/docs/search.index/2670b688dca6.js new file mode 100644 index 000000000..a23cd92a2 --- /dev/null +++ b/pr/255/docs/search.index/2670b688dca6.js @@ -0,0 +1 @@ +rn_("AYACsAARIQABsAARIwABNDYBBAGgoAAAFCp38hoUAAABAAELAPOPEwAAAQABACOAAqCAAAATtWVvYwIDoGAAABNOZW5wATgMAADzAAJhdgFHBwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/267d2567696a.js b/pr/255/docs/search.index/267d2567696a.js deleted file mode 100644 index 22b695cd2..000000000 --- a/pr/255/docs/search.index/267d2567696a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsEATSwABsGASMgABZXIBBQD0yg8AAAEAAQABAPOAAmZtAQYAOjAAAAEAAAAAAAgAEAAAABUPFg+6EPUR9hHgEmATkBOREwEAAaFAAAATiWf0ogcAAAEAAQABAMMAhKCwAAASybBAD+EAARQgBPUfBwAAWAULAz8C/QBjgAOwMA9OAAFhZWk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/26e84f065723.js b/pr/255/docs/search.index/26e84f065723.js new file mode 100644 index 000000000..e8386cae1 --- /dev/null +++ b/pr/255/docs/search.index/26e84f065723.js @@ -0,0 +1 @@ +rn_("AYECoBAAABLCoHAAABMDYWMBhwKwABNXAAGwABNZAAE0NlMAhKCQAAAS6bCwE30AAYEACfWJBwAAMwCDCA8BGQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/27198464c776.js b/pr/255/docs/search.index/27198464c776.js new file mode 100644 index 000000000..eee3c6b9c --- /dev/null +++ b/pr/255/docs/search.index/27198464c776.js @@ -0,0 +1 @@ +rn_("AQIA9VARAAABAAEAAQABAAGAArBgEpgAAaAgAAAQom95AQABoMAAABOoafTpEgAABwAXABsAAQYA9AsUAAABAAEAAQABAgD0oBAAAAEAnAABAAECAaBAAAASwXI7MAAAAQAABwACAJ4QAQA3EQUA84ACYW9nAwAAhrCAEsAAVbCgEzAAAQwwBjswAAABAAAIAAMAMQwAAGMRAwA3EgMA84ICZWkjAAKggAAAFBlmaPJNCQAAwQkBAAKwEAwaAAGwMBO/AAFlcPSTDwAAAQDiAAEAAQADsEATjQABoUAAABPxoFAAABGKYmNmAXEHAADzgAJtbgEBA6CwAAATS7BAEFwAAaBgAAARNmNldPRYBwAApAhHAv0AAQUAOzAAAAEAAAUAAQBiEgUAAQcA9eASAAABAAEAAQABACOAAqBQAAARBmFv8wCFIEkCOzAAAAEAAAgABACvBwAA4QcFAAcNAAA/EQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/271cda0a044e.js b/pr/255/docs/search.index/271cda0a044e.js new file mode 100644 index 000000000..d2a6641da --- /dev/null +++ b/pr/255/docs/search.index/271cda0a044e.js @@ -0,0 +1 @@ +rn_("AQYA9DIRAAABAAEAAQABAgA7MAAAAQAADAAFACMMAQA1EAUAWhIBALASAQDCEwAA84ACZm4BAQA7MAAAAQAABwACAFgPBQDYEgEA84ACZG4BAQDzkwcAAAEAAQABhgKgAAAAEtKgAAAAEtNkcvMBAXYB+BIAAEMAA7CAEm0AAbCwE+8AAWtscjswAAABAAAMAAMAigcIAAkNAQD1DwEAAQIA9VgIAAABAAEAAQABAPMAhBRBAAFtAAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/27677e8fce37.js b/pr/255/docs/search.index/27677e8fce37.js new file mode 100644 index 000000000..b754ef56e --- /dev/null +++ b/pr/255/docs/search.index/27677e8fce37.js @@ -0,0 +1 @@ +rn_("AQABsIASyQABdvS5CQAAAQC2CQEAE4ACsDAQrwABbG4BgAKgAAAAEDugAAAAEDw0NvMDAXYBBQ0AABMAAqBAAAARLGFz90cMAABfA1wBMgEBAAEAkQEBAgD0ohIAAAEAiQABAAEDAPTWEgAAAQCOAAEA8wACYnU6MAAAAQAAAAAAEwAQAAAArAetB64Hiw+MDy0QLhBMEE0Q3xDgEI4RjxGgEqESrRKuEr0SKhMrE/OAAmR0E4ACoCAAAA0PZXIBBwGgQAAAE6dl8tETAAABAAEHAPSmEAAAAQABAAEAAQAA9awJAAABAAEAAQABACOAAqCgAAAT/GZwAQMBoJAAABN8ZfJlDwAAAQDXAAAAhaBQAAAQI7FAFCMAAYEpAPLtBQAAAQDzgAJsdJcBAICFsTATqQABsRAT0wABEUUA") \ No newline at end of file diff --git a/pr/255/docs/search.index/278470046fa3.js b/pr/255/docs/search.index/278470046fa3.js new file mode 100644 index 000000000..1d6d8b5c0 --- /dev/null +++ b/pr/255/docs/search.index/278470046fa3.js @@ -0,0 +1 @@ +rn_("AQAA9FIJAAABAPsJ3AAXAAAAyaBAAAAQt7BgE9MAAaAQAAAMkrBQE3QAAbAwERoAAaAAAAAMU7EgE/IAAbBAELUB/gBOsAk6MAAAAQAAAAAAEQAQAAAAZwloCXwJfQkgDCEMIgwrDCwM4AwsElUSVhJXEv8SABODE4QT") \ No newline at end of file diff --git a/pr/255/docs/search.index/27bc89bd5eae.js b/pr/255/docs/search.index/27bc89bd5eae.js new file mode 100644 index 000000000..2150f3df1 --- /dev/null +++ b/pr/255/docs/search.index/27bc89bd5eae.js @@ -0,0 +1 @@ +rn_("AQEA98QQAAABAAEApwIBAH4ABQABAQKgQAAAE9egMAAAEMplaPVUCQAALgDtAgEADgUBAgD0dREAAAEAAQABABOBArAgEXkAAWFz84ACbm8BAgD0VxAAAAEAAQABABMAAqDQAAAT3GNz8s8PAAABAPOAA2Vpbw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/27f8ec34bd1f.js b/pr/255/docs/search.index/27f8ec34bd1f.js deleted file mode 100644 index 49f2588be..000000000 --- a/pr/255/docs/search.index/27f8ec34bd1f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQATngABsNATkAABa20BBAGgoAAAE6l38pkTAAABAAGAAqCAAAATNLCwEw0AAWVvYwQDoGAAABLMZW5wAd8LAAABCgDz8BIAAAEAbgATgAKiEAAAE6lsb3cAAACFoGAAABGfoQAAABNhBIEDOzAAAAEAADsABAABBgUAeAcAAMcHMwCsEAAAQ4ADsIAQqwEFoAAAAAHcZGt0") \ No newline at end of file diff --git a/pr/255/docs/search.index/281cb83843d4.js b/pr/255/docs/search.index/281cb83843d4.js deleted file mode 100644 index 1f251ac5d..000000000 --- a/pr/255/docs/search.index/281cb83843d4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9VYJAAABAAEAAQABAPMAAWnzkgwAAAAHAQABBAKgIAAAEP+gMAAAEbJiaAEEDwAApwAAgMWgEAAADJOwEBN/AAGgMAAAD6sEECgB") \ No newline at end of file diff --git a/pr/255/docs/search.index/28827f9488f7.js b/pr/255/docs/search.index/28827f9488f7.js deleted file mode 100644 index 218e8e9ed..000000000 --- a/pr/255/docs/search.index/28827f9488f7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkBoEAAABNNZfJsEwAAAQABgAKwAAyOAAGggAAAErpkcAEDAaAAAAAPbXPy/g4AAAEAAQIDsGASQQABsNATUAABoIAAABLZaXJzAVsTAAD3AACAhaEwAAATa5BJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/28d0ee3283f9.js b/pr/255/docs/search.index/28d0ee3283f9.js new file mode 100644 index 000000000..6ab5c018c --- /dev/null +++ b/pr/255/docs/search.index/28d0ee3283f9.js @@ -0,0 +1 @@ +rn_("AQADoKAAABPCoCAAABMGsDARiAABZWl08nsSAAABAAEDADswAAABAAAGAAEABxEGAAEIAPRtEwAAAQB+AAUAEwEDsJATzAABsFASvAFOZ2xwOzAAAAEAABIACQAVEAIAixEBAKsSAQDMEgEA/RIBAF4TAQCSEwEAoRMBAN4TAQABgAKwMBGEAAGwMBGGAAFydgECAbAAEkEAAWQ7MAAAAQAABQACAIARAwBrEgEAI4ECoJAAABPBaW8BBwD03RMAAAsAHgAPAHcLAAGIsFASQwD9sGASugABlQkDOjAAAAEAAAAAAA0AEAAAAOIM4wzkDHUOdg5yEHMQrhDREDIRMxE0ETURshIjgAKgEAAADOFubw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/29912ff817d4.js b/pr/255/docs/search.index/29912ff817d4.js new file mode 100644 index 000000000..8cede019b --- /dev/null +++ b/pr/255/docs/search.index/29912ff817d4.js @@ -0,0 +1 @@ +rn_("AQQBoFAAABPHcwErEgAAAYICsEASTwABsEASUQABNDYBBgD0FhQAAAEACgABAPMCAXIBghMAAPMDAWX0KRAAAAEAqAABAFOEA7CwE58AAWFlaWOAA6BQAAAT/WNldA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/29ffaf5f711f.js b/pr/255/docs/search.index/29ffaf5f711f.js new file mode 100644 index 000000000..cf078824c --- /dev/null +++ b/pr/255/docs/search.index/29ffaf5f711f.js @@ -0,0 +1 @@ +rn_("AYQCoCAAABDJoDAAABExaXQBAQA7MAAAAQAAfAACANQHAADBCXsA8wACZWz1PwUAAJkCDwkoAgEAAQIAOzAAAAEAAN4AAgAlDAAAFQ3dAMcAAACFsLASvgABoBAAABM7sDANEwABFDACOzAAAAEAAAoBCwC1AQYAFwYAAEQG3QCiBwcA8A8CAEARDQBoEQIALxIBAKgSAQDzEgEAhRMCAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2a2e9d6f638a.js b/pr/255/docs/search.index/2a2e9d6f638a.js new file mode 100644 index 000000000..5dcc70e30 --- /dev/null +++ b/pr/255/docs/search.index/2a2e9d6f638a.js @@ -0,0 +1 @@ +rn_("AYACoAAAABA7oAAAABA8NDYBgAOwABNXAAGwABNZAAGwcBPIAAE0NmEBBAD0FhQAAAEACgABACOBAqBAAAARAW1wAQEAOzAAAAEAAAgAAwBeEgAAxxIAACMUBgCHAwACxqBAAAAQBKBgAAATfKCAAAASO0AHgAg7MAAAAQAAFgAIAKQPAQC4EAEA/RADAG4RBgA2EwIAghMAANgTAQAHFAEA8wACZXY6MAAAAQAAAAAAEQAQAAAA6AHpASUGBQ1lD2YPgA+ZDykQKhDSENMQTxJQElESUhKfE6ATAYECsHAQ/QABsHAQ/wABNDYjgAKwEAfDAAFucAEDArBAEp4AAaAwAAAS8mV39C8QAAAFALcAAQATgQKgcAAAEydnbyOAArBQD6QAAWR0VwEAAIWgEAAAEASxIBPYAAERIQH0dREAAAEAAQABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2adb3d0bf2d8.js b/pr/255/docs/search.index/2adb3d0bf2d8.js deleted file mode 100644 index d282d849b..000000000 --- a/pr/255/docs/search.index/2adb3d0bf2d8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoDAAAAx3aQFwEgAAAQABsDAQcgABbvKBBwAAAQABAQDz+wcAAO8GAQATAAKgUAAAD9Nlc/XsAwAAAQABAAEAAQABhAKwoBMJAAGwoBMLAAFjcvMBAXTyDhEAAM8AAQMBsGATUgABZjswAAABAAAGAAMAyAsCAH0SAQABEwEA84ACYWXzgIQAKAU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/2b09faf5f111.js b/pr/255/docs/search.index/2b09faf5f111.js new file mode 100644 index 000000000..934598a00 --- /dev/null +++ b/pr/255/docs/search.index/2b09faf5f111.js @@ -0,0 +1 @@ +rn_("AQACoCAAABMGsDARiAABaXTyexIAAAEAAQMAOzAAAAEAAAYAAQAHEQYAAQgA9G0TAAABAH4ABQATAQOwkBPMAAGwUBK8AU5nbHA7MAAAAQAAEgAJABUQAgCLEQEAqxIBAMwSAQD9EgEAXhMBAJITAQChEwEA3hMBAAGAArAwEYQAAbAwEYYAAXJ2AQQBsAASQQABZDswAAABAAAFAAIAgBEDAGsSAQC3BQABh7BQEkMA/bBgEroAAZQJAzswAAABAAAKAAUA4gwCAHUOAQCuEAAAMhEDALISAAAjgAKgEAAADOFubwEDAPMSEAAAAQABACOAAqAAAAAMKGRyYwGEoFAAABEvoDAAABBKFAEQ8vsHAAABABOAArBgEmAAAWNnE4ADoLAAABOKoEAAAA50ZW9z") \ No newline at end of file diff --git a/pr/255/docs/search.index/2b35726b25dd.js b/pr/255/docs/search.index/2b35726b25dd.js new file mode 100644 index 000000000..2ba6b0a8f --- /dev/null +++ b/pr/255/docs/search.index/2b35726b25dd.js @@ -0,0 +1 @@ +rn_("AQIA9KwQAAABAHsBAQABAAD0oA8AAAEA6AAEASOCArBQEtAAAWVzAQIA9KISAAABAIkAAQABAwD01hIAAAEAjgABAPOFAmJ1AQIA9BgRAAABAGABAQDzgAJpbPMAA2J0dTowAAABAAAAAAAPABAAAADTB18IYAhhCGIIxw+AECMTnhPmE+cT6RP0E/UTGBQcFAEMAPOFEwAAAQABAAGAArAACW0AAaAgAAANBmRuAQYA9KASAAABAIkAAQDzAwFi9KoQAAABAHsBAQCXBgAAh7BAD54AAaBwAAASMrCQEs4AATgJAzswAAABAAAiABEAOAYDAJgHAQD7DAIAAQ0CAJcPAQDpDwEA7g8BAAsQBgBOEAAAexABAAMTAAAnEwAASxMAAN0TAADoEwAABhQAABUUAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/2b92810a6565.js b/pr/255/docs/search.index/2b92810a6565.js deleted file mode 100644 index 017e62f2a..000000000 --- a/pr/255/docs/search.index/2b92810a6565.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCoCAAABBOoDAAABC1aXQBAQA7MAAAAQAAdwACAJsHAAB/CXYAYwADsAAB3gABZGVs9s4FAAABAAEAnAohAgEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/2bed9cec1d26.js b/pr/255/docs/search.index/2bed9cec1d26.js deleted file mode 100644 index 797037952..000000000 --- a/pr/255/docs/search.index/2bed9cec1d26.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA82UTAAABADUAAQ0BoKAAABOpd/KZEwAAAQABgQKwgBNzAAGgYAAAE5dkczcBAIWFoEAAABNJsGATGwBNApAK") \ No newline at end of file diff --git a/pr/255/docs/search.index/2ce4b4057c53.js b/pr/255/docs/search.index/2ce4b4057c53.js new file mode 100644 index 000000000..f017607b1 --- /dev/null +++ b/pr/255/docs/search.index/2ce4b4057c53.js @@ -0,0 +1 @@ +rn_("AQ8A9JITAAABAEsAAQABBAD0KxAAAAEAsQABAAECADowAAABAAAAAAAJABAAAAB8EX0RfxKAElwTXROtE64THRQeFPMAAW/yvwkAAAEAU4ADsQAT7wABaG9w84ACc3Q=") \ No newline at end of file diff --git a/pr/255/docs/search.index/2d2960f9b8d4.js b/pr/255/docs/search.index/2d2960f9b8d4.js new file mode 100644 index 000000000..8b491b5d4 --- /dev/null +++ b/pr/255/docs/search.index/2d2960f9b8d4.js @@ -0,0 +1 @@ +rn_("AYACoGAAABN7oKAAABNvYWkBCwD0ERMAAAEAAQABAAEEAPRPEAAAAQABAAEAAQQA9KYQAAABAAEAAQDzgAJscvMAA2NkcwGdEAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/2e7d78ea0cfe.js b/pr/255/docs/search.index/2e7d78ea0cfe.js deleted file mode 100644 index 37920f8f7..000000000 --- a/pr/255/docs/search.index/2e7d78ea0cfe.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsPATkgABa/QIEwAABQABACYAEwACsQATfwABZG7y3hEAAAEAE4ACsBAMDAABZW8BBQA7MAAAAQAADQABAMQQDQABAgDzOw8AAAEAAQABAgD0Nw8AAAEAAQABAAEDADswAAABAAAIAAEA4w8IAAGAAqBAAAAQN7DAE0QAAWVzAQEAOzAAAAEAABMAAQBXDxMAI4ACsJAStwABaW03NgAAiqAQAAAL4qBQAAATEbBwEvYAAaAgAAAMlZxVEfV/BwAAkQgBAAEAAQDzgAJsdA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2e882e6bf78f.js b/pr/255/docs/search.index/2e882e6bf78f.js deleted file mode 100644 index 07118cb77..000000000 --- a/pr/255/docs/search.index/2e882e6bf78f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQoA9JYSAAABAA8AAQABgwKgIAAAD3+gMAAAEA9pdAEEAbAAEhAAAWT0uhEAAAEAAQABACOGhLCgEz4AAbBAEg4AAbBwEu4AARWAAAEAArAwD3EAAbAQEq4AAXN08t4FAAD3BQEMAPQiEwAAAQBGAAEAE4ACoAAAAAd5dHnzgIURwQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/2eb9123a10fd.js b/pr/255/docs/search.index/2eb9123a10fd.js new file mode 100644 index 000000000..95d506d1e --- /dev/null +++ b/pr/255/docs/search.index/2eb9123a10fd.js @@ -0,0 +1 @@ +rn_("AYACoJAAABL8oBAAAAYiaW8BCQDz5hMAAAEANQABDAGgoAAAFCp38hoUAAABAAEBAPOoDwAAAQABAPOAAnR1AYECsIAT9AABoGAAABQYZHM3AgCDhqBAAAATyrBgE54AS7AwE4sAAQKQDgESAPQCFAAAAQABAAEAAQDGoFAAABJooAAAABA/sCAQ7wABoFAAABGUoQAAABP9oEAAABOoAAMCCzswAAABAAAVAAcAIwYAAEUMAADrDAAAtw8NABMRAAB9EgEAoxMBAAEBAbCwE+8AAWw7MAAAAQAADAADAIoHCAAJDQEA9Q8BAAEBAaAwAAAQymjzVAkAAC4A/AcBAgD0dREAAAEAAQABABOBArAgEXkAAWFz84ICbm/3AwCAh6BAAAAMLhUBBw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2f0bd76574d0.js b/pr/255/docs/search.index/2f0bd76574d0.js deleted file mode 100644 index 8aaaf3670..000000000 --- a/pr/255/docs/search.index/2f0bd76574d0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABKEsDARDAABaXTy+REAAAEAAQMAOzAAAAEAAAYAAQCMEAYAAQgA9OsSAAABAH8ABQATAQOwkBNLAAGwUBI6AU9nbHA7MAAAAQAAEgAJAJsPAgAPEQEAKRIBAEoSAQB7EgEA3BIBAA8TAQAeEwEAXRMBAAGAArAwEQgAAbAwEQoAAXJ2AQQBsAARvwABZDswAAABAAAFAAIABBEDAOkRAQC3BQABh7BQEcEA/bBgEjgAAZQJAzswAAABAAAKAAUAhAwCAAgOAQAzEAAAthADADASAAAjgAKgEAAADINubwEDAPOYDwAAAQABACOAAqAAAAALz2RyYwGEoFAAABCzoDAAAA/PFAEQ8sEHAAABABOAArBgEd4AAWNnE4ADoLAAABMIoEAAAA4HZW9z") \ No newline at end of file diff --git a/pr/255/docs/search.index/2f2a8a6c3151.js b/pr/255/docs/search.index/2f2a8a6c3151.js deleted file mode 100644 index fee0361f6..000000000 --- a/pr/255/docs/search.index/2f2a8a6c3151.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9DEQAAABAHUBAQAjgQKgYAAAEjtiaQEAAPQnDwAAAQDmAAMBI4ICsFASTgABZXMBiQKwIBNZAAGgMAAAE2JpcAECAPQgEgAAAQCJAAEAAQMA9FQSAAABAI4AAQDzhQJidQECAPScEAAAAQBaAQEA84ACaWy3AQAAhaAgAAASKBIBDDowAAABAAAAAAAUABAAAACaByUIJggnCCgI0QsDDAQMBQwGDE0PBRChEhsTZRNmE2gTcxN0E5cTmxMBBQDzAxMAAAEAAQBDhgOwkBN9AAGgAAAAEcJiZHcBAwDzJQ8AAAEA+QABAgD21gsAAAEADgMBAJwDAQABAAA7MAAAAQAABgACAIASAADlEgUAI4ECsEATVAABZXNTgAOwAAlGAAFleHkBgAOgQAAAE3uwIBIcAAGwAAlEAAFlcngBgAKgQAAADJKwQA9OAAFnbJcGAADHsMASrAABoDAAABL5sEAMiwABAAagCzowAAABAAAAAAAIABAAAAC5BboFkQylDCEPeQ96DxgSGRIBBgD0HhIAAAEAiQABAPMDAWL0LxAAAAEAdQEBADcMAACJoHAAABGxsBAJKwABsJASTAABsGAPcQABoDAAABJwOIkTOjAAAAEAAAAAACwAEAAAAAoGCwYMBl8HYAcMCQ0JDgk+CT8J2wucDJ0MngyiDKMMpAweDx8Pbw9wD3QPdQ+RD5IPkw+UD5UPlg+XD7QPuQ/TDwAQARBwEHEQ/xGBEqUSyRJcE2cThROUEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/2fac3831697f.js b/pr/255/docs/search.index/2fac3831697f.js new file mode 100644 index 000000000..e597dde82 --- /dev/null +++ b/pr/255/docs/search.index/2fac3831697f.js @@ -0,0 +1 @@ +rn_("AYECsDAP6wABsBATMAABc3QBAwDzVRIAAAEAAQAjgAKwABFhAAFoaQEAADswAAABAAATAAEA5wcTACOAAqAwAAAM4GFl84ACcnTzAAJhbDswAAABAAAoAAMAhQATAIQBAADRDxMA") \ No newline at end of file diff --git a/pr/255/docs/search.index/2fd891c7dddc.js b/pr/255/docs/search.index/2fd891c7dddc.js new file mode 100644 index 000000000..026e8ab57 --- /dev/null +++ b/pr/255/docs/search.index/2fd891c7dddc.js @@ -0,0 +1 @@ +rn_("AQYA9LgQAAABALoAAQATgQOgAAAAEQGxIBQHAAFhZG4BFAD1JRQAAAEAAQABAAEAAQYBsIATyAABdjswAAABAAAHAAIAbhEEADYTAgBXAAABhqDAAAATAaCgAAATI6CQAAAS8bBQEDAAAQXgAvR7BwAAAQABAH8MAQYA81wSAAABAJoAAQABoGAAAA+bcgE/BAAA1wEAgMWgMAAADCcAAIoK") \ No newline at end of file diff --git a/pr/255/docs/search.index/30399b5c8304.js b/pr/255/docs/search.index/30399b5c8304.js deleted file mode 100644 index 70e4d7b8e..000000000 --- a/pr/255/docs/search.index/30399b5c8304.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgBoIAAABOYZgGMEgAAE4ACoOAAABNhYnABAwGwABMbAE1z9R4PAAABAOEAAQDIAgGAArBAEcMAAaAQAAAQP3ByAYEDoAAAABCwsAAPCQEYoBAAAA8BZXN184ADYW9yAQIA9QIQAAABAAEAMgIBAAEEADswAAABAAAJAAEAdhAJAAGBAqCQAAAS4rBQEa4AAWJ3o4CEsFAS/QABsJASLgABQCADVwMAAIagcAAAEtmgQAAAE0YwQQw6MAAAAQAAAAAAOwAQAAAAIwUkBdEF0gXTBdQF1QXWBdcF2AXZBaYHNwk4CT0J5wvoCwkMCgwLDIsMjAwHDvMO9A71DgkPJw8oD2sP4A/uD+8PBhAHEA4QDxAhEEcQSBC1EAMRDBENERER9BEkEiUSzRLOEtQS/RL+EhkTGhMzE5UTlhOgE6ET") \ No newline at end of file diff --git a/pr/255/docs/search.index/30a16458d826.js b/pr/255/docs/search.index/30a16458d826.js deleted file mode 100644 index f35bd4cb5..000000000 --- a/pr/255/docs/search.index/30a16458d826.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9pQSAAABAKAAUwAWAAEA8wEBaQFnCQAAAQAA9WoJAAABAAEAAQABAEcBAIDGe8YhXqUhoKAAABN7sGAS9gABoBAAAAlDAAogig==") \ No newline at end of file diff --git a/pr/255/docs/search.index/30d311112226.js b/pr/255/docs/search.index/30d311112226.js new file mode 100644 index 000000000..072a640e2 --- /dev/null +++ b/pr/255/docs/search.index/30d311112226.js @@ -0,0 +1 @@ +rn_("AQIAOjAAAAEAAAAAAA4AEAAAABANEQ23EJURlhGXEUASRxJIEkwSTRKcEp0S0BLREgEJAPMeEQAAAQABAAEKAPNVEgAAAQABAAEGAPXhEAAAAQABAAEAAQDzgAJkbnMAhLEgE6sAAQARA/KkEgAAAQABDQD2FhMAAAEAnwBTABYAAQABgAKwoBMuAAGgEAAADEhjdQEBAPQ9EwAAAQBKAAEA8wABZfK9CQAAAQD3AACAxbAwEFwAAQACqAg=") \ No newline at end of file diff --git a/pr/255/docs/search.index/30e9b37f1a9e.js b/pr/255/docs/search.index/30e9b37f1a9e.js deleted file mode 100644 index b4840eeba..000000000 --- a/pr/255/docs/search.index/30e9b37f1a9e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECsDAPcQABsBASrgABc3QBAwDz0xEAAAEAAQAjgAKwABDlAAFoaQEAADswAAABAAATAAEArQcTACOAAqAwAAAMgmFl84ACcnTzAAJhbDswAAABAAAoAAMAgQATAHYBAABXDxMA") \ No newline at end of file diff --git a/pr/255/docs/search.index/311e77def7dc.js b/pr/255/docs/search.index/311e77def7dc.js deleted file mode 100644 index 2dd6c2814..000000000 --- a/pr/255/docs/search.index/311e77def7dc.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQADoKAAABNBoCAAABKEsDARDAABZWl08vkRAAABAAEDADswAAABAAAGAAEAjBAGAAEIAPTrEgAAAQB/AAUAEwEDsJATSwABsFASOgFPZ2xwOzAAAAEAABIACQCbDwIADxEBACkSAQBKEgEAexIBANwSAQAPEwEAHhMBAF0TAQABgAKwMBEIAAGwMBEKAAFydgECAbAAEb8AAWQ7MAAAAQAABQACAAQRAwDpEQEAI4ECoJAAABNAaW8BBwD0XBMAAAsAHgAPAHcLAAGIsFARwQD9sGASOAABlQkDOjAAAAEAAAAAAA0AEAAAAIQMhQyGDAgOCQ73D/gPMxBWELYQtxC4ELkQMBIjgAKgEAAADINubw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/312e80bd916b.js b/pr/255/docs/search.index/312e80bd916b.js new file mode 100644 index 000000000..864e9da9b --- /dev/null +++ b/pr/255/docs/search.index/312e80bd916b.js @@ -0,0 +1 @@ +rn_("AYkCsCAT2gABoDAAABPjaXATAAOgIAAAEqqggAAAEr1laXX1KgwAADIAAQABAAEAAYYCsJAT/gABoAAAABJEYmQBgAKwMBKeAAGgMAAAEJpydtcAAAKFoDAAABAYoDAAABLyEAETOjAAAAEAAAAAAAkAEAAAAE4JTwlQCYAJgQkvEDQQ6xDsEIESAQMBsDASuAABc/NtEAAAAQABAAEAADswAAABAAAKAAMAFRECADITAwALFAMA0wCEsCAIYwABEBgB9YcMAAABAAEAAQABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3161d4c1c9e3.js b/pr/255/docs/search.index/3161d4c1c9e3.js deleted file mode 100644 index 13ab4fc0f..000000000 --- a/pr/255/docs/search.index/3161d4c1c9e3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQwA87QSAAABAAEAAQYA85kQAAABAAEAAYICsGASQQABsNATUAABaXITgAKwEAyOAAFlaZcBAIOHsTATbAABoFAAABAqsJASGAABsEAQKAABlBAH8wABYfRKCQAAAQAjBwEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/325f77b8029e.js b/pr/255/docs/search.index/325f77b8029e.js deleted file mode 100644 index a1ae4d35e..000000000 --- a/pr/255/docs/search.index/325f77b8029e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUBsEARygABZfLrEQAAAQABggKgkAAAEyCgkAAAEyEyMwEAAqAgAAARqaAgAAAJCWltOzAAAAEAAAwABgD+BAAAMgUFAHMJAADuDgEA+BIAAAsTAQDzAAFzAVkQAAABBQA7MAAAAQAABQABAIYSBQABAAD1LQwAAAEAAQABAAEA84ACZ2tzgISwsBLeAAERSAABBgGgQAAAERll86gMAACYAwEAAYACoJAAABLtsFAQgAABZ3oBgAOwUBMZAAGgEAAAC72gcAAAEnZnbnLHAQAAhaBgAAAS+aBQAAATShUBBDswAAABAAARAAQAxQEBAOMPCADfEAMAxxECAAGFArBwEwYAAbAwEmMAAWVzEwADsEAPDgABoGAAABC0YmVzOzAAAAEAABIABADyBQEA+AYKAIMPAQDUDwMAAQMA9J4PAAABAAQAAQABCwGgQAAAE01l8mwTAAABAPOAAmRy8wACZW87MAAAAQAABwACAMMHAwAECAMAAQIAOzAAAAEAAAgAAQC0CwgAAQAA9NgPAAABAAEAAQABAQA7MAAAAQAA1gACAA4GAAArCNUAYwADsBASIgABZWlzOjAAAAEAAAAAAAwAEAAAABsJUglTCVQJVQnWC9cL5Q7mDg0PJxCCEoMS44CEsCAHgQABEUAEAQGEsDALxgABoEAAAAx6oIAAABCHsEAMewABAAAdAdMBAAABBQD1zxIAAAEAAQBxAAEAE4ACoAAAAAcqYWcBAwD0ohEAAAEAUwEBAPOAAmlvAQEAOzAAAAEAANYAAgCeBwAA3grVAAEIAbBAE04AAWX1FBMAAAEAAQABAAEA84ECZ3QBAQGgcAAAER9pOzAAAAEAAOgAAgCdBwAA9gnnAAEFAPPyDwAAAQABAPOAAmFvE4ACoEAAAAvscnUBgAKgAAAAB4OgEAAACRpkeBMAArAgDKAAAWVy8k4PAAABABOAArCwE5IAAXJ4AQoA9I8SAAABAAEAAQATgAKwEBA7Ag5hZQEEAPTUDwAAAQABAAEAAQQAOjAAAAEAAAAAAAcAEAAAADQSNRJDEkQSvxLAEtIS0xIBBAD0KxAAAAEAAQABAAEDAPPaEQAAAQCaAPOAhAFIAce/AwCPoIAAABHcoGAAAAyRsEAMFAABsTATaQABP6kfOzAAAAEAAEwAIgBkAAAAaAAAAB4FAQAnBQAAywUBAGcHAQBxBwEAeQcAAH0HAQBMCQAAXwkHAHUJAQDFCwAA2QsBAOALAQDxCwcAFAwBACsMAQBxDAEAHA8BAIgPAQD+DwEAChABACIQAABEEAIAVBABAGYQBACLEAAA2RADABYRAQASEgEAFhIBAD8SAACOEwEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/32c27beceb5f.js b/pr/255/docs/search.index/32c27beceb5f.js deleted file mode 100644 index b8d235cf5..000000000 --- a/pr/255/docs/search.index/32c27beceb5f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUBsEARygABZfLrEQAAAQABAAA7MAAAAQAAEQAEAMUBAQDjDwgA3xADAMcRAgABCgGwQBNOAAFl9RQTAAABAAEAAQABAEcGAACHsCAQOwIOsMATkgABoCAAAAcqsDAHgQABGIkKOjAAAAEAAAAAAA4AEAAAAHEHcgd9B34HTAnZC9oL4AvhCysMLAxxDHIMFhIXEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/33aa643b366e.js b/pr/255/docs/search.index/33aa643b366e.js new file mode 100644 index 000000000..4c4203c98 --- /dev/null +++ b/pr/255/docs/search.index/33aa643b366e.js @@ -0,0 +1 @@ +rn_("AYACoCAAAA92oDAAABJ1ZXIBAAKgIAAAEwawMBGIAAFpdPJ7EgAAAQABAwA7MAAAAQAABgABAAcRBgABCAD0bRMAAAEAfgAFABMBA7CQE8wAAbBQErwBTmdscDswAAABAAASAAkAFRACAIsRAQCrEgEAzBIBAP0SAQBeEwEAkhMBAKETAQDeEwEAAYACsDARhAABsDARhgABcnYBBAGwABJBAAFkOzAAAAEAAAUAAgCAEQMAaxIBALcFAAGHsFASQwD9sGASugABlAkDOzAAAAEAAAoABQDiDAIAdQ4BAK4QAAAyEQMAshIAACOAAqAQAAAM4W5vAQMA8xIQAAABAAEAI4ACoAAAAAwoZHJjAYSgUAAAES+gMAAAEEoUARDy+wcAAAEAE4ADsGASYAABsAAPYAABY2dyVwAAAIWgsAAAE4qgQAAADnSgIAAAEU8QwAoBYg8AAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/33b38805b1c6.js b/pr/255/docs/search.index/33b38805b1c6.js new file mode 100644 index 000000000..8aa3be57b --- /dev/null +++ b/pr/255/docs/search.index/33b38805b1c6.js @@ -0,0 +1 @@ +rn_("AQEAOzAAAAEAAAYAAQAHEQYAAQAA93IJAAABALQGAQBrAAEADwEBggKgIAAAEMmgMAAAETFpdPOAA2FncwEBAaBAAAATp2Xy0RMAAAEAI4ACsFATYAABZnPzgAJpbw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3407cc8b99a3.js b/pr/255/docs/search.index/3407cc8b99a3.js deleted file mode 100644 index 20c8dcbd5..000000000 --- a/pr/255/docs/search.index/3407cc8b99a3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECoCAAABN8sEAPMgABYnABCQD0QxIAAAEAjgABAAEMAPSBEwAAAQABAAEA84ACbnYBgAKwMAwPAAGgMAAADBFpbwECAaAAAAATSnMBGBEAACOAAqBAAAAS+mFl5wEAgIWwAAW9AAGQSAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/34726ae306d9.js b/pr/255/docs/search.index/34726ae306d9.js deleted file mode 100644 index fe5e6a2ab..000000000 --- a/pr/255/docs/search.index/34726ae306d9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9qUMAAB8AlgAAQCeAgEAAQQAOzAAAAEAAAoABAC6DwUA2BEBAC4SAQBBEwAAAYYCoAAAABJQoAAAABJRZHLzAgF2AXYSAADzgAJlbycBAADHoDAAAA8goHAAABGsoIAAABMSoNAAABK5oLAAABMSQEUICTswAAABAAAJAAMABwYCAEsHBAASDAEAI4ACcpo+9Xx6ZHIBAAA6MAAAAQAAAAAACgAQAAAAXQleCVQPaBJpEpQSlRI1E4gTnhOfExOAAqAwAAAP0Gx0w4AEoAAAAA/AoAAAAA/BNDZhZQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/348567575911.js b/pr/255/docs/search.index/348567575911.js new file mode 100644 index 000000000..515a4ff55 --- /dev/null +++ b/pr/255/docs/search.index/348567575911.js @@ -0,0 +1 @@ +rn_("AQIA9KISAAABAIkAAQABAwD01hIAAAEAjgABAPMCAmJ1OjAAAAEAAAAAABMAEAAAAKwHrQeuB4sPjA8tEC4QTBBNEN8Q4BCOEY8RoBKhEq0SrhK9EioTKxM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/34bb2b1a0ab9.js b/pr/255/docs/search.index/34bb2b1a0ab9.js deleted file mode 100644 index d155cc168..000000000 --- a/pr/255/docs/search.index/34bb2b1a0ab9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDsEAIAcRIBAAMTAgABBwD2lBIAAAEAoABTABYAAQABBADz7xAAAAEAAQAjAAKgYAAAEf9hcvMWEAAAAQCrAQGAAqEQAAAThbCAE30AAWl1dwgAAIixUBOgAAGACScAFs6wcBLNAAGhMAAAE5QKQRvyZwkAAGkGAYECoFAAABA7oKAAABJJa3ABAwA7MAAAAQAA1gACAIkMAQAKDtQA84ACbHTzgAJhZQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/34e0c30a19a6.js b/pr/255/docs/search.index/34e0c30a19a6.js new file mode 100644 index 000000000..314f78484 --- /dev/null +++ b/pr/255/docs/search.index/34e0c30a19a6.js @@ -0,0 +1 @@ +rn_("AQIA9y8MAAABAC4DAQBDAWICAQABAwD0lw8AAAEA4wABAAGBAqAAAAARLKAQAAAPemV184ACYXIBgQKgkAAAE2SwUBIvAAFidxOAArCQErAAAW5y8wACZXT0aRAAAAEAFwABAAEBAPWHDAAAAQABAAEAAQATgAKwsBNgAAFhbyMAArBADP8AAWV0OzAAAAEAAAkABABHBQEA+QUBAG0MAQBVEQMAAQIAOzAAAAEAAAkAAgBGCAcAlhIBAAGAArCQEvMAAaCgAAATY2V2E4ACsYAUJQABY20BggKwQBONAAGgUAAAEYpiZhOAAqBAAAATtGRzI4ACoNAAABP9Y27zgIQRAUABBQGwQBLUAAFlAS4SAABDggOhAAAAFAmg0AAAE+FrbXMTgAKwYBCFAAFhcgEFADswAAABAAB8AAIAmRAAAKQRewABggOwIBKYAAGwIBAnAAGwQBEcAAFrbHNTgAOwIBPkAAFrdHUBiYSggAAAFBigQAAAE8qgYAAAE+mgkAAAFBwCgAoTgoSgoAAAE2KxoBQoAAGw0BPDAAEEAQkBgAKxcBQjAAGg0AAAE51jbyOAArBgEIMAAWlvAQAA9DkMAAABAEsAAQAjgQKg4AAAE7ZleQENADowAAABAAAAAAAHABAAAADMEs0SXhNfE5ITkxPeE98TAYECsEAS6gABoMAAABOcZW8BAgA6MAAAAQAAAAAACAAQAAAAjg+PDzYRdxJ4EmIT4RMRFBIU8wEBbzswAAABAAAJAAQAqgkBAEUQAwCDEAEAYBMBAPOAA21ucgEAADswAAABAAAGAAIAAhMAAGcTBQBDgAOwQBPVAAGgIAAADP5lcnMjAAKwMBNDAAFjcvIwEwAAAQABgQKwgBKcAAGhAAAAE+BjZgGAAqAAAAAQO6AAAAAQPDQ28wIBdgEFDQAA8wABZAFrCQAA1/4hAJKwoBOLAAGwcBF8AAGwgBJ/AAGgsAAAErKgcAAAEHCwAAmIAAGd3X87MAAAAQAAFgALAIIBAABDBQMA9gUCAGQHAQBuBwIARwwAAKYPAAACEQAAaxECADQSAgDHEwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/35cd5d54f947.js b/pr/255/docs/search.index/35cd5d54f947.js deleted file mode 100644 index 6d6766600..000000000 --- a/pr/255/docs/search.index/35cd5d54f947.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9NoSAAABAFEAAQABAgGgYAAAE3xz8v0QAAABAAGAArAgD1UAAaCQAAATM2FlAQcBsEATTgABZfUUEwAAAQABAAEAAQABAwGwQBNjAAF08soSAAABACOFAqBAAAAS+GJzAQIA9PkQAAABAAEAAQA3dAAAi7BAEqwAAaBQAAAQmKCQAAASoLBQEgsAAaAwAAAMIrOYBzswAAABAABXABEAzAEBAPgDAwANBgAA9AYBAIoHAQAYCQEAJAkAAC8JAABcCQAAOQw3AIMMAAAjDwEA8A8BAAwQAQBSEAEA1BAEAMMRAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/36de07894256.js b/pr/255/docs/search.index/36de07894256.js deleted file mode 100644 index 0bf508625..000000000 --- a/pr/255/docs/search.index/36de07894256.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBgBJzABDtczswAAABAAAFAAEAWBIFACOCAqCQAAATSmlzAQEA9CASAAABAIkAAQAjgAKwoBL7AAFjbgGEArCgEwkAAbCgEwsAAWNyAQIAOzAAAAEAAAYAAQCRDwYAE4ICoCAAABLtZXUBAgDz7xAAAAEAAQABgAKwIBMqAAGgYAAAEoFvdmOBA6AQAAASQGFjcwEDAPR+DAAAAQABAAEAAQEA9CUQAAABAJsAAQATgAOgwAAAE1awEAktAAFucHUBgAKwMA9OAAGhYAAAE4lhZQGBArBAEc0AAbBAEc8AATQ2AQUA9KYPAAABAKkAAQBTgISgsAAAExGwMBJqAAEBoAQBCADzZxIAAAcAFwATgAKwQBEUAAFhZQEAAaAgAAAPwnIBiBAAAAEAAPS7EgAAAQBKAAEApwAAgIWgMAAAECKgEAAAEEKwoBMcAAEJICEBCQGgQAAAE01l8mwTAAABAEOAhKAgAAATW6CQAAASuqEwAAATaxBJAAECAPRUEgAAAQCOAAEAE4ACsEASIgABaXkBAQKgMAAAEf+gQAAAEj9ncjswAAABAAAHAAIAIxABALsQBQABgAKwABLVAAGwABLXAAE0NgEGAPSVEwAAAQAKAAEA8wICcnYBABMAAPMCAWX0rg8AAAEAqAABAPOAAmR0560/ABKgMAAAEEOgQAAADJKw8BOSAAGwcBKCAAEwYWJjZWdoaWtsbm9wcnN0dXY7MAAAAQAA8QBFACIFAADvBQIA+QUDAPMGAABQBwAAcwcCAIMHAACVBwQAmwcAAPsHAAAjCAEAEAkBABYJAQAiCQAAewkBAH8JdgDCCwEAzwsAANwLAAARDAAAHQwAAOoOAQASDwEAKQ8AAIoPAACyDwEAxA8AANEPAQAWEAEAGhADACsQAwBkEAEAhhAAAKIQAgDSEAAA6xAAAA4RAAASEQEAIhEEALERAAC/EQEAwhEAAMwRAADdEQAAEBIBAB4SAQArEgEAMhIBADgSAQA7EgAAPhIAAFASAABlEgEAehIAAH8SAACPEgQAqBIBALkSAAC7EgEAwRIBAMwSAAD6EgAABhMCAA0TAQAoEwEANBMAAEcTAQBuEwEAqRMAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3748eeff0c66.js b/pr/255/docs/search.index/3748eeff0c66.js deleted file mode 100644 index cac70343e..000000000 --- a/pr/255/docs/search.index/3748eeff0c66.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAANYAAgCJDAEACg7UAAEBAaAAAAASRnP1JQUAAOMJrwMBAAIAAYACoCAAAA79oDAAABHzZXITAQKgIAAAENNwdQHpDgAAAQECoGAAABK9oOAAABMTZXQ7MAAAAQAACAABACkFCAABgAOwIBGgAAGwsBHWAAGwsBHYAAFiY3PzgMUAAQoK") \ No newline at end of file diff --git a/pr/255/docs/search.index/378531389b4a.js b/pr/255/docs/search.index/378531389b4a.js deleted file mode 100644 index 8e2994e31..000000000 --- a/pr/255/docs/search.index/378531389b4a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9XYPAAABAAEANgIBAAEEAaAAAAAQBXP1ogwAAAEAAQDQAgEAAQIA9dQQAAABAAEAAQABAAGAArBgEhYAAaAgAAAQJ295AQABoMAAABMnafRnEgAABwAXABsAAQYA9IoTAAABAAEAAQABAgD0JRAAAAEAmwABAAECAaBAAAASP3I7MAAAAQAABwACACMQAQC7EAUA84ACYW9nAwAAhrCAEj4AVbCgEq4AAQwwBjswAAABAAAIAAMA2AsAAOcQAwC2EQMA84ICZWlHAQAAhbBwErsAAaCAAAATmKBAAAAPLbBABPQLCQAADQYBAHMDAYECoCAAABAhsFARwwABYW8BBAGgAAAAEtRzASAQAABjBAOwUBCTAAFjZXP2EwkAAAEAAQAsAAEAaggBAAA7MAAAAQAAJAAIAGkHBwB2DwIAxBANAOwQAgCuEQEAJhIBAHESAQADEwIAAQACsBALwgABsDATPgABZXD0Gg8AAAEA4AABAAEAA7BAEwsAAaFAAAATcKBQAAARDmJjZgE4BwAA44CEsUATlQABAjAQAQEDoLAAABLJsEAP4QABoGAAABC6Y2V09B8HAABjCD8C/QABAwA7MAAAAQAABQABAOARBQABAAGgoAAAEzNy9CMPAAABAOgAAQDzgQJncwEHAPVeEgAAAQABAAEAAQABgAKgQAAAEIuwUBByAAFjafOAAmFvAQABoCAAABCqcvPtCwAAAwNcAROAAoAFuwAb6HJ4AQMCsEASHAABoDAAABJwZXfyuQ8AALgAE4MCoHAAABKlZ28BAgD1AhIAAAEA3wB3AAEAE4ACsDASLQE1aXABBgDzohIAAAEAAQDzBQJicwFzDwAAAQIA9FAPAAABAAEAAQAjgAKgYAAAEapiY/e/AACMoJAAABGrO8kaOjAAAAEAAAAAABcAEAAAANAB3gHfARMEFAQVBD8HdgenB6gHqQeqB6sHrAe9CycMpwxuD4APgQ9CEMMQfxOAEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/37cfa41c8509.js b/pr/255/docs/search.index/37cfa41c8509.js deleted file mode 100644 index 7d06027e9..000000000 --- a/pr/255/docs/search.index/37cfa41c8509.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoJAAABJ6oBAAAAX0aW8BCQDzZRMAAAEANQABDAGgoAAAE6l38pkTAAABAAEBAPMvDwAAAQABAPOAAnR1AYECsIATcwABoGAAABOXZHM3AgCDhqBAAAATSbBgExsATbAwEwkAAQKQDgESAPSBEwAAAQABAAEAAQDGoFAAABHmoAAAAA/EsCAQdAABoFAAABEYoQAAABN8oEAAABMnAAMCCzswAAABAAAUAAcA9QUAAOwLAACNDAAAPg8MAJgQAAD7EQEAIBMBAAEBAbCwE24AAWw7MAAAAQAADAADAFEHCACpDAEAew8BAAEBAaAwAAAQT2jzEgkAAC4AwgcBAgD0+RAAAAEAAQABABOBArAgEP0AAWFz84ICbm/3AwCAh6BAAAAL1RUBBw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3872754cddc0.js b/pr/255/docs/search.index/3872754cddc0.js deleted file mode 100644 index b881b0e6b..000000000 --- a/pr/255/docs/search.index/3872754cddc0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsIASRwABdvR3CQAAAQB2CQEAE4ACsDAQNAABbG4BgAKgAAAAD8CgAAAAD8E0NvMDAXYBpgwAABMAAqBAAAAQsGFz9+4LAAA/A1oBLAEBAAEAkQEBAgD0IBIAAAEAiQABAAEDAPRUEgAAAQCOAAEA8wACYnU6MAAAAQAAAAAAEwAQAAAAcwd0B3UHEg8TD7IPsw/RD9IPZBBlEBIRExEeEh8SKxIsEjsSqBKpEvOAAmR0E4ACoCAAAAyvZXIBBwGgQAAAEyZl8lATAAABAAEHAPQrEAAAAQABAAEAAQAA9WoJAAABAAEAAQABACOAAqCgAAATe2ZwAQMBoJAAABL6ZfLsDgAAAQDXAAAAhaBQAAAPqLFAE6IAAYEpAPK/BQAAAQDzgAJsdJcBAICFsTATKAABsRATUgABEUUA") \ No newline at end of file diff --git a/pr/255/docs/search.index/38ae726b5e74.js b/pr/255/docs/search.index/38ae726b5e74.js deleted file mode 100644 index 7c0c9015a..000000000 --- a/pr/255/docs/search.index/38ae726b5e74.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9kcQAAABAE0DAQAKAAEAAQAAOzAAAAEAAAYAAgCAEgAA5RIFACOIArBAE1QAAWVzAQ0BsEATTgABZfUUEwAAAQABAAEAAQABBQA7MAAAAQAACAADABwRAgAEEgQAExMAANcBAACFeJvYCPEYFIQC83QMAAABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/38cb6e24cf5d.js b/pr/255/docs/search.index/38cb6e24cf5d.js new file mode 100644 index 000000000..607315a02 --- /dev/null +++ b/pr/255/docs/search.index/38cb6e24cf5d.js @@ -0,0 +1 @@ +rn_("AQIBoQAAABPoZPLCBwAA9AEBBgGgMAAAEY10ASMTAAABAwGwUBJ9AAFl9GUJAAASAwEArAMBAQD0JwYAAAEAAQABAAEBAaEAAAAT3WTyJgYAAC4ClwcAAIewoBJ7AAGg4AAAE7QegArzEQQAAAEAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/3922a16454e0.js b/pr/255/docs/search.index/3922a16454e0.js new file mode 100644 index 000000000..a27545fd2 --- /dev/null +++ b/pr/255/docs/search.index/3922a16454e0.js @@ -0,0 +1 @@ +rn_("AQEA9ZgJAAABAAEAAQABAPMAAWnz8QwAACIHAQABBAKgIAAAEXugMAAAEjNiaAF9DwAApwAAgMWgEAAADPKwEBQAAAGgMAAAECYEECgB") \ No newline at end of file diff --git a/pr/255/docs/search.index/392fb1700c95.js b/pr/255/docs/search.index/392fb1700c95.js new file mode 100644 index 000000000..6b59c786b --- /dev/null +++ b/pr/255/docs/search.index/392fb1700c95.js @@ -0,0 +1 @@ +rn_("AYACoCAAAA+CoDAAABNLYXLzAAF0AeAHAAABBAGgQAAAE85l8u0TAAABAAEFADswAAABAAALAAUABRAFAFgSAQByEwEAwRMAAOATAADjAISgMAAAD4CFAAI7MAAAAQAACwAFABoGAgAlBwQAaAwBAC8RAABoEgAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/393da311e403.js b/pr/255/docs/search.index/393da311e403.js new file mode 100644 index 000000000..a87c8af33 --- /dev/null +++ b/pr/255/docs/search.index/393da311e403.js @@ -0,0 +1 @@ +rn_("AQIBsEAT5AABdDswAAABAAANAAYAghIDAOUSAQBMEwEAYxMBANoTAQD+EwEAE4ACsDASrwE0aXABBQDzJBMAAAEAAQATgAKgMAAAE3pleVMAA7BwE4gAAWJlcwHtDwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/39c20340df78.js b/pr/255/docs/search.index/39c20340df78.js deleted file mode 100644 index 89402d23a..000000000 --- a/pr/255/docs/search.index/39c20340df78.js +++ /dev/null @@ -1 +0,0 @@ -rn_("ARMA9aQTAAABAAEAAQABABOAAqDAAAASRWFvAQICoLAAABNAoLAAABNBY3Pz9w8AAAEAXgABgQKwUBEUAAGgwAAAExFoafOAAmVpI4ACoLAAABJ/aXQBBgGwgBNHAAF2OzAAAAEAAAcAAgDyEAQAtBICAHcAAACGoKAAABKhoJAAABJvsFAPtQABBeAC9EIHAAABAAEANww=") \ No newline at end of file diff --git a/pr/255/docs/search.index/3a529860f4ab.js b/pr/255/docs/search.index/3a529860f4ab.js new file mode 100644 index 000000000..941c7626d --- /dev/null +++ b/pr/255/docs/search.index/3a529860f4ab.js @@ -0,0 +1 @@ +rn_("AQQA9N0TAAALAB4ADwABAgGwQBJHAAFlAX4PAAABgAKgkAAAE6OgkAAAE6QyM5cCAADGoCAAAAyBoGAAABDnsGANCwABAWQAAzswAAABAAAGAAIAfgcFAFIMAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/3a6bd631205f.js b/pr/255/docs/search.index/3a6bd631205f.js new file mode 100644 index 000000000..6273f3fec --- /dev/null +++ b/pr/255/docs/search.index/3a6bd631205f.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAcAAgCMDAUA+xABAAECAPMeEQAAAQABAAEGAPQLFAAAAQABAAEA8wYBbfQ3EgAAAQABAAEA84ACbnbzgAJhaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3a74000719ff.js b/pr/255/docs/search.index/3a74000719ff.js deleted file mode 100644 index 91353690e..000000000 --- a/pr/255/docs/search.index/3a74000719ff.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYYCoAAAABJQoAAAABJRZHIBgAKgcAAAEtmgMAAAED9mdAELAaBAAAATJmXyUBMAAAEAI4ECsFAQFgABY3YBAAGwgBMoAAFw8iQTAAABAEMGA6AgAAAQiKBAAAARvmRlc/MuDwAAEwMBAPMABGlyc3Y7MAAAAQAADwAFACQHBQDgEQUACxIBAHYSAABbEwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/3a74061c4f9f.js b/pr/255/docs/search.index/3a74061c4f9f.js new file mode 100644 index 000000000..be8f5e249 --- /dev/null +++ b/pr/255/docs/search.index/3a74061c4f9f.js @@ -0,0 +1 @@ +rn_("AYACsAAPzwABsCAMbwABZWkBiQKwIBPaAAGgMAAAE+NpcBMAA6AgAAASqqCAAAASvWVpdfUqDAAAMgABAAEAAQABhgKwkBP+AAGgAAAAEkRiZAGAArAwEp4AAaAwAAAQmnJ21wAAAIWgMAAAEBigMAAAEvIQARM6MAAAAQAAAAAACgAQAAAATglPCVAJgAmBCTQMLxA0EOsQ7BCBEmOAA6AQAAAJQ2RtdA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3adb9518fd74.js b/pr/255/docs/search.index/3adb9518fd74.js new file mode 100644 index 000000000..5e9126e58 --- /dev/null +++ b/pr/255/docs/search.index/3adb9518fd74.js @@ -0,0 +1 @@ +rn_("AQQBoEAAABEmZQHoDwAAAQgA9GMRAAABAAEAAQABAwGgQAAAESVlAXkPAAABAgDzQgwAAAEAAQAjAAKwIAwyAAFrcvZZBwAAAQBLCesAAQADAvOAAnJ4AQMBsIATyAABdjswAAABAAALAAMAuBABAG4RBgA2EwIAI4ACsGAQLwC8YXIBAwGgAAAAD+dz8ncPAAABACOAAqCwAAATW2VoAQMBoEAAABC3ZfJnCQAAAQDXJQAAjLAgB8gJHrBwES0AAbAgB6oAAbCwErQAAaCAAAARZ6AAAAASwb8MTDowAAABAAAAAAAJABAAAADeASsELAQtBB4MHwx9DH4MfwzCEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3afe7bef2754.js b/pr/255/docs/search.index/3afe7bef2754.js new file mode 100644 index 000000000..80d670aaa --- /dev/null +++ b/pr/255/docs/search.index/3afe7bef2754.js @@ -0,0 +1 @@ +rn_("AQkA8+YTAAABADUAAYACsCATiwABoCAAAA+GaXkBCQGggAAAFBlmAQ4TAAABAwGwABOeAEtzAUsTAABDgAOwIA+CARqwUBJFAAFhb3IBAgD1fRAAAAEAAQA5AgEA8wADaXR1OjAAAAEAAAAAAA4AEAAAAOAHfwnlD1sQfxF2EqYSpxJPE1ATVhN/E4ATnBOdEwEGAPSUEgAAAQB6AQEAEwICsGASlgABZm3y5QwAAAEAI4ICsEASvgABZWwBgAKwQBCBAAGgIAAAE8pjdBOAArCwEygAAWFsAQYA85APAADXAAEAAQUA9HYTAAABAEYAAQDzAgFj8osSAAABAAGBArBQEM0AAbAgD2AAAWNuAQUAOzAAAAEAAA4AAgDrDAAAtw8NAAECADswAAABAAAHAAEAoQkHAOcFAAAJoDAAAAxnoLAAABOcoIAAABFOsNATqwABMGFmaWttcnV2OzAAAAEAADkCBQDSAQAALQPdANcHAAAtC90A8w17AAEMAaCgAAAUKnfyGhQAAAEAAQEA86gPAAABAAEA84ACdHUBAwDzSRIAAAEAAQABAQD14RAAAAEAAQABAAEAAQEA9soHAAABAIwARAejAOIBY4ADsJATeAABYW10AQMBoEAAABPOZfLtEwAAAQATgAKwYBQdAAFlcgEDAaAAAAATVnMBmxAAAAECADowAAABAAAAAAAKABAAAACfCaAJzg/qEusSFhMXE7YTCRQfFCAUgwAEoIAAABIlsHAREQABsCAQsQDqZm5ydgFWCAAAAYECoAAAAAl/oDAAAA+Gc3THAQCAxrAAE6kAAbCQEiMAAaAQAAAHsAASiCgBAgA7MAAAAQAADQAGAAUQBQAOEQEAWBIBAHITAQDBEwAA4BMAABOCArDwFB0AAWZnAYACsIAT9AABoGAAABQYZHMTgAKwwBM9AAFpbwEIAPWvEwAAAQABAAEAAQDzAgFm9UAQAAABAAEAAQABACOAA6AgAAAPgLCgE/IAAWRydPf7BwCPoDAAAA91l9cPOzAAAAEAACsBHQA2BAEAPAUCAPMFAgAaBgIAPgYBACUHBACfBwAAuQcAAFAIAwBVCQIAgwkBAD0MAgBoDAEAjAwFAOcMAQB3DuAAng8BABsQAgBcEAEAbRACAJoQAQD7EAEALxEAAIYRAQAtEgAAaBIAAPkSAQAaEwcAAhQDAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3b1e455f5b16.js b/pr/255/docs/search.index/3b1e455f5b16.js new file mode 100644 index 000000000..7d0122470 --- /dev/null +++ b/pr/255/docs/search.index/3b1e455f5b16.js @@ -0,0 +1 @@ +rn_("AQAA9CEQAAABAKkAAQABhAKwABEhAAGwABEjAAE0NvMCAWHyggwAAAEAAQEA9k4SAABmAAEARwDzAAEA84ACZW/zgAJoaw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3b786721c45c.js b/pr/255/docs/search.index/3b786721c45c.js deleted file mode 100644 index 5c6452fe8..000000000 --- a/pr/255/docs/search.index/3b786721c45c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOzAAAAEAAAYAAQCiEwYA8wYBZfRXEwAAAQAuAAEAEwMDsEATfwABoGAAABL/YXJ1AaoPAAAjgAKAEKIAEAFkcg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3bd565fd40d0.js b/pr/255/docs/search.index/3bd565fd40d0.js deleted file mode 100644 index 6e7dd8f45..000000000 --- a/pr/255/docs/search.index/3bd565fd40d0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQoBoIAAABOYZgGMEgAAAQgA9S4TAAABAAEAAQABAPMDAWb1xQ8AAAEAAQABAAEA84MCYXMBAgKgIAAAEP+gMAAAEbJiaAEEDwAAI4ACoIAAABJFYXDzAAJobQEGBQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/3ce49910eea7.js b/pr/255/docs/search.index/3ce49910eea7.js new file mode 100644 index 000000000..588de421e --- /dev/null +++ b/pr/255/docs/search.index/3ce49910eea7.js @@ -0,0 +1 @@ +rn_("AQIBsEAT5AABdDswAAABAAANAAYAghIDAOUSAQBMEwEAYxMBANoTAQD+EwEAE4ACsDASrwE0aXABBQDzJBMAAAEAAQATgAKgMAAAE3pleVMBA7BwE4gAAWJlcwHtDwAAE4ADsDAT8gABsCAHZAABZWxz") \ No newline at end of file diff --git a/pr/255/docs/search.index/3d41efe337a8.js b/pr/255/docs/search.index/3d41efe337a8.js deleted file mode 100644 index 093b649b3..000000000 --- a/pr/255/docs/search.index/3d41efe337a8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9NERAAABAJoAAQABCAD0fRIAAAEAgwABADMBA7BAElIAAWFiZfWYDAAAAQDTAkECwgABAAD15wsAAAEACwMBAAEA84ACc3UjgQKwgBJ3AAFydAGAArBwEgsAAaAQAAAMfW56AQYA9LIPAAABALEAAQBzAISgoAAAE6kCART1wwUAAAEAhQ1QAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/3d4983faf394.js b/pr/255/docs/search.index/3d4983faf394.js deleted file mode 100644 index d9c656ecc..000000000 --- a/pr/255/docs/search.index/3d4983faf394.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHAR3gABoLAAABMIZW8jAYSwcBEgAAGgYAAAEnqAEnMAEO0AMAM7MAAAAQAAGgAGAJMHAQACCQUAqwwBAHYQCQC0EAAAWBIFAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3eb044d68081.js b/pr/255/docs/search.index/3eb044d68081.js deleted file mode 100644 index 82e4776ea..000000000 --- a/pr/255/docs/search.index/3eb044d68081.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOzAAAAEAAAYAAQCMEAYAAQAA9zAJAAABAHsGAQBrAAEADgEBggKgIAAAEE6gMAAAELVpdPOAA2FncwEBAaBAAAATJmXyUBMAAAEAI4ACsFAS3gABZnPzgAJpbw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3f16c6444948.js b/pr/255/docs/search.index/3f16c6444948.js new file mode 100644 index 000000000..941dac3ae --- /dev/null +++ b/pr/255/docs/search.index/3f16c6444948.js @@ -0,0 +1 @@ +rn_("AQACoDAAABC+oJAAABMHMGj1nhEAAHMBAQABAAEAE4ACoDAAAA9/ZHIjAYSwEAlKAv+wIAwcAPagMAAAD6MSABj1EQYAAC8AAQABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/3f1d867bdbec.js b/pr/255/docs/search.index/3f1d867bdbec.js deleted file mode 100644 index 8be475bac..000000000 --- a/pr/255/docs/search.index/3f1d867bdbec.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ8A9A8TAAABAE0AAQABBAD0sA8AAAEAsQABAAECADowAAABAAAAAAAJABAAAAAAEQER/RH+EdoS2xIsEy0TnBOdE/MAAW/yfQkAAAEAU4ADsQATbgABaG9w84ACc3Q=") \ No newline at end of file diff --git a/pr/255/docs/search.index/3f2790b84249.js b/pr/255/docs/search.index/3f2790b84249.js deleted file mode 100644 index d943965b9..000000000 --- a/pr/255/docs/search.index/3f2790b84249.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHATfQABoAAAAAUGZmcBAQA7MAAAAQAABwABAPsLBwABAQGgcAAAEaphAT8HAAAjgAKhAAAAE4VkbnOAhKBgAAARqQBBSA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3f76acc9c4c0.js b/pr/255/docs/search.index/3f76acc9c4c0.js deleted file mode 100644 index 964c42a52..000000000 --- a/pr/255/docs/search.index/3f76acc9c4c0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAYAAQCRDwYAAQMA9H4MAAABAAEAAQBjAAOgkAAAEm5ocHM6MAAAAQAAAAAAEAAQAAAA7wXwBfEF8wYiCREMHQwrECwQLRAuEL8RwBEQEhESOBI5Eg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/3fe667d21e90.js b/pr/255/docs/search.index/3fe667d21e90.js deleted file mode 100644 index 08b7f9620..000000000 --- a/pr/255/docs/search.index/3fe667d21e90.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABoDAAABCwdPTuDwAAAQAXAAEAAYACoAAAAA/AoAAAAA/BNDbzAwF2AaYMAAAXAQAAh7CgEhoAAbAgC+AAAbBgEhYAAbCAEf0AAaAgAAAQJwlERjowAAABAAAAAAAJABAAAAA1BzYHNwfuCy0PhxCzEbQRtRFGEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/402127170d10.js b/pr/255/docs/search.index/402127170d10.js deleted file mode 100644 index 9fcb5452d..000000000 --- a/pr/255/docs/search.index/402127170d10.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAABAABQD1BQAA7AsAAI0MAAA+DwwAmBAAAAGEArAAEKUAAbAAEKcAATQ2FwgAAIigIAAAEP+gMAAAEGyg4AAAEqCgMAAAEbKwcA8YAAGgIAAABf7LwAg7MAAAAQAA+QAVAIABAADqBQAA/gUAAAkJAAAPCQAALQkBAM0LAAAHDAEAKAwBAJAMAAC1DNUABA8AABUPAQD9DwAAuhAAAPURAQDDEgUA4BIAAGATAAB1EwUAkBMBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/40672655bcf1.js b/pr/255/docs/search.index/40672655bcf1.js deleted file mode 100644 index d9d614b54..000000000 --- a/pr/255/docs/search.index/40672655bcf1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCATWQABoDAAABNiaXATAAOgIAAAEiiggAAAEjtlaXX10QsAADIAAQABAAEAAYYCsJATfQABoAAAABHCYmQBgAKwMBIcAAGgMAAAEB9ydnMChKAwAAAScBAAEzowAAABAAAAAAAJABAAAAAMCQ0JDgk+CT8JtA+5D3AQcRD/EQEDAbAwEjYAAXPz8g8AAAEAAQABAAA7MAAAAQAACgADAJkQAgCwEgMAihMDANMAhLAgCCkAARAYAfUtDAAAAQABAAEAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4083ed670548.js b/pr/255/docs/search.index/4083ed670548.js deleted file mode 100644 index 408697c82..000000000 --- a/pr/255/docs/search.index/4083ed670548.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAAA9rc/PkCwAAAQABAAECAPPjCwAApgQBACMAAqBAAAAMlGVy8hcFAAABAAGAAqBAAAASzLAwEfsAAWFzAQIBoEAAABNNZfJsEwAAAQDzgARsbnJ2") \ No newline at end of file diff --git a/pr/255/docs/search.index/409b3322db69.js b/pr/255/docs/search.index/409b3322db69.js new file mode 100644 index 000000000..ff45d8e2a --- /dev/null +++ b/pr/255/docs/search.index/409b3322db69.js @@ -0,0 +1 @@ +rn_("AQUA9fAPAAABAAEAPQIBAAEEAaAAAAAQgHP1AQ0AAAEAAQDrAgEAAQIA9VARAAABAAEAAQABAAGAArBgEpgAAaAgAAAQom95AQABoMAAABOoafTpEgAABwAXABsAAQYA9AsUAAABAAEAAQABAgD0oBAAAAEAnAABAAECAaBAAAASwXI7MAAAAQAABwACAJ4QAQA3EQUA84ACYW9nAwAAhrCAEsAAVbCgEzAAAQwwBjswAAABAAAIAAMAMQwAAGMRAwA3EgMA84ICZWlHAQAAhbBwEz0AAaCAAAAUGaBAAAAPprBABPRNCQAARAYBAHwDAYECoCAAABCcsFASRQABYW8BBAGgAAAAE1ZzAZsQAABjBAOwUBEOAAFjZXP2VQkAAAEAAQAsAAEAqQgBAAA7MAAAAQAAJAAIAKIHBwDwDwIAQBENAGgRAgAvEgEAqBIBAPMSAQCFEwIAAQACsBAMGgABsDATvwABZXD0kw8AAAEA4gABAAEAA7BAE40AAaFAAAAT8aBQAAARimJjZgFxBwAA44CEsUAUFgABAjAQAQEDoLAAABNLsEAQXAABoGAAABE2Y2V09FgHAACkCEcC/QABAwA7MAAAAQAABQABAGISBQABAAGgoAAAE7Ry9JwPAAABAOoAAQDzgQJncwEHAPXgEgAAAQABAAEAAQABgAKgQAAAEQawUBDtAAFjafOAAmFvAQABoCAAABEmcvNGDAAAIwNeAROAAoAF6QAcO3J4AQMCsEASngABoDAAABLyZXfyNBAAALgAE4MCoHAAABMnZ28BAgD1hBIAAAEA3wB2AAEAE4ACsDASrwE0aXABBgDzJBMAAAEAAQDzBQJicwHtDwAAAQIA9MoPAAABAAEAAQAjgAKgYAAAEitiY/e/AACMoJAAABIsO8kaOjAAAAEAAAAAABcAEAAAAN8B7QHuATMENAQ1BHgHrwfhB+IH4wfkB+UH5gcVDIEMBw3oD/oP+w+9ED8RABQBFA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/40d03efa707b.js b/pr/255/docs/search.index/40d03efa707b.js new file mode 100644 index 000000000..ad3c24a58 --- /dev/null +++ b/pr/255/docs/search.index/40d03efa707b.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgACEwAAZxMFACOIArBAE9UAAWVzAQQBsDAS2AABY/MpEQAAAQABAAEFADswAAABAAAIAAMAmBECAIYSBACWEwAA8wEDY2Vw89IMAAABAAEAAQIA9mwJAABQAG8GAQCxAAEA84ACbnI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/40d41dda421f.js b/pr/255/docs/search.index/40d41dda421f.js deleted file mode 100644 index c0f7cfdc8..000000000 --- a/pr/255/docs/search.index/40d41dda421f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9q0MAAABAM8CAQAiAQEAAQoA89oRAAABAJoAAQEA9zAJAAABAHsGAQBrAAEADgEjgAKwYBLeAAFpbwECAPRxDAAAAQCkBQEAAQUA9PQSAAABAEcAAQD3BAAAh6AgAAAMc7CQERoAAQScAzowAAABAAAAAAAIABAAAADcBSAJIQkbDBwMKBApEAkSChI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/40e5df003d92.js b/pr/255/docs/search.index/40e5df003d92.js deleted file mode 100644 index 38228ec94..000000000 --- a/pr/255/docs/search.index/40e5df003d92.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBoKAAABJnZPIiBwAAAQABgQKgMAAAE1ugUAAAEu1jcwEEA7AgEHQAAaBQAAARGKBAAAATJ2xzdvIgEwAAAQDzAANhZW/yGgQAAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/40fc47699d53.js b/pr/255/docs/search.index/40fc47699d53.js deleted file mode 100644 index cb5e24bae..000000000 --- a/pr/255/docs/search.index/40fc47699d53.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsIATKAABcPIkEwAAAQBDBQOgIAAAEIigQAAAEb5kZXPzLg8AABMDAQABAgA7MAAAAQAAEwABAFcPEwATgYSgUAAAEDegEAAAC+KgIAAADJUcQAAzgAOwUBJ3AAFhZm4=") \ No newline at end of file diff --git a/pr/255/docs/search.index/40fcfec120bb.js b/pr/255/docs/search.index/40fcfec120bb.js new file mode 100644 index 000000000..5b4721e8e --- /dev/null +++ b/pr/255/docs/search.index/40fcfec120bb.js @@ -0,0 +1 @@ +rn_("AQMBsEARBAABZfImDAAASQIBBQA7MAAAAQAABgABAAsQBgABAwD03AwAAAEAAQABAPMAAnBzOjAAAAEAAAAAAA4AEAAAAB0GHgYfBioHZAlqDHYMphCnEKgQqRBBEkISkhKTEjMAA7BQD4MAxmRwcjswAAABAAAPAAYAKgUAAN4FAwBvDwAAgBEDADwSAwBrEgEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/4154473306f6.js b/pr/255/docs/search.index/4154473306f6.js deleted file mode 100644 index b6fd0a831..000000000 --- a/pr/255/docs/search.index/4154473306f6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYUCsHATBgABsDASYwABZXMTAAOwQA8OAAGgYAAAELRiZXM7MAAAAQAAEgAEAPIFAQD4BgoAgw8BANQPAwABAgDz/QUAADUJAQABAwD1Bg8AAJgAAQAEAAEAAQoBoEAAABNNZfJsEwAAAQAjAAOgMAAAEEOgkAAAEoUwY2j1IhEAAG0BAQABAAEA84ACZHLnAAAAh7AQCQgC6LAgC8QA7qAwAAAPKrAAB2QAARJBODswAAABAAAQAAYAeAACAOMFAAARBgMAwwcDAAQIAwDOCwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/4165ec97becb.js b/pr/255/docs/search.index/4165ec97becb.js new file mode 100644 index 000000000..ef2110ac3 --- /dev/null +++ b/pr/255/docs/search.index/4165ec97becb.js @@ -0,0 +1 @@ +rn_("AQAA9OUPAADBAgEArwDzAAFzOzAAAAEAABkACAA8BQIAPQwCAJ4PAQBcEAEAmhABAIYRAQAaEwcAAhQDACOAArEQFAcAAWF0") \ No newline at end of file diff --git a/pr/255/docs/search.index/4179e32fae1c.js b/pr/255/docs/search.index/4179e32fae1c.js new file mode 100644 index 000000000..644e191b3 --- /dev/null +++ b/pr/255/docs/search.index/4179e32fae1c.js @@ -0,0 +1 @@ +rn_("AYADsAATVwABsAATWQABsHATyAABNDZhAQQA9BYUAAABAAoAAQAjgQKgQAAAEQFtcAEBADswAAABAAAIAAMAXhIAAMcSAAAjFAYAhwMAAMagQAAAEASgYAAAE3yggAAAEjtAB4AIOzAAAAEAABYACACkDwEAuBABAP0QAwBuEQYANhMCAIITAADYEwEABxQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4204d4b478b6.js b/pr/255/docs/search.index/4204d4b478b6.js new file mode 100644 index 000000000..fe2da09f3 --- /dev/null +++ b/pr/255/docs/search.index/4204d4b478b6.js @@ -0,0 +1 @@ +rn_("AYMCoFAAABC2oKAAABLLa3ABAAGwQBIjAAFs9LcJAAABAM0GAQABCAD0NxIAAAEAAQABAAEEAbAAEI8AAXMBARAAAAECAaBQAAASj2MB1gwAALcAAACFsEANEAABoDAAAAwplQABOzAAAAEAAAgABABPBQAADgYCANkMAQByDwIAJwEAgIWwMAl8AAGgEAAAEvuwIAfZAAGRAEQBEAD0AhQAAAEAAQABAAEDAPS3CQAAAQDNBgEAY4ADoAAAAAwpbnJ1AQACsNATPQABoDAAAA91Ymr28wUAAAEAAQBJAAEAYAEBAAGwgBNcAAF0OzAAAAEAAD4ABAA8BgAAZgkAAHEJAACTDDsAAQkA81USAAABAAEA84ADY2d0AYMCoJAAABOjoJAAABOkMjMBgAKgUAAAE8uggAAAEvhjZfMAAnN08qAHAAABAAEAAaCwAAATP2Lz0xIAABcBAQAjgAKgAAAAEtJkciOAAqBQAAATlWNl84ACaXkBBAD14RAAAAEAAQABAAEA8wEBbgGaBwAAAQEAOzAAAAEAAAkAAgBGCAcAlhIBAAEGAPQyEwAAAQABAAEAAQ8A9AsUAAABAAEAAQDzgQJobQEAAbBAE88AAWX1lxMAAAEAAQABAAEAU4ADoCAAABF/bG50120AgMugIAAAE/2wYBB0AAGwQA+rAAHAGzgK") \ No newline at end of file diff --git a/pr/255/docs/search.index/4296b91ec07a.js b/pr/255/docs/search.index/4296b91ec07a.js new file mode 100644 index 000000000..c8f35673d --- /dev/null +++ b/pr/255/docs/search.index/4296b91ec07a.js @@ -0,0 +1 @@ +rn_("AQIA9VARAAABAAEAAQABAAGAArBgEpgAAaAgAAAQom95AQABoMAAABOoafTpEgAABwAXABsAAQYA9AsUAAABAAEAAQABAgD0oBAAAAEAnAABAAECAaBAAAASwXI7MAAAAQAABwACAJ4QAQA3EQUA84ACYW9nAwAAhrCAEsAAVbCgEzAAAQwwBjswAAABAAAIAAMAMQwAAGMRAwA3EgMA84ACZWk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/42b912b0d8d6.js b/pr/255/docs/search.index/42b912b0d8d6.js new file mode 100644 index 000000000..695480078 --- /dev/null +++ b/pr/255/docs/search.index/42b912b0d8d6.js @@ -0,0 +1 @@ +rn_("AQoA9BgTAAABAA8AAQABgwKgIAAAD/mgMAAAEIppdAEEAbAAEpIAAWT0PBIAAAEAAQABACOGhLCgE78AAbBAEpAAAbBwE3AAARWAAAEAArAwD+sAAbAQEzAAAXN08gwGAAAiBgGAArDAE+oAAaAAAAAHsnR584CFEcEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/43625da5722d.js b/pr/255/docs/search.index/43625da5722d.js new file mode 100644 index 000000000..0938617c2 --- /dev/null +++ b/pr/255/docs/search.index/43625da5722d.js @@ -0,0 +1 @@ +rn_("AQUA9HYTAAABAEYAAQDzAwFj8osSAAABACOAArBwFB0AAWhvAYICsAASaQABsAARiAABZXNDAAOgoAAAE8KgIAAAEwZlaXTyexIAAAEAAQIAOzAAAAEAAAYAAQAHEQYAAQIBoEAAABOnZfLREwAAAQDzgAJpbwEIAPRtEwAAAQB+AAUAEwEDsJATzAABsFASvAFOZ2xwOzAAAAEAABIACQAVEAIAixEBAKsSAQDMEgEA/RIBAF4TAQCSEwEAoRMBAN4TAQABgAKwQBJDAP2gIAAAEMphaQGBArAwE30AAaAwAAASX2NpAQMBsAASpgABczswAAABAAANAAMAhhEBABoTBwACFAMAAQMA9YQRAAABAAsBAQBGAfOAAnJ2AQAA9EESAAABAFAAAQDzAgFkOzAAAAEAAAkAAwCAEQMAPBIDAGsSAQAjgAKgkAAAE8FpbxOAArDwFA8AAWxvAQUA9N0TAAALAB4ADwAjgAKgYAAAEvtncyOAArCQE78AAWJs98cAAI2wYBPyAAGwcBNwAAGwYBK6AAGwUBKoAAG1yRc6MAAAAQAAAAAAHwAQAAAAKwZUCYIJbwxwDOIM4wzkDHAOcQ5yDnMOdQ52DqsPrA+tD64Prw9yEHMQrhDREDIRMxE0ETURfhGyEskSyhKVEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4365fc23c2e2.js b/pr/255/docs/search.index/4365fc23c2e2.js deleted file mode 100644 index d6cd055ab..000000000 --- a/pr/255/docs/search.index/4365fc23c2e2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9FwTAAALAB4ADwABAgGwQBHFAAFlAQUPAAABgAKgkAAAEyCgkAAAEyEyM5cCAADGoCAAAAwnoGAAABBssGAMqwABAWQAAzswAAABAAAGAAIARQcFAPkLAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/440ac285a659.js b/pr/255/docs/search.index/440ac285a659.js new file mode 100644 index 000000000..47291bce5 --- /dev/null +++ b/pr/255/docs/search.index/440ac285a659.js @@ -0,0 +1 @@ +rn_("AQUA9HYTAAABAEYAAQDzBAFj8osSAAABACOCAqBQAAASX2Z0AQABsAATyAABZPQWDAAAAQABAAEA84ACZWkTgAKw4BPTAAF0dg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/442799c14c6f.js b/pr/255/docs/search.index/442799c14c6f.js deleted file mode 100644 index c46a3f073..000000000 --- a/pr/255/docs/search.index/442799c14c6f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA82UTAAABADUAAYACsCATCQABoCAAAA8NaXkBCQGggAAAE5hmAYwSAAABAwGwABMbAE1zAckSAABDgAOwIA8JARiwUBHDAAFhb3IBAgD1AhAAAAEAAQAyAgEA8wADaXR1OjAAAAEAAAAAAA4AEAAAAKYHPQlrD+APAxH0ESQSJRLNEs4S1BL9Ev4SGRMaEwEGAPQSEgAAAQB7AQEAEwICsGASFAABZm3yhwwAAAEAI4ICsEASPAABZWwBgAKwQBAGAAGgIAAAE0ljdBOAArCwEqYAAWFsAQYA8xcPAADVAAEAAQUA9PQSAAABAEcAAQDzAgFj8gkSAAABAAGBArBQEFIAAbAgDucAAWNuAQUAOzAAAAEAAA0AAgCNDAAAPg8MAAECADswAAABAAAHAAEAXwkHAOcFAAAJoDAAAAwOoLAAABMZoIAAABDSsNATKgABMGFmaWttcnV2OzAAAAEAACQCBQDEAQAAFgPVAJ4HAADeCtUAiw12AAEMAaCgAAATqXfymRMAAAEAAQEA8y8PAAABAAEA84ACdHUBAwDzxxEAAAEAAQABAQD1ZhAAAAEAAQABAAEAAQEA9pEHAAABAIsABQehANwBY4ADsJAS9gABYW10AQMBoEAAABNNZfJsEwAAAQATgAKwYBOcAAFlcgEDAaAAAAAS1HMBIBAAAAECADowAAABAAAAAAAKABAAAABdCV4JVA9oEmkSlBKVEjUTiBOeE58TgwAEoIAAABGksHAQlgABsCAQNgDpZm5ydgEcCAAAAYECoAAAAAk9oDAAAA8Nc3THAQCAxrAAEygAAbCQEaIAAaAQAAAHdwASiCgBAgA7MAAAAQAADQAGAIsPBQCTEAEA1hEBAPASAQBAEwAAXxMAABOCArDwE5wAAWZnAYACsIATcwABoGAAABOXZHMTgAKwwBK7AAFpbwEIAPUuEwAAAQABAAEAAQDzAgFm9cUPAAABAAEAAQABACOAA6AgAAAPB7CgE3EAAWRydPf7BwCPoDAAAA78l9cPOzAAAAEAAB8BHQAWBAEAFAUCAMUFAgDsBQIADwYBAO4GBABmBwAAgAcAABYIAwATCQIAQQkBAOQLAgAPDAEAMgwFAIkMAQAKDtQAJQ8BAKAPAgDhDwEA8g8CAB8QAQCAEAEAsxAAAAoRAQCsEQAA5hEAAHcSAQCYEgcAgRMDAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/44630589167e.js b/pr/255/docs/search.index/44630589167e.js new file mode 100644 index 000000000..e3f1cbb01 --- /dev/null +++ b/pr/255/docs/search.index/44630589167e.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAYAAgAvBgUAKBEAAAEEAbAAEqYAAXM7MAAAAQAACwACABoTBwACFAMARwAAAYaggAAAEvuxABQPAAGwQBJpAAGwgBQdAAGwUBKoAAEVABb0cA4AAAEAAQABAAEFAPOtDwAAAQABAGOAA7BAEDIAAW1ubwGBArAADOkAAbAQEDAAAXN18wACYWk7MAAAAQAACQAEAMkHAACQDwAAZxABAAgTBQABgAOwABNXAAGwABNZAAGwcBPIAAE0NmEBBAD0FhQAAAEACgABACOBAqBAAAARAW1wAQIAOzAAAAEAAA4ABADMBwEACw0BAPEQCQAwEQAAAQEAOzAAAAEAAAgAAwBeEgAAxxIAACMUBgABAQA7MAAAAQAACgADABURAgAyEwMACxQDACOAAqAwAAAQBGRnlwcAAMegYAAAE3yggAAAEjtAR4AIOzAAAAEAABgACQCkDwEAuBABAO0QAQD9EAMAbhEGADYTAgCCEwAA2BMBAAcUAQABAwD2bAkAAFAAbwYBALEAAQATgAKwcBOpAAFvcgEEAbCwE+8AAWz0CQ0AAAEA6wIBAAECADswAAABAAAMAAMASwkAAEUTBQD2EwUAAQEA8+sPAAABAD4CI4ACoLAAABOoZ3oBAgA6MAAAAQAAAAAACQAQAAAAfBF9EX8SgBJcE10TrROuEx0UHhTzAAFv8r8JAAABAAEFAPSXDwAAAQDjAAEAgwCEoEAAAAz+sHAS6gABsCAMhQABEAUCOzAAAAEAAAkAAwBDBQMA9gUCAGsRAgABgAKgIAAAEMewIBOpAAFkdAGEArCwE/IAAbAAE08AAWFz04CEoLAAABPcQCgEAYACoDAAABGUsGAPqwABaHJH/wEAzaAgAAAGFKAgAAAGFbBwE0MAAQNnNAc7MAAAAQAANwAYACYFAABbBQUAtQkAANcMAABnDwEAUxADABARAABeEgAAbxIFAMcSAQDpEgAA8BIAAAcTAAAYEwEAIhMAACQTAgAoEwEAehMAAIETAACNEwEApRMBALcTBQDLEwAAIxQGAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/44a3f431018f.js b/pr/255/docs/search.index/44a3f431018f.js new file mode 100644 index 000000000..8cccbd3e0 --- /dev/null +++ b/pr/255/docs/search.index/44a3f431018f.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwBoEQIA8xIBAIUTAgABBADzaxEAAAEAAQAjAAKgYAAAEoFhcvOREAAAAQCyAQGAAqEQAAAUBrCAE/4AAWl1NwQAgYexUBQhAAGACWkAFwewcBNPAAGhMAAAFBUKQBsBAAA7MAAAAQAAewABAPMNewABAgD2FhMAAAEAnwBTABYAAQAjgQKgIAAAELFydvOAAmVvI4ACoCAAABIlZHQBAAA7MAAAAQAA4AAEAD0GAABlCN0AkgwAABQRAADzgANkbnY=") \ No newline at end of file diff --git a/pr/255/docs/search.index/44a79dbac07c.js b/pr/255/docs/search.index/44a79dbac07c.js deleted file mode 100644 index ffe468f70..000000000 --- a/pr/255/docs/search.index/44a79dbac07c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAADgAAgAvCQAAOQw3AAGAArBQD+4AAbCwEpYAAWFsYwAEsEAO7gABoBAAAA+oYnBydjswAAABAAAGAAEAjBAGAAGAArCAEDoB97DgEvsAAWlyAQMBsEAQiQABZQECDgAAAQUAOzAAAAEAAAYAAQCRDwYAAQMA9H4MAAABAAEAAQDzAAJwczowAAABAAAAAAAOABAAAADvBfAF8QXzBiIJEQwdDCsQLBAtEC4QvxHAERASERJXAAAAhbBQD+ACFLBQDwoAxKBAAAAQtEiAAzswAAABAAAPAAYAAgUAALAFAwD2DgAABBEDALoRAwDpEQEA0wCEoGAAAAyQEAgG83cBAAABAPsK") \ No newline at end of file diff --git a/pr/255/docs/search.index/44f8510a4206.js b/pr/255/docs/search.index/44f8510a4206.js new file mode 100644 index 000000000..15e54eda6 --- /dev/null +++ b/pr/255/docs/search.index/44f8510a4206.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwBoEQIA8xIBAIUTAgABBADzaxEAAAEAAQAjAAKgYAAAEoFhcvOREAAAAQCyAQGAAqEQAAAUBrCAE/4AAWl1NwQAgoexUBQhAAGACWkAFwewcBNPAAGhMAAAFBUKQBsTgAKwEBKNAAFpcg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4508fe205566.js b/pr/255/docs/search.index/4508fe205566.js new file mode 100644 index 000000000..cc49c80f8 --- /dev/null +++ b/pr/255/docs/search.index/4508fe205566.js @@ -0,0 +1 @@ +rn_("AQQA9g0NAAABAOkCAQAkAQEAAQoA81wSAAABAJoAAQEA93IJAAABALQGAQBrAAEADwEjgAKwYBNgAAFpbwECAPTPDAAAAQDIBQEAAQUA9HYTAAABAEYAAQD3BAAAh6AgAAAM0bCQEZYAAQScAzowAAABAAAAAAAIABAAAAAKBmIJYwl0DHUMoxCkEIsSjBI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4599163a6a37.js b/pr/255/docs/search.index/4599163a6a37.js new file mode 100644 index 000000000..7fd1a32fc --- /dev/null +++ b/pr/255/docs/search.index/4599163a6a37.js @@ -0,0 +1 @@ +rn_("AYMCsQAUHwABsNAUEQABa20BCgDzchMAAAEAbQATgAKiEAAAFCpsbzMChKBgAAASIKEAAAAT4gSAAzswAAABAAA0AAIAsQcAAAEIMwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/45caa4397354.js b/pr/255/docs/search.index/45caa4397354.js deleted file mode 100644 index d2b0f7993..000000000 --- a/pr/255/docs/search.index/45caa4397354.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOjAAAAEAAAAAAAkAEAAAABUPFg/9D7oQ9RH2EeASYBOQE5ETAYACsOAS2gABsDAS8gABZHDDgISxQBOgAAGgkAAAEqECgAk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/45d12af4ff3b.js b/pr/255/docs/search.index/45d12af4ff3b.js new file mode 100644 index 000000000..a413f847b --- /dev/null +++ b/pr/255/docs/search.index/45d12af4ff3b.js @@ -0,0 +1 @@ +rn_("AQIA9YQRAAABAAsBAQBGAQEBAPfEEAAAAQABAKcCAQB+AAUAAQIA9FcQAAABAAEAAQATgAKg0AAAE9xjc/OAAmVvI4ACsAAHtAABbHTzAAJhcvJgDwAAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/45e872f24307.js b/pr/255/docs/search.index/45e872f24307.js deleted file mode 100644 index e8bfeb65f..000000000 --- a/pr/255/docs/search.index/45e872f24307.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9JAHAACHB9UAAQABBQD0NBIAAAEAigABAPMCAWP1iA8AAAEAuwABAAEAYwAEoDAAAAvvoHAAABEDZW5zdvOlDwAAlQD3AQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/45f4fbda75f7.js b/pr/255/docs/search.index/45f4fbda75f7.js deleted file mode 100644 index d1f2e2e5e..000000000 --- a/pr/255/docs/search.index/45f4fbda75f7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoEAAABCwc/XuCwAAmQQsAQEAAQATggKgIAAADK9lciOAA6BAAAAL7bAwCTcAAWVvdAECAPSWEgAAAQAPAAEAE4ACsEATRAABYnYTgAKwAAdiAAFveAEKAPXPEgAAAQABAHEAAQABgQKgIAAAECGwUBHDAAFhbwEEAaAAAAAS1HMBIBAAAGMDA7BQEJMAAWNlc/YTCQAAAQABACwAAQBqCAEBAPR+DAAAAQABAAEAI4ACsDASOgFPcnT3AQAAhrAQB2QAAQHAB/K4AQAAGw8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4682f9d07fab.js b/pr/255/docs/search.index/4682f9d07fab.js new file mode 100644 index 000000000..8f7c57642 --- /dev/null +++ b/pr/255/docs/search.index/4682f9d07fab.js @@ -0,0 +1 @@ +rn_("AYkCsCAT2gABoDAAABPjaXATAAOgIAAAEqqggAAAEr1laXX1KgwAADIAAQABAAEAAYYCsJAT/gABoAAAABJEYmQBAgD0LwwAAAEALgMBAAEAADswAAABAAAGAAIAAhMAAGcTBQAjgQKwQBPVAAFlc1OAA7AACYgAAWV4eQGAArAgEp4AAbAACYYAAXJ4RwEAAMawwBMuAAGgEAAAERSwQAzpAAGgMAAAEJoARIAL9OcFAAABAAcHAQDXAAAAhaAwAAAQGKAwAAAS8hABEzowAAABAAAAAAAKABAAAABOCU8JUAmACYEJNAwvEDQQ6xDsEIES") \ No newline at end of file diff --git a/pr/255/docs/search.index/46b30dba3752.js b/pr/255/docs/search.index/46b30dba3752.js new file mode 100644 index 000000000..73693bc8e --- /dev/null +++ b/pr/255/docs/search.index/46b30dba3752.js @@ -0,0 +1 @@ +rn_("AQgBoIAAABQZZgEOEwAAE4ACoOAAABPiYnABAwGwABOeAEtz9ZcPAAABAOMAAQDPAgGAArBAEkUAAaAQAAAQunByAYEDoAAAABEssAAPggEaoBAAAA96ZXN184ADYW9yAQIA9X0QAAABAAEAOQIBAAEEADswAAABAAAJAAEA8RAJAAGBAqCQAAATZLBQEi8AAWJ3o4CEsFATfwABsJASsAABQCADVwMAAIagcAAAE1ugQAAAE8cwQQw6MAAAAQAAAAAAOwAQAAAATAVNBf8FAAYBBgIGAwYEBgUGBgYHBuAHeQl6CX8JQAxBDGIMYwxkDOkM6gx0DmwPbQ9uD4IPoA+hD+UPWxBpEGoQgRCCEIkQihCcEMIQwxAxEX8RiBGJEY0RdhKmEqcSTxNQE1YTfxOAE5wTnRO0ExYUFxQhFCIU") \ No newline at end of file diff --git a/pr/255/docs/search.index/47b13875e45c.js b/pr/255/docs/search.index/47b13875e45c.js new file mode 100644 index 000000000..93526365d --- /dev/null +++ b/pr/255/docs/search.index/47b13875e45c.js @@ -0,0 +1 @@ +rn_("AQAAOjAAAAEAAAAAAAoAEAAAAJUPlg95EHoQBhGSEZMRlBKVEg8UEBTzAQF58n0TAAABACMAA6BAAAARJaBQAAATx2Vvc/J5DwAAsgI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/47cdb0491b20.js b/pr/255/docs/search.index/47cdb0491b20.js new file mode 100644 index 000000000..4532034a0 --- /dev/null +++ b/pr/255/docs/search.index/47cdb0491b20.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwBoEQIA8xIBAIUTAgABBADzaxEAAAEAAQAjAAKgYAAAEoFhcvOREAAAAQCyAQGAAqEQAAAUBrCAE/4AAWl1NwQAgYexUBQhAAGACWkAFwewcBNPAAGhMAAAFBUKQBsjgAKgMAAAEiVudg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/47d3233d790f.js b/pr/255/docs/search.index/47d3233d790f.js new file mode 100644 index 000000000..08844a15f --- /dev/null +++ b/pr/255/docs/search.index/47d3233d790f.js @@ -0,0 +1 @@ +rn_("AQEA98QQAAABAAEApwIBAH4ABQABAgD0VxAAAAEAAQABABOAAqDQAAAT3GNz84ACZW8jgQKwAAe0AAFsdAEAAPQnBgAAAQABAAEAU4ADoFAAABQqZG5y") \ No newline at end of file diff --git a/pr/255/docs/search.index/47fa58ac1f7e.js b/pr/255/docs/search.index/47fa58ac1f7e.js deleted file mode 100644 index 2b3339697..000000000 --- a/pr/255/docs/search.index/47fa58ac1f7e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsAAQpQABsAAQpwABNDbzAAFh8igMAAABACOAArCQEKsBBWx0AYACsHASjQABsIASwQABY3MBAAA6MAAAAQAAAAAACQAQAAAAABEBEf0R/hHaEtsSLBMtE5wTnRPzgAJkZScBAICFoNAAABMAsBAFIAABoDAAAA+oAggL") \ No newline at end of file diff --git a/pr/255/docs/search.index/481e68f578df.js b/pr/255/docs/search.index/481e68f578df.js deleted file mode 100644 index 766462807..000000000 --- a/pr/255/docs/search.index/481e68f578df.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9egFAADpCwEAmgABAAEAADswAAABAAAHAAMA1wEBACAMAQBQDwMAAYMCsHASjQABsIASwQABY3MBBQD0NBIAAAEAigABAPMIAWP1iA8AAAEAuwABAAEAAQABoDAAABCwdPTuDwAAAQAXAAEAAYACoAAAAA/AoAAAAA/BNDbzAwF2AaYMAACXAAAAhbCgEhoAAbAgC+AAAbCAEf0AAQkEBjowAAABAAAAAAAJABAAAAA1BzYHNwfuCy0PhxCzEbQRtRFGEwECAPQgEgAAAQCJAAEAAQMA9FQSAAABAI4AAQDzAAJidTowAAABAAAAAAAVABAAAABzB3QHdQcSDxMPsg+zD9EP0g9kEGUQEhETER4SHxIrEiwSOxJlEmYSqBKpEgEBAPTkBQAAAQCxBgEAtwAAgIWxABMsAAGwAAd9AAEMCEQBCAA7MAAAAQAABQABAOARBQDXDQAAiLBAEFQAAaAgAAAMr7kACzswAAABAAAPAAUAZgABAC0HBwCMBwEApg8BAFAQAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4821942f57b5.js b/pr/255/docs/search.index/4821942f57b5.js deleted file mode 100644 index e35afddbe..000000000 --- a/pr/255/docs/search.index/4821942f57b5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9dQQAAABAAEAAQABAAGAArBgEhYAAaAgAAAQJ295AQABoMAAABMnafRnEgAABwAXABsAAQYA9IoTAAABAAEAAQABAgD0JRAAAAEAmwABAAECAaBAAAASP3I7MAAAAQAABwACACMQAQC7EAUA84ACYW9nAwAAhrCAEj4AVbCgEq4AAQwwBjswAAABAAAIAAMA2AsAAOcQAwC2EQMA84ACZWk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/48917fd6b226.js b/pr/255/docs/search.index/48917fd6b226.js new file mode 100644 index 000000000..8248814fa --- /dev/null +++ b/pr/255/docs/search.index/48917fd6b226.js @@ -0,0 +1 @@ +rn_("AQEA98QQAAABAAEApwIBAH4ABQABAgD0VxAAAAEAAQABABOAAqDQAAAT3GNzU4ADoHAAABPXZWlvQ4ADoCAAAA+ZsAAHtAABZGx0") \ No newline at end of file diff --git a/pr/255/docs/search.index/48b3ceed3817.js b/pr/255/docs/search.index/48b3ceed3817.js new file mode 100644 index 000000000..f27d034b6 --- /dev/null +++ b/pr/255/docs/search.index/48b3ceed3817.js @@ -0,0 +1 @@ +rn_("AQcA9J8RAAABAAEAAQAjAQKgcAAAEZ5hcgHbBwAAAQMAOzAAAAEAAAcAAgBYDwUA2BIBAPMAAmN0OzAAAAEAAFcAJgAwBQsA5QUBAGAJAQA8DAAAQgwCAPMMAAD+DAIAEA0BAH8PAACEDwEAhw8BAI0PAAASEAIAGRABAB4QAQA9EAAAsRAAALcQAAAEEQEAEREBACURAQApEQIAhBEBAJURAgCbEQAAQBIAAEcSAQBMEgEAkBIBAJwSAwC+EgEAzhIDANQSAQAuEwEAPxMAAKcTAADMEwQA1RMCAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/48b9c2df65c3.js b/pr/255/docs/search.index/48b9c2df65c3.js deleted file mode 100644 index 1ae5bf062..000000000 --- a/pr/255/docs/search.index/48b9c2df65c3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcAOzAAAAEAAHcAAgAeEAAAKBF2AAEDADswAAABAAB2AAEAiw12AAECADswAAABAAAHAAEA+wsHAPMAA2JpdDswAAABAAB3AAIAAQUAADkFdgA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/48d55f753fb7.js b/pr/255/docs/search.index/48d55f753fb7.js new file mode 100644 index 000000000..b347f1992 --- /dev/null +++ b/pr/255/docs/search.index/48d55f753fb7.js @@ -0,0 +1 @@ +rn_("AQMA8xIQAAABAAEAAYACoLAAABOUsDAS7AABbnRDAAOgIAAAEL2wUBGQAAFlaGk7MAAAAQAABgADACgMAACfEQMAQxMBAPOAAmRy") \ No newline at end of file diff --git a/pr/255/docs/search.index/4909652ee282.js b/pr/255/docs/search.index/4909652ee282.js new file mode 100644 index 000000000..f635f3a76 --- /dev/null +++ b/pr/255/docs/search.index/4909652ee282.js @@ -0,0 +1 @@ +rn_("AQEBsIAS5wABdfKSCQAAAQAjgAKwEAmQAAEzNgEGAPOTEAAAAQAPAROAArAAD2oAAW91AQMA81USAAABAAEAI4ACsAARYQABaGkBAAA7MAAAAQAAEwABAOcHEwAjgAKgMAAADOBhZfOAAnJ0E4ACsDATMAABYWwBAAGggAAAFBlm8k0JAADBCQEHAPXgEgAAAQABAAEAAQAjgAKgUAAAEQZhb/MCAmZzOzAAAAEAAAgABACvBwAA4QcFAAcNAAA/EQAAE4ACoEAAAAwnYW8BAwGwQBPkAAF08kwTAAABACOFAqBAAAATemJzEwACoFAAABETYmb3WgkAAAEAQwDNBgEAYQABABOBAqBQAAARm2d0AYACoEAAABGKoCAAABNbYWkBAgD0jAkAAAEAXAcBAAECAPNiDAAAAQABABOAA7AQCYoAAbAwE40AAWl1eQECADswAAABAAALAAIARRMFAPYTBQDzCAFtOzAAAAEAAAwAAwAQEQAAbxIFALcTBQABgQKggAAAEl6gcAAAE5xhc/OAAm5yt7UBAI2hQAAAE/GwMBEtAAGgIAAACY6wIAezAdy3lQ47MAAAAQAAFQIFANABAAD1ASIBcQcAANYHAAA9Cu8A") \ No newline at end of file diff --git a/pr/255/docs/search.index/49d47034aeca.js b/pr/255/docs/search.index/49d47034aeca.js deleted file mode 100644 index 67d5b7651..000000000 --- a/pr/255/docs/search.index/49d47034aeca.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkBoIAAABOYZgGMEgAAAQIA9QIQAAABAAEAMgIBAPMAAml1OjAAAAEAAAAAAAcAEAAAAOAP9BHNEs4S/RL+EhkTGhMBCAD1LhMAAAEAAQABAAEA8wIBZvXFDwAAAQABAAEAAQATgAKwoBNxAAFydPMCAmFz8/IPAAABAAEAAQQBsEATTgABZfUUEwAAAQABAAEAAQABAgA7MAAAAQAACwACAMMSBQB1EwUA8wMBbTswAAABAAANAAQAeQwAAJUQAADtEQUANhMFAPOBAmNl84ACYWU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/49f51c99ba82.js b/pr/255/docs/search.index/49f51c99ba82.js deleted file mode 100644 index c6f3a5307..000000000 --- a/pr/255/docs/search.index/49f51c99ba82.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9PQSAAABAEcAAQDzAwFj8gkSAAABACOAArBwE5wAAWhvAYICsAAR5wABsAARDAABZXNDAAOgoAAAE0GgIAAAEoRlaXTy+REAAAEAAQIAOzAAAAEAAAYAAQCMEAYAAQIBoEAAABMmZfJQEwAAAQDzgAJpbwEIAPTrEgAAAQB/AAUAEwEDsJATSwABsFASOgFPZ2xwOzAAAAEAABIACQCbDwIADxEBACkSAQBKEgEAexIBANwSAQAPEwEAHhMBAF0TAQABgAKwQBHBAP2gIAAAEE9haQGBArAwEvsAAaAwAAAR3WNpAQMBsAASJAABczswAAABAAANAAMAChEBAJgSBwCBEwMAAQMA9QgRAAABAAUBAQBHAfOAAnJ2AQAA9L8RAAABAFAAAQDzAgFkOzAAAAEAAAkAAwAEEQMAuhEDAOkRAQAjgAKgkAAAE0BpbxOAArDwE44AAWxvAQUA9FwTAAALAB4ADwAjgAKgYAAAEnlncyOAArCQEz4AAWJs98cAAI2wYBNxAAGwcBLuAAGwYBI4AAGwUBImAAG1yRc6MAAAAQAAAAAAHwAQAAAA/QUSCUAJFgwXDIQMhQyGDAMOBA4FDgYOCA4JDjIPMw80DzUPNg/3D/gPMxBWELYQtxC4ELkQAhEwEkcSSBISEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4a10d1b50063.js b/pr/255/docs/search.index/4a10d1b50063.js new file mode 100644 index 000000000..aab50e3e8 --- /dev/null +++ b/pr/255/docs/search.index/4a10d1b50063.js @@ -0,0 +1 @@ +rn_("AQABsKASWgABZTswAAABAAAJAAIARggHAJYSAQABAAGgIAAADO5tAfsFAAABgAKwoBJYAAGwQA+JAAFsbwEEAbAAEpIAAWT0PBIAAAEAAQABACMChLCgE78AAbBAEpAAAbBwE3AAARWAAAGVEwAAAQABsIATqQABcPKlEwAAAQBDAAOgIAAAEQOgQAAAEkBkZXPzpw8AABwDAQDzgQJladcCAACGsCASIQABsNATrQABFwEC9CsFAAABAAEAtQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4a662a061b37.js b/pr/255/docs/search.index/4a662a061b37.js deleted file mode 100644 index ddcd0f74d..000000000 --- a/pr/255/docs/search.index/4a662a061b37.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsEASaAABoMAAABMZZW8BAgD0+RAAAAEAAQABABMAA7AgEP0AAbCAEywAAWFzdAGDDAAAAQQA8zQPAAABAAEAs4CEsEASdwABQQAG") \ No newline at end of file diff --git a/pr/255/docs/search.index/4a809c839d91.js b/pr/255/docs/search.index/4a809c839d91.js deleted file mode 100644 index 49cf24e15..000000000 --- a/pr/255/docs/search.index/4a809c839d91.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9NgPAAABAAEAAQDzAgFz9VIJAAABAAEAAQC4BQEGAPQjEQAAAQABAAEAAQEAOzAAAAEAAAYAAQCiEwYA8wYBZfRXEwAAAQAuAAEAEwYDsEATfwABoGAAABL/YXJ1AaoPAADzgAJhZQEDAPTfEAAAAQABAAEAAQIA9AIPAAABAAYEAQABgAOwAAefAAGgAAAAC9SwcA+3AAFucnOnBwAAh6BwAAARIrBwEf0AAZEFQTowAAABAAAAAAAMABAAAACuAa8BsAGxAaEHCggLCFsJDgw7DzwPPQ9DEA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4a869b28035c.js b/pr/255/docs/search.index/4a869b28035c.js new file mode 100644 index 000000000..edaa65601 --- /dev/null +++ b/pr/255/docs/search.index/4a869b28035c.js @@ -0,0 +1 @@ +rn_("AQkA8+YTAAABADUAAQwBoKAAABQqd/IaFAAAAQABAQDzqA8AAAEAAQDzgAJ0dQGBArCAE/QAAaBgAAAUGGRzNwIAgIagQAAAE8qwYBOeAEuwMBOLAAECkA4BAAGwUBCvAAFj9L8HAAABAAEA8wHDgISgEAAADISgUAAAEi0MQAQ=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4ac32d6f5fe0.js b/pr/255/docs/search.index/4ac32d6f5fe0.js deleted file mode 100644 index 6740040be..000000000 --- a/pr/255/docs/search.index/4ac32d6f5fe0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9CsQAAABAAEAAQABAAD1agkAAAEAAQABAAEAI4ACoKAAABN7ZnABAwGgkAAAEvpl8uwOAAABANcAAACFoFAAAA+osUATogABgSkA8r8FAAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4b168eb35e34.js b/pr/255/docs/search.index/4b168eb35e34.js deleted file mode 100644 index 1ca565898..000000000 --- a/pr/255/docs/search.index/4b168eb35e34.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9WYQAAABAAEAAQABACOBArCQEvYAAWF0Q4ADsRATbAABoIAAABK5Y290EwACsAATRAABbnL20QEAAAEARgIBAEgDIws=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4b2753b82fcd.js b/pr/255/docs/search.index/4b2753b82fcd.js deleted file mode 100644 index f0bffb349..000000000 --- a/pr/255/docs/search.index/4b2753b82fcd.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA8/kOAAABAAEAAYACoFAAAA/9oGAAABBtaXIBgAKgIAAADCegYAAAEGxlaAEBAaAgAAAQa2LzIwwAAAEAAQATgQKgEAAADCZhYwEGAPQSEgAAAQB7AQEAEwACsGASFAABZm3yhwwAAAEAI4ACoMAAABLUbnKnBwAAh6BAAAAO9rBADvcAATQAFzswAAABAAAXAAMAzgEAAPwDDQC0CwgAAYADsHASjQABsDASPAABsIASwQABY3JzAQABsCASjQABbzowAAABAAAAAAAJABAAAAAAEQER/RH+EdoS2xIsEy0TnBOdEwGAArAgCTIAAbAwEkcAAXJ09wAAAMegIAAAB5ygYAAADyKwgBJHAAFABpII9tsBAABEAlgFAQB2CQEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/4b3a70d5ace1.js b/pr/255/docs/search.index/4b3a70d5ace1.js deleted file mode 100644 index bc3233a52..000000000 --- a/pr/255/docs/search.index/4b3a70d5ace1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgA9S4TAAABAAEAAQABAPMAAWY7MAAAAQAABQACALkBAADFDwQAAQIAOzAAAAEAAAsAAgDDEgUAdRMFAPMGAW07MAAAAQAADQAEAHkMAACVEAAA7REFADYTBQBjgAOwAAkyAAFlbXM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4b88b05de3be.js b/pr/255/docs/search.index/4b88b05de3be.js new file mode 100644 index 000000000..76a1178da --- /dev/null +++ b/pr/255/docs/search.index/4b88b05de3be.js @@ -0,0 +1 @@ +rn_("AQMBoEAAABGVZfMIDQAAswMBAAEGAPS4EAAAAQC6AAEAE4EDoAAAABEBsSAUBwABYWRuARQA9SUUAAABAAEAAQABAAEGAbCAE8gAAXY7MAAAAQAABwACAG4RBAA2EwIAVwAAAYagwAAAEwGgoAAAEyOgkAAAEvGwUBAwAAEF4AL0ewcAAAEAAQB/DAEGAPNcEgAAAQCaAPOAA3J0dgEDADswAAABAAAHAAIAMhMDAAsUAwDzAAFzAcsTAADzAAFzAZQRAABnAQCAhqAwAAAMU7AAEuwAAaAQAAAM7hJADg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4bc2f7dbadf5.js b/pr/255/docs/search.index/4bc2f7dbadf5.js deleted file mode 100644 index 828bf9fa5..000000000 --- a/pr/255/docs/search.index/4bc2f7dbadf5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBsEATTgABZfUUEwAAAQABAAEAAQABAgA7MAAAAQAACwACAMMSBQB1EwUA8wEBbTswAAABAAANAAQAeQwAAJUQAADtEQUANhMFAPMBAWXyIBEAAAEAM4CEsBAPtwABoCAAAAvUFEAE") \ No newline at end of file diff --git a/pr/255/docs/search.index/4bf42a7ae759.js b/pr/255/docs/search.index/4bf42a7ae759.js new file mode 100644 index 000000000..3ddf54791 --- /dev/null +++ b/pr/255/docs/search.index/4bf42a7ae759.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAcAAwBoEQIA8xIBAIUTAgABBwD2FhMAAAEAnwBTABYAAQABBADzaxEAAAEAAQAjAAKgYAAAEoFhcvOREAAAAQCyAQGAAqEQAAAUBrCAE/4AAWl1dwgAAIixUBQhAAGACWkAFwewcBNPAAGhMAAAFBUKQRvyqQkAAKIGAYECoFAAABC2oKAAABLLa3ABAwA7MAAAAQAA4gACAOcMAQB3DuAA84ACbHTzgAJhZQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4bf63ac4398b.js b/pr/255/docs/search.index/4bf63ac4398b.js deleted file mode 100644 index f231b74ea..000000000 --- a/pr/255/docs/search.index/4bf63ac4398b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("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") \ No newline at end of file diff --git a/pr/255/docs/search.index/4c291219c272.js b/pr/255/docs/search.index/4c291219c272.js deleted file mode 100644 index d7e7d8520..000000000 --- a/pr/255/docs/search.index/4c291219c272.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCsAAQpQABsAAQpwABNDbzAgFh8igMAAABAAEAAPbMEQAAZgABAEcA9AABAPMAAWTz2hEAAAEAmgBjgAOgIAAACQphZW8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4c96afa0c0be.js b/pr/255/docs/search.index/4c96afa0c0be.js deleted file mode 100644 index 8faf3123f..000000000 --- a/pr/255/docs/search.index/4c96afa0c0be.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBoQAAABNnZPKJBwAA6wEBBgGgMAAAERF0AaESAAABAwGwUBH7AAFl9CMJAAD7AgEAigMBAQD0+QUAAAEAAQABAAEBAaEAAAATXGTy+AUAACIClwcAAIewoBH5AAGg4AAAEzMegArz8gMAAAEAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4d1ba35b8882.js b/pr/255/docs/search.index/4d1ba35b8882.js new file mode 100644 index 000000000..4ffa99b3a --- /dev/null +++ b/pr/255/docs/search.index/4d1ba35b8882.js @@ -0,0 +1 @@ +rn_("AQcA9hYTAAABAJ8AUwAWAAEA8wEBaQGpCQAAAQAA9awJAAABAAEAAQABAEcBAIDGTyQ22SWtoKAAABP8sGATeAABoBAAAAmFAAogig==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4d63d12f11e5.js b/pr/255/docs/search.index/4d63d12f11e5.js deleted file mode 100644 index f5b10d8de..000000000 --- a/pr/255/docs/search.index/4d63d12f11e5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsIASZQABdfJQCQAAAQAjgAKwEAlOAAEzNgEGAPMYEAAAAQAOAROAArAADvEAAW91AQMA89MRAAABAAEAI4ACsAAQ5QABaGkBAAA7MAAAAQAAEwABAK0HEwAjgAKgMAAADIJhZfOAAnJ0E4ACsDASrgABYWwBAAGggAAAE5hm8gsJAACBCQEHAPVeEgAAAQABAAEAAQAjgAKgUAAAEIthb/MCAmZzOzAAAAEAAAgABAB2BwAApwcFAKcMAADDEAAAE4ACoEAAAAvOYW8BAwGwQBNjAAF08soSAAABACOFAqBAAAAS+GJzEwACoFAAABCYYmb3GAkAAAEAQwCUBgEAYQABABOBAqBQAAARH2d0AYACoEAAABEOoCAAABLZYWkBAgD0SgkAAAEAIwcBAAECAPMJDAAAAQABABOAA7AQCUgAAbAwEwsAAWl1eQECADswAAABAAALAAIAwxIFAHUTBQDzCAFtOzAAAAEAAAwAAwCVEAAA7REFADYTBQABgQKggAAAEdygcAAAExlhc/OAAm5yt7UBAI2hQAAAE3CwMBCxAAGgIAAACUywIAd6AdO3lQ47MAAAAQAABQIFAMIBAADmARoBOAcAAJ0HAAD2CecA") \ No newline at end of file diff --git a/pr/255/docs/search.index/4d826694c35e.js b/pr/255/docs/search.index/4d826694c35e.js new file mode 100644 index 000000000..e367abc02 --- /dev/null +++ b/pr/255/docs/search.index/4d826694c35e.js @@ -0,0 +1 @@ +rn_("AQgA9a8TAAABAAEAAQABAPMAAWY7MAAAAQAABQACAMcBAABAEAQAAQIAOzAAAAEAAAsAAgBFEwUA9hMFAPMGAW07MAAAAQAADQAEANcMAAAQEQAAbxIFALcTBQBjgAOwAAl0AAFlbXM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4e0c6b87a738.js b/pr/255/docs/search.index/4e0c6b87a738.js deleted file mode 100644 index 93f1aafc7..000000000 --- a/pr/255/docs/search.index/4e0c6b87a738.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9mUTAAABAA0AAQAjAAQAAQMA88cRAAABAAEAI4ECsSATnAABY2sTgAKgMAAAEyZuclMAA6BAAAAL22VvcvRPEAAAYwGeAQEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/4e3799776c96.js b/pr/255/docs/search.index/4e3799776c96.js new file mode 100644 index 000000000..08089fc92 --- /dev/null +++ b/pr/255/docs/search.index/4e3799776c96.js @@ -0,0 +1 @@ +rn_("AQABoCAAAAzubQH7BQAAAQQBsAASkgABZPQ8EgAAAQABAAEAI4SEsKATvwABsEASkAABsHATcAABFYAAM4ADsNATrQABYWVp") \ No newline at end of file diff --git a/pr/255/docs/search.index/4e4aaeeb80ed.js b/pr/255/docs/search.index/4e4aaeeb80ed.js new file mode 100644 index 000000000..48957fb6c --- /dev/null +++ b/pr/255/docs/search.index/4e4aaeeb80ed.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAABEABQAjBgAARQwAAOsMAAC3Dw0AExEAAAGEArAAESEAAbAAESMAATQ2FwgAAIigIAAAEXugMAAAEOeg4AAAEyKgMAAAEjOwcA+RAAGgIAAABizLwAg7MAAAAQAAAQEVAI4BAAAYBgAALAYAAEsJAABRCQAAbwkBACUMAABgDAEAggwBAO4MAAAVDd0AfQ8AAI4PAQB4EAAANhEAAHcSAQBFEwUAYhMAAOETAAD2EwUAERQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4e720ea46bc3.js b/pr/255/docs/search.index/4e720ea46bc3.js deleted file mode 100644 index 0c21c02f2..000000000 --- a/pr/255/docs/search.index/4e720ea46bc3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcAOzAAAAEAAAUAAQCGEgUA8wUBdDswAAABAAAIAAIAxQsAAPELBwABBQDzohIAAAEAAQA3AACAhbAwD4AAAaCgAAASvaAwAAAS+BBBSA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4eb88f9761c0.js b/pr/255/docs/search.index/4eb88f9761c0.js new file mode 100644 index 000000000..947535e0c --- /dev/null +++ b/pr/255/docs/search.index/4eb88f9761c0.js @@ -0,0 +1 @@ +rn_("AYACsHARGgABsCATxQABYWQBBQD0xRIAAAEAjgABAPMAAWMBOxIAACOAArCgE6sAAXN5AQYA9LgQAAABALoAAQCTgISgAAAAEQGxIBQHAAEJIAHzgAJlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/4f2436d925ad.js b/pr/255/docs/search.index/4f2436d925ad.js new file mode 100644 index 000000000..dabbd4a6b --- /dev/null +++ b/pr/255/docs/search.index/4f2436d925ad.js @@ -0,0 +1 @@ +rn_("AQIA9FURAAABAAEAAQABCgDzNhMAAAEAAQDzgQJtdAEGAPMVEQAAAQABAAGCArBgEsMAAbDQE9EAAWlyE4ACsBAM7AABZWkBBQD0dhMAAAEARgABAPMEAWPyixIAAAEAI4ICoFAAABJfZnQBAAGwABPIAAFk9BYMAAABAAEAAQDzgQJlaTcGAACJsTAT7QABoGAAABEUoFAAABClsJASmgABsEAQowABtRAHAagTAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4f554ad18979.js b/pr/255/docs/search.index/4f554ad18979.js deleted file mode 100644 index 85d10002c..000000000 --- a/pr/255/docs/search.index/4f554ad18979.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOjAAAAEAAAAAAA4AEAAAALAMsQw8EBkRGhEbEb4RxRHGEcoRyxEaEhsSThJPEgEJAPOiEAAAAQABAAEKAPPTEQAAAQABAAEGAPVmEAAAAQABAAEAAQDzgAJkbnMAhLEgEyoAAQARA/IiEgAAAQABDQD2lBIAAAEAoABTABYAAQABgAKwoBKsAAGgEAAAC+9jdQEBAPS7EgAAAQBKAAEA8wABZfJ7CQAAAQD3AACAxbAwD+EAAQACqAg=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4fa3a94ba9bc.js b/pr/255/docs/search.index/4fa3a94ba9bc.js new file mode 100644 index 000000000..ca521f83e --- /dev/null +++ b/pr/255/docs/search.index/4fa3a94ba9bc.js @@ -0,0 +1 @@ +rn_("AQgAOjAAAAEAAAAAAAcAEAAAAMwSzRJeE18TkhOTE94T3xMjgAKwUBLAAFVmbgEAAbBAEpwAAWU7MAAAAQAADQACADoHDACyEAAAI4ACoDAAAAwrYWUzgISwUBMPAAGwEBOrAAEIYAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/4fab115143ff.js b/pr/255/docs/search.index/4fab115143ff.js new file mode 100644 index 000000000..5d8edbbaf --- /dev/null +++ b/pr/255/docs/search.index/4fab115143ff.js @@ -0,0 +1 @@ +rn_("AQQBsAASpgABczswAAABAAALAAIAGhMHAAIUAwBHAAABhqCAAAAS+7EAFA8AAbBAEmkAAbCAFB0AAbBQEqgAARUAFvRwDgAAAQABAAEAAQUA860PAAABAAEAY4CEsEAQMgABoAAAAAdHAPAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/5037f3c0b285.js b/pr/255/docs/search.index/5037f3c0b285.js deleted file mode 100644 index d7d38787f..000000000 --- a/pr/255/docs/search.index/5037f3c0b285.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9dQQAAABAAEAAQABAAGAArBgEhYAAaAgAAAQJ295AQABoMAAABMnafRnEgAABwAXABsAAQYA9IoTAAABAAEAAQABAgD0JRAAAAEAmwABAAECAaBAAAASP3I7MAAAAQAABwACACMQAQC7EAUA84ACYW9nAwAAhrCAEj4AVbCgEq4AAQwwBjswAAABAAAIAAMA2AsAAOcQAwC2EQMA84ICZWkjAAKggAAAE5hmaPILCQAAgQkBAAKwEAvCAAGwMBM+AAFlcPQaDwAAAQDgAAEAAQADsEATCwABoUAAABNwoFAAABEOYmNmATgHAADzgAJtbgEBA6CwAAASybBAD+EAAaBgAAAQumNldPQfBwAAYwg/Av0AAQUAOzAAAAEAAAUAAQDgEQUAAQcA9V4SAAABAAEAAQABACOAAqBQAAAQi2Fv8wCFIEkCOzAAAAEAAAgABAB2BwAApwcFAKcMAADDEAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/50c4c9dd70c1.js b/pr/255/docs/search.index/50c4c9dd70c1.js deleted file mode 100644 index e13d94126..000000000 --- a/pr/255/docs/search.index/50c4c9dd70c1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA90kQAAABAAEAoAIBAH8ABQABAQKgQAAAE1agMAAAEE9laPUSCQAALgDWAgEA6wQBAgD0+RAAAAEAAQABABOBArAgEP0AAWFz84ACbm8BAgD03A8AAAEAAQABABMAAqDQAAATW2Nz8lUPAAABAPOAA2Vpbw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/512cfed374c5.js b/pr/255/docs/search.index/512cfed374c5.js deleted file mode 100644 index a34b60b9d..000000000 --- a/pr/255/docs/search.index/512cfed374c5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABJGc/QIDwAArwMBAAIAAQECsGATKgABsEATYwABZHQ7MAAAAQAADQAGAAASAwBjEgEAyhIBAOESAQBZEwEAfRMBAAEBA7BwESAAAbCAEd4AAYAScwAQ7W1uczswAAABAAALAAIAAgkFAFgSBQCjgISgsAAAErmxcBOcAAEIQIIBAQA7MAAAAQAABgABAKITBgDzBgFl9FcTAAABAC4AAQATAQOwQBN/AAGgYAAAEv9hcnUBqg8AAFcBAACFsRATKgABsDASLQE1EYEIOzAAAAEAAAYAAgCAEgAA5RIFAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5161b276f515.js b/pr/255/docs/search.index/5161b276f515.js deleted file mode 100644 index a1f74460d..000000000 --- a/pr/255/docs/search.index/5161b276f515.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAAkABABoCQEAyg8DAAgQAQDeEgEAAQIBsEATYwABdDswAAABAAANAAYAABIDAGMSAQDKEgEA4RIBAFkTAQB9EwEAE4ACsDASLQE1aXABiAKwABLVAAGwABLXAAE0NhOBAqAwAAAQrGRzAYACoCAAAAwqsGATBgABbngBBQDzohIAAAEAAQATgAKgMAAAEvhlefMAhBIAA/JzDwAA2gDzgAJydA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/520fc5a0c8db.js b/pr/255/docs/search.index/520fc5a0c8db.js deleted file mode 100644 index 1521bbef6..000000000 --- a/pr/255/docs/search.index/520fc5a0c8db.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYECoCAAABAhsFARwwABYW8BAwGgAAAAEtRzASAQAAAjgAKgAAAACBxydmMAA7BQEJMAAWNlczswAAABAAAIAAQAEwkCAEEJAQCgDwIArBEAAAcBAICFsFAQUgABoKAAABKgsPAStwABsCAO5wABRCEE") \ No newline at end of file diff --git a/pr/255/docs/search.index/5259902f1872.js b/pr/255/docs/search.index/5259902f1872.js new file mode 100644 index 000000000..6698dd4da --- /dev/null +++ b/pr/255/docs/search.index/5259902f1872.js @@ -0,0 +1 @@ +rn_("AQUA9FMSAAABAJoAAQABCAD0/xIAAAEAgwABADMBA7BAEtQAAWFiZfX3DAAAAQDuAkgCwwABAAD1QAwAAAEAKwMBAAEA84ACc3UjgQKwgBL5AAFydAGAArBwEo0AAaAQAAAM2256AQYA9C0QAAABALEAAQBzAISgoAAAFCoCART18QUAAAEA2A1QAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/52a47b654b95.js b/pr/255/docs/search.index/52a47b654b95.js deleted file mode 100644 index 24cb236ea..000000000 --- a/pr/255/docs/search.index/52a47b654b95.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9QISAAABAN8AdwABABOAArAwEi0BNWlwAQYA86ISAAABAAEA8wICYnMBcw8AAPMBAWbyjwcAANwIAQIA9FQSAAABAI4AAQAzgAOwQBIiAAFpdXk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/52a660a476b8.js b/pr/255/docs/search.index/52a660a476b8.js deleted file mode 100644 index 9570f116b..000000000 --- a/pr/255/docs/search.index/52a660a476b8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEATYwABdDswAAABAAANAAYAABIDAGMSAQDKEgEA4RIBAFkTAQB9EwEAE4ACsDASLQE1aXABBQDzohIAAAEAAQATgAKgMAAAEvhleVMBA7BwEwYAAWJlcwFzDwAAE4ADsDATcQABsCAHKwABZWxz") \ No newline at end of file diff --git a/pr/255/docs/search.index/53206e8cf266.js b/pr/255/docs/search.index/53206e8cf266.js deleted file mode 100644 index 126f236eb..000000000 --- a/pr/255/docs/search.index/53206e8cf266.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA82UTAAABADUAAQwBoKAAABOpd/KZEwAAAQABAQDzLw8AAAEAAQDzgAJ0dQGBArCAE3MAAaBgAAATl2RzNwIAgIagQAAAE0mwYBMbAE2wMBMJAAECkA4BAAGwUBA0AAFj9IYHAAABAAEA6gHDgISgEAAADCqgUAAAEawMQAQ=") \ No newline at end of file diff --git a/pr/255/docs/search.index/53369ac5a189.js b/pr/255/docs/search.index/53369ac5a189.js new file mode 100644 index 000000000..fcac54a8c --- /dev/null +++ b/pr/255/docs/search.index/53369ac5a189.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABLIc/SBDwAAuAMBAAIAAQECsGATqwABsEAT5AABZHQ7MAAAAQAADQAGAIISAwDlEgEATBMBAGMTAQDaEwEA/hMBAAEBA7BwEZwAAbCAEmAAAYAS9QAQ7G1uczswAAABAAALAAIARAkFANoSBQCjgISgsAAAEzuxcBQdAAEIQIIBAQA7MAAAAQAABgABACMUBgDzBgFl9NgTAAABAC4AAQATAQOwQBQAAAGgYAAAE4FhcnUBJRAAAFcBAACFsRATqwABsDASrwE0EYEIOzAAAAEAAAYAAgACEwAAZxMFAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5347b986d048.js b/pr/255/docs/search.index/5347b986d048.js new file mode 100644 index 000000000..a3e891d04 --- /dev/null +++ b/pr/255/docs/search.index/5347b986d048.js @@ -0,0 +1 @@ +rn_("AQAA9KwQAAABAHsBAQAjgQKgYAAAEr1iaQEAAPSgDwAAAQDoAAQBI4ECsFAS0AABZXMTgAKwAAezAdxhcgGJArAgE9oAAaAwAAAT42lwAQIA9KISAAABAIkAAQABAwD01hIAAAEAjgABAPOFAmJ1AQIA9BgRAAABAGABAQDzgAJpbLcBAACFoCAAABKqEgEMOjAAAAEAAAAAABYAEAAAANMHXwhgCGEIYggqDFwMXQxeDF8Mxw+AEOwS7RIjE54T5hPnE+kT9BP1ExgUHBQ=") \ No newline at end of file diff --git a/pr/255/docs/search.index/53c1218b1076.js b/pr/255/docs/search.index/53c1218b1076.js deleted file mode 100644 index f8e0d3024..000000000 --- a/pr/255/docs/search.index/53c1218b1076.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsKAR2AABZTswAAABAAAJAAIADAgHABQSAQABAAGgIAAADJBtAc0FAAABgAKwoBHWAAGwQA8QAAFsbwEEAbAAEhAAAWT0uhEAAAEAAQABACMChLCgEz4AAbBAEg4AAbBwEu4AARWAAAESEwAAAQABsIATKAABcPIkEwAAAQBDAAOgIAAAEIigQAAAEb5kZXPzLg8AABMDAQDzgQJladcCAACGsCARoAABsNATLAABFwEC9AMFAAABAAEArwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/53d3e59dd54f.js b/pr/255/docs/search.index/53d3e59dd54f.js deleted file mode 100644 index 7377bb9ae..000000000 --- a/pr/255/docs/search.index/53d3e59dd54f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA90kQAAABAAEAoAIBAH8ABQABAgD03A8AAAEAAQABABOAAqDQAAATW2NzU4ADoHAAABNWZWlvQ4ADoCAAAA8gsAAHewABZGx0") \ No newline at end of file diff --git a/pr/255/docs/search.index/5452a8cd2f09.js b/pr/255/docs/search.index/5452a8cd2f09.js deleted file mode 100644 index 9eccb7022..000000000 --- a/pr/255/docs/search.index/5452a8cd2f09.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA88cRAAABAAEAI4ECsSATnAABY2sBBAGgQAAAERll86gMAACYAwEAAQAA9RoQAAABAAEAAQBiAnOAhKAwAAATJggwAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5456fb44b43c.js b/pr/255/docs/search.index/5456fb44b43c.js deleted file mode 100644 index d41ee4f71..000000000 --- a/pr/255/docs/search.index/5456fb44b43c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQABsGAS/QABZQEzEwAAAQYA9DISAAABADsBAQABBAD0TBIAAAEA/gABAPMAA2VyczowAAABAAAAAAAJABAAAAA0CTUJNgltEKsQohGjEbAR9hL3Eg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/547e81c6465c.js b/pr/255/docs/search.index/547e81c6465c.js new file mode 100644 index 000000000..c65caac45 --- /dev/null +++ b/pr/255/docs/search.index/547e81c6465c.js @@ -0,0 +1 @@ +rn_("AQcAOzAAAAEAAAUAAQAIEwUA8wUBdDswAAABAAAIAAIAHQwAAEoMBwABBQDzJBMAAAEAAQA3AACAhbAwD/oAAaCgAAATP6AwAAATehBBSA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/54c99bfc02b4.js b/pr/255/docs/search.index/54c99bfc02b4.js deleted file mode 100644 index ff4e8885b..000000000 --- a/pr/255/docs/search.index/54c99bfc02b4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAEoAAAAA/EsCAQdAABoFAAABEYoEAAABMnZGxzdjswAAABAAASAAYA9QUAAOwLAACNDAAAPg8MAJgQAAAgEwEAAQIA9PkQAAABAAEAAQAThAKwIBD9AAFhc/OAAmFl") \ No newline at end of file diff --git a/pr/255/docs/search.index/550f9f8ba786.js b/pr/255/docs/search.index/550f9f8ba786.js deleted file mode 100644 index cb06883b7..000000000 --- a/pr/255/docs/search.index/550f9f8ba786.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDsEAIAcRIBAAMTAgABBADz7xAAAAEAAQAjAAKgYAAAEf9hcvMWEAAAAQCrAQGAAqEQAAAThbCAE30AAWl1NwQAgYexUBOgAAGACScAFs6wcBLNAAGhMAAAE5QKQBsBAAA7MAAAAQAAdgABAIsNdgABAgD2lBIAAAEAoABTABYAAQAjgQKgIAAAEDZydvOAAmVvI4ACoCAAABGkZHQBAAA7MAAAAQAA1wADAA4GAAArCNUAOAwAAPOAA2Rudg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5535895d7e1a.js b/pr/255/docs/search.index/5535895d7e1a.js deleted file mode 100644 index 1a82c04fa..000000000 --- a/pr/255/docs/search.index/5535895d7e1a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBgBJzABDtczswAAABAAAFAAEAWBIFACOCAqCQAAATSmlzBwEAhMWwUBIiAAGgoAAAErqwcBKCAAGg0AAAE1aAARgI") \ No newline at end of file diff --git a/pr/255/docs/search.index/556039691422.js b/pr/255/docs/search.index/556039691422.js new file mode 100644 index 000000000..cb228ab41 --- /dev/null +++ b/pr/255/docs/search.index/556039691422.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABNWcwGbEAAAAYACsDAQMAABsFAQMgABYWkBgAKgsAAAE9ygMAAAEMdsbhcBAACFoCAAABIqoCAAAAlLsIATqQABEJEEOjAAAAEAAAAAABAAEAAAACYFWwVcBV0FXgVfBWAFtQlnD2gPyBJ6E4ETjROOE6UTphMBAgA6MAAAAQAAAAAACgAQAAAAnwmgCc4P6hLrEhYTFxO2EwkUHxQgFAEAADswAAABAAAGAAIAAhMAAGcTBQABAgGwMBLYAAFjOjAAAAEAAAAAABMAEAAAAP4Mfw8SEBMQFBAZEBoQHhAfELEQJREpESoRKxGbEc4SzxKnE8wTzRMBggKwMBOfAAGwQBERAAFhZQEBAbBAE88AAWX1lxMAAAEAAQABAAEAE4ACoBAAAAwpYW/HBwAAx7BAE9UAAaCAAAASJQBMiAnyVggAANcDAYACoIAAABLxoJAAABLLYWsBAwDzSRIAAAEAAQAjgISxIBQdAAGgAAAACX+gMAAAD4YEBAYBCAD1JRQAAAEAAQABAAEAE4oCsEAUAAABYXKTAISgwAAAEsehAAAAE4oBQAby2QcAAAEAAQMBoEAAABGVZfMIDQAAswMBAAEFAPQyEwAAAQABAAEAU4ADsAAS7AABZXN0AQYA9AsUAAABAAEAAQDzCAFt9DcSAAABAAEAAQABAgA7MAAAAQAABQABAPYTBQDzDQFtOzAAAAEAAAUAAQC3EwUAAQQA9xANAAABAC8FDAABAIMAAQABAwGAEvUAEOxzOzAAAAEAAAUAAQDaEgUAI4ICoJAAABPLaXMBgAKgsAAAE5SwMBLsAAFudAGAAqCAAAATB7BAEZAAAWFlAYACoBAAABC9oAAAABEDbnIBCQGgQAAAE85l8u0TAAABACOAAqCQAAATPGlsxyMAAAqgMAAAEL6wUBKkAAGw8BQTAAGwcBMEAAGg0AAAE9cwYmNlaGlrbm92OzAAAAEAABkACwAoDAAAlRADAJ4RBAABEwAAERMDAEMTAQCKEwAAjxMCAKkTAQC1EwAAyBMBAAECAqCwAAATwaCwAAATwmNz83IQAAABAF4AAQECsFARkAABoMAAABOUaGnyQxMAAAEA84ACZWkBAQGgkAAAEwFz9FcQAAABAAEAAQABAwGwABCPAAFzAQEQAADzgANoaXQBAQGgUAAAEo9jAdYMAAABBQGwgBPIAAF2OzAAAAEAAAcAAgBuEQQANhMCAAEBAPQhEAAAAQCpAAEA84ADY2Rs92UPANGwkBIjAAGgUAAAELahAAAAE/ygoAAAEyOgEAAAB7BAP78pOzAAAAEAADcAFgBOBQEADgYCAHsHAgAWDAMA2QwBAHIPAgCBDwAApw8AAM8PAQDUEAgALBEAAGASAQBpEgEAbRIBAMMSAQDgEgQAMBMBADkTAQA8EwAArxMEAPwTAAAZFAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/55eb9c789f72.js b/pr/255/docs/search.index/55eb9c789f72.js deleted file mode 100644 index 69233f091..000000000 --- a/pr/255/docs/search.index/55eb9c789f72.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoIAAABHcsHATGQABYXMBAAGggAAAE5hm8gsJAACBCQEHAPVeEgAAAQABAAEAAQAjgAKgUAAAEIthb/MAAmZzOzAAAAEAAAgABAB2BwAApwcFAKcMAADDEAAA84ACZHk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/56fbecce9190.js b/pr/255/docs/search.index/56fbecce9190.js new file mode 100644 index 000000000..33c9b2d13 --- /dev/null +++ b/pr/255/docs/search.index/56fbecce9190.js @@ -0,0 +1 @@ +rn_("AQMBoAAAABLIc/SBDwAAuAMBAAIAAQECsGATqwABsEAT5AABZHQ7MAAAAQAADQAGAIISAwDlEgEATBMBAGMTAQDaEwEA/hMBAAEBhLBwEZwAAbCAEmAAAaBgAAAS/IAS9QAQ7AAwAzswAAABAAALAAIARAkFANoSBQCjgISgsAAAEzuxcBQdAAEIQIIBAISgcAAAEiqgcAAAELGxABOrAAGwABK8AU4CIQHy7wUAAAEAAQEAOzAAAAEAAAYAAQAjFAYA8wYBZfTYEwAAAQAuAAEAEwEDsEAUAAABoGAAABOBYXJ1ASUQAAB3BAAAh6AQAAAGIrAwEq8BNKBAAAAQ1BHBDDswAAABAAAGAAIAAhMAAGcTBQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/570e64122582.js b/pr/255/docs/search.index/570e64122582.js deleted file mode 100644 index c0eb9cee0..000000000 --- a/pr/255/docs/search.index/570e64122582.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQATngABsNATkAABa20BCgDz8BIAAAEAbgATgAKiEAAAE6lsbzMChKBgAAARn6EAAAATYQSAAzswAAABAAA0AAIAeAcAAMcHMwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5726b451fa74.js b/pr/255/docs/search.index/5726b451fa74.js deleted file mode 100644 index d3630cac5..000000000 --- a/pr/255/docs/search.index/5726b451fa74.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAUAAQB1EwUA8w0BbTswAAABAAAFAAEANhMFAEcAAACFsAATRwABsEARygABoQAAABN7oAAAABL/OAgCOzAAAAEAABgABgC+CwMAWhAHAOsRAQBeEgQALhMEAJgTAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/574d932e9c29.js b/pr/255/docs/search.index/574d932e9c29.js new file mode 100644 index 000000000..bf9caeeff --- /dev/null +++ b/pr/255/docs/search.index/574d932e9c29.js @@ -0,0 +1 @@ +rn_("ARMA9SUUAAABAAEAAQABABOAAqDAAAASx2FvAQICoLAAABPBoLAAABPCY3PzchAAAAEAXgABgQKwUBGQAAGgwAAAE5RoafOAAmVpI4ACoLAAABMBaXQBBgGwgBPIAAF2OzAAAAEAAAcAAgBuEQQANhMCAHcAAACGoKAAABMjoJAAABLxsFAQMAABBeAC9HsHAAABAAEAfww=") \ No newline at end of file diff --git a/pr/255/docs/search.index/577580cd62c1.js b/pr/255/docs/search.index/577580cd62c1.js new file mode 100644 index 000000000..face2e92c --- /dev/null +++ b/pr/255/docs/search.index/577580cd62c1.js @@ -0,0 +1 @@ +rn_("AQQA82sRAAABAAEAAYICsEASTwABsEASUQABNDYBBgD0FhQAAAEACgABAPMCAXIBghMAAPMCAWX0KRAAAAEAqAABABOAAqBQAAASgWR00wCEsLATnwABEQEB95EQAAABAG8AHQABAAEAJAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/57f124ccc65e.js b/pr/255/docs/search.index/57f124ccc65e.js new file mode 100644 index 000000000..a00c94103 --- /dev/null +++ b/pr/255/docs/search.index/57f124ccc65e.js @@ -0,0 +1 @@ +rn_("AQIA9VARAAABAAEAAQABAAGAArBgEpgAAaAgAAAQom95AQABoMAAABOoafTpEgAABwAXABsAAQMAOzAAAAEAAAUAAQAIEwUAAQYA9AsUAAABAAEAAQABAgD0oBAAAAEAnAABAAECAaBAAAASwXI7MAAAAQAABwACAJ4QAQA3EQUA84ACYW9nBwAAh7CAEsAAVbCgEzAAAQwwBzswAAABAAAOAAQARAQFADEMAABjEQMANxIDAKOAhKDwAAATQKBQAAAP/JQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/57fa81511bf9.js b/pr/255/docs/search.index/57fa81511bf9.js new file mode 100644 index 000000000..1dfc5bd11 --- /dev/null +++ b/pr/255/docs/search.index/57fa81511bf9.js @@ -0,0 +1 @@ +rn_("AYACoFAAABDooFAAABIgYXUBgwKxABQfAAGw0BQRAAFrbQEEAaCgAAAUKnfyGhQAAAEAAQsA848TAAABAAEAI4ACoIAAABO1ZW9jAwOgYAAAE05lbnABOAwAACOAAqBAAAAQeG1wAQoA83ITAAABAG0AE4ACohAAABQqbG/3AAAAhaEAAAAT4gSBAzswAAABAAA7AAQALwYFALEHAAABCDMAKBEAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5833b407ef6d.js b/pr/255/docs/search.index/5833b407ef6d.js new file mode 100644 index 000000000..117c1197e --- /dev/null +++ b/pr/255/docs/search.index/5833b407ef6d.js @@ -0,0 +1 @@ +rn_("AQAA9FMQAAABAAEAAQDzAgFz9ZQJAAABAAEAAQDvBQEGAPSfEQAAAQABAAEAAQEAOzAAAAEAAAYAAQAjFAYA8wYBZfTYEwAAAQAuAAEAEwYDsEAUAAABoGAAABOBYXJ1ASUQAADzgAJhZQEDAPRbEQAAAQABAAEAAQIA9HsPAAABAA8EAQABgAOwAAfZAAGgAAAADC2wcBAyAAFucnOnBwAAh6BwAAARnrBwEn8AAZEFQTowAAABAAAAAAAMABAAAAC8Ab0BvgG/AdsHRAhFCJ0JZwy0D7UPtg++EA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/58539c8b579b.js b/pr/255/docs/search.index/58539c8b579b.js new file mode 100644 index 000000000..ab96c4f58 --- /dev/null +++ b/pr/255/docs/search.index/58539c8b579b.js @@ -0,0 +1 @@ +rn_("AQIAOzAAAAEAAAUAAQD2EwUA8w0BbTswAAABAAAFAAEAtxMFAEcAAACFsAATyAABsEASTAABoQAAABP8oAAAABOBOAgCOzAAAAEAABgABgAWDAMA1RAHAG0SAQDgEgQArxMEABkUAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/587c8d82fabf.js b/pr/255/docs/search.index/587c8d82fabf.js deleted file mode 100644 index e7a8f25af..000000000 --- a/pr/255/docs/search.index/587c8d82fabf.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAUAAQCGEgUAAQAA9S0MAAABAAEAAQABAPOAAmdrE4ACsLAS3gABYW8BgAKgIAAAC72wYBCAAAFlaQGFArBwEwYAAbAwEmMAAWVzEwADsEAPDgABoGAAABC0YmVzOzAAAAEAABIABADyBQEA+AYKAIMPAQDUDwMAAQMA9J4PAAABAAQAAQABCwGgQAAAE01l8mwTAAABAPOAAmRy8wACZW87MAAAAQAABwACAMMHAwAECAMAAQIAOzAAAAEAAAgAAQC0CwgA84ACb3QBAwA7MAAAAQAA1gACAJ4HAADeCtUAAQIBoHAAABEfaTswAAABAADoAAIAnQcAAPYJ5wATgAKgQAAAC+xydQEEAPRDEgAAAQCOAAEAAQMA89oRAAABAJoA84ACYW/XBwAAiLBADKAAAbEwE2kAATSBFjswAAABAAAdAAwAHgUBAMsFAQDFCwAA8QsHABQMAQAcDwEA/g8BAIsQAADZEAMAFhEBABISAQCOEwEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/588805b23add.js b/pr/255/docs/search.index/588805b23add.js new file mode 100644 index 000000000..8767efd79 --- /dev/null +++ b/pr/255/docs/search.index/588805b23add.js @@ -0,0 +1 @@ +rn_("AYQCoCAAABDJoDAAABExaXQBAQA7MAAAAQAAfAACANQHAADBCXsAYwADsAAB7QABZGVsOjAAAAEAAAAAAAcAEAAAAD8F/AX9Bf4F2AfnEA8TEBM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/590f4c9d8e22.js b/pr/255/docs/search.index/590f4c9d8e22.js new file mode 100644 index 000000000..75b2838b7 --- /dev/null +++ b/pr/255/docs/search.index/590f4c9d8e22.js @@ -0,0 +1 @@ +rn_("AQcA9J8RAAABAAEAAQAjAAKgcAAAEZ5hcgHbBwAAAQAA9sIQAAABAFMDAQAKAAEAAQAAOzAAAAEAAAYAAgACEwAAZxMFACOIArBAE9UAAWVzAQ0BsEATzwABZfWXEwAAAQABAAEAAQABBQA7MAAAAQAACAADAJgRAgCGEgQAlhMAANcDAACGa9tI9uj+FIQG9UkFAAABAIgHAQABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/59c419e706d0.js b/pr/255/docs/search.index/59c419e706d0.js deleted file mode 100644 index 99e5ed616..000000000 --- a/pr/255/docs/search.index/59c419e706d0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsAAPVQABsCAMFgABZWkBiQKwIBNZAAGgMAAAE2JpcBMAA6AgAAASKKCAAAASO2VpdfXRCwAAMgABAAEAAQABhgKwkBN9AAGgAAAAEcJiZAGAArAwEhwAAaAwAAAQH3J2cwCEoDAAABJwEAATOjAAAAEAAAAAAAoAEAAAAAwJDQkOCT4JPwnbC7QPuQ9wEHEQ/xFjgAOgEAAACQFkbXQ=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a23f547788d.js b/pr/255/docs/search.index/5a23f547788d.js new file mode 100644 index 000000000..300e99974 --- /dev/null +++ b/pr/255/docs/search.index/5a23f547788d.js @@ -0,0 +1 @@ +rn_("AYMCsQAUHwABsNAUEQABa20BCgDzchMAAAEAbQATgAKiEAAAFCpsbzMBhKBgAAASIKEAAAAT4gSAAzswAAABAAA0AAIAsQcAAAEIMwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a45b3b18493.js b/pr/255/docs/search.index/5a45b3b18493.js new file mode 100644 index 000000000..82c11c6e0 --- /dev/null +++ b/pr/255/docs/search.index/5a45b3b18493.js @@ -0,0 +1 @@ +rn_("AQgA9CEQAAABAKkAAQABAAGggAAAFBlm8k0JAADBCQEHAPXgEgAAAQABAAEAAQAjgAKgUAAAEQZhb/MCAmZzOzAAAAEAAAgABACvBwAA4QcFAAcNAAA/EQAAM4ADoEAAAAwnYWVv") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a5100ed4a84.js b/pr/255/docs/search.index/5a5100ed4a84.js deleted file mode 100644 index 0180853c8..000000000 --- a/pr/255/docs/search.index/5a5100ed4a84.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQsBoEAAABMmZfJQEwAAAQABBQD0IxEAAAEAAQABAAGDArAAEBYAAbBQEnEAAWR3E4ACoKAAABLhZXYBAgD0MRAAAAEAdQEBAAEAAPQnDwAAAQDmAAMBI4ICsFASTgABZXMBAgD0IBIAAAEAiQABAAEDAPRUEgAAAQCOAAEA84UCYnUBAgD0nBAAAAEAWgEBAPOAAmls8wADYnR1OjAAAAEAAAAAAA8AEAAAAJoHJQgmCCcIKAhNDwUQoRIbE2UTZhNoE3MTdBOXE5sTAQwA8wMTAAABAAEAAQYA9B4SAAABAIkAAQDzAwFi9C8QAAABAHUBAQAXBgAAh7BADyUAAaBwAAARsbAQCSsAAbCQEkwAATgJAzowAAABAAAAAAAhABAAAAAKBgsGDAZfB2AHnAydDJ4MogyjDKQMHg8fD28PcA90D3UPkQ+SD5MPlA+VD5YPlw/TDwAQARCBEqUSyRJcE2cThROUEwEDAPQyEgAAAQA7AQEA84ACY213AQCAxbGAE6QAAUCBBAg=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a6385e2310f.js b/pr/255/docs/search.index/5a6385e2310f.js new file mode 100644 index 000000000..06def5abc --- /dev/null +++ b/pr/255/docs/search.index/5a6385e2310f.js @@ -0,0 +1 @@ +rn_("AQQA9g0NAAABAOkCAQAkAQEAAQoA81wSAAABAJoAAQEA93IJAAABALQGAQBrAAEADwEjgAKwYBNgAAFpbwECAPTPDAAAAQDIBQEAAQUA9HYTAAABAEYAAQD3CAAAiLCQEzAAAaAgAAAM0bCQEZYAAQTcAzowAAABAAAAAAAIABAAAAAKBmIJYwl0DHUMoxCkEIsSjBI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a77bebba663.js b/pr/255/docs/search.index/5a77bebba663.js deleted file mode 100644 index 15f4e2199..000000000 --- a/pr/255/docs/search.index/5a77bebba663.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9BISAAABAHsBAQATAgKwYBIUAAFmbfKHDAAAAQAjggKwQBI8AAFlbAEFAPT0EgAAAQBHAAEA8wMBY/IJEgAAAQABgQKgAAAACT2gMAAADw1zdBOAAqAQAAAHd25404CEsHATnAABkEAB") \ No newline at end of file diff --git a/pr/255/docs/search.index/5a813a4820e0.js b/pr/255/docs/search.index/5a813a4820e0.js new file mode 100644 index 000000000..25c0f0dc4 --- /dev/null +++ b/pr/255/docs/search.index/5a813a4820e0.js @@ -0,0 +1 @@ +rn_("AQQBsAASpgABczswAAABAAALAAIAGhMHAAIUAwBHAAAEhqCAAAAS+7EAFA8AAbBAEmkAAbCAFB0AAbBQEqgAARUAFvRwDgAAAQABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/5ae4a918d2e4.js b/pr/255/docs/search.index/5ae4a918d2e4.js new file mode 100644 index 000000000..fc0296e1d --- /dev/null +++ b/pr/255/docs/search.index/5ae4a918d2e4.js @@ -0,0 +1 @@ +rn_("AQkA8+YTAAABADUAAYACsCATiwABoCAAAA+GaXkBCQGggAAAFBlmAQ4TAAABAwGwABOeAEtzAUsTAAAjgAKgIAAAD4JhcgECAPV9EAAAAQABADkCAQDzAANpdHU6MAAAAQAAAAAADQAQAAAA4Ad/CeUPWxB2EqYSpxJPE1ATVhN/E4ATnBOdEwGAArBAEIEAAaAgAAATymN0E4ACsLATKAABYWwBDAGgoAAAFCp38hoUAAABAAEBAPOoDwAAAQABAPOAAnR1AQMA80kSAAABAAEAAQEA9eEQAAABAAEAAQABACOAArCQE3gAAWF0AQQBoEAAABPOZfLtEwAAAQABAgA7MAAAAQAACwAFAAUQBQBYEgEAchMBAMETAADgEwAAE4ICsPAUHQABZmcBgQKwgBP0AAGgYAAAFBhkcwEIAPWvEwAAAQABAAEAAQDzAgFm9UAQAAABAAEAAQABACOAA6AgAAAPgLCgE/IAAWRydHfvAQCNsBATqQABsOATqwABl9UOOzAAAAEAABEBEgA2BAEAPAUCABoGAgAlBwQAUAgDAD0MAgBoDAEA5wwBAHcO4ACeDwEAXBABAG0QAgCaEAEALxEAAIYRAQBoEgAAGhMHAAIUAwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5c2e611e8037.js b/pr/255/docs/search.index/5c2e611e8037.js deleted file mode 100644 index 8d36974f8..000000000 --- a/pr/255/docs/search.index/5c2e611e8037.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYAOzAAAAEAAAkAAQB2EAkAAQIAOzAAAAEAABMAAQBXDxMAE4GEoFAAABA3oBAAAAvioCAAAAyVHEAAE4ACsFASdwABYW4zgAOwMA8CAAFpc3Q=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5c64021fc741.js b/pr/255/docs/search.index/5c64021fc741.js new file mode 100644 index 000000000..213a4879a --- /dev/null +++ b/pr/255/docs/search.index/5c64021fc741.js @@ -0,0 +1 @@ +rn_("AQIBsIASyQABdvS5CQAAAQC2CQEA8wABYwF1EgAAAQICoLAAABPBoLAAABPCY3PzchAAAAEAXgABgQKwUBGQAAGgwAAAE5RoafOCAmVp84ACZW8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5cc356801927.js b/pr/255/docs/search.index/5cc356801927.js deleted file mode 100644 index 1b7993fd6..000000000 --- a/pr/255/docs/search.index/5cc356801927.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsIASZQABdfJQCQAAAQAjgAKwEAlOAAEzNgECAPRKCQAAAQAjBwEAAQIA8wkMAAABAAEAE4ACsBAJSAABaXUBAgA7MAAAAQAACwACAMMSBQB1EwUA8wkBbTswAAABAAAMAAMAlRAAAO0RBQA2EwUAdyAAAIqgMAAAEtmwMBCxAAGgcAAAER+gIAAACUywMBDlAAGwIAd6AdOzhQo7MAAAAQAABAIEAMIBAADmARoBnQcAAPYJ5wA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/5d03104f5b36.js b/pr/255/docs/search.index/5d03104f5b36.js deleted file mode 100644 index f523a7ad1..000000000 --- a/pr/255/docs/search.index/5d03104f5b36.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoEAAABCwc/XuCwAAmQQsAQEAAQATggKgIAAADK9lcgECAPQjDwAAAQDoAAEAI4ECoBAAAAvtZWkTgAKg8AAAExJucjMAA7AwCTcAAWVvdAH/EAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/5d359e55eab7.js b/pr/255/docs/search.index/5d359e55eab7.js new file mode 100644 index 000000000..6ba04bd57 --- /dev/null +++ b/pr/255/docs/search.index/5d359e55eab7.js @@ -0,0 +1 @@ +rn_("AYMCoJAAABOjoJAAABOkMjMBgAKgUAAAE8uggAAAEvhjZfMAAnN08qAHAAABAAEAAaCwAAATP2Lz0xIAABcBAQAjgAKwAA+iAzBkcgEAAbCAE6kAAXDypRMAAAEAQwADoCAAABEDoEAAABJAZGVz86cPAAAcAwEAE4ICoCAAABOVZWnzgAJjZQEEADswAAABAAAJAAQAqgkBAEUQAwCDEAEAYBMBALOAhKCQAAAT/BABQg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5dcae36ab7a9.js b/pr/255/docs/search.index/5dcae36ab7a9.js deleted file mode 100644 index a8af7241f..000000000 --- a/pr/255/docs/search.index/5dcae36ab7a9.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQACoCAAABKEsDARDAABaXTy+REAAAEAAQMAOzAAAAEAAAYAAQCMEAYAAQgA9OsSAAABAH8ABQATAQOwkBNLAAGwUBI6AU9nbHA7MAAAAQAAEgAJAJsPAgAPEQEAKRIBAEoSAQB7EgEA3BIBAA8TAQAeEwEAXRMBAAGAArAwEQgAAbAwEQoAAXJ2AQQBsAARvwABZDswAAABAAAFAAIABBEDAOkRAQC3BQABh7BQEcEA/bBgEjgAAZQJAzswAAABAAAKAAUAhAwCAAgOAQAzEAAAthADADASAAAjgAKgEAAADINubwEDAPOYDwAAAQABACOAAqAAAAALz2RyYwCEoFAAABCzoDAAAA/PFAEQ8sEHAAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5dd964887ac3.js b/pr/255/docs/search.index/5dd964887ac3.js new file mode 100644 index 000000000..8a7fef51e --- /dev/null +++ b/pr/255/docs/search.index/5dd964887ac3.js @@ -0,0 +1 @@ +rn_("AQEBsFAPiQABY/QrBQAAAQABALUAAQABoIAAABQZZgEOEwAA8wYBc/IHDQAAOAQzAAOgYAAAE/1jaXPyeREAAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/5e27fec6e119.js b/pr/255/docs/search.index/5e27fec6e119.js deleted file mode 100644 index b2b9bb58f..000000000 --- a/pr/255/docs/search.index/5e27fec6e119.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYAOzAAAAEAAAkAAQB2EAkAI4ADsGASdwABsDAPAgABaXN0AQgA9S4TAAABAAEAAQABAPMBAWb1xQ8AAAEAAQABAAEAY4ADoDAAABI/ZWd0") \ No newline at end of file diff --git a/pr/255/docs/search.index/5e990d199296.js b/pr/255/docs/search.index/5e990d199296.js deleted file mode 100644 index 56eec354f..000000000 --- a/pr/255/docs/search.index/5e990d199296.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYAOzAAAAEAAAUAAQBYEgUAg4YEsFASIgABsHASggABoNAAABNWYm5vdhOAArAQEfsAAXByAQABoDAAABERdAGhEgAA8wIBc/LTDwAA0gITgAKgYAAAD8RldQECAPatDAAAAQDPAgEAIgEBAAGAArAAEecAAYAOBzBQAWVzAQEA84AHAAD3CgEAY4ADsIAS8gABYm5084ADYW9yARQA9IETAAABAAEAAQABAAA7MAAAAQAABgACAIASAADlEgUAI4gCsEATVAABZXMBBAGwMBJWAAFj860QAAABAAEAAQUAOzAAAAEAAAgAAwAcEQIABBIEABMTAADzAgNjZXDzdAwAAAEAAQBjgAOgYAAADyllb3UBAAGwYBL9AAFlATMTAADzAgFz9jQJAAABAAEANwc+AAUBAQgA88cRAAABAAEAQ4ADoBAAABKEoOAAABMIZG9zAQIBoFAAABCscgFNEAAAAYACoEAAAA/QoHAAABNBYWUBAAA7MAAAAQAACwACACQHBQDgEQUA84ACdHYBAQD0FggAAAEAAQABAPMAAm5y9ioJAABQADYGAQCxAAEA8wCHMJEM9fkRAAABAHkAAQDtAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5f3aaa0e45e4.js b/pr/255/docs/search.index/5f3aaa0e45e4.js deleted file mode 100644 index 1f6e97293..000000000 --- a/pr/255/docs/search.index/5f3aaa0e45e4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoFAAABBtoFAAABGfYXUBgwKxABOeAAGw0BOQAAFrbQEEAaCgAAATqXfymRMAAAEAAYACoIAAABM0sLATDQABZW9jAwOgYAAAEsxlbnAB3wsAACOAAqBAAAAP/W1wAQoA8/ASAAABAG4AE4ACohAAABOpbG/3AAAAhaEAAAATYQSBAzswAAABAAA7AAQAAQYFAHgHAADHBzMArBAAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/5f5fc12a19de.js b/pr/255/docs/search.index/5f5fc12a19de.js deleted file mode 100644 index 93c9c759d..000000000 --- a/pr/255/docs/search.index/5f5fc12a19de.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICoFAAABHmoQAAABN8Y3QjAAKwQA8LAAFldTswAAABAAA3ABYA9gYBAMsLAQCaDAEAEA8BAIsPBQC6DwUANBABAJMQAQAcEQIA1hEDAAQSBAAuEgEANBIBAEMSAQC/EgEA0hIBAPASAQD0EgEAExMAADwTAQBAEwEAXxMAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/602d50ba42fc.js b/pr/255/docs/search.index/602d50ba42fc.js deleted file mode 100644 index 2dac2e2f0..000000000 --- a/pr/255/docs/search.index/602d50ba42fc.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoCAAAA8JoDAAABLJYXLzAAF0AaYHAAABBAGgQAAAE01l8mwTAAABAAEFADswAAABAAALAAUAiw8FANYRAQDwEgEAQBMAAF8TAADjAISgMAAADweFAAI7MAAAAQAACwAFAOwFAgDuBgQADwwBALMQAADmEQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/6043b7b1f86b.js b/pr/255/docs/search.index/6043b7b1f86b.js deleted file mode 100644 index 4a591b007..000000000 --- a/pr/255/docs/search.index/6043b7b1f86b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9GsPAAC5AgEArwDzAAFzOzAAAAEAABkACAAUBQIA5AsCACUPAQDhDwEAHxABAAoRAQCYEgcAgRMDACOAArEQE4YAAWF0") \ No newline at end of file diff --git a/pr/255/docs/search.index/60bbd1af8668.js b/pr/255/docs/search.index/60bbd1af8668.js deleted file mode 100644 index b28b234e3..000000000 --- a/pr/255/docs/search.index/60bbd1af8668.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9CsQAAABAAEAAQATgAKgsAAAEu1jcwEEAPP5DgAAAQABAAGAAqBQAAAP/aBgAAAQbWlyAYACoCAAAAwnoGAAABBsZWgBAQGgIAAAEGti8yMMAAABAAEAE4ECoBAAAAwmYWMBgAKgEAAAErmwMAyzAAFlcyMAAqBAAAATTWV38mwTAAABAAEGAPQSEgAAAQB7AQEAEwACsGASFAABZm3yhwwAAAEAAQEA9DgQAAABAKoAAQAjgAKgsAAAEtRkZwGCAqCgAAASQKBAAAAPpW9284ADZ25yAYACoEAAABINoDAAAA72aGy3HwAAibBADvcAATRAVzswAAABAAAYAAQAzgEAAPwDDQC0CwgAeAwAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/611bcb3d4014.js b/pr/255/docs/search.index/611bcb3d4014.js new file mode 100644 index 000000000..8f247e2c3 --- /dev/null +++ b/pr/255/docs/search.index/611bcb3d4014.js @@ -0,0 +1 @@ +rn_("AQsA9BgTAAABAA8AAQABBAGwQBLUAAFlAS4SAADzAAF0AcoTAAABDQDz4RMAADAAAQABEADzCRQAABYAAQDzgQNrbXMBAAA7MAAAAQAABgACAAITAABnEwUAI4YCsEAT1QABZXMBBAD0aRAAAAEAFwABAPOAA2NydDOAhLBgEIUAAaAQAAAGLAEICQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6133a24a21bd.js b/pr/255/docs/search.index/6133a24a21bd.js deleted file mode 100644 index 19db52b63..000000000 --- a/pr/255/docs/search.index/6133a24a21bd.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsRATfwABsBAMDAABZW8BBQA7MAAAAQAADQABAMQQDQABAgDzOw8AAAEAAQABAgD0Nw8AAAEAAQABAAEDADswAAABAAAIAAEA4w8IAIcHAACHsKAStwABsNATRAABoFAAABMRjBQR9X8HAACRCAEAAQABAPOBAmx08wABaTswAAABAAB4AAMAKwQAAB4QAAAoEXYAAQUA82UTAAABADUAAQABoEAAABAiZfMWCQAAAQCaCBOAAqAwAAAPFGRy8wABZfMcBwAAAQABAPOAAmh0AQEAOzAAAAEAAHcAAgAeEAAAKBF2ABOAAqBQAAAPVGl0AQgA9OsSAAABAH8ABQATAISw8BNnAC2wkBNLAAGwUBI6AU9AiQA7MAAAAQAAEgAJAJsPAgAPEQEAKRIBAEoSAQB7EgEA3BIBAA8TAQAeEwEAXRMBANcBAACGsIAQ3QABoEAAAAk5CDAmOjAAAAEAAAAAAA0AEAAAAH0AfgCJB3QJxAuyDDEQMhCnEagRIBIhEqoSqxI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/61b0c88b9449.js b/pr/255/docs/search.index/61b0c88b9449.js deleted file mode 100644 index d1f228cb1..000000000 --- a/pr/255/docs/search.index/61b0c88b9449.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEASrAABZfL0BgAAAQABBADzoA8AAAEAAQBDAAOwQBIaAAGxABLwAAFlZnA7MAAAAQAAIQAGAN0BAAADBwsAEAcLAN8OBQA3EAAAVhIBAGOAA7AwC9IAAWFlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/61d6cf934531.js b/pr/255/docs/search.index/61d6cf934531.js deleted file mode 100644 index 4a2f7cbd4..000000000 --- a/pr/255/docs/search.index/61d6cf934531.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgCAEgAA5RIFACOIArBAE1QAAWVzAQQBsDASVgABY/OtEAAAAQABAAEFADswAAABAAAIAAMAHBECAAQSBAATEwAA8wMDY2Vw83QMAAABAAEAAQABsGAS/QABZQEzEwAA8wIBc/Y0CQAAAQABADcHPgAFAQECAaBQAAAQrHIBTRAAAPOAA2ZtcA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/61e64371195c.js b/pr/255/docs/search.index/61e64371195c.js deleted file mode 100644 index 316f1059f..000000000 --- a/pr/255/docs/search.index/61e64371195c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9D0QAAABALkAAQATgQOgAAAAEIaxIBOGAAFhZG4BFAD1pBMAAAEAAQABAAEAAQYBsIATRwABdjswAAABAAAHAAIA8hAEALQSAgBXAAABhqDAAAASf6CgAAASoaCQAAASb7BQD7UAAQXgAvRCBwAAAQABADcMAQYA89oRAAABAJoAAQABoGAAAA8icgEfBAAA1wEAgMWgMAAAC84AAIoK") \ No newline at end of file diff --git a/pr/255/docs/search.index/61e80bc02385.js b/pr/255/docs/search.index/61e80bc02385.js deleted file mode 100644 index dbf6e7649..000000000 --- a/pr/255/docs/search.index/61e80bc02385.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEA9R4IAAABAAEAAQABAAEAAqAwAAAQQ6CQAAAShTBo9SIRAABtAQEAAQABABOAAqAwAAAPBmRyIwKEsBAJCALosCALxADuoDAAAA8qEgAY9eMFAAAuAAEAAQABADOAhLCgEdYAAbBADxAAARBJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/62030eb677af.js b/pr/255/docs/search.index/62030eb677af.js new file mode 100644 index 000000000..aa3b388e5 --- /dev/null +++ b/pr/255/docs/search.index/62030eb677af.js @@ -0,0 +1 @@ +rn_("AQEAOjAAAAEAAAAAAAkAEAAAAI4Pjw94EDYRdxJ4EmIT4RMRFBIUAYACsOATXAABsDATdAABZHDDgISxQBQhAAGgkAAAEyMCgAk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6373129d4310.js b/pr/255/docs/search.index/6373129d4310.js deleted file mode 100644 index 9d01fc7d1..000000000 --- a/pr/255/docs/search.index/6373129d4310.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCsQATngABsNATkAABa20BCgDz8BIAAAEAbgATgAKiEAAAE6lsbzMBhKBgAAARn6EAAAATYQSAAzswAAABAAA0AAIAeAcAAMcHMwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6383b6d7c4f5.js b/pr/255/docs/search.index/6383b6d7c4f5.js deleted file mode 100644 index 47b7c25f2..000000000 --- a/pr/255/docs/search.index/6383b6d7c4f5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9DQSAAABAIoAAQDzAAFj9YgPAAABALsAAQABAAEJAPNlEwAAAQA1AAENAaCgAAATqXfymRMAAAEAAYECsIATcwABoGAAABOXZHM3AQCEhaBAAAATSbBgExsATQKQCiOAAqBwAAAQh2RyAQsBoEAAABNNZfJsEwAAAQATgAKwMA+jAAFkcvMCAWX0BAgAAAEAAQABACOAArAgC8YAAWV5AQoA88cRAAABAAEAAQsAOzAAAAEAAAcAAQCYEgcAAQIA9PQSAAABAEcAAQC3AACAhbBwEfkAAbDQE44AAWAgBgEGAPPTEQAAAQABAAEDAbBAE2MAAXTyyhIAAAEAI4UCoEAAABL4YnMTAgKgUAAAEJhiZvcYCQAAAQBDAJQGAQBhAAEA84ACaXABBADzoA8AAAEAAQDzAAFwOzAAAAEAAAsAAQAQBwsAI4ADoDAAAAvTsHASrAABYWVp84ADZG1uAQAA9iIJAAD7AqIFAQBQAAEA8wIBZDswAAABAAAJAAMABBEDALoRAwDpEQEAI4ACoJAAABNAaW8BgAOwMBJlAAGAEqIAEAGwUBBHAAFjc3jzAAFlASgFAADnFQAAiaAAAAAMKqBAAAAMerBADHsAAZBIXQHTAQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/63a6d2637da3.js b/pr/255/docs/search.index/63a6d2637da3.js deleted file mode 100644 index 7b5cdec15..000000000 --- a/pr/255/docs/search.index/63a6d2637da3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9NgPAAABAAEAAQABAAA6MAAAAQAAAAAACgAQAAAAHA8dD/4P/w+LEBYRFxESEhMSjhOPE/MBAXny+xIAAAEAAYABD6dKNNM8bkOAA6AgAAAMeqAQAAAMg21ubwEDAPSYDwAAAQABAA8BAYACoLAAABMRsDASagABbnRDAAOgIAAAEEKwUBEUAAFlaGk7MAAAAQAABgADAM8LAAAjEQMAwRIBAPOAAmRyhwsAAAqAAbwAEAGAAb8AEAGgUAAAELOgUAAAE0agMAAAD8SgMAAAD88wMWNlaW9zdHV39cEHAAABAD4HqgJDAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/64129e8e0e98.js b/pr/255/docs/search.index/64129e8e0e98.js deleted file mode 100644 index 0cdd79ff2..000000000 --- a/pr/255/docs/search.index/64129e8e0e98.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBsAASJAABczswAAABAAALAAIAmBIHAIETAwBHAAABhqCAAAASebEAE44AAbBAEecAAbCAE5wAAbBQEiYAARUAFvQDDgAAAQABAAEAAQUA8zQPAAABAAEAY4CEsEAPtwABoAAAAAcPAPAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/642a5cb13021.js b/pr/255/docs/search.index/642a5cb13021.js new file mode 100644 index 000000000..f8b6a53a7 --- /dev/null +++ b/pr/255/docs/search.index/642a5cb13021.js @@ -0,0 +1 @@ +rn_("AQABoLAAABM/YvPTEgAAFwEBAAGAAqAgAAAPgqAwAAATS2Fy8wABdAHgBwAAAQQBoEAAABPOZfLtEwAAAQABBQA7MAAAAQAACwAFAAUQBQBYEgEAchMBAMETAADgEwAA4wGEoDAAAA+AhQACOzAAAAEAAAsABQAaBgIAJQcEAGgMAQAvEQAAaBIAAGOAA7AAD6IDMGRucg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6465615c7c4e.js b/pr/255/docs/search.index/6465615c7c4e.js new file mode 100644 index 000000000..28f3420ec --- /dev/null +++ b/pr/255/docs/search.index/6465615c7c4e.js @@ -0,0 +1 @@ +rn_("AQwBoKAAABQqd/IaFAAAAQABAQDzqA8AAAEAAQABiYSggAAAFBigQAAAE8qgYAAAE+mgkAAAFBwCgAoTgYSgoAAAE2KxoBQoAAGw0BPDAAEEAQnzgANhdHU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/64816476bdd2.js b/pr/255/docs/search.index/64816476bdd2.js new file mode 100644 index 000000000..fc09247d1 --- /dev/null +++ b/pr/255/docs/search.index/64816476bdd2.js @@ -0,0 +1 @@ +rn_("AQYA9DITAAABAAEAAQABDwD0CxQAAAEAAQABAAEAAbDwFBMAAWv1ihMAAAUAAQABACQAAQIA9CEQAAABAKkAAQD3AAAAhbEAFAAAAYkwAPJgEgAAAQATgAKwEAxlAAFlbwEFADswAAABAAANAAEAQBENAAECAPO0DwAAAQABAAECAPSwDwAAAQABAAEAAQMAOzAAAAEAAAgAAQBeEAgAAYACoAAAAAw7sDATzwABcXIBgAKgQAAAELKwwBPFAAFlcwEBADswAAABAAATAAEA0Q8TACOAArCQEzkAAWltdzYAAIqgUAAAE5SwcBN4AAGgIAAADPScVRE7MAAAAQAACQADALgHAACLEAMAlxMEAAECAbAwERoAAXABLBIAALOAhKAgAAARfwIoBA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/648a36bbbcb1.js b/pr/255/docs/search.index/648a36bbbcb1.js new file mode 100644 index 000000000..b0eaa0b87 --- /dev/null +++ b/pr/255/docs/search.index/648a36bbbcb1.js @@ -0,0 +1 @@ +rn_("AQgA9FwTAAABAFAAAQABAgGgYAAAE/1z8nkRAAABAAGAArAgD88AAaCQAAATtGFlAQcBsEATzwABZfWXEwAAAQABAAEAAQABAwGwQBPkAAF08kwTAAABACOFAqBAAAATemJzAQIA9HURAAABAAEAAQA3dAAAi7BAEy4AAaBQAAARE6CQAAATIrBQEo0AAaAwAAAMe7OYBzswAAABAABbABEA2wEBABcEAwA8BgAAKwcBAMMHAQBaCQEAZgkAAHEJAACeCQAAkww7AOEMAACcDwEAaxABAIcQAQDNEAEAUBEEAEUSAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/64a47a036ee9.js b/pr/255/docs/search.index/64a47a036ee9.js new file mode 100644 index 000000000..4972d4330 --- /dev/null +++ b/pr/255/docs/search.index/64a47a036ee9.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAAUAAQBiEgUAAQACsEATLgABoKAAABO0ZXI6MAAAAQAAAAAABwAQAAAAKwcsB8MHxAecD50PhxCIEFOAA6CgAAATlGdpcw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/64d11c8fb329.js b/pr/255/docs/search.index/64d11c8fb329.js new file mode 100644 index 000000000..c8ca8e518 --- /dev/null +++ b/pr/255/docs/search.index/64d11c8fb329.js @@ -0,0 +1 @@ +rn_("AQUBsEASTAABZfJtEgAAAQABggKgkAAAE6OgkAAAE6QyMwEAAqAgAAASKqAgAAAJS2ltOzAAAAEAAAwABgAmBQAAWwUFALUJAABnDwEAehMAAI0TAQDzAAFzAdQQAAABBQA7MAAAAQAABQABAAgTBQABAAD1hwwAAAEAAQABAAEA84ACZ2tzgISwsBNgAAERSAABBgGgQAAAEZVl8wgNAACzAwEAAYACoJAAABNvsFAQ+wABZ3oBgAOwUBOcAAGgEAAADBWgcAAAEvhnbnLHAQAAhaBgAAATe6BQAAATyxUBBDswAAABAAARAAQA0wEBAF4QCABbEQMASRICAAGFArBwE4gAAbAwEuUAAWVzEwADsEAPhwABoGAAABEwYmVzOzAAAAEAABIABAAgBgEALwcKAP0PAQBPEAMAAQMA9BkQAAABAAQAAQABCwGgQAAAE85l8u0TAAABAPOAAmRy8wACZW87MAAAAQAABwACAP0HAwA+CAMAAQIAOzAAAAEAAAkAAQALDAkAAQAA9FMQAAABAAEAAQABAQA7MAAAAQAA3gACAD0GAABlCN0AYwADsBASpAABZWlzOjAAAAEAAAAAAAwAEAAAAF0JlAmVCZYJlwkvDDAMXg9fD4YPohAEEwUT44CEsCAHugABEUAEAQGEsDAMHgABoEAAAAzYoIAAABECsEAM2QABAAAdAeIBAAABBQD1URMAAAEAAQBwAAEAE4ACoAAAAAdjYWcBAwD0IxIAAAEAVAEBAPOAAmlvAQEAOzAAAAEAAN4AAgDXBwAALQvdAAEIAbBAE88AAWX1lxMAAAEAAQABAAEA84ECZ3QBAQGgcAAAEZtpOzAAAAEAAPAAAgDWBwAAPQrvAAEFAPNtEAAAAQABAPOAAmFvE4ACoEAAAAxFcnUBgAKgAAAAB7ygEAAACVxkeBMAArAgDP8AAWVy8sgPAAABABOAArCwFBMAAXJ4AQoA9BETAAABAAEAAQATgAKwEBC2AhVhZQEEAPRPEAAAAQABAAEAAQQAOjAAAAEAAAAAAAcAEAAAALYStxLFEsYSQRNCE1QTVRMBBAD0phAAAAEAAQABAAEDAPNcEgAAAQCaAPOAhAFIAce/AwCPoIAAABJesGAM7wABsEAMbQABsTAT6gABP6kfOzAAAAEAAE0AIwBoAAAAbAAAAEcFAQBQBQAA+QUBAKAHAQCqBwEAsgcAALYHAQCOCQAAoQkHALcJAQAdDAAAMgwBADkMAQBKDAcAbQwBAIUMAQDPDAEAlQ8BAAIQAQB5EAEAhRABAJ0QAAC/EAIAzxABAOEQBAAGEQAAVREDAJIRAQA7EgAAlBIBAJgSAQDBEgAADxQBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/64e752cb7ef8.js b/pr/255/docs/search.index/64e752cb7ef8.js new file mode 100644 index 000000000..36769a04c --- /dev/null +++ b/pr/255/docs/search.index/64e752cb7ef8.js @@ -0,0 +1 @@ +rn_("AQYA9FwTAAABAFAAAQAjgAKhEAAAFApjchOAAqAgAAAJXWh5AQEBoGAAABP9c/J5EQAAAQAjgAKwIAm9AAFldQGAArAgD88AAaCQAAATtGFlAQcBsEATzwABZfWXEwAAAQABAAEAAQABBAGwABKmAAFzOzAAAAEAAAsAAgAaEwcAAhQDAEcAAASGoIAAABL7sQAUDwABsEASaQABsIAUHQABsFASqAABFQAW9HAOAAABAAEAAQCDAISgAAAAE3ywQBQTAAGwMBMuAAFIAAP3QgUAAHELAQClAAEABQABAAEDAbBAE+QAAXTyTBMAAAEAI4UCoEAAABN6YnMBAQD0dREAAAEAAQABABOAAqAQAAAJfmRst+gAAIyg0AAAEwagUAAAEROgkAAAEyKwUBKNAAGgMAAADHu3mAc7MAAAAQAAXgATANUBAQDbAQEAFwQDADwGAAArBwEAwwcBANUHAABaCQEAZgkAAHEJAACeCQAAkww7AOEMAACcDwEAaxABAIcQAQDNEAEAUBEEAEUSAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/64eb9b668729.js b/pr/255/docs/search.index/64eb9b668729.js new file mode 100644 index 000000000..2a28b5160 --- /dev/null +++ b/pr/255/docs/search.index/64eb9b668729.js @@ -0,0 +1 @@ +rn_("AQUA9HYTAAABAEYAAQDzAwFj8osSAAABACOAArBwFB0AAWhvAYICsAASaQABsAARiAABZXNDAAOgoAAAE8KgIAAAEwZlaXT1exIAAAEAeQABAOwAAYECoEAAABL8sEASugABYWYBgAKwcBJgAAGgsAAAE4plbwECADswAAABAAAGAAEABxEGAAECAaBAAAATp2Xy0RMAAAEA84ACaW8BCAD0bRMAAAEAfgAFABMBA7CQE8wAAbBQErwBTmdscDswAAABAAASAAkAFRACAIsRAQCrEgEAzBIBAP0SAQBeEwEAkhMBAKETAQDeEwEAAYACsEASQwD9oCAAABDKYWkBgQKwMBN9AAGgMAAAEl9jaQEDAbAAEqYAAXM7MAAAAQAADQADAIYRAQAaEwcAAhQDAAEDAPWEEQAAAQALAQEARgHzgAJydgEAAPRBEgAAAQBQAAEA8wIBZDswAAABAAAJAAMAgBEDADwSAwBrEgEAI4ACoJAAABPBaW8TgAKw8BQPAAFsbwEFAPTdEwAACwAeAA8AI4ACoGAAABL7Z3MjgAKwkBO/AAFibPeXAwCPsHARnAABsGAT8gABsHATcAABsFASqAABtfkXOzAAAAEAADsAFwArBgAAzAcBAEQJBQBUCQAAggkAACkMAABvDAEA4gwCAAsNAQBwDgMAdQ4BAKsPBAByEAEArhAAANEQAADxEAkAMBEAADIRAwB+EQAAshIAAMkSAQDaEgUAlRMAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/65694b9e3122.js b/pr/255/docs/search.index/65694b9e3122.js new file mode 100644 index 000000000..9710192a4 --- /dev/null +++ b/pr/255/docs/search.index/65694b9e3122.js @@ -0,0 +1 @@ +rn_("AYACsRAUAAABsBAMZQABZW8BBQA7MAAAAQAADQABAEARDQABAgDztA8AAAEAAQABAgD0sA8AAAEAAQABAAEDADswAAABAAAIAAEAXhAIAIcHAACHsKATOQABsNATxQABoFAAABOUjBQR9bgHAADTCAEAAQABAPOBAmx08wABaTswAAABAAB9AAMASwQAAJkQAACkEXsAAQUA8+YTAAABADUAAQABoEAAABCdZfNYCQAAAQDZCBOAAqAwAAAPjWRy8wABZfNVBwAAAQABAPOAAmh0AQEAOzAAAAEAAHwAAgCZEAAApBF7ABOAAqBQAAAPzml0AQgA9G0TAAABAH4ABQATAISw8BPoAC2wkBPMAAGwUBK8AU5AiQA7MAAAAQAAEgAJABUQAgCLEQEAqxIBAMwSAQD9EgEAXhMBAJITAQChEwEA3hMBANcBAACGsIARWQABoEAAAAl7CDAmOjAAAAEAAAAAAA0AEAAAAIEAggDCB7YJHAwSDawQrRAoEikSohKjEiwTLRM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/657321230ec5.js b/pr/255/docs/search.index/657321230ec5.js deleted file mode 100644 index bd1f1a945..000000000 --- a/pr/255/docs/search.index/657321230ec5.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAHcAAgAeEAAAKBF2AAEAAbBwErsAAWXyGA8AAAEA8wABc/SADwAAAQD+AwEAM4ADoGAAABDSZGlv") \ No newline at end of file diff --git a/pr/255/docs/search.index/659cd1b8f458.js b/pr/255/docs/search.index/659cd1b8f458.js deleted file mode 100644 index 3b343bf58..000000000 --- a/pr/255/docs/search.index/659cd1b8f458.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9LASAAABAAEAAQABDwD0ihMAAAEAAQABAPOHAmhtAQQBsAASEAABZPS6EQAAAQABAAEAI4eEsKATPgABsEASDgABsHAS7gABFYAAAQABoEAAAA/CZTswAAABAAAGAAIAlQcEACMIAQATgAKwUA+AAAFkcgEJAPXPEgAAAQABAHEAAQC3AgCAhrAgEcMAAVU1iV1+GhFJAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/65b95eb2cbb1.js b/pr/255/docs/search.index/65b95eb2cbb1.js deleted file mode 100644 index 0b2736f43..000000000 --- a/pr/255/docs/search.index/65b95eb2cbb1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYIBfODbmy34dAEAAbBgEv0AAWUBMxMAAPMCAXP2NAkAAAEAAQA3Bz4ABQEBAgGgUAAAEKxyAU0QAADzgANmbXA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/65e587e4fe56.js b/pr/255/docs/search.index/65e587e4fe56.js new file mode 100644 index 000000000..a7ae4ae8c --- /dev/null +++ b/pr/255/docs/search.index/65e587e4fe56.js @@ -0,0 +1 @@ +rn_("AYACoIAAABJesHATnAABYXMBAAGggAAAFBlm8k0JAADBCQEHAPXgEgAAAQABAAEAAQAjgAKgUAAAEQZhb/MAAmZzOzAAAAEAAAgABACvBwAA4QcFAAcNAAA/EQAA84ACZHk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/65f055028fa9.js b/pr/255/docs/search.index/65f055028fa9.js new file mode 100644 index 000000000..fd5cb46e4 --- /dev/null +++ b/pr/255/docs/search.index/65f055028fa9.js @@ -0,0 +1 @@ +rn_("AYMCsCARJwEKoJAAABOWbXABggKwoBOLAAGwoBONAAFjcgECAaBAAAARJmUB6A8AADOAhLAgEKMAAbAgD2oAAVAUAPOAAm9y") \ No newline at end of file diff --git a/pr/255/docs/search.index/66080551a4d4.js b/pr/255/docs/search.index/66080551a4d4.js deleted file mode 100644 index e86576487..000000000 --- a/pr/255/docs/search.index/66080551a4d4.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoAAAABLUcwEgEAAAAYACsDAPtQABsFAPtwABYWkBgAKgsAAAE1ugMAAAEExsbhcBAACFoCAAABGpoCAAAAkJsIATKAABEJEEOjAAAAEAAAAAABAAEAAAAP4EMgUzBTQFNQU2BTcFcwnuDu8ORhL4Ev8SCxMMEyQTJRMBAgA6MAAAAQAAAAAACgAQAAAAXQleCVQPaBJpEpQSlRI1E4gTnhOfEwEAADswAAABAAAGAAIAgBIAAOUSBQABAgGwMBJWAAFjOjAAAAEAAAAAABMAEAAAAJ8MBg+YD5kPmg+eD58Pow+kDzYQqRCtEK4QrxAfEUwSTRImE0sTTBMBggKwMBMcAAGwQBCWAAFhZQEBAbBAE04AAWX1FBMAAAEAAQABAAEAE4ACoBAAAAvQYW/HBwAAx7BAE1QAAaCAAAARpABMiAnyHAgAALgDAYACoIAAABJvoJAAABJJYWsBAwDzxxEAAAEAAQAjgISxIBOcAAGgAAAACT2gMAAADw0EBAYBCAD1pBMAAAEAAQABAAEAE4oCsEATfwABYXKTAISgwAAAEkWhAAAAEwgBQAbynwcAAAEAAQMBoEAAABEZZfOoDAAAmAMBAAEFAPSwEgAAAQABAAEAU4ADsAASagABZXN0AQYA9IoTAAABAAEAAQDzCAFt9LYRAAABAAEAAQABAgA7MAAAAQAABQABAHUTBQDzDQFtOzAAAAEAAAUAAQA2EwUAAQQA97AMAAABAA0FDAABAIMAAQABAwGAEnMAEO1zOzAAAAEAAAUAAQBYEgUAI4ICoJAAABNKaXMBgAKgsAAAExGwMBJqAAFudAGAAqCAAAAShbBAERQAAWFlAYACoBAAABBCoAAAABCIbnIBCQGgQAAAE01l8mwTAAABACOAAqCQAAASumlsxyMAAAqgMAAAEEOwUBIiAAGw8BOSAAGwcBKCAAGg0AAAE1YwYmNlaGlrbm92OzAAAAEAABgACwDPCwAAGhADACIRBAB/EgAAjxIDAMESAQAIEwAADRMBACgTAQA0EwAARxMBAAECAqCwAAATQKCwAAATQWNz8/cPAAABAF4AAQECsFARFAABoMAAABMRaGnywRIAAAEA84ACZWkBAQGgkAAAEn9z9NwPAAABAAEAAQABAwGwABAUAAFzAYcPAADzgANoaXQBAQGgUAAAEg1jAXgMAAABBQGwgBNHAAF2OzAAAAEAAAcAAgDyEAQAtBICAAEBAPSmDwAAAQCpAAEA84ADY2Rs92UPANGwkBGiAAGgUAAAEDuhAAAAE3ugoAAAEqGgEAAAB3dAP78pOzAAAAEAADcAFgAlBQEA4AUCAEIHAgC+CwMAewwBAPkOAgAIDwAALg8AAFUPAQBZEAgAsBAAAN4RAQDnEQEA6xEBAEESAQBeEgQArhIBALcSAQC6EgAALhMEAHsTAACYEwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/660ac0c7b41d.js b/pr/255/docs/search.index/660ac0c7b41d.js deleted file mode 100644 index 1aca980a1..000000000 --- a/pr/255/docs/search.index/660ac0c7b41d.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBoEAAABMmZfJQEwAAAQABBAGwABIQAAFk9LoRAAABAAEAAQCnAAAChbCgEz4AAbBAEg4AAbBwEu4AARWIAAESEwAAAQABsIATKAABcPIkEwAAAQBDAAOgIAAAEIigQAAAEb5kZXPzLg8AABMDAQDzgAJlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/663d3ccd45e8.js b/pr/255/docs/search.index/663d3ccd45e8.js deleted file mode 100644 index 95003c14d..000000000 --- a/pr/255/docs/search.index/663d3ccd45e8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYADsAAS1QABsAAS1wABsHATRwABNDZhAQQA9JUTAAABAAoAAQAjgQKgQAAAEIZtcAEBADswAAABAAAIAAMA3BEAAEUSAACiEwYAxwEAAMWgQAAAD4qgYAAAEvpABYAIOzAAAAEAABYACAArDwEAPRABAIIQAwDyEAYAtBICAAATAABXEwEAhhMBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/672d94eeb5ad.js b/pr/255/docs/search.index/672d94eeb5ad.js deleted file mode 100644 index 468c9dd2f..000000000 --- a/pr/255/docs/search.index/672d94eeb5ad.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9CMRAAABAAEAAQAjAQKgcAAAESJhcgGhBwAAAQMAOzAAAAEAAAcAAgDfDgUAVhIBAPMAAmN0OzAAAAEAAFcAJgAIBQsAtwUBAB4JAQDjCwAA6QsCAJQMAACfDAIAsAwBAAYPAAALDwEADg8BABQPAACYDwIAng8BAKMPAQDCDwAANhAAADwQAACJEAEAlhABAKkQAQCtEAIACBEBABkRAgAfEQAAvhEAAMURAQDKEQEADhIBABoSAwA8EgEATBIDAFISAQCsEgEAvRIAACYTAABLEwQAVBMCAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/678443ae36ae.js b/pr/255/docs/search.index/678443ae36ae.js new file mode 100644 index 000000000..8d4fdc442 --- /dev/null +++ b/pr/255/docs/search.index/678443ae36ae.js @@ -0,0 +1 @@ +rn_("AQMBoEAAABOnZfLREwAAAQABBAGwABKSAAFk9DwSAAABAAEAAQCnAAAChbCgE78AAbBAEpAAAbBwE3AAARWIAAGVEwAAAQABsIATqQABcPKlEwAAAQBDAAOgIAAAEQOgQAAAEkBkZXPzpw8AABwDAQDzgAJlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/679d38ece98b.js b/pr/255/docs/search.index/679d38ece98b.js new file mode 100644 index 000000000..fec03a673 --- /dev/null +++ b/pr/255/docs/search.index/679d38ece98b.js @@ -0,0 +1 @@ +rn_("AQUAOzAAAAEAAAYAAQALEAYAAQMA9NwMAAABAAEAAQBjAAOgkAAAEvBocHM6MAAAAQAAAAAAEAAQAAAAHQYeBh8GKgdkCWoMdgymEKcQqBCpEEESQhKSEpMSuhK7Eg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/679f4284e04c.js b/pr/255/docs/search.index/679f4284e04c.js deleted file mode 100644 index c43c138f9..000000000 --- a/pr/255/docs/search.index/679f4284e04c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCoJAAABMgoJAAABMhMjMBgAKgUAAAE0qggAAAEnZjZfMAAnN08mcHAAABAAEAAaCwAAASvWL1URIAANEAAQBGAAEAI4ACsAAPKQMnZHIBAAGwgBMoAAFw8iQTAAABAEMAA6AgAAAQiKBAAAARvmRlc/MuDwAAEwMBABOCAqAgAAATEmVp84ACY2UBBAA7MAAAAQAACQAEAGgJAQDKDwMACBABAN4SAQCzgISgkAAAE3sQAUI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/67d96877f75a.js b/pr/255/docs/search.index/67d96877f75a.js deleted file mode 100644 index bd192d081..000000000 --- a/pr/255/docs/search.index/67d96877f75a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQkA82UTAAABADUAAYACsCATCQABoCAAAA8NaXkBCQGggAAAE5hmAYwSAAABAwGwABMbAE1zAckSAAAjgAKgIAAADwlhcgECAPUCEAAAAQABADICAQDzAANpdHU6MAAAAQAAAAAADQAQAAAApgc9CWsP4A/0ESQSJRLNEs4S1BL9Ev4SGRMaEwGAArBAEAYAAaAgAAATSWN0E4ACsLASpgABYWwBDAGgoAAAE6l38pkTAAABAAEBAPMvDwAAAQABAPOAAnR1AQMA88cRAAABAAEAAQEA9WYQAAABAAEAAQABACOAArCQEvYAAWF0AQQBoEAAABNNZfJsEwAAAQABAgA7MAAAAQAACwAFAIsPBQDWEQEA8BIBAEATAABfEwAAE4ICsPATnAABZmcBgQKwgBNzAAGgYAAAE5dkcwEIAPUuEwAAAQABAAEAAQDzAgFm9cUPAAABAAEAAQABACOAA6AgAAAPB7CgE3EAAWRydHfvAQCNsBATKAABsOATKgABl9UOOzAAAAEAAAUBEgAWBAEAFAUCAOwFAgDuBgQAFggDAOQLAgAPDAEAiQwBAAoO1AAlDwEA4Q8BAPIPAgAfEAEAsxAAAAoRAQDmEQAAmBIHAIETAwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/67f7a312869a.js b/pr/255/docs/search.index/67f7a312869a.js deleted file mode 100644 index d03d1ec18..000000000 --- a/pr/255/docs/search.index/67f7a312869a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9qUMAAB8AlgAAQCeAgEAAQQAOzAAAAEAAAoABAC6DwUA2BEBAC4SAQBBEwAAAYYCoAAAABJQoAAAABJRZHLzAgF2AXYSAADzgAJlbycBAADHoDAAAA8goHAAABGsoIAAABMSoNAAABK5oLAAABMSQEUICTswAAABAAAJAAMABwYCAEsHBAASDAEAI4ACcpo+9Xx6ZHIBAAA6MAAAAQAAAAAACgAQAAAAXQleCVQPaBJpEpQSlRI1E4gTnhOfExOAAqAwAAAP0Gx084ACYWU=") \ No newline at end of file diff --git a/pr/255/docs/search.index/681c1ab8da48.js b/pr/255/docs/search.index/681c1ab8da48.js deleted file mode 100644 index f41ebd266..000000000 --- a/pr/255/docs/search.index/681c1ab8da48.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBoGAAABN8c/L9EAAAAQABCAD1LhMAAAEAAQABAAEAowCEsCAJewABoIAAABH0MEAIOzAAAAEAAAUAAgC5AQAAxQ8EAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/681f74d11d66.js b/pr/255/docs/search.index/681f74d11d66.js new file mode 100644 index 000000000..8ffe0e971 --- /dev/null +++ b/pr/255/docs/search.index/681f74d11d66.js @@ -0,0 +1 @@ +rn_("AQUA9LYSAAABAIoAAQDzAAFj9QIQAAABALwAAQABAAEJAPPmEwAAAQA1AAENAaCgAAAUKnfyGhQAAAEAAYECsIAT9AABoGAAABQYZHM3AQCEhaBAAAATyrBgE54ASwKQCiOAAqBwAAARAmRyAQsBoEAAABPOZfLtEwAAAQATgAKwMBAeAAFkcvMCAWX0PggAAAEAAQABACOAArAgDB4AAWV5AQoA80kSAAABAAEAAQsAOzAAAAEAAAcAAQAaEwcAAQIA9HYTAAABAEYAAQC3AACAhbBwEnsAAbDQFA8AAWAgBgEGAPNVEgAAAQABAAEDAbBAE+QAAXTyTBMAAAEAI4UCoEAAABN6YnMTAgKgUAAAERNiZvdaCQAAAQBDAM0GAQBhAAEA84ACaXABBADzGxAAAAEAAQDzAAFwOzAAAAEAAAwAAQBIBwwAI4ADoDAAAAwssHATLgABYWVp84ADZG1uAQAA9mQJAAASA8sFAQBQAAEA8wIBZDswAAABAAAJAAMAgBEDADwSAwBrEgEAI4ACoJAAABPBaW8BgAOwMBLnAAGAEyQAEAGwUBDCAAFjc3jzAAFlAVEFAADnFQAAiaAAAAAMhKBAAAAM2LBADNkAAZBIXQHiAQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/682a70b084b3.js b/pr/255/docs/search.index/682a70b084b3.js deleted file mode 100644 index bce9127e5..000000000 --- a/pr/255/docs/search.index/682a70b084b3.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEAOzAAAAEAAAcAAQBfCQcAAQIA938PAADPAIECAQABAHEAAQATgAKwMBAPAKZpdPMAAXPycRMAAAEAM4ADsRAS7gABZG5w") \ No newline at end of file diff --git a/pr/255/docs/search.index/69247c51b33f.js b/pr/255/docs/search.index/69247c51b33f.js deleted file mode 100644 index d5c7832b8..000000000 --- a/pr/255/docs/search.index/69247c51b33f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQ0A9c8SAAABAAEAcQABAAGAAqEQAAATCLBwExwAAW5yAQcA9N8QAAABAAEAAQAzAASgIAAACTmw4BL9AAExZWly8/EDAACGA6MBAQIA9DEQAAABAHUBAQABAwD0nBAAAAEAWgEBAPMAAmJ1AU0PAAABAwD0LxAAAAEAdQEBAPOEAmRzAQIA8xwJAAABAFQA84ACaXQBGADzphMAAAEAAQABgAKwsBLNAAGgwAAAEnpldfOBAmNtAQ0BsEATTgABZfUUEwAAAQABAAEAAQATggKwABBHAAFrcwEEAPTYDwAAAQABAAEAAYECoCAAABBCsEASagABZWnzggJldAEEAaBgAAARzHL03QsAAAEAbQMBAPOAA2FlbwEJAPb1EQAAAQDqAIAAMAABABOAArBgD/AAAWRuAQYA9RoQAAABAAEAAQBiAgEDAaBwAAASKGf0hAcAAAEA6gEBAAEJAPNlEwAAAQA1AAGBArCAE3MAAaBgAAATl2RzFwEAiIWw0BOZAAGgQAAAE0mwYBMbAE0CkAoBBAD0uxIAAAEASgABAFOAA7CQE5IAAWVobwEAAaBAAAAQqWUBAA8AACOBArBQEFQAAWt0d/wBAI2hkAAAE4mwsBI2AAGgoAAAEfT9gQ87MAAAAQAAGQAIAG0AAABzAAMAuwUBAGIHAwBECQMA+wsHAIUPAQCkEQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/6977b4c99668.js b/pr/255/docs/search.index/6977b4c99668.js new file mode 100644 index 000000000..58a783a82 --- /dev/null +++ b/pr/255/docs/search.index/6977b4c99668.js @@ -0,0 +1 @@ +rn_("AYICsEASTwABsEASUQABNDYBBgD0FhQAAAEACgABAPMCAXIBghMAAPMDAWX0KRAAAAEAqAABAFOAA7CwE58AAWFlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6978b4ea0875.js b/pr/255/docs/search.index/6978b4ea0875.js deleted file mode 100644 index 49727be56..000000000 --- a/pr/255/docs/search.index/6978b4ea0875.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9LASAAABAAEAAQABDwD0ihMAAAEAAQABAAEAAbDwE5IAAWv0CBMAAAUAAQAmAAECAPSmDwAAAQCpAAEA9wAAAIWxABN/AAGJMADy3hEAAAEAE4ACsBAMDAABZW8BBQA7MAAAAQAADQABAMQQDQABAgDzOw8AAAEAAQABAgD0Nw8AAAEAAQABAAEDADswAAABAAAIAAEA4w8IAAGAAqAAAAAL4rAwE04AAXFyAYACoEAAABA3sMATRAABZXMBAQA7MAAAAQAAEwABAFcPEwAjgAKwkBK3AAFpbXc2AACKoFAAABMRsHAS9gABoCAAAAyVnFUROzAAAAEAAAkAAwB/BwAAEBADABQTBAABAgGwMBCeAAFwAasRAACzgISgIAAAEQMCKAQ=") \ No newline at end of file diff --git a/pr/255/docs/search.index/69bf077966ff.js b/pr/255/docs/search.index/69bf077966ff.js new file mode 100644 index 000000000..788ceacaf --- /dev/null +++ b/pr/255/docs/search.index/69bf077966ff.js @@ -0,0 +1 @@ +rn_("AQEBoGAAABP9c/J5EQAAAQABCAD1rxMAAAEAAQABAAEAowCEsCAJvQABoIAAABJ2MEAIOzAAAAEAAAUAAgDHAQAAQBAEAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6a74a6193ac1.js b/pr/255/docs/search.index/6a74a6193ac1.js deleted file mode 100644 index cf54e1ad9..000000000 --- a/pr/255/docs/search.index/6a74a6193ac1.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMAOzAAAAEAAAcAAgAyDAUAgBABAAEAAbBQEyoAAXIBIgUAAFMBhLBAEcUAAbBAE2MAAZgABDowAAABAAAAAAAoABAAAAAcBB0EHgTfBRwJHQlDCXEJfQwFD3EPcg9/D6sPAhADEAQQThCpEQASARICEgMSKBI2EjcSYxJkEsoSyxLPEtAS0RLhEuISQhNDE1kTWhN9E34T") \ No newline at end of file diff --git a/pr/255/docs/search.index/6a91ed0cfbc4.js b/pr/255/docs/search.index/6a91ed0cfbc4.js new file mode 100644 index 000000000..be1c40f03 --- /dev/null +++ b/pr/255/docs/search.index/6a91ed0cfbc4.js @@ -0,0 +1 @@ +rn_("AYACsHASYAABoLAAABOKZW8jAYSwcBGcAAGgYAAAEvyAEvUAEOwAMAM7MAAAAQAAGgAGAMwHAQBECQUACw0BAPEQCQAwEQAA2hIFAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6adf1d99a4d5.js b/pr/255/docs/search.index/6adf1d99a4d5.js new file mode 100644 index 000000000..3889cc1cf --- /dev/null +++ b/pr/255/docs/search.index/6adf1d99a4d5.js @@ -0,0 +1 @@ +rn_("AQoBoIAAABQZZgEOEwAAAQgA9a8TAAABAAEAAQABAPMDAWb1QBAAAAEAAQABAAEA84MCYXMBAgKgIAAAEXugMAAAEjNiaAF9DwAAI4ACoIAAABLHYXDzAAJobQEuBQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/6b465541ac5c.js b/pr/255/docs/search.index/6b465541ac5c.js new file mode 100644 index 000000000..bbca78125 --- /dev/null +++ b/pr/255/docs/search.index/6b465541ac5c.js @@ -0,0 +1 @@ +rn_("AQUBsEASTAABZfJtEgAAAQABAAA7MAAAAQAAEQAEANMBAQBeEAgAWxEDAEkSAgABCgGwQBPPAAFl9ZcTAAABAAEAAQABAEcGAACHsCAQtgIVsMAUEwABoCAAAAdjsDAHugABGIkKOjAAAAEAAAAAAA4AEAAAAKoHqwe2B7cHjgkyDDMMOQw6DIUMhgzPDNAMmBKZEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6b51a243b1b9.js b/pr/255/docs/search.index/6b51a243b1b9.js new file mode 100644 index 000000000..5c0752e2d --- /dev/null +++ b/pr/255/docs/search.index/6b51a243b1b9.js @@ -0,0 +1 @@ +rn_("AQgA9G0TAAABAH4ABQATAAOwkBPMAAGwUBK8AU5nbHA7MAAAAQAAEgAJABUQAgCLEQEAqxIBAMwSAQD9EgEAXhMBAJITAQChEwEA3hMBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6b5ec36867cc.js b/pr/255/docs/search.index/6b5ec36867cc.js new file mode 100644 index 000000000..747cd0766 --- /dev/null +++ b/pr/255/docs/search.index/6b5ec36867cc.js @@ -0,0 +1 @@ +rn_("AQMBgBL1ABDsczswAAABAAAFAAEA2hIFACOCAqCQAAATy2lzBwEAhMWwUBKkAAGgoAAAEzywcBMEAAGg0AAAE9eAARgI") \ No newline at end of file diff --git a/pr/255/docs/search.index/6bc821d036fc.js b/pr/255/docs/search.index/6bc821d036fc.js deleted file mode 100644 index 79600e540..000000000 --- a/pr/255/docs/search.index/6bc821d036fc.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9PQSAAABAEcAAQDzAwFj8gkSAAABACOAArBwE5wAAWhvAYICsAAR5wABsAARDAABZXNDAAOgoAAAE0GgIAAAEoRlaXT1+REAAAEAeQABAO0AAYECoEAAABJ6sEASOAABYWYBgAKwcBHeAAGgsAAAEwhlbwECADswAAABAAAGAAEAjBAGAAECAaBAAAATJmXyUBMAAAEA84ACaW8BCAD06xIAAAEAfwAFABMBA7CQE0sAAbBQEjoBT2dscDswAAABAAASAAkAmw8CAA8RAQApEgEAShIBAHsSAQDcEgEADxMBAB4TAQBdEwEAAYACsEARwQD9oCAAABBPYWkBgQKwMBL7AAGgMAAAEd1jaQEDAbAAEiQAAXM7MAAAAQAADQADAAoRAQCYEgcAgRMDAAEDAPUIEQAAAQAFAQEARwHzgAJydgEAAPS/EQAAAQBQAAEA8wIBZDswAAABAAAJAAMABBEDALoRAwDpEQEAI4ACoJAAABNAaW8TgAKw8BOOAAFsbwEFAPRcEwAACwAeAA8AI4ACoGAAABJ5Z3MjgAKwkBM+AAFibPeXAwCPsHARIAABsGATcQABsHAS7gABsFASJgABtfkXOzAAAAEAADsAFwD9BQAAkwcBAAIJBQASCQAAQAkAANALAAAWDAEAhAwCAKsMAQADDgMACA4BADIPBAD3DwEAMxAAAFYQAAB2EAkAtBAAALYQAwACEQAAMBIAAEcSAQBYEgUAEhMAAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6bcf985f9cc0.js b/pr/255/docs/search.index/6bcf985f9cc0.js deleted file mode 100644 index 93e502813..000000000 --- a/pr/255/docs/search.index/6bcf985f9cc0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9NkQAAABAAEAAQABAQDz7xAAAAEAAQATgAJmPTzNRehlcwEKAPO0EgAAAQABAAGAArAgEyoAAaBgAAASgW92AYACoDAAABHMoAAAABJAY2TzgIUFEAY=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6bdb48f6e8fe.js b/pr/255/docs/search.index/6bdb48f6e8fe.js new file mode 100644 index 000000000..335093a74 --- /dev/null +++ b/pr/255/docs/search.index/6bdb48f6e8fe.js @@ -0,0 +1 @@ +rn_("AQMBsDAS2AABY/MpEQAAAQABAAEDAYAS9QAQ7HM7MAAAAQAABQABANoSBQAjggKgkAAAE8tpcwcBAIDFsFASpAABoKAAABM8sHATBAABoNAAABPXgAEYCPOAAmRy") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c11604302a6.js b/pr/255/docs/search.index/6c11604302a6.js new file mode 100644 index 000000000..a3c889536 --- /dev/null +++ b/pr/255/docs/search.index/6c11604302a6.js @@ -0,0 +1 @@ +rn_("AQEA9VgIAAABAAEAAQABAAEAAqAwAAAQvqCQAAATBzBo9Z4RAABzAQEAAQABABOAAqAwAAAPf2RyIwKEsBAJSgL/sCAMHAD2oDAAAA+jEgAY9REGAAAvAAEAAQABADOAhLCgElgAAbBAD4kAARBJAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c19dc66c62e.js b/pr/255/docs/search.index/6c19dc66c62e.js deleted file mode 100644 index 5a275e3d8..000000000 --- a/pr/255/docs/search.index/6c19dc66c62e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9DEQAAABAHUBAQABAAD0Jw8AAAEA5gADASOCArBQEk4AAWVzAQIA9CASAAABAIkAAQABAwD0VBIAAAEAjgABAPOFAmJ1AQIA9JwQAAABAFoBAQDzgAJpbPMAA2J0dTowAAABAAAAAAAPABAAAACaByUIJggnCCgITQ8FEKESGxNlE2YTaBNzE3QTlxObEwEMAPMDEwAAAQABAAEGAPQeEgAAAQCJAAEA8wMBYvQvEAAAAQB1AQEAFwYAAIewQA8lAAGgcAAAEbGwEAkrAAGwkBJMAAE4CQM6MAAAAQAAAAAAIQAQAAAACgYLBgwGXwdgB5wMnQyeDKIMowykDB4PHw9vD3APdA91D5EPkg+TD5QPlQ+WD5cP0w8AEAEQgRKlEskSXBNnE4UTlBM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c2ea040f627.js b/pr/255/docs/search.index/6c2ea040f627.js new file mode 100644 index 000000000..122ffd6cd --- /dev/null +++ b/pr/255/docs/search.index/6c2ea040f627.js @@ -0,0 +1 @@ +rn_("AQMA80kSAAABAAEAI4ECsSAUHQABY2sBBAGgQAAAEZVl8wgNAACzAwEAAQAA9ZUQAAABAAEAAQBpAnOAhKAwAAATpwgwAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c5b31781505.js b/pr/255/docs/search.index/6c5b31781505.js deleted file mode 100644 index f22950253..000000000 --- a/pr/255/docs/search.index/6c5b31781505.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsHAQngABsCATRAABYWQBBgD0QxIAAAEAjgABACOAArCgEyoAAXN5AQYA9D0QAAABALkAAQCTgISgAAAAEIaxIBOGAAEJIAHzgAJlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c6bec7a76cc.js b/pr/255/docs/search.index/6c6bec7a76cc.js new file mode 100644 index 000000000..844c139e2 --- /dev/null +++ b/pr/255/docs/search.index/6c6bec7a76cc.js @@ -0,0 +1 @@ +rn_("AQQA9CMSAAABAFQBAQDzAAFsOzAAAAEAAAgAAwC3CQEAhRABAOEQBAABAAGwYBN/AAFl9GIMAAABAAEAUAcBBQD0tBIAAAEAOgEBAAEHADswAAABAAAFAAEACBMFAPMCAXQ7MAAAAQAACAACAB0MAABKDAcA84ACYWUBgAKxEBQAAAGwEAxlAAFlbwEFADswAAABAAANAAEAQBENAAECAPO0DwAAAQABAAECAPSwDwAAAQABAAEAAQMAOzAAAAEAAAgAAQBeEAgAhwcAAIewoBM5AAGw0BPFAAGgUAAAE5SMFBH1uAcAANMIAQABAAEA84ACbHQTgAOgIAAADNWwoBOtAAFhZG4BgAKwgBKNAAGwoBL5AAFpdAGAArDgE+oAAbBAD/8AAWxyAQYA9IsQAAABAAEAAQBHBQAAh6DQAAATx7BQD/0AAaAAAAAS+7DwE6UAAQWRA/KjDwAApwABAgD0zhIAAAEA/QABACOAAqAgAAAMKWlyAQgA9DcSAAABAAEAAQABBAGwABCPAAFzAQEQAAABAgGgUAAAEo9jAdYMAAC3AgAAh7BADRAAAbAQEuwAAaAAAAASyJUQAzowAAABAAAAAAANABAAAABOBU8FDgYPBhAG2QzaDHIPcw90D4EPORM6EzwTAYACsCAJfAABoOAAABNvYmz3FgAAibAQBggAAbAgB9kAAZEJRzswAAABAACKAAoASwQAAHYJAgCZEAAA6BAAACcRAACkEXsAIRIDADESAADyEgAAeBMBAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6c87bbe255e2.js b/pr/255/docs/search.index/6c87bbe255e2.js deleted file mode 100644 index e60b3dfda..000000000 --- a/pr/255/docs/search.index/6c87bbe255e2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYkCsCATWQABoDAAABNiaXATAAOgIAAAEiiggAAAEjtlaXX10QsAADIAAQABAAEAAYYCsJATfQABoAAAABHCYmQBgAKwMBIcAAGgMAAAEB9ydnMAhKAwAAAScBAAEzowAAABAAAAAAAJABAAAAAMCQ0JDgk+CT8JtA+5D3AQcRD/EQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6ca19f0a3313.js b/pr/255/docs/search.index/6ca19f0a3313.js new file mode 100644 index 000000000..6d3811bb7 --- /dev/null +++ b/pr/255/docs/search.index/6ca19f0a3313.js @@ -0,0 +1 @@ +rn_("AQIBsEAT5AABdDswAAABAAANAAYAghIDAOUSAQBMEwEAYxMBANoTAQD+EwEAE4ACsDASrwE0aXABBQDzJBMAAAEAAQATgAKgMAAAE3pleVMCA7BwE4gAAWJlcwHtDwAAEwACoCAAAAYYZm32cgAAAFUHAQDCAQEAWwc=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6cc490e2f6c0.js b/pr/255/docs/search.index/6cc490e2f6c0.js deleted file mode 100644 index 83832c930..000000000 --- a/pr/255/docs/search.index/6cc490e2f6c0.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgCAEgAA5RIFACOIArBAE1QAAWVzAQQBsDASVgABY/OtEAAAAQABAAEFADswAAABAAAIAAMAHBECAAQSBAATEwAA8wEDY2Vw83QMAAABAAEAAQIA9ioJAABQADYGAQCxAAEA84ACbnI=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6ccad3bd4a7d.js b/pr/255/docs/search.index/6ccad3bd4a7d.js new file mode 100644 index 000000000..b052fe0e4 --- /dev/null +++ b/pr/255/docs/search.index/6ccad3bd4a7d.js @@ -0,0 +1 @@ +rn_("AQUA9FMSAAABAJoAAQABCAD0/xIAAAEAgwABADMAA7BAEtQAAWFiZTowAAABAAAAAAAJABAAAACWB5cH9wz4DHoP5g8wEDEQLhLxEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6da9782962b9.js b/pr/255/docs/search.index/6da9782962b9.js new file mode 100644 index 000000000..452e7cb91 --- /dev/null +++ b/pr/255/docs/search.index/6da9782962b9.js @@ -0,0 +1 @@ +rn_("AQAAOzAAAAEAAAYAAgACEwAAZxMFACOIArBAE9UAAWVzAQQBsDAS2AABY/MpEQAAAQABAAEFADswAAABAAAIAAMAmBECAIYSBACWEwAA8wMDY2Vw89IMAAABAAEAAQABsGATfwABZQG0EwAA8wIBc/Z2CQAAAQABAHAHPwAKAQECAaBQAAARKHIByBAAAPOAA2ZtcA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/6e48f0d21453.js b/pr/255/docs/search.index/6e48f0d21453.js deleted file mode 100644 index ff1ece725..000000000 --- a/pr/255/docs/search.index/6e48f0d21453.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9DEQAAABAHUBAQAjgQKgYAAAEjtiaQEAAPQnDwAAAQDmAAMBI4ECsFASTgABZXMTgAKwAAd6AdNhcgGJArAgE1kAAaAwAAATYmlwAQIA9CASAAABAIkAAQABAwD0VBIAAAEAjgABAPOFAmJ1AQIA9JwQAAABAFoBAQDzgAJpbLcBAACFoCAAABIoEgEMOjAAAAEAAAAAABYAEAAAAJoHJQgmCCcIKAjRCwMMBAwFDAYMTQ8FEGoSaxKhEhsTZRNmE2gTcxN0E5cTmxM=") \ No newline at end of file diff --git a/pr/255/docs/search.index/6e4b7a20ef6a.js b/pr/255/docs/search.index/6e4b7a20ef6a.js new file mode 100644 index 000000000..f9ef47ef7 --- /dev/null +++ b/pr/255/docs/search.index/6e4b7a20ef6a.js @@ -0,0 +1 @@ +rn_("AQMAOzAAAAEAAAcAAgCMDAUA+xABAAEAAbBQE6sAAXIBSwUAAFMBhLBAEkcAAbBAE+QAAZgABDowAAABAAAAAAAoABAAAAA8BD0EPgQNBl4JXwmFCbMJ2wx+D+sP7A/5DyYQfRB+EH8QyRAqEoISgxKEEoUSqhK4ErkS5RLmEkwTTRNRE1ITUxNjE2QTwxPEE9oT2xP+E/8T") \ No newline at end of file diff --git a/pr/255/docs/search.index/6ee2f712ff40.js b/pr/255/docs/search.index/6ee2f712ff40.js new file mode 100644 index 000000000..922539d97 --- /dev/null +++ b/pr/255/docs/search.index/6ee2f712ff40.js @@ -0,0 +1 @@ +rn_("AQwA8zYTAAABAAEAAQYA8xURAAABAAEAAYICsGASwwABsNAT0QABaXITgAKwEAzsAAFlaRcDAIOIsTAT7QABoGAAABEUoFAAABClsJASmgABsEAQowABtBAH8wABYfSMCQAAAQBcBwEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/6fcb853616ae.js b/pr/255/docs/search.index/6fcb853616ae.js new file mode 100644 index 000000000..dfb329961 --- /dev/null +++ b/pr/255/docs/search.index/6fcb853616ae.js @@ -0,0 +1 @@ +rn_("AYACsHAT/gABoAAAAAUuZmcBAQA7MAAAAQAABwABAFQMBwABAQGgcAAAEithAXgHAAAjgAKhAAAAFAZkbnOAhKBgAAASKgBBSA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/70212e5b30bb.js b/pr/255/docs/search.index/70212e5b30bb.js deleted file mode 100644 index 13a10b901..000000000 --- a/pr/255/docs/search.index/70212e5b30bb.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYQCoCAAABBOoDAAABC1aXQBAQA7MAAAAQAAdwACAJsHAAB/CXYA8wACZWzzbBAAACECAQABAgA7MAAAAQAA1gACAM0LAAC1DNUAxwAAAIWwsBI8AAGgEAAAErmwMAyzAAEUMAI7MAAAAQAAAgELAKcBBgDpBQAAFQbVAGkHBwB2DwIAxBANAOwQAgCuEQEAJhIBAHESAQADEwIA") \ No newline at end of file diff --git a/pr/255/docs/search.index/711db6f37c54.js b/pr/255/docs/search.index/711db6f37c54.js new file mode 100644 index 000000000..d64951e5e --- /dev/null +++ b/pr/255/docs/search.index/711db6f37c54.js @@ -0,0 +1 @@ +rn_("AQcA9KYQAAABAAEAAQABAAD1rAkAAAEAAQABAAEAI4ACoKAAABP8ZnABAwGgkAAAE3xl8mUPAAABANcAAACFoFAAABAjsUAUIwABgSkA8u0FAAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/713ea441eaa3.js b/pr/255/docs/search.index/713ea441eaa3.js new file mode 100644 index 000000000..3b5343dc9 --- /dev/null +++ b/pr/255/docs/search.index/713ea441eaa3.js @@ -0,0 +1 @@ +rn_("AQIBoKAAABLpZPJbBwAAAQABgQKgMAAAE9ygUAAAE29jcwEEA7AgEO8AAaBQAAARlKBAAAATqGxzdvKjEwAAAQDzAANhZW/yOgQAAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/71646ec45998.js b/pr/255/docs/search.index/71646ec45998.js deleted file mode 100644 index ec9ad8c92..000000000 --- a/pr/255/docs/search.index/71646ec45998.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9PQSAAABAEcAAQDzBAFj8gkSAAABACOCAqBQAAAR3WZ0AQABsAATRwABZPS+CwAAAQABAAEA84ACZWkTgAKw4BNSAAF0dg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/71e93f057075.js b/pr/255/docs/search.index/71e93f057075.js deleted file mode 100644 index 6aa692a0e..000000000 --- a/pr/255/docs/search.index/71e93f057075.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA9KIRAAABAFMBAQDzAAFsOzAAAAEAAAgAAwB1CQEAChABAGYQBAABAAGwYBL9AAFl9AkMAAABAAEAKAcBBQD0MhIAAAEAOwEBAAEHADswAAABAAAFAAEAhhIFAPMCAXQ7MAAAAQAACAACAMULAADxCwcA84ACYWUBgAKxEBN/AAGwEAwMAAFlbwEFADswAAABAAANAAEAxBANAAECAPM7DwAAAQABAAECAPQ3DwAAAQABAAEAAQMAOzAAAAEAAAgAAQDjDwgAhwcAAIewoBK3AAGw0BNEAAGgUAAAExGMFBH1fwcAAJEIAQABAAEA84ACbHQTgAOgIAAADHewoBMsAAFhZG4BgAKwgBILAAGwoBJ3AAFpdAEOAPQiEwAAAQBGAAEAE4ACsEAPhQABbHIBBgD0EBAAAAEAAQABAEcFAACHoNAAABNGsFAPgwABoAAAABJ5sPATJAABBZED8ioPAAClAAECAPRMEgAAAQD+AAEAI4ACoCAAAAvQaXIBCAD0thEAAAEAAQABAAEEAbAAEBQAAXMBhw8AAAECAaBQAAASDWMBeAwAALcCAACHsEAMsAABsBASagABoAAAABJGlRADOjAAAAEAAAAAAA0AEAAAACUFJgXgBeEF4gV7DHwM+Q76DvsOCA+3ErgSuhIBgAKwIAk6AAGg4AAAEu1ibPcWAACJsBAF2gABsCAHnwABkQlHOzAAAAEAAIUACgArBAAANAkCAB4QAABtEAAAqxAAACgRdgCgEQMAsBEAAHASAAD2EgEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/72352df403a5.js b/pr/255/docs/search.index/72352df403a5.js new file mode 100644 index 000000000..07a2b6946 --- /dev/null +++ b/pr/255/docs/search.index/72352df403a5.js @@ -0,0 +1 @@ +rn_("AQMA9GIJAAABABEDAQABAwDzcQwAAAEAAQDzgAJpbwEBAbBQEK8AAWP0vwcAAAEAAQDzASOBAqBQAAAQcWNuAQQAOzAAAAEAAAcAAwBoEQIA8xIBAIUTAgABAQA6MAAAAQAAAAAABwAQAAAAixGMEasSrBL9Ev4SoROiE/MJAWkBrhAAANcCAACHsMAS7AABoFAAAA9poRAAABPHFAEXOzAAAAEAACMAAQCPASMA") \ No newline at end of file diff --git a/pr/255/docs/search.index/729a3ef57c7a.js b/pr/255/docs/search.index/729a3ef57c7a.js deleted file mode 100644 index 9714162c4..000000000 --- a/pr/255/docs/search.index/729a3ef57c7a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYICsEARzQABsEARzwABNDYBBgD0lRMAAAEACgABAPMCAXIBABMAAPMDAWX0rg8AAAEAqAABAFOAA7CwExwAAWFlaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/729ca138be4c.js b/pr/255/docs/search.index/729ca138be4c.js deleted file mode 100644 index 8aabef055..000000000 --- a/pr/255/docs/search.index/729ca138be4c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9NERAAABAJoAAQABCAD0fRIAAAEAgwABADMBA7BAElIAAWFiZfWYDAAAAQDTAkECwgABAAD15wsAAAEACwMBAAEA84ACc3UjgQKwgBJ3AAFydAEGAPSyDwAAAQCxAAEAUwCEsIASCwABoKAAABOpAgEU9cMFAAABAIUNUAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/731dde1dce82.js b/pr/255/docs/search.index/731dde1dce82.js new file mode 100644 index 000000000..0ef573de7 --- /dev/null +++ b/pr/255/docs/search.index/731dde1dce82.js @@ -0,0 +1 @@ +rn_("AQAAOjAAAAEAAAAAAAoAEAAAAJUPlg95EHoQBhGSEZMRlBKVEg8UEBQBBADzkA8AANcAAQDzAAFx9w0NAAABAOkCAQDCAGIAAQDzAAJleTowAAABAAAAAAAMABAAAABlDGYMMhAzEMQQxRDGEG0TbhN9E34T7BPxEw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/734aaab2a00b.js b/pr/255/docs/search.index/734aaab2a00b.js new file mode 100644 index 000000000..ddfc7fa59 --- /dev/null +++ b/pr/255/docs/search.index/734aaab2a00b.js @@ -0,0 +1 @@ +rn_("AQYA9DITAAABAAEAAQABDwD0CxQAAAEAAQABAPOHAmhtAQQBsAASkgABZPQ8EgAAAQABAAEAI4eEsKATvwABsEASkAABsHATcAABFYAAAQABoEAAABA9ZTswAAABAAAGAAIAzgcEAF0IAQATgAKwUA/6AAFkcgEJAPVREwAAAQABAHAAAQC3AgCAhrAgEkUAAWtew2hnzBFJAQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7489318a49dc.js b/pr/255/docs/search.index/7489318a49dc.js new file mode 100644 index 000000000..c37aa8519 --- /dev/null +++ b/pr/255/docs/search.index/7489318a49dc.js @@ -0,0 +1 @@ +rn_("AQABsPAUEwABa/WKEwAABQABAAEAJAATAAKxABQAAAFkbvJgEgAAAQATgAKwEAxlAAFlbwEFADswAAABAAANAAEAQBENAAECAPO0DwAAAQABAAECAPSwDwAAAQABAAEAAQMAOzAAAAEAAAgAAQBeEAgAAYACoEAAABCysMATxQABZXMBAQA7MAAAAQAAEwABANEPEwAjgAKwkBM5AAFpbTc2AACKoBAAAAw7oFAAABOUsHATeAABoCAAAAz0nFUR9bgHAADTCAEAAQABAPOAAmx0") \ No newline at end of file diff --git a/pr/255/docs/search.index/74c41d060fa6.js b/pr/255/docs/search.index/74c41d060fa6.js deleted file mode 100644 index d4070dcbb..000000000 --- a/pr/255/docs/search.index/74c41d060fa6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUA9NERAAABAJoAAQABCAD0fRIAAAEAgwABADMBA7BAElIAAWFiZTowAAABAAAAAAAJABAAAABdB14HmAyZDAEPbA+1D7YPrRFvEgEAADswAAABAAAeAA4AIwUBANEFCAA3CQEA5wsBAIsMAQAHDgAA8w4CAAkPAAAnDwEADhABACEQAAC1EAAADBEBABERAAABgQKwABClAAGwABCnAAE0NiOAArCAE3EAAW9wAQABsEASTgABZfOwEAAANwEBALcBAICFoGAAABBNEAEL") \ No newline at end of file diff --git a/pr/255/docs/search.index/75b83b34138f.js b/pr/255/docs/search.index/75b83b34138f.js new file mode 100644 index 000000000..76c46754b --- /dev/null +++ b/pr/255/docs/search.index/75b83b34138f.js @@ -0,0 +1 @@ +rn_("AQEA9RYGAAA9DAEAmgABAAEAADswAAABAAAHAAMA5gEBAHkMAQDKDwMAAYMCsHATDwABsIATQwABY3MBBQD0thIAAAEAigABAPMIAWP1AhAAAAEAvAABAAEAAQABoDAAABEsdPRpEAAAAQAXAAEAAYACoAAAABA7oAAAABA8NDbzAwF2AQUNAACXAAAAhbCgEpwAAbAgDDkAAbCAEn8AAQkEBjowAAABAAAAAAAJABAAAABuB28HcAdHDKYPAhE0EjUSNhLHEwECAPSiEgAAAQCJAAEAAQMA9NYSAAABAI4AAQDzAAJidTowAAABAAAAAAAVABAAAACsB60HrgeLD4wPLRAuEEwQTRDfEOAQjhGPEaASoRKtEq4SvRLnEugSKhMrEwEBAPQSBgAAAQDiBgEAtwAAgIWxABOtAAGwAAe2AAEMCEQBCAA7MAAAAQAABQABAGISBQDXDQAAiLBAEM8AAaAgAAAND7kACzswAAABAAAPAAUAagABAGYHBwDFBwEAIRABAMsQAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7601f1395e7f.js b/pr/255/docs/search.index/7601f1395e7f.js deleted file mode 100644 index 4330d0c33..000000000 --- a/pr/255/docs/search.index/7601f1395e7f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQA8+8QAAABAAEAAYICsEARzQABsEARzwABNDYBBgD0lRMAAAEACgABAPMCAXIBABMAAPMCAWX0rg8AAAEAqAABABOAAqBQAAAR/2R00wCEsLATHAABEQEB9xYQAAABAG8AHAABAAEAHgE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/76f46ceef4bd.js b/pr/255/docs/search.index/76f46ceef4bd.js deleted file mode 100644 index 51026b5c1..000000000 --- a/pr/255/docs/search.index/76f46ceef4bd.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsAAQpQABsAAQpwABNDYBBAGgoAAAE6l38pkTAAABAAGAAqCAAAATNLCwEw0AAWVvYwIDoGAAABLMZW5wAd8LAADzAAJhdgEPBwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7707a0af636d.js b/pr/255/docs/search.index/7707a0af636d.js new file mode 100644 index 000000000..cd724e228 --- /dev/null +++ b/pr/255/docs/search.index/7707a0af636d.js @@ -0,0 +1 @@ +rn_("AYQCsAARIQABsAARIwABNDbzAgFh8oIMAAABAAEAAPZOEgAAZgABAEcA8wABAPMAAWTzXBIAAAEAmgBjgAOgIAAACUxhZW8=") \ No newline at end of file diff --git a/pr/255/docs/search.index/77281c5ced0c.js b/pr/255/docs/search.index/77281c5ced0c.js deleted file mode 100644 index 2c53bd057..000000000 --- a/pr/255/docs/search.index/77281c5ced0c.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQEBsFAPEAABY/QDBQAAAQABAK8AAQABoIAAABOYZgGMEgAA8wYBc/KnDAAAHAQzAAOgYAAAE3xjaXPy/RAAAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/77607e6e8760.js b/pr/255/docs/search.index/77607e6e8760.js deleted file mode 100644 index c47bc9852..000000000 --- a/pr/255/docs/search.index/77607e6e8760.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAA9EoJAAABACMHAQABCQGggAAAE5hmAYwSAAABAgD1AhAAAAEAAQAyAgEA8wACaXU6MAAAAQAAAAAABwAQAAAA4A/0Ec0SzhL9Ev4SGRMaEwEIAPUuEwAAAQABAAEAAQDzAgFm9cUPAAABAAEAAQABABOAArCgE3EAAXJ08wACYXPz8g8AAAEAAQDzgAJ0dg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/77f373856497.js b/pr/255/docs/search.index/77f373856497.js new file mode 100644 index 000000000..4d845a12c --- /dev/null +++ b/pr/255/docs/search.index/77f373856497.js @@ -0,0 +1 @@ +rn_("AQEBoEAAABEsc/VHDAAAuwQyAQEAAQATggKgIAAADQ9lcgECAPScDwAAAQDqAAEAI4ECoBAAAAxGZWkTgAKg8AAAE5VucjMAA7AwCXkAAWVvdAF7EQAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/78318d6c832f.js b/pr/255/docs/search.index/78318d6c832f.js new file mode 100644 index 000000000..88a5c03f5 --- /dev/null +++ b/pr/255/docs/search.index/78318d6c832f.js @@ -0,0 +1 @@ +rn_("AYICsEATzAABsGAStAABZXIBBQD0RRAAAAEAAQABAPOAAmZtAQYAOjAAAAEAAAAAAAgAEAAAAI4Pjw82EXcSeBJiE+ETERQSFAEAAaFAAAAUCmf03AcAAAEAAQABAMMAhKCwAAATS7BAEFwAARQgBPVYBwAAfQUnA0cC/QBjgAOwMA/IAAFhZWk=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7861667f4a43.js b/pr/255/docs/search.index/7861667f4a43.js new file mode 100644 index 000000000..cd420f997 --- /dev/null +++ b/pr/255/docs/search.index/7861667f4a43.js @@ -0,0 +1 @@ +rn_("AYUCsHATiAABsDAS5QABZXMTAAOwQA+HAAGgYAAAETBiZXM7MAAAAQAAEgAEACAGAQAvBwoA/Q8BAE8QAwABAgDzKwYAAIAJAQABAwD1fw8AAJoAAQAEAAEAAQoBoEAAABPOZfLtEwAAAQAjAAOgMAAAEL6gkAAAEwcwY2j1nhEAAHMBAQABAAEA84ACZHLnAAAAh7AQCUoC/7AgDBwA9qAwAAAPo7AAB50AARJBODswAAABAAAQAAYAfAACABEGAABABgMA/QcDAD4IAwAnDAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/789bd808f118.js b/pr/255/docs/search.index/789bd808f118.js deleted file mode 100644 index 5b77e1277..000000000 --- a/pr/255/docs/search.index/789bd808f118.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMBsDASVgABY/OtEAAAAQABAAEDAYAScwAQ7XM7MAAAAQAABQABAFgSBQAjggKgkAAAE0ppcwcBAIDFsFASIgABoKAAABK6sHASggABoNAAABNWgAEYCPOAAmRy") \ No newline at end of file diff --git a/pr/255/docs/search.index/78e2e859c206.js b/pr/255/docs/search.index/78e2e859c206.js deleted file mode 100644 index 1705dcf4f..000000000 --- a/pr/255/docs/search.index/78e2e859c206.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoAAAAA/AoAAAAA/BNDYBgAOwABLVAAGwABLXAAGwcBNHAAE0NmEBBAD0lRMAAAEACgABACOBAqBAAAAQhm1wAQEAOzAAAAEAAAgAAwDcEQAARRIAAKITBgDHAQACxaBAAAAPiqBgAAAS+kAFgAg7MAAAAQAAFgAIACsPAQA9EAEAghADAPIQBgC0EgIAABMAAFcTAQCGEwEA8wACZXY6MAAAAQAAAAAAEQAQAAAA2QHaAfcFpgzsDu0OBw8gD64Prw9XEFgQzRHOEc8R0BEcEx0TAYECsHAQggABsHAQhAABNDYjgAKwEAeKAAFucAEDArBAEhwAAaAwAAAScGV39LQPAAAFALcAAQATgQKgcAAAEqVnbyOAArBQDysAAWR0VwEAAIWgEAAAD4qxIBNXAAERIQH0+RAAAAEAAQABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/78f080218498.js b/pr/255/docs/search.index/78f080218498.js new file mode 100644 index 000000000..91527b83a --- /dev/null +++ b/pr/255/docs/search.index/78f080218498.js @@ -0,0 +1 @@ +rn_("AQABsIATXAABdAFmCQAAAQkA81USAAABAAEA84ACY2cBgwKgkAAAE6OgkAAAE6QyMwGAAqBQAAATy6CAAAAS+GNl8wACc3TyoAcAAAEAAQABoLAAABM/YvPTEgAAFwEBACOAAqAAAAAS0mRyI4ACoFAAABOVY2XzgAJpeQEGAPXhEAAAAQABAAEAAQABAQGwQBPPAAFl9ZcTAAABAAEAAQABAPcAAICFoBAAAAwpKWAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7a4fbb02a71b.js b/pr/255/docs/search.index/7a4fbb02a71b.js deleted file mode 100644 index 0d1a7de32..000000000 --- a/pr/255/docs/search.index/7a4fbb02a71b.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQMA9CAJAAABAPoCAQABAwDzGAwAAAEAAQDzgAJpbwEBAbBQEDQAAWP0hgcAAAEAAQDqASOBAqBQAAAP9mNuAQQAOzAAAAEAAAcAAwDsEAIAcRIBAAMTAgABAQA6MAAAAQAAAAAABwAQAAAADxEQESkSKhJ7EnwSHhMfE/MJAWkBMxAAANcCAACHsMASagABoFAAAA7woRAAABNGFAEXOzAAAAEAACMAAQCBASMA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7b1c227ec211.js b/pr/255/docs/search.index/7b1c227ec211.js deleted file mode 100644 index ca25740c8..000000000 --- a/pr/255/docs/search.index/7b1c227ec211.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA99YLAAABAA4DAQBBAVsCAQABAwD0Hg8AAAEA4QABAAGBAqAAAAAQsKAQAAAPAWV184ACYXIBgQKgkAAAEuKwUBGuAAFidxOAArCQEi4AAW5y8wACZXT07g8AAAEAFwABAAEBAPUtDAAAAQABAAEAAQATgAKwsBLeAAFhbyMAArBADKAAAWV0OzAAAAEAAAkABAAeBQEAywUBABQMAQDZEAMAAQIAOzAAAAEAAAkAAgAMCAcAFBIBAAGAArCQEnEAAaCgAAAS4WV2E4ACsYATpAABY20BggKwQBMLAAGgUAAAEQ5iZhOAAqBAAAATM2RzI4ACoNAAABN8Y27zgIQRAUABBQGwQBJSAAFlAa0RAABDggOhAAAAE4ig0AAAE2BrbXMTgAKwYBAKAAFhcgEFADswAAABAAB3AAIAHhAAACgRdgABggOwIBIWAAGwIA+sAAGwQBCgAAFrbHNTgAOwIBNjAAFrdHUBiYSggAAAE5egQAAAE0mgYAAAE2igkAAAE5sCgAoTgoSgoAAAEuCxoBOnAAGw0BNCAAEEAQkBgAKxcBOiAAGg0AAAExpjbyOAArBgEAgAAWlvAQAA9OALAAABAEoAAQAjgQKg4AAAEzVleQENADowAAABAAAAAAAHABAAAABKEksS3BLdEg8TEBNdE14TAYECsEASaAABoMAAABMZZW8BAgA6MAAAAQAAAAAACAAQAAAAFQ8WD7oQ9RH2EeASYBOQE5ET8wEBbzswAAABAAAJAAQAaAkBAMoPAwAIEAEA3hIBAPOAA21ucgEAADswAAABAAAGAAIAgBIAAOUSBQBDgAOwQBNUAAGgIAAADJ9lcnMjAAKwMBLBAAFjcvKuEgAAAQABgQKwgBIaAAGhAAAAE19jZgGAAqAAAAAPwKAAAAAPwTQ28wIBdgGmDAAA8wABZAEpCQAA1/4hAJKwoBMJAAGwcBEAAAGwgBH9AAGgsAAAEjCgcAAAD/WwAAlGAAGd3X87MAAAAQAAFgALAHQBAAAaBQMAyAUCACsHAQA1BwIA7gsAAC0PAACHEAAA7xACALMRAgBGEwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7b387f9a1467.js b/pr/255/docs/search.index/7b387f9a1467.js new file mode 100644 index 000000000..3e74e65f7 --- /dev/null +++ b/pr/255/docs/search.index/7b387f9a1467.js @@ -0,0 +1 @@ +rn_("AQACoCAAABMGsDARiAABaXTyexIAAAEAAQMAOzAAAAEAAAYAAQAHEQYAAQgA9G0TAAABAH4ABQATAQOwkBPMAAGwUBK8AU5nbHA7MAAAAQAAEgAJABUQAgCLEQEAqxIBAMwSAQD9EgEAXhMBAJITAQChEwEA3hMBAAGAArAwEYQAAbAwEYYAAXJ2AQQBsAASQQABZDswAAABAAAFAAIAgBEDAGsSAQC3BQABh7BQEkMA/bBgEroAAZQJAzswAAABAAAKAAUA4gwCAHUOAQCuEAAAMhEDALISAAAjgAKgEAAADOFubwEDAPMSEAAAAQABACOAAqAAAAAMKGRyYwCEoFAAABEvoDAAABBKFAEQ8vsHAAABAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7b6c1a81028e.js b/pr/255/docs/search.index/7b6c1a81028e.js deleted file mode 100644 index e6be82355..000000000 --- a/pr/255/docs/search.index/7b6c1a81028e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQgAOjAAAAEAAAAAAAcAEAAAAEoSSxLcEt0SDxMQE10TXhMjgAKwUBI+AFVmbgEAAbBAEhoAAWU7MAAAAQAADAACAAMHCwA3EAAAI4ACoDAAAAvSYWUzgISwUBKNAAGwEBMqAAEIYAE=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7bb9d7afc6de.js b/pr/255/docs/search.index/7bb9d7afc6de.js deleted file mode 100644 index 7f5c14c95..000000000 --- a/pr/255/docs/search.index/7bb9d7afc6de.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQYA9NoSAAABAFEAAQAjgAKhEAAAE4ljchOAAqAgAAAJG2h5AQEBoGAAABN8c/L9EAAAAQAjgAKwIAl7AAFldQGAArAgD1UAAaCQAAATM2FlAQcBsEATTgABZfUUEwAAAQABAAEAAQABBAGwABIkAAFzOzAAAAEAAAsAAgCYEgcAgRMDAEcAAASGoIAAABJ5sQATjgABsEAR5wABsIATnAABsFASJgABFQAW9AMOAAABAAEAAQCDAISgAAAAEvqwQBOSAAGwMBKsAAFIAAP3GQUAAB8LAQCkAAEABQABAAEDAbBAE2MAAXTyyhIAAAEAI4UCoEAAABL4YnMBAQD0+RAAAAEAAQABABOAAqAQAAAJPGRst+gAAIyg0AAAEoSgUAAAEJigkAAAEqCwUBILAAGgMAAADCK3mAc7MAAAAQAAWgATAMcBAQDMAQEA+AMDAA0GAAD0BgEAigcBAJwHAAAYCQEAJAkAAC8JAABcCQAAOQw3AIMMAAAjDwEA8A8BAAwQAQBSEAEA1BAEAMMRAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7bc6215ea521.js b/pr/255/docs/search.index/7bc6215ea521.js deleted file mode 100644 index 5033277d3..000000000 --- a/pr/255/docs/search.index/7bc6215ea521.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIA9NkQAAABAAEAAQABCgDztBIAAAEAAQDzgQJtdAEGAPOZEAAAAQABAAGCArBgEkEAAbDQE1AAAWlyE4ACsBAMjgABZWkBBQD09BIAAAEARwABAPMEAWPyCRIAAAEAI4ICoFAAABHdZnQBAAGwABNHAAFk9L4LAAABAAEAAQDzgQJlaTcDAACIsTATbAABoFAAABAqsJASGAABsEAQKAABlRAHAScTAAA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7c19fbc10374.js b/pr/255/docs/search.index/7c19fbc10374.js deleted file mode 100644 index 2767d335f..000000000 --- a/pr/255/docs/search.index/7c19fbc10374.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIAOzAAAAEAAAcAAgAyDAUAgBABAAECAPOiEAAAAQABAAEGAPSKEwAAAQABAAEA8wYBbfS2EQAAAQABAAEA84ACbnbzgAJhaQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7c3ea2f4edb6.js b/pr/255/docs/search.index/7c3ea2f4edb6.js deleted file mode 100644 index 1ece895c5..000000000 --- a/pr/255/docs/search.index/7c3ea2f4edb6.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBsAASJAABczswAAABAAALAAIAmBIHAIETAwBHAAAEhqCAAAASebEAE44AAbBAEecAAbCAE5wAAbBQEiYAARUAFvQDDgAAAQABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7c6d85f865c7.js b/pr/255/docs/search.index/7c6d85f865c7.js deleted file mode 100644 index b695cae28..000000000 --- a/pr/255/docs/search.index/7c6d85f865c7.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQBoEAAABCqZQFuDwAAAQgA9OcQAAABAAEAAQABAwGgQAAAEKllAQAPAAABAgDz6QsAAAEAAQAjAAKwIAvZAAFrcvYgBwAAAQAJCeoAAQD8AfOAAnJ4AQMBsIATRwABdjswAAABAAALAAMAPRABAPIQBgC0EgIAI4ACsGAPtAC8YXIBAwGgAAAAD21z8v4OAAABACOAAqCwAAAS2WVoAQMBoEAAABA8ZfIlCQAAAQDXJQAAjLAgB48I3LBwELEAAbAgB3EAAbCwEjIAAaCAAAAQ66AAAAASP78MTDowAAABAAAAAAAJABAAAADPAQsEDAQNBMYLxwsjDCQMJQxAEg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7c7b9eca657f.js b/pr/255/docs/search.index/7c7b9eca657f.js deleted file mode 100644 index 126a52665..000000000 --- a/pr/255/docs/search.index/7c7b9eca657f.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQQAOjAAAAEAAAAAAAcAEAAAABIPEw/RD9IPHhIfEqgSqRIBAAD0EAkAAAEAuwndABcAAACHoEAAABA8sGATUgABoBAAAAw4sFAS8gABsDAQngABsSATcQABOMECOjAAAAEAAAAAAA4AEAAAACUJJgk6CTsJyAvJC8oL0gvTC4IMqxF9En4SARMCEzOAA6CAAAAS+WVveQ==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7ca0ef420c00.js b/pr/255/docs/search.index/7ca0ef420c00.js deleted file mode 100644 index f4f66f1f6..000000000 --- a/pr/255/docs/search.index/7ca0ef420c00.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQUAOzAAAAEAAAcAAwDsEAIAcRIBAAMTAgABBADz7xAAAAEAAQAjAAKgYAAAEf9hcvMWEAAAAQCrAQGAAqEQAAAThbCAE30AAWl1NwQAgoexUBOgAAGACScAFs6wcBLNAAGhMAAAE5QKQBsTgAKwEBILAAFpcg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7cada5462b17.js b/pr/255/docs/search.index/7cada5462b17.js deleted file mode 100644 index b4cb60f11..000000000 --- a/pr/255/docs/search.index/7cada5462b17.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQIBsEATYwABdDswAAABAAANAAYAABIDAGMSAQDKEgEA4RIBAFkTAQB9EwEAE4ACsDASLQE1aXABBQDzohIAAAEAAQATgAKgMAAAEvhleVMAA7BwEwYAAWJlcwFzDwAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7ce0db9b2df8.js b/pr/255/docs/search.index/7ce0db9b2df8.js deleted file mode 100644 index 793a0fe6c..000000000 --- a/pr/255/docs/search.index/7ce0db9b2df8.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQAAOzAAAAEAAAYAAgCAEgAA5RIFACOIArBAE1QAAWVzAQQBsDASVgABY/OtEAAAAQABAAEFADswAAABAAAIAAMAHBECAAQSBAATEwAA8wADY2Vw83QMAAABAAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7da0e5fc56e2.js b/pr/255/docs/search.index/7da0e5fc56e2.js deleted file mode 100644 index a85ebc5a3..000000000 --- a/pr/255/docs/search.index/7da0e5fc56e2.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYMCoFAAABA7oKAAABJJa3ABAAGwQBGiAAFs9HUJAAABAJQGAQABCAD0thEAAAEAAQABAAEEAbAAEBQAAXMBhw8AAAECAaBQAAASDWMBeAwAALcAAACFsEAMsAABoDAAAAvQlQABOzAAAAEAAAgABAAmBQAA4AUCAHsMAQD5DgIAJwEAgIWwMAk6AAGgEAAAEnmwIAefAAGRAEQBEAD0gRMAAAEAAQABAAEDAPR1CQAAAQCUBgEAY4ADoAAAAAvQbnJ1AQACsNASuwABoDAAAA78Ymr2xQUAAAEAAQBIAAEAVgEBAAGwgBLaAAF0OzAAAAEAADoABAANBgAAJAkAAC8JAAA5DDcAAQkA89MRAAABAAEA84ADY2d0AYMCoJAAABMgoJAAABMhMjMBgAKgUAAAE0qggAAAEnZjZfMAAnN08mcHAAABAAEAAaCwAAASvWL1URIAANEAAQBGAAEAI4ACoAAAABJQZHIjgAKgUAAAExJjZfOAAml5AQQA9WYQAAABAAEAAQABAPMBAW4BYQcAAAEBADswAAABAAAJAAIADAgHABQSAQABBgD0sBIAAAEAAQABAAEPAPSKEwAAAQABAAEA84ECaG0BAAGwQBNOAAFl9RQTAAABAAEAAQABAFOAA6AgAAARA2xudNdtAIDLoCAAABN8sGAP+QABsEAPMgABwBs4Cg==") \ No newline at end of file diff --git a/pr/255/docs/search.index/7de8caeba04a.js b/pr/255/docs/search.index/7de8caeba04a.js deleted file mode 100644 index b7d8e6be9..000000000 --- a/pr/255/docs/search.index/7de8caeba04a.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACsFATBgABoAAAAAkaY3QBAQA7MAAAAQAABQABAIYSBQABAwD0lAwAACkGlwABAAGAAqAQAAAMKqBQAAARrGNkAQIA8w8JAAD4AgEA8wABbfMHBQAArgABAAGBAqAQAAASQKBwAAASgWFj8wABcvODBwAATwkZAGcPAICIsDAPCgDEoDAAABN7KTAj") \ No newline at end of file diff --git a/pr/255/docs/search.index/7e247cb6de94.js b/pr/255/docs/search.index/7e247cb6de94.js new file mode 100644 index 000000000..13eef2841 --- /dev/null +++ b/pr/255/docs/search.index/7e247cb6de94.js @@ -0,0 +1 @@ +rn_("AQcA9VETAAABAAEAcAABAAEHAPNtEAAAAQABAAGAAqAAAAAHvKAQAAAJXGR48wEBZfLIDwAAAQDnAAAAhbBgDO8AAbBADG0AATIIAfRQBQAAYgIdCQEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7e614ec002b9.js b/pr/255/docs/search.index/7e614ec002b9.js new file mode 100644 index 000000000..5418e0fb4 --- /dev/null +++ b/pr/255/docs/search.index/7e614ec002b9.js @@ -0,0 +1 @@ +rn_("AQQA9uYTAAABAA0AAQAjAAQAAQMA80kSAAABAAEAI4ECsSAUHQABY2sTgAKgMAAAE6duclMAA6BAAAAMNGVvcvTKEAAAaQGeAQEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7ebc0d37a846.js b/pr/255/docs/search.index/7ebc0d37a846.js new file mode 100644 index 000000000..60c99898d --- /dev/null +++ b/pr/255/docs/search.index/7ebc0d37a846.js @@ -0,0 +1 @@ +rn_("AQYAOzAAAAEAAAkAAQDxEAkAI4ADsGAS+QABsDAPewABaXN0AQgA9a8TAAABAAEAAQABAPMBAWb1QBAAAAEAAQABAAEAY4ADoDAAABLBZWd0") \ No newline at end of file diff --git a/pr/255/docs/search.index/7f51efe5046e.js b/pr/255/docs/search.index/7f51efe5046e.js new file mode 100644 index 000000000..942753c2d --- /dev/null +++ b/pr/255/docs/search.index/7f51efe5046e.js @@ -0,0 +1 @@ +rn_("AQ0A9VETAAABAAEAcAABAAECAPSsEAAAAQB7AQEAAQMA9BgRAAABAGABAQDzAAJidQHHDwAAAQMA9KoQAAABAHsBAQDzhAJkcwECAPNeCQAAAQBUAPOAAml0ARgA8ycUAAABAAEAAYACsLATTwABoMAAABL8ZXXzgQJjbQEFAaBgAAASTnL0NgwAAAEAjgMBAAEJAPZ3EgAAAQDqAH8AMAABABOAArBgEGsAAWRuAQMBoHAAABKqZ/S9BwAAAQDzAQEAAQkA8+YTAAABADUAAYECsIAT9AABoGAAABQYZHMXAQCJhbDQFBoAAaBAAAATyrBgE54ASwKQCmdeAACLsHAQzwABsLASuAABoKAAABJ2sPATfwABbYEP9HcAAAABAAEAAQA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/7fbcc8b0cc40.js b/pr/255/docs/search.index/7fbcc8b0cc40.js deleted file mode 100644 index cb59bc09e..000000000 --- a/pr/255/docs/search.index/7fbcc8b0cc40.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AYACoGAAABL5oKAAABLtYWkBCwD0jxIAAAEAAQABAAEEAPTUDwAAAQABAAEAAQQA9CsQAAABAAEAAQDzgAJscvMAA2NkcwEiEAAA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7fc1150b9f0e.js b/pr/255/docs/search.index/7fc1150b9f0e.js deleted file mode 100644 index a3f60e45c..000000000 --- a/pr/255/docs/search.index/7fc1150b9f0e.js +++ /dev/null @@ -1 +0,0 @@ -rn_("AQcA9c8SAAABAAEAcQABAAEHAPPyDwAAAQABAAGAAqAAAAAHg6AQAAAJGmR48wEBZfJODwAAAQDnAAAAhaBgAAAMkbBADBQAATIIAfQnBQAAUgLbCAEA") \ No newline at end of file diff --git a/pr/255/docs/search.index/7fc1930a76ba.js b/pr/255/docs/search.index/7fc1930a76ba.js new file mode 100644 index 000000000..8d3d7ac56 --- /dev/null +++ b/pr/255/docs/search.index/7fc1930a76ba.js @@ -0,0 +1 @@ +rn_("AQABoJAAABLwaPK6EgAAAQDzAgFk8nkHAAABAAECADswAAABAAAFAAEA9hMFAPMLAW07MAAAAQAABQABALcTBQAjgAKwIAzvAAFhbwECAPNRCQAADwMBAAGKArAAE1cAAbAAE1kAATQ2I4ECoDAAAAyEZXIBgAKwQBGSAAFFmRY6ajdjdbcGAACHsBAP/wABsFAT0wABEVEJ9SUFAAAKALQAAQArBw==") \ No newline at end of file diff --git a/pr/255/docs/search.index/desc/d59362727558.js b/pr/255/docs/search.index/desc/d59362727558.js new file mode 100644 index 000000000..430e62403 --- /dev/null +++ b/pr/255/docs/search.index/desc/d59362727558.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.AoGet the identity of this stream00AfWhich path is now openAjWhich path has been closedB`Which path had its state droppedBaPath for which the error occurredAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa6AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetBcExperimental! Use at your own risk.0ClWhether 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\xa61B`The current best RTT estimation.BeThe amount of I/O operations executed0BcLength 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\xa600: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 length87666CkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000ChThe 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.AcAn open (Multi)PathAb(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 pathCjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBkCurrent congestion window of the connection0gPayloadAoReturns the argument unchanged.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCeMethod for opening a sealed message dataB`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 datagramBlMethod for sealing message data0CiQueue 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 phaseBiConstruct 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\xa6A`Closes this pathAnClose a connection immediatelyAgThe error that occurredBcFrame 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 Endpoint1BcTitle 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\xa6CeChunks returned from RecvStream::read().AmThe initiator of a connection0AdRun as a perf clientAfA path has been closedCgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6CcFuture produced by Connection::open_biAjA new path has been openedChOne 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 connection0AdRun as a perf servermStream 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 close000BhHuman-readable explanation of the reasonBeReason that the connection was closedAjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataAmThe remote side of this tuple1AmTLS 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 remoteCfThe size of a single datagram in the associated bufferCgStatistics about UDP datagrams received on a connection0CjStatistics about UDP datagrams transmitted on a connection0AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0CaA key for sealing data with AEAD-based algorithms0A`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 streamClThe 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 connectionCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header10ClConstructs 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 header10Abiroh NAT TraversalCbCheck 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\xa60BbOne 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 ConnectionAkSet 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\xa60ChResponsible 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.C`Statistics about frames received on a connection0CcStatistics about frames transmitted on a connection0DhConstructs 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\xa6000AmThe local side of this tuple.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\xa600BoAll remaining state for a path has been removedCfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa6CnAt least one new stream of a certain directionality may be \xe2\x80\xa6ClConfiguration for the Bbr congestion controller0BkFuture produced by Path::closeBkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.BgInfallible 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 closedAnApplication events about pathsBiStatistics related to a transmission path0AeA 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 state0BdThe amount of UDP datagrams observedAaControl 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 iCjWait 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 timeCkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CkNumber of frames transmitted or received of each frame type0BoThe connection ID was not recognized by the \xe2\x80\xa60DdThe type used to refer to FrameTypes in closing and \xe2\x80\xa6AnThe QUIC-MULTIPATH path statusBeConfiguration 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\xa60BmCloses a path by sending a PATH_ABANDON frameCdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10BgError code supplied by the peer See \xe2\x80\xa6AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0BfQUIC transport protocol implementationCnWhether 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 toBeThe amount of bytes lost on this path0CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statistics0CjThe final path stats, they are no longer available via \xe2\x80\xa6C`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.0AhA Quinn runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CdLargest UDP payload size the path currently supportsClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00BkStarting 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\xa60AdPacing rate (bits/s)0DiA broadcast receiver of PathEvents for all paths in this \xe2\x80\xa6DfGets 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.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 invalidCaThis is the last path, which can not be abandonedAmIroh\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa6CiFuture produced by Connection::read_datagramBiThe remote changed the status of the pathBlRTT 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\xa6AiA Quinn runtime for TokioC`Returns the lifetime of generated Connection IDs0BlIf the connection is closed, the reason 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\xa6000BgThe amount of packets lost on this path0DcMaximum 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.0CkThe segment size if this transmission contains multiple \xe2\x80\xa600ChThe number of streams that may have unacknowledged data.BgThe amount of packets sent on this path0CbSet 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 Initial0AlThe packet header is invalidBkThe local application closed the connectionAgPath was closed locally1DaThe 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\xa610CnAttempts to read from the stream into the provided buffer, \xe2\x80\xa6AkReturns 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 pathAgThe 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\xa6AfDerive AEAD using hkdf0BnCreate 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.CjUniform interface to send and receive UDP packets with \xe2\x80\xa6DdReturns 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 update0BkConfigures 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 ConnectionAeConnection statistics0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0CfError 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 receivedCaThe 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 pathsClThe 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 abandonedBcA 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 spontaneously0BoLow-level protocol logic for the QUIC protoocolCnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60CeGet 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 connection0B`Constructs controllers on demand0BdCommon congestion controller metrics0AlA pseudo random key for HKDF0BcThe given server name was malformed0AcPacket decode errorBmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BcCongestion events on the connection0AiCongestion 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 statusAjTransport-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\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\xa6CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60BkNo remote CIDs available to open a new pathCkTransport 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.CgPeriod of inactivity before sending a keep-alive packet0CiThe amount of PLPMTUD probe packets lost on this path \xe2\x80\xa60BlPackets 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 SendBufferCiThe amount of PLPMTUD probe packets sent on this path \xe2\x80\xa60Bireceived 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\xa60CiThe remote SocketAddr supplied was malformedCkThe remote address for the path is not supported by the \xe2\x80\xa61ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60BdPaths can only be opened client-sideDmError 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\xa60CiThe number of times a black hole was detected in the path0CgMaximum 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\xa60C`Sets the keep_alive_interval 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\xa60CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0DjA broadcast receiver of iroh_hp::Events for updates about \xe2\x80\xa6CjGet 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 peerCnError when the multipath extension was not negotiated, but \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 changed on our external address as reported by the \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa6CmCreate 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.C`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 connectBmSets the max_idle_timeout for a specific pathBfThe QUIC protocol version implemented.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\xa6CnCreate 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 lost0CnRemoves 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 timeout0BoThe 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/255/docs/search.index/desc/ee2830ff879e.js b/pr/255/docs/search.index/desc/ee2830ff879e.js deleted file mode 100644 index 06a657920..000000000 --- a/pr/255/docs/search.index/desc/ee2830ff879e.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.AoGet the identity of this stream00AfWhich path is now openAjWhich path has been closedB`Which path had its state droppedBaPath for which the error occurredAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa6AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetBcExperimental! Use at your own risk.0ClWhether 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\xa61B`The current best RTT estimation.BeThe amount of I/O operations executed0BcLength 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\xa600: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 length87666CkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000ChThe 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 handshakeAcAn open (Multi)PathAb(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 pathCjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBkCurrent congestion window of the connection0gPayloadAoReturns the argument unchanged.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCeMethod for opening a sealed message dataB`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 datagramBlMethod for sealing message data0CiQueue 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\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 phaseBiConstruct 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\xa6A`Closes this pathAnClose a connection immediatelyAgThe error that occurredBcFrame 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 Endpoint1BcTitle 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\xa6CeChunks returned from RecvStream::read().AmThe initiator of a connection0AdRun as a perf clientAfA path has been closedCgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6CcFuture produced by Connection::open_biAjA new path has been openedChOne 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 connection0AdRun as a perf servermStream 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 close000BhHuman-readable explanation of the reasonBeReason that the connection was closedAjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataAmThe remote side of this tuple1AmTLS 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 remoteCfThe size of a single datagram in the associated bufferCgStatistics about UDP datagrams received on a connection0CjStatistics about UDP datagrams transmitted on a connection0AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0CaA key for sealing data with AEAD-based algorithms0A`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 streamClThe 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 limitClIndicates 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 connectionCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header10ClConstructs 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 header10Abiroh NAT TraversalCbCheck 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\xa60BbOne 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 ConnectionAkSet 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\xa60ChResponsible 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.C`Statistics about frames received on a connection0CcStatistics about frames transmitted on a connection0DhConstructs 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\xa6000AmThe local side of this tuple.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\xa600BoAll remaining state for a path has been removedCfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa6CnAt least one new stream of a certain directionality may be \xe2\x80\xa6ClConfiguration for the Bbr congestion controller0BkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.BgInfallible 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 closedAnApplication events about pathsBiStatistics related to a transmission path0AeA 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 state0BdThe amount of UDP datagrams observedAaControl 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 iCjWait 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 timeCkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CkNumber of frames transmitted or received of each frame type0BoThe connection ID was not recognized by the \xe2\x80\xa6AnThe QUIC-MULTIPATH path statusBeConfiguration 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\xa60BmCloses a path by sending a PATH_ABANDON frameCdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10BgError code supplied by the peer See \xe2\x80\xa6AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0BfQUIC transport protocol implementationCnWhether 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 toBeThe amount of bytes lost on this path0CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statistics0CjThe final path stats, they are no longer available via \xe2\x80\xa6C`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.0AhA Quinn runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CdLargest UDP payload size the path currently supportsClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00BkStarting 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\xa60AdPacing rate (bits/s)0DiA broadcast receiver of PathEvents for all paths in this \xe2\x80\xa6DfGets 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.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 invalidCaThis is the last path, which can not be abandonedAmIroh\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa6CiFuture produced by Connection::read_datagramBiThe remote changed the status of the pathBlRTT 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\xa6AiA Quinn runtime for TokioC`Returns the lifetime of generated Connection IDs0BlIf the connection is closed, the reason 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\xa6000BgThe amount of packets lost on this path0DcMaximum 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.0CkThe segment size if this transmission contains multiple \xe2\x80\xa600ChThe number of streams that may have unacknowledged data.BgThe amount of packets sent on this path0CbSet 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 Initial0AlThe packet header is invalidBkThe local application closed the connectionAgPath was closed locally1DaThe 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\xa610CnAttempts to read from the stream into the provided buffer, \xe2\x80\xa6AkReturns 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 pathAgThe 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 ConnectingCeThe 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\xa6AfDerive AEAD using hkdf0BnCreate 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.CjUniform interface to send and receive UDP packets with \xe2\x80\xa6DdReturns 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 update0BkConfigures 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 ConnectionAeConnection statistics0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0CfError 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\xa60CiReason 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 receivedCaThe 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 pathsClThe 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 abandonedBcA 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 spontaneously0BoLow-level protocol logic for the QUIC protoocolCnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60CeGet 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 connection0B`Constructs controllers on demand0BdCommon congestion controller metrics0AlA pseudo random key for HKDF0BcThe given server name was malformed0AcPacket decode errorBmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BcCongestion events on the connection0AiCongestion 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 statusAjTransport-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\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\xa6CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60BkNo remote CIDs available to open a new pathCkTransport 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.CgPeriod of inactivity before sending a keep-alive packet0CiThe amount of PLPMTUD probe packets lost on this path \xe2\x80\xa60BlPackets 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 SendBufferCiThe amount of PLPMTUD probe packets sent on this path \xe2\x80\xa60Bireceived 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\xa60CiThe remote SocketAddr supplied was malformedCkThe remote address for the path is not supported by the \xe2\x80\xa61ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60BdPaths can only be opened client-sideDmError 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\xa60CiThe number of times a black hole was detected in the path0CgMaximum 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\xa60C`Sets the keep_alive_interval 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\xa60CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0DjA broadcast receiver of iroh_hp::Events for updates about \xe2\x80\xa6CjGet 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 peerBnHeader 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 changed on our external address as reported by the \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa6CnCreate a client configuration that trusts the platform\xe2\x80\x99s \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.C`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 connectBmSets the max_idle_timeout for a specific pathBfThe QUIC protocol version implemented.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\xa6CnCreate 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 lost0CnRemoves 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 timeout0BoThe 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/255/docs/search.index/entry/23e89d8be7e8.js b/pr/255/docs/search.index/entry/23e89d8be7e8.js new file mode 100644 index 000000000..7a877cc5e --- /dev/null +++ b/pr/255/docs/search.index/entry/23e89d8be7e8.js @@ -0,0 +1 @@ +rd_("Ah[3938,15,3939,0,117,0,0]Ak[4725,15,4726,4726,118,0,0]Ai[3938,15,3939,0,4124,0,0]Al[4725,15,4726,1930,4125,0,0]Al[4431,15,4432,4432,4126,0,0]Al[4725,15,1836,1836,1589,0,0]Ao[1361,13,1362,1362,3970,3132,0]Ao[3938,13,3939,3702,4767,3132,0]Ao[3938,13,3939,4074,4391,3132,0]Ao[3938,13,3939,4074,3140,3132,0]Ao[3938,13,3939,4074,3327,3132,0]Ao[3938,13,3939,4074,4390,3132,0]Ao[3938,13,3939,4079,3345,3132,0]Ao[3938,13,3939,4079,4158,3132,0]Al[3938,13,3939,0,1599,3132,0]Al[3938,13,3939,0,4926,3132,0]Al[3938,13,3939,0,1320,3132,0]Al[3938,13,3939,0,1582,3132,0]Al[3938,13,3939,0,3137,3132,0]Al[3938,13,3939,0,2010,3132,0]Al[3938,13,3939,0,4110,3132,0]Al[3938,13,3939,0,4485,3132,0]Al[3938,13,3939,0,3983,3132,0]Al[3938,13,3939,0,3973,3132,0]Al[3938,13,3939,0,3120,3132,0]Al[3938,13,3939,0,4482,3132,0]Al[3938,13,3939,0,4670,3132,0]Al[3938,13,3939,0,4116,3132,0]Al[3938,13,3939,0,4119,3132,0]Al[3938,13,3939,0,4124,3132,0]Al[3938,13,3939,0,4825,3132,0]Ak[3938,13,3939,0,481,3132,0]Ak[3938,13,3939,0,117,3132,0]Al[3938,13,3939,0,2414,3132,0]Al[3938,13,1840,0,5072,3132,0]Al[3938,13,1919,0,1337,3132,0]Ao[4725,13,4726,1952,1600,3132,0]Ao[4725,13,4726,1952,4927,3132,0]Ao[4725,13,4726,3156,1321,3132,0]Ao[4725,13,4726,3165,4768,3132,0]Ao[4725,13,4726,1522,1583,3132,0]Ao[4725,13,4726,1522,3321,3132,0]Ao[4725,13,4726,1522,3136,3132,0]Ao[4725,13,4726,1522,4822,3132,0]Ao[4725,13,4726,1522,3296,3132,0]Ao[4725,13,4726,1538,3138,3132,0]Ao[4725,13,4726,1071,3141,3132,0]Ao[4725,13,4726,1071,4280,3132,0]Ao[4725,13,4726,1076,2011,3132,0]Ao[4725,13,4726,1076,3346,3132,0]Ao[4725,13,4726,1076,3982,3132,0]Ao[4725,13,4726,2144,4000,3132,0]Ao[4725,13,4726,2144,4392,3132,0]Ao[4725,13,4726,2144,4114,3132,0]Ao[4725,13,4726,3703,4486,3132,0]Ao[4725,13,4726,3703,3133,3132,0]Ao[4725,13,4726,3703,4358,3132,0]Ao[4725,13,4726,3283,3984,3132,0]Ao[4725,13,4726,1838,3974,3132,0]Ao[4725,13,4726,1512,3121,3132,0]Ao[4725,13,4726,1512,4373,3132,0]Ao[4725,13,4726,1512,3313,3132,0]Ao[4725,13,4726,1512,3335,3132,0]Ao[4725,13,4726,1512,4121,3132,0]Ao[4725,13,4726,1512,4484,3132,0]Ao[4725,13,4726,1512,4672,3132,0]Ao[4725,13,4726,2437,4676,3132,0]Ao[4725,13,4726,2437,4117,3132,0]Ao[4725,13,4726,1903,2398,3132,0]Ao[4725,13,4726,1903,4766,3132,0]Ao[4725,13,4726,1930,4120,3132,0]Ao[4725,13,4726,1930,4125,3132,0]Al[4725,13,4726,0,4396,3132,0]Al[4725,13,4726,0,4826,3132,0]An[4725,13,4726,4726,482,3132,0]An[4725,13,4726,4726,118,3132,0]Ao[4725,13,4726,4726,2415,3132,0]Ao[4725,13,4726,4726,3119,3132,0]Ao[4725,13,1836,1836,4286,3132,0]Ao[4725,13,4968,4968,4867,3132,0]Ao[4725,13,4968,4968,1339,3132,0]Ao[4725,13,1841,1841,5073,3132,0]Al[4725,13,1920,0,1338,3132,0]Ao[4431,13,4432,4432,4126,3132,0]Ak[3938,13,3939,1045,474,0,0]Al[3938,13,3939,4074,3325,0,0]Al[3938,13,3939,4074,4868,0,0]Al[3938,13,3939,4079,3331,0,0]Ai[4725,14,3134,0,1576,0,0]Ai[4725,14,3134,0,1566,0,0]Ai[4725,14,3134,0,3099,0,0]Ai[4725,14,3134,0,4263,0,0]Ai[4725,14,3134,0,4145,0,0]Ai[4725,14,3134,0,4138,0,0]Ai[4725,14,3999,0,2408,0,0]Ai[4725,14,3999,0,2429,0,0]Ai[4725,14,3999,0,2393,0,0]Ai[4725,14,3999,0,1999,0,0]Ae[1361,7,1362,0,0,0,0]Ah[4725,14,4497,0,470,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Ag[3938,5,3697,133,0,0,0]Ag[4725,5,3698,133,0,0,0]Al[1046,15,1047,1047,4860,0,0]Ae[3958,5,3959,0,0,0,0]Ah[3938,6,3939,4726,0,0,0]Ae[4725,6,4726,0,0,0,0]Al[4725,15,1836,1836,1589,0,0]Ai[3938,19,3939,0,1599,0,0]Ai[3938,19,3939,0,1582,0,0]Al[4725,19,4726,1952,1600,0,0]Al[4725,19,4726,1522,1583,0,0]Ae[1361,5,1362,0,0,0,0]Ae[1046,5,1830,0,0,0,0]Ae[1046,5,1925,0,0,0,0]Ah[3938,15,3939,0,117,0,0]Ak[4725,15,4726,4726,118,0,0]Ak[3938,13,3939,0,1599,128,0]Ak[3938,13,3939,0,1582,128,0]Ak[3938,13,3939,0,3983,128,0]Ak[3938,13,3939,0,4119,128,0]Aj[3938,13,3939,0,481,128,0]Aj[3938,13,3939,0,117,128,0]Ak[3938,13,3939,0,2414,128,0]An[4725,13,4726,1952,1600,128,0]An[4725,13,4726,3165,4768,128,0]An[4725,13,4726,1522,1583,128,0]An[4725,13,4726,1071,3141,128,0]An[4725,13,4726,1071,4280,128,0]An[4725,13,4726,1076,3346,128,0]An[4725,13,4726,3283,3984,128,0]An[4725,13,4726,2437,4676,128,0]An[4725,13,4726,1903,4766,128,0]An[4725,13,4726,1930,4120,128,0]Am[4725,13,4726,4726,482,128,0]Am[4725,13,4726,4726,118,128,0]An[4725,13,4726,4726,2415,128,0]Ai[3938,13,3939,0,2414,0,0]Al[4725,13,4726,4726,2415,0,0]Ai[4725,14,3999,0,1577,0,0]Ai[4725,14,3999,0,3105,0,0]Ai[3938,14,3939,0,2423,0,0]Al[4725,14,4726,4726,2424,0,0]Al[4431,14,4432,4432,2412,0,0]Al[4431,14,4432,4432,2425,0,0]An[1361,13,1362,1362,125,1327,0]Ao[1361,13,1362,1362,3970,1327,0]Ao[1361,13,1536,1536,4393,1327,0]Ao[4007,13,4008,4008,5014,1327,0]Ao[3938,13,3939,3702,3298,1327,0]Ao[3938,13,3939,3702,3300,1327,0]Ao[3938,13,3939,3702,4929,1327,0]Dd[3938,13,3939,3702,4767,1971,0,\"impl-Display-for-SendDatagramError\"]Db[3938,13,3939,3702,4767,1327,0,\"impl-Debug-for-SendDatagramError\"]Ao[3938,13,3939,2436,2391,1327,0]Ao[3938,13,3939,2436,4253,1327,0]Ao[3938,13,3939,2463,2395,1327,0]Cm[3938,13,3939,2463,3328,1971,0,\"impl-Display-for-RetryError\"]Ck[3938,13,3939,2463,3328,1327,0,\"impl-Debug-for-RetryError\"]Ao[3938,13,3939,2463,4372,1327,0]An[3938,13,3939,1045,474,1327,0]Ao[3938,13,3939,4074,3325,1327,0]Ao[3938,13,3939,4074,4868,1327,0]Da[3938,13,3939,4074,4391,1971,0,\"impl-Display-for-ReadToEndError\"]Co[3938,13,3939,4074,4391,1327,0,\"impl-Debug-for-ReadToEndError\"]Cj[3938,13,3939,4074,3140,1327,0,\"impl-Debug-for-ReadError\"]Cl[3938,13,3939,4074,3140,1971,0,\"impl-Display-for-ReadError\"]Ck[3938,13,3939,4074,3327,1327,0,\"impl-Debug-for-ResetError\"]Cm[3938,13,3939,4074,3327,1971,0,\"impl-Display-for-ResetError\"]Da[3938,13,3939,4074,4390,1971,0,\"impl-Display-for-ReadExactError\"]Co[3938,13,3939,4074,4390,1327,0,\"impl-Debug-for-ReadExactError\"]Ao[3938,13,3939,1548,4159,1327,0]Ao[3938,13,3939,1088,3996,1327,0]Ao[3938,13,3939,4079,3331,1327,0]Ck[3938,13,3939,4079,3345,1327,0,\"impl-Debug-for-WriteError\"]Cm[3938,13,3939,4079,3345,1971,0,\"impl-Display-for-WriteError\"]Cm[3938,13,3939,4079,4158,1327,0,\"impl-Debug-for-StoppedError\"]Co[3938,13,3939,4079,4158,1971,0,\"impl-Display-for-StoppedError\"]Cf[3938,13,3939,0,1599,1971,0,\"impl-Display-for-VarInt\"]Cd[3938,13,3939,0,1599,1327,0,\"impl-Debug-for-VarInt\"]Dd[3938,13,3939,0,4926,1971,0,\"impl-Display-for-VarIntBoundsExceeded\"]Db[3938,13,3939,0,4926,1327,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Al[3938,13,3939,0,1320,1327,0]Cd[3938,13,3939,0,1582,1327,0,\"impl-Debug-for-PathId\"]Cf[3938,13,3939,0,1582,1971,0,\"impl-Display-for-PathId\"]Al[3938,13,3939,0,2426,1327,0]Al[3938,13,3939,0,3306,1327,0]Al[3938,13,3939,0,3137,1327,0]Al[3938,13,3939,0,4489,1327,0]Al[3938,13,3939,0,2010,1327,0]Cj[3938,13,3939,0,4110,1327,0,\"impl-Debug-for-ClosedStream\"]Cl[3938,13,3939,0,4110,1971,0,\"impl-Display-for-ClosedStream\"]Cm[3938,13,3939,0,4485,1327,0,\"impl-Debug-for-ConnectionError\"]Co[3938,13,3939,0,4485,1971,0,\"impl-Display-for-ConnectionError\"]Al[3938,13,3939,0,4499,1327,0]Al[3938,13,3939,0,4506,1327,0]Al[3938,13,3939,0,4791,1327,0]Al[3938,13,3939,0,4806,1327,0]Al[3938,13,3939,0,3983,1327,0]Al[3938,13,3939,0,4367,1327,0]Al[3938,13,3939,0,4152,1327,0]Al[3938,13,3939,0,4983,1327,0]Al[3938,13,3939,0,4104,1327,0]Ci[3938,13,3939,0,3973,1327,0,\"impl-Debug-for-ConfigError\"]Ck[3938,13,3939,0,3973,1971,0,\"impl-Display-for-ConfigError\"]Ci[3938,13,3939,0,3120,1971,0,\"impl-Display-for-FrameType\"]Cg[3938,13,3939,0,3120,1327,0,\"impl-Debug-for-FrameType\"]Co[3938,13,3939,0,4482,1971,0,\"impl-Display-for-ConnectionClose\"]Cm[3938,13,3939,0,4482,1327,0,\"impl-Debug-for-ConnectionClose\"]Cn[3938,13,3939,0,4670,1327,0,\"impl-Debug-for-ApplicationClose\"]D`[3938,13,3939,0,4670,1971,0,\"impl-Display-for-ApplicationClose\"]Cj[3938,13,3939,0,4116,1327,0,\"impl-Debug-for-ConnectError\"]Cl[3938,13,3939,0,4116,1971,0,\"impl-Display-for-ConnectError\"]Cl[3938,13,3939,0,4119,1971,0,\"impl-Display-for-ConnectionId\"]Cj[3938,13,3939,0,4119,1327,0,\"impl-Debug-for-ConnectionId\"]Al[3938,13,3939,0,4124,1327,0]Db[3938,13,3939,0,4825,1971,0,\"impl-Display-for-TransportErrorCode\"]D`[3938,13,3939,0,4825,1327,0,\"impl-Debug-for-TransportErrorCode\"]Al[3938,13,3939,0,3309,1327,0]Al[3938,13,3939,0,4701,1327,0]Ak[3938,13,3939,0,481,1327,0]C`[3938,13,3939,0,117,1327,0,\"impl-Debug-for-Dir\"]Cb[3938,13,3939,0,117,1971,0,\"impl-Display-for-Dir\"]Cf[3938,13,3939,0,2414,1327,0,\"impl-Debug-for-StreamId\"]Ch[3938,13,3939,0,2414,1971,0,\"impl-Display-for-StreamId\"]Al[3938,13,3939,0,2423,1327,0]Ak[3938,13,3697,0,111,1327,0]Al[3938,13,3697,0,3108,1327,0]Al[3938,13,3697,0,1324,1327,0]Al[3938,13,3697,0,3978,1327,0]Al[3938,13,3697,0,1984,1327,0]Al[3938,13,3697,0,4272,1327,0]Al[3938,13,3697,0,4759,1327,0]Al[3938,13,1840,0,5072,1327,0]Al[3938,13,1840,0,3976,1327,0]Al[3938,13,1840,0,4829,1327,0]Dd[3938,13,1919,0,4922,1971,0,\"impl-Display-for-NoInitialCipherSuite\"]Db[3938,13,1919,0,4922,1327,0,\"impl-Debug-for-NoInitialCipherSuite\"]Cc[3938,13,1919,0,1337,1327,0,\"impl-Debug-for-Error\"]Ce[3938,13,1919,0,1337,1971,0,\"impl-Display-for-Error\"]Ao[4725,13,4726,3703,3301,1327,0]Ao[4725,13,4726,2437,2392,1327,0]Ci[4725,13,4726,1952,1600,1971,0,\"impl-Display-for-VarInt\"]Cg[4725,13,4726,1952,1600,1327,0,\"impl-Debug-for-VarInt\"]Dg[4725,13,4726,1952,4927,1971,0,\"impl-Display-for-VarIntBoundsExceeded\"]De[4725,13,4726,1952,4927,1327,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Ao[4725,13,4726,3156,1321,1327,0]Db[4725,13,4726,3165,4768,1327,0,\"impl-Debug-for-SendDatagramError\"]Dd[4725,13,4726,3165,4768,1971,0,\"impl-Display-for-SendDatagramError\"]Cg[4725,13,4726,1522,1583,1327,0,\"impl-Debug-for-PathId\"]Ci[4725,13,4726,1522,1583,1971,0,\"impl-Display-for-PathId\"]Ao[4725,13,4726,1522,4148,1327,0]Ao[4725,13,4726,1522,3321,1327,0]Ao[4725,13,4726,1522,3136,1327,0]Dc[4725,13,4726,1522,4822,1327,0,\"impl-Debug-for-SetPathStatusError\"]De[4725,13,4726,1522,4822,1971,0,\"impl-Display-for-SetPathStatusError\"]Cm[4725,13,4726,1522,3296,1971,0,\"impl-Display-for-ClosedPath\"]Ck[4725,13,4726,1522,3296,1327,0,\"impl-Debug-for-ClosedPath\"]Ao[4725,13,4726,1538,2427,1327,0]Ao[4725,13,4726,1538,3307,1327,0]Ao[4725,13,4726,1538,3138,1327,0]Ao[4725,13,4726,1538,4490,1327,0]Cl[4725,13,4726,1071,3141,1971,0,\"impl-Display-for-ReadError\"]Cj[4725,13,4726,1071,3141,1327,0,\"impl-Debug-for-ReadError\"]D`[4725,13,4726,1071,4280,1971,0,\"impl-Display-for-ReadableError\"]Cn[4725,13,4726,1071,4280,1327,0,\"impl-Debug-for-ReadableError\"]Ao[4725,13,4726,1076,2011,1327,0]Cm[4725,13,4726,1076,3346,1971,0,\"impl-Display-for-WriteError\"]Ck[4725,13,4726,1076,3346,1327,0,\"impl-Debug-for-WriteError\"]Cl[4725,13,4726,1076,3982,1327,0,\"impl-Debug-for-FinishError\"]Cn[4725,13,4726,1076,3982,1971,0,\"impl-Display-for-FinishError\"]Ao[4725,13,4726,2144,4000,1327,0]Ao[4725,13,4726,2144,4392,1327,0]Co[4725,13,4726,2144,4114,1971,0,\"impl-Display-for-ClosedStream\"]Cm[4725,13,4726,2144,4114,1327,0,\"impl-Debug-for-ClosedStream\"]Db[4725,13,4726,3703,4486,1971,0,\"impl-Display-for-ConnectionError\"]D`[4725,13,4726,3703,4486,1327,0,\"impl-Debug-for-ConnectionError\"]Cl[4725,13,4726,3703,3133,1971,0,\"impl-Display-for-PathError\"]Cj[4725,13,4726,3703,3133,1327,0,\"impl-Debug-for-PathError\"]Co[4725,13,4726,3703,4358,1327,0,\"impl-Debug-for-ClosePathError\"]Da[4725,13,4726,3703,4358,1971,0,\"impl-Display-for-ClosePathError\"]Dg[4725,13,4726,3703,5010,1327,0,\"impl-Debug-for-MultipathNotNegotiated\"]Di[4725,13,4726,3703,5010,1971,0,\"impl-Display-for-MultipathNotNegotiated\"]Ao[4725,13,4726,3703,1342,1327,0]Ao[4725,13,4726,1067,4500,1327,0]Ao[4725,13,4726,3283,4507,1327,0]Ao[4725,13,4726,3283,4792,1327,0]Ao[4725,13,4726,3283,4807,1327,0]Ao[4725,13,4726,3283,3984,1327,0]Ao[4725,13,4726,1838,4368,1327,0]Ao[4725,13,4726,1838,4154,1327,0]Ao[4725,13,4726,1838,4984,1327,0]Ao[4725,13,4726,1838,4106,1327,0]Cn[4725,13,4726,1838,3974,1971,0,\"impl-Display-for-ConfigError\"]Cl[4725,13,4726,1838,3974,1327,0,\"impl-Debug-for-ConfigError\"]Cl[4725,13,4726,1512,3121,1971,0,\"impl-Display-for-FrameType\"]Cj[4725,13,4726,1512,3121,1327,0,\"impl-Debug-for-FrameType\"]Ao[4725,13,4726,1512,4373,1327,0]Cm[4725,13,4726,1512,3313,1971,0,\"impl-Display-for-MaybeFrame\"]Ck[4725,13,4726,1512,3313,1327,0,\"impl-Debug-for-MaybeFrame\"]Ck[4725,13,4726,1512,3335,1327,0,\"impl-Debug-for-StreamInfo\"]Cm[4725,13,4726,1512,3335,1971,0,\"impl-Display-for-StreamInfo\"]Co[4725,13,4726,1512,4121,1971,0,\"impl-Display-for-DatagramInfo\"]Cm[4725,13,4726,1512,4121,1327,0,\"impl-Debug-for-DatagramInfo\"]D`[4725,13,4726,1512,4484,1327,0,\"impl-Debug-for-ConnectionClose\"]Db[4725,13,4726,1512,4484,1971,0,\"impl-Display-for-ConnectionClose\"]Dc[4725,13,4726,1512,4672,1971,0,\"impl-Display-for-ApplicationClose\"]Da[4725,13,4726,1512,4672,1327,0,\"impl-Debug-for-ApplicationClose\"]Ao[4725,13,4726,1512,2385,1327,0]Ao[4725,13,4726,2437,4676,1327,0]Ao[4725,13,4726,2437,2396,1327,0]Co[4725,13,4726,2437,4117,1971,0,\"impl-Display-for-ConnectError\"]Cm[4725,13,4726,2437,4117,1327,0,\"impl-Debug-for-ConnectError\"]Ao[4725,13,4726,2437,3968,1327,0]Cm[4725,13,4726,2437,3329,1971,0,\"impl-Display-for-RetryError\"]Ck[4725,13,4726,2437,3329,1327,0,\"impl-Debug-for-RetryError\"]Ao[4725,13,4726,1903,4275,1327,0]Ao[4725,13,4726,1903,4498,1327,0]Ao[4725,13,4726,1903,5013,1327,0]Ao[4725,13,4726,1903,2398,1327,0]Dd[4725,13,4726,1903,4766,1971,0,\"impl-Display-for-PacketDecodeError\"]Db[4725,13,4726,1903,4766,1327,0,\"impl-Debug-for-PacketDecodeError\"]Ao[4725,13,4726,1930,4488,1327,0]Ao[4725,13,4726,1930,4252,1327,0]Cm[4725,13,4726,1930,4120,1327,0,\"impl-Debug-for-ConnectionId\"]Co[4725,13,4726,1930,4120,1971,0,\"impl-Display-for-ConnectionId\"]Ao[4725,13,4726,1930,4125,1327,0]Ce[4725,13,4726,0,4396,1971,0,\"impl-Display-for-Error\"]Cc[4725,13,4726,0,4396,1327,0,\"impl-Debug-for-Error\"]Cd[4725,13,4726,0,4826,1971,0,\"impl-Display-for-Code\"]Cb[4725,13,4726,0,4826,1327,0,\"impl-Debug-for-Code\"]Ao[4725,13,4726,4293,3310,1327,0]Ao[4725,13,4726,4293,5106,1327,0]Ao[4725,13,4726,4856,4702,1327,0]An[4725,13,4726,4726,482,1327,0]Cc[4725,13,4726,4726,118,1327,0,\"impl-Debug-for-Dir\"]Ce[4725,13,4726,4726,118,1971,0,\"impl-Display-for-Dir\"]Ck[4725,13,4726,4726,2415,1971,0,\"impl-Display-for-StreamId\"]Ci[4725,13,4726,4726,2415,1327,0,\"impl-Debug-for-StreamId\"]Ao[4725,13,4726,4726,2424,1327,0]Cj[4725,13,4726,4726,3119,1327,0,\"impl-Debug-for-FourTuple\"]Cl[4725,13,4726,4726,3119,1971,0,\"impl-Display-for-FourTuple\"]Cn[4725,13,1836,1836,4286,1327,0,\"impl-Debug-for-UnexpectedEnd\"]D`[4725,13,1836,1836,4286,1971,0,\"impl-Display-for-UnexpectedEnd\"]Ao[4725,13,4968,4968,4867,1327,0]Ch[4725,13,4968,4968,1339,1971,0,\"impl-Display-for-Error\"]Cf[4725,13,4968,4968,1339,1327,0,\"impl-Debug-for-Error\"]Ao[4725,13,1841,1841,5073,1327,0]Ao[4725,13,1841,1841,3977,1327,0]Ao[4725,13,1841,1841,4832,1327,0]Dg[4725,13,1920,1920,4923,1971,0,\"impl-Display-for-NoInitialCipherSuite\"]De[4725,13,1920,1920,4923,1327,0,\"impl-Debug-for-NoInitialCipherSuite\"]Cc[4725,13,1920,0,1338,1327,0,\"impl-Debug-for-Error\"]Ce[4725,13,1920,0,1338,1971,0,\"impl-Display-for-Error\"]Am[4725,13,3698,133,112,1327,0]An[4725,13,3698,133,3109,1327,0]Ao[4725,13,3698,1507,1325,1327,0]Ao[4725,13,3698,1507,3979,1327,0]Ao[4725,13,3698,2485,1985,1327,0]Ao[4725,13,3698,2485,4273,1327,0]Ao[4725,13,3698,3698,4760,1327,0]Cf[4725,13,2115,2115,1340,1327,0,\"impl-Debug-for-Error\"]Ch[4725,13,2115,2115,1340,1971,0,\"impl-Display-for-Error\"]Ao[4725,13,2115,2115,1343,1327,0]An[4431,13,4432,389,4397,1327,0]Ao[4431,13,4432,4432,2412,1327,0]Ao[4431,13,4432,4432,2425,1327,0]Ao[4431,13,4432,4432,4126,1327,0]Al[4725,13,4726,1522,4148,0,0]Ai[3938,14,3939,0,2426,0,0]Al[4725,14,4726,1538,2427,0,0]Al[4725,13,4726,1903,4275,0,0]Al[4725,14,4726,1903,5013,0,0]Ah[4725,14,4497,0,470,0,0]Al[4431,14,4432,4432,2412,0,0]Ai[3938,13,3939,0,4983,0,0]Al[4725,13,4726,1838,4984,0,0]8Al[1361,13,1536,1536,4393,0,0]Al[4007,13,4008,4008,5014,0,0]Ai[3938,13,3939,0,4244,0,0]Al[3938,13,3939,2436,2391,0,0]Ai[3938,13,3939,0,3322,0,0]Ai[3938,13,3939,0,4499,0,0]Ai[3938,13,3939,0,4367,0,0]Ai[3938,13,3939,0,4152,0,0]Ai[3938,13,3939,0,4104,0,0]Ai[3938,13,3939,0,4119,0,0]Ai[3938,13,3939,0,4701,0,0]Ai[3938,13,3939,0,2414,0,0]Ah[3938,13,3697,0,111,0,0]Ai[3938,13,3697,0,1324,0,0]Ai[3938,13,3697,0,1984,0,0]Al[4725,13,4726,4516,4245,0,0]Al[4725,13,4726,1067,3323,0,0]Al[4725,13,4726,2437,2392,0,0]Al[4725,13,4726,1903,5131,0,0]Al[4725,13,4726,4293,5101,0,0]Al[4725,13,4726,1067,4500,0,0]Al[4725,13,4726,1838,4368,0,0]Al[4725,13,4726,1838,4154,0,0]Al[4725,13,4726,1838,4106,0,0]Al[4725,13,4726,1903,4275,0,0]Al[4725,13,4726,1930,4120,0,0]Ai[4725,13,4726,0,4396,0,0]Al[4725,13,4726,4293,5106,0,0]Al[4725,13,4726,4856,4702,0,0]Al[4725,13,4726,4726,2415,0,0]Aj[4725,13,3698,133,112,0,0]Al[4725,13,3698,1507,1325,0,0]Al[4725,13,3698,2485,1985,0,0]Ak[4431,13,4432,389,4397,0,0]Al[1046,13,4211,4211,5058,0,0]Al[1046,13,4211,4211,5059,0,0]Aj[3938,13,3939,0,481,124,0]Am[4725,13,4726,4726,482,124,0]Ai[3938,12,3939,0,3338,0,0]Al[3938,13,3939,2136,1996,0,0]0Ao[3938,13,3939,1548,4159,1996,0]Al[3938,13,3939,0,4284,3338,0]Al[4725,12,4726,1838,3339,0,0]Ao[4725,13,4726,1838,4285,3339,0]Al[3938,13,3939,3702,3300,0,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,13,4726,3703,3301,0,0]Al[4725,14,4726,1538,3138,0,0]Ae[1046,7,1830,0,0,0,0]Ae[1046,7,1925,0,0,0,0]Ae[3938,4,3939,0,0,0,0]Ai[3938,15,3939,0,4124,0,0]Al[4725,15,4726,1930,4125,0,0]Al[4431,15,4432,4432,4126,0,0]210Ah[3938,5,1840,1841,0,0,0]Ae[4725,5,1841,0,0,0,0]Al[4725,15,4726,1903,4498,0,0]Al[4725,15,4726,1512,3313,0,0]Ah[3938,5,3939,1045,0,0,0]Al[4725,15,4726,3703,1342,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Al[3938,15,3939,4074,4391,0,0]Ah[3938,6,3939,4726,0,0,0]Ae[4725,6,4726,0,0,0,0]Ai[3938,19,3939,0,1582,0,0]Al[4725,19,4726,1522,1583,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Ai[4725,14,3134,0,4138,0,0]Al[4431,14,4432,4432,2412,0,0]Aa[491,3,0,0,0,0,0]Ai[4725,14,4726,0,4396,0,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,14,4726,1538,3138,0,0]Al[4725,14,4726,1512,2385,0,0]An[3938,13,3939,3702,2405,458,0]An[3938,13,3939,2463,2395,458,0]An[3938,13,3939,4074,3325,458,0]An[3938,13,3939,4079,3331,458,0]An[4725,13,4726,1071,1562,458,0]Am[1361,13,1362,1362,125,465,0]An[1361,13,1362,1362,3970,465,0]An[1361,13,1536,1536,4001,465,0]An[1361,13,1536,1536,1357,465,0]An[1361,13,1536,1536,4393,465,0]Ak[491,13,492,492,3971,465,0]An[4007,13,4008,4008,5014,465,0]An[3938,13,3939,3702,4511,465,0]An[3938,13,3939,3702,2405,465,0]Ak[3938,13,3939,0,4244,465,0]An[3938,13,3939,1045,2406,465,0]An[3938,13,3939,1045,3111,465,0]An[3938,13,3939,1045,4668,465,0]An[3938,13,3939,3702,3298,465,0]An[3938,13,3939,3702,3300,465,0]An[3938,13,3939,3702,1987,465,0]An[3938,13,3939,3702,1575,465,0]An[3938,13,3939,3702,3101,465,0]An[3938,13,3939,3702,2379,465,0]An[3938,13,3939,3702,4144,465,0]An[3938,13,3939,3702,4149,465,0]An[3938,13,3939,3702,4929,465,0]An[3938,13,3939,3702,4767,465,0]0An[3938,13,3939,2436,2391,465,0]An[3938,13,3939,2436,4253,465,0]An[3938,13,3939,2436,1554,465,0]An[3938,13,3939,2463,2395,465,0]An[3938,13,3939,2463,3328,465,0]An[3938,13,3939,2463,4372,465,0]Am[3938,13,3939,1045,474,465,0]An[3938,13,3939,4074,3325,465,0]An[3938,13,3939,4074,4868,465,0]An[3938,13,3939,4074,4391,465,0]0Dm[3938,13,3939,4074,3140,465,0,\"impl-From%3CConnectionError%3E-for-ReadError\"]Dh[3938,13,3939,4074,3140,465,0,\"impl-From%3CResetError%3E-for-ReadError\"]An[3938,13,3939,4074,3140,465,0]An[3938,13,3939,4074,3327,465,0]0An[3938,13,3939,4074,4390,465,0]0An[3938,13,3939,1548,4159,465,0]An[3938,13,3939,1088,3996,465,0]An[3938,13,3939,4079,3331,465,0]An[3938,13,3939,4079,3345,465,0]Dn[3938,13,3939,4079,3345,465,0,\"impl-From%3CConnectionError%3E-for-WriteError\"]Dk[3938,13,3939,4079,3345,465,0,\"impl-From%3CStoppedError%3E-for-WriteError\"]Dk[3938,13,3939,4079,3345,465,0,\"impl-From%3CClosedStream%3E-for-WriteError\"]An[3938,13,3939,4079,4158,465,0]0Ak[3938,13,3939,0,3322,465,0]Ak[3938,13,3939,0,4284,465,0]Ak[3938,13,3939,0,4503,465,0]Ak[3938,13,3939,0,4136,465,0]Ak[3938,13,3939,0,4381,465,0]Dj[3938,13,3939,0,1599,465,0,\"impl-From%3CTransportErrorCode%3E-for-VarInt\"]Ak[3938,13,3939,0,1599,465,0]Ck[3938,13,3939,0,1599,465,0,\"impl-From%3Cu32%3E-for-VarInt\"]D`[3938,13,3939,0,1599,465,0,\"impl-From%3CStreamId%3E-for-VarInt\"]Cj[3938,13,3939,0,1599,465,0,\"impl-From%3Cu8%3E-for-VarInt\"]Ck[3938,13,3939,0,1599,465,0,\"impl-From%3Cu16%3E-for-VarInt\"]Ak[3938,13,3939,0,4926,465,0]Ak[3938,13,3939,0,1320,465,0]Ak[3938,13,3939,0,1582,465,0]0Ak[3938,13,3939,0,2426,465,0]Ak[3938,13,3939,0,3306,465,0]Ak[3938,13,3939,0,3137,465,0]Ak[3938,13,3939,0,4489,465,0]Ak[3938,13,3939,0,2010,465,0]Ak[3938,13,3939,0,4110,465,0]Dl[3938,13,3939,0,4485,465,0,\"impl-From%3CCloseReason%3E-for-ConnectionError\"]Do[3938,13,3939,0,4485,465,0,\"impl-From%3CTransportError%3E-for-ConnectionError\"]Df[3938,13,3939,0,4485,465,0,\"impl-From%3CClose%3E-for-ConnectionError\"]Ak[3938,13,3939,0,4485,465,0]Ak[3938,13,3939,0,4499,465,0]Ak[3938,13,3939,0,4506,465,0]Ak[3938,13,3939,0,4791,465,0]Ak[3938,13,3939,0,4806,465,0]Ak[3938,13,3939,0,3983,465,0]0Ak[3938,13,3939,0,4367,465,0]Ak[3938,13,3939,0,4152,465,0]Ak[3938,13,3939,0,4983,465,0]Ak[3938,13,3939,0,4104,465,0]Ea[3938,13,3939,0,3973,465,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]Ak[3938,13,3939,0,3973,465,0]Dl[3938,13,3939,0,3973,465,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]Ak[3938,13,3939,0,3120,465,0]Ak[3938,13,3939,0,4482,465,0]0Ak[3938,13,3939,0,4670,465,0]Ak[3938,13,3939,0,4116,465,0]0Ak[3938,13,3939,0,4119,465,0]Ak[3938,13,3939,0,4124,465,0]Ak[3938,13,3939,0,4825,465,0]0Ak[3938,13,3939,0,3309,465,0]Ak[3938,13,3939,0,4701,465,0]Aj[3938,13,3939,0,481,465,0]Aj[3938,13,3939,0,117,465,0]Ak[3938,13,3939,0,2414,465,0]0Ak[3938,13,3939,0,2423,465,0]Aj[3938,13,3697,0,111,465,0]Ak[3938,13,3697,0,3108,465,0]Ak[3938,13,3697,0,1324,465,0]Ak[3938,13,3697,0,3978,465,0]Ak[3938,13,3697,0,1984,465,0]Ak[3938,13,3697,0,4272,465,0]Ak[3938,13,3697,0,4759,465,0]Ak[3938,13,1840,0,1979,465,0]Aj[3938,13,1840,0,468,465,0]Ak[3938,13,1840,0,5072,465,0]Ak[3938,13,1840,0,3976,465,0]0Ak[3938,13,1840,0,4829,465,0]Ak[3938,13,1919,0,3340,465,0]Ak[3938,13,1919,0,4255,465,0]Ak[3938,13,1919,0,4697,465,0]Ak[3938,13,1919,0,4699,465,0]Ak[3938,13,1919,0,4922,465,0]Ak[3938,13,1919,0,1337,465,0]E`[3938,13,1919,0,1337,465,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]Dg[3938,13,1919,0,1337,465,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]De[3938,13,1919,0,1337,465,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]De[3938,13,1919,0,1337,465,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]Dg[3938,13,1919,0,1337,465,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]Dg[3938,13,1919,0,1337,465,0,\"impl-From%3CCertificateError%3E-for-Error\"]Dn[3938,13,1919,0,1337,465,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]E`[3938,13,1919,0,1337,465,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]Df[3938,13,1919,0,1337,465,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]Df[3938,13,1919,0,1337,465,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Da[3938,13,1919,0,1337,465,0,\"impl-From%3COtherError%3E-for-Error\"]An[4725,13,4726,4516,4245,465,0]An[4725,13,4726,3165,3115,465,0]An[4725,13,4726,1071,1562,465,0]An[4725,13,4726,2144,2004,465,0]An[4725,13,4726,2144,3326,465,0]An[4725,13,4726,2144,3332,465,0]An[4725,13,4726,3703,3301,465,0]An[4725,13,4726,1067,3323,465,0]An[4725,13,4726,1838,4285,465,0]An[4725,13,4726,2437,2392,465,0]An[4725,13,4726,2437,4251,465,0]An[4725,13,4726,1903,5131,465,0]An[4725,13,4726,4293,5101,465,0]An[4725,13,4726,1547,4504,465,0]An[4725,13,4726,1547,4137,465,0]An[4725,13,4726,1547,4382,465,0]Cn[4725,13,4726,1952,1600,465,0,\"impl-From%3Cu32%3E-for-VarInt\"]Dc[4725,13,4726,1952,1600,465,0,\"impl-From%3CStreamId%3E-for-VarInt\"]Co[4725,13,4726,1952,1600,465,0,\"impl-From%3CCode%3E-for-VarInt\"]Cm[4725,13,4726,1952,1600,465,0,\"impl-From%3Cu8%3E-for-VarInt\"]Cn[4725,13,4726,1952,1600,465,0,\"impl-From%3Cu16%3E-for-VarInt\"]An[4725,13,4726,1952,1600,465,0]An[4725,13,4726,1952,4927,465,0]An[4725,13,4726,3156,1321,465,0]An[4725,13,4726,3165,4768,465,0]An[4725,13,4726,1522,1583,465,0]0An[4725,13,4726,1522,4148,465,0]An[4725,13,4726,1522,3321,465,0]An[4725,13,4726,1522,3136,465,0]An[4725,13,4726,1522,4822,465,0]An[4725,13,4726,1522,3296,465,0]An[4725,13,4726,1538,2427,465,0]An[4725,13,4726,1538,3307,465,0]An[4725,13,4726,1538,3138,465,0]An[4725,13,4726,1538,4490,465,0]An[4725,13,4726,1071,3141,465,0]An[4725,13,4726,1071,4280,465,0]An[4725,13,4726,1076,2011,465,0]An[4725,13,4726,1076,3346,465,0]An[4725,13,4726,1076,3982,465,0]An[4725,13,4726,2144,4000,465,0]An[4725,13,4726,2144,4392,465,0]An[4725,13,4726,2144,4114,465,0]An[4725,13,4726,3703,4486,465,0]0An[4725,13,4726,3703,3133,465,0]An[4725,13,4726,3703,4358,465,0]An[4725,13,4726,3703,5010,465,0]An[4725,13,4726,3703,1342,465,0]0An[4725,13,4726,1067,4500,465,0]An[4725,13,4726,3283,4507,465,0]An[4725,13,4726,3283,4792,465,0]An[4725,13,4726,3283,4807,465,0]An[4725,13,4726,3283,3984,465,0]0An[4725,13,4726,1838,4368,465,0]An[4725,13,4726,1838,4154,465,0]An[4725,13,4726,1838,4984,465,0]An[4725,13,4726,1838,4106,465,0]Do[4725,13,4726,1838,3974,465,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]Ed[4725,13,4726,1838,3974,465,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]An[4725,13,4726,1838,3974,465,0]An[4725,13,4726,1512,3121,465,0]An[4725,13,4726,1512,4373,465,0]An[4725,13,4726,1512,3313,465,0]An[4725,13,4726,1512,3335,465,0]An[4725,13,4726,1512,4121,465,0]An[4725,13,4726,1512,4484,465,0]0An[4725,13,4726,1512,4672,465,0]An[4725,13,4726,1512,2385,465,0]An[4725,13,4726,2437,4676,465,0]An[4725,13,4726,2437,2396,465,0]An[4725,13,4726,2437,4117,465,0]0An[4725,13,4726,2437,3968,465,0]An[4725,13,4726,2437,3329,465,0]An[4725,13,4726,1903,4275,465,0]An[4725,13,4726,1903,4498,465,0]An[4725,13,4726,1903,5013,465,0]An[4725,13,4726,1903,2398,465,0]An[4725,13,4726,1903,4766,465,0]0An[4725,13,4726,1930,4488,465,0]An[4725,13,4726,1930,4252,465,0]An[4725,13,4726,1930,4120,465,0]An[4725,13,4726,1930,4125,465,0]Ak[4725,13,4726,0,4396,465,0]0Ak[4725,13,4726,0,4826,465,0]0An[4725,13,4726,4293,3310,465,0]An[4725,13,4726,4293,5106,465,0]An[4725,13,4726,4856,4702,465,0]Am[4725,13,4726,4726,482,465,0]Am[4725,13,4726,4726,118,465,0]An[4725,13,4726,4726,2415,465,0]0An[4725,13,4726,4726,2424,465,0]An[4725,13,4726,4726,3119,465,0]An[4725,13,1836,1836,4286,465,0]An[4725,13,4968,4968,4867,465,0]An[4725,13,4968,4968,1339,465,0]0An[4725,13,1841,1841,1980,465,0]Am[4725,13,1841,1841,469,465,0]An[4725,13,1841,1841,5073,465,0]An[4725,13,1841,1841,3977,465,0]0An[4725,13,1841,1841,4832,465,0]An[4725,13,1920,1920,3341,465,0]An[4725,13,1920,1920,4256,465,0]An[4725,13,1920,1920,4698,465,0]An[4725,13,1920,1920,4700,465,0]An[4725,13,1920,1920,4923,465,0]Dg[4725,13,1920,0,1338,465,0,\"impl-From%3CCertificateError%3E-for-Error\"]Df[4725,13,1920,0,1338,465,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Df[4725,13,1920,0,1338,465,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]Ak[4725,13,1920,0,1338,465,0]E`[4725,13,1920,0,1338,465,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]E`[4725,13,1920,0,1338,465,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]Da[4725,13,1920,0,1338,465,0,\"impl-From%3COtherError%3E-for-Error\"]Dn[4725,13,1920,0,1338,465,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]Dg[4725,13,1920,0,1338,465,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]De[4725,13,1920,0,1338,465,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]De[4725,13,1920,0,1338,465,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]Dg[4725,13,1920,0,1338,465,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]Al[4725,13,3698,133,112,465,0]Am[4725,13,3698,133,3109,465,0]An[4725,13,3698,1507,1325,465,0]An[4725,13,3698,1507,3979,465,0]An[4725,13,3698,2485,1985,465,0]An[4725,13,3698,2485,4273,465,0]An[4725,13,3698,3698,4760,465,0]An[4725,13,2115,2115,1340,465,0]An[4725,13,2115,2115,1343,465,0]An[4431,13,4432,4432,3344,465,0]0Am[4431,13,4432,389,4397,465,0]An[4431,13,4432,4432,2412,465,0]An[4431,13,4432,4432,2425,465,0]An[4431,13,4432,4432,4126,465,0]An[1046,13,1047,1047,3112,465,0]An[1046,13,1047,1047,4860,465,0]Am[1046,13,1830,1830,126,465,0]An[1046,13,1537,1537,1358,465,0]An[1046,13,1537,1537,4002,465,0]An[1046,13,1537,1537,4494,465,0]An[1046,13,4211,4211,5058,465,0]An[1046,13,4211,4211,5059,465,0]Am[1046,13,1925,1925,127,465,0]Am[3958,13,3959,3959,116,465,0]An[3958,13,3959,3959,2382,465,0]Ak[3938,13,3939,0,1599,466,0]Ak[3938,13,3939,0,1582,466,0]Ak[3938,13,3939,0,3983,466,0]Ak[3938,13,3939,0,4119,466,0]Aj[3938,13,3939,0,481,466,0]Aj[3938,13,3939,0,117,466,0]Ak[3938,13,3939,0,2414,466,0]An[4725,13,4726,1952,1600,466,0]An[4725,13,4726,3165,4768,466,0]An[4725,13,4726,1522,1583,466,0]An[4725,13,4726,1071,3141,466,0]An[4725,13,4726,1071,4280,466,0]An[4725,13,4726,1076,3346,466,0]An[4725,13,4726,3283,3984,466,0]An[4725,13,4726,2437,4676,466,0]An[4725,13,4726,1903,4766,466,0]An[4725,13,4726,1930,4120,466,0]Am[4725,13,4726,4726,482,466,0]Am[4725,13,4726,4726,118,466,0]An[4725,13,4726,4726,2415,466,0]An[4725,13,4726,4726,3119,466,0]Am[1361,13,1362,1362,125,467,0]An[1361,13,1362,1362,3970,467,0]An[1361,13,1536,1536,4001,467,0]An[1361,13,1536,1536,1357,467,0]An[1361,13,1536,1536,4393,467,0]Ak[491,13,492,492,3971,467,0]An[4007,13,4008,4008,5014,467,0]An[3938,13,3939,3702,4511,467,0]An[3938,13,3939,3702,2405,467,0]Ak[3938,13,3939,0,4244,467,0]An[3938,13,3939,1045,2406,467,0]An[3938,13,3939,1045,3111,467,0]An[3938,13,3939,1045,4668,467,0]An[3938,13,3939,3702,3298,467,0]An[3938,13,3939,3702,3300,467,0]An[3938,13,3939,3702,1987,467,0]An[3938,13,3939,3702,1575,467,0]An[3938,13,3939,3702,3101,467,0]An[3938,13,3939,3702,2379,467,0]An[3938,13,3939,3702,4144,467,0]An[3938,13,3939,3702,4149,467,0]An[3938,13,3939,3702,4929,467,0]An[3938,13,3939,3702,4767,467,0]An[3938,13,3939,2436,2391,467,0]An[3938,13,3939,2436,4253,467,0]An[3938,13,3939,2436,1554,467,0]An[3938,13,3939,2463,2395,467,0]An[3938,13,3939,2463,3328,467,0]An[3938,13,3939,2463,4372,467,0]Am[3938,13,3939,1045,474,467,0]An[3938,13,3939,4074,3325,467,0]An[3938,13,3939,4074,4868,467,0]An[3938,13,3939,4074,4391,467,0]An[3938,13,3939,4074,3140,467,0]An[3938,13,3939,4074,3327,467,0]An[3938,13,3939,4074,4390,467,0]An[3938,13,3939,1548,4159,467,0]An[3938,13,3939,1088,3996,467,0]An[3938,13,3939,4079,3331,467,0]An[3938,13,3939,4079,3345,467,0]An[3938,13,3939,4079,4158,467,0]Ak[3938,13,3939,0,3322,467,0]Ak[3938,13,3939,0,4284,467,0]Ak[3938,13,3939,0,4503,467,0]Ak[3938,13,3939,0,4136,467,0]Ak[3938,13,3939,0,4381,467,0]Ak[3938,13,3939,0,1599,467,0]Ak[3938,13,3939,0,4926,467,0]Ak[3938,13,3939,0,1320,467,0]Ak[3938,13,3939,0,1582,467,0]Ak[3938,13,3939,0,2426,467,0]Ak[3938,13,3939,0,3306,467,0]Ak[3938,13,3939,0,3137,467,0]Ak[3938,13,3939,0,4489,467,0]Ak[3938,13,3939,0,2010,467,0]Ak[3938,13,3939,0,4110,467,0]Ak[3938,13,3939,0,4485,467,0]Ak[3938,13,3939,0,4499,467,0]Ak[3938,13,3939,0,4506,467,0]Ak[3938,13,3939,0,4791,467,0]Ak[3938,13,3939,0,4806,467,0]Ak[3938,13,3939,0,3983,467,0]Ak[3938,13,3939,0,4367,467,0]Ak[3938,13,3939,0,4152,467,0]Ak[3938,13,3939,0,4983,467,0]Ak[3938,13,3939,0,4104,467,0]Ak[3938,13,3939,0,3973,467,0]Ak[3938,13,3939,0,3120,467,0]Ak[3938,13,3939,0,4482,467,0]Ak[3938,13,3939,0,4670,467,0]Ak[3938,13,3939,0,4116,467,0]Ak[3938,13,3939,0,4119,467,0]Ak[3938,13,3939,0,4124,467,0]Ak[3938,13,3939,0,4825,467,0]Ak[3938,13,3939,0,3309,467,0]Ak[3938,13,3939,0,4701,467,0]Aj[3938,13,3939,0,481,467,0]Aj[3938,13,3939,0,117,467,0]Ak[3938,13,3939,0,2414,467,0]Ak[3938,13,3939,0,2423,467,0]Aj[3938,13,3697,0,111,467,0]Ak[3938,13,3697,0,3108,467,0]Ak[3938,13,3697,0,1324,467,0]Ak[3938,13,3697,0,3978,467,0]Ak[3938,13,3697,0,1984,467,0]Ak[3938,13,3697,0,4272,467,0]Ak[3938,13,3697,0,4759,467,0]Ak[3938,13,1840,0,1979,467,0]Aj[3938,13,1840,0,468,467,0]Ak[3938,13,1840,0,5072,467,0]Ak[3938,13,1840,0,3976,467,0]Ak[3938,13,1840,0,4829,467,0]Ak[3938,13,1919,0,3340,467,0]Ak[3938,13,1919,0,4255,467,0]Ak[3938,13,1919,0,4697,467,0]Ak[3938,13,1919,0,4699,467,0]Ak[3938,13,1919,0,4922,467,0]Ak[3938,13,1919,0,1337,467,0]An[4725,13,4726,4516,4245,467,0]An[4725,13,4726,3165,3115,467,0]An[4725,13,4726,1071,1562,467,0]An[4725,13,4726,2144,2004,467,0]An[4725,13,4726,2144,3326,467,0]An[4725,13,4726,2144,3332,467,0]An[4725,13,4726,3703,3301,467,0]An[4725,13,4726,1067,3323,467,0]An[4725,13,4726,1838,4285,467,0]An[4725,13,4726,2437,2392,467,0]An[4725,13,4726,2437,4251,467,0]An[4725,13,4726,1903,5131,467,0]An[4725,13,4726,4293,5101,467,0]An[4725,13,4726,1547,4504,467,0]An[4725,13,4726,1547,4137,467,0]An[4725,13,4726,1547,4382,467,0]An[4725,13,4726,1952,1600,467,0]An[4725,13,4726,1952,4927,467,0]An[4725,13,4726,3156,1321,467,0]An[4725,13,4726,3165,4768,467,0]An[4725,13,4726,1522,1583,467,0]An[4725,13,4726,1522,4148,467,0]An[4725,13,4726,1522,3321,467,0]An[4725,13,4726,1522,3136,467,0]An[4725,13,4726,1522,4822,467,0]An[4725,13,4726,1522,3296,467,0]An[4725,13,4726,1538,2427,467,0]An[4725,13,4726,1538,3307,467,0]An[4725,13,4726,1538,3138,467,0]An[4725,13,4726,1538,4490,467,0]An[4725,13,4726,1071,3141,467,0]An[4725,13,4726,1071,4280,467,0]An[4725,13,4726,1076,2011,467,0]An[4725,13,4726,1076,3346,467,0]An[4725,13,4726,1076,3982,467,0]An[4725,13,4726,2144,4000,467,0]An[4725,13,4726,2144,4392,467,0]An[4725,13,4726,2144,4114,467,0]An[4725,13,4726,3703,4486,467,0]An[4725,13,4726,3703,3133,467,0]An[4725,13,4726,3703,4358,467,0]An[4725,13,4726,3703,5010,467,0]An[4725,13,4726,3703,1342,467,0]An[4725,13,4726,1067,4500,467,0]An[4725,13,4726,3283,4507,467,0]An[4725,13,4726,3283,4792,467,0]An[4725,13,4726,3283,4807,467,0]An[4725,13,4726,3283,3984,467,0]An[4725,13,4726,1838,4368,467,0]An[4725,13,4726,1838,4154,467,0]An[4725,13,4726,1838,4984,467,0]An[4725,13,4726,1838,4106,467,0]An[4725,13,4726,1838,3974,467,0]An[4725,13,4726,1512,3121,467,0]An[4725,13,4726,1512,4373,467,0]An[4725,13,4726,1512,3313,467,0]An[4725,13,4726,1512,3335,467,0]An[4725,13,4726,1512,4121,467,0]An[4725,13,4726,1512,4484,467,0]An[4725,13,4726,1512,4672,467,0]An[4725,13,4726,1512,2385,467,0]An[4725,13,4726,2437,4676,467,0]An[4725,13,4726,2437,2396,467,0]An[4725,13,4726,2437,4117,467,0]An[4725,13,4726,2437,3968,467,0]An[4725,13,4726,2437,3329,467,0]An[4725,13,4726,1903,4275,467,0]An[4725,13,4726,1903,4498,467,0]An[4725,13,4726,1903,5013,467,0]An[4725,13,4726,1903,2398,467,0]An[4725,13,4726,1903,4766,467,0]An[4725,13,4726,1930,4488,467,0]An[4725,13,4726,1930,4252,467,0]An[4725,13,4726,1930,4120,467,0]An[4725,13,4726,1930,4125,467,0]Ak[4725,13,4726,0,4396,467,0]Ak[4725,13,4726,0,4826,467,0]An[4725,13,4726,4293,3310,467,0]An[4725,13,4726,4293,5106,467,0]An[4725,13,4726,4856,4702,467,0]Am[4725,13,4726,4726,482,467,0]Am[4725,13,4726,4726,118,467,0]An[4725,13,4726,4726,2415,467,0]An[4725,13,4726,4726,2424,467,0]An[4725,13,4726,4726,3119,467,0]An[4725,13,1836,1836,4286,467,0]An[4725,13,4968,4968,4867,467,0]An[4725,13,4968,4968,1339,467,0]An[4725,13,1841,1841,1980,467,0]Am[4725,13,1841,1841,469,467,0]An[4725,13,1841,1841,5073,467,0]An[4725,13,1841,1841,3977,467,0]An[4725,13,1841,1841,4832,467,0]An[4725,13,1920,1920,3341,467,0]An[4725,13,1920,1920,4256,467,0]An[4725,13,1920,1920,4698,467,0]An[4725,13,1920,1920,4700,467,0]An[4725,13,1920,1920,4923,467,0]Ak[4725,13,1920,0,1338,467,0]Al[4725,13,3698,133,112,467,0]Am[4725,13,3698,133,3109,467,0]An[4725,13,3698,1507,1325,467,0]An[4725,13,3698,1507,3979,467,0]An[4725,13,3698,2485,1985,467,0]An[4725,13,3698,2485,4273,467,0]An[4725,13,3698,3698,4760,467,0]An[4725,13,2115,2115,1340,467,0]An[4725,13,2115,2115,1343,467,0]An[4431,13,4432,4432,3344,467,0]Am[4431,13,4432,389,4397,467,0]An[4431,13,4432,4432,2412,467,0]An[4431,13,4432,4432,2425,467,0]An[4431,13,4432,4432,4126,467,0]An[1046,13,1047,1047,3112,467,0]An[1046,13,1047,1047,4860,467,0]Am[1046,13,1830,1830,126,467,0]An[1046,13,1537,1537,1358,467,0]An[1046,13,1537,1537,4002,467,0]An[1046,13,1537,1537,4494,467,0]An[1046,13,4211,4211,5058,467,0]An[1046,13,4211,4211,5059,467,0]Am[1046,13,1925,1925,127,467,0]Am[3958,13,3959,3959,116,467,0]An[3958,13,3959,3959,2382,467,0]Ac[491,7,492,0,0,0,0]Ae[4007,7,4008,0,0,0,0]Ae[4296,7,4297,0,0,0,0]Ae[3958,7,3959,0,0,0,0]Ae[4786,7,4787,0,0,0,0]Al[4725,13,4726,1071,1562,0,0]Ai[3938,12,1840,0,1963,0,0]Al[4725,13,4726,2144,2004,0,0]Al[4725,12,1841,1841,1964,0,0]Al[3938,13,3939,3702,3300,0,0]Ab[1046,3,0,0,0,0,0]Ak[3938,13,3939,1045,474,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,13,4726,3703,3301,0,0]Al[4725,14,4726,1538,3307,0,0]Al[3938,12,3939,2136,3289,0,0]Ao[3938,13,3939,3702,4511,1572,0]Ao[3938,13,3939,3702,2405,1572,0]Ao[3938,13,3939,1045,2406,1572,0]Ao[3938,13,3939,1045,3111,1572,0]Ao[3938,13,3939,3702,3298,1572,0]Ao[3938,13,3939,3702,1987,1572,0]Ao[3938,13,3939,3702,1575,1572,0]Ao[3938,13,3939,3702,3101,1572,0]Ao[3938,13,3939,3702,2379,1572,0]Ao[3938,13,3939,3702,4144,1572,0]Ao[3938,13,3939,3702,4149,1572,0]Ao[3938,13,3939,2436,1554,1572,0]Ao[3938,13,3939,2463,4372,1572,0]?Al[3938,13,3939,4074,3325,0,0]Al[4725,13,4726,2144,3326,0,0]Al[4725,13,4968,4968,4867,0,0]Al[4725,13,4726,3165,3115,0,0]Ak[4431,13,4432,389,4397,0,0]Ai[3938,12,1840,0,1963,0,0]Al[4725,12,1841,1841,1964,0,0]32Ai[3938,13,3939,0,4983,0,0]Al[4725,13,4726,1838,4984,0,0]Al[3938,13,3939,3702,3300,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,12,1840,0,1975,0,0]Al[4725,12,1841,1841,1976,0,0]Al[1361,14,1536,1536,4393,0,0]Ai[3938,14,3939,0,2423,0,0]Al[4725,14,4726,4726,2424,0,0]Ai[4725,14,4497,0,1354,0,0]Al[3938,13,3939,4074,3325,0,0]Al[3938,13,3939,4074,4868,0,0]Al[4725,13,4726,2144,3326,0,0]Ai[3938,12,3939,0,3342,0,0]Al[3938,13,3939,0,4381,3342,0]Al[3938,13,3939,0,4701,3342,0]Al[4725,12,4726,1547,3343,0,0]Ao[4725,13,4726,1547,4382,3343,0]Ao[4725,13,4726,4856,4702,3343,0]Am[1361,13,1362,1362,125,484,0]An[1361,13,1362,1362,3970,484,0]An[1361,13,1536,1536,4001,484,0]An[1361,13,1536,1536,1357,484,0]An[1361,13,1536,1536,4393,484,0]Ak[491,13,492,492,3971,484,0]An[4007,13,4008,4008,5014,484,0]An[3938,13,3939,3702,4511,484,0]An[3938,13,3939,3702,2405,484,0]Ak[3938,13,3939,0,4244,484,0]An[3938,13,3939,1045,2406,484,0]An[3938,13,3939,1045,3111,484,0]An[3938,13,3939,1045,4668,484,0]An[3938,13,3939,3702,3298,484,0]An[3938,13,3939,3702,3300,484,0]An[3938,13,3939,3702,1987,484,0]An[3938,13,3939,3702,1575,484,0]An[3938,13,3939,3702,3101,484,0]An[3938,13,3939,3702,2379,484,0]An[3938,13,3939,3702,4144,484,0]An[3938,13,3939,3702,4149,484,0]An[3938,13,3939,3702,4929,484,0]An[3938,13,3939,3702,4767,484,0]An[3938,13,3939,2436,2391,484,0]An[3938,13,3939,2436,4253,484,0]An[3938,13,3939,2436,1554,484,0]An[3938,13,3939,2463,2395,484,0]An[3938,13,3939,2463,3328,484,0]An[3938,13,3939,2463,4372,484,0]Am[3938,13,3939,1045,474,484,0]An[3938,13,3939,4074,3325,484,0]An[3938,13,3939,4074,4868,484,0]An[3938,13,3939,4074,4391,484,0]An[3938,13,3939,4074,3140,484,0]An[3938,13,3939,4074,3327,484,0]An[3938,13,3939,4074,4390,484,0]An[3938,13,3939,1548,4159,484,0]An[3938,13,3939,1088,3996,484,0]An[3938,13,3939,4079,3331,484,0]An[3938,13,3939,4079,3345,484,0]An[3938,13,3939,4079,4158,484,0]Ak[3938,13,3939,0,3322,484,0]Ak[3938,13,3939,0,4284,484,0]Ak[3938,13,3939,0,4503,484,0]Ak[3938,13,3939,0,4136,484,0]Ak[3938,13,3939,0,4381,484,0]Ak[3938,13,3939,0,1599,484,0]Ak[3938,13,3939,0,4926,484,0]Ak[3938,13,3939,0,1320,484,0]Ak[3938,13,3939,0,1582,484,0]Ak[3938,13,3939,0,2426,484,0]Ak[3938,13,3939,0,3306,484,0]Ak[3938,13,3939,0,3137,484,0]Ak[3938,13,3939,0,4489,484,0]Ak[3938,13,3939,0,2010,484,0]Ak[3938,13,3939,0,4110,484,0]Ak[3938,13,3939,0,4485,484,0]Ak[3938,13,3939,0,4499,484,0]Ak[3938,13,3939,0,4506,484,0]Ak[3938,13,3939,0,4791,484,0]Ak[3938,13,3939,0,4806,484,0]Ak[3938,13,3939,0,3983,484,0]Ak[3938,13,3939,0,4367,484,0]Ak[3938,13,3939,0,4152,484,0]Ak[3938,13,3939,0,4983,484,0]Ak[3938,13,3939,0,4104,484,0]Ak[3938,13,3939,0,3973,484,0]Ak[3938,13,3939,0,3120,484,0]Ak[3938,13,3939,0,4482,484,0]Ak[3938,13,3939,0,4670,484,0]Ak[3938,13,3939,0,4116,484,0]Ak[3938,13,3939,0,4119,484,0]Ak[3938,13,3939,0,4124,484,0]Ak[3938,13,3939,0,4825,484,0]Ak[3938,13,3939,0,3309,484,0]Ak[3938,13,3939,0,4701,484,0]Aj[3938,13,3939,0,481,484,0]Aj[3938,13,3939,0,117,484,0]Ak[3938,13,3939,0,2414,484,0]Ak[3938,13,3939,0,2423,484,0]Aj[3938,13,3697,0,111,484,0]Ak[3938,13,3697,0,3108,484,0]Ak[3938,13,3697,0,1324,484,0]Ak[3938,13,3697,0,3978,484,0]Ak[3938,13,3697,0,1984,484,0]Ak[3938,13,3697,0,4272,484,0]Ak[3938,13,3697,0,4759,484,0]Ak[3938,13,1840,0,1979,484,0]Aj[3938,13,1840,0,468,484,0]Ak[3938,13,1840,0,5072,484,0]Ak[3938,13,1840,0,3976,484,0]Ak[3938,13,1840,0,4829,484,0]Ak[3938,13,1919,0,3340,484,0]Ak[3938,13,1919,0,4255,484,0]Ak[3938,13,1919,0,4697,484,0]Ak[3938,13,1919,0,4699,484,0]Ak[3938,13,1919,0,4922,484,0]Ak[3938,13,1919,0,1337,484,0]An[4725,13,4726,4516,4245,484,0]An[4725,13,4726,3165,3115,484,0]An[4725,13,4726,1071,1562,484,0]An[4725,13,4726,2144,2004,484,0]An[4725,13,4726,2144,3326,484,0]An[4725,13,4726,2144,3332,484,0]An[4725,13,4726,3703,3301,484,0]An[4725,13,4726,1067,3323,484,0]An[4725,13,4726,1838,4285,484,0]An[4725,13,4726,2437,2392,484,0]An[4725,13,4726,2437,4251,484,0]An[4725,13,4726,1903,5131,484,0]An[4725,13,4726,4293,5101,484,0]An[4725,13,4726,1547,4504,484,0]An[4725,13,4726,1547,4137,484,0]An[4725,13,4726,1547,4382,484,0]An[4725,13,4726,1952,1600,484,0]An[4725,13,4726,1952,4927,484,0]An[4725,13,4726,3156,1321,484,0]An[4725,13,4726,3165,4768,484,0]An[4725,13,4726,1522,1583,484,0]An[4725,13,4726,1522,4148,484,0]An[4725,13,4726,1522,3321,484,0]An[4725,13,4726,1522,3136,484,0]An[4725,13,4726,1522,4822,484,0]An[4725,13,4726,1522,3296,484,0]An[4725,13,4726,1538,2427,484,0]An[4725,13,4726,1538,3307,484,0]An[4725,13,4726,1538,3138,484,0]An[4725,13,4726,1538,4490,484,0]An[4725,13,4726,1071,3141,484,0]An[4725,13,4726,1071,4280,484,0]An[4725,13,4726,1076,2011,484,0]An[4725,13,4726,1076,3346,484,0]An[4725,13,4726,1076,3982,484,0]An[4725,13,4726,2144,4000,484,0]An[4725,13,4726,2144,4392,484,0]An[4725,13,4726,2144,4114,484,0]An[4725,13,4726,3703,4486,484,0]An[4725,13,4726,3703,3133,484,0]An[4725,13,4726,3703,4358,484,0]An[4725,13,4726,3703,5010,484,0]An[4725,13,4726,3703,1342,484,0]An[4725,13,4726,1067,4500,484,0]An[4725,13,4726,3283,4507,484,0]An[4725,13,4726,3283,4792,484,0]An[4725,13,4726,3283,4807,484,0]An[4725,13,4726,3283,3984,484,0]An[4725,13,4726,1838,4368,484,0]An[4725,13,4726,1838,4154,484,0]An[4725,13,4726,1838,4984,484,0]An[4725,13,4726,1838,4106,484,0]An[4725,13,4726,1838,3974,484,0]An[4725,13,4726,1512,3121,484,0]An[4725,13,4726,1512,4373,484,0]An[4725,13,4726,1512,3313,484,0]An[4725,13,4726,1512,3335,484,0]An[4725,13,4726,1512,4121,484,0]An[4725,13,4726,1512,4484,484,0]An[4725,13,4726,1512,4672,484,0]An[4725,13,4726,1512,2385,484,0]An[4725,13,4726,2437,4676,484,0]An[4725,13,4726,2437,2396,484,0]An[4725,13,4726,2437,4117,484,0]An[4725,13,4726,2437,3968,484,0]An[4725,13,4726,2437,3329,484,0]An[4725,13,4726,1903,4275,484,0]An[4725,13,4726,1903,4498,484,0]An[4725,13,4726,1903,5013,484,0]An[4725,13,4726,1903,2398,484,0]An[4725,13,4726,1903,4766,484,0]An[4725,13,4726,1930,4488,484,0]An[4725,13,4726,1930,4252,484,0]An[4725,13,4726,1930,4120,484,0]An[4725,13,4726,1930,4125,484,0]Ak[4725,13,4726,0,4396,484,0]Ak[4725,13,4726,0,4826,484,0]An[4725,13,4726,4293,3310,484,0]An[4725,13,4726,4293,5106,484,0]An[4725,13,4726,4856,4702,484,0]Am[4725,13,4726,4726,482,484,0]Am[4725,13,4726,4726,118,484,0]An[4725,13,4726,4726,2415,484,0]An[4725,13,4726,4726,2424,484,0]An[4725,13,4726,4726,3119,484,0]An[4725,13,1836,1836,4286,484,0]An[4725,13,4968,4968,4867,484,0]An[4725,13,4968,4968,1339,484,0]An[4725,13,1841,1841,1980,484,0]Am[4725,13,1841,1841,469,484,0]An[4725,13,1841,1841,5073,484,0]An[4725,13,1841,1841,3977,484,0]An[4725,13,1841,1841,4832,484,0]An[4725,13,1920,1920,3341,484,0]An[4725,13,1920,1920,4256,484,0]An[4725,13,1920,1920,4698,484,0]An[4725,13,1920,1920,4700,484,0]An[4725,13,1920,1920,4923,484,0]Ak[4725,13,1920,0,1338,484,0]Al[4725,13,3698,133,112,484,0]Am[4725,13,3698,133,3109,484,0]An[4725,13,3698,1507,1325,484,0]An[4725,13,3698,1507,3979,484,0]An[4725,13,3698,2485,1985,484,0]An[4725,13,3698,2485,4273,484,0]An[4725,13,3698,3698,4760,484,0]An[4725,13,2115,2115,1340,484,0]An[4725,13,2115,2115,1343,484,0]An[1046,13,1047,1047,3112,484,0]An[1046,13,1047,1047,4860,484,0]Am[1046,13,1830,1830,126,484,0]An[1046,13,1537,1537,1358,484,0]An[1046,13,1537,1537,4002,484,0]An[1046,13,1537,1537,4494,484,0]An[1046,13,4211,4211,5058,484,0]An[1046,13,4211,4211,5059,484,0]Am[1046,13,1925,1925,127,484,0]Am[3958,13,3959,3959,116,484,0]An[3958,13,3959,3959,2382,484,0]Ah[3938,5,3939,3156,0,0,0]Ah[4725,5,4726,3156,0,0,0]Ah[3938,5,3697,1507,0,0,0]Ah[4725,5,3698,1507,0,0,0]Al[1046,15,1047,1047,4860,0,0]Ah[3938,6,1919,1510,0,0,0]Ah[4725,6,1920,1510,0,0,0]Ae[4725,6,4968,0,0,0,0]Ae[4725,6,2115,0,0,0,0]Ah[4725,6,4726,3703,0,0,0]1Al[4725,15,4726,1512,3313,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]Al[3938,15,3939,4074,3140,0,0]Ai[3938,15,3939,0,4485,0,0]Al[4725,15,4726,1071,3141,0,0]Al[4725,15,4726,3703,4486,0,0]Al[4725,15,4726,1903,4498,0,0]0Ae[1361,5,1536,0,0,0,0]Ae[1046,5,1537,0,0,0,0]Ab[1361,3,0,0,0,0,0]Ai[3938,12,3697,0,4757,0,0]Al[3938,13,3697,0,3108,4757,0]Al[3938,13,3697,0,3978,4757,0]Al[3938,13,3697,0,4272,4757,0]Al[4725,12,3698,3698,4758,0,0]An[4725,13,3698,133,3109,4758,0]Ao[4725,13,3698,1507,3979,4758,0]Ao[4725,13,3698,2485,4273,4758,0]Al[1046,13,1047,1047,4860,0,0]Ai[3938,14,3939,0,1320,0,0]Ai[3938,14,3939,0,2426,0,0]Ai[3938,14,3939,0,2010,0,0]Al[4725,14,4726,3156,1321,0,0]Al[4725,14,4726,1538,2427,0,0]Al[4725,14,4726,1076,2011,0,0]Al[4725,14,4726,2437,3968,0,0]An[1361,13,1362,1362,125,1322,0]Ao[1361,13,1362,1362,3970,1322,0]Ao[3938,13,3939,3702,3300,1322,0]Ao[3938,13,3939,3702,4929,1322,0]Ao[3938,13,3939,3702,4767,1322,0]Ao[3938,13,3939,2436,2391,1322,0]Ao[3938,13,3939,2436,4253,1322,0]Ao[3938,13,3939,4074,4391,1322,0]Ao[3938,13,3939,4074,3140,1322,0]Ao[3938,13,3939,4074,3327,1322,0]Ao[3938,13,3939,4074,4390,1322,0]Ao[3938,13,3939,4079,3345,1322,0]Ao[3938,13,3939,4079,4158,1322,0]Al[3938,13,3939,0,1599,1322,0]Al[3938,13,3939,0,4926,1322,0]Al[3938,13,3939,0,1582,1322,0]Al[3938,13,3939,0,2426,1322,0]Al[3938,13,3939,0,3306,1322,0]Al[3938,13,3939,0,3137,1322,0]Al[3938,13,3939,0,4489,1322,0]Al[3938,13,3939,0,2010,1322,0]Al[3938,13,3939,0,4110,1322,0]Al[3938,13,3939,0,4485,1322,0]Al[3938,13,3939,0,4506,1322,0]Al[3938,13,3939,0,4791,1322,0]Al[3938,13,3939,0,4806,1322,0]Al[3938,13,3939,0,3983,1322,0]Al[3938,13,3939,0,4367,1322,0]Al[3938,13,3939,0,4152,1322,0]Al[3938,13,3939,0,4983,1322,0]Al[3938,13,3939,0,4104,1322,0]Al[3938,13,3939,0,3973,1322,0]Al[3938,13,3939,0,3120,1322,0]Al[3938,13,3939,0,4482,1322,0]Al[3938,13,3939,0,4670,1322,0]Al[3938,13,3939,0,4116,1322,0]Al[3938,13,3939,0,4119,1322,0]Al[3938,13,3939,0,4124,1322,0]Al[3938,13,3939,0,4825,1322,0]Al[3938,13,3939,0,3309,1322,0]Ak[3938,13,3939,0,481,1322,0]Ak[3938,13,3939,0,117,1322,0]Al[3938,13,3939,0,2414,1322,0]Ak[3938,13,3697,0,111,1322,0]Al[3938,13,3697,0,3108,1322,0]Al[3938,13,3697,0,1324,1322,0]Al[3938,13,3697,0,3978,1322,0]Al[3938,13,3697,0,1984,1322,0]Al[3938,13,3697,0,4272,1322,0]Al[3938,13,1919,0,4922,1322,0]Al[3938,13,1919,0,1337,1322,0]Ao[4725,13,4726,1952,1600,1322,0]Ao[4725,13,4726,1952,4927,1322,0]Ao[4725,13,4726,3165,4768,1322,0]Ao[4725,13,4726,1522,1583,1322,0]Ao[4725,13,4726,1522,4148,1322,0]Ao[4725,13,4726,1522,3321,1322,0]Ao[4725,13,4726,1522,3136,1322,0]Ao[4725,13,4726,1522,4822,1322,0]Ao[4725,13,4726,1522,3296,1322,0]Ao[4725,13,4726,1538,2427,1322,0]Ao[4725,13,4726,1538,3307,1322,0]Ao[4725,13,4726,1538,3138,1322,0]Ao[4725,13,4726,1538,4490,1322,0]Ao[4725,13,4726,1071,3141,1322,0]Ao[4725,13,4726,1071,4280,1322,0]Ao[4725,13,4726,1076,2011,1322,0]Ao[4725,13,4726,1076,3346,1322,0]Ao[4725,13,4726,1076,3982,1322,0]Ao[4725,13,4726,2144,4392,1322,0]Ao[4725,13,4726,2144,4114,1322,0]Ao[4725,13,4726,3703,4486,1322,0]Ao[4725,13,4726,3703,3133,1322,0]Ao[4725,13,4726,3703,4358,1322,0]Ao[4725,13,4726,3703,5010,1322,0]Ao[4725,13,4726,3283,4507,1322,0]Ao[4725,13,4726,3283,4792,1322,0]Ao[4725,13,4726,3283,4807,1322,0]Ao[4725,13,4726,3283,3984,1322,0]Ao[4725,13,4726,1838,4368,1322,0]Ao[4725,13,4726,1838,4154,1322,0]Ao[4725,13,4726,1838,4984,1322,0]Ao[4725,13,4726,1838,4106,1322,0]Ao[4725,13,4726,1838,3974,1322,0]Ao[4725,13,4726,1512,3121,1322,0]Ao[4725,13,4726,1512,3313,1322,0]Ao[4725,13,4726,1512,3335,1322,0]Ao[4725,13,4726,1512,4121,1322,0]Ao[4725,13,4726,1512,4484,1322,0]Ao[4725,13,4726,1512,4672,1322,0]Ao[4725,13,4726,1512,2385,1322,0]Ao[4725,13,4726,2437,4676,1322,0]Ao[4725,13,4726,2437,4117,1322,0]Ao[4725,13,4726,1903,4498,1322,0]Ao[4725,13,4726,1903,5013,1322,0]Ao[4725,13,4726,1903,2398,1322,0]Ao[4725,13,4726,1903,4766,1322,0]Ao[4725,13,4726,1930,4120,1322,0]Ao[4725,13,4726,1930,4125,1322,0]Al[4725,13,4726,0,4396,1322,0]Al[4725,13,4726,0,4826,1322,0]Ao[4725,13,4726,4293,3310,1322,0]Ao[4725,13,4726,4293,5106,1322,0]An[4725,13,4726,4726,482,1322,0]An[4725,13,4726,4726,118,1322,0]Ao[4725,13,4726,4726,2415,1322,0]Ao[4725,13,4726,4726,3119,1322,0]Ao[4725,13,1836,1836,4286,1322,0]Ao[4725,13,4968,4968,4867,1322,0]Ao[4725,13,4968,4968,1339,1322,0]Ao[4725,13,1920,1920,4923,1322,0]Al[4725,13,1920,0,1338,1322,0]Am[4725,13,3698,133,112,1322,0]An[4725,13,3698,133,3109,1322,0]Ao[4725,13,3698,1507,1325,1322,0]Ao[4725,13,3698,1507,3979,1322,0]Ao[4725,13,3698,2485,1985,1322,0]Ao[4725,13,3698,2485,4273,1322,0]Ao[4725,13,2115,2115,1343,1322,0]Ao[4431,13,4432,4432,2412,1322,0]Ao[4431,13,4432,4432,2425,1322,0]Ao[4431,13,4432,4432,4126,1322,0]Ao[1046,13,1047,1047,4860,1322,0]Ao[1046,13,1537,1537,4494,1322,0]Al[3938,13,3939,3702,3300,0,0]Al[3938,13,3939,2436,2391,0,0]Ak[3938,13,3939,1045,474,0,0]Al[4725,13,4726,3703,3301,0,0]Al[3938,13,3939,0,4119,1328,0]Ao[4725,13,4726,1930,4120,1328,0]Ai[4725,14,3134,0,4263,0,0]Ai[4725,14,4726,0,4396,0,0]Ai[3938,13,3939,0,2414,0,0]Al[4725,13,4726,4726,2415,0,0]Ai[3938,13,3939,0,4124,0,0]Al[4725,13,4726,1930,4125,0,0]Ai[3938,14,1840,0,1979,0,0]Al[4725,14,1841,1841,1980,0,0]Al[4725,12,4726,1903,4797,0,0]Ao[4725,13,4726,1903,5131,4797,0]=Al[4725,13,4968,4968,4867,0,0]Ah[3938,5,3939,2436,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Al[1361,15,1362,1362,3970,0,0]0Al[4725,15,4726,1522,3321,0,0]Ah[4725,5,4726,1071,0,0,0]Ah[3938,15,3939,0,481,0,0]Ak[4725,15,4726,4726,482,0,0]Al[3958,15,3959,3959,2382,0,0]Al[4725,15,4726,1522,3136,0,0]Al[4725,15,2115,2115,1340,0,0]98Ah[3938,5,3939,3702,0,0,0]2Al[4725,15,4726,2144,4000,0,0]Ah[3938,5,3939,1522,0,0,0]Ah[4725,5,4726,1522,0,0,0]Ae[4725,8,1836,0,0,0,0]987>Al[4725,15,4726,3703,1342,0,0]>Ah[3938,5,3939,1952,0,0,0]Ah[4725,5,4726,1952,0,0,0]Al[3938,13,3939,2436,2391,0,0]Al[3938,13,3939,2463,2395,0,0]Al[4725,13,4726,2144,2004,0,0]Al[4725,13,4726,2437,2392,0,0]An[1361,13,1362,1362,125,1560,0]Ao[1361,13,1362,1362,3970,1560,0]Ao[1361,13,1536,1536,4001,1560,0]Ao[1361,13,1536,1536,1357,1560,0]Ao[1361,13,1536,1536,4393,1560,0]Al[491,13,492,492,3971,1560,0]Ao[4007,13,4008,4008,5014,1560,0]Ao[3938,13,3939,3702,4511,1560,0]Ao[3938,13,3939,3702,2405,1560,0]Al[3938,13,3939,0,4244,1560,0]Ao[3938,13,3939,1045,2406,1560,0]Ao[3938,13,3939,1045,3111,1560,0]Ao[3938,13,3939,1045,4668,1560,0]Ao[3938,13,3939,3702,3298,1560,0]Ao[3938,13,3939,3702,3300,1560,0]Ao[3938,13,3939,3702,1987,1560,0]Ao[3938,13,3939,3702,1575,1560,0]Ao[3938,13,3939,3702,3101,1560,0]Ao[3938,13,3939,3702,2379,1560,0]Ao[3938,13,3939,3702,4144,1560,0]Ao[3938,13,3939,3702,4149,1560,0]Ao[3938,13,3939,3702,4929,1560,0]Ao[3938,13,3939,3702,4767,1560,0]Ao[3938,13,3939,2436,2391,1560,0]Ao[3938,13,3939,2436,4253,1560,0]Ao[3938,13,3939,2436,1554,1560,0]Ao[3938,13,3939,2463,2395,1560,0]Ao[3938,13,3939,2463,3328,1560,0]Ao[3938,13,3939,2463,4372,1560,0]An[3938,13,3939,1045,474,1560,0]Ao[3938,13,3939,4074,3325,1560,0]Ao[3938,13,3939,4074,4868,1560,0]Ao[3938,13,3939,4074,4391,1560,0]Ao[3938,13,3939,4074,3140,1560,0]Ao[3938,13,3939,4074,3327,1560,0]Ao[3938,13,3939,4074,4390,1560,0]Ao[3938,13,3939,1548,4159,1560,0]Ao[3938,13,3939,1088,3996,1560,0]Ao[3938,13,3939,4079,3331,1560,0]Ao[3938,13,3939,4079,3345,1560,0]Ao[3938,13,3939,4079,4158,1560,0]Al[3938,13,3939,0,3322,1560,0]Al[3938,13,3939,0,4284,1560,0]Al[3938,13,3939,0,4503,1560,0]Al[3938,13,3939,0,4136,1560,0]Al[3938,13,3939,0,4381,1560,0]Al[3938,13,3939,0,1599,1560,0]Al[3938,13,3939,0,4926,1560,0]Al[3938,13,3939,0,1320,1560,0]Al[3938,13,3939,0,1582,1560,0]Al[3938,13,3939,0,2426,1560,0]Al[3938,13,3939,0,3306,1560,0]Al[3938,13,3939,0,3137,1560,0]Al[3938,13,3939,0,4489,1560,0]Al[3938,13,3939,0,2010,1560,0]Al[3938,13,3939,0,4110,1560,0]Al[3938,13,3939,0,4485,1560,0]Al[3938,13,3939,0,4499,1560,0]Al[3938,13,3939,0,4506,1560,0]Al[3938,13,3939,0,4791,1560,0]Al[3938,13,3939,0,4806,1560,0]Al[3938,13,3939,0,3983,1560,0]Al[3938,13,3939,0,4367,1560,0]Al[3938,13,3939,0,4152,1560,0]Al[3938,13,3939,0,4983,1560,0]Al[3938,13,3939,0,4104,1560,0]Al[3938,13,3939,0,3973,1560,0]Al[3938,13,3939,0,3120,1560,0]Al[3938,13,3939,0,4482,1560,0]Al[3938,13,3939,0,4670,1560,0]Al[3938,13,3939,0,4116,1560,0]Al[3938,13,3939,0,4119,1560,0]Al[3938,13,3939,0,4124,1560,0]Al[3938,13,3939,0,4825,1560,0]Al[3938,13,3939,0,3309,1560,0]Al[3938,13,3939,0,4701,1560,0]Ak[3938,13,3939,0,481,1560,0]Ak[3938,13,3939,0,117,1560,0]Al[3938,13,3939,0,2414,1560,0]Al[3938,13,3939,0,2423,1560,0]Ak[3938,13,3697,0,111,1560,0]Al[3938,13,3697,0,3108,1560,0]Al[3938,13,3697,0,1324,1560,0]Al[3938,13,3697,0,3978,1560,0]Al[3938,13,3697,0,1984,1560,0]Al[3938,13,3697,0,4272,1560,0]Al[3938,13,3697,0,4759,1560,0]Al[3938,13,1840,0,1979,1560,0]Ak[3938,13,1840,0,468,1560,0]Al[3938,13,1840,0,5072,1560,0]Al[3938,13,1840,0,3976,1560,0]Al[3938,13,1840,0,4829,1560,0]Al[3938,13,1919,0,3340,1560,0]Al[3938,13,1919,0,4255,1560,0]Al[3938,13,1919,0,4697,1560,0]Al[3938,13,1919,0,4699,1560,0]Al[3938,13,1919,0,4922,1560,0]Al[3938,13,1919,0,1337,1560,0]Ao[4725,13,4726,4516,4245,1560,0]Ao[4725,13,4726,3165,3115,1560,0]Ao[4725,13,4726,1071,1562,1560,0]Ao[4725,13,4726,2144,2004,1560,0]Ao[4725,13,4726,2144,3326,1560,0]Ao[4725,13,4726,2144,3332,1560,0]Ao[4725,13,4726,3703,3301,1560,0]Ao[4725,13,4726,1067,3323,1560,0]Ao[4725,13,4726,1838,4285,1560,0]Ao[4725,13,4726,2437,2392,1560,0]Ao[4725,13,4726,2437,4251,1560,0]Ao[4725,13,4726,1903,5131,1560,0]Ao[4725,13,4726,4293,5101,1560,0]Ao[4725,13,4726,1547,4504,1560,0]Ao[4725,13,4726,1547,4137,1560,0]Ao[4725,13,4726,1547,4382,1560,0]Ao[4725,13,4726,1952,1600,1560,0]Ao[4725,13,4726,1952,4927,1560,0]Ao[4725,13,4726,3156,1321,1560,0]Ao[4725,13,4726,3165,4768,1560,0]Ao[4725,13,4726,1522,1583,1560,0]Ao[4725,13,4726,1522,4148,1560,0]Ao[4725,13,4726,1522,3321,1560,0]Ao[4725,13,4726,1522,3136,1560,0]Ao[4725,13,4726,1522,4822,1560,0]Ao[4725,13,4726,1522,3296,1560,0]Ao[4725,13,4726,1538,2427,1560,0]Ao[4725,13,4726,1538,3307,1560,0]Ao[4725,13,4726,1538,3138,1560,0]Ao[4725,13,4726,1538,4490,1560,0]Ao[4725,13,4726,1071,3141,1560,0]Ao[4725,13,4726,1071,4280,1560,0]Ao[4725,13,4726,1076,2011,1560,0]Ao[4725,13,4726,1076,3346,1560,0]Ao[4725,13,4726,1076,3982,1560,0]Ao[4725,13,4726,2144,4000,1560,0]Ao[4725,13,4726,2144,4392,1560,0]Ao[4725,13,4726,2144,4114,1560,0]Ao[4725,13,4726,3703,4486,1560,0]Ao[4725,13,4726,3703,3133,1560,0]Ao[4725,13,4726,3703,4358,1560,0]Ao[4725,13,4726,3703,5010,1560,0]Ao[4725,13,4726,3703,1342,1560,0]Ao[4725,13,4726,1067,4500,1560,0]Ao[4725,13,4726,3283,4507,1560,0]Ao[4725,13,4726,3283,4792,1560,0]Ao[4725,13,4726,3283,4807,1560,0]Ao[4725,13,4726,3283,3984,1560,0]Ao[4725,13,4726,1838,4368,1560,0]Ao[4725,13,4726,1838,4154,1560,0]Ao[4725,13,4726,1838,4984,1560,0]Ao[4725,13,4726,1838,4106,1560,0]Ao[4725,13,4726,1838,3974,1560,0]Ao[4725,13,4726,1512,3121,1560,0]Ao[4725,13,4726,1512,4373,1560,0]Ao[4725,13,4726,1512,3313,1560,0]Ao[4725,13,4726,1512,3335,1560,0]Ao[4725,13,4726,1512,4121,1560,0]Ao[4725,13,4726,1512,4484,1560,0]Ao[4725,13,4726,1512,4672,1560,0]Ao[4725,13,4726,1512,2385,1560,0]Ao[4725,13,4726,2437,4676,1560,0]Ao[4725,13,4726,2437,2396,1560,0]Ao[4725,13,4726,2437,4117,1560,0]Ao[4725,13,4726,2437,3968,1560,0]Ao[4725,13,4726,2437,3329,1560,0]Ao[4725,13,4726,1903,4275,1560,0]Ao[4725,13,4726,1903,4498,1560,0]Ao[4725,13,4726,1903,5013,1560,0]Ao[4725,13,4726,1903,2398,1560,0]Ao[4725,13,4726,1903,4766,1560,0]Ao[4725,13,4726,1930,4488,1560,0]Ao[4725,13,4726,1930,4252,1560,0]Ao[4725,13,4726,1930,4120,1560,0]Ao[4725,13,4726,1930,4125,1560,0]Al[4725,13,4726,0,4396,1560,0]Al[4725,13,4726,0,4826,1560,0]Ao[4725,13,4726,4293,3310,1560,0]Ao[4725,13,4726,4293,5106,1560,0]Ao[4725,13,4726,4856,4702,1560,0]An[4725,13,4726,4726,482,1560,0]An[4725,13,4726,4726,118,1560,0]Ao[4725,13,4726,4726,2415,1560,0]Ao[4725,13,4726,4726,2424,1560,0]Ao[4725,13,4726,4726,3119,1560,0]Ao[4725,13,1836,1836,4286,1560,0]Ao[4725,13,4968,4968,4867,1560,0]Ao[4725,13,4968,4968,1339,1560,0]Ao[4725,13,1841,1841,1980,1560,0]An[4725,13,1841,1841,469,1560,0]Ao[4725,13,1841,1841,5073,1560,0]Ao[4725,13,1841,1841,3977,1560,0]Ao[4725,13,1841,1841,4832,1560,0]Ao[4725,13,1920,1920,3341,1560,0]Ao[4725,13,1920,1920,4256,1560,0]Ao[4725,13,1920,1920,4698,1560,0]Ao[4725,13,1920,1920,4700,1560,0]Ao[4725,13,1920,1920,4923,1560,0]Al[4725,13,1920,0,1338,1560,0]Am[4725,13,3698,133,112,1560,0]An[4725,13,3698,133,3109,1560,0]Ao[4725,13,3698,1507,1325,1560,0]Ao[4725,13,3698,1507,3979,1560,0]Ao[4725,13,3698,2485,1985,1560,0]Ao[4725,13,3698,2485,4273,1560,0]Ao[4725,13,3698,3698,4760,1560,0]Ao[4725,13,2115,2115,1340,1560,0]Ao[4725,13,2115,2115,1343,1560,0]Ao[4431,13,4432,4432,3344,1560,0]An[4431,13,4432,389,4397,1560,0]Ao[4431,13,4432,4432,2412,1560,0]Ao[4431,13,4432,4432,2425,1560,0]Ao[4431,13,4432,4432,4126,1560,0]Ao[1046,13,1047,1047,3112,1560,0]Ao[1046,13,1047,1047,4860,1560,0]An[1046,13,1830,1830,126,1560,0]Ao[1046,13,1537,1537,1358,1560,0]Ao[1046,13,1537,1537,4002,1560,0]Ao[1046,13,1537,1537,4494,1560,0]Ao[1046,13,4211,4211,5058,1560,0]Ao[1046,13,4211,4211,5059,1560,0]An[1046,13,1925,1925,127,1560,0]An[3958,13,3959,3959,116,1560,0]Ao[3958,13,3959,3959,2382,1560,0]Ai[3938,14,3939,0,2010,0,0]Al[4725,14,4726,1076,2011,0,0]Ak[1361,14,1362,1362,125,0,0]Ac[491,7,492,0,0,0,0]Al[3938,13,3939,2436,2391,0,0]Ae[1046,2,1047,0,0,0,0]Ae[4786,7,4787,0,0,0,0]Al[3938,13,3939,3702,3300,0,0]Ae[4725,2,4726,0,0,0,0]Al[4725,13,4726,2437,2392,0,0]Ah[3938,2,3939,4726,0,0,0]Ai[3938,13,3939,0,4825,0,0]Ai[3938,14,3939,0,3306,0,0]Ai[3938,14,3939,0,4152,0,0]5Ai[4725,13,4726,0,4826,0,0]Al[4725,14,4726,1538,3307,0,0]Al[4725,14,4726,1838,4154,0,0]Ai[4725,14,4726,0,4396,0,0]Al[3938,13,3939,0,1599,3116,0]Al[3938,13,3939,0,1582,3116,0]Al[3938,13,3939,0,3120,3116,0]Al[3938,13,3939,0,4825,3116,0]Al[3938,13,3939,0,2414,3116,0]Ao[4725,13,4726,1952,1600,3116,0]Ao[4725,13,4726,1522,1583,3116,0]Ao[4725,13,4726,1512,3121,3116,0]Ao[4725,13,4726,1512,3313,3116,0]Al[4725,13,4726,1903,4498,0,0]Al[4725,13,4726,0,4826,3116,0]Ao[4725,13,4726,4726,2415,3116,0]Al[4725,12,1836,1836,3116,0,0]Al[4431,14,4432,4432,2412,0,0]Al[3938,13,3939,0,1599,3117,0]Al[3938,13,3939,0,1582,3117,0]Al[3938,13,3939,0,3120,3117,0]Al[3938,13,3939,0,4825,3117,0]Al[3938,13,3939,0,2414,3117,0]Ao[4725,13,4726,1952,1600,3117,0]Ao[4725,13,4726,1522,1583,3117,0]Ao[4725,13,4726,1512,3121,3117,0]Ao[4725,13,4726,1512,3313,3117,0]Ao[4725,13,4726,1512,2385,3117,0]Al[4725,13,4726,0,4826,3117,0]Ao[4725,13,4726,4726,2415,3117,0]Al[4725,12,1836,1836,3117,0,0]Al[3938,13,3939,4079,3331,0,0]Al[4725,13,4726,2144,3332,0,0]Al[1046,13,1537,1537,4002,0,0]Al[4725,13,4726,2437,2392,0,0]Ah[3938,14,1840,0,468,0,0]Ak[4725,14,1841,1841,469,0,0]Al[3938,13,3939,2463,2395,0,0]3Ai[3938,12,3939,0,3342,0,0]Al[3938,13,3939,0,4381,3342,0]Al[3938,13,3939,0,4701,3342,0]Al[4725,12,4726,1547,3343,0,0]Ao[4725,13,4726,1547,4382,3343,0]Ao[4725,13,4726,4856,4702,3343,0]Al[1046,14,1047,1047,3112,0,0]Ai[3938,14,3939,0,1320,0,0]Al[4725,14,4726,3156,1321,0,0]Ai[3938,13,3697,0,3302,0,0]Ak[3938,13,3697,0,111,3302,0]Al[3938,13,3697,0,1324,3302,0]Al[3938,13,3697,0,1984,3302,0]Al[4725,13,3698,3698,3303,0,0]Am[4725,13,3698,133,112,3303,0]Ao[4725,13,3698,1507,1325,3303,0]Ao[4725,13,3698,2485,1985,3303,0]Ah[3938,14,1840,0,468,0,0]Ak[4725,14,1841,1841,469,0,0]Ai[4725,14,4497,0,4705,0,0]Ai[3938,14,3939,0,4482,0,0]Ai[3938,14,3939,0,4670,0,0]Al[4725,14,4726,1512,4484,0,0]Al[4725,14,4726,1512,4672,0,0]Ai[4725,14,4726,0,4396,0,0]Ai[4725,14,1341,0,4360,0,0]Al[3938,13,3939,2436,2391,0,0]Al[3938,13,3939,2463,2395,0,0]Al[4725,13,4726,2437,2392,0,0]Ai[3938,14,1840,0,1979,0,0]Al[4725,14,4726,4726,3119,0,0]Al[4725,14,1841,1841,1980,0,0]Ae[3938,4,3939,0,0,0,0]Ah[3938,2,1840,1841,0,0,0]Ae[4725,4,4726,0,0,0,0]Ae[4725,2,1841,0,0,0,0]Ac[491,7,492,0,0,0,0]:Ae[1046,2,1047,0,0,0,0]Ae[4786,7,4787,0,0,0,0]Ao[3938,13,3939,3702,4767,1330,0]Ao[3938,13,3939,4074,4391,1330,0]Ao[3938,13,3939,4074,3140,1330,0]Ao[3938,13,3939,4074,3327,1330,0]Ao[3938,13,3939,4074,4390,1330,0]Ao[3938,13,3939,4079,3345,1330,0]Ao[3938,13,3939,4079,4158,1330,0]Al[3938,13,3939,0,4485,1330,0]Ao[4725,13,4726,3703,4486,1330,0]Ai[3938,14,3939,0,2423,0,0]Al[4725,14,4726,4726,2424,0,0]Al[4431,14,4432,4432,2425,0,0]Ak[3938,13,3939,1045,474,0,0]Ai[4725,14,3134,0,4145,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Al[4431,14,4432,4432,2412,0,0]Ai[3938,14,3939,0,4489,0,0]Al[4725,14,4726,1538,4490,0,0]10Ai[3938,12,1840,0,1975,0,0]Al[4725,12,1841,1841,1976,0,0]Ai[3938,12,3697,0,3302,0,0]Ak[3938,13,3697,0,111,3302,0]Al[3938,13,3697,0,1324,3302,0]Al[3938,13,3697,0,1984,3302,0]Al[4725,12,3698,3698,3303,0,0]Am[4725,13,3698,133,112,3303,0]Ao[4725,13,3698,1507,1325,3303,0]Ao[4725,13,3698,2485,1985,3303,0]Ai[3938,10,1840,1841,0,0,0]Af[4725,10,1841,0,0,0,0]Al[4725,15,4726,3165,4768,0,0]Al[4725,15,4726,1071,3141,0,0]Al[4725,15,4726,1076,3346,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]65Al[4725,15,4726,1903,4498,0,0]Ah[3938,5,1840,1841,0,0,0]Ae[4725,5,1841,0,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Ah[3938,5,3697,2485,0,0,0]Ah[4725,5,3698,2485,0,0,0]Al[1046,15,1047,1047,4860,0,0]Ah[3938,5,3939,3702,0,0,0]5454Ai[3938,10,3939,2136,0,0,0]Ai[3938,10,1840,1841,0,0,0]Af[4725,10,1841,0,0,0,0]Al[3938,15,3939,4079,3345,0,0]?Al[4725,15,4726,1076,3982,0,0]Al[4725,15,4726,2144,4000,0,0]Ah[4725,5,4726,2144,0,0,0]Al[3938,15,3939,4074,4391,0,0]Al[4725,15,4726,1512,3313,0,0]Ah[3938,5,3939,1076,0,0,0]Ah[4725,5,4726,1076,0,0,0]Al[4725,15,4726,1903,2398,0,0]Ai[3938,12,3939,0,4974,0,0]Al[4725,12,4726,4293,4975,0,0]Ao[4725,13,4726,4293,5101,4975,0]Ao[4725,13,4726,4293,5106,4975,0]Ak[1361,14,1362,1362,125,0,0]An[1361,13,1362,1362,125,4359,0]Ao[1046,13,1047,1047,3112,4359,0]An[1046,13,1830,1830,126,4359,0]An[1046,13,1925,1925,127,4359,0]An[3958,13,3959,3959,116,4359,0]Ak[3958,14,3959,3959,116,0,0]Al[3938,13,3939,0,1599,3297,0]Al[3938,13,3939,0,1582,3297,0]Al[3938,13,3939,0,3983,3297,0]Al[3938,13,3939,0,4119,3297,0]Ak[3938,13,3939,0,481,3297,0]Ak[3938,13,3939,0,117,3297,0]Al[3938,13,3939,0,2414,3297,0]Ao[4725,13,4726,1952,1600,3297,0]Ao[4725,13,4726,3165,4768,3297,0]Ao[4725,13,4726,1522,1583,3297,0]Ao[4725,13,4726,1071,3141,3297,0]Ao[4725,13,4726,1071,4280,3297,0]Ao[4725,13,4726,1076,3346,3297,0]Ao[4725,13,4726,3283,3984,3297,0]Ao[4725,13,4726,2437,4676,3297,0]Ao[4725,13,4726,1903,4766,3297,0]Ao[4725,13,4726,1930,4120,3297,0]An[4725,13,4726,4726,482,3297,0]An[4725,13,4726,4726,118,3297,0]Ao[4725,13,4726,4726,2415,3297,0]Al[3938,13,3939,2436,2391,0,0]Al[4725,13,4726,2437,2392,0,0]Ai[3938,12,1840,0,3130,0,0]Ai[3938,12,1840,0,3123,0,0]Al[4725,12,1841,1841,3131,0,0]Al[4725,12,1841,1841,3124,0,0]Ao[1361,13,1536,1536,4001,1970,0]Ao[1361,13,1536,1536,1357,1970,0]Al[491,13,492,492,3971,1970,0]Al[3938,13,3939,0,4244,1970,0]Ao[3938,13,3939,2436,4253,1970,0]Al[3938,13,3939,0,1599,1970,0]Al[3938,13,3939,0,1582,1970,0]Al[3938,13,3939,0,2426,1970,0]Al[3938,13,3939,0,3306,1970,0]Al[3938,13,3939,0,3137,1970,0]Al[3938,13,3939,0,4489,1970,0]Al[3938,13,3939,0,2010,1970,0]Al[3938,13,3939,0,4110,1970,0]Al[3938,13,3939,0,4506,1970,0]Al[3938,13,3939,0,4791,1970,0]Al[3938,13,3939,0,4806,1970,0]Al[3938,13,3939,0,3983,1970,0]Al[3938,13,3939,0,4367,1970,0]Al[3938,13,3939,0,4983,1970,0]Al[3938,13,3939,0,4701,1970,0]Al[3938,13,3697,0,3108,1970,0]Al[3938,13,3697,0,3978,1970,0]Al[3938,13,3697,0,4272,1970,0]Al[3938,13,3697,0,4759,1970,0]Ao[4725,13,4726,4516,4245,1970,0]Ao[4725,13,4726,4293,5101,1970,0]Ao[4725,13,4726,1952,1600,1970,0]Ao[4725,13,4726,1522,1583,1970,0]Ao[4725,13,4726,1522,3321,1970,0]Ao[4725,13,4726,1522,3296,1970,0]Ao[4725,13,4726,1538,2427,1970,0]Ao[4725,13,4726,1538,3307,1970,0]Ao[4725,13,4726,1538,3138,1970,0]Ao[4725,13,4726,1538,4490,1970,0]Ao[4725,13,4726,1076,2011,1970,0]Ao[4725,13,4726,2144,4392,1970,0]Ao[4725,13,4726,2144,4114,1970,0]Ao[4725,13,4726,3283,4507,1970,0]Ao[4725,13,4726,3283,4792,1970,0]Ao[4725,13,4726,3283,4807,1970,0]Ao[4725,13,4726,3283,3984,1970,0]Ao[4725,13,4726,1838,4368,1970,0]Ao[4725,13,4726,1838,4984,1970,0]Ao[4725,13,4726,4293,5106,1970,0]Ao[4725,13,4726,4856,4702,1970,0]An[4725,13,3698,133,3109,1970,0]Ao[4725,13,3698,1507,3979,1970,0]Ao[4725,13,3698,2485,4273,1970,0]Ao[4725,13,3698,3698,4760,1970,0]Ao[4431,13,4432,4432,2412,1970,0]Ao[1046,13,1537,1537,1358,1970,0]Ao[1046,13,1537,1537,4494,1970,0]Al[4725,13,4726,1930,4252,0,0]Al[4725,13,4726,1903,4275,0,0]Al[4725,13,4726,1903,4498,0,0]Al[4725,14,4726,1903,5013,0,0]Ai[4725,14,4765,0,4827,0,0]Ah[4725,14,4497,0,470,0,0]Ai[4725,14,4497,0,1352,0,0]Ai[4725,14,4497,0,1354,0,0]Ai[4725,14,4497,0,4705,0,0]Ai[3938,12,1840,0,3130,0,0]Ai[3938,12,1840,0,3123,0,0]Al[4725,12,1841,1841,3131,0,0]Al[4725,12,1841,1841,3124,0,0]Ae[4725,2,4726,0,0,0,0]Al[3938,13,3939,4074,3325,0,0]Al[3938,13,3939,4074,4868,0,0]Ai[3938,13,3697,0,3302,0,0]Ak[3938,13,3697,0,111,3302,0]Al[3938,13,3697,0,1324,3302,0]Al[3938,13,3697,0,1984,3302,0]Al[4725,13,3698,3698,3303,0,0]Am[4725,13,3698,133,112,3303,0]Ao[4725,13,3698,1507,1325,3303,0]Ao[4725,13,3698,2485,1985,3303,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]9854Al[3938,13,3939,3702,3300,0,0]Al[3938,13,3939,1045,2406,0,0]Al[4725,14,4726,1903,5013,0,0]Ai[4725,14,4765,0,4827,0,0]Ah[4725,14,4497,0,470,0,0]Ai[4725,14,4497,0,1352,0,0]Ai[4725,14,4497,0,4705,0,0]Al[3938,13,3939,4079,3331,0,0]Al[4725,13,4726,2144,3332,0,0]Ak[1361,14,1362,1362,125,0,0]Al[1361,14,1536,1536,1357,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,12,1840,0,3130,0,0]Al[4725,12,1841,1841,3131,0,0]Am[1361,13,1362,1362,125,109,0]An[1361,13,1362,1362,3970,109,0]An[1361,13,1536,1536,4001,109,0]An[1361,13,1536,1536,1357,109,0]An[1361,13,1536,1536,4393,109,0]Ak[491,13,492,492,3971,109,0]An[4007,13,4008,4008,5014,109,0]An[3938,13,3939,3702,4511,109,0]An[3938,13,3939,3702,2405,109,0]Ak[3938,13,3939,0,4244,109,0]An[3938,13,3939,1045,2406,109,0]An[3938,13,3939,1045,3111,109,0]An[3938,13,3939,1045,4668,109,0]An[3938,13,3939,3702,3298,109,0]An[3938,13,3939,3702,3300,109,0]An[3938,13,3939,3702,1987,109,0]An[3938,13,3939,3702,1575,109,0]An[3938,13,3939,3702,3101,109,0]An[3938,13,3939,3702,2379,109,0]An[3938,13,3939,3702,4144,109,0]An[3938,13,3939,3702,4149,109,0]An[3938,13,3939,3702,4929,109,0]An[3938,13,3939,3702,4767,109,0]An[3938,13,3939,2436,2391,109,0]An[3938,13,3939,2436,4253,109,0]An[3938,13,3939,2436,1554,109,0]An[3938,13,3939,2463,2395,109,0]An[3938,13,3939,2463,3328,109,0]An[3938,13,3939,2463,4372,109,0]Am[3938,13,3939,1045,474,109,0]An[3938,13,3939,4074,3325,109,0]An[3938,13,3939,4074,4868,109,0]An[3938,13,3939,4074,4391,109,0]An[3938,13,3939,4074,3140,109,0]An[3938,13,3939,4074,3327,109,0]An[3938,13,3939,4074,4390,109,0]An[3938,13,3939,1548,4159,109,0]An[3938,13,3939,1088,3996,109,0]An[3938,13,3939,4079,3331,109,0]An[3938,13,3939,4079,3345,109,0]An[3938,13,3939,4079,4158,109,0]Ak[3938,13,3939,0,3322,109,0]Ak[3938,13,3939,0,4284,109,0]Ak[3938,13,3939,0,4503,109,0]Ak[3938,13,3939,0,4136,109,0]Ak[3938,13,3939,0,4381,109,0]Ak[3938,13,3939,0,1599,109,0]Ak[3938,13,3939,0,4926,109,0]Ak[3938,13,3939,0,1320,109,0]Ak[3938,13,3939,0,1582,109,0]Ak[3938,13,3939,0,2426,109,0]Ak[3938,13,3939,0,3306,109,0]Ak[3938,13,3939,0,3137,109,0]Ak[3938,13,3939,0,4489,109,0]Ak[3938,13,3939,0,2010,109,0]Ak[3938,13,3939,0,4110,109,0]Ak[3938,13,3939,0,4485,109,0]Ak[3938,13,3939,0,4499,109,0]Ak[3938,13,3939,0,4506,109,0]Ak[3938,13,3939,0,4791,109,0]Ak[3938,13,3939,0,4806,109,0]Ak[3938,13,3939,0,3983,109,0]Ak[3938,13,3939,0,4367,109,0]Ak[3938,13,3939,0,4152,109,0]Ak[3938,13,3939,0,4983,109,0]Ak[3938,13,3939,0,4104,109,0]Ak[3938,13,3939,0,3973,109,0]Ak[3938,13,3939,0,3120,109,0]Ak[3938,13,3939,0,4482,109,0]Ak[3938,13,3939,0,4670,109,0]Ak[3938,13,3939,0,4116,109,0]Ak[3938,13,3939,0,4119,109,0]Ak[3938,13,3939,0,4124,109,0]Ak[3938,13,3939,0,4825,109,0]Ak[3938,13,3939,0,3309,109,0]Ak[3938,13,3939,0,4701,109,0]Aj[3938,13,3939,0,481,109,0]Aj[3938,13,3939,0,117,109,0]Ak[3938,13,3939,0,2414,109,0]Ak[3938,13,3939,0,2423,109,0]Aj[3938,13,3697,0,111,109,0]Ak[3938,13,3697,0,3108,109,0]Ak[3938,13,3697,0,1324,109,0]Ak[3938,13,3697,0,3978,109,0]Ak[3938,13,3697,0,1984,109,0]Ak[3938,13,3697,0,4272,109,0]Ak[3938,13,3697,0,4759,109,0]Ak[3938,13,1840,0,1979,109,0]Aj[3938,13,1840,0,468,109,0]Ak[3938,13,1840,0,5072,109,0]Ak[3938,13,1840,0,3976,109,0]Ak[3938,13,1840,0,4829,109,0]Ak[3938,13,1919,0,3340,109,0]Ak[3938,13,1919,0,4255,109,0]Ak[3938,13,1919,0,4697,109,0]Ak[3938,13,1919,0,4699,109,0]Ak[3938,13,1919,0,4922,109,0]Ak[3938,13,1919,0,1337,109,0]An[4725,13,4726,4516,4245,109,0]An[4725,13,4726,3165,3115,109,0]An[4725,13,4726,1071,1562,109,0]An[4725,13,4726,2144,2004,109,0]An[4725,13,4726,2144,3326,109,0]An[4725,13,4726,2144,3332,109,0]An[4725,13,4726,3703,3301,109,0]An[4725,13,4726,1067,3323,109,0]An[4725,13,4726,1838,4285,109,0]An[4725,13,4726,2437,2392,109,0]An[4725,13,4726,2437,4251,109,0]An[4725,13,4726,1903,5131,109,0]An[4725,13,4726,4293,5101,109,0]An[4725,13,4726,1547,4504,109,0]An[4725,13,4726,1547,4137,109,0]An[4725,13,4726,1547,4382,109,0]An[4725,13,4726,1952,1600,109,0]An[4725,13,4726,1952,4927,109,0]An[4725,13,4726,3156,1321,109,0]An[4725,13,4726,3165,4768,109,0]An[4725,13,4726,1522,1583,109,0]An[4725,13,4726,1522,4148,109,0]An[4725,13,4726,1522,3321,109,0]An[4725,13,4726,1522,3136,109,0]An[4725,13,4726,1522,4822,109,0]An[4725,13,4726,1522,3296,109,0]An[4725,13,4726,1538,2427,109,0]An[4725,13,4726,1538,3307,109,0]An[4725,13,4726,1538,3138,109,0]An[4725,13,4726,1538,4490,109,0]An[4725,13,4726,1071,3141,109,0]An[4725,13,4726,1071,4280,109,0]An[4725,13,4726,1076,2011,109,0]An[4725,13,4726,1076,3346,109,0]An[4725,13,4726,1076,3982,109,0]An[4725,13,4726,2144,4000,109,0]An[4725,13,4726,2144,4392,109,0]An[4725,13,4726,2144,4114,109,0]An[4725,13,4726,3703,4486,109,0]An[4725,13,4726,3703,3133,109,0]An[4725,13,4726,3703,4358,109,0]An[4725,13,4726,3703,5010,109,0]An[4725,13,4726,3703,1342,109,0]An[4725,13,4726,1067,4500,109,0]An[4725,13,4726,3283,4507,109,0]An[4725,13,4726,3283,4792,109,0]An[4725,13,4726,3283,4807,109,0]An[4725,13,4726,3283,3984,109,0]An[4725,13,4726,1838,4368,109,0]An[4725,13,4726,1838,4154,109,0]An[4725,13,4726,1838,4984,109,0]An[4725,13,4726,1838,4106,109,0]An[4725,13,4726,1838,3974,109,0]An[4725,13,4726,1512,3121,109,0]An[4725,13,4726,1512,4373,109,0]An[4725,13,4726,1512,3313,109,0]An[4725,13,4726,1512,3335,109,0]An[4725,13,4726,1512,4121,109,0]An[4725,13,4726,1512,4484,109,0]An[4725,13,4726,1512,4672,109,0]An[4725,13,4726,1512,2385,109,0]An[4725,13,4726,2437,4676,109,0]An[4725,13,4726,2437,2396,109,0]An[4725,13,4726,2437,4117,109,0]An[4725,13,4726,2437,3968,109,0]An[4725,13,4726,2437,3329,109,0]An[4725,13,4726,1903,4275,109,0]An[4725,13,4726,1903,4498,109,0]An[4725,13,4726,1903,5013,109,0]An[4725,13,4726,1903,2398,109,0]An[4725,13,4726,1903,4766,109,0]An[4725,13,4726,1930,4488,109,0]An[4725,13,4726,1930,4252,109,0]An[4725,13,4726,1930,4120,109,0]An[4725,13,4726,1930,4125,109,0]Ak[4725,13,4726,0,4396,109,0]Ak[4725,13,4726,0,4826,109,0]An[4725,13,4726,4293,3310,109,0]An[4725,13,4726,4293,5106,109,0]An[4725,13,4726,4856,4702,109,0]Am[4725,13,4726,4726,482,109,0]Am[4725,13,4726,4726,118,109,0]An[4725,13,4726,4726,2415,109,0]An[4725,13,4726,4726,2424,109,0]An[4725,13,4726,4726,3119,109,0]An[4725,13,1836,1836,4286,109,0]An[4725,13,4968,4968,4867,109,0]An[4725,13,4968,4968,1339,109,0]An[4725,13,1841,1841,1980,109,0]Am[4725,13,1841,1841,469,109,0]An[4725,13,1841,1841,5073,109,0]An[4725,13,1841,1841,3977,109,0]An[4725,13,1841,1841,4832,109,0]An[4725,13,1920,1920,3341,109,0]An[4725,13,1920,1920,4256,109,0]An[4725,13,1920,1920,4698,109,0]An[4725,13,1920,1920,4700,109,0]An[4725,13,1920,1920,4923,109,0]Ak[4725,13,1920,0,1338,109,0]Al[4725,13,3698,133,112,109,0]Am[4725,13,3698,133,3109,109,0]An[4725,13,3698,1507,1325,109,0]An[4725,13,3698,1507,3979,109,0]An[4725,13,3698,2485,1985,109,0]An[4725,13,3698,2485,4273,109,0]An[4725,13,3698,3698,4760,109,0]An[4725,13,2115,2115,1340,109,0]An[4725,13,2115,2115,1343,109,0]An[4431,13,4432,4432,3344,109,0]Am[4431,13,4432,389,4397,109,0]An[4431,13,4432,4432,2412,109,0]An[4431,13,4432,4432,2425,109,0]An[4431,13,4432,4432,4126,109,0]An[1046,13,1047,1047,3112,109,0]An[1046,13,1047,1047,4860,109,0]Am[1046,13,1830,1830,126,109,0]An[1046,13,1537,1537,1358,109,0]An[1046,13,1537,1537,4002,109,0]An[1046,13,1537,1537,4494,109,0]An[1046,13,4211,4211,5058,109,0]An[1046,13,4211,4211,5059,109,0]Am[1046,13,1925,1925,127,109,0]Am[3958,13,3959,3959,116,109,0]An[3958,13,3959,3959,2382,109,0]Al[3938,13,3939,3702,4929,0,0]Ai[3938,13,3939,0,4104,0,0]Al[4725,13,4726,1838,4106,0,0]Al[4725,14,4726,1903,5013,0,0]Ai[4725,14,4765,0,4827,0,0]Ah[4725,14,4497,0,470,0,0]Ai[4725,14,4497,0,1352,0,0]Ah[3938,5,3939,3702,0,0,0]Al[1361,15,1362,1362,3970,0,0]Ae[3958,6,3959,0,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Ah[4725,5,4726,1512,0,0,0]Al[3938,15,3939,3702,4767,0,0]Al[4725,15,4726,3165,4768,0,0]Ah[3938,5,3939,2436,0,0,0]Ah[4725,5,4726,2437,0,0,0]Al[4725,15,4726,2144,4000,0,0]Ah[3938,5,3939,2463,0,0,0]2Ah[4725,6,4726,1903,0,0,0]Ai[3938,19,3939,0,1599,0,0]Al[4725,19,4726,1952,1600,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]=Ai[3938,12,1840,0,4153,0,0]>Al[3938,13,1919,0,4699,4153,0]>Al[4725,12,1841,1841,4155,0,0]>Ao[4725,13,1920,1920,4700,4155,0]Ao[1046,13,4211,4211,5059,4155,0]An[3958,13,3959,3959,116,3985,0]Ao[3958,13,3959,3959,2382,3985,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,14,4726,1538,3138,0,0]Ai[3938,13,3939,0,4152,0,0]Al[4725,13,4726,1838,4154,0,0]Al[3938,13,3939,2136,4355,0,0]0>=Al[1046,13,1537,1537,4494,0,0]Ae[1046,2,1047,0,0,0,0]Al[3938,13,3939,2463,2395,0,0]Al[4725,13,4726,2437,2396,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]43Ai[3938,14,3939,0,2423,0,0]Al[4725,14,4726,4726,2424,0,0]Al[4431,14,4432,4432,2425,0,0]Al[4725,13,4726,2144,2004,0,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,14,4726,1538,3138,0,0]Al[4725,13,4726,4293,5101,0,0]Al[4725,13,4726,4293,5106,0,0]Al[3938,13,3939,4079,3331,0,0]Al[4725,13,4726,2144,3332,0,0]>=Al[1361,14,1536,1536,1357,0,0]Ai[491,14,492,492,3971,0,0]Ai[3938,13,1919,0,4697,0,0]Ai[3938,13,1919,0,4699,0,0]Al[4725,13,1920,1920,4698,0,0]Al[4725,13,1920,1920,4700,0,0]76Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]Ah[3938,5,3939,4516,0,0,0]Ah[4725,5,4726,4516,0,0,0]Ai[3938,15,3939,0,4485,0,0]Ai[3938,15,3939,0,4116,0,0]Al[4725,15,4726,3703,4486,0,0]Al[4725,15,4726,2437,4117,0,0]Ah[4725,6,4726,2437,0,0,0]Ah[4725,5,4726,1930,0,0,0]Ah[3938,5,3939,2436,0,0,0]Al[3938,15,3939,4074,4390,0,0]Ah[3938,5,1919,1920,0,0,0]Ae[4725,5,1920,0,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Al[4725,15,4726,1903,4766,0,0]>Al[4725,15,4726,1522,3136,0,0]=5454Al[4725,15,4726,2437,4251,0,0]Ah[3938,5,3697,2485,0,0,0]Ah[4725,5,3698,2485,0,0,0]Ah[4725,5,4726,1903,0,0,0]98Ah[4725,6,4726,1071,0,0,0]:9Ah[3938,5,3939,1838,0,0,0]Ah[4725,5,4726,1838,0,0,0]Ae[4725,5,1836,0,0,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Al[1046,14,1047,1047,3112,0,0]Ae[4725,2,4726,0,0,0,0]Ai[3938,13,3939,0,4367,0,0]Al[4725,13,4726,1838,4368,0,0]Al[3938,12,3939,2136,4355,0,0]Ab[4296,3,0,0,0,0,0]Ak[1361,14,1362,1362,125,0,0]Al[1361,14,1536,1536,4001,0,0]98Al[3938,13,3939,2463,3328,0,0]Al[4725,13,4726,2437,3329,0,0]Ai[3938,13,3939,0,4791,0,0]Al[4725,13,4726,3283,4792,0,0];=Al[3938,13,3939,4074,4868,0,0]Al[4725,13,4726,2144,3326,0,0]Al[3938,13,3939,3702,3298,0,0]Al[3938,13,3939,3702,3300,0,0]Al[3938,13,3939,2463,2395,0,0]Ak[3938,13,3939,1045,474,0,0]Al[4725,13,4726,2437,2396,0,0]<;Ai[3938,13,3939,0,1599,0,0]Ai[3938,13,3939,0,1582,0,0]Al[4725,13,4726,1952,1600,0,0]Al[4725,13,4726,1522,1583,0,0]20Ae[1361,7,1536,0,0,0,0]?>Al[1361,14,1536,1536,1357,0,0]Ao[1046,13,1047,1047,4860,3145,0]Ai[3938,15,3939,0,3120,0,0]Ah[3938,5,3939,1512,0,0,0]Al[4725,15,4726,1512,3121,0,0]Ah[4725,5,4726,1512,0,0,0]Ah[3938,6,3939,3703,0,0,0]Ah[4725,6,4726,3703,0,0,0]Al[4725,15,4726,2437,4251,0,0]Ah[4725,5,4726,1930,0,0,0]Ah[3938,5,3939,1538,0,0,0]Ah[4725,5,4726,1538,0,0,0]97Ae[1046,5,1537,0,0,0,0]:8Ah[4725,6,4726,1903,0,0,0]Ah[3938,5,3939,1067,0,0,0]Ah[4725,5,4726,1067,0,0,0]Ah[3938,5,3939,1547,0,0,0]Ah[4725,5,4726,1547,0,0,0]Ah[3938,5,3939,3283,0,0,0]Ah[4725,5,4726,3283,0,0,0]Ai[3938,15,3939,0,4485,0,0]Al[4725,15,4726,3703,4486,0,0]Ah[3938,5,3939,3702,0,0,0]Al[3938,15,3939,4074,3140,0,0]Al[3938,15,3939,4074,3327,0,0]Al[3938,15,3939,4079,3345,0,0]Al[3938,15,3939,4079,4158,0,0]An[1361,13,1362,1362,125,4250,0]Ao[1361,13,1362,1362,3970,4250,0]Ao[3938,13,3939,3702,3300,4250,0]Ao[3938,13,3939,3702,4929,4250,0]Ao[3938,13,3939,3702,4767,4250,0]Ao[3938,13,3939,2436,2391,4250,0]Ao[3938,13,3939,2436,4253,4250,0]Ao[3938,13,3939,4074,4391,4250,0]Ao[3938,13,3939,4074,3140,4250,0]Ao[3938,13,3939,4074,3327,4250,0]Ao[3938,13,3939,4074,4390,4250,0]Ao[3938,13,3939,4079,3345,4250,0]Ao[3938,13,3939,4079,4158,4250,0]Al[3938,13,3939,0,1599,4250,0]Al[3938,13,3939,0,4926,4250,0]Al[3938,13,3939,0,1582,4250,0]Al[3938,13,3939,0,2426,4250,0]Al[3938,13,3939,0,3306,4250,0]Al[3938,13,3939,0,3137,4250,0]Al[3938,13,3939,0,4489,4250,0]Al[3938,13,3939,0,2010,4250,0]Al[3938,13,3939,0,4110,4250,0]Al[3938,13,3939,0,4485,4250,0]Al[3938,13,3939,0,4506,4250,0]Al[3938,13,3939,0,4791,4250,0]Al[3938,13,3939,0,4806,4250,0]Al[3938,13,3939,0,3983,4250,0]Al[3938,13,3939,0,4367,4250,0]Al[3938,13,3939,0,4152,4250,0]Al[3938,13,3939,0,4983,4250,0]Al[3938,13,3939,0,4104,4250,0]Al[3938,13,3939,0,3973,4250,0]Al[3938,13,3939,0,3120,4250,0]Al[3938,13,3939,0,4482,4250,0]Al[3938,13,3939,0,4670,4250,0]Al[3938,13,3939,0,4116,4250,0]Al[3938,13,3939,0,4119,4250,0]Al[3938,13,3939,0,4124,4250,0]Al[3938,13,3939,0,4825,4250,0]Al[3938,13,3939,0,3309,4250,0]Ak[3938,13,3939,0,481,4250,0]Ak[3938,13,3939,0,117,4250,0]Al[3938,13,3939,0,2414,4250,0]Ak[3938,13,3697,0,111,4250,0]Al[3938,13,3697,0,3108,4250,0]Al[3938,13,3697,0,1324,4250,0]Al[3938,13,3697,0,3978,4250,0]Al[3938,13,3697,0,1984,4250,0]Al[3938,13,3697,0,4272,4250,0]Al[3938,13,1919,0,4922,4250,0]Al[3938,13,1919,0,1337,4250,0]Ao[4725,13,4726,1952,1600,4250,0]Ao[4725,13,4726,1952,4927,4250,0]Ao[4725,13,4726,3165,4768,4250,0]Ao[4725,13,4726,1522,1583,4250,0]Ao[4725,13,4726,1522,4148,4250,0]Ao[4725,13,4726,1522,3321,4250,0]Ao[4725,13,4726,1522,3136,4250,0]Ao[4725,13,4726,1522,4822,4250,0]Ao[4725,13,4726,1522,3296,4250,0]Ao[4725,13,4726,1538,2427,4250,0]Ao[4725,13,4726,1538,3307,4250,0]Ao[4725,13,4726,1538,3138,4250,0]Ao[4725,13,4726,1538,4490,4250,0]Ao[4725,13,4726,1071,3141,4250,0]Ao[4725,13,4726,1071,4280,4250,0]Ao[4725,13,4726,1076,2011,4250,0]Ao[4725,13,4726,1076,3346,4250,0]Ao[4725,13,4726,1076,3982,4250,0]Ao[4725,13,4726,2144,4392,4250,0]Ao[4725,13,4726,2144,4114,4250,0]Ao[4725,13,4726,3703,4486,4250,0]Ao[4725,13,4726,3703,3133,4250,0]Ao[4725,13,4726,3703,4358,4250,0]Ao[4725,13,4726,3703,5010,4250,0]Ao[4725,13,4726,3283,4507,4250,0]Ao[4725,13,4726,3283,4792,4250,0]Ao[4725,13,4726,3283,4807,4250,0]Ao[4725,13,4726,3283,3984,4250,0]Ao[4725,13,4726,1838,4368,4250,0]Ao[4725,13,4726,1838,4154,4250,0]Ao[4725,13,4726,1838,4984,4250,0]Ao[4725,13,4726,1838,4106,4250,0]Ao[4725,13,4726,1838,3974,4250,0]Ao[4725,13,4726,1512,3121,4250,0]Ao[4725,13,4726,1512,3313,4250,0]Ao[4725,13,4726,1512,3335,4250,0]Ao[4725,13,4726,1512,4121,4250,0]Ao[4725,13,4726,1512,4484,4250,0]Ao[4725,13,4726,1512,4672,4250,0]Ao[4725,13,4726,1512,2385,4250,0]Ao[4725,13,4726,2437,4676,4250,0]Ao[4725,13,4726,2437,4117,4250,0]Ao[4725,13,4726,1903,4498,4250,0]Ao[4725,13,4726,1903,5013,4250,0]Ao[4725,13,4726,1903,2398,4250,0]Ao[4725,13,4726,1903,4766,4250,0]Ao[4725,13,4726,1930,4120,4250,0]Ao[4725,13,4726,1930,4125,4250,0]Al[4725,13,4726,0,4396,4250,0]Al[4725,13,4726,0,4826,4250,0]Ao[4725,13,4726,4293,3310,4250,0]Ao[4725,13,4726,4293,5106,4250,0]An[4725,13,4726,4726,482,4250,0]An[4725,13,4726,4726,118,4250,0]Ao[4725,13,4726,4726,2415,4250,0]Ao[4725,13,4726,4726,3119,4250,0]Ao[4725,13,1836,1836,4286,4250,0]Ao[4725,13,4968,4968,4867,4250,0]Ao[4725,13,4968,4968,1339,4250,0]Ao[4725,13,1920,1920,4923,4250,0]Al[4725,13,1920,0,1338,4250,0]Am[4725,13,3698,133,112,4250,0]An[4725,13,3698,133,3109,4250,0]Ao[4725,13,3698,1507,1325,4250,0]Ao[4725,13,3698,1507,3979,4250,0]Ao[4725,13,3698,2485,1985,4250,0]Ao[4725,13,3698,2485,4273,4250,0]Ao[4725,13,2115,2115,1343,4250,0]Ao[4431,13,4432,4432,2412,4250,0]Ao[4431,13,4432,4432,2425,4250,0]Ao[4431,13,4432,4432,4126,4250,0]Ao[1046,13,1047,1047,4860,4250,0]Ao[1046,13,1537,1537,4494,4250,0]Ah[3938,7,3939,2136,0,0,0]Ai[3938,13,3939,0,4367,0,0]Al[4725,13,4726,1838,4368,0,0]Ai[3938,12,1840,0,3130,0,0]Al[4725,12,1841,1841,3131,0,0]Al[4431,14,4432,4432,2412,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]10Ae[1046,7,1047,0,0,0,0]Al[3938,13,3939,2436,2391,0,0]Ae[4296,7,4297,0,0,0,0]Ae[1361,7,1362,0,0,0,0]Al[4725,13,4726,3703,3301,0,0]Al[3938,13,3939,3702,3300,0,0]1Al[4725,13,4726,2144,4392,0,0]Al[1361,13,1536,1536,1357,0,0]Al[1361,14,1536,1536,4001,0,0]Al[3938,12,3939,2136,1996,0,0]Ao[3938,13,3939,1548,4159,1996,0]Ao[3938,13,3939,1088,3996,1996,0]Ai[3938,12,1840,0,1997,0,0]Al[3938,13,1919,0,3340,1997,0]Al[4725,12,1841,1841,1998,0,0]Ao[4725,13,1920,1920,3341,1998,0]Ah[3938,5,3939,1045,0,0,0]Ai[3938,15,3939,0,3120,0,0]Ah[3938,5,3939,1512,0,0,0]Al[4725,15,4726,1512,3121,0,0]Ah[4725,5,4726,1512,0,0,0]Ai[3938,15,3939,0,4485,0,0]Al[4725,15,4726,3703,4486,0,0]Ah[4725,5,4726,2437,0,0,0]Al[4725,15,4726,3703,1342,0,0]Ai[3938,15,3939,0,4116,0,0]Al[4725,15,4726,2437,4117,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]32Al[4725,15,4726,3703,3133,0,0]><><><21Ah[3938,5,1919,1920,0,0,0]Ae[4725,5,1920,0,0,0,0]10Ah[3938,5,3939,4856,0,0,0]Ah[4725,5,4726,4856,0,0,0]Al[4725,15,2115,2115,1340,0,0]5Al[4725,15,4726,1903,4498,0,0]Ai[3938,12,3939,0,2419,0,0]Al[3938,13,3939,0,4244,2419,0]Al[3938,13,3939,0,4136,2419,0]Al[4725,12,4726,1547,2420,0,0]Ao[4725,13,4726,4516,4245,2420,0]Ao[4725,13,4726,1547,4137,2420,0]Ae[4007,7,4008,0,0,0,0]Al[3938,13,3939,3702,3300,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]32An[1361,13,1362,1362,125,4369,0]Ao[1046,13,1047,1047,3112,4369,0]An[1046,13,1830,1830,126,4369,0]An[1046,13,1925,1925,127,4369,0]An[3958,13,3959,3959,116,4369,0]Ao[3958,13,3959,3959,2382,4369,0]Ab[4725,3,0,0,0,0,0]Ak[4431,13,4432,389,4397,0,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0];:Al[3938,13,3939,2436,2391,0,0]Al[4725,13,4726,2437,2392,0,0]?>32Ae[4296,7,4297,0,0,0,0]5Al[1046,14,1047,1047,3112,0,0]60Ae[1361,7,1362,0,0,0,0]Ai[3938,13,3939,0,4152,0,0]Ai[3938,13,3939,0,4104,0,0]Al[4725,13,4726,1838,4154,0,0]Al[4725,13,4726,1838,4106,0,0]Ai[3938,14,3939,0,4152,0,0]Al[4725,14,4726,1838,4154,0,0]53Al[3938,13,3939,4079,3331,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Ai[3938,15,3939,0,4485,0,0]Al[4725,15,4726,3703,4486,0,0]Ai[3938,10,3697,3698,0,0,0]Af[4725,10,3698,0,0,0,0]Ah[3938,5,3697,3698,0,0,0]Ae[4725,5,3698,0,0,0,0]Ai[3938,10,1840,1841,0,0,0]Af[4725,10,1841,0,0,0,0]Ai[3938,15,3939,0,4116,0,0]Al[4725,15,4726,2437,4117,0,0]Ah[4725,6,4726,1903,0,0,0]Ah[3938,6,3939,3702,0,0,0]Ah[4725,6,4726,3165,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]10Al[3938,15,3939,3702,4767,0,0]Al[4725,15,4726,3165,4768,0,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,14,4726,1538,3138,0,0]Ai[3938,14,3697,0,4759,0,0]Al[4725,14,3698,3698,4760,0,0]Al[3938,13,3939,3702,3300,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]10Al[4725,13,4726,3165,3115,0,0]Al[3938,13,3939,2436,2391,0,0]Al[4725,13,4726,2437,2392,0,0]Ab[4786,3,0,0,0,0,0]Ao[1046,13,1047,1047,4860,3145,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Ah[3938,5,3939,3283,0,0,0]Ah[4725,5,4726,3283,0,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]54Ai[4725,10,4726,1903,0,0,0]Al[4725,15,4726,3703,1342,0,0]7600Al[4725,15,4726,1071,4280,0,0]4365Al[4725,15,2115,2115,1340,0,0]Ae[1046,9,1047,0,0,0,0]:9Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]<;<;Ah[4725,6,4726,1522,0,0,0]21Ae[3938,5,3939,0,0,0,0]Ae[4725,5,4726,0,0,0,0]Ai[3938,15,3939,0,4116,0,0]Ah[3938,5,1840,1841,0,0,0]Al[4725,15,4726,2437,4117,0,0]Al[4725,15,4726,1903,4766,0,0]Ae[4725,5,1841,0,0,0,0]An[1361,13,1362,1362,125,4359,0]Ao[1046,13,1047,1047,3112,4359,0]An[1046,13,1830,1830,126,4359,0]An[1046,13,1925,1925,127,4359,0]An[3958,13,3959,3959,116,4359,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]Ai[3938,13,3939,0,1599,0,0]Al[4725,13,4726,1952,1600,0,0]Al[3938,14,3939,2436,4253,0,0]Ai[3938,13,3939,0,4367,0,0]Al[4725,13,4726,1838,4368,0,0]Ai[3938,13,3939,0,4244,0,0]Al[4725,13,4726,4516,4245,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]6Al[4725,13,4726,3703,3301,0,0]Al[3938,13,3939,3702,3300,0,0]0176Ao[4007,13,4008,4008,5014,4820,0]Ai[3938,13,3939,0,4499,0,0]Al[4725,13,4726,1067,4500,0,0]Ae[1046,6,1047,0,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]10Al[4725,15,4726,3703,3133,0,0]Ae[4725,5,4968,0,0,0,0]Ah[3938,5,3939,4074,0,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]Al[4725,15,2115,2115,1340,0,0]Al[3938,14,3939,2436,4253,0,0]Ak[3938,13,3939,0,481,3102,0]Ak[3938,13,3939,0,117,3102,0]Al[3938,13,3939,0,2414,3102,0]An[4725,13,4726,4726,482,3102,0]An[4725,13,4726,4726,118,3102,0]Ao[4725,13,4726,4726,2415,3102,0]Ao[3958,13,3959,3959,2382,3336,0]Ai[3938,13,3939,0,4806,0,0]Al[4725,13,4726,3283,4807,0,0]Ai[3938,12,1840,0,1997,0,0]Al[3938,13,1919,0,3340,1997,0]Al[4725,12,1841,1841,1998,0,0]Ao[4725,13,1920,1920,3341,1998,0]Al[3938,13,3939,3702,3300,0,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]Ai[3938,14,3939,0,3137,0,0]Al[4725,14,4726,1538,3138,0,0]Ai[3938,12,3697,0,3302,0,0]Ak[3938,13,3697,0,111,3302,0]Al[3938,13,3697,0,1324,3302,0]Al[3938,13,3697,0,1984,3302,0]Al[4725,12,3698,3698,3303,0,0]Am[4725,13,3698,133,112,3303,0]Ao[4725,13,3698,1507,1325,3303,0]Ao[4725,13,3698,2485,1985,3303,0]Al[3938,14,3939,2436,4253,0,0]Al[4725,13,4726,2144,2004,0,0]Ah[4725,2,4291,4078,0,0,0]Ae[1361,7,1362,0,0,0,0]==Ak[3938,13,3939,1045,474,0,0]Ak[4431,13,4432,389,4397,0,0]032Ai[3938,12,1840,0,1997,0,0]Al[3938,13,1919,0,3340,1997,0]Ae[4725,2,4726,0,0,0,0]Al[4725,12,1841,1841,1998,0,0]Ao[4725,13,1920,1920,3341,1998,0]Ai[3938,10,3939,4293,0,0,0]Ai[4725,10,4726,4293,0,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]Ai[3938,15,3939,0,4116,0,0]Al[4725,15,4726,2437,4117,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Ah[3938,5,3939,1838,0,0,0]Ah[4725,5,4726,1838,0,0,0]Ai[3938,12,1840,0,3130,0,0]Al[4725,12,1841,1841,3131,0,0]Al[4725,13,4726,2437,2392,0,0]Al[4725,13,4726,4726,3119,0,0]Al[4725,13,4726,3703,3301,0,0]Ai[3938,13,3697,0,4272,0,0]Al[4725,13,3698,2485,4273,0,0]Al[3938,13,3939,2136,3143,0,0]0Al[3938,13,3939,3702,3300,0,0]4Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]Al[1046,14,1047,1047,3112,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Al[4725,15,2115,2115,1340,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]10Al[4725,15,4726,1522,4822,0,0]Al[4725,15,4726,3703,3133,0,0]Ah[4725,5,4726,3703,0,0,0]Ai[3938,15,3939,0,3120,0,0]Al[4725,15,4726,1512,3121,0,0]Ah[4725,5,4726,1903,0,0,0]Ae[4007,5,4008,0,0,0,0]Al[1046,13,1047,1047,3112,0,0]Al[3938,13,3939,3702,3300,0,0]Ai[3938,12,1840,0,1997,0,0]Al[3938,13,1919,0,3340,1997,0]Al[4725,12,1841,1841,1998,0,0]Ao[4725,13,1920,1920,3341,1998,0]Ah[4725,7,4902,4901,0,0,0]0Al[4725,13,4726,3703,3301,0,0]6Ak[3938,13,3939,1045,474,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]Ao[4007,13,4008,4008,5014,4820,0]0Ai[3938,13,3939,0,4104,0,0]Al[4725,13,4726,1838,4106,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]10Ai[3938,13,3939,0,4791,0,0]Al[4725,13,4726,3283,4792,0,0]Am[1361,13,1362,1362,125,456,0]An[1046,13,1047,1047,3112,456,0]Am[1046,13,1830,1830,126,456,0]Am[1046,13,1925,1925,127,456,0]Am[3958,13,3959,3959,116,456,0]??>An[1361,13,1362,1362,125,4369,0]Ao[1046,13,1047,1047,3112,4369,0]An[1046,13,1830,1830,126,4369,0]An[1046,13,1925,1925,127,4369,0]An[3958,13,3959,3959,116,4369,0]Ao[3958,13,3959,3959,2382,4369,0]Ai[3938,13,3939,0,4152,0,0]Al[4725,13,4726,1838,4154,0,0]Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]Ae[1046,5,4211,0,0,0,0]0Ai[3938,13,3939,0,4367,0,0]Al[4725,13,4726,1838,4368,0,0]Ai[3938,13,3939,0,4104,0,0]Al[4725,13,4726,1838,4106,0,0]Al[3938,13,3939,2436,2391,0,0]Al[3938,13,3939,2463,2395,0,0]Al[4725,13,4726,2437,2396,0,0]Al[4725,13,4726,3703,3301,0,0]Ao[4007,13,4008,4008,5014,4820,0];:Ah[3938,5,1840,1841,0,0,0]Ae[4725,5,1841,0,0,0,0]Ai[3938,15,1919,0,1337,0,0]Ai[4725,15,1920,0,1338,0,0]?>?>Al[3938,13,3939,3702,3300,0,0]6Ai[3938,13,3939,0,4506,0,0]Al[4725,13,4726,3283,4507,0,0]Ae[4007,7,4008,0,0,0,0]Ae[4296,7,4297,0,0,0,0]Ai[3938,14,3939,0,3306,0,0]Al[4725,14,4726,1538,3307,0,0]?=Ai[3938,19,3939,0,4825,0,0]Ai[4725,19,4726,0,4826,0,0]2=<==<>=>=>=<;<;Al[4725,14,4968,4968,4867,0,0]?>Ai[4725,18,4726,3283,0,0,0]") \ No newline at end of file diff --git a/pr/255/docs/search.index/entry/ebf157109a27.js b/pr/255/docs/search.index/entry/ebf157109a27.js deleted file mode 100644 index c219da8fe..000000000 --- a/pr/255/docs/search.index/entry/ebf157109a27.js +++ /dev/null @@ -1 +0,0 @@ -rd_("Ah[3817,15,3818,0,113,0,0]Ak[4595,15,4596,4596,114,0,0]Ai[3817,15,3818,0,4001,0,0]Al[4595,15,4596,1873,4002,0,0]Al[4307,15,4308,4308,4003,0,0]Al[4595,15,1781,1781,1543,0,0]Ao[1320,13,1321,1321,3849,3043,0]Ao[3817,13,3818,3593,4637,3043,0]Ao[3817,13,3818,3952,4267,3043,0]Ao[3817,13,3818,3952,3051,3043,0]Ao[3817,13,3818,3952,3232,3043,0]Ao[3817,13,3818,3952,4266,3043,0]Ao[3817,13,3818,3957,3249,3043,0]Ao[3817,13,3818,3957,4035,3043,0]Al[3817,13,3818,0,1552,3043,0]Al[3817,13,3818,0,4796,3043,0]Al[3817,13,3818,0,1280,3043,0]Al[3817,13,3818,0,1536,3043,0]Al[3817,13,3818,0,3048,3043,0]Al[3817,13,3818,0,1952,3043,0]Al[3817,13,3818,0,3988,3043,0]Al[3817,13,3818,0,4361,3043,0]Al[3817,13,3818,0,3862,3043,0]Al[3817,13,3818,0,3852,3043,0]Al[3817,13,3818,0,3031,3043,0]Al[3817,13,3818,0,4358,3043,0]Al[3817,13,3818,0,4540,3043,0]Al[3817,13,3818,0,3994,3043,0]Al[3817,13,3818,0,3997,3043,0]Al[3817,13,3818,0,4001,3043,0]Al[3817,13,3818,0,4695,3043,0]Ak[3817,13,3818,0,466,3043,0]Ak[3817,13,3818,0,113,3043,0]Al[3817,13,3818,0,2348,3043,0]Al[3817,13,1785,0,4943,3043,0]Al[3817,13,1862,0,1297,3043,0]Ao[4595,13,4596,1895,1553,3043,0]Ao[4595,13,4596,1895,4797,3043,0]Ao[4595,13,4596,3067,1281,3043,0]Ao[4595,13,4596,3076,4638,3043,0]Ao[4595,13,4596,1476,1537,3043,0]Ao[4595,13,4596,1476,3226,3043,0]Ao[4595,13,4596,1476,3047,3043,0]Ao[4595,13,4596,1476,4692,3043,0]Ao[4595,13,4596,1476,3202,3043,0]Ao[4595,13,4596,1492,3049,3043,0]Ao[4595,13,4596,1039,3052,3043,0]Ao[4595,13,4596,1039,4157,3043,0]Ao[4595,13,4596,1044,1953,3043,0]Ao[4595,13,4596,1044,3250,3043,0]Ao[4595,13,4596,1044,3861,3043,0]Ao[4595,13,4596,2086,3879,3043,0]Ao[4595,13,4596,2086,4268,3043,0]Ao[4595,13,4596,2086,3992,3043,0]Ao[4595,13,4596,3594,4362,3043,0]Ao[4595,13,4596,3594,3044,3043,0]Ao[4595,13,4596,3594,4235,3043,0]Ao[4595,13,4596,3189,3863,3043,0]Ao[4595,13,4596,1783,3853,3043,0]Ao[4595,13,4596,1466,3032,3043,0]Ao[4595,13,4596,1466,4360,3043,0]Ao[4595,13,4596,1466,4542,3043,0]Ao[4595,13,4596,2371,4546,3043,0]Ao[4595,13,4596,2371,3995,3043,0]Ao[4595,13,4596,1846,2332,3043,0]Ao[4595,13,4596,1846,4636,3043,0]Ao[4595,13,4596,1873,3998,3043,0]Ao[4595,13,4596,1873,4002,3043,0]Al[4595,13,4596,0,4272,3043,0]Al[4595,13,4596,0,4696,3043,0]An[4595,13,4596,4596,467,3043,0]An[4595,13,4596,4596,114,3043,0]Ao[4595,13,4596,4596,2349,3043,0]Ao[4595,13,4596,4596,3030,3043,0]Ao[4595,13,1781,1781,4163,3043,0]Ao[4595,13,4838,4838,4737,3043,0]Ao[4595,13,4838,4838,1299,3043,0]Ao[4595,13,1786,1786,4944,3043,0]Al[4595,13,1863,0,1298,3043,0]Ao[4307,13,4308,4308,4003,3043,0]Ak[3817,13,3818,1014,459,0,0]Al[3817,13,3818,3952,3230,0,0]Al[3817,13,3818,3952,4738,0,0]Al[3817,13,3818,3957,3236,0,0]Ai[4595,14,3045,0,1530,0,0]Ai[4595,14,3045,0,1520,0,0]Ai[4595,14,3045,0,3011,0,0]Ai[4595,14,3045,0,4140,0,0]Ai[4595,14,3045,0,4022,0,0]Ai[4595,14,3045,0,4015,0,0]Ai[4595,14,3878,0,2342,0,0]Ai[4595,14,3878,0,2363,0,0]Ai[4595,14,3878,0,2327,0,0]Ai[4595,14,3878,0,1942,0,0]Ae[1320,7,1321,0,0,0,0]Ah[4595,14,4373,0,456,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Ag[3817,5,3588,129,0,0,0]Ag[4595,5,3589,129,0,0,0]Al[1015,15,1016,1016,4730,0,0]Ae[3837,5,3838,0,0,0,0]Ah[3817,6,3818,4596,0,0,0]Ae[4595,6,4596,0,0,0,0]Al[4595,15,1781,1781,1543,0,0]Ai[3817,19,3818,0,1552,0,0]Ai[3817,19,3818,0,1536,0,0]Al[4595,19,4596,1895,1553,0,0]Al[4595,19,4596,1476,1537,0,0]Ae[1320,5,1321,0,0,0,0]Ae[1015,5,1775,0,0,0,0]Ae[1015,5,1868,0,0,0,0]Ah[3817,15,3818,0,113,0,0]Ak[4595,15,4596,4596,114,0,0]Ak[3817,13,3818,0,1552,124,0]Ak[3817,13,3818,0,1536,124,0]Ak[3817,13,3818,0,3862,124,0]Ak[3817,13,3818,0,3997,124,0]Aj[3817,13,3818,0,466,124,0]Aj[3817,13,3818,0,113,124,0]Ak[3817,13,3818,0,2348,124,0]An[4595,13,4596,1895,1553,124,0]An[4595,13,4596,3076,4638,124,0]An[4595,13,4596,1476,1537,124,0]An[4595,13,4596,1039,3052,124,0]An[4595,13,4596,1039,4157,124,0]An[4595,13,4596,1044,3250,124,0]An[4595,13,4596,3189,3863,124,0]An[4595,13,4596,2371,4546,124,0]An[4595,13,4596,1846,4636,124,0]An[4595,13,4596,1873,3998,124,0]Am[4595,13,4596,4596,467,124,0]Am[4595,13,4596,4596,114,124,0]An[4595,13,4596,4596,2349,124,0]Ai[3817,13,3818,0,2348,0,0]Al[4595,13,4596,4596,2349,0,0]Ai[4595,14,3878,0,1531,0,0]Ai[4595,14,3878,0,3017,0,0]Ai[3817,14,3818,0,2357,0,0]Al[4595,14,4596,4596,2358,0,0]Al[4307,14,4308,4308,2346,0,0]Al[4307,14,4308,4308,2359,0,0]An[1320,13,1321,1321,121,1287,0]Ao[1320,13,1321,1321,3849,1287,0]Ao[1320,13,1490,1490,4269,1287,0]Ao[3886,13,3887,3887,4883,1287,0]Ao[3817,13,3818,3593,3204,1287,0]Ao[3817,13,3818,3593,3206,1287,0]Ao[3817,13,3818,3593,4799,1287,0]Db[3817,13,3818,3593,4637,1287,0,\"impl-Debug-for-SendDatagramError\"]Dd[3817,13,3818,3593,4637,1914,0,\"impl-Display-for-SendDatagramError\"]Ao[3817,13,3818,2370,2325,1287,0]Ao[3817,13,3818,2370,4130,1287,0]Ao[3817,13,3818,2397,2329,1287,0]Ck[3817,13,3818,2397,3233,1287,0,\"impl-Debug-for-RetryError\"]Cm[3817,13,3818,2397,3233,1914,0,\"impl-Display-for-RetryError\"]Ao[3817,13,3818,2397,4249,1287,0]An[3817,13,3818,1014,459,1287,0]Ao[3817,13,3818,3952,3230,1287,0]Ao[3817,13,3818,3952,4738,1287,0]Da[3817,13,3818,3952,4267,1914,0,\"impl-Display-for-ReadToEndError\"]Co[3817,13,3818,3952,4267,1287,0,\"impl-Debug-for-ReadToEndError\"]Cl[3817,13,3818,3952,3051,1914,0,\"impl-Display-for-ReadError\"]Cj[3817,13,3818,3952,3051,1287,0,\"impl-Debug-for-ReadError\"]Ck[3817,13,3818,3952,3232,1287,0,\"impl-Debug-for-ResetError\"]Cm[3817,13,3818,3952,3232,1914,0,\"impl-Display-for-ResetError\"]Co[3817,13,3818,3952,4266,1287,0,\"impl-Debug-for-ReadExactError\"]Da[3817,13,3818,3952,4266,1914,0,\"impl-Display-for-ReadExactError\"]Ao[3817,13,3818,1502,4036,1287,0]Ao[3817,13,3818,1056,3875,1287,0]Ao[3817,13,3818,3957,3236,1287,0]Cm[3817,13,3818,3957,3249,1914,0,\"impl-Display-for-WriteError\"]Ck[3817,13,3818,3957,3249,1287,0,\"impl-Debug-for-WriteError\"]Cm[3817,13,3818,3957,4035,1287,0,\"impl-Debug-for-StoppedError\"]Co[3817,13,3818,3957,4035,1914,0,\"impl-Display-for-StoppedError\"]Cf[3817,13,3818,0,1552,1914,0,\"impl-Display-for-VarInt\"]Cd[3817,13,3818,0,1552,1287,0,\"impl-Debug-for-VarInt\"]Db[3817,13,3818,0,4796,1287,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Dd[3817,13,3818,0,4796,1914,0,\"impl-Display-for-VarIntBoundsExceeded\"]Al[3817,13,3818,0,1280,1287,0]Cd[3817,13,3818,0,1536,1287,0,\"impl-Debug-for-PathId\"]Cf[3817,13,3818,0,1536,1914,0,\"impl-Display-for-PathId\"]Al[3817,13,3818,0,2360,1287,0]Al[3817,13,3818,0,3212,1287,0]Al[3817,13,3818,0,3048,1287,0]Al[3817,13,3818,0,4365,1287,0]Al[3817,13,3818,0,1952,1287,0]Cl[3817,13,3818,0,3988,1914,0,\"impl-Display-for-ClosedStream\"]Cj[3817,13,3818,0,3988,1287,0,\"impl-Debug-for-ClosedStream\"]Cm[3817,13,3818,0,4361,1287,0,\"impl-Debug-for-ConnectionError\"]Co[3817,13,3818,0,4361,1914,0,\"impl-Display-for-ConnectionError\"]Al[3817,13,3818,0,4375,1287,0]Al[3817,13,3818,0,4382,1287,0]Al[3817,13,3818,0,4661,1287,0]Al[3817,13,3818,0,4676,1287,0]Al[3817,13,3818,0,3862,1287,0]Al[3817,13,3818,0,4244,1287,0]Al[3817,13,3818,0,4029,1287,0]Al[3817,13,3818,0,4853,1287,0]Al[3817,13,3818,0,3982,1287,0]Ck[3817,13,3818,0,3852,1914,0,\"impl-Display-for-ConfigError\"]Ci[3817,13,3818,0,3852,1287,0,\"impl-Debug-for-ConfigError\"]Ci[3817,13,3818,0,3031,1914,0,\"impl-Display-for-FrameType\"]Cg[3817,13,3818,0,3031,1287,0,\"impl-Debug-for-FrameType\"]Cm[3817,13,3818,0,4358,1287,0,\"impl-Debug-for-ConnectionClose\"]Co[3817,13,3818,0,4358,1914,0,\"impl-Display-for-ConnectionClose\"]D`[3817,13,3818,0,4540,1914,0,\"impl-Display-for-ApplicationClose\"]Cn[3817,13,3818,0,4540,1287,0,\"impl-Debug-for-ApplicationClose\"]Cj[3817,13,3818,0,3994,1287,0,\"impl-Debug-for-ConnectError\"]Cl[3817,13,3818,0,3994,1914,0,\"impl-Display-for-ConnectError\"]Cl[3817,13,3818,0,3997,1914,0,\"impl-Display-for-ConnectionId\"]Cj[3817,13,3818,0,3997,1287,0,\"impl-Debug-for-ConnectionId\"]Al[3817,13,3818,0,4001,1287,0]Db[3817,13,3818,0,4695,1914,0,\"impl-Display-for-TransportErrorCode\"]D`[3817,13,3818,0,4695,1287,0,\"impl-Debug-for-TransportErrorCode\"]Al[3817,13,3818,0,4571,1287,0]Ak[3817,13,3818,0,466,1287,0]C`[3817,13,3818,0,113,1287,0,\"impl-Debug-for-Dir\"]Cb[3817,13,3818,0,113,1914,0,\"impl-Display-for-Dir\"]Ch[3817,13,3818,0,2348,1914,0,\"impl-Display-for-StreamId\"]Cf[3817,13,3818,0,2348,1287,0,\"impl-Debug-for-StreamId\"]Al[3817,13,3818,0,2357,1287,0]Ak[3817,13,3588,0,107,1287,0]Al[3817,13,3588,0,3020,1287,0]Al[3817,13,3588,0,1284,1287,0]Al[3817,13,3588,0,3857,1287,0]Al[3817,13,3588,0,1927,1287,0]Al[3817,13,3588,0,4149,1287,0]Al[3817,13,3588,0,4629,1287,0]Al[3817,13,1785,0,4943,1287,0]Al[3817,13,1785,0,3855,1287,0]Al[3817,13,1785,0,4699,1287,0]Db[3817,13,1862,0,4792,1287,0,\"impl-Debug-for-NoInitialCipherSuite\"]Dd[3817,13,1862,0,4792,1914,0,\"impl-Display-for-NoInitialCipherSuite\"]Ce[3817,13,1862,0,1297,1914,0,\"impl-Display-for-Error\"]Cc[3817,13,1862,0,1297,1287,0,\"impl-Debug-for-Error\"]Ao[4595,13,4596,3594,3207,1287,0]Ao[4595,13,4596,2371,2326,1287,0]Cg[4595,13,4596,1895,1553,1287,0,\"impl-Debug-for-VarInt\"]Ci[4595,13,4596,1895,1553,1914,0,\"impl-Display-for-VarInt\"]De[4595,13,4596,1895,4797,1287,0,\"impl-Debug-for-VarIntBoundsExceeded\"]Dg[4595,13,4596,1895,4797,1914,0,\"impl-Display-for-VarIntBoundsExceeded\"]Ao[4595,13,4596,3067,1281,1287,0]Db[4595,13,4596,3076,4638,1287,0,\"impl-Debug-for-SendDatagramError\"]Dd[4595,13,4596,3076,4638,1914,0,\"impl-Display-for-SendDatagramError\"]Ci[4595,13,4596,1476,1537,1914,0,\"impl-Display-for-PathId\"]Cg[4595,13,4596,1476,1537,1287,0,\"impl-Debug-for-PathId\"]Ao[4595,13,4596,1476,4025,1287,0]Ao[4595,13,4596,1476,3226,1287,0]Ao[4595,13,4596,1476,3047,1287,0]De[4595,13,4596,1476,4692,1914,0,\"impl-Display-for-SetPathStatusError\"]Dc[4595,13,4596,1476,4692,1287,0,\"impl-Debug-for-SetPathStatusError\"]Cm[4595,13,4596,1476,3202,1914,0,\"impl-Display-for-ClosedPath\"]Ck[4595,13,4596,1476,3202,1287,0,\"impl-Debug-for-ClosedPath\"]Ao[4595,13,4596,1492,2361,1287,0]Ao[4595,13,4596,1492,3213,1287,0]Ao[4595,13,4596,1492,3049,1287,0]Ao[4595,13,4596,1492,4366,1287,0]Cl[4595,13,4596,1039,3052,1914,0,\"impl-Display-for-ReadError\"]Cj[4595,13,4596,1039,3052,1287,0,\"impl-Debug-for-ReadError\"]D`[4595,13,4596,1039,4157,1914,0,\"impl-Display-for-ReadableError\"]Cn[4595,13,4596,1039,4157,1287,0,\"impl-Debug-for-ReadableError\"]Ao[4595,13,4596,1044,1953,1287,0]Ck[4595,13,4596,1044,3250,1287,0,\"impl-Debug-for-WriteError\"]Cm[4595,13,4596,1044,3250,1914,0,\"impl-Display-for-WriteError\"]Cn[4595,13,4596,1044,3861,1914,0,\"impl-Display-for-FinishError\"]Cl[4595,13,4596,1044,3861,1287,0,\"impl-Debug-for-FinishError\"]Ao[4595,13,4596,2086,3879,1287,0]Ao[4595,13,4596,2086,4268,1287,0]Cm[4595,13,4596,2086,3992,1287,0,\"impl-Debug-for-ClosedStream\"]Co[4595,13,4596,2086,3992,1914,0,\"impl-Display-for-ClosedStream\"]Db[4595,13,4596,3594,4362,1914,0,\"impl-Display-for-ConnectionError\"]D`[4595,13,4596,3594,4362,1287,0,\"impl-Debug-for-ConnectionError\"]Cl[4595,13,4596,3594,3044,1914,0,\"impl-Display-for-PathError\"]Cj[4595,13,4596,3594,3044,1287,0,\"impl-Debug-for-PathError\"]Da[4595,13,4596,3594,4235,1914,0,\"impl-Display-for-ClosePathError\"]Co[4595,13,4596,3594,4235,1287,0,\"impl-Debug-for-ClosePathError\"]Ao[4595,13,4596,3594,1302,1287,0]Ao[4595,13,4596,1035,4376,1287,0]Ao[4595,13,4596,3189,4383,1287,0]Ao[4595,13,4596,3189,4662,1287,0]Ao[4595,13,4596,3189,4677,1287,0]Ao[4595,13,4596,3189,3863,1287,0]Ao[4595,13,4596,1783,4245,1287,0]Ao[4595,13,4596,1783,4031,1287,0]Ao[4595,13,4596,1783,4854,1287,0]Ao[4595,13,4596,1783,3984,1287,0]Cl[4595,13,4596,1783,3853,1287,0,\"impl-Debug-for-ConfigError\"]Cn[4595,13,4596,1783,3853,1914,0,\"impl-Display-for-ConfigError\"]Cj[4595,13,4596,1466,3032,1287,0,\"impl-Debug-for-FrameType\"]Cl[4595,13,4596,1466,3032,1914,0,\"impl-Display-for-FrameType\"]D`[4595,13,4596,1466,4360,1287,0,\"impl-Debug-for-ConnectionClose\"]Db[4595,13,4596,1466,4360,1914,0,\"impl-Display-for-ConnectionClose\"]Da[4595,13,4596,1466,4542,1287,0,\"impl-Debug-for-ApplicationClose\"]Dc[4595,13,4596,1466,4542,1914,0,\"impl-Display-for-ApplicationClose\"]Ao[4595,13,4596,1466,2319,1287,0]Ao[4595,13,4596,2371,4546,1287,0]Ao[4595,13,4596,2371,2330,1287,0]Co[4595,13,4596,2371,3995,1914,0,\"impl-Display-for-ConnectError\"]Cm[4595,13,4596,2371,3995,1287,0,\"impl-Debug-for-ConnectError\"]Ao[4595,13,4596,2371,3847,1287,0]Cm[4595,13,4596,2371,3234,1914,0,\"impl-Display-for-RetryError\"]Ck[4595,13,4596,2371,3234,1287,0,\"impl-Debug-for-RetryError\"]Ao[4595,13,4596,1846,4152,1287,0]Ao[4595,13,4596,1846,4374,1287,0]Ao[4595,13,4596,1846,4882,1287,0]Ao[4595,13,4596,1846,2332,1287,0]Dd[4595,13,4596,1846,4636,1914,0,\"impl-Display-for-PacketDecodeError\"]Db[4595,13,4596,1846,4636,1287,0,\"impl-Debug-for-PacketDecodeError\"]Ao[4595,13,4596,1873,4364,1287,0]Ao[4595,13,4596,1873,4129,1287,0]Cm[4595,13,4596,1873,3998,1287,0,\"impl-Debug-for-ConnectionId\"]Co[4595,13,4596,1873,3998,1914,0,\"impl-Display-for-ConnectionId\"]Ao[4595,13,4596,1873,4002,1287,0]Cc[4595,13,4596,0,4272,1287,0,\"impl-Debug-for-Error\"]Ce[4595,13,4596,0,4272,1914,0,\"impl-Display-for-Error\"]Cd[4595,13,4596,0,4696,1914,0,\"impl-Display-for-Code\"]Cb[4595,13,4596,0,4696,1287,0,\"impl-Debug-for-Code\"]Ao[4595,13,4596,4170,3216,1287,0]Ao[4595,13,4596,4170,4977,1287,0]Ao[4595,13,4596,4726,4572,1287,0]An[4595,13,4596,4596,467,1287,0]Cc[4595,13,4596,4596,114,1287,0,\"impl-Debug-for-Dir\"]Ce[4595,13,4596,4596,114,1914,0,\"impl-Display-for-Dir\"]Ci[4595,13,4596,4596,2349,1287,0,\"impl-Debug-for-StreamId\"]Ck[4595,13,4596,4596,2349,1914,0,\"impl-Display-for-StreamId\"]Ao[4595,13,4596,4596,2358,1287,0]Cj[4595,13,4596,4596,3030,1287,0,\"impl-Debug-for-FourTuple\"]Cl[4595,13,4596,4596,3030,1914,0,\"impl-Display-for-FourTuple\"]Cn[4595,13,1781,1781,4163,1287,0,\"impl-Debug-for-UnexpectedEnd\"]D`[4595,13,1781,1781,4163,1914,0,\"impl-Display-for-UnexpectedEnd\"]Ao[4595,13,4838,4838,4737,1287,0]Ch[4595,13,4838,4838,1299,1914,0,\"impl-Display-for-Error\"]Cf[4595,13,4838,4838,1299,1287,0,\"impl-Debug-for-Error\"]Ao[4595,13,1786,1786,4944,1287,0]Ao[4595,13,1786,1786,3856,1287,0]Ao[4595,13,1786,1786,4702,1287,0]De[4595,13,1863,1863,4793,1287,0,\"impl-Debug-for-NoInitialCipherSuite\"]Dg[4595,13,1863,1863,4793,1914,0,\"impl-Display-for-NoInitialCipherSuite\"]Cc[4595,13,1863,0,1298,1287,0,\"impl-Debug-for-Error\"]Ce[4595,13,1863,0,1298,1914,0,\"impl-Display-for-Error\"]Am[4595,13,3589,129,108,1287,0]An[4595,13,3589,129,3021,1287,0]Ao[4595,13,3589,1461,1285,1287,0]Ao[4595,13,3589,1461,3858,1287,0]Ao[4595,13,3589,2419,1928,1287,0]Ao[4595,13,3589,2419,4150,1287,0]Ao[4595,13,3589,3589,4630,1287,0]Cf[4595,13,2057,2057,1300,1287,0,\"impl-Debug-for-Error\"]Ch[4595,13,2057,2057,1300,1914,0,\"impl-Display-for-Error\"]Ao[4595,13,2057,2057,1303,1287,0]An[4307,13,4308,375,4273,1287,0]Ao[4307,13,4308,4308,2346,1287,0]Ao[4307,13,4308,4308,2359,1287,0]Ao[4307,13,4308,4308,4003,1287,0]Al[4595,13,4596,1476,4025,0,0]Ai[3817,14,3818,0,2360,0,0]Al[4595,14,4596,1492,2361,0,0]Al[4595,13,4596,1846,4152,0,0]Al[4595,14,4596,1846,4882,0,0]Ah[4595,14,4373,0,456,0,0]Al[4307,14,4308,4308,2346,0,0]Ai[3817,13,3818,0,4853,0,0]Al[4595,13,4596,1783,4854,0,0]8Al[1320,13,1490,1490,4269,0,0]Al[3886,13,3887,3887,4883,0,0]Ai[3817,13,3818,0,4121,0,0]Al[3817,13,3818,2370,2325,0,0]Ai[3817,13,3818,0,3227,0,0]Ai[3817,13,3818,0,4375,0,0]Ai[3817,13,3818,0,4244,0,0]Ai[3817,13,3818,0,4029,0,0]Ai[3817,13,3818,0,3982,0,0]Ai[3817,13,3818,0,3997,0,0]Ai[3817,13,3818,0,4571,0,0]Ai[3817,13,3818,0,2348,0,0]Ah[3817,13,3588,0,107,0,0]Ai[3817,13,3588,0,1284,0,0]Ai[3817,13,3588,0,1927,0,0]Al[4595,13,4596,4392,4122,0,0]Al[4595,13,4596,1035,3228,0,0]Al[4595,13,4596,2371,2326,0,0]Al[4595,13,4596,1846,5002,0,0]Al[4595,13,4596,4170,4972,0,0]Al[4595,13,4596,1035,4376,0,0]Al[4595,13,4596,1783,4245,0,0]Al[4595,13,4596,1783,4031,0,0]Al[4595,13,4596,1783,3984,0,0]Al[4595,13,4596,1846,4152,0,0]Al[4595,13,4596,1873,3998,0,0]Ai[4595,13,4596,0,4272,0,0]Al[4595,13,4596,4170,4977,0,0]Al[4595,13,4596,4726,4572,0,0]Al[4595,13,4596,4596,2349,0,0]Aj[4595,13,3589,129,108,0,0]Al[4595,13,3589,1461,1285,0,0]Al[4595,13,3589,2419,1928,0,0]Ak[4307,13,4308,375,4273,0,0]Al[1015,13,4088,4088,4929,0,0]Al[1015,13,4088,4088,4930,0,0]Aj[3817,13,3818,0,466,120,0]Am[4595,13,4596,4596,467,120,0]Ai[3817,12,3818,0,3242,0,0]Al[3817,13,3818,2078,1939,0,0]0Ao[3817,13,3818,1502,4036,1939,0]Al[3817,13,3818,0,4161,3242,0]Al[4595,12,4596,1783,3243,0,0]Ao[4595,13,4596,1783,4162,3243,0]Al[3817,13,3818,3593,3206,0,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,13,4596,3594,3207,0,0]Al[4595,14,4596,1492,3049,0,0]Ae[1015,7,1775,0,0,0,0]Ae[1015,7,1868,0,0,0,0]Ae[3817,4,3818,0,0,0,0]Ai[3817,15,3818,0,4001,0,0]Al[4595,15,4596,1873,4002,0,0]Al[4307,15,4308,4308,4003,0,0]210Ah[3817,5,1785,1786,0,0,0]Ae[4595,5,1786,0,0,0,0]Al[4595,15,4596,1846,4374,0,0]Ah[3817,5,3818,1014,0,0,0]Al[4595,15,4596,3594,1302,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Al[3817,15,3818,3952,4267,0,0]Ah[3817,6,3818,4596,0,0,0]Ae[4595,6,4596,0,0,0,0]Ai[3817,19,3818,0,1536,0,0]Al[4595,19,4596,1476,1537,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Ai[4595,14,3045,0,4015,0,0]Al[4307,14,4308,4308,2346,0,0]Aa[476,3,0,0,0,0,0]Ai[4595,14,4596,0,4272,0,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,14,4596,1492,3049,0,0]Al[4595,14,4596,1466,2319,0,0]An[3817,13,3818,3593,2339,444,0]An[3817,13,3818,2397,2329,444,0]An[3817,13,3818,3952,3230,444,0]An[3817,13,3818,3957,3236,444,0]An[4595,13,4596,1039,1516,444,0]Am[1320,13,1321,1321,121,451,0]An[1320,13,1321,1321,3849,451,0]An[1320,13,1490,1490,3880,451,0]An[1320,13,1490,1490,1316,451,0]An[1320,13,1490,1490,4269,451,0]Ak[476,13,477,477,3850,451,0]An[3886,13,3887,3887,4883,451,0]An[3817,13,3818,3593,4387,451,0]An[3817,13,3818,3593,2339,451,0]Ak[3817,13,3818,0,4121,451,0]An[3817,13,3818,1014,2340,451,0]An[3817,13,3818,3593,3204,451,0]An[3817,13,3818,3593,3206,451,0]An[3817,13,3818,3593,1930,451,0]An[3817,13,3818,3593,1529,451,0]An[3817,13,3818,3593,3013,451,0]An[3817,13,3818,3593,2313,451,0]An[3817,13,3818,3593,4021,451,0]An[3817,13,3818,3593,4026,451,0]An[3817,13,3818,3593,4799,451,0]An[3817,13,3818,3593,4637,451,0]0An[3817,13,3818,2370,2325,451,0]An[3817,13,3818,2370,4130,451,0]An[3817,13,3818,2370,1508,451,0]An[3817,13,3818,2397,2329,451,0]An[3817,13,3818,2397,3233,451,0]An[3817,13,3818,2397,4249,451,0]Am[3817,13,3818,1014,459,451,0]An[3817,13,3818,3952,3230,451,0]An[3817,13,3818,3952,4738,451,0]An[3817,13,3818,3952,4267,451,0]0An[3817,13,3818,3952,3051,451,0]Dh[3817,13,3818,3952,3051,451,0,\"impl-From%3CResetError%3E-for-ReadError\"]Dm[3817,13,3818,3952,3051,451,0,\"impl-From%3CConnectionError%3E-for-ReadError\"]An[3817,13,3818,3952,3232,451,0]0An[3817,13,3818,3952,4266,451,0]0An[3817,13,3818,1502,4036,451,0]An[3817,13,3818,1056,3875,451,0]An[3817,13,3818,3957,3236,451,0]Dn[3817,13,3818,3957,3249,451,0,\"impl-From%3CConnectionError%3E-for-WriteError\"]Dk[3817,13,3818,3957,3249,451,0,\"impl-From%3CStoppedError%3E-for-WriteError\"]Dk[3817,13,3818,3957,3249,451,0,\"impl-From%3CClosedStream%3E-for-WriteError\"]An[3817,13,3818,3957,3249,451,0]An[3817,13,3818,3957,4035,451,0]0Ak[3817,13,3818,0,3227,451,0]Ak[3817,13,3818,0,4161,451,0]Ak[3817,13,3818,0,4379,451,0]Ak[3817,13,3818,0,4013,451,0]Ak[3817,13,3818,0,4257,451,0]Ak[3817,13,3818,0,1552,451,0]Ck[3817,13,3818,0,1552,451,0,\"impl-From%3Cu32%3E-for-VarInt\"]Cj[3817,13,3818,0,1552,451,0,\"impl-From%3Cu8%3E-for-VarInt\"]Ck[3817,13,3818,0,1552,451,0,\"impl-From%3Cu16%3E-for-VarInt\"]D`[3817,13,3818,0,1552,451,0,\"impl-From%3CStreamId%3E-for-VarInt\"]Dj[3817,13,3818,0,1552,451,0,\"impl-From%3CTransportErrorCode%3E-for-VarInt\"]Ak[3817,13,3818,0,4796,451,0]Ak[3817,13,3818,0,1280,451,0]Ak[3817,13,3818,0,1536,451,0]0Ak[3817,13,3818,0,2360,451,0]Ak[3817,13,3818,0,3212,451,0]Ak[3817,13,3818,0,3048,451,0]Ak[3817,13,3818,0,4365,451,0]Ak[3817,13,3818,0,1952,451,0]Ak[3817,13,3818,0,3988,451,0]Dl[3817,13,3818,0,4361,451,0,\"impl-From%3CCloseReason%3E-for-ConnectionError\"]Ak[3817,13,3818,0,4361,451,0]Df[3817,13,3818,0,4361,451,0,\"impl-From%3CClose%3E-for-ConnectionError\"]Do[3817,13,3818,0,4361,451,0,\"impl-From%3CTransportError%3E-for-ConnectionError\"]Ak[3817,13,3818,0,4375,451,0]Ak[3817,13,3818,0,4382,451,0]Ak[3817,13,3818,0,4661,451,0]Ak[3817,13,3818,0,4676,451,0]Ak[3817,13,3818,0,3862,451,0]0Ak[3817,13,3818,0,4244,451,0]Ak[3817,13,3818,0,4029,451,0]Ak[3817,13,3818,0,4853,451,0]Ak[3817,13,3818,0,3982,451,0]Dl[3817,13,3818,0,3852,451,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]Ak[3817,13,3818,0,3852,451,0]Ea[3817,13,3818,0,3852,451,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]Ak[3817,13,3818,0,3031,451,0]Ak[3817,13,3818,0,4358,451,0]0Ak[3817,13,3818,0,4540,451,0]Ak[3817,13,3818,0,3994,451,0]0Ak[3817,13,3818,0,3997,451,0]Ak[3817,13,3818,0,4001,451,0]Ak[3817,13,3818,0,4695,451,0]0Ak[3817,13,3818,0,4571,451,0]Aj[3817,13,3818,0,466,451,0]Aj[3817,13,3818,0,113,451,0]Ak[3817,13,3818,0,2348,451,0]0Ak[3817,13,3818,0,2357,451,0]Aj[3817,13,3588,0,107,451,0]Ak[3817,13,3588,0,3020,451,0]Ak[3817,13,3588,0,1284,451,0]Ak[3817,13,3588,0,3857,451,0]Ak[3817,13,3588,0,1927,451,0]Ak[3817,13,3588,0,4149,451,0]Ak[3817,13,3588,0,4629,451,0]Ak[3817,13,1785,0,1922,451,0]Aj[3817,13,1785,0,454,451,0]Ak[3817,13,1785,0,4943,451,0]Ak[3817,13,1785,0,3855,451,0]0Ak[3817,13,1785,0,4699,451,0]Ak[3817,13,1862,0,3244,451,0]Ak[3817,13,1862,0,4132,451,0]Ak[3817,13,1862,0,4567,451,0]Ak[3817,13,1862,0,4569,451,0]Ak[3817,13,1862,0,4792,451,0]Dg[3817,13,1862,0,1297,451,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]E`[3817,13,1862,0,1297,451,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]Df[3817,13,1862,0,1297,451,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Df[3817,13,1862,0,1297,451,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]E`[3817,13,1862,0,1297,451,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]Dn[3817,13,1862,0,1297,451,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]Dg[3817,13,1862,0,1297,451,0,\"impl-From%3CCertificateError%3E-for-Error\"]Dg[3817,13,1862,0,1297,451,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]De[3817,13,1862,0,1297,451,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]De[3817,13,1862,0,1297,451,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]Ak[3817,13,1862,0,1297,451,0]Da[3817,13,1862,0,1297,451,0,\"impl-From%3COtherError%3E-for-Error\"]An[4595,13,4596,4392,4122,451,0]An[4595,13,4596,3076,3026,451,0]An[4595,13,4596,1039,1516,451,0]An[4595,13,4596,2086,1947,451,0]An[4595,13,4596,2086,3231,451,0]An[4595,13,4596,2086,3237,451,0]An[4595,13,4596,3594,3207,451,0]An[4595,13,4596,1035,3228,451,0]An[4595,13,4596,1783,4162,451,0]An[4595,13,4596,2371,2326,451,0]An[4595,13,4596,2371,4128,451,0]An[4595,13,4596,1846,5002,451,0]An[4595,13,4596,4170,4972,451,0]An[4595,13,4596,1501,4380,451,0]An[4595,13,4596,1501,4014,451,0]An[4595,13,4596,1501,4258,451,0]Dc[4595,13,4596,1895,1553,451,0,\"impl-From%3CStreamId%3E-for-VarInt\"]Co[4595,13,4596,1895,1553,451,0,\"impl-From%3CCode%3E-for-VarInt\"]Cn[4595,13,4596,1895,1553,451,0,\"impl-From%3Cu16%3E-for-VarInt\"]An[4595,13,4596,1895,1553,451,0]Cn[4595,13,4596,1895,1553,451,0,\"impl-From%3Cu32%3E-for-VarInt\"]Cm[4595,13,4596,1895,1553,451,0,\"impl-From%3Cu8%3E-for-VarInt\"]An[4595,13,4596,1895,4797,451,0]An[4595,13,4596,3067,1281,451,0]An[4595,13,4596,3076,4638,451,0]An[4595,13,4596,1476,1537,451,0]0An[4595,13,4596,1476,4025,451,0]An[4595,13,4596,1476,3226,451,0]An[4595,13,4596,1476,3047,451,0]An[4595,13,4596,1476,4692,451,0]An[4595,13,4596,1476,3202,451,0]An[4595,13,4596,1492,2361,451,0]An[4595,13,4596,1492,3213,451,0]An[4595,13,4596,1492,3049,451,0]An[4595,13,4596,1492,4366,451,0]An[4595,13,4596,1039,3052,451,0]An[4595,13,4596,1039,4157,451,0]An[4595,13,4596,1044,1953,451,0]An[4595,13,4596,1044,3250,451,0]An[4595,13,4596,1044,3861,451,0]An[4595,13,4596,2086,3879,451,0]An[4595,13,4596,2086,4268,451,0]An[4595,13,4596,2086,3992,451,0]An[4595,13,4596,3594,4362,451,0]0An[4595,13,4596,3594,3044,451,0]An[4595,13,4596,3594,4235,451,0]An[4595,13,4596,3594,1302,451,0]0An[4595,13,4596,1035,4376,451,0]An[4595,13,4596,3189,4383,451,0]An[4595,13,4596,3189,4662,451,0]An[4595,13,4596,3189,4677,451,0]An[4595,13,4596,3189,3863,451,0]0An[4595,13,4596,1783,4245,451,0]An[4595,13,4596,1783,4031,451,0]An[4595,13,4596,1783,4854,451,0]An[4595,13,4596,1783,3984,451,0]Do[4595,13,4596,1783,3853,451,0,\"impl-From%3CTryFromIntError%3E-for-ConfigError\"]An[4595,13,4596,1783,3853,451,0]Ed[4595,13,4596,1783,3853,451,0,\"impl-From%3CVarIntBoundsExceeded%3E-for-ConfigError\"]An[4595,13,4596,1466,3032,451,0]An[4595,13,4596,1466,4360,451,0]0An[4595,13,4596,1466,4542,451,0]An[4595,13,4596,1466,2319,451,0]An[4595,13,4596,2371,4546,451,0]An[4595,13,4596,2371,2330,451,0]An[4595,13,4596,2371,3995,451,0]0An[4595,13,4596,2371,3847,451,0]An[4595,13,4596,2371,3234,451,0]An[4595,13,4596,1846,4152,451,0]An[4595,13,4596,1846,4374,451,0]An[4595,13,4596,1846,4882,451,0]An[4595,13,4596,1846,2332,451,0]An[4595,13,4596,1846,4636,451,0]0An[4595,13,4596,1873,4364,451,0]An[4595,13,4596,1873,4129,451,0]An[4595,13,4596,1873,3998,451,0]An[4595,13,4596,1873,4002,451,0]Ak[4595,13,4596,0,4272,451,0]0Ak[4595,13,4596,0,4696,451,0]0An[4595,13,4596,4170,3216,451,0]An[4595,13,4596,4170,4977,451,0]An[4595,13,4596,4726,4572,451,0]Am[4595,13,4596,4596,467,451,0]Am[4595,13,4596,4596,114,451,0]An[4595,13,4596,4596,2349,451,0]0An[4595,13,4596,4596,2358,451,0]An[4595,13,4596,4596,3030,451,0]An[4595,13,1781,1781,4163,451,0]An[4595,13,4838,4838,4737,451,0]An[4595,13,4838,4838,1299,451,0]0An[4595,13,1786,1786,1923,451,0]Am[4595,13,1786,1786,455,451,0]An[4595,13,1786,1786,4944,451,0]An[4595,13,1786,1786,3856,451,0]0An[4595,13,1786,1786,4702,451,0]An[4595,13,1863,1863,3245,451,0]An[4595,13,1863,1863,4133,451,0]An[4595,13,1863,1863,4568,451,0]An[4595,13,1863,1863,4570,451,0]An[4595,13,1863,1863,4793,451,0]De[4595,13,1863,0,1298,451,0,\"impl-From%3CInvalidMessage%3E-for-Error\"]Dn[4595,13,1863,0,1298,451,0,\"impl-From%3CCertRevocationListError%3E-for-Error\"]Ak[4595,13,1863,0,1298,451,0]E`[4595,13,1863,0,1298,451,0,\"impl-From%3CUnsupportedOperationError%3E-for-Error\"]Dg[4595,13,1863,0,1298,451,0,\"impl-From%3CInconsistentKeys%3E-for-Error\"]Da[4595,13,1863,0,1298,451,0,\"impl-From%3COtherError%3E-for-Error\"]Df[4595,13,1863,0,1298,451,0,\"impl-From%3CGetRandomFailed%3E-for-Error\"]Df[4595,13,1863,0,1298,451,0,\"impl-From%3CSystemTimeError%3E-for-Error\"]E`[4595,13,1863,0,1298,451,0,\"impl-From%3CEncryptedClientHelloError%3E-for-Error\"]De[4595,13,1863,0,1298,451,0,\"impl-From%3CPeerMisbehaved%3E-for-Error\"]Dg[4595,13,1863,0,1298,451,0,\"impl-From%3CPeerIncompatible%3E-for-Error\"]Dg[4595,13,1863,0,1298,451,0,\"impl-From%3CCertificateError%3E-for-Error\"]Al[4595,13,3589,129,108,451,0]Am[4595,13,3589,129,3021,451,0]An[4595,13,3589,1461,1285,451,0]An[4595,13,3589,1461,3858,451,0]An[4595,13,3589,2419,1928,451,0]An[4595,13,3589,2419,4150,451,0]An[4595,13,3589,3589,4630,451,0]An[4595,13,2057,2057,1300,451,0]An[4595,13,2057,2057,1303,451,0]An[4307,13,4308,4308,3248,451,0]0Am[4307,13,4308,375,4273,451,0]An[4307,13,4308,4308,2346,451,0]An[4307,13,4308,4308,2359,451,0]An[4307,13,4308,4308,4003,451,0]An[1015,13,1016,1016,3023,451,0]An[1015,13,1016,1016,4730,451,0]Am[1015,13,1775,1775,122,451,0]An[1015,13,1491,1491,1317,451,0]An[1015,13,1491,1491,3881,451,0]An[1015,13,1491,1491,4370,451,0]An[1015,13,4088,4088,4929,451,0]An[1015,13,4088,4088,4930,451,0]Am[1015,13,1868,1868,123,451,0]Am[3837,13,3838,3838,112,451,0]An[3837,13,3838,3838,2316,451,0]Ak[3817,13,3818,0,1552,452,0]Ak[3817,13,3818,0,1536,452,0]Ak[3817,13,3818,0,3862,452,0]Ak[3817,13,3818,0,3997,452,0]Aj[3817,13,3818,0,466,452,0]Aj[3817,13,3818,0,113,452,0]Ak[3817,13,3818,0,2348,452,0]An[4595,13,4596,1895,1553,452,0]An[4595,13,4596,3076,4638,452,0]An[4595,13,4596,1476,1537,452,0]An[4595,13,4596,1039,3052,452,0]An[4595,13,4596,1039,4157,452,0]An[4595,13,4596,1044,3250,452,0]An[4595,13,4596,3189,3863,452,0]An[4595,13,4596,2371,4546,452,0]An[4595,13,4596,1846,4636,452,0]An[4595,13,4596,1873,3998,452,0]Am[4595,13,4596,4596,467,452,0]Am[4595,13,4596,4596,114,452,0]An[4595,13,4596,4596,2349,452,0]An[4595,13,4596,4596,3030,452,0]Am[1320,13,1321,1321,121,453,0]An[1320,13,1321,1321,3849,453,0]An[1320,13,1490,1490,3880,453,0]An[1320,13,1490,1490,1316,453,0]An[1320,13,1490,1490,4269,453,0]Ak[476,13,477,477,3850,453,0]An[3886,13,3887,3887,4883,453,0]An[3817,13,3818,3593,4387,453,0]An[3817,13,3818,3593,2339,453,0]Ak[3817,13,3818,0,4121,453,0]An[3817,13,3818,1014,2340,453,0]An[3817,13,3818,3593,3204,453,0]An[3817,13,3818,3593,3206,453,0]An[3817,13,3818,3593,1930,453,0]An[3817,13,3818,3593,1529,453,0]An[3817,13,3818,3593,3013,453,0]An[3817,13,3818,3593,2313,453,0]An[3817,13,3818,3593,4021,453,0]An[3817,13,3818,3593,4026,453,0]An[3817,13,3818,3593,4799,453,0]An[3817,13,3818,3593,4637,453,0]An[3817,13,3818,2370,2325,453,0]An[3817,13,3818,2370,4130,453,0]An[3817,13,3818,2370,1508,453,0]An[3817,13,3818,2397,2329,453,0]An[3817,13,3818,2397,3233,453,0]An[3817,13,3818,2397,4249,453,0]Am[3817,13,3818,1014,459,453,0]An[3817,13,3818,3952,3230,453,0]An[3817,13,3818,3952,4738,453,0]An[3817,13,3818,3952,4267,453,0]An[3817,13,3818,3952,3051,453,0]An[3817,13,3818,3952,3232,453,0]An[3817,13,3818,3952,4266,453,0]An[3817,13,3818,1502,4036,453,0]An[3817,13,3818,1056,3875,453,0]An[3817,13,3818,3957,3236,453,0]An[3817,13,3818,3957,3249,453,0]An[3817,13,3818,3957,4035,453,0]Ak[3817,13,3818,0,3227,453,0]Ak[3817,13,3818,0,4161,453,0]Ak[3817,13,3818,0,4379,453,0]Ak[3817,13,3818,0,4013,453,0]Ak[3817,13,3818,0,4257,453,0]Ak[3817,13,3818,0,1552,453,0]Ak[3817,13,3818,0,4796,453,0]Ak[3817,13,3818,0,1280,453,0]Ak[3817,13,3818,0,1536,453,0]Ak[3817,13,3818,0,2360,453,0]Ak[3817,13,3818,0,3212,453,0]Ak[3817,13,3818,0,3048,453,0]Ak[3817,13,3818,0,4365,453,0]Ak[3817,13,3818,0,1952,453,0]Ak[3817,13,3818,0,3988,453,0]Ak[3817,13,3818,0,4361,453,0]Ak[3817,13,3818,0,4375,453,0]Ak[3817,13,3818,0,4382,453,0]Ak[3817,13,3818,0,4661,453,0]Ak[3817,13,3818,0,4676,453,0]Ak[3817,13,3818,0,3862,453,0]Ak[3817,13,3818,0,4244,453,0]Ak[3817,13,3818,0,4029,453,0]Ak[3817,13,3818,0,4853,453,0]Ak[3817,13,3818,0,3982,453,0]Ak[3817,13,3818,0,3852,453,0]Ak[3817,13,3818,0,3031,453,0]Ak[3817,13,3818,0,4358,453,0]Ak[3817,13,3818,0,4540,453,0]Ak[3817,13,3818,0,3994,453,0]Ak[3817,13,3818,0,3997,453,0]Ak[3817,13,3818,0,4001,453,0]Ak[3817,13,3818,0,4695,453,0]Ak[3817,13,3818,0,4571,453,0]Aj[3817,13,3818,0,466,453,0]Aj[3817,13,3818,0,113,453,0]Ak[3817,13,3818,0,2348,453,0]Ak[3817,13,3818,0,2357,453,0]Aj[3817,13,3588,0,107,453,0]Ak[3817,13,3588,0,3020,453,0]Ak[3817,13,3588,0,1284,453,0]Ak[3817,13,3588,0,3857,453,0]Ak[3817,13,3588,0,1927,453,0]Ak[3817,13,3588,0,4149,453,0]Ak[3817,13,3588,0,4629,453,0]Ak[3817,13,1785,0,1922,453,0]Aj[3817,13,1785,0,454,453,0]Ak[3817,13,1785,0,4943,453,0]Ak[3817,13,1785,0,3855,453,0]Ak[3817,13,1785,0,4699,453,0]Ak[3817,13,1862,0,3244,453,0]Ak[3817,13,1862,0,4132,453,0]Ak[3817,13,1862,0,4567,453,0]Ak[3817,13,1862,0,4569,453,0]Ak[3817,13,1862,0,4792,453,0]Ak[3817,13,1862,0,1297,453,0]An[4595,13,4596,4392,4122,453,0]An[4595,13,4596,3076,3026,453,0]An[4595,13,4596,1039,1516,453,0]An[4595,13,4596,2086,1947,453,0]An[4595,13,4596,2086,3231,453,0]An[4595,13,4596,2086,3237,453,0]An[4595,13,4596,3594,3207,453,0]An[4595,13,4596,1035,3228,453,0]An[4595,13,4596,1783,4162,453,0]An[4595,13,4596,2371,2326,453,0]An[4595,13,4596,2371,4128,453,0]An[4595,13,4596,1846,5002,453,0]An[4595,13,4596,4170,4972,453,0]An[4595,13,4596,1501,4380,453,0]An[4595,13,4596,1501,4014,453,0]An[4595,13,4596,1501,4258,453,0]An[4595,13,4596,1895,1553,453,0]An[4595,13,4596,1895,4797,453,0]An[4595,13,4596,3067,1281,453,0]An[4595,13,4596,3076,4638,453,0]An[4595,13,4596,1476,1537,453,0]An[4595,13,4596,1476,4025,453,0]An[4595,13,4596,1476,3226,453,0]An[4595,13,4596,1476,3047,453,0]An[4595,13,4596,1476,4692,453,0]An[4595,13,4596,1476,3202,453,0]An[4595,13,4596,1492,2361,453,0]An[4595,13,4596,1492,3213,453,0]An[4595,13,4596,1492,3049,453,0]An[4595,13,4596,1492,4366,453,0]An[4595,13,4596,1039,3052,453,0]An[4595,13,4596,1039,4157,453,0]An[4595,13,4596,1044,1953,453,0]An[4595,13,4596,1044,3250,453,0]An[4595,13,4596,1044,3861,453,0]An[4595,13,4596,2086,3879,453,0]An[4595,13,4596,2086,4268,453,0]An[4595,13,4596,2086,3992,453,0]An[4595,13,4596,3594,4362,453,0]An[4595,13,4596,3594,3044,453,0]An[4595,13,4596,3594,4235,453,0]An[4595,13,4596,3594,1302,453,0]An[4595,13,4596,1035,4376,453,0]An[4595,13,4596,3189,4383,453,0]An[4595,13,4596,3189,4662,453,0]An[4595,13,4596,3189,4677,453,0]An[4595,13,4596,3189,3863,453,0]An[4595,13,4596,1783,4245,453,0]An[4595,13,4596,1783,4031,453,0]An[4595,13,4596,1783,4854,453,0]An[4595,13,4596,1783,3984,453,0]An[4595,13,4596,1783,3853,453,0]An[4595,13,4596,1466,3032,453,0]An[4595,13,4596,1466,4360,453,0]An[4595,13,4596,1466,4542,453,0]An[4595,13,4596,1466,2319,453,0]An[4595,13,4596,2371,4546,453,0]An[4595,13,4596,2371,2330,453,0]An[4595,13,4596,2371,3995,453,0]An[4595,13,4596,2371,3847,453,0]An[4595,13,4596,2371,3234,453,0]An[4595,13,4596,1846,4152,453,0]An[4595,13,4596,1846,4374,453,0]An[4595,13,4596,1846,4882,453,0]An[4595,13,4596,1846,2332,453,0]An[4595,13,4596,1846,4636,453,0]An[4595,13,4596,1873,4364,453,0]An[4595,13,4596,1873,4129,453,0]An[4595,13,4596,1873,3998,453,0]An[4595,13,4596,1873,4002,453,0]Ak[4595,13,4596,0,4272,453,0]Ak[4595,13,4596,0,4696,453,0]An[4595,13,4596,4170,3216,453,0]An[4595,13,4596,4170,4977,453,0]An[4595,13,4596,4726,4572,453,0]Am[4595,13,4596,4596,467,453,0]Am[4595,13,4596,4596,114,453,0]An[4595,13,4596,4596,2349,453,0]An[4595,13,4596,4596,2358,453,0]An[4595,13,4596,4596,3030,453,0]An[4595,13,1781,1781,4163,453,0]An[4595,13,4838,4838,4737,453,0]An[4595,13,4838,4838,1299,453,0]An[4595,13,1786,1786,1923,453,0]Am[4595,13,1786,1786,455,453,0]An[4595,13,1786,1786,4944,453,0]An[4595,13,1786,1786,3856,453,0]An[4595,13,1786,1786,4702,453,0]An[4595,13,1863,1863,3245,453,0]An[4595,13,1863,1863,4133,453,0]An[4595,13,1863,1863,4568,453,0]An[4595,13,1863,1863,4570,453,0]An[4595,13,1863,1863,4793,453,0]Ak[4595,13,1863,0,1298,453,0]Al[4595,13,3589,129,108,453,0]Am[4595,13,3589,129,3021,453,0]An[4595,13,3589,1461,1285,453,0]An[4595,13,3589,1461,3858,453,0]An[4595,13,3589,2419,1928,453,0]An[4595,13,3589,2419,4150,453,0]An[4595,13,3589,3589,4630,453,0]An[4595,13,2057,2057,1300,453,0]An[4595,13,2057,2057,1303,453,0]An[4307,13,4308,4308,3248,453,0]Am[4307,13,4308,375,4273,453,0]An[4307,13,4308,4308,2346,453,0]An[4307,13,4308,4308,2359,453,0]An[4307,13,4308,4308,4003,453,0]An[1015,13,1016,1016,3023,453,0]An[1015,13,1016,1016,4730,453,0]Am[1015,13,1775,1775,122,453,0]An[1015,13,1491,1491,1317,453,0]An[1015,13,1491,1491,3881,453,0]An[1015,13,1491,1491,4370,453,0]An[1015,13,4088,4088,4929,453,0]An[1015,13,4088,4088,4930,453,0]Am[1015,13,1868,1868,123,453,0]Am[3837,13,3838,3838,112,453,0]An[3837,13,3838,3838,2316,453,0]Ac[476,7,477,0,0,0,0]Ae[3886,7,3887,0,0,0,0]Ae[4173,7,4174,0,0,0,0]Ae[3837,7,3838,0,0,0,0]Ae[4656,7,4657,0,0,0,0]Al[4595,13,4596,1039,1516,0,0]Ai[3817,12,1785,0,1906,0,0]Al[4595,13,4596,2086,1947,0,0]Al[4595,12,1786,1786,1907,0,0]Al[3817,13,3818,3593,3206,0,0]Ab[1015,3,0,0,0,0,0]Ak[3817,13,3818,1014,459,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,13,4596,3594,3207,0,0]Al[4595,14,4596,1492,3213,0,0]Al[3817,12,3818,2078,3195,0,0]Ao[3817,13,3818,3593,4387,1526,0]Ao[3817,13,3818,3593,2339,1526,0]Ao[3817,13,3818,1014,2340,1526,0]Ao[3817,13,3818,3593,3204,1526,0]Ao[3817,13,3818,3593,1930,1526,0]Ao[3817,13,3818,3593,1529,1526,0]Ao[3817,13,3818,3593,3013,1526,0]Ao[3817,13,3818,3593,2313,1526,0]Ao[3817,13,3818,3593,4021,1526,0]Ao[3817,13,3818,3593,4026,1526,0]Ao[3817,13,3818,2370,1508,1526,0]Ao[3817,13,3818,2397,4249,1526,0]>Al[3817,13,3818,3952,3230,0,0]Al[4595,13,4596,2086,3231,0,0]Al[4595,13,4838,4838,4737,0,0]Al[4595,13,4596,3076,3026,0,0]Ak[4307,13,4308,375,4273,0,0]Ai[3817,12,1785,0,1906,0,0]Al[4595,12,1786,1786,1907,0,0]32Ai[3817,13,3818,0,4853,0,0]Al[4595,13,4596,1783,4854,0,0]Al[3817,13,3818,3593,3206,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,12,1785,0,1918,0,0]Al[4595,12,1786,1786,1919,0,0]Al[1320,14,1490,1490,4269,0,0]Ai[3817,14,3818,0,2357,0,0]Al[4595,14,4596,4596,2358,0,0]Ai[4595,14,4373,0,1313,0,0]Al[3817,13,3818,3952,3230,0,0]Al[3817,13,3818,3952,4738,0,0]Al[4595,13,4596,2086,3231,0,0]Ai[3817,12,3818,0,3246,0,0]Al[3817,13,3818,0,4257,3246,0]Al[3817,13,3818,0,4571,3246,0]Al[4595,12,4596,1501,3247,0,0]Ao[4595,13,4596,1501,4258,3247,0]Ao[4595,13,4596,4726,4572,3247,0]Am[1320,13,1321,1321,121,469,0]An[1320,13,1321,1321,3849,469,0]An[1320,13,1490,1490,3880,469,0]An[1320,13,1490,1490,1316,469,0]An[1320,13,1490,1490,4269,469,0]Ak[476,13,477,477,3850,469,0]An[3886,13,3887,3887,4883,469,0]An[3817,13,3818,3593,4387,469,0]An[3817,13,3818,3593,2339,469,0]Ak[3817,13,3818,0,4121,469,0]An[3817,13,3818,1014,2340,469,0]An[3817,13,3818,3593,3204,469,0]An[3817,13,3818,3593,3206,469,0]An[3817,13,3818,3593,1930,469,0]An[3817,13,3818,3593,1529,469,0]An[3817,13,3818,3593,3013,469,0]An[3817,13,3818,3593,2313,469,0]An[3817,13,3818,3593,4021,469,0]An[3817,13,3818,3593,4026,469,0]An[3817,13,3818,3593,4799,469,0]An[3817,13,3818,3593,4637,469,0]An[3817,13,3818,2370,2325,469,0]An[3817,13,3818,2370,4130,469,0]An[3817,13,3818,2370,1508,469,0]An[3817,13,3818,2397,2329,469,0]An[3817,13,3818,2397,3233,469,0]An[3817,13,3818,2397,4249,469,0]Am[3817,13,3818,1014,459,469,0]An[3817,13,3818,3952,3230,469,0]An[3817,13,3818,3952,4738,469,0]An[3817,13,3818,3952,4267,469,0]An[3817,13,3818,3952,3051,469,0]An[3817,13,3818,3952,3232,469,0]An[3817,13,3818,3952,4266,469,0]An[3817,13,3818,1502,4036,469,0]An[3817,13,3818,1056,3875,469,0]An[3817,13,3818,3957,3236,469,0]An[3817,13,3818,3957,3249,469,0]An[3817,13,3818,3957,4035,469,0]Ak[3817,13,3818,0,3227,469,0]Ak[3817,13,3818,0,4161,469,0]Ak[3817,13,3818,0,4379,469,0]Ak[3817,13,3818,0,4013,469,0]Ak[3817,13,3818,0,4257,469,0]Ak[3817,13,3818,0,1552,469,0]Ak[3817,13,3818,0,4796,469,0]Ak[3817,13,3818,0,1280,469,0]Ak[3817,13,3818,0,1536,469,0]Ak[3817,13,3818,0,2360,469,0]Ak[3817,13,3818,0,3212,469,0]Ak[3817,13,3818,0,3048,469,0]Ak[3817,13,3818,0,4365,469,0]Ak[3817,13,3818,0,1952,469,0]Ak[3817,13,3818,0,3988,469,0]Ak[3817,13,3818,0,4361,469,0]Ak[3817,13,3818,0,4375,469,0]Ak[3817,13,3818,0,4382,469,0]Ak[3817,13,3818,0,4661,469,0]Ak[3817,13,3818,0,4676,469,0]Ak[3817,13,3818,0,3862,469,0]Ak[3817,13,3818,0,4244,469,0]Ak[3817,13,3818,0,4029,469,0]Ak[3817,13,3818,0,4853,469,0]Ak[3817,13,3818,0,3982,469,0]Ak[3817,13,3818,0,3852,469,0]Ak[3817,13,3818,0,3031,469,0]Ak[3817,13,3818,0,4358,469,0]Ak[3817,13,3818,0,4540,469,0]Ak[3817,13,3818,0,3994,469,0]Ak[3817,13,3818,0,3997,469,0]Ak[3817,13,3818,0,4001,469,0]Ak[3817,13,3818,0,4695,469,0]Ak[3817,13,3818,0,4571,469,0]Aj[3817,13,3818,0,466,469,0]Aj[3817,13,3818,0,113,469,0]Ak[3817,13,3818,0,2348,469,0]Ak[3817,13,3818,0,2357,469,0]Aj[3817,13,3588,0,107,469,0]Ak[3817,13,3588,0,3020,469,0]Ak[3817,13,3588,0,1284,469,0]Ak[3817,13,3588,0,3857,469,0]Ak[3817,13,3588,0,1927,469,0]Ak[3817,13,3588,0,4149,469,0]Ak[3817,13,3588,0,4629,469,0]Ak[3817,13,1785,0,1922,469,0]Aj[3817,13,1785,0,454,469,0]Ak[3817,13,1785,0,4943,469,0]Ak[3817,13,1785,0,3855,469,0]Ak[3817,13,1785,0,4699,469,0]Ak[3817,13,1862,0,3244,469,0]Ak[3817,13,1862,0,4132,469,0]Ak[3817,13,1862,0,4567,469,0]Ak[3817,13,1862,0,4569,469,0]Ak[3817,13,1862,0,4792,469,0]Ak[3817,13,1862,0,1297,469,0]An[4595,13,4596,4392,4122,469,0]An[4595,13,4596,3076,3026,469,0]An[4595,13,4596,1039,1516,469,0]An[4595,13,4596,2086,1947,469,0]An[4595,13,4596,2086,3231,469,0]An[4595,13,4596,2086,3237,469,0]An[4595,13,4596,3594,3207,469,0]An[4595,13,4596,1035,3228,469,0]An[4595,13,4596,1783,4162,469,0]An[4595,13,4596,2371,2326,469,0]An[4595,13,4596,2371,4128,469,0]An[4595,13,4596,1846,5002,469,0]An[4595,13,4596,4170,4972,469,0]An[4595,13,4596,1501,4380,469,0]An[4595,13,4596,1501,4014,469,0]An[4595,13,4596,1501,4258,469,0]An[4595,13,4596,1895,1553,469,0]An[4595,13,4596,1895,4797,469,0]An[4595,13,4596,3067,1281,469,0]An[4595,13,4596,3076,4638,469,0]An[4595,13,4596,1476,1537,469,0]An[4595,13,4596,1476,4025,469,0]An[4595,13,4596,1476,3226,469,0]An[4595,13,4596,1476,3047,469,0]An[4595,13,4596,1476,4692,469,0]An[4595,13,4596,1476,3202,469,0]An[4595,13,4596,1492,2361,469,0]An[4595,13,4596,1492,3213,469,0]An[4595,13,4596,1492,3049,469,0]An[4595,13,4596,1492,4366,469,0]An[4595,13,4596,1039,3052,469,0]An[4595,13,4596,1039,4157,469,0]An[4595,13,4596,1044,1953,469,0]An[4595,13,4596,1044,3250,469,0]An[4595,13,4596,1044,3861,469,0]An[4595,13,4596,2086,3879,469,0]An[4595,13,4596,2086,4268,469,0]An[4595,13,4596,2086,3992,469,0]An[4595,13,4596,3594,4362,469,0]An[4595,13,4596,3594,3044,469,0]An[4595,13,4596,3594,4235,469,0]An[4595,13,4596,3594,1302,469,0]An[4595,13,4596,1035,4376,469,0]An[4595,13,4596,3189,4383,469,0]An[4595,13,4596,3189,4662,469,0]An[4595,13,4596,3189,4677,469,0]An[4595,13,4596,3189,3863,469,0]An[4595,13,4596,1783,4245,469,0]An[4595,13,4596,1783,4031,469,0]An[4595,13,4596,1783,4854,469,0]An[4595,13,4596,1783,3984,469,0]An[4595,13,4596,1783,3853,469,0]An[4595,13,4596,1466,3032,469,0]An[4595,13,4596,1466,4360,469,0]An[4595,13,4596,1466,4542,469,0]An[4595,13,4596,1466,2319,469,0]An[4595,13,4596,2371,4546,469,0]An[4595,13,4596,2371,2330,469,0]An[4595,13,4596,2371,3995,469,0]An[4595,13,4596,2371,3847,469,0]An[4595,13,4596,2371,3234,469,0]An[4595,13,4596,1846,4152,469,0]An[4595,13,4596,1846,4374,469,0]An[4595,13,4596,1846,4882,469,0]An[4595,13,4596,1846,2332,469,0]An[4595,13,4596,1846,4636,469,0]An[4595,13,4596,1873,4364,469,0]An[4595,13,4596,1873,4129,469,0]An[4595,13,4596,1873,3998,469,0]An[4595,13,4596,1873,4002,469,0]Ak[4595,13,4596,0,4272,469,0]Ak[4595,13,4596,0,4696,469,0]An[4595,13,4596,4170,3216,469,0]An[4595,13,4596,4170,4977,469,0]An[4595,13,4596,4726,4572,469,0]Am[4595,13,4596,4596,467,469,0]Am[4595,13,4596,4596,114,469,0]An[4595,13,4596,4596,2349,469,0]An[4595,13,4596,4596,2358,469,0]An[4595,13,4596,4596,3030,469,0]An[4595,13,1781,1781,4163,469,0]An[4595,13,4838,4838,4737,469,0]An[4595,13,4838,4838,1299,469,0]An[4595,13,1786,1786,1923,469,0]Am[4595,13,1786,1786,455,469,0]An[4595,13,1786,1786,4944,469,0]An[4595,13,1786,1786,3856,469,0]An[4595,13,1786,1786,4702,469,0]An[4595,13,1863,1863,3245,469,0]An[4595,13,1863,1863,4133,469,0]An[4595,13,1863,1863,4568,469,0]An[4595,13,1863,1863,4570,469,0]An[4595,13,1863,1863,4793,469,0]Ak[4595,13,1863,0,1298,469,0]Al[4595,13,3589,129,108,469,0]Am[4595,13,3589,129,3021,469,0]An[4595,13,3589,1461,1285,469,0]An[4595,13,3589,1461,3858,469,0]An[4595,13,3589,2419,1928,469,0]An[4595,13,3589,2419,4150,469,0]An[4595,13,3589,3589,4630,469,0]An[4595,13,2057,2057,1300,469,0]An[4595,13,2057,2057,1303,469,0]An[1015,13,1016,1016,3023,469,0]An[1015,13,1016,1016,4730,469,0]Am[1015,13,1775,1775,122,469,0]An[1015,13,1491,1491,1317,469,0]An[1015,13,1491,1491,3881,469,0]An[1015,13,1491,1491,4370,469,0]An[1015,13,4088,4088,4929,469,0]An[1015,13,4088,4088,4930,469,0]Am[1015,13,1868,1868,123,469,0]Am[3837,13,3838,3838,112,469,0]An[3837,13,3838,3838,2316,469,0]Ah[3817,5,3818,3067,0,0,0]Ah[4595,5,4596,3067,0,0,0]Ah[3817,5,3588,1461,0,0,0]Ah[4595,5,3589,1461,0,0,0]Al[1015,15,1016,1016,4730,0,0]Ah[3817,6,1862,1464,0,0,0]Ah[4595,6,1863,1464,0,0,0]Ae[4595,6,4838,0,0,0,0]Ae[4595,6,2057,0,0,0,0]Ah[4595,6,4596,3594,0,0,0]1Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]Al[3817,15,3818,3952,3051,0,0]Ai[3817,15,3818,0,4361,0,0]Al[4595,15,4596,1039,3052,0,0]Al[4595,15,4596,3594,4362,0,0]Al[4595,15,4596,1846,4374,0,0]0Ae[1320,5,1490,0,0,0,0]Ae[1015,5,1491,0,0,0,0]Ab[1320,3,0,0,0,0,0]Ai[3817,12,3588,0,4627,0,0]Al[3817,13,3588,0,3020,4627,0]Al[3817,13,3588,0,3857,4627,0]Al[3817,13,3588,0,4149,4627,0]Al[4595,12,3589,3589,4628,0,0]An[4595,13,3589,129,3021,4628,0]Ao[4595,13,3589,1461,3858,4628,0]Ao[4595,13,3589,2419,4150,4628,0]Al[1015,13,1016,1016,4730,0,0]Ai[3817,14,3818,0,1280,0,0]Ai[3817,14,3818,0,2360,0,0]Ai[3817,14,3818,0,1952,0,0]Al[4595,14,4596,3067,1281,0,0]Al[4595,14,4596,1492,2361,0,0]Al[4595,14,4596,1044,1953,0,0]Al[4595,14,4596,2371,3847,0,0]An[1320,13,1321,1321,121,1282,0]Ao[1320,13,1321,1321,3849,1282,0]Ao[3817,13,3818,3593,3206,1282,0]Ao[3817,13,3818,3593,4799,1282,0]Ao[3817,13,3818,3593,4637,1282,0]Ao[3817,13,3818,2370,2325,1282,0]Ao[3817,13,3818,2370,4130,1282,0]Ao[3817,13,3818,3952,4267,1282,0]Ao[3817,13,3818,3952,3051,1282,0]Ao[3817,13,3818,3952,3232,1282,0]Ao[3817,13,3818,3952,4266,1282,0]Ao[3817,13,3818,3957,3249,1282,0]Ao[3817,13,3818,3957,4035,1282,0]Al[3817,13,3818,0,1552,1282,0]Al[3817,13,3818,0,4796,1282,0]Al[3817,13,3818,0,1536,1282,0]Al[3817,13,3818,0,2360,1282,0]Al[3817,13,3818,0,3212,1282,0]Al[3817,13,3818,0,3048,1282,0]Al[3817,13,3818,0,4365,1282,0]Al[3817,13,3818,0,1952,1282,0]Al[3817,13,3818,0,3988,1282,0]Al[3817,13,3818,0,4361,1282,0]Al[3817,13,3818,0,4382,1282,0]Al[3817,13,3818,0,4661,1282,0]Al[3817,13,3818,0,4676,1282,0]Al[3817,13,3818,0,3862,1282,0]Al[3817,13,3818,0,4244,1282,0]Al[3817,13,3818,0,4029,1282,0]Al[3817,13,3818,0,4853,1282,0]Al[3817,13,3818,0,3982,1282,0]Al[3817,13,3818,0,3852,1282,0]Al[3817,13,3818,0,3031,1282,0]Al[3817,13,3818,0,4358,1282,0]Al[3817,13,3818,0,4540,1282,0]Al[3817,13,3818,0,3994,1282,0]Al[3817,13,3818,0,3997,1282,0]Al[3817,13,3818,0,4001,1282,0]Al[3817,13,3818,0,4695,1282,0]Ak[3817,13,3818,0,466,1282,0]Ak[3817,13,3818,0,113,1282,0]Al[3817,13,3818,0,2348,1282,0]Ak[3817,13,3588,0,107,1282,0]Al[3817,13,3588,0,3020,1282,0]Al[3817,13,3588,0,1284,1282,0]Al[3817,13,3588,0,3857,1282,0]Al[3817,13,3588,0,1927,1282,0]Al[3817,13,3588,0,4149,1282,0]Al[3817,13,1862,0,4792,1282,0]Al[3817,13,1862,0,1297,1282,0]Ao[4595,13,4596,1895,1553,1282,0]Ao[4595,13,4596,1895,4797,1282,0]Ao[4595,13,4596,3076,4638,1282,0]Ao[4595,13,4596,1476,1537,1282,0]Ao[4595,13,4596,1476,4025,1282,0]Ao[4595,13,4596,1476,3226,1282,0]Ao[4595,13,4596,1476,3047,1282,0]Ao[4595,13,4596,1476,4692,1282,0]Ao[4595,13,4596,1476,3202,1282,0]Ao[4595,13,4596,1492,2361,1282,0]Ao[4595,13,4596,1492,3213,1282,0]Ao[4595,13,4596,1492,3049,1282,0]Ao[4595,13,4596,1492,4366,1282,0]Ao[4595,13,4596,1039,3052,1282,0]Ao[4595,13,4596,1039,4157,1282,0]Ao[4595,13,4596,1044,1953,1282,0]Ao[4595,13,4596,1044,3250,1282,0]Ao[4595,13,4596,1044,3861,1282,0]Ao[4595,13,4596,2086,4268,1282,0]Ao[4595,13,4596,2086,3992,1282,0]Ao[4595,13,4596,3594,4362,1282,0]Ao[4595,13,4596,3594,3044,1282,0]Ao[4595,13,4596,3594,4235,1282,0]Ao[4595,13,4596,3189,4383,1282,0]Ao[4595,13,4596,3189,4662,1282,0]Ao[4595,13,4596,3189,4677,1282,0]Ao[4595,13,4596,3189,3863,1282,0]Ao[4595,13,4596,1783,4245,1282,0]Ao[4595,13,4596,1783,4031,1282,0]Ao[4595,13,4596,1783,4854,1282,0]Ao[4595,13,4596,1783,3984,1282,0]Ao[4595,13,4596,1783,3853,1282,0]Ao[4595,13,4596,1466,3032,1282,0]Ao[4595,13,4596,1466,4360,1282,0]Ao[4595,13,4596,1466,4542,1282,0]Ao[4595,13,4596,1466,2319,1282,0]Ao[4595,13,4596,2371,4546,1282,0]Ao[4595,13,4596,2371,3995,1282,0]Ao[4595,13,4596,1846,4374,1282,0]Ao[4595,13,4596,1846,4882,1282,0]Ao[4595,13,4596,1846,2332,1282,0]Ao[4595,13,4596,1846,4636,1282,0]Ao[4595,13,4596,1873,3998,1282,0]Ao[4595,13,4596,1873,4002,1282,0]Al[4595,13,4596,0,4272,1282,0]Al[4595,13,4596,0,4696,1282,0]Ao[4595,13,4596,4170,3216,1282,0]Ao[4595,13,4596,4170,4977,1282,0]An[4595,13,4596,4596,467,1282,0]An[4595,13,4596,4596,114,1282,0]Ao[4595,13,4596,4596,2349,1282,0]Ao[4595,13,4596,4596,3030,1282,0]Ao[4595,13,1781,1781,4163,1282,0]Ao[4595,13,4838,4838,4737,1282,0]Ao[4595,13,4838,4838,1299,1282,0]Ao[4595,13,1863,1863,4793,1282,0]Al[4595,13,1863,0,1298,1282,0]Am[4595,13,3589,129,108,1282,0]An[4595,13,3589,129,3021,1282,0]Ao[4595,13,3589,1461,1285,1282,0]Ao[4595,13,3589,1461,3858,1282,0]Ao[4595,13,3589,2419,1928,1282,0]Ao[4595,13,3589,2419,4150,1282,0]Ao[4595,13,2057,2057,1303,1282,0]Ao[4307,13,4308,4308,2346,1282,0]Ao[4307,13,4308,4308,2359,1282,0]Ao[4307,13,4308,4308,4003,1282,0]Ao[1015,13,1016,1016,4730,1282,0]Ao[1015,13,1491,1491,4370,1282,0]Al[3817,13,3818,3593,3206,0,0]Al[3817,13,3818,2370,2325,0,0]Ak[3817,13,3818,1014,459,0,0]Al[4595,13,4596,3594,3207,0,0]Al[3817,13,3818,0,3997,1288,0]Ao[4595,13,4596,1873,3998,1288,0]Ai[4595,14,3045,0,4140,0,0]Ai[4595,14,4596,0,4272,0,0]Ai[3817,13,3818,0,2348,0,0]Al[4595,13,4596,4596,2349,0,0]Ai[3817,13,3818,0,4001,0,0]Al[4595,13,4596,1873,4002,0,0]Ai[3817,14,1785,0,1922,0,0]Al[4595,14,1786,1786,1923,0,0]Al[4595,12,4596,1846,4667,0,0]Ao[4595,13,4596,1846,5002,4667,0]=Al[4595,13,4838,4838,4737,0,0]Ah[3817,5,3818,2370,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Al[1320,15,1321,1321,3849,0,0]0Al[4595,15,4596,1476,3226,0,0]Ah[4595,5,4596,1039,0,0,0]Ah[3817,15,3818,0,466,0,0]Ak[4595,15,4596,4596,467,0,0]Al[3837,15,3838,3838,2316,0,0]Al[4595,15,4596,1476,3047,0,0]Al[4595,15,2057,2057,1300,0,0]98Ah[3817,5,3818,3593,0,0,0]2Al[4595,15,4596,2086,3879,0,0]Ah[3817,5,3818,1476,0,0,0]Ah[4595,5,4596,1476,0,0,0]Ae[4595,8,1781,0,0,0,0]987>Al[4595,15,4596,3594,1302,0,0]>Ah[3817,5,3818,1895,0,0,0]Ah[4595,5,4596,1895,0,0,0]Al[3817,13,3818,2370,2325,0,0]Al[3817,13,3818,2397,2329,0,0]Al[4595,13,4596,2086,1947,0,0]Al[4595,13,4596,2371,2326,0,0]An[1320,13,1321,1321,121,1514,0]Ao[1320,13,1321,1321,3849,1514,0]Ao[1320,13,1490,1490,3880,1514,0]Ao[1320,13,1490,1490,1316,1514,0]Ao[1320,13,1490,1490,4269,1514,0]Al[476,13,477,477,3850,1514,0]Ao[3886,13,3887,3887,4883,1514,0]Ao[3817,13,3818,3593,4387,1514,0]Ao[3817,13,3818,3593,2339,1514,0]Al[3817,13,3818,0,4121,1514,0]Ao[3817,13,3818,1014,2340,1514,0]Ao[3817,13,3818,3593,3204,1514,0]Ao[3817,13,3818,3593,3206,1514,0]Ao[3817,13,3818,3593,1930,1514,0]Ao[3817,13,3818,3593,1529,1514,0]Ao[3817,13,3818,3593,3013,1514,0]Ao[3817,13,3818,3593,2313,1514,0]Ao[3817,13,3818,3593,4021,1514,0]Ao[3817,13,3818,3593,4026,1514,0]Ao[3817,13,3818,3593,4799,1514,0]Ao[3817,13,3818,3593,4637,1514,0]Ao[3817,13,3818,2370,2325,1514,0]Ao[3817,13,3818,2370,4130,1514,0]Ao[3817,13,3818,2370,1508,1514,0]Ao[3817,13,3818,2397,2329,1514,0]Ao[3817,13,3818,2397,3233,1514,0]Ao[3817,13,3818,2397,4249,1514,0]An[3817,13,3818,1014,459,1514,0]Ao[3817,13,3818,3952,3230,1514,0]Ao[3817,13,3818,3952,4738,1514,0]Ao[3817,13,3818,3952,4267,1514,0]Ao[3817,13,3818,3952,3051,1514,0]Ao[3817,13,3818,3952,3232,1514,0]Ao[3817,13,3818,3952,4266,1514,0]Ao[3817,13,3818,1502,4036,1514,0]Ao[3817,13,3818,1056,3875,1514,0]Ao[3817,13,3818,3957,3236,1514,0]Ao[3817,13,3818,3957,3249,1514,0]Ao[3817,13,3818,3957,4035,1514,0]Al[3817,13,3818,0,3227,1514,0]Al[3817,13,3818,0,4161,1514,0]Al[3817,13,3818,0,4379,1514,0]Al[3817,13,3818,0,4013,1514,0]Al[3817,13,3818,0,4257,1514,0]Al[3817,13,3818,0,1552,1514,0]Al[3817,13,3818,0,4796,1514,0]Al[3817,13,3818,0,1280,1514,0]Al[3817,13,3818,0,1536,1514,0]Al[3817,13,3818,0,2360,1514,0]Al[3817,13,3818,0,3212,1514,0]Al[3817,13,3818,0,3048,1514,0]Al[3817,13,3818,0,4365,1514,0]Al[3817,13,3818,0,1952,1514,0]Al[3817,13,3818,0,3988,1514,0]Al[3817,13,3818,0,4361,1514,0]Al[3817,13,3818,0,4375,1514,0]Al[3817,13,3818,0,4382,1514,0]Al[3817,13,3818,0,4661,1514,0]Al[3817,13,3818,0,4676,1514,0]Al[3817,13,3818,0,3862,1514,0]Al[3817,13,3818,0,4244,1514,0]Al[3817,13,3818,0,4029,1514,0]Al[3817,13,3818,0,4853,1514,0]Al[3817,13,3818,0,3982,1514,0]Al[3817,13,3818,0,3852,1514,0]Al[3817,13,3818,0,3031,1514,0]Al[3817,13,3818,0,4358,1514,0]Al[3817,13,3818,0,4540,1514,0]Al[3817,13,3818,0,3994,1514,0]Al[3817,13,3818,0,3997,1514,0]Al[3817,13,3818,0,4001,1514,0]Al[3817,13,3818,0,4695,1514,0]Al[3817,13,3818,0,4571,1514,0]Ak[3817,13,3818,0,466,1514,0]Ak[3817,13,3818,0,113,1514,0]Al[3817,13,3818,0,2348,1514,0]Al[3817,13,3818,0,2357,1514,0]Ak[3817,13,3588,0,107,1514,0]Al[3817,13,3588,0,3020,1514,0]Al[3817,13,3588,0,1284,1514,0]Al[3817,13,3588,0,3857,1514,0]Al[3817,13,3588,0,1927,1514,0]Al[3817,13,3588,0,4149,1514,0]Al[3817,13,3588,0,4629,1514,0]Al[3817,13,1785,0,1922,1514,0]Ak[3817,13,1785,0,454,1514,0]Al[3817,13,1785,0,4943,1514,0]Al[3817,13,1785,0,3855,1514,0]Al[3817,13,1785,0,4699,1514,0]Al[3817,13,1862,0,3244,1514,0]Al[3817,13,1862,0,4132,1514,0]Al[3817,13,1862,0,4567,1514,0]Al[3817,13,1862,0,4569,1514,0]Al[3817,13,1862,0,4792,1514,0]Al[3817,13,1862,0,1297,1514,0]Ao[4595,13,4596,4392,4122,1514,0]Ao[4595,13,4596,3076,3026,1514,0]Ao[4595,13,4596,1039,1516,1514,0]Ao[4595,13,4596,2086,1947,1514,0]Ao[4595,13,4596,2086,3231,1514,0]Ao[4595,13,4596,2086,3237,1514,0]Ao[4595,13,4596,3594,3207,1514,0]Ao[4595,13,4596,1035,3228,1514,0]Ao[4595,13,4596,1783,4162,1514,0]Ao[4595,13,4596,2371,2326,1514,0]Ao[4595,13,4596,2371,4128,1514,0]Ao[4595,13,4596,1846,5002,1514,0]Ao[4595,13,4596,4170,4972,1514,0]Ao[4595,13,4596,1501,4380,1514,0]Ao[4595,13,4596,1501,4014,1514,0]Ao[4595,13,4596,1501,4258,1514,0]Ao[4595,13,4596,1895,1553,1514,0]Ao[4595,13,4596,1895,4797,1514,0]Ao[4595,13,4596,3067,1281,1514,0]Ao[4595,13,4596,3076,4638,1514,0]Ao[4595,13,4596,1476,1537,1514,0]Ao[4595,13,4596,1476,4025,1514,0]Ao[4595,13,4596,1476,3226,1514,0]Ao[4595,13,4596,1476,3047,1514,0]Ao[4595,13,4596,1476,4692,1514,0]Ao[4595,13,4596,1476,3202,1514,0]Ao[4595,13,4596,1492,2361,1514,0]Ao[4595,13,4596,1492,3213,1514,0]Ao[4595,13,4596,1492,3049,1514,0]Ao[4595,13,4596,1492,4366,1514,0]Ao[4595,13,4596,1039,3052,1514,0]Ao[4595,13,4596,1039,4157,1514,0]Ao[4595,13,4596,1044,1953,1514,0]Ao[4595,13,4596,1044,3250,1514,0]Ao[4595,13,4596,1044,3861,1514,0]Ao[4595,13,4596,2086,3879,1514,0]Ao[4595,13,4596,2086,4268,1514,0]Ao[4595,13,4596,2086,3992,1514,0]Ao[4595,13,4596,3594,4362,1514,0]Ao[4595,13,4596,3594,3044,1514,0]Ao[4595,13,4596,3594,4235,1514,0]Ao[4595,13,4596,3594,1302,1514,0]Ao[4595,13,4596,1035,4376,1514,0]Ao[4595,13,4596,3189,4383,1514,0]Ao[4595,13,4596,3189,4662,1514,0]Ao[4595,13,4596,3189,4677,1514,0]Ao[4595,13,4596,3189,3863,1514,0]Ao[4595,13,4596,1783,4245,1514,0]Ao[4595,13,4596,1783,4031,1514,0]Ao[4595,13,4596,1783,4854,1514,0]Ao[4595,13,4596,1783,3984,1514,0]Ao[4595,13,4596,1783,3853,1514,0]Ao[4595,13,4596,1466,3032,1514,0]Ao[4595,13,4596,1466,4360,1514,0]Ao[4595,13,4596,1466,4542,1514,0]Ao[4595,13,4596,1466,2319,1514,0]Ao[4595,13,4596,2371,4546,1514,0]Ao[4595,13,4596,2371,2330,1514,0]Ao[4595,13,4596,2371,3995,1514,0]Ao[4595,13,4596,2371,3847,1514,0]Ao[4595,13,4596,2371,3234,1514,0]Ao[4595,13,4596,1846,4152,1514,0]Ao[4595,13,4596,1846,4374,1514,0]Ao[4595,13,4596,1846,4882,1514,0]Ao[4595,13,4596,1846,2332,1514,0]Ao[4595,13,4596,1846,4636,1514,0]Ao[4595,13,4596,1873,4364,1514,0]Ao[4595,13,4596,1873,4129,1514,0]Ao[4595,13,4596,1873,3998,1514,0]Ao[4595,13,4596,1873,4002,1514,0]Al[4595,13,4596,0,4272,1514,0]Al[4595,13,4596,0,4696,1514,0]Ao[4595,13,4596,4170,3216,1514,0]Ao[4595,13,4596,4170,4977,1514,0]Ao[4595,13,4596,4726,4572,1514,0]An[4595,13,4596,4596,467,1514,0]An[4595,13,4596,4596,114,1514,0]Ao[4595,13,4596,4596,2349,1514,0]Ao[4595,13,4596,4596,2358,1514,0]Ao[4595,13,4596,4596,3030,1514,0]Ao[4595,13,1781,1781,4163,1514,0]Ao[4595,13,4838,4838,4737,1514,0]Ao[4595,13,4838,4838,1299,1514,0]Ao[4595,13,1786,1786,1923,1514,0]An[4595,13,1786,1786,455,1514,0]Ao[4595,13,1786,1786,4944,1514,0]Ao[4595,13,1786,1786,3856,1514,0]Ao[4595,13,1786,1786,4702,1514,0]Ao[4595,13,1863,1863,3245,1514,0]Ao[4595,13,1863,1863,4133,1514,0]Ao[4595,13,1863,1863,4568,1514,0]Ao[4595,13,1863,1863,4570,1514,0]Ao[4595,13,1863,1863,4793,1514,0]Al[4595,13,1863,0,1298,1514,0]Am[4595,13,3589,129,108,1514,0]An[4595,13,3589,129,3021,1514,0]Ao[4595,13,3589,1461,1285,1514,0]Ao[4595,13,3589,1461,3858,1514,0]Ao[4595,13,3589,2419,1928,1514,0]Ao[4595,13,3589,2419,4150,1514,0]Ao[4595,13,3589,3589,4630,1514,0]Ao[4595,13,2057,2057,1300,1514,0]Ao[4595,13,2057,2057,1303,1514,0]Ao[4307,13,4308,4308,3248,1514,0]An[4307,13,4308,375,4273,1514,0]Ao[4307,13,4308,4308,2346,1514,0]Ao[4307,13,4308,4308,2359,1514,0]Ao[4307,13,4308,4308,4003,1514,0]Ao[1015,13,1016,1016,3023,1514,0]Ao[1015,13,1016,1016,4730,1514,0]An[1015,13,1775,1775,122,1514,0]Ao[1015,13,1491,1491,1317,1514,0]Ao[1015,13,1491,1491,3881,1514,0]Ao[1015,13,1491,1491,4370,1514,0]Ao[1015,13,4088,4088,4929,1514,0]Ao[1015,13,4088,4088,4930,1514,0]An[1015,13,1868,1868,123,1514,0]An[3837,13,3838,3838,112,1514,0]Ao[3837,13,3838,3838,2316,1514,0]Ai[3817,14,3818,0,1952,0,0]Al[4595,14,4596,1044,1953,0,0]Ak[1320,14,1321,1321,121,0,0]Ac[476,7,477,0,0,0,0]Al[3817,13,3818,2370,2325,0,0]Ae[1015,2,1016,0,0,0,0]Ae[4656,7,4657,0,0,0,0]Al[3817,13,3818,3593,3206,0,0]Ae[4595,2,4596,0,0,0,0]Al[4595,13,4596,2371,2326,0,0]Ah[3817,2,3818,4596,0,0,0]Ai[3817,13,3818,0,4695,0,0]Ai[3817,14,3818,0,3212,0,0]Ai[3817,14,3818,0,4029,0,0]5Ai[4595,13,4596,0,4696,0,0]Al[4595,14,4596,1492,3213,0,0]Al[4595,14,4596,1783,4031,0,0]Ai[4595,14,4596,0,4272,0,0]Al[3817,13,3818,0,1552,3027,0]Al[3817,13,3818,0,1536,3027,0]Al[3817,13,3818,0,3031,3027,0]Al[3817,13,3818,0,4695,3027,0]Al[3817,13,3818,0,2348,3027,0]Ao[4595,13,4596,1895,1553,3027,0]Ao[4595,13,4596,1476,1537,3027,0]Ao[4595,13,4596,1466,3032,3027,0]Al[4595,13,4596,1846,4374,0,0]Al[4595,13,4596,0,4696,3027,0]Ao[4595,13,4596,4596,2349,3027,0]Al[4595,12,1781,1781,3027,0,0]Al[4307,14,4308,4308,2346,0,0]Al[3817,13,3818,0,1552,3028,0]Al[3817,13,3818,0,1536,3028,0]Al[3817,13,3818,0,3031,3028,0]Al[3817,13,3818,0,4695,3028,0]Al[3817,13,3818,0,2348,3028,0]Ao[4595,13,4596,1895,1553,3028,0]Ao[4595,13,4596,1476,1537,3028,0]Ao[4595,13,4596,1466,3032,3028,0]Ao[4595,13,4596,1466,2319,3028,0]Al[4595,13,4596,0,4696,3028,0]Ao[4595,13,4596,4596,2349,3028,0]Al[4595,12,1781,1781,3028,0,0]Al[3817,13,3818,3957,3236,0,0]Al[4595,13,4596,2086,3237,0,0]Al[1015,13,1491,1491,3881,0,0]Al[4595,13,4596,2371,2326,0,0]Ah[3817,14,1785,0,454,0,0]Ak[4595,14,1786,1786,455,0,0]Al[3817,13,3818,2397,2329,0,0]3Ai[3817,12,3818,0,3246,0,0]Al[3817,13,3818,0,4257,3246,0]Al[3817,13,3818,0,4571,3246,0]Al[4595,12,4596,1501,3247,0,0]Ao[4595,13,4596,1501,4258,3247,0]Ao[4595,13,4596,4726,4572,3247,0]Al[1015,14,1016,1016,3023,0,0]Ai[3817,14,3818,0,1280,0,0]Al[4595,14,4596,3067,1281,0,0]Ai[3817,13,3588,0,3208,0,0]Ak[3817,13,3588,0,107,3208,0]Al[3817,13,3588,0,1284,3208,0]Al[3817,13,3588,0,1927,3208,0]Al[4595,13,3589,3589,3209,0,0]Am[4595,13,3589,129,108,3209,0]Ao[4595,13,3589,1461,1285,3209,0]Ao[4595,13,3589,2419,1928,3209,0]Ah[3817,14,1785,0,454,0,0]Ak[4595,14,1786,1786,455,0,0]Ai[4595,14,4373,0,4575,0,0]Ai[3817,14,3818,0,4358,0,0]Ai[3817,14,3818,0,4540,0,0]Al[4595,14,4596,1466,4360,0,0]Al[4595,14,4596,1466,4542,0,0]Ai[4595,14,4596,0,4272,0,0]Ai[4595,14,1301,0,4237,0,0]Al[3817,13,3818,2370,2325,0,0]Al[3817,13,3818,2397,2329,0,0]Al[4595,13,4596,2371,2326,0,0]Ai[3817,14,1785,0,1922,0,0]Al[4595,14,4596,4596,3030,0,0]Al[4595,14,1786,1786,1923,0,0]Ae[3817,4,3818,0,0,0,0]Ah[3817,2,1785,1786,0,0,0]Ae[4595,4,4596,0,0,0,0]Ae[4595,2,1786,0,0,0,0]Ac[476,7,477,0,0,0,0]:Ae[1015,2,1016,0,0,0,0]Ae[4656,7,4657,0,0,0,0]Ao[3817,13,3818,3593,4637,1290,0]Ao[3817,13,3818,3952,4267,1290,0]Ao[3817,13,3818,3952,3051,1290,0]Ao[3817,13,3818,3952,3232,1290,0]Ao[3817,13,3818,3952,4266,1290,0]Ao[3817,13,3818,3957,3249,1290,0]Ao[3817,13,3818,3957,4035,1290,0]Al[3817,13,3818,0,4361,1290,0]Ao[4595,13,4596,3594,4362,1290,0]Ai[3817,14,3818,0,2357,0,0]Al[4595,14,4596,4596,2358,0,0]Al[4307,14,4308,4308,2359,0,0]Ak[3817,13,3818,1014,459,0,0]Ai[4595,14,3045,0,4022,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Al[4307,14,4308,4308,2346,0,0]Ai[3817,14,3818,0,4365,0,0]Al[4595,14,4596,1492,4366,0,0]10Ai[3817,12,1785,0,1918,0,0]Al[4595,12,1786,1786,1919,0,0]Ai[3817,12,3588,0,3208,0,0]Ak[3817,13,3588,0,107,3208,0]Al[3817,13,3588,0,1284,3208,0]Al[3817,13,3588,0,1927,3208,0]Al[4595,12,3589,3589,3209,0,0]Am[4595,13,3589,129,108,3209,0]Ao[4595,13,3589,1461,1285,3209,0]Ao[4595,13,3589,2419,1928,3209,0]Ai[3817,10,1785,1786,0,0,0]Af[4595,10,1786,0,0,0,0]Al[4595,15,4596,3076,4638,0,0]Al[4595,15,4596,1039,3052,0,0]Al[4595,15,4596,1044,3250,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]65Al[4595,15,4596,1846,4374,0,0]Ah[3817,5,1785,1786,0,0,0]Ae[4595,5,1786,0,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Ah[3817,5,3588,2419,0,0,0]Ah[4595,5,3589,2419,0,0,0]Al[1015,15,1016,1016,4730,0,0]Ah[3817,5,3818,3593,0,0,0]5454Ai[3817,10,3818,2078,0,0,0]Ai[3817,10,1785,1786,0,0,0]Af[4595,10,1786,0,0,0,0]Al[3817,15,3818,3957,3249,0,0]?Al[4595,15,4596,1044,3861,0,0]Al[4595,15,4596,2086,3879,0,0]Ah[4595,5,4596,2086,0,0,0]Al[3817,15,3818,3952,4267,0,0]Ah[3817,5,3818,1044,0,0,0]Ah[4595,5,4596,1044,0,0,0]Al[4595,15,4596,1846,2332,0,0]Ai[3817,12,3818,0,4844,0,0]Al[4595,12,4596,4170,4845,0,0]Ao[4595,13,4596,4170,4972,4845,0]Ao[4595,13,4596,4170,4977,4845,0]Ak[1320,14,1321,1321,121,0,0]An[1320,13,1321,1321,121,4236,0]Ao[1015,13,1016,1016,3023,4236,0]An[1015,13,1775,1775,122,4236,0]An[1015,13,1868,1868,123,4236,0]An[3837,13,3838,3838,112,4236,0]Ak[3837,14,3838,3838,112,0,0]Al[3817,13,3818,0,1552,3203,0]Al[3817,13,3818,0,1536,3203,0]Al[3817,13,3818,0,3862,3203,0]Al[3817,13,3818,0,3997,3203,0]Ak[3817,13,3818,0,466,3203,0]Ak[3817,13,3818,0,113,3203,0]Al[3817,13,3818,0,2348,3203,0]Ao[4595,13,4596,1895,1553,3203,0]Ao[4595,13,4596,3076,4638,3203,0]Ao[4595,13,4596,1476,1537,3203,0]Ao[4595,13,4596,1039,3052,3203,0]Ao[4595,13,4596,1039,4157,3203,0]Ao[4595,13,4596,1044,3250,3203,0]Ao[4595,13,4596,3189,3863,3203,0]Ao[4595,13,4596,2371,4546,3203,0]Ao[4595,13,4596,1846,4636,3203,0]Ao[4595,13,4596,1873,3998,3203,0]An[4595,13,4596,4596,467,3203,0]An[4595,13,4596,4596,114,3203,0]Ao[4595,13,4596,4596,2349,3203,0]Al[3817,13,3818,2370,2325,0,0]Al[4595,13,4596,2371,2326,0,0]Ai[3817,12,1785,0,3041,0,0]Ai[3817,12,1785,0,3034,0,0]Al[4595,12,1786,1786,3042,0,0]Al[4595,12,1786,1786,3035,0,0]Ao[1320,13,1490,1490,3880,1913,0]Ao[1320,13,1490,1490,1316,1913,0]Al[476,13,477,477,3850,1913,0]Al[3817,13,3818,0,4121,1913,0]Ao[3817,13,3818,2370,4130,1913,0]Al[3817,13,3818,0,1552,1913,0]Al[3817,13,3818,0,1536,1913,0]Al[3817,13,3818,0,2360,1913,0]Al[3817,13,3818,0,3212,1913,0]Al[3817,13,3818,0,3048,1913,0]Al[3817,13,3818,0,4365,1913,0]Al[3817,13,3818,0,1952,1913,0]Al[3817,13,3818,0,3988,1913,0]Al[3817,13,3818,0,4382,1913,0]Al[3817,13,3818,0,4661,1913,0]Al[3817,13,3818,0,4676,1913,0]Al[3817,13,3818,0,3862,1913,0]Al[3817,13,3818,0,4244,1913,0]Al[3817,13,3818,0,4853,1913,0]Al[3817,13,3818,0,4571,1913,0]Al[3817,13,3588,0,3020,1913,0]Al[3817,13,3588,0,3857,1913,0]Al[3817,13,3588,0,4149,1913,0]Al[3817,13,3588,0,4629,1913,0]Ao[4595,13,4596,4392,4122,1913,0]Ao[4595,13,4596,4170,4972,1913,0]Ao[4595,13,4596,1895,1553,1913,0]Ao[4595,13,4596,1476,1537,1913,0]Ao[4595,13,4596,1476,3226,1913,0]Ao[4595,13,4596,1476,3202,1913,0]Ao[4595,13,4596,1492,2361,1913,0]Ao[4595,13,4596,1492,3213,1913,0]Ao[4595,13,4596,1492,3049,1913,0]Ao[4595,13,4596,1492,4366,1913,0]Ao[4595,13,4596,1044,1953,1913,0]Ao[4595,13,4596,2086,4268,1913,0]Ao[4595,13,4596,2086,3992,1913,0]Ao[4595,13,4596,3189,4383,1913,0]Ao[4595,13,4596,3189,4662,1913,0]Ao[4595,13,4596,3189,4677,1913,0]Ao[4595,13,4596,3189,3863,1913,0]Ao[4595,13,4596,1783,4245,1913,0]Ao[4595,13,4596,1783,4854,1913,0]Ao[4595,13,4596,4170,4977,1913,0]Ao[4595,13,4596,4726,4572,1913,0]An[4595,13,3589,129,3021,1913,0]Ao[4595,13,3589,1461,3858,1913,0]Ao[4595,13,3589,2419,4150,1913,0]Ao[4595,13,3589,3589,4630,1913,0]Ao[4307,13,4308,4308,2346,1913,0]Ao[1015,13,1491,1491,1317,1913,0]Ao[1015,13,1491,1491,4370,1913,0]Al[4595,13,4596,1873,4129,0,0]Al[4595,13,4596,1846,4152,0,0]Al[4595,13,4596,1846,4374,0,0]Al[4595,14,4596,1846,4882,0,0]Ai[4595,14,4635,0,4697,0,0]Ah[4595,14,4373,0,456,0,0]Ai[4595,14,4373,0,1311,0,0]Ai[4595,14,4373,0,1313,0,0]Ai[4595,14,4373,0,4575,0,0]Ai[3817,12,1785,0,3041,0,0]Ai[3817,12,1785,0,3034,0,0]Al[4595,12,1786,1786,3042,0,0]Al[4595,12,1786,1786,3035,0,0]Ae[4595,2,4596,0,0,0,0]Al[3817,13,3818,3952,3230,0,0]Al[3817,13,3818,3952,4738,0,0]Ai[3817,13,3588,0,3208,0,0]Ak[3817,13,3588,0,107,3208,0]Al[3817,13,3588,0,1284,3208,0]Al[3817,13,3588,0,1927,3208,0]Al[4595,13,3589,3589,3209,0,0]Am[4595,13,3589,129,108,3209,0]Ao[4595,13,3589,1461,1285,3209,0]Ao[4595,13,3589,2419,1928,3209,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]9854Al[3817,13,3818,3593,3206,0,0]Al[3817,13,3818,1014,2340,0,0]Al[4595,14,4596,1846,4882,0,0]Ai[4595,14,4635,0,4697,0,0]Ah[4595,14,4373,0,456,0,0]Ai[4595,14,4373,0,1311,0,0]Ai[4595,14,4373,0,4575,0,0]Al[3817,13,3818,3957,3236,0,0]Al[4595,13,4596,2086,3237,0,0]Ak[1320,14,1321,1321,121,0,0]Al[1320,14,1490,1490,1316,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,12,1785,0,3041,0,0]Al[4595,12,1786,1786,3042,0,0]Am[1320,13,1321,1321,121,105,0]An[1320,13,1321,1321,3849,105,0]An[1320,13,1490,1490,3880,105,0]An[1320,13,1490,1490,1316,105,0]An[1320,13,1490,1490,4269,105,0]Ak[476,13,477,477,3850,105,0]An[3886,13,3887,3887,4883,105,0]An[3817,13,3818,3593,4387,105,0]An[3817,13,3818,3593,2339,105,0]Ak[3817,13,3818,0,4121,105,0]An[3817,13,3818,1014,2340,105,0]An[3817,13,3818,3593,3204,105,0]An[3817,13,3818,3593,3206,105,0]An[3817,13,3818,3593,1930,105,0]An[3817,13,3818,3593,1529,105,0]An[3817,13,3818,3593,3013,105,0]An[3817,13,3818,3593,2313,105,0]An[3817,13,3818,3593,4021,105,0]An[3817,13,3818,3593,4026,105,0]An[3817,13,3818,3593,4799,105,0]An[3817,13,3818,3593,4637,105,0]An[3817,13,3818,2370,2325,105,0]An[3817,13,3818,2370,4130,105,0]An[3817,13,3818,2370,1508,105,0]An[3817,13,3818,2397,2329,105,0]An[3817,13,3818,2397,3233,105,0]An[3817,13,3818,2397,4249,105,0]Am[3817,13,3818,1014,459,105,0]An[3817,13,3818,3952,3230,105,0]An[3817,13,3818,3952,4738,105,0]An[3817,13,3818,3952,4267,105,0]An[3817,13,3818,3952,3051,105,0]An[3817,13,3818,3952,3232,105,0]An[3817,13,3818,3952,4266,105,0]An[3817,13,3818,1502,4036,105,0]An[3817,13,3818,1056,3875,105,0]An[3817,13,3818,3957,3236,105,0]An[3817,13,3818,3957,3249,105,0]An[3817,13,3818,3957,4035,105,0]Ak[3817,13,3818,0,3227,105,0]Ak[3817,13,3818,0,4161,105,0]Ak[3817,13,3818,0,4379,105,0]Ak[3817,13,3818,0,4013,105,0]Ak[3817,13,3818,0,4257,105,0]Ak[3817,13,3818,0,1552,105,0]Ak[3817,13,3818,0,4796,105,0]Ak[3817,13,3818,0,1280,105,0]Ak[3817,13,3818,0,1536,105,0]Ak[3817,13,3818,0,2360,105,0]Ak[3817,13,3818,0,3212,105,0]Ak[3817,13,3818,0,3048,105,0]Ak[3817,13,3818,0,4365,105,0]Ak[3817,13,3818,0,1952,105,0]Ak[3817,13,3818,0,3988,105,0]Ak[3817,13,3818,0,4361,105,0]Ak[3817,13,3818,0,4375,105,0]Ak[3817,13,3818,0,4382,105,0]Ak[3817,13,3818,0,4661,105,0]Ak[3817,13,3818,0,4676,105,0]Ak[3817,13,3818,0,3862,105,0]Ak[3817,13,3818,0,4244,105,0]Ak[3817,13,3818,0,4029,105,0]Ak[3817,13,3818,0,4853,105,0]Ak[3817,13,3818,0,3982,105,0]Ak[3817,13,3818,0,3852,105,0]Ak[3817,13,3818,0,3031,105,0]Ak[3817,13,3818,0,4358,105,0]Ak[3817,13,3818,0,4540,105,0]Ak[3817,13,3818,0,3994,105,0]Ak[3817,13,3818,0,3997,105,0]Ak[3817,13,3818,0,4001,105,0]Ak[3817,13,3818,0,4695,105,0]Ak[3817,13,3818,0,4571,105,0]Aj[3817,13,3818,0,466,105,0]Aj[3817,13,3818,0,113,105,0]Ak[3817,13,3818,0,2348,105,0]Ak[3817,13,3818,0,2357,105,0]Aj[3817,13,3588,0,107,105,0]Ak[3817,13,3588,0,3020,105,0]Ak[3817,13,3588,0,1284,105,0]Ak[3817,13,3588,0,3857,105,0]Ak[3817,13,3588,0,1927,105,0]Ak[3817,13,3588,0,4149,105,0]Ak[3817,13,3588,0,4629,105,0]Ak[3817,13,1785,0,1922,105,0]Aj[3817,13,1785,0,454,105,0]Ak[3817,13,1785,0,4943,105,0]Ak[3817,13,1785,0,3855,105,0]Ak[3817,13,1785,0,4699,105,0]Ak[3817,13,1862,0,3244,105,0]Ak[3817,13,1862,0,4132,105,0]Ak[3817,13,1862,0,4567,105,0]Ak[3817,13,1862,0,4569,105,0]Ak[3817,13,1862,0,4792,105,0]Ak[3817,13,1862,0,1297,105,0]An[4595,13,4596,4392,4122,105,0]An[4595,13,4596,3076,3026,105,0]An[4595,13,4596,1039,1516,105,0]An[4595,13,4596,2086,1947,105,0]An[4595,13,4596,2086,3231,105,0]An[4595,13,4596,2086,3237,105,0]An[4595,13,4596,3594,3207,105,0]An[4595,13,4596,1035,3228,105,0]An[4595,13,4596,1783,4162,105,0]An[4595,13,4596,2371,2326,105,0]An[4595,13,4596,2371,4128,105,0]An[4595,13,4596,1846,5002,105,0]An[4595,13,4596,4170,4972,105,0]An[4595,13,4596,1501,4380,105,0]An[4595,13,4596,1501,4014,105,0]An[4595,13,4596,1501,4258,105,0]An[4595,13,4596,1895,1553,105,0]An[4595,13,4596,1895,4797,105,0]An[4595,13,4596,3067,1281,105,0]An[4595,13,4596,3076,4638,105,0]An[4595,13,4596,1476,1537,105,0]An[4595,13,4596,1476,4025,105,0]An[4595,13,4596,1476,3226,105,0]An[4595,13,4596,1476,3047,105,0]An[4595,13,4596,1476,4692,105,0]An[4595,13,4596,1476,3202,105,0]An[4595,13,4596,1492,2361,105,0]An[4595,13,4596,1492,3213,105,0]An[4595,13,4596,1492,3049,105,0]An[4595,13,4596,1492,4366,105,0]An[4595,13,4596,1039,3052,105,0]An[4595,13,4596,1039,4157,105,0]An[4595,13,4596,1044,1953,105,0]An[4595,13,4596,1044,3250,105,0]An[4595,13,4596,1044,3861,105,0]An[4595,13,4596,2086,3879,105,0]An[4595,13,4596,2086,4268,105,0]An[4595,13,4596,2086,3992,105,0]An[4595,13,4596,3594,4362,105,0]An[4595,13,4596,3594,3044,105,0]An[4595,13,4596,3594,4235,105,0]An[4595,13,4596,3594,1302,105,0]An[4595,13,4596,1035,4376,105,0]An[4595,13,4596,3189,4383,105,0]An[4595,13,4596,3189,4662,105,0]An[4595,13,4596,3189,4677,105,0]An[4595,13,4596,3189,3863,105,0]An[4595,13,4596,1783,4245,105,0]An[4595,13,4596,1783,4031,105,0]An[4595,13,4596,1783,4854,105,0]An[4595,13,4596,1783,3984,105,0]An[4595,13,4596,1783,3853,105,0]An[4595,13,4596,1466,3032,105,0]An[4595,13,4596,1466,4360,105,0]An[4595,13,4596,1466,4542,105,0]An[4595,13,4596,1466,2319,105,0]An[4595,13,4596,2371,4546,105,0]An[4595,13,4596,2371,2330,105,0]An[4595,13,4596,2371,3995,105,0]An[4595,13,4596,2371,3847,105,0]An[4595,13,4596,2371,3234,105,0]An[4595,13,4596,1846,4152,105,0]An[4595,13,4596,1846,4374,105,0]An[4595,13,4596,1846,4882,105,0]An[4595,13,4596,1846,2332,105,0]An[4595,13,4596,1846,4636,105,0]An[4595,13,4596,1873,4364,105,0]An[4595,13,4596,1873,4129,105,0]An[4595,13,4596,1873,3998,105,0]An[4595,13,4596,1873,4002,105,0]Ak[4595,13,4596,0,4272,105,0]Ak[4595,13,4596,0,4696,105,0]An[4595,13,4596,4170,3216,105,0]An[4595,13,4596,4170,4977,105,0]An[4595,13,4596,4726,4572,105,0]Am[4595,13,4596,4596,467,105,0]Am[4595,13,4596,4596,114,105,0]An[4595,13,4596,4596,2349,105,0]An[4595,13,4596,4596,2358,105,0]An[4595,13,4596,4596,3030,105,0]An[4595,13,1781,1781,4163,105,0]An[4595,13,4838,4838,4737,105,0]An[4595,13,4838,4838,1299,105,0]An[4595,13,1786,1786,1923,105,0]Am[4595,13,1786,1786,455,105,0]An[4595,13,1786,1786,4944,105,0]An[4595,13,1786,1786,3856,105,0]An[4595,13,1786,1786,4702,105,0]An[4595,13,1863,1863,3245,105,0]An[4595,13,1863,1863,4133,105,0]An[4595,13,1863,1863,4568,105,0]An[4595,13,1863,1863,4570,105,0]An[4595,13,1863,1863,4793,105,0]Ak[4595,13,1863,0,1298,105,0]Al[4595,13,3589,129,108,105,0]Am[4595,13,3589,129,3021,105,0]An[4595,13,3589,1461,1285,105,0]An[4595,13,3589,1461,3858,105,0]An[4595,13,3589,2419,1928,105,0]An[4595,13,3589,2419,4150,105,0]An[4595,13,3589,3589,4630,105,0]An[4595,13,2057,2057,1300,105,0]An[4595,13,2057,2057,1303,105,0]An[4307,13,4308,4308,3248,105,0]Am[4307,13,4308,375,4273,105,0]An[4307,13,4308,4308,2346,105,0]An[4307,13,4308,4308,2359,105,0]An[4307,13,4308,4308,4003,105,0]An[1015,13,1016,1016,3023,105,0]An[1015,13,1016,1016,4730,105,0]Am[1015,13,1775,1775,122,105,0]An[1015,13,1491,1491,1317,105,0]An[1015,13,1491,1491,3881,105,0]An[1015,13,1491,1491,4370,105,0]An[1015,13,4088,4088,4929,105,0]An[1015,13,4088,4088,4930,105,0]Am[1015,13,1868,1868,123,105,0]Am[3837,13,3838,3838,112,105,0]An[3837,13,3838,3838,2316,105,0]Al[3817,13,3818,3593,4799,0,0]Ai[3817,13,3818,0,3982,0,0]Al[4595,13,4596,1783,3984,0,0]Al[4595,14,4596,1846,4882,0,0]Ai[4595,14,4635,0,4697,0,0]Ah[4595,14,4373,0,456,0,0]Ai[4595,14,4373,0,1311,0,0]Ah[3817,5,3818,3593,0,0,0]Al[1320,15,1321,1321,3849,0,0]Ae[3837,6,3838,0,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Ah[4595,5,4596,1466,0,0,0]Al[3817,15,3818,3593,4637,0,0]Al[4595,15,4596,3076,4638,0,0]Ah[3817,5,3818,2370,0,0,0]Ah[4595,5,4596,2371,0,0,0]Al[4595,15,4596,2086,3879,0,0]Ah[3817,5,3818,2397,0,0,0]2Ah[4595,6,4596,1846,0,0,0]Ai[3817,19,3818,0,1552,0,0]Al[4595,19,4596,1895,1553,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]=Ai[3817,12,1785,0,4030,0,0]>Al[3817,13,1862,0,4569,4030,0]>Al[4595,12,1786,1786,4032,0,0]>Ao[4595,13,1863,1863,4570,4032,0]Ao[1015,13,4088,4088,4930,4032,0]An[3837,13,3838,3838,112,3864,0]Ao[3837,13,3838,3838,2316,3864,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,14,4596,1492,3049,0,0]Ai[3817,13,3818,0,4029,0,0]Al[4595,13,4596,1783,4031,0,0]Al[3817,13,3818,2078,4232,0,0]0>=Al[1015,13,1491,1491,4370,0,0]Ae[1015,2,1016,0,0,0,0]Al[3817,13,3818,2397,2329,0,0]Al[4595,13,4596,2371,2330,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]43Ai[3817,14,3818,0,2357,0,0]Al[4595,14,4596,4596,2358,0,0]Al[4307,14,4308,4308,2359,0,0]Al[4595,13,4596,2086,1947,0,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,14,4596,1492,3049,0,0]Al[4595,13,4596,4170,4972,0,0]Al[4595,13,4596,4170,4977,0,0]Al[3817,13,3818,3957,3236,0,0]Al[4595,13,4596,2086,3237,0,0]>=Al[1320,14,1490,1490,1316,0,0]Ai[476,14,477,477,3850,0,0]Ai[3817,13,1862,0,4567,0,0]Ai[3817,13,1862,0,4569,0,0]Al[4595,13,1863,1863,4568,0,0]Al[4595,13,1863,1863,4570,0,0]76Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]Ah[3817,5,3818,4392,0,0,0]Ah[4595,5,4596,4392,0,0,0]Ai[3817,15,3818,0,4361,0,0]Ai[3817,15,3818,0,3994,0,0]Al[4595,15,4596,3594,4362,0,0]Al[4595,15,4596,2371,3995,0,0]Ah[4595,6,4596,2371,0,0,0]Ah[4595,5,4596,1873,0,0,0]Ah[3817,5,3818,2370,0,0,0]Al[3817,15,3818,3952,4266,0,0]Ah[3817,5,1862,1863,0,0,0]Ae[4595,5,1863,0,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Al[4595,15,4596,1846,4636,0,0]>Al[4595,15,4596,1476,3047,0,0]=5454Al[4595,15,4596,2371,4128,0,0]Ah[3817,5,3588,2419,0,0,0]Ah[4595,5,3589,2419,0,0,0]Ah[4595,5,4596,1846,0,0,0]98Ah[4595,6,4596,1039,0,0,0]:9Ah[3817,5,3818,1783,0,0,0]Ah[4595,5,4596,1783,0,0,0]Ae[4595,5,1781,0,0,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Al[1015,14,1016,1016,3023,0,0]Ae[4595,2,4596,0,0,0,0]Ai[3817,13,3818,0,4244,0,0]Al[4595,13,4596,1783,4245,0,0]Al[3817,12,3818,2078,4232,0,0]Ab[4173,3,0,0,0,0,0]Ak[1320,14,1321,1321,121,0,0]Al[1320,14,1490,1490,3880,0,0]98Al[3817,13,3818,2397,3233,0,0]Al[4595,13,4596,2371,3234,0,0]Ai[3817,13,3818,0,4661,0,0]Al[4595,13,4596,3189,4662,0,0];=Al[3817,13,3818,3952,4738,0,0]Al[4595,13,4596,2086,3231,0,0]Al[3817,13,3818,3593,3204,0,0]Al[3817,13,3818,3593,3206,0,0]Al[3817,13,3818,2397,2329,0,0]Ak[3817,13,3818,1014,459,0,0]Al[4595,13,4596,2371,2330,0,0]<;Ai[3817,13,3818,0,1552,0,0]Ai[3817,13,3818,0,1536,0,0]Al[4595,13,4596,1895,1553,0,0]Al[4595,13,4596,1476,1537,0,0]20Ae[1320,7,1490,0,0,0,0]?>Al[1320,14,1490,1490,1316,0,0]Ao[1015,13,1016,1016,4730,3056,0]Ai[3817,15,3818,0,3031,0,0]Ah[3817,5,3818,1466,0,0,0]Al[4595,15,4596,1466,3032,0,0]Ah[4595,5,4596,1466,0,0,0]Ah[3817,6,3818,3594,0,0,0]Ah[4595,6,4596,3594,0,0,0]Al[4595,15,4596,2371,4128,0,0]Ah[4595,5,4596,1873,0,0,0]Ah[3817,5,3818,1492,0,0,0]Ah[4595,5,4596,1492,0,0,0]97Ae[1015,5,1491,0,0,0,0]:8Ah[4595,6,4596,1846,0,0,0]Ah[3817,5,3818,1035,0,0,0]Ah[4595,5,4596,1035,0,0,0]Ah[3817,5,3818,1501,0,0,0]Ah[4595,5,4596,1501,0,0,0]Ah[3817,5,3818,3189,0,0,0]Ah[4595,5,4596,3189,0,0,0]Ai[3817,15,3818,0,4361,0,0]Al[4595,15,4596,3594,4362,0,0]Ah[3817,5,3818,3593,0,0,0]Al[3817,15,3818,3952,3051,0,0]Al[3817,15,3818,3952,3232,0,0]Al[3817,15,3818,3957,3249,0,0]Al[3817,15,3818,3957,4035,0,0]An[1320,13,1321,1321,121,4127,0]Ao[1320,13,1321,1321,3849,4127,0]Ao[3817,13,3818,3593,3206,4127,0]Ao[3817,13,3818,3593,4799,4127,0]Ao[3817,13,3818,3593,4637,4127,0]Ao[3817,13,3818,2370,2325,4127,0]Ao[3817,13,3818,2370,4130,4127,0]Ao[3817,13,3818,3952,4267,4127,0]Ao[3817,13,3818,3952,3051,4127,0]Ao[3817,13,3818,3952,3232,4127,0]Ao[3817,13,3818,3952,4266,4127,0]Ao[3817,13,3818,3957,3249,4127,0]Ao[3817,13,3818,3957,4035,4127,0]Al[3817,13,3818,0,1552,4127,0]Al[3817,13,3818,0,4796,4127,0]Al[3817,13,3818,0,1536,4127,0]Al[3817,13,3818,0,2360,4127,0]Al[3817,13,3818,0,3212,4127,0]Al[3817,13,3818,0,3048,4127,0]Al[3817,13,3818,0,4365,4127,0]Al[3817,13,3818,0,1952,4127,0]Al[3817,13,3818,0,3988,4127,0]Al[3817,13,3818,0,4361,4127,0]Al[3817,13,3818,0,4382,4127,0]Al[3817,13,3818,0,4661,4127,0]Al[3817,13,3818,0,4676,4127,0]Al[3817,13,3818,0,3862,4127,0]Al[3817,13,3818,0,4244,4127,0]Al[3817,13,3818,0,4029,4127,0]Al[3817,13,3818,0,4853,4127,0]Al[3817,13,3818,0,3982,4127,0]Al[3817,13,3818,0,3852,4127,0]Al[3817,13,3818,0,3031,4127,0]Al[3817,13,3818,0,4358,4127,0]Al[3817,13,3818,0,4540,4127,0]Al[3817,13,3818,0,3994,4127,0]Al[3817,13,3818,0,3997,4127,0]Al[3817,13,3818,0,4001,4127,0]Al[3817,13,3818,0,4695,4127,0]Ak[3817,13,3818,0,466,4127,0]Ak[3817,13,3818,0,113,4127,0]Al[3817,13,3818,0,2348,4127,0]Ak[3817,13,3588,0,107,4127,0]Al[3817,13,3588,0,3020,4127,0]Al[3817,13,3588,0,1284,4127,0]Al[3817,13,3588,0,3857,4127,0]Al[3817,13,3588,0,1927,4127,0]Al[3817,13,3588,0,4149,4127,0]Al[3817,13,1862,0,4792,4127,0]Al[3817,13,1862,0,1297,4127,0]Ao[4595,13,4596,1895,1553,4127,0]Ao[4595,13,4596,1895,4797,4127,0]Ao[4595,13,4596,3076,4638,4127,0]Ao[4595,13,4596,1476,1537,4127,0]Ao[4595,13,4596,1476,4025,4127,0]Ao[4595,13,4596,1476,3226,4127,0]Ao[4595,13,4596,1476,3047,4127,0]Ao[4595,13,4596,1476,4692,4127,0]Ao[4595,13,4596,1476,3202,4127,0]Ao[4595,13,4596,1492,2361,4127,0]Ao[4595,13,4596,1492,3213,4127,0]Ao[4595,13,4596,1492,3049,4127,0]Ao[4595,13,4596,1492,4366,4127,0]Ao[4595,13,4596,1039,3052,4127,0]Ao[4595,13,4596,1039,4157,4127,0]Ao[4595,13,4596,1044,1953,4127,0]Ao[4595,13,4596,1044,3250,4127,0]Ao[4595,13,4596,1044,3861,4127,0]Ao[4595,13,4596,2086,4268,4127,0]Ao[4595,13,4596,2086,3992,4127,0]Ao[4595,13,4596,3594,4362,4127,0]Ao[4595,13,4596,3594,3044,4127,0]Ao[4595,13,4596,3594,4235,4127,0]Ao[4595,13,4596,3189,4383,4127,0]Ao[4595,13,4596,3189,4662,4127,0]Ao[4595,13,4596,3189,4677,4127,0]Ao[4595,13,4596,3189,3863,4127,0]Ao[4595,13,4596,1783,4245,4127,0]Ao[4595,13,4596,1783,4031,4127,0]Ao[4595,13,4596,1783,4854,4127,0]Ao[4595,13,4596,1783,3984,4127,0]Ao[4595,13,4596,1783,3853,4127,0]Ao[4595,13,4596,1466,3032,4127,0]Ao[4595,13,4596,1466,4360,4127,0]Ao[4595,13,4596,1466,4542,4127,0]Ao[4595,13,4596,1466,2319,4127,0]Ao[4595,13,4596,2371,4546,4127,0]Ao[4595,13,4596,2371,3995,4127,0]Ao[4595,13,4596,1846,4374,4127,0]Ao[4595,13,4596,1846,4882,4127,0]Ao[4595,13,4596,1846,2332,4127,0]Ao[4595,13,4596,1846,4636,4127,0]Ao[4595,13,4596,1873,3998,4127,0]Ao[4595,13,4596,1873,4002,4127,0]Al[4595,13,4596,0,4272,4127,0]Al[4595,13,4596,0,4696,4127,0]Ao[4595,13,4596,4170,3216,4127,0]Ao[4595,13,4596,4170,4977,4127,0]An[4595,13,4596,4596,467,4127,0]An[4595,13,4596,4596,114,4127,0]Ao[4595,13,4596,4596,2349,4127,0]Ao[4595,13,4596,4596,3030,4127,0]Ao[4595,13,1781,1781,4163,4127,0]Ao[4595,13,4838,4838,4737,4127,0]Ao[4595,13,4838,4838,1299,4127,0]Ao[4595,13,1863,1863,4793,4127,0]Al[4595,13,1863,0,1298,4127,0]Am[4595,13,3589,129,108,4127,0]An[4595,13,3589,129,3021,4127,0]Ao[4595,13,3589,1461,1285,4127,0]Ao[4595,13,3589,1461,3858,4127,0]Ao[4595,13,3589,2419,1928,4127,0]Ao[4595,13,3589,2419,4150,4127,0]Ao[4595,13,2057,2057,1303,4127,0]Ao[4307,13,4308,4308,2346,4127,0]Ao[4307,13,4308,4308,2359,4127,0]Ao[4307,13,4308,4308,4003,4127,0]Ao[1015,13,1016,1016,4730,4127,0]Ao[1015,13,1491,1491,4370,4127,0]Ah[3817,7,3818,2078,0,0,0]Ai[3817,13,3818,0,4244,0,0]Al[4595,13,4596,1783,4245,0,0]Ai[3817,12,1785,0,3041,0,0]Al[4595,12,1786,1786,3042,0,0]Al[4307,14,4308,4308,2346,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]10Ae[1015,7,1016,0,0,0,0]Al[3817,13,3818,2370,2325,0,0]Ae[4173,7,4174,0,0,0,0]Ae[1320,7,1321,0,0,0,0]Al[4595,13,4596,3594,3207,0,0]Al[3817,13,3818,3593,3206,0,0]1Al[4595,13,4596,2086,4268,0,0]Al[1320,13,1490,1490,1316,0,0]Al[1320,14,1490,1490,3880,0,0]Al[3817,12,3818,2078,1939,0,0]Ao[3817,13,3818,1502,4036,1939,0]Ao[3817,13,3818,1056,3875,1939,0]Ai[3817,12,1785,0,1940,0,0]Al[3817,13,1862,0,3244,1940,0]Al[4595,12,1786,1786,1941,0,0]Ao[4595,13,1863,1863,3245,1941,0]Ai[3817,15,3818,0,3031,0,0]Ah[3817,5,3818,1466,0,0,0]Al[4595,15,4596,1466,3032,0,0]Ah[4595,5,4596,1466,0,0,0]Ai[3817,15,3818,0,4361,0,0]Al[4595,15,4596,3594,4362,0,0]Ah[4595,5,4596,2371,0,0,0]Al[4595,15,4596,3594,1302,0,0]Ai[3817,15,3818,0,3994,0,0]Al[4595,15,4596,2371,3995,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]32Al[4595,15,4596,3594,3044,0,0]><><><21Ah[3817,5,1862,1863,0,0,0]Ae[4595,5,1863,0,0,0,0]10Ah[3817,5,3818,4726,0,0,0]Ah[4595,5,4596,4726,0,0,0]Al[4595,15,2057,2057,1300,0,0]5Al[4595,15,4596,1846,4374,0,0]Ai[3817,12,3818,0,2353,0,0]Al[3817,13,3818,0,4121,2353,0]Al[3817,13,3818,0,4013,2353,0]Al[4595,12,4596,1501,2354,0,0]Ao[4595,13,4596,4392,4122,2354,0]Ao[4595,13,4596,1501,4014,2354,0]Ae[3886,7,3887,0,0,0,0]Al[3817,13,3818,3593,3206,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]32An[1320,13,1321,1321,121,4246,0]Ao[1015,13,1016,1016,3023,4246,0]An[1015,13,1775,1775,122,4246,0]An[1015,13,1868,1868,123,4246,0]An[3837,13,3838,3838,112,4246,0]Ao[3837,13,3838,3838,2316,4246,0]Ab[4595,3,0,0,0,0,0]Ak[4307,13,4308,375,4273,0,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0];:Al[3817,13,3818,2370,2325,0,0]Al[4595,13,4596,2371,2326,0,0]?>32Ae[4173,7,4174,0,0,0,0]5Al[1015,14,1016,1016,3023,0,0]60Ae[1320,7,1321,0,0,0,0]Ai[3817,13,3818,0,4029,0,0]Ai[3817,13,3818,0,3982,0,0]Al[4595,13,4596,1783,4031,0,0]Al[4595,13,4596,1783,3984,0,0]Ai[3817,14,3818,0,4029,0,0]Al[4595,14,4596,1783,4031,0,0]53Al[3817,13,3818,3957,3236,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Ai[3817,15,3818,0,4361,0,0]Al[4595,15,4596,3594,4362,0,0]Ai[3817,10,3588,3589,0,0,0]Af[4595,10,3589,0,0,0,0]Ah[3817,5,3588,3589,0,0,0]Ae[4595,5,3589,0,0,0,0]Ai[3817,10,1785,1786,0,0,0]Af[4595,10,1786,0,0,0,0]Ai[3817,15,3818,0,3994,0,0]Al[4595,15,4596,2371,3995,0,0]Ah[4595,6,4596,1846,0,0,0]Ah[3817,6,3818,3593,0,0,0]Ah[4595,6,4596,3076,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]10Al[3817,15,3818,3593,4637,0,0]Al[4595,15,4596,3076,4638,0,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,14,4596,1492,3049,0,0]Ai[3817,14,3588,0,4629,0,0]Al[4595,14,3589,3589,4630,0,0]Al[3817,13,3818,3593,3206,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]10Al[4595,13,4596,3076,3026,0,0]Al[3817,13,3818,2370,2325,0,0]Al[4595,13,4596,2371,2326,0,0]Ab[4656,3,0,0,0,0,0]Ao[1015,13,1016,1016,4730,3056,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Ah[3817,5,3818,3189,0,0,0]Ah[4595,5,4596,3189,0,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]54Ai[4595,10,4596,1846,0,0,0]Al[4595,15,4596,3594,1302,0,0]7600Al[4595,15,4596,1039,4157,0,0]4365Al[4595,15,2057,2057,1300,0,0]Ae[1015,9,1016,0,0,0,0]:9Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]<;<;Ah[4595,6,4596,1476,0,0,0]21Ae[3817,5,3818,0,0,0,0]Ae[4595,5,4596,0,0,0,0]Ai[3817,15,3818,0,3994,0,0]Ah[3817,5,1785,1786,0,0,0]Al[4595,15,4596,2371,3995,0,0]Al[4595,15,4596,1846,4636,0,0]Ae[4595,5,1786,0,0,0,0]An[1320,13,1321,1321,121,4236,0]Ao[1015,13,1016,1016,3023,4236,0]An[1015,13,1775,1775,122,4236,0]An[1015,13,1868,1868,123,4236,0]An[3837,13,3838,3838,112,4236,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]Ai[3817,13,3818,0,1552,0,0]Al[4595,13,4596,1895,1553,0,0]Al[3817,14,3818,2370,4130,0,0]Ai[3817,13,3818,0,4244,0,0]Al[4595,13,4596,1783,4245,0,0]Ai[3817,13,3818,0,4121,0,0]Al[4595,13,4596,4392,4122,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]6Al[4595,13,4596,3594,3207,0,0]Al[3817,13,3818,3593,3206,0,0]0176Ao[3886,13,3887,3887,4883,4690,0]Ai[3817,13,3818,0,4375,0,0]Al[4595,13,4596,1035,4376,0,0]Ae[1015,6,1016,0,0,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]10Al[4595,15,4596,3594,3044,0,0]Ae[4595,5,4838,0,0,0,0]Ah[3817,5,3818,3952,0,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]Al[4595,15,2057,2057,1300,0,0]Al[3817,14,3818,2370,4130,0,0]Ak[3817,13,3818,0,466,3014,0]Ak[3817,13,3818,0,113,3014,0]Al[3817,13,3818,0,2348,3014,0]An[4595,13,4596,4596,467,3014,0]An[4595,13,4596,4596,114,3014,0]Ao[4595,13,4596,4596,2349,3014,0]Ao[3837,13,3838,3838,2316,3240,0]Ai[3817,13,3818,0,4676,0,0]Al[4595,13,4596,3189,4677,0,0]Ai[3817,12,1785,0,1940,0,0]Al[3817,13,1862,0,3244,1940,0]Al[4595,12,1786,1786,1941,0,0]Ao[4595,13,1863,1863,3245,1941,0]Al[3817,13,3818,3593,3206,0,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]Ai[3817,14,3818,0,3048,0,0]Al[4595,14,4596,1492,3049,0,0]Ai[3817,12,3588,0,3208,0,0]Ak[3817,13,3588,0,107,3208,0]Al[3817,13,3588,0,1284,3208,0]Al[3817,13,3588,0,1927,3208,0]Al[4595,12,3589,3589,3209,0,0]Am[4595,13,3589,129,108,3209,0]Ao[4595,13,3589,1461,1285,3209,0]Ao[4595,13,3589,2419,1928,3209,0]Al[3817,14,3818,2370,4130,0,0]Al[4595,13,4596,2086,1947,0,0]Ah[4595,2,4168,3956,0,0,0]Ae[1320,7,1321,0,0,0,0]==Ak[3817,13,3818,1014,459,0,0]Ak[4307,13,4308,375,4273,0,0]032Ai[3817,12,1785,0,1940,0,0]Al[3817,13,1862,0,3244,1940,0]Ae[4595,2,4596,0,0,0,0]Al[4595,12,1786,1786,1941,0,0]Ao[4595,13,1863,1863,3245,1941,0]Ai[3817,10,3818,4170,0,0,0]Ai[4595,10,4596,4170,0,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]Ai[3817,15,3818,0,3994,0,0]Al[4595,15,4596,2371,3995,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Ah[3817,5,3818,1783,0,0,0]Ah[4595,5,4596,1783,0,0,0]Ai[3817,12,1785,0,3041,0,0]Al[4595,12,1786,1786,3042,0,0]Al[4595,13,4596,2371,2326,0,0]Al[4595,13,4596,4596,3030,0,0]Al[4595,13,4596,3594,3207,0,0]Ai[3817,13,3588,0,4149,0,0]Al[4595,13,3589,2419,4150,0,0]Al[3817,13,3818,2078,3054,0,0]0Al[3817,13,3818,3593,3206,0,0]4Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]Al[1015,14,1016,1016,3023,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Al[4595,15,2057,2057,1300,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]10Al[4595,15,4596,1476,4692,0,0]Al[4595,15,4596,3594,3044,0,0]Ai[3817,15,3818,0,3031,0,0]Al[4595,15,4596,1466,3032,0,0]Ah[4595,5,4596,1846,0,0,0]Ae[3886,5,3887,0,0,0,0]Al[1015,13,1016,1016,3023,0,0]Al[3817,13,3818,3593,3206,0,0]Ai[3817,12,1785,0,1940,0,0]Al[3817,13,1862,0,3244,1940,0]Al[4595,12,1786,1786,1941,0,0]Ao[4595,13,1863,1863,3245,1941,0]Ah[4595,7,4772,4771,0,0,0]0Al[4595,13,4596,3594,3207,0,0]6Ak[3817,13,3818,1014,459,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]Ao[3886,13,3887,3887,4883,4690,0]0Ai[3817,13,3818,0,3982,0,1]Al[4595,13,4596,1783,3984,0,1]Ai[3817,13,3818,0,3982,0,0]Al[4595,13,4596,1783,3984,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]10Ai[3817,13,3818,0,4661,0,0]Al[4595,13,4596,3189,4662,0,0]Am[1320,13,1321,1321,121,442,0]An[1015,13,1016,1016,3023,442,0]Am[1015,13,1775,1775,122,442,0]Am[1015,13,1868,1868,123,442,0]Am[3837,13,3838,3838,112,442,0]Al[4595,13,4596,3594,3207,0,0]0Ak[3817,13,3818,1014,459,0,0]An[1320,13,1321,1321,121,4246,0]Ao[1015,13,1016,1016,3023,4246,0]An[1015,13,1775,1775,122,4246,0]An[1015,13,1868,1868,123,4246,0]An[3837,13,3838,3838,112,4246,0]Ao[3837,13,3838,3838,2316,4246,0]Ai[3817,13,3818,0,4029,0,0]Al[4595,13,4596,1783,4031,0,0]Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]Ae[1015,5,4088,0,0,0,0]0Ai[3817,13,3818,0,4244,0,0]Al[4595,13,4596,1783,4245,0,0]Ai[3817,13,3818,0,3982,0,0]Al[4595,13,4596,1783,3984,0,0]Al[3817,13,3818,2370,2325,0,0]Al[3817,13,3818,2397,2329,0,0]Al[4595,13,4596,2371,2330,0,0]Al[4595,13,4596,3594,3207,0,0]Ao[3886,13,3887,3887,4883,4690,0];:Ah[3817,5,1785,1786,0,0,0]Ae[4595,5,1786,0,0,0,0]Ai[3817,15,1862,0,1297,0,0]Ai[4595,15,1863,0,1298,0,0]?>?>Al[3817,13,3818,3593,3206,0,0]6Ai[3817,13,3818,0,4382,0,0]Al[4595,13,4596,3189,4383,0,0]Ae[3886,7,3887,0,0,0,0]Ae[4173,7,4174,0,0,0,0]Ai[3817,14,3818,0,3212,0,0]Al[4595,14,4596,1492,3213,0,0]?=Ai[3817,19,3818,0,4695,0,0]Ai[4595,19,4596,0,4696,0,0]2=<==<>=>=>=<;<;Al[4595,14,4838,4838,4737,0,0]?>Ai[4595,18,4596,3189,0,0,0]") \ No newline at end of file diff --git a/pr/255/docs/search.index/function/0a18a7c168e3.js b/pr/255/docs/search.index/function/0a18a7c168e3.js new file mode 100644 index 000000000..f97d324b1 --- /dev/null +++ b/pr/255/docs/search.index/function/0a18a7c168e3.js @@ -0,0 +1 @@ +rd_("Bf[\"{{{AI@j{AO@d}}{AI@j{AO@d}}}CMf}\",[]]Bf[\"{{{AI@j{BECn}}{AI@j{BECn}}}CMf}\",[]]Bf[\"{{{AI@j{BBDn}}{AI@j{BBDn}}}CMf}\",[]]Bf[\"{{{AI@j{AHHh}}{AI@j{AHHh}}}CMf}\",[]]Bf[\"{{{AI@j{AIOn}}{AI@j{AIOn}}}CMf}\",[]]Bf[\"{{{AI@j{BBDl}}{AI@j{BBDl}}}CMf}\",[]]Bf[\"{{{AI@j{AJBb}}{AI@j{AJBb}}}CMf}\",[]]Bf[\"{{{AI@j{B@Gl}}{AI@j{B@Gl}}}CMf}\",[]]Bd[\"{{{AI@j{LGn}}{AI@j{LGn}}}CMf}\",[]]Bf[\"{{{AI@j{BFGl}}{AI@j{BFGl}}}CMf}\",[]]Bd[\"{{{AI@j{JE`}}{AI@j{JE`}}}CMf}\",[]]Bd[\"{{{AI@j{LEl}}{AI@j{LEl}}}CMf}\",[]]Bf[\"{{{AI@j{AHHb}}{AI@j{AHHb}}}CMf}\",[]]Bd[\"{{{AI@j{OKd}}{AI@j{OKd}}}CMf}\",[]]Bf[\"{{{AI@j{B@Al}}{AI@j{B@Al}}}CMf}\",[]]Bf[\"{{{AI@j{BC@j}}{AI@j{BC@j}}}CMf}\",[]]Bf[\"{{{AI@j{AOAn}}{AI@j{AOAn}}}CMf}\",[]]Bf[\"{{{AI@j{AO@j}}{AI@j{AO@j}}}CMf}\",[]]Bf[\"{{{AI@j{AHF`}}{AI@j{AHF`}}}CMf}\",[]]Bf[\"{{{AI@j{BC@d}}{AI@j{BC@d}}}CMf}\",[]]Bf[\"{{{AI@j{BDGl}}{AI@j{BDGl}}}CMf}\",[]]Bf[\"{{{AI@j{B@Bh}}{AI@j{B@Bh}}}CMf}\",[]]Bf[\"{{{AI@j{B@Bn}}{AI@j{B@Bn}}}CMf}\",[]]Bf[\"{{{AI@j{B@Ch}}{AI@j{B@Ch}}}CMf}\",[]]Bf[\"{{{AI@j{BEKb}}{AI@j{BEKb}}}CMf}\",[]]Bd[\"{{{AI@j{CLb}}{AI@j{CLb}}}CMf}\",[]]Bb[\"{{{AI@j{Nj}}{AI@j{Nj}}}CMf}\",[]]Bf[\"{{{AI@j{ABMl}}{AI@j{ABMl}}}CMf}\",[]]Bf[\"{{{AI@j{BGJ`}}{AI@j{BGJ`}}}CMf}\",[]]Bd[\"{{{AI@j{JGb}}{AI@j{JGb}}}CMf}\",[]]Bd[\"{{{AI@j{LH`}}{AI@j{LH`}}}CMf}\",[]]Bf[\"{{{AI@j{BFGn}}{AI@j{BFGn}}}CMf}\",[]]Bd[\"{{{AI@j{JEb}}{AI@j{JEb}}}CMf}\",[]]Bf[\"{{{AI@j{BED`}}{AI@j{BED`}}}CMf}\",[]]Bd[\"{{{AI@j{LEn}}{AI@j{LEn}}}CMf}\",[]]Bf[\"{{{AI@j{AIOb}}{AI@j{AIOb}}}CMf}\",[]]Bf[\"{{{AI@j{AHH`}}{AI@j{AHH`}}}CMf}\",[]]Bf[\"{{{AI@j{BEJl}}{AI@j{BEJl}}}CMf}\",[]]Bf[\"{{{AI@j{AIL`}}{AI@j{AIL`}}}CMf}\",[]]Bf[\"{{{AI@j{AHHd}}{AI@j{AHHd}}}CMf}\",[]]Bf[\"{{{AI@j{AHHj}}{AI@j{AHHj}}}CMf}\",[]]Bf[\"{{{AI@j{BAG`}}{AI@j{BAG`}}}CMf}\",[]]Bd[\"{{{AI@j{OKf}}{AI@j{OKf}}}CMf}\",[]]Bf[\"{{{AI@j{AJBd}}{AI@j{AJBd}}}CMf}\",[]]Bf[\"{{{AI@j{AOAl}}{AI@j{AOAl}}}CMf}\",[]]Bf[\"{{{AI@j{AOD`}}{AI@j{AOD`}}}CMf}\",[]]Bf[\"{{{AI@j{BBE`}}{AI@j{BBE`}}}CMf}\",[]]Bf[\"{{{AI@j{B@Bd}}{AI@j{B@Bd}}}CMf}\",[]]Bf[\"{{{AI@j{BC@l}}{AI@j{BC@l}}}CMf}\",[]]Bf[\"{{{AI@j{AHGj}}{AI@j{AHGj}}}CMf}\",[]]Bf[\"{{{AI@j{BB@l}}{AI@j{BB@l}}}CMf}\",[]]Bf[\"{{{AI@j{AOB`}}{AI@j{AOB`}}}CMf}\",[]]Bf[\"{{{AI@j{AO@l}}{AI@j{AO@l}}}CMf}\",[]]Bf[\"{{{AI@j{AHFb}}{AI@j{AHFb}}}CMf}\",[]]Bf[\"{{{AI@j{BBBj}}{AI@j{BBBj}}}CMf}\",[]]Bf[\"{{{AI@j{AINb}}{AI@j{AINb}}}CMf}\",[]]Bf[\"{{{AI@j{AJ@n}}{AI@j{AJ@n}}}CMf}\",[]]Bf[\"{{{AI@j{B@Cb}}{AI@j{B@Cb}}}CMf}\",[]]Bf[\"{{{AI@j{BC@h}}{AI@j{BC@h}}}CMf}\",[]]Bf[\"{{{AI@j{BDH`}}{AI@j{BDH`}}}CMf}\",[]]Bf[\"{{{AI@j{BDHh}}{AI@j{BDHh}}}CMf}\",[]]Bf[\"{{{AI@j{B@Bj}}{AI@j{B@Bj}}}CMf}\",[]]Bf[\"{{{AI@j{ABKl}}{AI@j{ABKl}}}CMf}\",[]]Bf[\"{{{AI@j{BECl}}{AI@j{BECl}}}CMf}\",[]]Bf[\"{{{AI@j{B@C`}}{AI@j{B@C`}}}CMf}\",[]]Bf[\"{{{AI@j{B@Cj}}{AI@j{B@Cj}}}CMf}\",[]]Bf[\"{{{AI@j{BBEh}}{AI@j{BBEh}}}CMf}\",[]]Bf[\"{{{AI@j{BEKd}}{AI@j{BEKd}}}CMf}\",[]]Bd[\"{{{AI@j{CLd}}{AI@j{CLd}}}CMf}\",[]]Bb[\"{{{AI@j{Nl}}{AI@j{Nl}}}CMf}\",[]]Bf[\"{{{AI@j{ABMn}}{AI@j{ABMn}}}CMf}\",[]]Bf[\"{{{AI@j{AHEn}}{AI@j{AHEn}}}CMf}\",[]]Bf[\"{{{AI@j{BAGl}}{AI@j{BAGl}}}CMf}\",[]]Bf[\"{{{AI@j{BF@f}}{AI@j{BF@f}}}CMf}\",[]]Bd[\"{{{AI@j{JGf}}{AI@j{JGf}}}CMf}\",[]]Bf[\"{{{AI@j{BGJb}}{AI@j{BGJb}}}CMf}\",[]]Bd[\"{{{AI@j{JGd}}{AI@j{JGd}}}CMf}\",[]]Bf[\"{{{AI@j{B@Cl}}{AI@j{B@Cl}}}CMf}\",[]]Ai[\"{{{AI@j{CKd}}}LEl}\",[]]Ak[\"{{{AI@j{AIOj}}}ABMl}\",[]]Ak[\"{{{AI@j{BF@h}}}ABMl}\",[]]Ak[\"{{{AI@j{AJ@f}}}ABMl}\",[]]o[\"{LE`LEn}\",[]]o[\"{LClLEn}\",[]]A`[\"{AHCfLEn}\",[]]A`[\"{BADnLEn}\",[]]A`[\"{B@FbLEn}\",[]]A`[\"{B@EdLEn}\",[]]Aa[\"{ABM`ABMn}\",[]]Aa[\"{ABOjABMn}\",[]]Aa[\"{ABKbABMn}\",[]]A`[\"{OInABMn}\",[]]n[\"{{}OIf}\",[]]A`[\"{CJlABKl}\",[]]Be[\"{{{AI@j{LGn}}{AI@j{LGn}}}ABLn}\",[]]Be[\"{{{AI@j{LEl}}{AI@j{LEl}}}ABLn}\",[]]Bg[\"{{{AI@j{AOAn}}{AI@j{AOAn}}}ABLn}\",[]]Bg[\"{{{AI@j{B@Bn}}{AI@j{B@Bn}}}ABLn}\",[]]Be[\"{{{AI@j{CLb}}{AI@j{CLb}}}ABLn}\",[]]Bc[\"{{{AI@j{Nj}}{AI@j{Nj}}}ABLn}\",[]]Bg[\"{{{AI@j{ABMl}}{AI@j{ABMl}}}ABLn}\",[]]Be[\"{{{AI@j{LH`}}{AI@j{LH`}}}ABLn}\",[]]Bg[\"{{{AI@j{BED`}}{AI@j{BED`}}}ABLn}\",[]]Be[\"{{{AI@j{LEn}}{AI@j{LEn}}}ABLn}\",[]]Bg[\"{{{AI@j{AHHj}}{AI@j{AHHj}}}ABLn}\",[]]Bg[\"{{{AI@j{BAG`}}{AI@j{BAG`}}}ABLn}\",[]]Bg[\"{{{AI@j{AJBd}}{AI@j{AJBd}}}ABLn}\",[]]Bg[\"{{{AI@j{AOB`}}{AI@j{AOB`}}}ABLn}\",[]]Bg[\"{{{AI@j{BDHh}}{AI@j{BDHh}}}ABLn}\",[]]Bg[\"{{{AI@j{BECl}}{AI@j{BECl}}}ABLn}\",[]]Bg[\"{{{AI@j{B@C`}}{AI@j{B@C`}}}ABLn}\",[]]Be[\"{{{AI@j{CLd}}{AI@j{CLd}}}ABLn}\",[]]Bc[\"{{{AI@j{Nl}}{AI@j{Nl}}}ABLn}\",[]]Bg[\"{{{AI@j{ABMn}}{AI@j{ABMn}}}ABLn}\",[]]o[\"{ABMlNj}\",[]]o[\"{ABMnNl}\",[]]n[\"{LEbNl}\",[]]o[\"{AHDbNl}\",[]]A`[\"{ABNnLEh}\",[]]A`[\"{ABO`LEh}\",[]]A`[\"{ABMhLEh}\",[]]A`[\"{ABObLEh}\",[]]Bg[\"{{{AI@j{Oj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AO@d}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBEb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BGBl}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AILd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AILh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BFHb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BECn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{ABJn}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BACj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABKf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AJ@`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BBBh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{CKd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AIOj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BF@h}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBDn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AHHh}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AIOn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BBDl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{B@Gn}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AOCh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AJ@f}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AJBb}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{B@Gl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Cd[\"{{{AI@j{LGn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{BFGl}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Cd[\"{{{AI@j{JE`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cd[\"{{{AI@j{LEl}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{ABOd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AIMd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AHHb}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BCAb}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cd[\"{{{AI@j{OKd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{B@Al}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{BC@j}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{BCBf}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BCCd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BEFn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BEHl}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AOAn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BBAn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{B@G`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BFNn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{B@A`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AO@j}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{AHF`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{BC@d}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{BDGl}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{B@Bh}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{B@Bn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{B@Ch}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BEKb}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{AIMj}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BDKj}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cd[\"{{{AI@j{CLb}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cc[\"{{{AI@j{Nj}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{ABMl}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Ce[\"{{{AI@j{ABNn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cc[\"{{{AI@j{Mn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AHDh}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cd[\"{{{AI@j{JEh}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AOAd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Cd[\"{{{AI@j{OH`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BAF`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BEBn}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BGJ`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{AOA`}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BEKj}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]Ce[\"{{{AI@j{BFGd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Cd[\"{{{AI@j{JGb}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Bi[\"{{{AI@j{AILj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABK`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{LH`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BFGn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bh[\"{{{AI@j{JEb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BED`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bh[\"{{{AI@j{LEn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{B@Fh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AIOb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AHH`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BEJl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AIL`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{ABOf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AIMf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AHHd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BCAd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AHHj}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BAG`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bh[\"{{{AI@j{OKf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AJBd}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AOAl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AOD`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBE`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@Bd}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BC@l}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AHGj}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BB@l}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BGBd}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bh[\"{{{AI@j{JGl}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BCBh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BCCf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BEG`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BEHn}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AOB`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBB`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@Gd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BFO`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@Ad}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AO@l}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AHFb}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BBBj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AINb}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AJ@n}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{B@Cb}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BC@h}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BDH`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{ABJb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BDHh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABKh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@Bj}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AO@`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AJ@b}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BAFf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BCBd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BGBj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABKl}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BECl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BCA`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BACh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@C`}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{B@Cj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBEh}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BEKd}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{AIMl}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BGNd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BDKl}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{CLd}}{AI@j{CAnAHEl}}}LF`}\",[]]Bg[\"{{{AI@j{Nl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{ABMn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{ABO`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AHEn}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BAGl}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BF@f}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{JGf}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bi[\"{{{AI@j{BGJb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AOAb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BEL`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BFGf}}{AI@j{CAnAHEl}}}LF`}\",[]]0Cd[\"{{{AI@j{JGd}}{AI@j{CAnAHEl}}}{{LFb{HIhJFb}}}}\",[]]0Bg[\"{{{AI@j{N`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AHDj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{JEj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{AOAf}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{OHb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BAFb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BEC`}}{AI@j{CAnAHEl}}}LF`}\",[]]Bh[\"{{{AI@j{JGh}}{AI@j{CAnAHEl}}}LF`}\",[]]0Bh[\"{{{AI@j{JGn}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{BBEj}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABMh}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{ABOb}}{AI@j{CAnAHEl}}}LF`}\",[]]Bi[\"{{{AI@j{B@Cl}}{AI@j{CAnAHEl}}}LF`}\",[]]Ak[\"{{{AI@j{B@Fh}}}ABJj}\",[]]A`[\"{ABOdCHl}\",[]]A`[\"{ABOfCHl}\",[]]Aj[\"{{{AI@j{BAFf}}}LAl}\",[]]A`[\"{BGBjCHl}\",[]]o[\"{CJlCHl}\",[]]A`[\"{ABMhLAl}\",[]]Ce[\"{{{AI@j{CAnBFNn}}{Ml{ABNf}}}{{AI@j{CAnBFNn}}}}\",[]]Ce[\"{{{AI@j{CAnBFO`}}{Ml{ABNh}}}{{AI@j{CAnBFO`}}}}\",[]]8Af[\"{{ABJjCHl}BBEb}\",[]]Ag[\"{{}{{Ml{BGBl}}}}\",[]]Ae[\"{{LAlCHj}BABh}\",[]]Cd[\"{{BBAn{LEh{B@G`}}AHI`{Ml{OIh}}}{{LFd{ABJn}}}}\",[]]Ah[\"{{{Nd{JJ`}}}AIOd}\",[]]A`[\"{OI`BCBf}\",[]]Ah[\"{{{Ml{OFn}}}BBAn}\",[]]Bc[\"{{{Ml{B@Gb}}{Ml{BECb}}}B@G`}\",[]]Ai[\"{{{Ml{B@Ab}}}B@A`}\",[]]B`[\"{{{AI@j{{KOh{Md}}}}}B@Bn}\",[]]Ae[\"{{CHjLAl}BDKj}\",[]]Ag[\"{{CLbNjCHl}ABMl}\",[]]Aj[\"{{{Ml{AHDh}}CHh}Mn}\",[]]An[\"{{{Ml{AOAd}}OGdCHh}JEh}\",[]]An[\"{{{Ml{BAF`}}OGdCHh}OH`}\",[]]Ae[\"{{LAlCHj}BABj}\",[]]Ah[\"{{{Nd{JJ`}}}AIOf}\",[]]Bm[\"{{{Ml{BBB`}}{LEh{{Ml{B@Gd}}}}CMf}ABK`}\",[]]A`[\"{LAlBHAf}\",[]]o[\"{{}BGMj}\",[]]A`[\"{OI`BCBh}\",[]]Ah[\"{{{Ml{OG`}}}BBB`}\",[]]Bc[\"{{{Ml{B@Gf}}{Ml{BECd}}}B@Gd}\",[]]Ai[\"{{{Ml{B@Af}}}B@Ad}\",[]]Ek[\"{{ABIh{AI@j{c}}{AI@j{{KOh{CHj}}}}CMf}{{LFb{{LAj{BAFf{LEh{ABIh}}}}BECl}}}{BEGjJIh}}\",[\"\"]]B`[\"{{{AI@j{{KOh{Md}}}}}B@C`}\",[]]Af[\"{{BEKdLGj}BBEh}\",[]]A`[\"{LAlBGNd}\",[]]Ae[\"{{CHjLAl}BDKl}\",[]]Ag[\"{{CLdNlCHl}ABMn}\",[]]Aj[\"{{{Ml{AHDj}}CHh}N`}\",[]]An[\"{{{Ml{AOAf}}OGdCHh}JEj}\",[]]An[\"{{{Ml{BAFb}}OGdCHh}OHb}\",[]]Aj[\"{AJB`{{LFd{BBEj}}}}\",[]]Ai[\"{{{Ml{BDKd}}}BGHd}\",[]]Ai[\"{{{Ml{BDKh}}}BGHf}\",[]]o[\"{CLbCLb}\",[]]o[\"{CLdCLd}\",[]]Ak[\"{{{AI@j{AJAd}}}AJAb}\",[]]Ai[\"{{{AI@j{OIh}}}OGd}\",[]]0Aj[\"{{{AI@j{B@Gn}}}OGd}\",[]]Ak[\"{{{AI@j{BAGh}}}AJAb}\",[]]Ak[\"{{{AI@j{AJAf}}}AJAb}\",[]]Ak[\"{{{AI@j{BAGj}}}AJAb}\",[]]Bg[\"{{{AI@j{AILh}}LEl}{{LEh{ABJj}}}}\",[]]Aa[\"{AHHbABJj}\",[]]Bg[\"{{{AI@j{AILj}}LEn}{{LEh{ABJj}}}}\",[]]Aa[\"{AHHdABJj}\",[]]Ag[\"{Ol{{LFf{HIh}}}}\",[]]Ag[\"{On{{LFf{HIh}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Aa[\"{B@EdAJ@l}\",[]]Aa[\"{ABMhAJ@l}\",[]]Aa[\"{BBEhBEKd}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]A`[\"{ABJbJDn}\",[]]Am[\"{{{AI@j{CAnABLj}}}HIh}\",[]]Am[\"{{{AI@j{CAnABKf}}}HIh}\",[]]Am[\"{{{AI@j{CAnAIOj}}}HIh}\",[]]Am[\"{{{AI@j{CAnAJ@f}}}HIh}\",[]]Al[\"{{{AI@j{CAnLCd}}}HIh}\",[]]A`[\"{cc{}}\",[\"T\"]]0000000000000000000000Aa[\"{BC@jBECn}\",[]]111111111Aa[\"{AHHhBBDn}\",[]]2Aa[\"{BC@jAHHh}\",[]]Aa[\"{AIOnAHHh}\",[]]4Aa[\"{BC@jAIOn}\",[]]5Aa[\"{AHHhBBDl}\",[]]66666Aa[\"{BC@jAJBb}\",[]]Aa[\"{B@GlAJBb}\",[]]Aa[\"{B@AlAJBb}\",[]]Aa[\"{BC@jB@Gl}\",[]]::::::A`[\"{BEKbLGn}\",[]];o[\"{CHjLGn}\",[]]A`[\"{ABMlLGn}\",[]]n[\"{MdLGn}\",[]]o[\"{CHhLGn}\",[]]???Al[\"{cLEl{{CJf{CHj}}}}\",[\"T\"]]A`[\"{cc{}}\",[\"T\"]]00000Aa[\"{AO@hBC@j}\",[]]A`[\"{JFnBC@j}\",[]]A`[\"{JEfBC@j}\",[]]33333A`[\"{LGnAOAn}\",[]]44444Aa[\"{BFGlAO@j}\",[]]5Aa[\"{BCChAO@j}\",[]]66A`[\"{JFnBC@d}\",[]]77Aa[\"{BEKjB@Bh}\",[]]888A`[\"{LGnBEKb}\",[]]9999A`[\"{LGnABMl}\",[]]::::::::::::Aa[\"{AODfAOA`}\",[]];;;;;;;;A`[\"{BGK`JGb}\",[]]A`[\"{BDIdJGb}\",[]]A`[\"{BBBlJGb}\",[]]A`[\"{BBCnJGb}\",[]]A`[\"{BDJlJGb}\",[]]A`[\"{BDHbJGb}\",[]]A`[\"{BGE`JGb}\",[]]A`[\"{BGInJGb}\",[]]A`[\"{BCBlJGb}\",[]]A`[\"{BCAfJGb}\",[]]A`[\"{AINhJGb}\",[]]A`[\"{cc{}}\",[\"T\"]]000000000000000o[\"{CHjLH`}\",[]]A`[\"{ABMnLH`}\",[]]A`[\"{BEKdLH`}\",[]]n[\"{MdLH`}\",[]]o[\"{CHhLH`}\",[]]5555Al[\"{cLEn{{CJf{CHj}}}}\",[\"T\"]]6666666666666666666Aa[\"{BBEhBC@l}\",[]]7777A`[\"{AHH`JGl}\",[]]8888A`[\"{LH`AOB`}\",[]]99999Aa[\"{BCChAO@l}\",[]]Aa[\"{BFGnAO@l}\",[]];;;;;;;Aa[\"{BBEhBC@h}\",[]]<<<>>>>A`[\"{JGfBBEh}\",[]]?A`[\"{LH`BEKd}\",[]]A`[\"{cc{}}\",[\"T\"]]00000A`[\"{LH`ABMn}\",[]]1111A`[\"{BAGlJGf}\",[]]2222Aa[\"{AODfAOAb}\",[]]3333333A`[\"{BDHbJGd}\",[]]A`[\"{BCAfJGd}\",[]]A`[\"{BCBlJGd}\",[]]6A`[\"{BGK`JGd}\",[]]A`[\"{BGInJGd}\",[]]A`[\"{AINhJGd}\",[]]A`[\"{BGE`JGd}\",[]]A`[\"{BDIdJGd}\",[]]A`[\"{BBBlJGd}\",[]]A`[\"{BBCnJGd}\",[]]A`[\"{BDJlJGd}\",[]]>>>>>>>>>An[\"{{{AI@j{c}}}AJB`CIb}\",[\"S\"]]????????????????Bm[\"{{{AI@j{LGn}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bk[\"{{{AI@j{LEl}}{AI@j{CAnc}}}HIhLDj}\",[\"H\"]]Bn[\"{{{AI@j{AOAn}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{B@Bn}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bm[\"{{{AI@j{CLb}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bl[\"{{{AI@j{Nj}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{ABMl}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bm[\"{{{AI@j{LH`}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{BED`}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bk[\"{{{AI@j{LEn}}{AI@j{CAnc}}}HIhLDj}\",[\"H\"]]Bn[\"{{{AI@j{AHHj}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{BAG`}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{AJBd}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{AOB`}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{BDHh}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{BECl}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{B@C`}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bm[\"{{{AI@j{CLd}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bl[\"{{{AI@j{Nl}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{ABMn}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Bn[\"{{{AI@j{AHEn}}{AI@j{CAnc}}}HIhLDj}\",[\"__H\"]]Aa[\"{{}c{}}\",[\"U\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n[\"{{}HIh}\",[]]0000Cc[\"{{{AI@j{CAnLCd}}LAl}{{LFb{{LEh{JEb}}AHHj}}}}\",[]]El[\"{{{AI@j{OEf}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{{AI@j{CAn{KOh{Md}}}}AOA`}}}}\",[]]Bh[\"{{{AI@j{CAnOJh}}Nl}{{LEh{ABMn}}}}\",[]]El[\"{{{AI@j{OEh}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{{AI@j{CAn{KOh{Md}}}}AOAb}}}}\",[]]Bf[\"{{{AI@j{AILh}}LEl}{{LEh{CKd}}}}\",[]]Bf[\"{{{AI@j{CKd}}}{{LFb{HIhAIKj}}}}\",[]]A`[\"{AIMdCHl}\",[]]Am[\"{{{AI@j{CAnAILj}}}HIh}\",[]]A`[\"{AIMfCHl}\",[]]Ck[\"{{{A@b{{AI@j{CAnAIKb}}}}{AI@j{CAnOFb}}}{{CKl{HIh}}}}\",[]]Dk[\"{{{A@b{{AI@j{CAnBCCn}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnABLj}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnABLl}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnAHDn}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnAILd}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{A@b{{AI@j{CAnOHf}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{A@b{{AI@j{CAnLDn}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnAHCj}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnABIf}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnB@F`}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnB@Fj}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{A@b{{AI@j{CAnLBd}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Dk[\"{{{A@b{{AI@j{CAnBBBh}}}}{AI@j{CAnOFb}}}{{CKl{c}}}{}}\",[\"Future::Output\"]]Bf[\"{{{AI@j{CAnAILj}}}{{LEh{JGl}}}}\",[]]De[\"{{{AI@j{CAnAIOj}}{AI@j{CAn{KOh{Md}}}}}{{LFb{{LEh{LAl}}AHHh}}}}\",[]]Bm[\"{{{AI@j{CAnAIOl}}CMf}{{LFb{LCdBAG`}}}}\",[]]Bo[\"{{CLd{AI@j{CAnc}}}{{LFb{BF@fJGf}}}Nf}\",[\"R\"]]Bf[\"{{{AI@j{CAnAHEf}}}{{LEh{JDn}}}}\",[]]Ec[\"{{{AI@j{BBEj}}AJB`{AI@j{CAn{KOh{AIMn}}}}{AI@j{CAn{KOh{ABMh}}}}}{{LFd{LAl}}}}\",[]]Dk[\"{{{AI@j{OEf}}{AI@j{CAn{A@h{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhAOA`}}}}\",[]]Dk[\"{{{AI@j{OEh}}{AI@j{CAn{A@h{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhAOAb}}}}\",[]]C`[\"{{{AI@j{CAnAHEf}}JDnCMf}{{LFb{HIhBED`}}}}\",[]]Cc[\"{{{AI@j{BBEj}}AJB`{AI@j{ABOb}}}{{LFd{HIh}}}}\",[]]Bn[\"{{{AI@j{CAnBFNn}}CHj}{{AI@j{CAnBFNn}}}}\",[]]Bn[\"{{{AI@j{CAnBFO`}}CHj}{{AI@j{CAnBFO`}}}}\",[]]Aj[\"{{{AI@j{AILh}}}CLb}\",[]]Aj[\"{{{AI@j{AILj}}}CLd}\",[]]Cn[\"{{{AI@j{OFn}}{AI@j{{KOh{Md}}}}{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]Cn[\"{{{AI@j{OG`}}{AI@j{{KOh{Md}}}}{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]A`[\"{BBEbCHl}\",[]]A`[\"{ABNnLAl}\",[]]A`[\"{ABO`LAl}\",[]]o[\"{JIdCMf}\",[]]Bm[\"{{{AI@j{CAnAIOj}}LGn}{{LFb{HIhB@Al}}}}\",[]]Bm[\"{{{AI@j{CAnBF@h}}LGn}{{LFb{HIhB@Al}}}}\",[]]Bm[\"{{{AI@j{CAnAIOl}}LH`}{{LFb{HIhB@Bd}}}}\",[]]Bn[\"{{{AI@j{AJAl}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Bn[\"{{{AI@j{BBCj}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Bn[\"{{{AI@j{BDKj}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Bn[\"{{{AI@j{AJAn}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Bn[\"{{{AI@j{BBCl}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Bn[\"{{{AI@j{BDKl}}{AI@j{CHf}}}{{LEh{JDn}}}}\",[]]Aa[\"{{}c{}}\",[\"V\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bg[\"{{{Ml{BEBj}}OGdCHh}{{Nd{AILl}}}}\",[]]Bg[\"{{{Ml{AHDh}}OGdCHh}{{Nd{AILl}}}}\",[]]Bg[\"{{{Ml{AOAd}}OGdCHh}{{Nd{AILl}}}}\",[]]Bg[\"{{{Ml{BAF`}}OGdCHh}{{Nd{AILl}}}}\",[]]Bg[\"{{{Ml{BEBl}}OGdCHh}{{Nd{AILn}}}}\",[]]Bg[\"{{{Ml{AHDj}}OGdCHh}{{Nd{AILn}}}}\",[]]Bg[\"{{{Ml{AOAf}}OGdCHh}{{Nd{AILn}}}}\",[]]Bg[\"{{{Ml{BAFb}}OGdCHh}{{Nd{AILn}}}}\",[]]Ai[\"{BEOh{{Ml{BEBl}}}}\",[]]o[\"{JE`JDn}\",[]]A`[\"{ABOdCHl}\",[]]o[\"{OKdLAl}\",[]]o[\"{JEbJDn}\",[]]A`[\"{ABOfCHl}\",[]]o[\"{OKfLAl}\",[]]Aa[\"{AO@`BC@l}\",[]]Ag[\"{{{AI@j{Oj}}}Oj}\",[]]Ak[\"{{{AI@j{AO@d}}}AO@d}\",[]]Ak[\"{{{AI@j{AILh}}}AILh}\",[]]Ak[\"{{{AI@j{BFHb}}}BFHb}\",[]]Ak[\"{{{AI@j{BECn}}}BECn}\",[]]Ak[\"{{{AI@j{ABJn}}}ABJn}\",[]]Ak[\"{{{AI@j{BACj}}}BACj}\",[]]Ak[\"{{{AI@j{BBDn}}}BBDn}\",[]]Ak[\"{{{AI@j{AHHh}}}AHHh}\",[]]Ak[\"{{{AI@j{AIOn}}}AIOn}\",[]]Ak[\"{{{AI@j{BBDl}}}BBDl}\",[]]Ak[\"{{{AI@j{AJBb}}}AJBb}\",[]]Ak[\"{{{AI@j{B@Gl}}}B@Gl}\",[]]Ai[\"{{{AI@j{LGn}}}LGn}\",[]]Ak[\"{{{AI@j{BFGl}}}BFGl}\",[]]Ai[\"{{{AI@j{LEl}}}LEl}\",[]]Ak[\"{{{AI@j{ABOd}}}ABOd}\",[]]Ak[\"{{{AI@j{AIMd}}}AIMd}\",[]]Ak[\"{{{AI@j{AHHb}}}AHHb}\",[]]Ak[\"{{{AI@j{BCAb}}}BCAb}\",[]]Ai[\"{{{AI@j{OKd}}}OKd}\",[]]Ak[\"{{{AI@j{B@Al}}}B@Al}\",[]]Ak[\"{{{AI@j{BC@j}}}BC@j}\",[]]Ak[\"{{{AI@j{BCCd}}}BCCd}\",[]]Ak[\"{{{AI@j{BEFn}}}BEFn}\",[]]Ak[\"{{{AI@j{BEHl}}}BEHl}\",[]]Ak[\"{{{AI@j{AOAn}}}AOAn}\",[]]Ak[\"{{{AI@j{BBAn}}}BBAn}\",[]]Ak[\"{{{AI@j{B@G`}}}B@G`}\",[]]Ak[\"{{{AI@j{BFNn}}}BFNn}\",[]]Ak[\"{{{AI@j{B@A`}}}B@A`}\",[]]Ak[\"{{{AI@j{AO@j}}}AO@j}\",[]]Ak[\"{{{AI@j{AHF`}}}AHF`}\",[]]Ak[\"{{{AI@j{BC@d}}}BC@d}\",[]]Ak[\"{{{AI@j{BDGl}}}BDGl}\",[]]Ak[\"{{{AI@j{B@Bh}}}B@Bh}\",[]]Ak[\"{{{AI@j{B@Bn}}}B@Bn}\",[]]Ak[\"{{{AI@j{B@Ch}}}B@Ch}\",[]]Ak[\"{{{AI@j{BEKb}}}BEKb}\",[]]Ak[\"{{{AI@j{AIMj}}}AIMj}\",[]]Ai[\"{{{AI@j{CLb}}}CLb}\",[]]Ag[\"{{{AI@j{Nj}}}Nj}\",[]]Ak[\"{{{AI@j{ABMl}}}ABMl}\",[]]Ag[\"{{{AI@j{Mn}}}Mn}\",[]]Ak[\"{{{AI@j{AHDh}}}AHDh}\",[]]Ai[\"{{{AI@j{JEh}}}JEh}\",[]]Ak[\"{{{AI@j{AOAd}}}AOAd}\",[]]Ai[\"{{{AI@j{OH`}}}OH`}\",[]]Ak[\"{{{AI@j{BAF`}}}BAF`}\",[]]Ak[\"{{{AI@j{BFGd}}}BFGd}\",[]]Ai[\"{{{AI@j{JGb}}}JGb}\",[]]Ai[\"{{{AI@j{LH`}}}LH`}\",[]]Ak[\"{{{AI@j{BFGn}}}BFGn}\",[]]Ak[\"{{{AI@j{BED`}}}BED`}\",[]]Ai[\"{{{AI@j{LEn}}}LEn}\",[]]Ak[\"{{{AI@j{B@Fh}}}B@Fh}\",[]]Ak[\"{{{AI@j{AIOb}}}AIOb}\",[]]Ak[\"{{{AI@j{AHH`}}}AHH`}\",[]]Ak[\"{{{AI@j{BEJl}}}BEJl}\",[]]Ak[\"{{{AI@j{AIL`}}}AIL`}\",[]]Ak[\"{{{AI@j{ABOf}}}ABOf}\",[]]Ak[\"{{{AI@j{AIMf}}}AIMf}\",[]]Ak[\"{{{AI@j{AHHd}}}AHHd}\",[]]Ak[\"{{{AI@j{BCAd}}}BCAd}\",[]]Ak[\"{{{AI@j{AHHj}}}AHHj}\",[]]Ak[\"{{{AI@j{BAG`}}}BAG`}\",[]]Ai[\"{{{AI@j{OKf}}}OKf}\",[]]Ak[\"{{{AI@j{AJBd}}}AJBd}\",[]]Ak[\"{{{AI@j{AOAl}}}AOAl}\",[]]Ak[\"{{{AI@j{BBE`}}}BBE`}\",[]]Ak[\"{{{AI@j{B@Bd}}}B@Bd}\",[]]Ak[\"{{{AI@j{BC@l}}}BC@l}\",[]]Ak[\"{{{AI@j{AHGj}}}AHGj}\",[]]Ak[\"{{{AI@j{BB@l}}}BB@l}\",[]]Ak[\"{{{AI@j{BGBd}}}BGBd}\",[]]Ak[\"{{{AI@j{BCCf}}}BCCf}\",[]]Ak[\"{{{AI@j{BEG`}}}BEG`}\",[]]Ak[\"{{{AI@j{BEHn}}}BEHn}\",[]]Ak[\"{{{AI@j{AOB`}}}AOB`}\",[]]Ak[\"{{{AI@j{BBB`}}}BBB`}\",[]]Ak[\"{{{AI@j{B@Gd}}}B@Gd}\",[]]Ak[\"{{{AI@j{BFO`}}}BFO`}\",[]]Ak[\"{{{AI@j{B@Ad}}}B@Ad}\",[]]Ak[\"{{{AI@j{AO@l}}}AO@l}\",[]]Ak[\"{{{AI@j{AHFb}}}AHFb}\",[]]Ak[\"{{{AI@j{AINb}}}AINb}\",[]]Ak[\"{{{AI@j{AJ@n}}}AJ@n}\",[]]Ak[\"{{{AI@j{B@Cb}}}B@Cb}\",[]]Ak[\"{{{AI@j{BC@h}}}BC@h}\",[]]Ak[\"{{{AI@j{BDH`}}}BDH`}\",[]]Ak[\"{{{AI@j{ABJb}}}ABJb}\",[]]Ak[\"{{{AI@j{BDHh}}}BDHh}\",[]]Ak[\"{{{AI@j{B@Bj}}}B@Bj}\",[]]Ak[\"{{{AI@j{BCBd}}}BCBd}\",[]]Ak[\"{{{AI@j{BGBj}}}BGBj}\",[]]Ak[\"{{{AI@j{ABKl}}}ABKl}\",[]]Ak[\"{{{AI@j{BECl}}}BECl}\",[]]Ak[\"{{{AI@j{B@C`}}}B@C`}\",[]]Ak[\"{{{AI@j{B@Cj}}}B@Cj}\",[]]Ak[\"{{{AI@j{BBEh}}}BBEh}\",[]]Ak[\"{{{AI@j{BEKd}}}BEKd}\",[]]Ak[\"{{{AI@j{AIMl}}}AIMl}\",[]]Ak[\"{{{AI@j{BGNd}}}BGNd}\",[]]Ai[\"{{{AI@j{CLd}}}CLd}\",[]]Ag[\"{{{AI@j{Nl}}}Nl}\",[]]Ak[\"{{{AI@j{ABMn}}}ABMn}\",[]]Ak[\"{{{AI@j{AHEn}}}AHEn}\",[]]Ak[\"{{{AI@j{BAGl}}}BAGl}\",[]]Ak[\"{{{AI@j{BF@f}}}BF@f}\",[]]Ai[\"{{{AI@j{JGf}}}JGf}\",[]]Ak[\"{{{AI@j{BFGf}}}BFGf}\",[]]Ai[\"{{{AI@j{JGd}}}JGd}\",[]]Ag[\"{{{AI@j{N`}}}N`}\",[]]Ak[\"{{{AI@j{AHDj}}}AHDj}\",[]]Ai[\"{{{AI@j{JEj}}}JEj}\",[]]Ak[\"{{{AI@j{AOAf}}}AOAf}\",[]]Ai[\"{{{AI@j{OHb}}}OHb}\",[]]Ak[\"{{{AI@j{BAFb}}}BAFb}\",[]]Ai[\"{{{AI@j{JGn}}}JGn}\",[]]Ak[\"{{{AI@j{ABMh}}}ABMh}\",[]]Ak[\"{{{AI@j{ABOb}}}ABOb}\",[]]Ak[\"{{{AI@j{B@Cl}}}B@Cl}\",[]]Ak[\"{{{AI@j{BEOh}}}BEOh}\",[]]Ak[\"{{{AI@j{BCAl}}}BCAl}\",[]]Bn[\"{{{AI@j{AILh}}LGn{AI@j{{KOh{Md}}}}}HIh}\",[]]Bn[\"{{{AI@j{ABJn}}LGn{AI@j{{KOh{Md}}}}}HIh}\",[]]Bg[\"{{{AI@j{CKd}}}{{LFb{AHDnBB@j}}}}\",[]]Bf[\"{{{AI@j{CAnAILj}}OGdLH`JDn}HIh}\",[]]Bj[\"{{{AI@j{B@Bn}}}{{AI@j{{KOh{Md}}}}}}\",[]]Bj[\"{{{AI@j{B@C`}}}{{AI@j{{KOh{Md}}}}}}\",[]]Aa[\"{BADnAHGj}\",[]]Aa[\"{BBEhAINb}\",[]]A`[\"{ABMlCHl}\",[]]A`[\"{ABMnCHl}\",[]]A`[\"{B@ChCMf}\",[]]A`[\"{B@CjCMf}\",[]]l[\"{OGf}\",[]]l[\"{OGh}\",[]]Ce[\"{{{AI@j{BEGj}}{AI@j{CAnNf}}}{{LFb{B@C`BECl}}}}\",[]]Ce[\"{{{AI@j{BHAf}}{AI@j{CAnNf}}}{{LFb{B@C`BECl}}}}\",[]]Bc[\"{{{AI@j{AILj}}}{{A@h{LEn}}}}\",[]]Bd[\"{{{AI@j{JIj}}{AI@j{CHf}}}HIh}\",[]]Am[\"{{{AI@j{AO@f}}LAl}HIh}\",[]]Ai[\"{{{AI@j{JIl}}}HIh}\",[]]Bg[\"{{{A@b{{AI@j{CAnAIKb}}}}OGd}HIh}\",[]]Bm[\"{{{AI@j{CAnAJ@f}}LGn}{{LFb{HIhB@Al}}}}\",[]]Bm[\"{{{AI@j{CAnAJ@h}}LH`}{{LFb{HIhB@Bd}}}}\",[]]Am[\"{ABKf{{LFb{HIhAJ@`}}}}\",[]]Dc[\"{{{AI@j{CAnABK`}}ABKh{AI@j{CAn{A@h{Md}}}}}{{LFb{ABO`AJ@b}}}}\",[]]Bi[\"{{{AI@j{OIh}}{A@b{{Nd{LDh}}}}}HIh}\",[]]Bj[\"{{{AI@j{B@Gn}}{A@b{{Nd{LDh}}}}}HIh}\",[]]Bj[\"{{{AI@j{AOCh}}{A@b{{Nd{LDh}}}}}HIh}\",[]]n[\"{OjCMf}\",[]]Ak[\"{{{AI@j{AILh}}}BCAb}\",[]]Ak[\"{{{AI@j{ABJn}}}BACj}\",[]]An[\"{{{AI@j{CAnAILj}}}BCAd}\",[]]Ce[\"{{{AI@j{CAnAIOd}}{LEh{LGj}}}{{AI@j{CAnAIOd}}}}\",[]]Ce[\"{{{AI@j{CAnAIOf}}{LEh{LGj}}}{{AI@j{CAnAIOf}}}}\",[]]Ck[\"{{{AI@j{CAnAJ@f}}{AI@j{{KOh{Md}}}}}{{LFb{LAlAJBb}}}}\",[]]Ck[\"{{{AI@j{CAnAJ@h}}{AI@j{{KOh{Md}}}}}{{LFb{LAlAJBd}}}}\",[]]Bl[\"{{{AI@j{BF@f}}{AI@j{CAnc}}}HIhLCb}\",[\"W\"]]Aj[\"{{{AI@j{ABJn}}}LBd}\",[]]An[\"{ABKf{{LFb{AILdBC@j}}}}\",[]]Bh[\"{{{AI@j{CAnOJh}}Nl}{{LEh{ABMn}}}}\",[]]Fh[\"{{{AI@j{CAnABK`}}ABKhOGd{AI@j{CAn{A@h{Md}}}}{LEh{{Ml{B@Gd}}}}}{{LFb{{LAj{BDHhAILj}}{Nd{AO@`}}}}}}\",[]]Am[\"{AI@j{{AI@j{c}}}{}}\",[\"T\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000o[\"{OKdLAl}\",[]]o[\"{OKfLAl}\",[]]o[\"{OjAO@d}\",[]]Bb[\"{{AJ@lBB@hOj}{{LFf{AO@f}}}}\",[]]Aj[\"{AJ@l{{LFd{ABJn}}}}\",[]]B`[\"{{}{{LFb{HIh{Nd{JFd}}}}}}\",[]]Ak[\"{{{AI@j{AILh}}}BC@j}\",[]]Be[\"{{{AI@j{ABK`}}}{{AI@j{BBB`}}}}\",[]]o[\"{MdBEKb}\",[]]A`[\"{AIMdCHl}\",[]]o[\"{B@G`Ml}\",[]]o[\"{MdBEKd}\",[]]A`[\"{AIMfCHl}\",[]]o[\"{B@GdMl}\",[]]A`[\"{BBEhLEh}\",[]]Bl[\"{{{AI@j{CAnc}}}{{LFb{LGnBAGl}}}Nf}\",[\"B\"]]Bl[\"{{{AI@j{CAnc}}}{{LFb{LElBAGl}}}Nf}\",[\"B\"]]Bm[\"{{{AI@j{CAnc}}}{{LFb{AHF`BAGl}}}Nf}\",[\"B\"]]Bm[\"{{{AI@j{CAnc}}}{{LFb{BEKbBAGl}}}Nf}\",[\"B\"]]Bm[\"{{{AI@j{CAnc}}}{{LFb{ABMlBAGl}}}Nf}\",[\"B\"]]Bh[\"{{{AI@j{CAnc}}}{{LFj{LH`}}}Nf}\",[\"B\"]]Bh[\"{{{AI@j{CAnc}}}{{LFj{LEn}}}Nf}\",[\"B\"]]Bi[\"{{{AI@j{CAnc}}}{{LFj{AHFb}}}Nf}\",[\"B\"]]Bi[\"{{{AI@j{CAnc}}}{{LFj{AINb}}}Nf}\",[\"B\"]]Ek[\"{{{AI@j{CAn{LDf{ABIh}}}}{AI@j{c}}{AI@j{{KOh{CHj}}}}CMf}{{LFb{BCBdBECl}}}{BEGjJIh}}\",[\"\"]]Bi[\"{{{AI@j{CAnc}}}{{LFj{BEKd}}}Nf}\",[\"B\"]]Bi[\"{{{AI@j{CAnc}}}{{LFj{ABMn}}}Nf}\",[\"B\"]]Bi[\"{{{AI@j{CAnc}}}{{LFj{AHEh}}}Nf}\",[\"B\"]]A`[\"{ABMhLEh}\",[]]Bk[\"{{{AI@j{LGn}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bk[\"{{{AI@j{LEl}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{AHF`}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{BEKb}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{ABMl}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bk[\"{{{AI@j{LH`}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bk[\"{{{AI@j{LEn}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{AHFb}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{AINb}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{ABJb}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{BEKd}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{ABMn}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bl[\"{{{AI@j{AHEj}}{AI@j{CAnc}}}HIhLCb}\",[\"B\"]]Bj[\"{{{AI@j{CAnAJ@f}}}{{LFb{HIhB@Al}}}}\",[]]Bj[\"{{{AI@j{CAnAJ@h}}}{{LFb{HIhAOAl}}}}\",[]]An[\"{{{AI@j{AODd}}ABJj}HIh}\",[]]Ea[\"{{{AI@j{CAnABK`}}OGdAHEn{LEh{B@Cj}}ABIh{AI@j{CAn{A@h{Md}}}}}{{LEh{BACf}}}}\",[]]o[\"{CJhOGf}\",[]]o[\"{CJjOGh}\",[]]A`[\"{ABKfHIh}\",[]]Ba[\"{{{AI@j{CAnABK`}}ABKh}HIh}\",[]]Bh[\"{{{AI@j{AJAl}}{AI@j{CHf}}JDn}HIh}\",[]]Bh[\"{{{AI@j{BBCj}}{AI@j{CHf}}JDn}HIh}\",[]]Bh[\"{{{AI@j{BDKj}}{AI@j{CHf}}JDn}HIh}\",[]]Bh[\"{{{AI@j{AJAn}}{AI@j{CHf}}JDn}HIh}\",[]]Bh[\"{{{AI@j{BBCl}}{AI@j{CHf}}JDn}HIh}\",[]]Bh[\"{{{AI@j{BDKl}}{AI@j{CHf}}JDn}HIh}\",[]]A`[\"{AHE`CMf}\",[]]o[\"{JE`CHl}\",[]]o[\"{JEbCHl}\",[]]Ce[\"{{{AI@j{CAnAILl}}OGdOGdCHlCMf{AI@j{B@Ff}}}HIh}\",[]]Cc[\"{{{AI@j{CAnMn}}OGdOGdCHlCMf{AI@j{B@Ff}}}HIh}\",[]]Cd[\"{{{AI@j{CAnJEh}}OGdOGdCHlCMf{AI@j{B@Ff}}}HIh}\",[]]Cd[\"{{{AI@j{CAnOH`}}OGdOGdCHlCMf{AI@j{B@Ff}}}HIh}\",[]]Ce[\"{{{AI@j{CAnAILn}}OGdOGdCHlCMf{AI@j{B@Fh}}}HIh}\",[]]Cc[\"{{{AI@j{CAnN`}}OGdOGdCHlCMf{AI@j{B@Fh}}}HIh}\",[]]Cd[\"{{{AI@j{CAnJEj}}OGdOGdCHlCMf{AI@j{B@Fh}}}HIh}\",[]]Cd[\"{{{AI@j{CAnOHb}}OGdOGdCHlCMf{AI@j{B@Fh}}}HIh}\",[]]o[\"{CJhOGf}\",[]]o[\"{CJjOGh}\",[]]o[\"{BDLbMd}\",[]]A`[\"{BC@dJDn}\",[]]A`[\"{BDGlJDn}\",[]]A`[\"{BC@hJDn}\",[]]A`[\"{BDH`JDn}\",[]]A`[\"{BBEhLGj}\",[]]Aa[\"{BBA`BC@l}\",[]]Bg[\"{{{AI@j{ABJn}}AHI`}{{LFd{HIh}}}}\",[]]A`[\"{ABKfHIh}\",[]]Cf[\"{{{AI@j{CAnABK`}}ABKh{AI@j{CAn{A@h{Md}}}}}ABO`}\",[]]l[\"{OGf}\",[]]Aa[\"{AHEnAJ@l}\",[]]l[\"{OGh}\",[]]Am[\"{{ABJlOj}{{LFf{HIh}}}}\",[]]B`[\"{{B@G`AJ@l}{{LFd{ABJn}}}}\",[]]Bb[\"{B@Fn{{LFb{HIh{Nd{JFd}}}}}}\",[]]Bk[\"{{{AI@j{BECn}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{BBDn}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{AHHh}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{AIOn}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{BBDl}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{AJBb}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{B@Gl}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{BC@j}}}{{LEh{{AI@j{JFd}}}}}}\",[]]Bk[\"{{{AI@j{BC@l}}}{{LEh{{AI@j{JFd}}}}}}\",[]]A`[\"{ABNnLEh}\",[]]A`[\"{ABO`LEh}\",[]]A`[\"{ABObLEh}\",[]]Bg[\"{{{AI@j{CKd}}}{{LFb{AIO`AIKj}}}}\",[]]Aa[\"{B@FbAIOb}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]A`[\"{ABMhLAl}\",[]]Aa[\"{BCAbABOd}\",[]]Aa[\"{BCAdABOf}\",[]]10Dh[\"{{{AI@j{OFn}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhAOA`}}}}\",[]]Dh[\"{{{AI@j{OG`}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhAOAb}}}}\",[]]Aj[\"{{{AI@j{AILl}}}CHl}\",[]]Ah[\"{{{AI@j{Mn}}}CHl}\",[]]Ai[\"{{{AI@j{JEh}}}CHl}\",[]]Ai[\"{{{AI@j{OH`}}}CHl}\",[]]Aj[\"{{{AI@j{AILn}}}CHl}\",[]]Ah[\"{{{AI@j{N`}}}CHl}\",[]]Ai[\"{{{AI@j{JEj}}}CHl}\",[]]Ai[\"{{{AI@j{OHb}}}CHl}\",[]]Aj[\"{{{AI@j{BFMl}}}LAl}\",[]]Aj[\"{{{AI@j{BFMn}}}LAl}\",[]]Aj[\"{{{AI@j{BGMj}}}LAl}\",[]]Aj[\"{{{AI@j{BGNd}}}LAl}\",[]]n[\"{OjLAl}\",[]]n[\"{{}OF`}\",[]]0000o[\"{NhABIl}\",[]]Ba[\"{{AI@j{AI@j{c}}}ABLn{}}\",[\"K\"]]0000000000000000000Cg[\"{{{AI@j{ABJn}}AJ@l{AI@j{CHf}}}{{LFb{AILdB@Bh}}}}\",[]]Dl[\"{{{AI@j{CAnABK`}}OGdB@AdAJ@l{AI@j{CHf}}}{{LFb{{LAj{BDHhAILj}}B@Bj}}}}\",[]]Dm[\"{{{AI@j{AHGd}}LElCHl{AI@j{{KOh{Md}}}}{AI@j{CAnABIh}}}{{LFb{HIhAOA`}}}}\",[]]Ca[\"{{{AI@j{AHFf}}LAl{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]Dm[\"{{{AI@j{AHGf}}LEnCHl{AI@j{{KOh{Md}}}}{AI@j{CAnABIh}}}{{LFb{HIhAOAb}}}}\",[]]Ca[\"{{{AI@j{AHFh}}LAl{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]o[\"{{}AODb}\",[]]n[\"{{}JIj}\",[]]o[\"{{}AO@f}\",[]]o[\"{{}BABh}\",[]]o[\"{{}BACj}\",[]]n[\"{{}LGn}\",[]]n[\"{{}LEl}\",[]]o[\"{{}ABOd}\",[]]o[\"{{}AIMd}\",[]]o[\"{{}AHHb}\",[]]o[\"{{}BCAb}\",[]]n[\"{{}OKd}\",[]]o[\"{{}B@Al}\",[]]o[\"{{}BCCd}\",[]]o[\"{{}BEFn}\",[]]o[\"{{}BEHl}\",[]]o[\"{{}AOAn}\",[]]o[\"{{}BBAn}\",[]]o[\"{{}BFNn}\",[]]o[\"{{}BDKj}\",[]]o[\"{{}AHDh}\",[]]o[\"{{}AOAd}\",[]]o[\"{{}BAF`}\",[]]o[\"{{}BEBn}\",[]]o[\"{{}BABj}\",[]]o[\"{{}BGMj}\",[]]n[\"{{}LH`}\",[]]n[\"{{}LEn}\",[]]o[\"{{}AIOb}\",[]]o[\"{{}AIL`}\",[]]o[\"{{}ABOf}\",[]]o[\"{{}AIMf}\",[]]o[\"{{}AHHd}\",[]]o[\"{{}BCAd}\",[]]n[\"{{}OKf}\",[]]o[\"{{}BBE`}\",[]]o[\"{{}B@Bd}\",[]]o[\"{{}BCCf}\",[]]o[\"{{}BEG`}\",[]]o[\"{{}BEHn}\",[]]o[\"{{}AOB`}\",[]]o[\"{{}BBB`}\",[]]o[\"{{}BFO`}\",[]]o[\"{{}BGNd}\",[]]o[\"{{}BDKl}\",[]]o[\"{{}AHDj}\",[]]o[\"{{}AOAf}\",[]]o[\"{{}BAFb}\",[]]o[\"{{}BEC`}\",[]]o[\"{{}ABMh}\",[]]n[\"{{}JIl}\",[]]o[\"{{}BCAl}\",[]]o[\"{{}BACh}\",[]]Ak[\"{{{AI@j{BAFf}}}B@C`}\",[]]Ak[\"{{{AI@j{BCBd}}}B@C`}\",[]]Aa[\"{BGBjB@C`}\",[]]Aa[\"{BEKfB@C`}\",[]]A`[\"{CJlB@C`}\",[]]A`[\"{JI`B@C`}\",[]]A`[\"{JIdB@C`}\",[]]Aa[\"{BDLbB@C`}\",[]]Cg[\"{{{AI@j{AHGd}}LElCHl{AI@j{CAn{KOh{Md}}}}LAl}HIh}\",[]]Ca[\"{{{AI@j{AHFf}}LAl{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]Cg[\"{{{AI@j{AHGf}}LEnCHl{AI@j{CAn{KOh{Md}}}}LAl}HIh}\",[]]Ca[\"{{{AI@j{AHFh}}LAl{AI@j{CAn{KOh{Md}}}}}HIh}\",[]]Aj[\"{{{AI@j{AIOj}}}CMf}\",[]]Aj[\"{{{AI@j{BF@h}}}CMf}\",[]]Ak[\"{{{AI@j{AILl}}}BEBn}\",[]]Ai[\"{{{AI@j{Mn}}}BEBn}\",[]]Aj[\"{{{AI@j{JEh}}}BEBn}\",[]]Aj[\"{{{AI@j{OH`}}}BEBn}\",[]]Ak[\"{{{AI@j{AILn}}}BEC`}\",[]]Ai[\"{{{AI@j{N`}}}BEC`}\",[]]Aj[\"{{{AI@j{JEj}}}BEC`}\",[]]Aj[\"{{{AI@j{OHb}}}BEC`}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CHh}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CHh}{{AI@j{CAnBCCf}}}}\",[]]Bf[\"{{{AI@j{CAnAILl}}OGdCHlCHl}HIh}\",[]]Bd[\"{{{AI@j{CAnMn}}OGdCHlCHl}HIh}\",[]]Bf[\"{{{AI@j{CAnAILn}}OGdCHlCHl}HIh}\",[]]Bd[\"{{{AI@j{CAnN`}}OGdCHlCHl}HIh}\",[]]Aj[\"{{{AI@j{AILh}}}LDn}\",[]]Bc[\"{{{AI@j{ABLl}}}{{LEh{LEl}}}}\",[]]Aa[\"{BGBjB@C`}\",[]]Aa[\"{BEKfB@C`}\",[]]A`[\"{CJlB@C`}\",[]]A`[\"{JI`B@C`}\",[]]Aa[\"{BDLbB@C`}\",[]]Di[\"{{{AI@j{AJ@f}}}{{`{{LDh{}{{LEj{{LFb{{LEh{LGn}}B@Gl}}}}}}CL`CLf}}}}\",[]]Bn[\"{{{AI@j{AJ@h}}}{{LFb{{LEh{LH`}}B@Bd}}}}\",[]]n[\"{OjLAl}\",[]]o[\"{JIjLAl}\",[]]Am[\"{{{AI@j{CAnAILj}}}OJh}\",[]]Aj[\"{{{AI@j{AHGd}}}LAl}\",[]]Aj[\"{{{AI@j{AHGf}}}LAl}\",[]]A`[\"{AI@jLGl}\",[]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bd[\"{{{AI@j{BFHb}}}{{LEh{AILh}}}}\",[]]Bn[\"{{{AI@j{CAnB@A`}}CHj}{{AI@j{CAnB@A`}}}}\",[]]Bn[\"{{{AI@j{CAnB@Ad}}CHj}{{AI@j{CAnB@Ad}}}}\",[]]A`[\"{BGBjCHj}\",[]]A`[\"{BEKfCHj}\",[]]o[\"{CJlCHj}\",[]]o[\"{JI`CHj}\",[]]A`[\"{AHE`LEh}\",[]]Aa[\"{ABObAI@j}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Aa[\"{BBEbABJj}\",[]]A`[\"{LCdBBE`}\",[]]Aa[\"{BCAbAIMd}\",[]]Aa[\"{BCAdAIMf}\",[]]10Bg[\"{{{AI@j{CAnc}}LAl}B@Bn{NfJIh}}\",[\"\"]]Bg[\"{{{AI@j{CAnc}}LAl}B@C`{NfJIh}}\",[\"\"]]o[\"{{}BCBf}\",[]]o[\"{{}BCBh}\",[]]A`[\"{CHlBGMj}\",[]]Cd[\"{{{AI@j{CHf}}}{{LFf{AO@dc}}}{}}\",[\"FromStr::Err\"]]o[\"{CHjLGn}\",[]]o[\"{CHjLH`}\",[]]Al[\"{CHl{{LFb{LGnBFGl}}}}\",[]]Al[\"{CHl{{LFb{LH`BFGn}}}}\",[]]Aa[\"{BFFfAO@n}\",[]]Aa[\"{BHAhBADf}\",[]]Aa[\"{BFFhAO@n}\",[]]Aa[\"{BHAjBADf}\",[]]Af[\"{{}{{LEh{Ab}}}}\",[]]0000Aj[\"{{{AI@j{AILj}}}CMf}\",[]]Bo[\"{{{AI@j{CAnBEHl}}ABJj}{{AI@j{CAnBEHl}}}}\",[]]Bo[\"{{{AI@j{CAnBEHn}}ABJj}{{AI@j{CAnBEHn}}}}\",[]]Ao[\"{{{Nd{AILl}}}{{Nd{Mj}}}}\",[]]Am[\"{{{Nd{Mn}}}{{Nd{Mj}}}}\",[]]An[\"{{{Nd{JEh}}}{{Nd{Mj}}}}\",[]]An[\"{{{Nd{OH`}}}{{Nd{Mj}}}}\",[]]Ao[\"{{{Nd{AILn}}}{{Nd{Mj}}}}\",[]]Am[\"{{{Nd{N`}}}{{Nd{Mj}}}}\",[]]An[\"{{{Nd{JEj}}}{{Nd{Mj}}}}\",[]]An[\"{{{Nd{OHb}}}{{Nd{Mj}}}}\",[]]Aj[\"{{{AI@j{BFHb}}}CMf}\",[]]Bo[\"{{{AI@j{CAnBFNn}}ABJj}{{AI@j{CAnBFNn}}}}\",[]]Bo[\"{{{AI@j{CAnBFO`}}ABJj}{{AI@j{CAnBFO`}}}}\",[]]Bc[\"{{{AI@j{AILd}}}{{LEh{LDl}}}}\",[]]Bc[\"{{{AI@j{AILh}}}{{LEh{LDl}}}}\",[]]Bc[\"{{{AI@j{ABKf}}}{{LEh{LDl}}}}\",[]]Bc[\"{{{AI@j{ABKh}}}{{LEh{LDl}}}}\",[]]A`[\"{AHEnLEh}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Bc[\"{{{AI@j{AHEf}}}{{LEh{LAl}}}}\",[]]Am[\"{{{AI@j{AODd}}LAl}HIh}\",[]]Aj[\"{{{AI@j{AILh}}}OHf}\",[]]Bg[\"{{{AI@j{AJ@f}}}{{LFb{C@hB@Al}}}}\",[]]Bg[\"{{{AI@j{AJ@h}}}{{LFb{C@hB@Bd}}}}\",[]]A`[\"{BACnLEh}\",[]]A`[\"{BAD`LEh}\",[]]A`[\"{AHE`LEh}\",[]]A`[\"{AO@`LEh}\",[]]Ck[\"{{{AI@j{CAnBBAn}}{LEh{{JJb{Md}}}}}{{AI@j{CAnBBAn}}}}\",[]]Ck[\"{{{AI@j{CAnBBB`}}{LEh{{JJb{Md}}}}}{{AI@j{CAnBBB`}}}}\",[]]A`[\"{BEBnLEh}\",[]]A`[\"{BEC`LEh}\",[]]Ac[\"{AI@jc{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Ao[\"{c{{LFb{e}}}{}{}}\",[\"U\",\"T\"]]000000000000000000000000000000000000000000000Al[\"{CHl{{LFb{LGnBFGl}}}}\",[]]Al[\"{LAl{{LFb{LGnBFGl}}}}\",[]]2Al[\"{HIf{{LFb{LGnBFGl}}}}\",[]]333333333333333Aj[\"{ABJj{{LFb{AOAn}}}}\",[]]444444Ai[\"{CHl{{LFb{AHF`}}}}\",[]]55555555555555555555555555Bb[\"{{{Ml{B@@l}}}{{LFb{BDKb}}}}\",[]]Aj[\"{B@@l{{LFb{BDKb}}}}\",[]]77Bb[\"{{{Ml{B@Fl}}}{{LFb{BDKf}}}}\",[]]Aj[\"{B@Fl{{LFb{BDKf}}}}\",[]]999999999999999999Al[\"{CHl{{LFb{LH`BFGn}}}}\",[]]Al[\"{HIf{{LFb{LH`BFGn}}}}\",[]]Al[\"{LAl{{LFb{LH`BFGn}}}}\",[]]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Bm[\"{B@@l{{LFb{BDKdc}}}{}}\",[\"TryFrom::Error\"]]Ce[\"{{{Ml{B@@l}}}{{LFb{BDKdc}}}{}}\",[\"TryFrom::Error\"]]Ao[\"{c{{LFb{e}}}{}{}}\",[\"U\",\"T\"]]Ce[\"{{{Ml{B@Fl}}}{{LFb{BDKhc}}}{}}\",[\"TryFrom::Error\"]]Bm[\"{B@Fl{{LFb{BDKhc}}}{}}\",[\"TryFrom::Error\"]]2222222222222222222222222222Aj[\"{{}{{LFb{c}}}{}}\",[\"U\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cd[\"{{{A@b{{AI@j{CAnc}}}}{AI@j{CAnOFb}}}CKl{}}\",[\"F\"]]000000000Cc[\"{{{AI@j{BBEj}}AJB`{AI@j{ABOb}}}{{LFd{HIh}}}}\",[]]Bk[\"{{{AI@j{BFMl}}B@Bn}{{LFb{HIhAIMj}}}}\",[]]Bk[\"{{{AI@j{BFMn}}B@C`}{{LFb{HIhAIMl}}}}\",[]]0Bk[\"{{{AI@j{BGMj}}B@C`}{{LFb{HIhAIMl}}}}\",[]]Ak[\"{{{AI@j{AILh}}}ABIf}\",[]]Bi[\"{{{AI@j{CAnB@H`}}}{{LFb{LGnJG`}}}}\",[]]Bi[\"{{{AI@j{CAnB@H`}}}{{LFb{CLbJG`}}}}\",[]]Bh[\"{{{AI@j{CAnB@H`}}}{{LFb{NjJG`}}}}\",[]]Bj[\"{{{AI@j{CAnB@H`}}}{{LFb{ABMlJG`}}}}\",[]]Bf[\"{{{AI@j{CAnB@H`}}}{{LFh{LH`}}}}\",[]]Bf[\"{{{AI@j{CAnB@H`}}}{{LFh{CLd}}}}\",[]]Be[\"{{{AI@j{CAnB@H`}}}{{LFh{Nl}}}}\",[]]Bg[\"{{{AI@j{CAnB@H`}}}{{LFh{ABMn}}}}\",[]]Aa[\"{AO@dBFGj}\",[]]Bc[\"{{{AI@j{AILl}}}{{Nd{AILl}}}}\",[]]Ba[\"{{{AI@j{Mn}}}{{Nd{AILl}}}}\",[]]Bb[\"{{{AI@j{JEh}}}{{Nd{AILl}}}}\",[]]Bb[\"{{{AI@j{OH`}}}{{Nd{AILl}}}}\",[]]Bc[\"{{{AI@j{AILn}}}{{Nd{AILn}}}}\",[]]Ba[\"{{{AI@j{N`}}}{{Nd{AILn}}}}\",[]]Bb[\"{{{AI@j{JEj}}}{{Nd{AILn}}}}\",[]]Bb[\"{{{AI@j{OHb}}}{{Nd{AILn}}}}\",[]]A`[\"{ABOdCHl}\",[]]An[\"{{{AI@j{CAnAILj}}}AHEf}\",[]]A`[\"{ABOfCHl}\",[]]C`[\"{{{AI@j{CAnB@Bn}}}{{AI@j{CAn{KOh{Md}}}}}}\",[]]C`[\"{{{AI@j{CAnB@C`}}}{{AI@j{CAn{KOh{Md}}}}}}\",[]]Ah[\"{Md{{LEh{B@Ch}}}}\",[]]Ah[\"{Md{{LEh{B@Cj}}}}\",[]]Ah[\"{Md{{LEh{B@Cl}}}}\",[]]A`[\"{ABMlCLb}\",[]]A`[\"{ABMnCLd}\",[]]Bi[\"{AILd{{LFb{{LAj{AILhBCCn}}AILd}}}}\",[]]o[\"{CLbCMf}\",[]]o[\"{CLdCMf}\",[]]Aj[\"{{{AI@j{AILj}}}CMf}\",[]]21Aj[\"{{{AI@j{ABKf}}}CMf}\",[]]Aj[\"{{{AI@j{ABKh}}}CMf}\",[]]Bn[\"{{{AI@j{CAnB@G`}}CMf}{{AI@j{CAnB@G`}}}}\",[]]Bn[\"{{{AI@j{CAnB@Gd}}CMf}{{AI@j{CAnB@Gd}}}}\",[]]Bl[\"{{{AI@j{OIh}}OGd}{{A@b{{Nd{AIKb}}}}}}\",[]]Bm[\"{{{AI@j{B@Gn}}OGd}{{A@b{{Nd{AIKb}}}}}}\",[]]Bm[\"{{{AI@j{AOCh}}OGd}{{A@b{{Nd{AIKb}}}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Ak[\"{{{AI@j{AILh}}}ABLj}\",[]]Bc[\"{{{AI@j{AILh}}AJ@lAIO`}ABLl}\",[]]Ce[\"{{{AI@j{CAnAILj}}AHEnAIObOGd}{{LFb{LEnAHGj}}}}\",[]]43Bm[\"{{{AI@j{CAnAILj}}LEn}{{LFb{HIhAIL`}}}}\",[]]E`[\"{{{A@b{{AI@j{CAnBDGh}}}}{AI@j{CAnOFb}}}{{CKl{{LEh{c}}}}}{}}\",[\"Stream::Item\"]]Ef[\"{{{A@b{{AI@j{CAnAIOj}}}}{AI@j{CAnOFb}}{AI@j{CAn{KOh{Md}}}}}{{CKl{{LFd{LAl}}}}}}\",[]]E`[\"{{{A@b{{AI@j{CAnAIOj}}}}{AI@j{CAnOFb}}{AI@j{CAnOIb}}}{{CKl{{LFd{HIh}}}}}}\",[]]Ec[\"{{{AI@j{CAnAIOj}}{AI@j{CAnOFb}}{AI@j{CAn{KOh{Md}}}}}{{CKl{{LFb{LAlAHHh}}}}}}\",[]]Fg[\"{{{AI@j{CAnBB@f}}{AI@j{CAnOFb}}{AI@j{CAn{KOh{AIMn}}}}{AI@j{CAn{KOh{ABMh}}}}}{{CKl{{LFd{LAl}}}}}}\",[]]Dn[\"{{{A@b{{AI@j{CAnAHHn}}}}{AI@j{ABOb}}{AI@j{CAnOFb}}}{{CKl{{LFd{HIh}}}}}}\",[]];:Cd[\"{{{AI@j{CAnBBAn}}{Ml{OFn}}}{{AI@j{CAnBBAn}}}}\",[]]Cd[\"{{{AI@j{CAnBBB`}}{Ml{OG`}}}{{AI@j{CAnBBB`}}}}\",[]]Cj[\"{{{AI@j{B@Gb}}CHjB@Bn{AI@j{{KOh{Md}}}}}{{JJb{Md}}}}\",[]]Cj[\"{{{AI@j{BDKf}}CHjB@Bn{AI@j{{KOh{Md}}}}}{{JJb{Md}}}}\",[]]Cj[\"{{{AI@j{B@Gf}}CHjB@C`{AI@j{{KOh{Md}}}}}{{JJb{Md}}}}\",[]]Cj[\"{{{AI@j{BDKh}}CHjB@C`{AI@j{{KOh{Md}}}}}{{JJb{Md}}}}\",[]]Cj[\"{{{AI@j{BGHf}}CHjB@Bl{AI@j{{KOh{Md}}}}}{{JJb{Md}}}}\",[]]Bb[\"{LAl{{LAj{LAl{LEh{LAl}}}}}}\",[]]00000Aj[\"{{{AI@j{AILh}}}LAl}\",[]]A`[\"{AI@jLGj}\",[]]00000000000000000000000000000000000000000000000000000000000Ce[\"{{{AI@j{CAnB@G`}}{Ml{BECb}}}{{AI@j{CAnB@G`}}}}\",[]]Ce[\"{{{AI@j{CAnB@Gd}}{Ml{BECd}}}{{AI@j{CAnB@Gd}}}}\",[]]A`[\"{BGBjJHf}\",[]]o[\"{B@G`Ml}\",[]]o[\"{B@GdMl}\",[]]Aj[\"{{{AI@j{ABJn}}}HIh}\",[]]Ck[\"{{{AI@j{CAnAJ@f}}{AI@j{{KOh{Md}}}}}{{LFb{HIhAJBb}}}}\",[]]n[\"{{}LAl}\",[]]Ak[\"{{{AI@j{AILh}}}AHCj}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CMf}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CMf}{{AI@j{CAnBCCf}}}}\",[]]Bi[\"{{{AI@j{CAn}}}{{AI@j{CAnc}}}{}}\",[\"T\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bc[\"{{AI@j{AI@j{CAnc}}}HIh{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cc[\"{{{AI@j{CAnAILj}}OGdLEnLH`}{{LFb{HIhBB@l}}}}\",[]]A`[\"{AHE`CMf}\",[]]B`[\"{{AI@j{AI@j{c}}}CMf{}}\",[\"K\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Aa[\"{BC@dBEKb}\",[]]A`[\"{BDGlLGn}\",[]]Aa[\"{BC@hBEKd}\",[]]A`[\"{BDH`LH`}\",[]]o[\"{LClLH`}\",[]]o[\"{OInLH`}\",[]]Aa[\"{BC@dAIN`}\",[]]Aa[\"{BC@hAINb}\",[]]o[\"{LGnCHl}\",[]]o[\"{LH`CHl}\",[]]Aj[\"{{{AI@j{AILj}}}CMf}\",[]]Aj[\"{{{AI@j{BACh}}}CMf}\",[]]Bd[\"{{{AI@j{BB@f}}}{{LFd{AJ@l}}}}\",[]]Bd[\"{{{AI@j{ABJn}}}{{LFd{AJ@l}}}}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]Cb[\"{{{AI@j{BCAl}}{AI@j{AJ@d}}CHl}{{Ml{AODd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CMf}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CMf}{{AI@j{CAnBCCf}}}}\",[]]Bg[\"{{{AI@j{AILh}}LEl}{{LEh{AHHb}}}}\",[]]Bj[\"{{{AI@j{CAnAILj}}LEn}{{LEh{AHHd}}}}\",[]]Aa[\"{AHCfAHHd}\",[]]Db[\"{{{A@b{{AI@j{CAnAJ@f}}}}{AI@j{CAnOFb}}}{{CKl{{LFd{HIh}}}}}}\",[]]00Eg[\"{{{A@b{{AI@j{CAnAJ@f}}}}{AI@j{CAnOFb}}{AI@j{{KOh{Md}}}}}{{CKl{{LFb{LAlAJBb}}}}}}\",[]]Ec[\"{{{A@b{{AI@j{CAnAJ@f}}}}{AI@j{CAnOFb}}{AI@j{{KOh{Md}}}}}{{CKl{{LFd{LAl}}}}}}\",[]]0Bm[\"{{{AI@j{JIl}}{AI@j{CKb}}}{{LFd{HIh}}}}\",[]]Cd[\"{{{AI@j{CAnAIOj}}LAl}{{LFb{{LEh{JE`}}AHHh}}}}\",[]]Cd[\"{{{AI@j{CAnBF@h}}LAl}{{LFb{{LEh{JE`}}AHHh}}}}\",[]]Cn[\"{{{AI@j{CAnAIOj}}{AI@j{CAn{KOh{Md}}}}}{{LFb{HIhBBDl}}}}\",[]]Bj[\"{{{AI@j{CKd}}AIO`}{{LFb{HIhBEJj}}}}\",[]]Bn[\"{{{AI@j{CAnAIOd}}OGd}{{AI@j{CAnAIOd}}}}\",[]]Bn[\"{{{AI@j{CAnAIOf}}OGd}{{AI@j{CAnAIOf}}}}\",[]]A`[\"{BBEbADf}\",[]]o[\"{JIjCHl}\",[]]o[\"{{}AJ@l}\",[]]0o[\"{{}AI@j}\",[]]Bj[\"{{ABKf{Ml{B@G`}}}{{LFb{AILdBC@j}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Bh[\"{{{AI@j{AHE`}}AJ@l}{{LFf{AHI`}}}}\",[]]A`[\"{AHHbCHh}\",[]]Aj[\"{{{AI@j{AILj}}}CHh}\",[]]A`[\"{AHHdCHh}\",[]]Ce[\"{{{AI@j{CAnAIOd}}{LEh{LGj}}}{{AI@j{CAnAIOd}}}}\",[]]Ce[\"{{{AI@j{CAnAIOf}}{LEh{LGj}}}{{AI@j{CAnAIOf}}}}\",[]]Aa[\"{ABNnAJ@l}\",[]]Aa[\"{ABO`AJ@l}\",[]]Aa[\"{ABObAJ@l}\",[]]n[\"{OjCHh}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CHh}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CHh}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHE`CHh}\",[]]Bo[\"{{{AI@j{CAnBCCd}}ABJj}{{AI@j{CAnBCCd}}}}\",[]]Bo[\"{{{AI@j{CAnBCCf}}ABJj}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHE`LEh}\",[]]k[\"{{}}\",[]]00000000000Bh[\"{ABKfc{}}\",[\"IntoFuture::IntoFuture\"]]1A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]n[\"{OjLAl}\",[]]Ao[\"{{AI@jc}{{OGj{c}}}{}}\",[\"S\"]]0C`[\"{{{AI@j{CAnAILl}}OGdCHlCMf{LEh{CHl}}}HIh}\",[]]Bn[\"{{{AI@j{CAnMn}}OGdCHlCMf{LEh{CHl}}}HIh}\",[]]C`[\"{{{AI@j{CAnAILn}}OGdCHlCMf{LEh{CHl}}}HIh}\",[]]Bn[\"{{{AI@j{CAnN`}}OGdCHlCMf{LEh{CHl}}}HIh}\",[]]Bk[\"{{{AI@j{CAnJIl}}OGd{AI@j{BCAl}}}HIh}\",[]]A`[\"{BEBnLEh}\",[]]A`[\"{BEC`LEh}\",[]]Bn[\"{{{AI@j{LGn}}{AI@j{LGn}}}{{LEh{ABLn}}}}\",[]]Bn[\"{{{AI@j{LEl}}{AI@j{LEl}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{AOAn}}{AI@j{AOAn}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{B@Bn}}{AI@j{B@Bn}}}{{LEh{ABLn}}}}\",[]]Bn[\"{{{AI@j{CLb}}{AI@j{CLb}}}{{LEh{ABLn}}}}\",[]]Bl[\"{{{AI@j{Nj}}{AI@j{Nj}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{ABMl}}{AI@j{ABMl}}}{{LEh{ABLn}}}}\",[]]Bn[\"{{{AI@j{LH`}}{AI@j{LH`}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{BED`}}{AI@j{BED`}}}{{LEh{ABLn}}}}\",[]]Bn[\"{{{AI@j{LEn}}{AI@j{LEn}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{AHHj}}{AI@j{AHHj}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{BAG`}}{AI@j{BAG`}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{AJBd}}{AI@j{AJBd}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{AOB`}}{AI@j{AOB`}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{BDHh}}{AI@j{BDHh}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{BECl}}{AI@j{BECl}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{B@C`}}{AI@j{B@C`}}}{{LEh{ABLn}}}}\",[]]Bn[\"{{{AI@j{CLd}}{AI@j{CLd}}}{{LEh{ABLn}}}}\",[]]Bl[\"{{{AI@j{Nl}}{AI@j{Nl}}}{{LEh{ABLn}}}}\",[]]C`[\"{{{AI@j{ABMn}}{AI@j{ABMn}}}{{LEh{ABLn}}}}\",[]]Be[\"{{{AI@j{AILh}}}{{ABMd{AHGn}}}}\",[]]Bk[\"{{{AI@j{AILj}}LEn}{{LFb{AIObAIL`}}}}\",[]]Df[\"{{{AI@j{CAnAIOj}}{AI@j{CAn{KOh{JDn}}}}}{{LFb{{LEh{LAl}}AHHh}}}}\",[]]Cc[\"{{{AI@j{CAnAIOj}}LAl}{{LFb{{A@h{Md}}BBDn}}}}\",[]]Bb[\"{{{AI@j{CAnAILj}}ABMn}AIOl}\",[]]Aj[\"{{{AI@j{AHFf}}}LAl}\",[]]Aj[\"{{{AI@j{AHFh}}}LAl}\",[]]Bb[\"{{{AI@j{CAnAILj}}ABMn}AJ@h}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CHl}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CHl}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHE`LEh}\",[]]A`[\"{BACnLEh}\",[]]A`[\"{BAD`LEh}\",[]]Ce[\"{{{AI@j{CAnB@G`}}{Ml{AJAd}}}{{AI@j{CAnB@G`}}}}\",[]]Ce[\"{{{AI@j{CAnB@Gd}}{Ml{AJAf}}}{{AI@j{CAnB@Gd}}}}\",[]]Ce[\"{{{AI@j{CAnB@A`}}{Ml{AJAl}}}{{AI@j{CAnB@A`}}}}\",[]]Ce[\"{{{AI@j{CAnB@Ad}}{Ml{AJAn}}}{{AI@j{CAnB@Ad}}}}\",[]]n[\"{OjCHl}\",[]]Bn[\"{{{AI@j{CAnBEHl}}CHh}{{AI@j{CAnBEHl}}}}\",[]]Bn[\"{{{AI@j{CAnBEHn}}CHh}{{AI@j{CAnBEHn}}}}\",[]]Ak[\"{{{AI@j{AILh}}}BFHb}\",[]]Ai[\"{{{Ml{B@Gb}}}B@G`}\",[]]Ai[\"{{{Ml{B@Gf}}}B@Gd}\",[]]Aj[\"{{BCBfc}BCBfABNd}\",[\"\"]]Aj[\"{{BCBhc}BCBhABNd}\",[\"\"]]Bm[\"{{{AI@j{CAnAJ@f}}JDn}{{LFb{HIhAJBb}}}}\",[]]n[\"{{}LDl}\",[]]o[\"{OF`OF`}\",[]]0000Bd[\"{{{AI@j{BFMl}}}{{LEh{ABJj}}}}\",[]]Bd[\"{{{AI@j{BFMn}}}{{LEh{ABJj}}}}\",[]]Bd[\"{{{AI@j{BGMj}}}{{LEh{ABJj}}}}\",[]]Bd[\"{{{AI@j{BGNd}}}{{LEh{ABJj}}}}\",[]]Bd[\"{{{AI@j{AILh}}}{{LEh{BC@j}}}}\",[]]Ck[\"{{{AI@j{ABJn}}B@A`AJ@l{AI@j{CHf}}}{{LFb{AILdB@Bh}}}}\",[]]Ak[\"{{{AI@j{B@Fh}}}ABJj}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]An[\"{{AIOhCMf}{{LFf{LAl}}}}\",[]]Cj[\"{{{AI@j{OIj}}}{{LEh{{LAj{{Nd{AHFf}}{Nd{AHGd}}}}}}}}\",[]]Ck[\"{{{AI@j{AJAh}}}{{LEh{{LAj{{Nd{AHFf}}{Nd{AHGd}}}}}}}}\",[]]Cj[\"{{{AI@j{OIl}}}{{LEh{{LAj{{Nd{AHFh}}{Nd{AHGf}}}}}}}}\",[]]Ck[\"{{{AI@j{AJAj}}}{{LEh{{LAj{{Nd{AHFh}}{Nd{AHGf}}}}}}}}\",[]]A`[\"{BFFfA@h}\",[]]A`[\"{BHAhA@h}\",[]]A`[\"{BFFhA@h}\",[]]A`[\"{BHAjA@h}\",[]]An[\"{{{AI@j{CAnBFMl}}}B@Bn}\",[]]An[\"{{{AI@j{CAnBFMn}}}B@C`}\",[]]An[\"{{{AI@j{CAnBGMj}}}B@C`}\",[]]An[\"{{{AI@j{CAnBGNd}}}B@C`}\",[]]Ak[\"{{{AI@j{BBEj}}}B@Dn}\",[]]Ba[\"{{{AI@j{CAnAILj}}BCA`}HIh}\",[]]Bo[\"{{{AI@j{CAnABK`}}BDHhBACh}{{LEh{BCA`}}}}\",[]]B`[\"{{{AI@j{OIj}}B@BnCLb}CJh}\",[]]Bn[\"{{{AI@j{B@Gb}}CHjB@Bn}{{LFb{CJhBEKj}}}}\",[]]Ba[\"{{{AI@j{AJAh}}B@BnCLb}CJh}\",[]]Bn[\"{{{AI@j{BDKf}}CHjB@Bn}{{LFb{CJhBEKj}}}}\",[]]B`[\"{{{AI@j{OIl}}B@C`CLd}CJj}\",[]]Bn[\"{{{AI@j{B@Gf}}CHjB@C`}{{LFb{CJjBEL`}}}}\",[]]Ba[\"{{{AI@j{AJAj}}B@C`CLd}CJj}\",[]]Bn[\"{{{AI@j{BDKh}}CHjB@C`}{{LFb{CJjBEL`}}}}\",[]]Bn[\"{{{AI@j{BGHf}}CHjB@Bl}{{LFb{CJjBEL`}}}}\",[]]Aj[\"{{}{{OId{c}}}{}}\",[\"T\"]]0A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]Bn[\"{{{AI@j{CAnB@G`}}LAl}{{AI@j{CAnB@G`}}}}\",[]]Bn[\"{{{AI@j{CAnB@Gd}}LAl}{{AI@j{CAnB@Gd}}}}\",[]]Aj[\"{{{AI@j{BB@f}}}CMf}\",[]]0Aj[\"{{{AI@j{BBEj}}}CMf}\",[]]Bk[\"{{{AI@j{AILj}}LEn}{{LFb{AHEnAIL`}}}}\",[]]Cb[\"{{{AI@j{BCAl}}{AI@j{AIOh}}CHl}{{Ml{AODd}}}}\",[]]Ak[\"{{{AI@j{ABKf}}}B@Bn}\",[]]Ak[\"{{{AI@j{ABKh}}}B@C`}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Bf[\"{{{AI@j{CAnAILj}}}{{LEh{OGd}}}}\",[]]Ce[\"{{{AI@j{CAnBCCd}}{Ml{AOBl}}}{{AI@j{CAnBCCd}}}}\",[]]Ce[\"{{{AI@j{CAnBCCf}}{Ml{AOBn}}}{{AI@j{CAnBCCf}}}}\",[]]43A`[\"{ABNnLEh}\",[]]A`[\"{ABO`LEh}\",[]]A`[\"{ABObLEh}\",[]]Ai[\"{{{AI@j{OJh}}}LAl}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]Bo[\"{{{AI@j{CAnBGMj}}ABJj}{{AI@j{CAnBGMj}}}}\",[]]Bo[\"{{{AI@j{CAnBGNd}}ABJj}{{AI@j{CAnBGNd}}}}\",[]]Bj[\"{{{AI@j{AJ@f}}C@h}{{LFb{HIhB@Al}}}}\",[]]Bm[\"{{{AI@j{CAnAJ@h}}C@h}{{LFb{HIhB@Bd}}}}\",[]]>=A`[\"{JIjAODb}\",[]]A`[\"{AO@fJIj}\",[]]Bi[\"{{{Ml{B@@l}}JIn}{{LFb{BDKbBFGd}}}}\",[]]Bi[\"{{{Ml{B@Fl}}JIn}{{LFb{BDKfBFGd}}}}\",[]]Bi[\"{{{Ml{B@@l}}JIn}{{LFb{BDKdBFGf}}}}\",[]]Bi[\"{{{Ml{B@Fl}}JIn}{{LFb{BDKhBFGf}}}}\",[]]Co[\"{{{AI@j{CAnAJ@f}}{AI@j{CAn{KOh{JDn}}}}}{{LFb{OKdAJBb}}}}\",[]]Co[\"{{{AI@j{CAnAJ@h}}{AI@j{CAn{KOh{JDn}}}}}{{LFb{OKfAJBd}}}}\",[]]Aj[\"{{{AI@j{AILj}}}CMf}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]A`[\"{AHE`CMf}\",[]]E`[\"{{{AI@j{CAnBBAn}}c}{{AI@j{CAnBBAn}}}{{A`{}{{LEj{{Nd{BFMl}}}}}}CL`CLf}}\",[\"F\"]]E`[\"{{{AI@j{CAnBBB`}}c}{{AI@j{CAnBBB`}}}{{A`{}{{LEj{{Nd{BFMn}}}}}}CL`CLf}}\",[\"F\"]]Bj[\"{{{AI@j{BB@f}}}{{A@b{{Nd{AHHn}}}}}}\",[]]n[\"{OjCHl}\",[]]Aa[\"{AODbAHFj}\",[]]76Aa[\"{AJ@`ABKf}\",[]]Aa[\"{AJ@bABKh}\",[]]Cf[\"{{{AI@j{CAnBEFn}}{LEh{ABJj}}}{{AI@j{CAnBEFn}}}}\",[]]Cf[\"{{{AI@j{CAnBEG`}}{LEh{ABJj}}}{{AI@j{CAnBEG`}}}}\",[]]9;:An[\"{{{AI@j{AODd}}ABJj}HIh}\",[]]B`[\"{{{AI@j{CAnAILl}}CHh}HIh}\",[]]An[\"{{{AI@j{CAnMn}}CHh}HIh}\",[]]Ao[\"{{{AI@j{CAnJEh}}CHh}HIh}\",[]]Ao[\"{{{AI@j{CAnOH`}}CHh}HIh}\",[]]B`[\"{{{AI@j{CAnAILn}}CHh}HIh}\",[]]An[\"{{{AI@j{CAnN`}}CHh}HIh}\",[]]Ao[\"{{{AI@j{CAnJEj}}CHh}HIh}\",[]]Ao[\"{{{AI@j{CAnOHb}}CHh}HIh}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]10Bh[\"{{{AI@j{AILh}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bg[\"{{{AI@j{OIj}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bh[\"{{{AI@j{AJAh}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bg[\"{{{AI@j{OIl}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bh[\"{{{AI@j{AJAj}}}{{LEh{{Nd{Mj}}}}}}\",[]]Dm[\"{{{AI@j{CAnAIOj}}{AI@j{CAnOFb}}{AI@j{CAnOIb}}}{{CKl{{LFb{HIhAHHh}}}}}}\",[]]Db[\"{{{A@b{{AI@j{CAnAJ@f}}}}{AI@j{CAnOFb}}}{{CKl{{LFd{HIh}}}}}}\",[]]Db[\"{{{AI@j{CAnAILj}}OGdB@Dn{AI@j{CAn{A@h{Md}}}}}{{LEh{ABO`}}}}\",[]]Cf[\"{{{AI@j{CAnBCCd}}{AI@j{CHf}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{AI@j{CHf}}}{{AI@j{CAnBCCf}}}}\",[]]Ak[\"{{{AI@j{AILh}}}B@F`}\",[]]Bj[\"{{{AI@j{AILh}}JDn}{{LFb{HIhBECn}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CMf}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CMf}{{AI@j{CAnBCCf}}}}\",[]]Ai[\"{{{AI@j{OFn}}}LAl}\",[]]Ai[\"{{{AI@j{OG`}}}LAl}\",[]]De[\"{{{Ml{B@Ab}}CHj{AI@j{CHf}}{AI@j{BF@f}}}{{LFb{{Nd{OIj}}B@Bh}}}}\",[]]Bo[\"{{{Ml{B@Gb}}CHj{AI@j{BF@f}}}{{Nd{OIj}}}}\",[]]De[\"{{{Ml{BDKb}}CHj{AI@j{CHf}}{AI@j{BF@f}}}{{LFb{{Nd{OIj}}B@Bh}}}}\",[]]Bo[\"{{{Ml{BDKf}}CHj{AI@j{BF@f}}}{{Nd{OIj}}}}\",[]]De[\"{{{Ml{B@Af}}CHj{AI@j{CHf}}{AI@j{BF@f}}}{{LFb{{Nd{OIl}}B@Bj}}}}\",[]]Bo[\"{{{Ml{B@Gf}}CHj{AI@j{BF@f}}}{{Nd{OIl}}}}\",[]]De[\"{{{Ml{BDKd}}CHj{AI@j{CHf}}{AI@j{BF@f}}}{{LFb{{Nd{OIl}}B@Bj}}}}\",[]]Bo[\"{{{Ml{BDKh}}CHj{AI@j{BF@f}}}{{Nd{OIl}}}}\",[]]De[\"{{{Ml{BGHd}}CHj{AI@j{CHf}}{AI@j{BF@f}}}{{LFb{{Nd{OIl}}B@Bf}}}}\",[]]Bo[\"{{{Ml{BGHf}}CHj{AI@j{BF@f}}}{{Nd{OIl}}}}\",[]]Bm[\"{LAl{{LFb{{LAj{LAl{LEh{LAl}}}}BEOj}}}}\",[]]0Cc[\"{{{AI@j{BECb}}{AI@j{{KOh{Md}}}}}{{Nd{OEf}}}}\",[]]Cc[\"{{{AI@j{BECd}}{AI@j{{KOh{Md}}}}}{{Nd{OEh}}}}\",[]]Bm[\"{{AJ@lBB@hOj}{{LFf{{LAj{ABJlAILf}}}}}}\",[]]Bd[\"{{{AI@j{AILj}}}{{AI@j{OIl}}}}\",[]]A`[\"{AO@fJIj}\",[]]Cb[\"{{{AI@j{AOBl}}CLbAJ@lB@BnOGd}{{LEh{AIOd}}}}\",[]]Cb[\"{{{AI@j{BCBf}}CLbAJ@lB@BnOGd}{{LEh{AIOd}}}}\",[]]Cb[\"{{{AI@j{AOBn}}CLdAJ@lB@C`OGd}{{LEh{AIOf}}}}\",[]]Cb[\"{{{AI@j{BCBh}}CLdAJ@lB@C`OGd}{{LEh{AIOf}}}}\",[]]B`[\"{{{AI@j{CAnAILj}}OGd}HIh}\",[]]Bo[\"{{{AI@j{CAnAILd}}}{{LFb{{Nd{Mj}}BC@j}}}}\",[]]Bh[\"{{{AI@j{AILh}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bg[\"{{{AI@j{OIj}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bh[\"{{{AI@j{AJAh}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bg[\"{{{AI@j{OIl}}}{{LEh{{Nd{Mj}}}}}}\",[]]Bh[\"{{{AI@j{AJAj}}}{{LEh{{Nd{Mj}}}}}}\",[]]o[\"{AIMdMd}\",[]]o[\"{AIMfMd}\",[]]Ai[\"{{{AI@j{CHf}}}CMf}\",[]]Aj[\"{{{AI@j{AILl}}}CHl}\",[]]Ah[\"{{{AI@j{Mn}}}CHl}\",[]]Bn[\"{{{AI@j{CAnAHDh}}CHl}{{AI@j{CAnAHDh}}}}\",[]]Ai[\"{{{AI@j{JEh}}}CHl}\",[]]Bn[\"{{{AI@j{CAnAOAd}}CHl}{{AI@j{CAnAOAd}}}}\",[]]Ai[\"{{{AI@j{OH`}}}CHl}\",[]]Bn[\"{{{AI@j{CAnBAF`}}CHl}{{AI@j{CAnBAF`}}}}\",[]]Aj[\"{{{AI@j{AILn}}}CHl}\",[]]Ah[\"{{{AI@j{N`}}}CHl}\",[]]Bn[\"{{{AI@j{CAnAHDj}}CHl}{{AI@j{CAnAHDj}}}}\",[]]Ai[\"{{{AI@j{JEj}}}CHl}\",[]]Bn[\"{{{AI@j{CAnAOAf}}CHl}{{AI@j{CAnAOAf}}}}\",[]]Ai[\"{{{AI@j{OHb}}}CHl}\",[]]Bn[\"{{{AI@j{CAnBAFb}}CHl}{{AI@j{CAnBAFb}}}}\",[]]Aa[\"{AIOjBF@h}\",[]]Ai[\"{{{AI@j{OIj}}}CMf}\",[]]Aj[\"{{{AI@j{AJAh}}}CMf}\",[]]Aj[\"{{{AI@j{AILj}}}CMf}\",[]]Ai[\"{{{AI@j{OIl}}}CMf}\",[]]Aj[\"{{{AI@j{AJAj}}}CMf}\",[]]Co[\"{{{AI@j{OIj}}B@Bn{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}CMf}\",[]]D`[\"{{{AI@j{AJAh}}B@Bn{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}CMf}\",[]]Co[\"{{{AI@j{OIl}}B@C`{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}CMf}\",[]]D`[\"{{{AI@j{AJAj}}B@C`{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}CMf}\",[]]Bn[\"{{{AI@j{CAnBEHl}}CHh}{{AI@j{CAnBEHl}}}}\",[]]Bn[\"{{{AI@j{CAnBEHn}}CHh}{{AI@j{CAnBEHn}}}}\",[]]Cc[\"{{{AI@j{CAnOIj}}}{{LEh{{OGf{{Nd{AHGd}}}}}}}}\",[]]Cd[\"{{{AI@j{CAnAJAh}}}{{LEh{{OGf{{Nd{AHGd}}}}}}}}\",[]]Cc[\"{{{AI@j{CAnOIl}}}{{LEh{{OGh{{Nd{AHGf}}}}}}}}\",[]]Cd[\"{{{AI@j{CAnAJAj}}}{{LEh{{OGh{{Nd{AHGf}}}}}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]De[\"{{{AI@j{CAnBCCd}}c{AI@j{CHf}}}{{AI@j{CAnBCCd}}}{{JDl{CKb}}}}\",[\"\"]]De[\"{{{AI@j{CAnBCCf}}c{AI@j{CHf}}}{{AI@j{CAnBCCf}}}{{JDl{CKb}}}}\",[\"\"]]Ci[\"{{{AI@j{CAnOIj}}{AI@j{{KOh{Md}}}}}{{LFb{CMfJFn}}}}\",[]]Cj[\"{{{AI@j{CAnAJAh}}{AI@j{{KOh{Md}}}}}{{LFb{CMfJFn}}}}\",[]]Cj[\"{{{AI@j{CAnOIl}}{AI@j{{KOh{Md}}}}}{{LFb{CMfBBEh}}}}\",[]]Ck[\"{{{AI@j{CAnAJAj}}{AI@j{{KOh{Md}}}}}{{LFb{CMfBBEh}}}}\",[]]n[\"{OjCMf}\",[]]Bn[\"{{{AI@j{CAnBCCd}}LGn}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}LH`}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHE`LEh}\",[]]Ca[\"{{{AI@j{CAnAIOj}}}{{LFb{{LEh{LGn}}AIOn}}}}\",[]]Ca[\"{{{AI@j{CAnBF@h}}}{{LFb{{LEh{LGn}}AIOn}}}}\",[]]Ca[\"{{{AI@j{CAnAIOl}}}{{LFb{{LEh{LH`}}B@Bd}}}}\",[]]Ak[\"{{{AI@j{AILd}}}AJ@l}\",[]]Ak[\"{{{AI@j{AILh}}}AJ@l}\",[]]Ak[\"{{{AI@j{ABKf}}}AJ@l}\",[]]Bg[\"{{{AI@j{CKd}}}{{LFb{AJ@lAIKj}}}}\",[]]Ak[\"{{{AI@j{ABKh}}}AJ@l}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]B`[\"{{LGnc}LGn{{CJf{LGn}}}}\",[\"\"]]B`[\"{{LElc}LEl{{CJf{LEl}}}}\",[\"\"]]B`[\"{{LH`c}LH`{{CJf{LH`}}}}\",[\"\"]]B`[\"{{LEnc}LEn{{CJf{LEn}}}}\",[\"\"]]20Ae[\"{{ABJjCHl}ADf}\",[]]Bn[\"{{{AI@j{CAnBCCd}}ADd}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}ADd}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{JIjABJj}\",[]]B`[\"{{}{{AI@j{{KOh{BEOh}}}}}}\",[]]Ao[\"{{AI@j{A@Jn{CAnMd}}}HIh}\",[]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Am[\"{{}{{LEh{{Ml{OIh}}}}}}\",[]]Bn[\"{{{AI@j{CAnBBAn}}CMf}{{AI@j{CAnBBAn}}}}\",[]]Bn[\"{{{AI@j{CAnBBB`}}CMf}{{AI@j{CAnBBB`}}}}\",[]]Aj[\"{{{AI@j{AHGd}}}CHl}\",[]]Aj[\"{{{AI@j{AHGf}}}CHl}\",[]]A`[\"{ABMhLEh}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]10Bf[\"{{{AI@j{CHf}}}{{LFf{CHlBAFd}}}}\",[]]Bm[\"{{{AI@j{ABJn}}{Nd{BB@f}}}{{LFd{HIh}}}}\",[]]Ai[\"{AILf{{LFf{HIh}}}}\",[]]Ci[\"{{{AI@j{OIf}}BB@hBAFn{AI@j{Oj}}}{{LAj{AJ@lABJl}}}}\",[]]Cb[\"{{{AI@j{CAnAILj}}LEnAIOb}{{LFb{AIObBEJl}}}}\",[]]Am[\"{{{AI@j{AILh}}CHl}HIh}\",[]]B`[\"{{{AI@j{CAnAILj}}CHl}HIh}\",[]]A`[\"{BBE`CMf}\",[]]B`[\"{{{AI@j{CAnJIj}}BBEb}HIh}\",[]]Aa[\"{AODbAHFj}\",[]]Bm[\"{{{AI@j{OIh}}AHI`}{{LFd{{Nd{BB@f}}}}}}\",[]]Bn[\"{{{AI@j{B@Gn}}AHI`}{{LFd{{Nd{BB@f}}}}}}\",[]]Bn[\"{{{AI@j{AOCh}}AHI`}{{LFd{{Nd{BB@f}}}}}}\",[]]Ci[\"{{{AI@j{CAnOIj}}{AI@j{CAn{A@h{Md}}}}}{{LEh{CJh}}}}\",[]]Cj[\"{{{AI@j{CAnAJAh}}{AI@j{CAn{A@h{Md}}}}}{{LEh{CJh}}}}\",[]]Ci[\"{{{AI@j{CAnOIl}}{AI@j{CAn{A@h{Md}}}}}{{LEh{CJj}}}}\",[]]Cj[\"{{{AI@j{CAnAJAj}}{AI@j{CAn{A@h{Md}}}}}{{LEh{CJj}}}}\",[]]Cb[\"{{{AI@j{ABNf}}HIfAJAbABJj}{{LFb{HIhBCBn}}}}\",[]]Cb[\"{{{AI@j{BABh}}HIfAJAbABJj}{{LFb{HIhBCBn}}}}\",[]]Cb[\"{{{AI@j{B@E`}}HIfAJAbABJj}{{LFb{HIhBCBn}}}}\",[]]Cb[\"{{{AI@j{ABNh}}HIfAJAbABJj}{{LFb{HIhBCC`}}}}\",[]]Cb[\"{{{AI@j{BABj}}HIfAJAbABJj}{{LFb{HIhBCC`}}}}\",[]]Cb[\"{{{AI@j{B@Eb}}HIfAJAbABJj}{{LFb{HIhBCC`}}}}\",[]]Al[\"{{}{{LFb{B@@nBFGf}}}}\",[]]Bm[\"{{{AI@j{AILh}}LEl}{{LEh{{Nd{AILl}}}}}}\",[]]Bo[\"{{{AI@j{AILj}}LEn}{{LEh{{AI@j{AILn}}}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Aj[\"{{{AI@j{AILh}}}HIh}\",[]]Am[\"{{{AI@j{CAnAILj}}}HIh}\",[]]Be[\"{{{AI@j{AIK`}}}{{LFb{OjJFh}}}}\",[]]Bg[\"{{{AI@j{AIK`}}}{{LFb{AHE`JFh}}}}\",[]]Be[\"{{{AI@j{AIK`}}}{{LFb{OlJFh}}}}\",[]]Be[\"{{{AI@j{AIK`}}}{{LFb{OnJFh}}}}\",[]]Be[\"{{{AI@j{AIK`}}}{{LFb{NhJFh}}}}\",[]]Bg[\"{{{AI@j{AIK`}}}{{LFb{ABIlJFh}}}}\",[]]Ak[\"{{{AI@j{BBEj}}}B@Dn}\",[]]Cf[\"{{{AI@j{CAnBCCd}}{LEh{AOAn}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{LEh{AOB`}}}{{AI@j{CAnBCCf}}}}\",[]]<;Aj[\"{{{AI@j{ABJn}}}LAl}\",[]]Aj[\"{{{AI@j{ABK`}}}LAl}\",[]]Bc[\"{{{AI@j{AILh}}AJ@lAIO`}ABLl}\",[]]Co[\"{{{AI@j{CAnAILj}}AHEnAIObOGd}{{LFb{{LAj{LEnCMf}}AHGj}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CHj}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CHj}{{AI@j{CAnBCCf}}}}\",[]]Ai[\"{AILf{{LFf{HIh}}}}\",[]]Bg[\"{{{AI@j{BBEj}}AJB`}{{LFd{LAl}}}}\",[]]A`[\"{AHE`CHl}\",[]]10Ai[\"{{{AI@j{Oj}}}BCCb}\",[]]Ce[\"{{{AI@j{CAnB@G`}}{Ml{BCCd}}}{{AI@j{CAnB@G`}}}}\",[]]Ce[\"{{{AI@j{CAnB@A`}}{Ml{BCCd}}}{{AI@j{CAnB@A`}}}}\",[]]Ce[\"{{{AI@j{CAnB@Gd}}{Ml{BCCf}}}{{AI@j{CAnB@Gd}}}}\",[]]Ce[\"{{{AI@j{CAnB@Ad}}{Ml{BCCf}}}{{AI@j{CAnB@Ad}}}}\",[]]Aa[\"{B@G`BFNn}\",[]]Aa[\"{B@GdBFO`}\",[]]Bj[\"{{{A@h{BB@h}}BAFn}{{LFb{B@G`JGb}}}}\",[]]Bj[\"{{{A@h{BB@h}}BAFn}{{LFb{B@GdJGd}}}}\",[]]Co[\"{{{AI@j{CAnAJ@f}}{AI@j{CAn{KOh{JDn}}}}}{{LFb{HIhAJBb}}}}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]A`[\"{BEBnCHl}\",[]]A`[\"{BEC`CHl}\",[]]Bc[\"{{{AI@j{AILh}}}{{LEh{LAl}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]10Aj[\"{{{AI@j{AHEf}}}LAl}\",[]]Be[\"{{{AI@j{ABJn}}{LEh{B@G`}}}HIh}\",[]]Bn[\"{{{AI@j{CAnABK`}}{LEh{{Ml{B@Gd}}}}}HIh}\",[]]Bd[\"{{{AI@j{BEOh}}}{{LEh{BAFl}}}}\",[]]o[\"{{}AI@j}\",[]]n[\"{{}OF`}\",[]]0000Bn[\"{{{AI@j{CAnBCCd}}LAl}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}LAl}{{AI@j{CAnBCCf}}}}\",[]]o[\"{CHlLGn}\",[]]o[\"{CHlLH`}\",[]]A`[\"{BACjCHl}\",[]]Bo[\"{{{AI@j{CAnBBAn}}ABJj}{{AI@j{CAnBBAn}}}}\",[]]Bo[\"{{{AI@j{CAnBBB`}}ABJj}{{AI@j{CAnBBB`}}}}\",[]]Ae[\"{{LAlCHl}BABh}\",[]]Ae[\"{{LAlCHl}BABj}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]6Bg[\"{{{AI@j{AILj}}LEn}{{LEh{AIOb}}}}\",[]]An[\"{{{AI@j{AILh}}JDn}B@Fj}\",[]]Am[\"{{{AI@j{AILh}}LGn}HIh}\",[]]B`[\"{{{AI@j{CAnAILj}}LH`}HIh}\",[]]Ce[\"{{{AI@j{CAnBBAn}}{A@h{CHj}}}{{AI@j{CAnBBAn}}}}\",[]]Ce[\"{{{AI@j{CAnBBB`}}{A@h{CHj}}}{{AI@j{CAnBBB`}}}}\",[]]Fg[\"{{{AI@j{BGBl}}{AI@j{BB@h}}{AI@j{{KOh{BB@h}}}}{AI@j{AJ@j}}{AI@j{{KOh{Md}}}}ABOh}{{LFb{BEJfJFf}}}}\",[]]Af[\"{{BCBfOGd}BCBf}\",[]]Af[\"{{BCBhOGd}BCBh}\",[]]?Al[\"{B@H`{{LFb{CLbJG`}}}}\",[]]Ak[\"{B@H`{{LFb{NjJG`}}}}\",[]]Am[\"{B@H`{{LFb{ABMlJG`}}}}\",[]]Ai[\"{B@H`{{LFh{CLd}}}}\",[]]Ah[\"{B@H`{{LFh{Nl}}}}\",[]]Aj[\"{B@H`{{LFh{ABMn}}}}\",[]]o[\"{OF`OF`}\",[]]Bo[\"{{{AI@j{CAnBEHl}}ABJj}{{AI@j{CAnBEHl}}}}\",[]]Bo[\"{{{AI@j{CAnBEHn}}ABJj}{{AI@j{CAnBEHn}}}}\",[]]Bb[\"{{{AI@j{OIj}}}{{LEh{CMf}}}}\",[]]Bc[\"{{{AI@j{AJAh}}}{{LEh{CMf}}}}\",[]]Bb[\"{{{AI@j{OIl}}}{{LEh{CMf}}}}\",[]]Bc[\"{{{AI@j{AJAj}}}{{LEh{CMf}}}}\",[]]Bg[\"{{{AI@j{AILh}}}{{LFb{HIhBC@j}}}}\",[]]Cf[\"{{{AI@j{CAnBCCd}}{LEh{ABJj}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{LEh{ABJj}}}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]Bl[\"{{{AI@j{CAnAILl}}OGdOGdCMfCMfCHl}HIh}\",[]]Bj[\"{{{AI@j{CAnMn}}OGdOGdCMfCMfCHl}HIh}\",[]]Bk[\"{{{AI@j{CAnJEh}}OGdOGdCMfCMfCHl}HIh}\",[]]Bk[\"{{{AI@j{CAnOH`}}OGdOGdCMfCMfCHl}HIh}\",[]]Bl[\"{{{AI@j{CAnAILn}}OGdOGdCMfCMfCHl}HIh}\",[]]Bj[\"{{{AI@j{CAnN`}}OGdOGdCMfCMfCHl}HIh}\",[]]Bk[\"{{{AI@j{CAnJEj}}OGdOGdCMfCMfCHl}HIh}\",[]]Bk[\"{{{AI@j{CAnOHb}}OGdOGdCMfCMfCHl}HIh}\",[]]A`[\"{BACjCHl}\",[]]Ak[\"{{{AI@j{OJh}}Nl}CHl}\",[]]Bi[\"{{{AI@j{CAnAJ@d}}CHl}{{LFf{HIh}}}}\",[]]<;A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]10Cf[\"{{{AI@j{CAnBCCd}}{LEh{BEFn}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{LEh{BEG`}}}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHHbCHl}\",[]]A`[\"{AHHdCHl}\",[]]Bh[\"{{{AI@j{CAnAIK`}}}{{LFb{OjJFh}}}}\",[]]Bj[\"{{{AI@j{CAnAIK`}}}{{LFb{AHE`JFh}}}}\",[]]Bh[\"{{{AI@j{CAnAIK`}}}{{LFb{OlJFh}}}}\",[]]Bh[\"{{{AI@j{CAnAIK`}}}{{LFb{OnJFh}}}}\",[]]Bh[\"{{{AI@j{CAnAIK`}}}{{LFb{NhJFh}}}}\",[]]Bj[\"{{{AI@j{CAnAIK`}}}{{LFb{ABIlJFh}}}}\",[]]Cc[\"{{{Ml{AILf}}CHlCMf}{{LFf{{LAj{BBEbBBEb}}}}}}\",[]]Bn[\"{{{AI@j{CAnB@G`}}CHl}{{AI@j{CAnB@G`}}}}\",[]]Bn[\"{{{AI@j{CAnB@Gd}}CHl}{{AI@j{CAnB@Gd}}}}\",[]]Aj[\"{{{AI@j{AILh}}}CMf}\",[]]Ak[\"{{{AI@j{BB@f}}}B@Dn}\",[]]0Ci[\"{{{AI@j{CAnBBAn}}CHh}{{LFb{{AI@j{CAnBBAn}}AO@j}}}}\",[]]Ci[\"{{{AI@j{CAnBBB`}}CHh}{{LFb{{AI@j{CAnBBB`}}AO@l}}}}\",[]]A`[\"{AHE`CHh}\",[]]Cf[\"{{{AI@j{CAnBCCd}}{LEh{BEHl}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{LEh{BEHn}}}{{AI@j{CAnBCCf}}}}\",[]]Bg[\"{{{AI@j{CAnAILj}}}{{LEh{BACh}}}}\",[]]Cf[\"{{{AI@j{CAnB@G`}}{LEh{B@Gh}}}{{AI@j{CAnB@G`}}}}\",[]]Cf[\"{{{AI@j{CAnB@Gd}}{LEh{B@Gh}}}{{AI@j{CAnB@Gd}}}}\",[]]Cf[\"{{{AI@j{CAnB@G`}}{LEh{B@Gj}}}{{AI@j{CAnB@G`}}}}\",[]]Cf[\"{{{AI@j{CAnB@Gd}}{LEh{B@Gj}}}{{AI@j{CAnB@Gd}}}}\",[]]Cc[\"{{}{{LFb{{LAj{{A@h{BB@h}}BAFn}}{Nd{JFd}}}}}}\",[]]Bn[\"{{{AI@j{CAnBEFn}}LGn}{{AI@j{CAnBEFn}}}}\",[]]Bn[\"{{{AI@j{CAnBEG`}}LH`}{{AI@j{CAnBEG`}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Bo[\"{{{AI@j{CAnB@G`}}ABJj}{{AI@j{CAnB@G`}}}}\",[]]Bo[\"{{{AI@j{CAnB@Gd}}ABJj}{{AI@j{CAnB@Gd}}}}\",[]]Ci[\"{{{AI@j{CKd}}{LEh{ABJj}}}{{LFb{{LEh{ABJj}}AIKj}}}}\",[]]Bj[\"{{{AI@j{BBEj}}AJB`LAl}{{LFd{HIh}}}}\",[]]054Bm[\"{{{AI@j{OIj}}}{{LFb{{LEh{BF@f}}JFn}}}}\",[]]Bn[\"{{{AI@j{AJAh}}}{{LFb{{LEh{BF@f}}JFn}}}}\",[]]Bn[\"{{{AI@j{OIl}}}{{LFb{{LEh{BF@f}}BBEh}}}}\",[]]Bo[\"{{{AI@j{AJAj}}}{{LFb{{LEh{BF@f}}BBEh}}}}\",[]]Aj[\"{{{AI@j{AHGd}}}CHl}\",[]]Aj[\"{{{AI@j{AHGf}}}CHl}\",[]]Aj[\"{{{AI@j{ABK`}}}CHl}\",[]]Bf[\"{{{AI@j{AHEn}}{AI@j{AHEn}}}CMf}\",[]]Am[\"{{{AI@j{CAnAILj}}}HIh}\",[]]Bn[\"{{{AI@j{CAnBAF`}}ADd}{{AI@j{CAnBAF`}}}}\",[]]Bn[\"{{{AI@j{CAnBAFb}}ADd}{{AI@j{CAnBAFb}}}}\",[]]Ak[\"{{{AI@j{AHHn}}}B@Dn}\",[]]0Bd[\"{{{AI@j{AILh}}}{{ABMd{JGn}}}}\",[]]Cb[\"{{{AI@j{AILj}}LEn}{{LFb{{LEh{AJ@l}}AIL`}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]Bn[\"{{{AI@j{CAnBCCd}}LGn}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}LH`}{{AI@j{CAnBCCf}}}}\",[]]A`[\"{AHE`LEh}\",[]]Bo[\"{{{AI@j{AHE`}}{AI@j{CHf}}}{{LFd{BCCb}}}}\",[]]Em[\"{{{AI@j{AILh}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhBGJ`}}}}\",[]]El[\"{{{AI@j{OIj}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhBGJ`}}}}\",[]]Em[\"{{{AI@j{AJAh}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhBGJ`}}}}\",[]]El[\"{{{AI@j{OIl}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhBGJb}}}}\",[]]Em[\"{{{AI@j{AJAj}}{AI@j{CAn{KOh{Md}}}}{AI@j{{KOh{Md}}}}{AI@j{{KOh{Md}}}}}{{LFb{HIhBGJb}}}}\",[]]Am[\"{{{AI@j{CAnAHEd}}}HIh}\",[]]0Al[\"{{{AI@j{AILj}}Nl}CHl}\",[]]Bl[\"{{{AI@j{AILh}}}{{ABMf{{LEh{AJ@l}}}}}}\",[]]Bg[\"{{{AI@j{CKd}}}{{LFb{BDGhAIKj}}}}\",[]]>=E`[\"{{{AI@j{BGBl}}{AI@j{{KOh{Md}}}}{AI@j{BB@h}}{AI@j{BFN`}}}{{LFb{BGEbJFf}}}}\",[]]0Bf[\"{{{Ml{BAGf}}}{{LFb{B@A`BFH`}}}}\",[]]Bf[\"{{{Ml{BAGf}}}{{LFb{B@AdBFH`}}}}\",[]]Bn[\"{{{AI@j{CAnBEFn}}LGn}{{AI@j{CAnBEFn}}}}\",[]]Bn[\"{{{AI@j{CAnBEG`}}LH`}{{AI@j{CAnBEG`}}}}\",[]]o[\"{OF`OF`}\",[]]0000Aj[\"{{{AI@j{AILj}}}CMf}\",[]]0Ci[\"{{{AI@j{CKd}}{LEh{ABJj}}}{{LFb{{LEh{ABJj}}AIKj}}}}\",[]]Cc[\"{{{AI@j{CAnOj}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Ce[\"{{{AI@j{CAnAHE`}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Cc[\"{{{AI@j{CAnOl}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Cc[\"{{{AI@j{CAnOn}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Cc[\"{{{AI@j{CAnNh}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Ce[\"{{{AI@j{CAnABIl}}{AI@j{AIK`}}}{{LFb{HIhJFh}}}}\",[]]Bo[\"{{{AI@j{CAnB@G`}}BFNn}{{AI@j{CAnB@G`}}}}\",[]]Bo[\"{{{AI@j{CAnB@Gd}}BFO`}{{AI@j{CAnB@Gd}}}}\",[]]Aj[\"{{{AI@j{BBAn}}}CHl}\",[]]Aj[\"{{{AI@j{BBB`}}}CHl}\",[]]Cc[\"{{{AI@j{CAnB@A`}}{Ml{A`}}}{{AI@j{CAnB@A`}}}}\",[]]Cc[\"{{{AI@j{CAnB@Ad}}{Ml{A`}}}{{AI@j{CAnB@Ad}}}}\",[]]Cj[\"{{BBAn{LEh{B@G`}}{Nd{BB@f}}{Ml{OIh}}}{{LFd{ABJn}}}}\",[]]Aj[\"{{{AI@j{ABKf}}}CMf}\",[]]Aj[\"{{{AI@j{ABKh}}}CMf}\",[]]Ca[\"{{{AI@j{CAnAILj}}OGdAINf}{{LFb{HIhBGBd}}}}\",[]]Bd[\"{{{AI@j{BGBl}}}{{A@h{BCBj}}}}\",[]]Bj[\"{{{AI@j{AILh}}AJ@l}{{LFb{HIhJGh}}}}\",[]]Bm[\"{{{AI@j{CAnAILj}}AJ@l}{{LFb{HIhJGh}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}LAl}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}LAl}{{AI@j{CAnBCCf}}}}\",[]]Bl[\"{{}{{LFb{{LAj{BB@hBEIh}}{Nd{JFd}}}}}}\",[]]Ai[\"{AILf{{LFf{HIh}}}}\",[]]A`[\"{AIMdCHl}\",[]]A`[\"{AIMfCHl}\",[]]An[\"{{{AI@j{ABJn}}B@A`}HIh}\",[]]D`[\"{{{AI@j{CAnAILj}}LEn{LEh{ABJj}}}{{LFb{{LEh{ABJj}}AIL`}}}}\",[]]o[\"{{}AI@j}\",[]]Aj[\"{{{AI@j{AILh}}}LAl}\",[]]Bn[\"{{{AI@j{CAnB@G`}}CHl}{{AI@j{CAnB@G`}}}}\",[]]Bn[\"{{{AI@j{CAnB@Gd}}CHl}{{AI@j{CAnB@Gd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}LGn}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}LH`}{{AI@j{CAnBCCf}}}}\",[]]:Bb[\"{{{AI@j{CAnAILj}}NlLH`}HIh}\",[]]Ak[\"{{}{{LFb{B@A`JGb}}}}\",[]]Ak[\"{{}{{LFb{B@AdJGd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CMf}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CMf}{{AI@j{CAnBCCf}}}}\",[]]65Cf[\"{{{AI@j{CAnOj}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Ch[\"{{{AI@j{CAnAHE`}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Cf[\"{{{AI@j{CAnOl}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Cf[\"{{{AI@j{CAnOn}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Cf[\"{{{AI@j{CAnNh}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Ch[\"{{{AI@j{CAnABIl}}{AI@j{CAnAIK`}}}{{LFb{HIhJFh}}}}\",[]]Bi[\"{{{AI@j{CAnAHEn}}{AI@j{AHEn}}}CMf}\",[]]n[\"{{}HIh}\",[]]Ce[\"{{{AI@j{CAnBCCd}}{LEh{LAl}}}{{AI@j{CAnBCCd}}}}\",[]]Ce[\"{{{AI@j{CAnBCCf}}{LEh{LAl}}}{{AI@j{CAnBCCf}}}}\",[]]Bn[\"{{{AI@j{AILh}}}{{LFb{{A@h{AJ@l}}JGh}}}}\",[]]Cd[\"{{{AI@j{CAnAILj}}OGd}{{LFb{{A@h{AJ@l}}JGh}}}}\",[]]Am[\"{{{AI@j{CAnAILl}}}HIh}\",[]]Al[\"{{{AI@j{CAnJEh}}}HIh}\",[]]Am[\"{{{AI@j{CAnAILn}}}HIh}\",[]]Al[\"{{{AI@j{CAnJEj}}}HIh}\",[]]Ai[\"{AILf{{LFf{HIh}}}}\",[]]Bj[\"{{{AI@j{AILh}}AJ@l}{{LFb{HIhJGh}}}}\",[]]Bm[\"{{{AI@j{CAnAILj}}AJ@l}{{LFb{HIhJGh}}}}\",[]]D`[\"{{{AI@j{CAnAILj}}LEn{LEh{ABJj}}}{{LFb{{LEh{ABJj}}AIL`}}}}\",[]]Ce[\"{{{AI@j{CAnBCCd}}{Ml{BEBj}}}{{AI@j{CAnBCCd}}}}\",[]]Ce[\"{{{AI@j{CAnBCCf}}{Ml{BEBl}}}{{AI@j{CAnBCCf}}}}\",[]]Cf[\"{{{AI@j{CAnBCCd}}{LEh{ABJj}}}{{AI@j{CAnBCCd}}}}\",[]]Cf[\"{{{AI@j{CAnBCCf}}{LEh{ABJj}}}{{AI@j{CAnBCCf}}}}\",[]]Aa[\"{BACnAINd}\",[]]Aa[\"{BAD`AINd}\",[]]9Bn[\"{{{AI@j{CAnBCCd}}CMf}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CMf}{{AI@j{CAnBCCf}}}}\",[]]Am[\"{{{AI@j{AILh}}LGn}HIh}\",[]]o[\"{OF`OF`}\",[]]Bn[\"{{{AI@j{CAnBCCd}}CHj}{{AI@j{CAnBCCd}}}}\",[]]Bn[\"{{{AI@j{CAnBCCf}}CHj}{{AI@j{CAnBCCf}}}}\",[]]3109854Bn[\"{{{AI@j{AILh}}}{{LFb{{A@h{AJ@l}}JGh}}}}\",[]]Bn[\"{{{AI@j{AILj}}}{{LFb{{A@h{AJ@l}}JGh}}}}\",[]]10A`[\"{BF@fLEh}\",[]]Bm[\"{{{AI@j{CAnBCCd}}Md}{{AI@j{CAnBCCd}}}}\",[]]Bm[\"{{{AI@j{CAnBCCf}}Md}{{AI@j{CAnBCCf}}}}\",[]]o[\"{{}AINf}\",[]]") \ No newline at end of file diff --git a/pr/255/docs/search.index/function/e0bd020fee7e.js b/pr/255/docs/search.index/function/e0bd020fee7e.js deleted file mode 100644 index c5150c6dd..000000000 --- a/pr/255/docs/search.index/function/e0bd020fee7e.js +++ /dev/null @@ -1 +0,0 @@ -rd_("Bf[\"{{{AHEf{ANAb}}{AHEf{ANAb}}}CKh}\",[]]Bf[\"{{{AHEf{BDCj}}{AHEf{BDCj}}}CKh}\",[]]Bf[\"{{{AHEf{BAEf}}{AHEf{BAEf}}}CKh}\",[]]Bf[\"{{{AHEf{AGMf}}{AHEf{AGMf}}}CKh}\",[]]Bf[\"{{{AHEf{AID`}}{AHEf{AID`}}}CKh}\",[]]Bf[\"{{{AHEf{BAEd}}{AHEf{BAEd}}}CKh}\",[]]Bf[\"{{{AHEf{AIFb}}{AHEf{AIFb}}}CKh}\",[]]Bf[\"{{{AHEf{AOHf}}{AHEf{AOHf}}}CKh}\",[]]Bd[\"{{{AHEf{LB`}}{AHEf{LB`}}}CKh}\",[]]Bf[\"{{{AHEf{BEGh}}{AHEf{BEGh}}}CKh}\",[]]Bd[\"{{{AHEf{J@`}}{AHEf{J@`}}}CKh}\",[]]Bd[\"{{{AHEf{L@`}}{AHEf{L@`}}}CKh}\",[]]Bf[\"{{{AHEf{AGM`}}{AHEf{AGM`}}}CKh}\",[]]Bd[\"{{{AHEf{OD`}}{AHEf{OD`}}}CKh}\",[]]Bf[\"{{{AHEf{AOBh}}{AHEf{AOBh}}}CKh}\",[]]Bf[\"{{{AHEf{BBAb}}{AHEf{BBAb}}}CKh}\",[]]Bf[\"{{{AHEf{ANBl}}{AHEf{ANBl}}}CKh}\",[]]Bf[\"{{{AHEf{ANAh}}{AHEf{ANAh}}}CKh}\",[]]Bf[\"{{{AHEf{AGJn}}{AHEf{AGJn}}}CKh}\",[]]Bf[\"{{{AHEf{BB@l}}{AHEf{BB@l}}}CKh}\",[]]Bf[\"{{{AHEf{BCGh}}{AHEf{BCGh}}}CKh}\",[]]Bf[\"{{{AHEf{AOCd}}{AHEf{AOCd}}}CKh}\",[]]Bf[\"{{{AHEf{AOCj}}{AHEf{AOCj}}}CKh}\",[]]Bf[\"{{{AHEf{AODb}}{AHEf{AODb}}}CKh}\",[]]Bf[\"{{{AHEf{BDJn}}{AHEf{BDJn}}}CKh}\",[]]Bd[\"{{{AHEf{CJd}}{AHEf{CJd}}}CKh}\",[]]Bb[\"{{{AHEf{Nb}}{AHEf{Nb}}}CKh}\",[]]Bf[\"{{{AHEf{ABEh}}{AHEf{ABEh}}}CKh}\",[]]Bf[\"{{{AHEf{BFIn}}{AHEf{BFIn}}}CKh}\",[]]Bd[\"{{{AHEf{JBb}}{AHEf{JBb}}}CKh}\",[]]Bd[\"{{{AHEf{LBb}}{AHEf{LBb}}}CKh}\",[]]Bf[\"{{{AHEf{BEGj}}{AHEf{BEGj}}}CKh}\",[]]Bd[\"{{{AHEf{J@b}}{AHEf{J@b}}}CKh}\",[]]Bf[\"{{{AHEf{BDCl}}{AHEf{BDCl}}}CKh}\",[]]Bd[\"{{{AHEf{L@b}}{AHEf{L@b}}}CKh}\",[]]Bf[\"{{{AHEf{AICd}}{AHEf{AICd}}}CKh}\",[]]Bf[\"{{{AHEf{AGLn}}{AHEf{AGLn}}}CKh}\",[]]Bf[\"{{{AHEf{BDJh}}{AHEf{BDJh}}}CKh}\",[]]Bf[\"{{{AHEf{AI@d}}{AHEf{AI@d}}}CKh}\",[]]Bf[\"{{{AHEf{AGMb}}{AHEf{AGMb}}}CKh}\",[]]Bf[\"{{{AHEf{AGMh}}{AHEf{AGMh}}}CKh}\",[]]Bf[\"{{{AHEf{B@Gj}}{AHEf{B@Gj}}}CKh}\",[]]Bd[\"{{{AHEf{ODb}}{AHEf{ODb}}}CKh}\",[]]Bf[\"{{{AHEf{AIFd}}{AHEf{AIFd}}}CKh}\",[]]Bf[\"{{{AHEf{ANBj}}{AHEf{ANBj}}}CKh}\",[]]Bf[\"{{{AHEf{ANDn}}{AHEf{ANDn}}}CKh}\",[]]Bf[\"{{{AHEf{BAEh}}{AHEf{BAEh}}}CKh}\",[]]Bf[\"{{{AHEf{AOC`}}{AHEf{AOC`}}}CKh}\",[]]Bf[\"{{{AHEf{BBAd}}{AHEf{BBAd}}}CKh}\",[]]Bf[\"{{{AHEf{AGLh}}{AHEf{AGLh}}}CKh}\",[]]Bf[\"{{{AHEf{BAAf}}{AHEf{BAAf}}}CKh}\",[]]Bf[\"{{{AHEf{ANBn}}{AHEf{ANBn}}}CKh}\",[]]Bf[\"{{{AHEf{ANAj}}{AHEf{ANAj}}}CKh}\",[]]Bf[\"{{{AHEf{AGK`}}{AHEf{AGK`}}}CKh}\",[]]Bf[\"{{{AHEf{BBA`}}{AHEf{BBA`}}}CKh}\",[]]Bf[\"{{{AHEf{BCGl}}{AHEf{BCGl}}}CKh}\",[]]Bf[\"{{{AHEf{BCHd}}{AHEf{BCHd}}}CKh}\",[]]Bf[\"{{{AHEf{AOCf}}{AHEf{AOCf}}}CKh}\",[]]Bf[\"{{{AHEf{ABCh}}{AHEf{ABCh}}}CKh}\",[]]Bf[\"{{{AHEf{BDCh}}{AHEf{BDCh}}}CKh}\",[]]Bf[\"{{{AHEf{AOCl}}{AHEf{AOCl}}}CKh}\",[]]Bf[\"{{{AHEf{AODd}}{AHEf{AODd}}}CKh}\",[]]Bf[\"{{{AHEf{BAF`}}{AHEf{BAF`}}}CKh}\",[]]Bf[\"{{{AHEf{BDK`}}{AHEf{BDK`}}}CKh}\",[]]Bd[\"{{{AHEf{CJf}}{AHEf{CJf}}}CKh}\",[]]Bb[\"{{{AHEf{Nd}}{AHEf{Nd}}}CKh}\",[]]Bf[\"{{{AHEf{ABEj}}{AHEf{ABEj}}}CKh}\",[]]Bf[\"{{{AHEf{AGJl}}{AHEf{AGJl}}}CKh}\",[]]Bf[\"{{{AHEf{B@Hf}}{AHEf{B@Hf}}}CKh}\",[]]Bf[\"{{{AHEf{BE@b}}{AHEf{BE@b}}}CKh}\",[]]Bd[\"{{{AHEf{JBf}}{AHEf{JBf}}}CKh}\",[]]Bf[\"{{{AHEf{BFJ`}}{AHEf{BFJ`}}}CKh}\",[]]Bd[\"{{{AHEf{JBd}}{AHEf{JBd}}}CKh}\",[]]Bf[\"{{{AHEf{AODf}}{AHEf{AODf}}}CKh}\",[]]Ai[\"{{{AHEf{CIf}}}L@`}\",[]]Ak[\"{{{AHEf{AICl}}}ABEh}\",[]]Ak[\"{{{AHEf{BE@d}}}ABEh}\",[]]Ak[\"{{{AHEf{AIDh}}}ABEh}\",[]]o[\"{KOdL@b}\",[]]o[\"{KN`L@b}\",[]]A`[\"{AGHfL@b}\",[]]A`[\"{B@EhL@b}\",[]]A`[\"{AOFlL@b}\",[]]A`[\"{AOEnL@b}\",[]]Aa[\"{ABDlABEj}\",[]]Aa[\"{ABGfABEj}\",[]]Aa[\"{ABBnABEj}\",[]]A`[\"{OBlABEj}\",[]]n[\"{{}OBd}\",[]]A`[\"{CI`ABCh}\",[]]Be[\"{{{AHEf{LB`}}{AHEf{LB`}}}ABDj}\",[]]Be[\"{{{AHEf{L@`}}{AHEf{L@`}}}ABDj}\",[]]Bg[\"{{{AHEf{ANBl}}{AHEf{ANBl}}}ABDj}\",[]]Bg[\"{{{AHEf{AOCj}}{AHEf{AOCj}}}ABDj}\",[]]Be[\"{{{AHEf{CJd}}{AHEf{CJd}}}ABDj}\",[]]Bc[\"{{{AHEf{Nb}}{AHEf{Nb}}}ABDj}\",[]]Bg[\"{{{AHEf{ABEh}}{AHEf{ABEh}}}ABDj}\",[]]Be[\"{{{AHEf{LBb}}{AHEf{LBb}}}ABDj}\",[]]Bg[\"{{{AHEf{BDCl}}{AHEf{BDCl}}}ABDj}\",[]]Be[\"{{{AHEf{L@b}}{AHEf{L@b}}}ABDj}\",[]]Bg[\"{{{AHEf{AGMh}}{AHEf{AGMh}}}ABDj}\",[]]Bg[\"{{{AHEf{B@Gj}}{AHEf{B@Gj}}}ABDj}\",[]]Bg[\"{{{AHEf{AIFd}}{AHEf{AIFd}}}ABDj}\",[]]Bg[\"{{{AHEf{ANBn}}{AHEf{ANBn}}}ABDj}\",[]]Bg[\"{{{AHEf{BCHd}}{AHEf{BCHd}}}ABDj}\",[]]Bg[\"{{{AHEf{BDCh}}{AHEf{BDCh}}}ABDj}\",[]]Bg[\"{{{AHEf{AOCl}}{AHEf{AOCl}}}ABDj}\",[]]Be[\"{{{AHEf{CJf}}{AHEf{CJf}}}ABDj}\",[]]Bc[\"{{{AHEf{Nd}}{AHEf{Nd}}}ABDj}\",[]]Bg[\"{{{AHEf{ABEj}}{AHEf{ABEj}}}ABDj}\",[]]o[\"{ABEhNb}\",[]]o[\"{ABEjNd}\",[]]n[\"{KOfNd}\",[]]o[\"{AGIbNd}\",[]]A`[\"{ABFjKOl}\",[]]A`[\"{ABFlKOl}\",[]]A`[\"{ABEdKOl}\",[]]A`[\"{ABFnKOl}\",[]]Bg[\"{{{AHEf{Ob}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANAb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BAEj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BFBf}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AI@h}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AI@l}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BEGn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDCj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ABBj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{B@Dd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABCb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIDb}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BACb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{CIf}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AICl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BE@d}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BAEf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AGMf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AID`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BAEd}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AOHh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANDf}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIDh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIFb}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AOHf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Cd[\"{{{AHEf{LB`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BEGh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Cd[\"{{{AHEf{J@`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cd[\"{{{AHEf{L@`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{ABG`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AIAh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AGM`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BBAj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cd[\"{{{AHEf{OD`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AOBh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BBAb}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BBBn}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BBCl}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BDFj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BDHh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{ANBl}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BABh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AOGj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BENj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AOAl}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{ANAh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{AGJn}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BB@l}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BCGh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{AOCd}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{AOCj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{AODb}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BDJn}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{BCKf}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cd[\"{{{AHEf{CJd}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cc[\"{{{AHEf{Nb}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{ABEh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Ce[\"{{{AHEf{ABFj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cc[\"{{{AHEf{Mf}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{AGIh}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cd[\"{{{AHEf{J@h}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{ANBb}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Cd[\"{{{AHEf{O@n}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{B@Fj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BDBj}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BFIn}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{ANAn}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BDKf}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]Ce[\"{{{AHEf{BEG`}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Cd[\"{{{AHEf{JBb}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Bi[\"{{{AHEf{AI@n}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABBl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{LBb}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BEGj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bh[\"{{{AHEf{J@b}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDCl}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bh[\"{{{AHEf{L@b}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AOGb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AICd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AGLn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDJh}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AI@d}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ABGb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIAj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AGMb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BBAl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AGMh}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{B@Gj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bh[\"{{{AHEf{ODb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIFd}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ANBj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ANDn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BAEh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AOC`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BBAd}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AGLh}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BAAf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bh[\"{{{AHEf{JBl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BBC`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BBCn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDFl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDHj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANBn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BABj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AOGn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BENl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AOB`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANAj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AGK`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BBA`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BCGl}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ABAn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BCHd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABCd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AOCf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AN@n}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AIDd}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{B@G`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BBBl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BFBd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABCh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDCh}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BBAh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{B@Db}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AOCl}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AODd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BAF`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BDK`}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{AIB`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BFNb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BCKh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{CJf}}{AHEf{C@bAGJj}}}L@d}\",[]]Bg[\"{{{AHEf{Nd}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ABEj}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{ABFl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AGJl}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{B@Hf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BE@b}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{JBf}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bi[\"{{{AHEf{BFJ`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANB`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDKl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BEGb}}{AHEf{C@bAGJj}}}L@d}\",[]]0Cd[\"{{{AHEf{JBd}}{AHEf{C@bAGJj}}}{{L@f{HEhJAb}}}}\",[]]0Bg[\"{{{AHEf{Mh}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AGIj}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{J@j}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ANBd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{OA`}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{B@Fl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BDBl}}{AHEf{C@bAGJj}}}L@d}\",[]]Bh[\"{{{AHEf{JBh}}{AHEf{C@bAGJj}}}L@d}\",[]]0Bh[\"{{{AHEf{JBn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{BAFb}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABEd}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{ABFn}}{AHEf{C@bAGJj}}}L@d}\",[]]Bi[\"{{{AHEf{AODf}}{AHEf{C@bAGJj}}}L@d}\",[]]Ak[\"{{{AHEf{AOGb}}}ABBf}\",[]]A`[\"{ABG`CG`}\",[]]A`[\"{ABGbCG`}\",[]]Aj[\"{{{AHEf{B@G`}}}KL`}\",[]]A`[\"{BFBdCG`}\",[]]o[\"{CI`CG`}\",[]]A`[\"{ABEdKL`}\",[]]Ce[\"{{{AHEf{C@bBENj}}{Md{ABFb}}}{{AHEf{C@bBENj}}}}\",[]]Ce[\"{{{AHEf{C@bBENl}}{Md{ABFd}}}{{AHEf{C@bBENl}}}}\",[]]8Af[\"{{ABBfCG`}BAEj}\",[]]Ag[\"{{}{{Md{BFBf}}}}\",[]]Ae[\"{{KL`CFn}B@Cb}\",[]]Cd[\"{{BABh{KOl{AOGj}}AGMn{Md{OBf}}}{{L@h{ABBj}}}}\",[]]Ah[\"{{{Ml{JDn}}}AICf}\",[]]A`[\"{OAnBBBn}\",[]]Ah[\"{{{Md{NOl}}}BABh}\",[]]Bc[\"{{{Md{AOGl}}{Md{BDBn}}}AOGj}\",[]]Ai[\"{{{Md{AOAn}}}AOAl}\",[]]B`[\"{{{AHEf{{KIl{Ll}}}}}AOCj}\",[]]Ae[\"{{CFnKL`}BCKf}\",[]]Ag[\"{{CJdNbCG`}ABEh}\",[]]Aj[\"{{{Md{AGIh}}CFl}Mf}\",[]]An[\"{{{Md{ANBb}}O@bCFl}J@h}\",[]]An[\"{{{Md{B@Fj}}O@bCFl}O@n}\",[]]Ae[\"{{KL`CFn}B@Cd}\",[]]Ah[\"{{{Ml{JDn}}}AICh}\",[]]Cm[\"{{{Md{BABj}}{KOl{{Md{AOGn}}}}CKh{KOl{{JE`{Ll}}}}}ABBl}\",[]]A`[\"{KL`BGAd}\",[]]o[\"{{}BFMh}\",[]]A`[\"{OAnBBC`}\",[]]Ah[\"{{{Md{NOn}}}BABj}\",[]]Bc[\"{{{Md{AOH`}}{Md{BDC`}}}AOGn}\",[]]Ai[\"{{{Md{AOBb}}}AOB`}\",[]]Ek[\"{{ABAd{AHEf{c}}{AHEf{{KIl{CFn}}}}CKh}{{L@f{{KKn{B@G`{KOl{ABAd}}}}BDCh}}}{BDGfJDf}}\",[\"\"]]B`[\"{{{AHEf{{KIl{Ll}}}}}AOCl}\",[]]Af[\"{{BDK`LAl}BAF`}\",[]]A`[\"{KL`BFNb}\",[]]Ae[\"{{CFnKL`}BCKh}\",[]]Ag[\"{{CJfNdCG`}ABEj}\",[]]Aj[\"{{{Md{AGIj}}CFl}Mh}\",[]]An[\"{{{Md{ANBd}}O@bCFl}J@j}\",[]]An[\"{{{Md{B@Fl}}O@bCFl}OA`}\",[]]Aj[\"{AIF`{{L@h{BAFb}}}}\",[]]Ai[\"{{{Md{BCK`}}}BFHb}\",[]]Ai[\"{{{Md{BCKd}}}BFHd}\",[]]o[\"{CJdCJd}\",[]]o[\"{CJfCJf}\",[]]Ak[\"{{{AHEf{AIEd}}}AIEb}\",[]]Ai[\"{{{AHEf{OBf}}}O@b}\",[]]0Aj[\"{{{AHEf{AOHh}}}O@b}\",[]]Ak[\"{{{AHEf{B@Hb}}}AIEb}\",[]]Ak[\"{{{AHEf{AIEf}}}AIEb}\",[]]Ak[\"{{{AHEf{B@Hd}}}AIEb}\",[]]Bg[\"{{{AHEf{AI@l}}L@`}{{KOl{ABBf}}}}\",[]]Aa[\"{AGM`ABBf}\",[]]Bg[\"{{{AHEf{AI@n}}L@b}{{KOl{ABBf}}}}\",[]]Aa[\"{AGMbABBf}\",[]]Ag[\"{Od{{L@j{HEh}}}}\",[]]Ag[\"{Of{{L@j{HEh}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Aa[\"{AOEnAIDn}\",[]]Aa[\"{ABEdAIDn}\",[]]Aa[\"{BAF`BDK`}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]A`[\"{ABAnIOn}\",[]]Am[\"{{{AHEf{C@bABDf}}}HEh}\",[]]Am[\"{{{AHEf{C@bABCb}}}HEh}\",[]]Am[\"{{{AHEf{C@bAICl}}}HEh}\",[]]Am[\"{{{AHEf{C@bAIDh}}}HEh}\",[]]Al[\"{{{AHEf{C@bKMh}}}HEh}\",[]]A`[\"{cc{}}\",[\"T\"]]00000000000000000000Aa[\"{BBAbBDCj}\",[]]111111111Aa[\"{AGMfBAEf}\",[]]22Aa[\"{AID`AGMf}\",[]]Aa[\"{BBAbAGMf}\",[]]4Aa[\"{BBAbAID`}\",[]]5Aa[\"{AGMfBAEd}\",[]]666Aa[\"{BBAbAIFb}\",[]]Aa[\"{AOHfAIFb}\",[]]Aa[\"{AOBhAIFb}\",[]]9Aa[\"{BBAbAOHf}\",[]]:::::::o[\"{CFnLB`}\",[]]n[\"{LlLB`}\",[]]o[\"{CFlLB`}\",[]]A`[\"{ABEhLB`}\",[]]A`[\"{BDJnLB`}\",[]]??Al[\"{cL@`{{CHj{CFn}}}}\",[\"T\"]]A`[\"{cc{}}\",[\"T\"]]000000Aa[\"{ANAfBBAb}\",[]]1A`[\"{J@fBBAb}\",[]]A`[\"{JAnBBAb}\",[]]33333A`[\"{LB`ANBl}\",[]]4444Aa[\"{BBD`ANAh}\",[]]5Aa[\"{BEGhANAh}\",[]]66A`[\"{JAnBB@l}\",[]]77Aa[\"{BDKfAOCd}\",[]]888A`[\"{LB`BDJn}\",[]]999A`[\"{LB`ABEh}\",[]]:::::::::::::Aa[\"{ANEdANAn}\",[]];;;;;;A`[\"{BCI`JBb}\",[]]A`[\"{BFJnJBb}\",[]]A`[\"{BBAnJBb}\",[]]A`[\"{BBCdJBb}\",[]]A`[\"{BFIlJBb}\",[]]A`[\"{BFDnJBb}\",[]]A`[\"{BCGnJBb}\",[]]A`[\"{BCJhJBb}\",[]]A`[\"{BADfJBb}\",[]]A`[\"{BACdJBb}\",[]]A`[\"{cc{}}\",[\"T\"]]A`[\"{AIBjJBb}\",[]]1111111111111111A`[\"{ABEjLBb}\",[]]A`[\"{BDK`LBb}\",[]]o[\"{CFlLBb}\",[]]4o[\"{CFnLBb}\",[]]n[\"{LlLBb}\",[]]6666Al[\"{cL@b{{CHj{CFn}}}}\",[\"T\"]]777777777777777777Aa[\"{BAF`BBAd}\",[]]888A`[\"{AGLnJBl}\",[]]99999A`[\"{LBbANBn}\",[]]::::Aa[\"{BBD`ANAj}\",[]];Aa[\"{BEGjANAj}\",[]]>>>>>>>Aa[\"{B@HfBDCh}\",[]]????A`[\"{JBfBAF`}\",[]]A`[\"{cc{}}\",[\"T\"]]A`[\"{LBbBDK`}\",[]]111111A`[\"{LBbABEj}\",[]]22222A`[\"{B@HfJBf}\",[]]33333Aa[\"{ANEdANB`}\",[]]444444A`[\"{BACdJBd}\",[]]A`[\"{BFDnJBd}\",[]]6A`[\"{BFJnJBd}\",[]]A`[\"{BCI`JBd}\",[]]A`[\"{AIBjJBd}\",[]]A`[\"{BBAnJBd}\",[]]A`[\"{BBCdJBd}\",[]]A`[\"{BFIlJBd}\",[]]A`[\"{BADfJBd}\",[]]A`[\"{BCJhJBd}\",[]]A`[\"{BCGnJBd}\",[]]?????????An[\"{{{AHEf{c}}}AIF`CGf}\",[\"S\"]]A`[\"{cc{}}\",[\"T\"]]000000000000000Bm[\"{{{AHEf{LB`}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bk[\"{{{AHEf{L@`}}{AHEf{C@bc}}}HEhKNn}\",[\"H\"]]Bn[\"{{{AHEf{ANBl}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{AOCj}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bm[\"{{{AHEf{CJd}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bl[\"{{{AHEf{Nb}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{ABEh}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bm[\"{{{AHEf{LBb}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{BDCl}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bk[\"{{{AHEf{L@b}}{AHEf{C@bc}}}HEhKNn}\",[\"H\"]]Bn[\"{{{AHEf{AGMh}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{B@Gj}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{AIFd}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{ANBn}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{BCHd}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{BDCh}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{AOCl}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bm[\"{{{AHEf{CJf}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bl[\"{{{AHEf{Nd}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{ABEj}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Bn[\"{{{AHEf{AGJl}}{AHEf{C@bc}}}HEhKNn}\",[\"__H\"]]Aa[\"{{}c{}}\",[\"U\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n[\"{{}HEh}\",[]]0000Cc[\"{{{AHEf{C@bKMh}}KL`}{{L@f{{KOl{J@b}}AGMh}}}}\",[]]El[\"{{{AHEf{NNd}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{{AHEf{C@b{KIl{Ll}}}}ANAn}}}}\",[]]Bh[\"{{{AHEf{C@bOCf}}Nd}{{KOl{ABEj}}}}\",[]]El[\"{{{AHEf{NNf}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{{AHEf{C@b{KIl{Ll}}}}ANB`}}}}\",[]]Bf[\"{{{AHEf{AI@l}}L@`}{{KOl{CIf}}}}\",[]]Bf[\"{{{AHEf{CIf}}}{{L@f{HEhAHOn}}}}\",[]]A`[\"{AIAhCG`}\",[]]Am[\"{{{AHEf{C@bAI@n}}}HEh}\",[]]A`[\"{AIAjCG`}\",[]]Cj[\"{{{Oj{{AHEf{C@bAHOf}}}}{AHEf{C@bNO`}}}{{CIn{HEh}}}}\",[]]Dj[\"{{{Oj{{AHEf{C@bBBDf}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bABDf}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bABDh}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bAI@h}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Di[\"{{{Oj{{AHEf{C@bOAd}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Di[\"{{{Oj{{AHEf{C@bKOb}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bAGHj}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bABAb}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bAOFj}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bAOGd}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Di[\"{{{Oj{{AHEf{C@bKLh}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Dj[\"{{{Oj{{AHEf{C@bBACb}}}}{AHEf{C@bNO`}}}{{CIn{c}}}{}}\",[\"Future::Output\"]]Bf[\"{{{AHEf{C@bAI@n}}}{{KOl{JBl}}}}\",[]]De[\"{{{AHEf{C@bAICl}}{AHEf{C@b{KIl{Ll}}}}}{{L@f{{KOl{KL`}}AGMf}}}}\",[]]Bm[\"{{{AHEf{C@bAICn}}CKh}{{L@f{KMhB@Gj}}}}\",[]]Bo[\"{{CJf{AHEf{C@bc}}}{{L@f{BE@bJBf}}}Mn}\",[\"R\"]]Bf[\"{{{AHEf{C@bAGJd}}}{{KOl{IOn}}}}\",[]]Ec[\"{{{AHEf{BAFb}}AIF`{AHEf{C@b{KIl{AIBb}}}}{AHEf{C@b{KIl{ABEd}}}}}{{L@h{KL`}}}}\",[]]Dk[\"{{{AHEf{NNd}}{AHEf{C@b{A@`{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhANAn}}}}\",[]]Dk[\"{{{AHEf{NNf}}{AHEf{C@b{A@`{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhANB`}}}}\",[]]C`[\"{{{AHEf{C@bAGJd}}IOnCKh}{{L@f{HEhBDCl}}}}\",[]]Cc[\"{{{AHEf{BAFb}}AIF`{AHEf{ABFn}}}{{L@h{HEh}}}}\",[]]Bn[\"{{{AHEf{C@bBENj}}CFn}{{AHEf{C@bBENj}}}}\",[]]Bn[\"{{{AHEf{C@bBENl}}CFn}{{AHEf{C@bBENl}}}}\",[]]Aj[\"{{{AHEf{AI@l}}}CJd}\",[]]Aj[\"{{{AHEf{AI@n}}}CJf}\",[]]Cn[\"{{{AHEf{NOl}}{AHEf{{KIl{Ll}}}}{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]Cn[\"{{{AHEf{NOn}}{AHEf{{KIl{Ll}}}}{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]A`[\"{BAEjCG`}\",[]]A`[\"{ABFjKL`}\",[]]A`[\"{ABFlKL`}\",[]]o[\"{JDbCKh}\",[]]Bm[\"{{{AHEf{C@bAICl}}LB`}{{L@f{HEhAOBh}}}}\",[]]Bm[\"{{{AHEf{C@bBE@d}}LB`}{{L@f{HEhAOBh}}}}\",[]]Bm[\"{{{AHEf{C@bAICn}}LBb}{{L@f{HEhAOC`}}}}\",[]]Bn[\"{{{AHEf{AIEl}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Bn[\"{{{AHEf{BADb}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Bn[\"{{{AHEf{BCKf}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Bn[\"{{{AHEf{AIEn}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Bn[\"{{{AHEf{BADd}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Bn[\"{{{AHEf{BCKh}}{AHEf{CFj}}}{{KOl{IOn}}}}\",[]]Aa[\"{{}c{}}\",[\"V\"]]0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bg[\"{{{Md{BDBf}}O@bCFl}{{Ml{AIA`}}}}\",[]]Bg[\"{{{Md{AGIh}}O@bCFl}{{Ml{AIA`}}}}\",[]]Bg[\"{{{Md{ANBb}}O@bCFl}{{Ml{AIA`}}}}\",[]]Bg[\"{{{Md{B@Fj}}O@bCFl}{{Ml{AIA`}}}}\",[]]Bg[\"{{{Md{BDBh}}O@bCFl}{{Ml{AIAb}}}}\",[]]Bg[\"{{{Md{AGIj}}O@bCFl}{{Ml{AIAb}}}}\",[]]Bg[\"{{{Md{ANBd}}O@bCFl}{{Ml{AIAb}}}}\",[]]Bg[\"{{{Md{B@Fl}}O@bCFl}{{Ml{AIAb}}}}\",[]]Ai[\"{BDOd{{Md{BDBh}}}}\",[]]o[\"{J@`IOn}\",[]]A`[\"{ABG`CG`}\",[]]o[\"{OD`KL`}\",[]]o[\"{J@bIOn}\",[]]A`[\"{ABGbCG`}\",[]]o[\"{ODbKL`}\",[]]Aa[\"{AN@nBBAd}\",[]]Ag[\"{{{AHEf{Ob}}}Ob}\",[]]Ak[\"{{{AHEf{ANAb}}}ANAb}\",[]]Ak[\"{{{AHEf{AI@l}}}AI@l}\",[]]Ak[\"{{{AHEf{BEGn}}}BEGn}\",[]]Ak[\"{{{AHEf{BDCj}}}BDCj}\",[]]Ak[\"{{{AHEf{ABBj}}}ABBj}\",[]]Ak[\"{{{AHEf{B@Dd}}}B@Dd}\",[]]Ak[\"{{{AHEf{BAEf}}}BAEf}\",[]]Ak[\"{{{AHEf{AGMf}}}AGMf}\",[]]Ak[\"{{{AHEf{AID`}}}AID`}\",[]]Ak[\"{{{AHEf{BAEd}}}BAEd}\",[]]Ak[\"{{{AHEf{AIFb}}}AIFb}\",[]]Ak[\"{{{AHEf{AOHf}}}AOHf}\",[]]Ai[\"{{{AHEf{LB`}}}LB`}\",[]]Ak[\"{{{AHEf{BEGh}}}BEGh}\",[]]Ai[\"{{{AHEf{L@`}}}L@`}\",[]]Ak[\"{{{AHEf{ABG`}}}ABG`}\",[]]Ak[\"{{{AHEf{AIAh}}}AIAh}\",[]]Ak[\"{{{AHEf{AGM`}}}AGM`}\",[]]Ak[\"{{{AHEf{BBAj}}}BBAj}\",[]]Ai[\"{{{AHEf{OD`}}}OD`}\",[]]Ak[\"{{{AHEf{AOBh}}}AOBh}\",[]]Ak[\"{{{AHEf{BBAb}}}BBAb}\",[]]Ak[\"{{{AHEf{BBCl}}}BBCl}\",[]]Ak[\"{{{AHEf{BDFj}}}BDFj}\",[]]Ak[\"{{{AHEf{BDHh}}}BDHh}\",[]]Ak[\"{{{AHEf{ANBl}}}ANBl}\",[]]Ak[\"{{{AHEf{BABh}}}BABh}\",[]]Ak[\"{{{AHEf{AOGj}}}AOGj}\",[]]Ak[\"{{{AHEf{BENj}}}BENj}\",[]]Ak[\"{{{AHEf{AOAl}}}AOAl}\",[]]Ak[\"{{{AHEf{ANAh}}}ANAh}\",[]]Ak[\"{{{AHEf{AGJn}}}AGJn}\",[]]Ak[\"{{{AHEf{BB@l}}}BB@l}\",[]]Ak[\"{{{AHEf{BCGh}}}BCGh}\",[]]Ak[\"{{{AHEf{AOCd}}}AOCd}\",[]]Ak[\"{{{AHEf{AOCj}}}AOCj}\",[]]Ak[\"{{{AHEf{AODb}}}AODb}\",[]]Ak[\"{{{AHEf{BDJn}}}BDJn}\",[]]Ai[\"{{{AHEf{CJd}}}CJd}\",[]]Ag[\"{{{AHEf{Nb}}}Nb}\",[]]Ak[\"{{{AHEf{ABEh}}}ABEh}\",[]]Ag[\"{{{AHEf{Mf}}}Mf}\",[]]Ak[\"{{{AHEf{AGIh}}}AGIh}\",[]]Ai[\"{{{AHEf{J@h}}}J@h}\",[]]Ak[\"{{{AHEf{ANBb}}}ANBb}\",[]]Ai[\"{{{AHEf{O@n}}}O@n}\",[]]Ak[\"{{{AHEf{B@Fj}}}B@Fj}\",[]]Ak[\"{{{AHEf{BEG`}}}BEG`}\",[]]Ai[\"{{{AHEf{JBb}}}JBb}\",[]]Ai[\"{{{AHEf{LBb}}}LBb}\",[]]Ak[\"{{{AHEf{BEGj}}}BEGj}\",[]]Ak[\"{{{AHEf{BDCl}}}BDCl}\",[]]Ai[\"{{{AHEf{L@b}}}L@b}\",[]]Ak[\"{{{AHEf{AOGb}}}AOGb}\",[]]Ak[\"{{{AHEf{AICd}}}AICd}\",[]]Ak[\"{{{AHEf{AGLn}}}AGLn}\",[]]Ak[\"{{{AHEf{BDJh}}}BDJh}\",[]]Ak[\"{{{AHEf{AI@d}}}AI@d}\",[]]Ak[\"{{{AHEf{ABGb}}}ABGb}\",[]]Ak[\"{{{AHEf{AIAj}}}AIAj}\",[]]Ak[\"{{{AHEf{AGMb}}}AGMb}\",[]]Ak[\"{{{AHEf{BBAl}}}BBAl}\",[]]Ak[\"{{{AHEf{AGMh}}}AGMh}\",[]]Ak[\"{{{AHEf{B@Gj}}}B@Gj}\",[]]Ai[\"{{{AHEf{ODb}}}ODb}\",[]]Ak[\"{{{AHEf{AIFd}}}AIFd}\",[]]Ak[\"{{{AHEf{ANBj}}}ANBj}\",[]]Ak[\"{{{AHEf{BAEh}}}BAEh}\",[]]Ak[\"{{{AHEf{AOC`}}}AOC`}\",[]]Ak[\"{{{AHEf{BBAd}}}BBAd}\",[]]Ak[\"{{{AHEf{AGLh}}}AGLh}\",[]]Ak[\"{{{AHEf{BAAf}}}BAAf}\",[]]Ak[\"{{{AHEf{BBCn}}}BBCn}\",[]]Ak[\"{{{AHEf{BDFl}}}BDFl}\",[]]Ak[\"{{{AHEf{BDHj}}}BDHj}\",[]]Ak[\"{{{AHEf{ANBn}}}ANBn}\",[]]Ak[\"{{{AHEf{BABj}}}BABj}\",[]]Ak[\"{{{AHEf{AOGn}}}AOGn}\",[]]Ak[\"{{{AHEf{BENl}}}BENl}\",[]]Ak[\"{{{AHEf{AOB`}}}AOB`}\",[]]Ak[\"{{{AHEf{ANAj}}}ANAj}\",[]]Ak[\"{{{AHEf{AGK`}}}AGK`}\",[]]Ak[\"{{{AHEf{BBA`}}}BBA`}\",[]]Ak[\"{{{AHEf{BCGl}}}BCGl}\",[]]Ak[\"{{{AHEf{ABAn}}}ABAn}\",[]]Ak[\"{{{AHEf{BCHd}}}BCHd}\",[]]Ak[\"{{{AHEf{AOCf}}}AOCf}\",[]]Ak[\"{{{AHEf{BBBl}}}BBBl}\",[]]Ak[\"{{{AHEf{BFBd}}}BFBd}\",[]]Ak[\"{{{AHEf{ABCh}}}ABCh}\",[]]Ak[\"{{{AHEf{BDCh}}}BDCh}\",[]]Ak[\"{{{AHEf{AOCl}}}AOCl}\",[]]Ak[\"{{{AHEf{AODd}}}AODd}\",[]]Ak[\"{{{AHEf{BAF`}}}BAF`}\",[]]Ak[\"{{{AHEf{BDK`}}}BDK`}\",[]]Ak[\"{{{AHEf{AIB`}}}AIB`}\",[]]Ak[\"{{{AHEf{BFNb}}}BFNb}\",[]]Ai[\"{{{AHEf{CJf}}}CJf}\",[]]Ag[\"{{{AHEf{Nd}}}Nd}\",[]]Ak[\"{{{AHEf{ABEj}}}ABEj}\",[]]Ak[\"{{{AHEf{AGJl}}}AGJl}\",[]]Ak[\"{{{AHEf{B@Hf}}}B@Hf}\",[]]Ak[\"{{{AHEf{BE@b}}}BE@b}\",[]]Ai[\"{{{AHEf{JBf}}}JBf}\",[]]Ak[\"{{{AHEf{BEGb}}}BEGb}\",[]]Ai[\"{{{AHEf{JBd}}}JBd}\",[]]Ag[\"{{{AHEf{Mh}}}Mh}\",[]]Ak[\"{{{AHEf{AGIj}}}AGIj}\",[]]Ai[\"{{{AHEf{J@j}}}J@j}\",[]]Ak[\"{{{AHEf{ANBd}}}ANBd}\",[]]Ai[\"{{{AHEf{OA`}}}OA`}\",[]]Ak[\"{{{AHEf{B@Fl}}}B@Fl}\",[]]Ai[\"{{{AHEf{JBn}}}JBn}\",[]]Ak[\"{{{AHEf{ABEd}}}ABEd}\",[]]Ak[\"{{{AHEf{ABFn}}}ABFn}\",[]]Ak[\"{{{AHEf{AODf}}}AODf}\",[]]Ak[\"{{{AHEf{BDOd}}}BDOd}\",[]]Ak[\"{{{AHEf{BBBd}}}BBBd}\",[]]Bn[\"{{{AHEf{AI@l}}LB`{AHEf{{KIl{Ll}}}}}HEh}\",[]]Bn[\"{{{AHEf{ABBj}}LB`{AHEf{{KIl{Ll}}}}}HEh}\",[]]Bd[\"{{{AHEf{CIf}}}{{L@f{`BAAd}}}}\",[]]Bf[\"{{{AHEf{C@bAI@n}}O@bLBbIOn}HEh}\",[]]Bj[\"{{{AHEf{AOCj}}}{{AHEf{{KIl{Ll}}}}}}\",[]]Bj[\"{{{AHEf{AOCl}}}{{AHEf{{KIl{Ll}}}}}}\",[]]Aa[\"{B@EhAGLh}\",[]]k[\"{{}}\",[]]A`[\"{ABEhCG`}\",[]]A`[\"{ABEjCG`}\",[]]A`[\"{AODbCKh}\",[]]A`[\"{AODdCKh}\",[]]l[\"{O@d}\",[]]l[\"{O@f}\",[]]Ce[\"{{{AHEf{BDGf}}{AHEf{C@bMn}}}{{L@f{AOClBDCh}}}}\",[]]Ce[\"{{{AHEf{BGAd}}{AHEf{C@bMn}}}{{L@f{AOClBDCh}}}}\",[]]Bc[\"{{{AHEf{AI@n}}}{{A@`{L@b}}}}\",[]]Bd[\"{{{AHEf{JDh}}{AHEf{CFj}}}HEh}\",[]]Am[\"{{{AHEf{ANAd}}KL`}HEh}\",[]]Ai[\"{{{AHEf{JDj}}}HEh}\",[]]Bf[\"{{{Oj{{AHEf{C@bAHOf}}}}O@b}HEh}\",[]]Bm[\"{{{AHEf{C@bAIDh}}LB`}{{L@f{HEhAOBh}}}}\",[]]Bm[\"{{{AHEf{C@bAIDj}}LBb}{{L@f{HEhAOC`}}}}\",[]]Am[\"{ABCb{{L@f{HEhAIDb}}}}\",[]]Dc[\"{{{AHEf{C@bABBl}}ABCd{AHEf{C@b{A@`{Ll}}}}}{{L@f{ABFlAIDd}}}}\",[]]Bh[\"{{{AHEf{OBf}}{Oj{{Ml{KNl}}}}}HEh}\",[]]Bi[\"{{{AHEf{AOHh}}{Oj{{Ml{KNl}}}}}HEh}\",[]]Bi[\"{{{AHEf{ANDf}}{Oj{{Ml{KNl}}}}}HEh}\",[]]n[\"{ObCKh}\",[]]Ak[\"{{{AHEf{AI@l}}}BBAj}\",[]]Ak[\"{{{AHEf{ABBj}}}B@Dd}\",[]]An[\"{{{AHEf{C@bAI@n}}}BBAl}\",[]]Ce[\"{{{AHEf{C@bAICf}}{KOl{LAl}}}{{AHEf{C@bAICf}}}}\",[]]Ce[\"{{{AHEf{C@bAICh}}{KOl{LAl}}}{{AHEf{C@bAICh}}}}\",[]]Ck[\"{{{AHEf{C@bAIDh}}{AHEf{{KIl{Ll}}}}}{{L@f{KL`AIFb}}}}\",[]]Ck[\"{{{AHEf{C@bAIDj}}{AHEf{{KIl{Ll}}}}}{{L@f{KL`AIFd}}}}\",[]]Bl[\"{{{AHEf{BE@b}}{AHEf{C@bc}}}HEhKMf}\",[\"W\"]]Aj[\"{{{AHEf{ABBj}}}KLh}\",[]]An[\"{ABCb{{L@f{AI@hBBAb}}}}\",[]]Bh[\"{{{AHEf{C@bOCf}}Nd}{{KOl{ABEj}}}}\",[]]Fh[\"{{{AHEf{C@bABBl}}ABCdO@b{AHEf{C@b{A@`{Ll}}}}{KOl{{Md{AOGn}}}}}{{L@f{{KKn{BCHdAI@n}}{Ml{AN@n}}}}}}\",[]]Am[\"{AHEf{{AHEf{c}}}{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000o[\"{OD`KL`}\",[]]o[\"{ODbKL`}\",[]]o[\"{ObANAb}\",[]]Bb[\"{{AIDnBAAbOb}{{L@j{ANAd}}}}\",[]]Aj[\"{AIDn{{L@h{ABBj}}}}\",[]]B`[\"{{}{{L@f{HEh{Ml{JAd}}}}}}\",[]]Ak[\"{{{AHEf{AI@l}}}BBAb}\",[]]Be[\"{{{AHEf{ABBl}}}{{AHEf{BABj}}}}\",[]]o[\"{LlBDJn}\",[]]A`[\"{AIAhCG`}\",[]]o[\"{AOGjMd}\",[]]o[\"{LlBDK`}\",[]]A`[\"{AIAjCG`}\",[]]o[\"{AOGnMd}\",[]]A`[\"{BAF`KOl}\",[]]Bl[\"{{{AHEf{C@bc}}}{{L@f{LB`B@Hf}}}Mn}\",[\"B\"]]Bl[\"{{{AHEf{C@bc}}}{{L@f{L@`B@Hf}}}Mn}\",[\"B\"]]Bm[\"{{{AHEf{C@bc}}}{{L@f{AGJnB@Hf}}}Mn}\",[\"B\"]]Bm[\"{{{AHEf{C@bc}}}{{L@f{BDJnB@Hf}}}Mn}\",[\"B\"]]Bm[\"{{{AHEf{C@bc}}}{{L@f{ABEhB@Hf}}}Mn}\",[\"B\"]]Bh[\"{{{AHEf{C@bc}}}{{L@n{LBb}}}Mn}\",[\"B\"]]Bh[\"{{{AHEf{C@bc}}}{{L@n{L@b}}}Mn}\",[\"B\"]]Bi[\"{{{AHEf{C@bc}}}{{L@n{AGK`}}}Mn}\",[\"B\"]]Ek[\"{{{AHEf{C@b{KNj{ABAd}}}}{AHEf{c}}{AHEf{{KIl{CFn}}}}CKh}{{L@f{BBBlBDCh}}}{BDGfJDf}}\",[\"\"]]Bi[\"{{{AHEf{C@bc}}}{{L@n{BDK`}}}Mn}\",[\"B\"]]Bi[\"{{{AHEf{C@bc}}}{{L@n{ABEj}}}Mn}\",[\"B\"]]Bi[\"{{{AHEf{C@bc}}}{{L@n{AGJf}}}Mn}\",[\"B\"]]A`[\"{ABEdKOl}\",[]]Bk[\"{{{AHEf{LB`}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bk[\"{{{AHEf{L@`}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{AGJn}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{BDJn}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{ABEh}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bk[\"{{{AHEf{LBb}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bk[\"{{{AHEf{L@b}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{AGK`}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{ABAn}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{BDK`}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{ABEj}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bl[\"{{{AHEf{AGJh}}{AHEf{C@bc}}}HEhKMf}\",[\"B\"]]Bj[\"{{{AHEf{C@bAIDh}}}{{L@f{HEhAOBh}}}}\",[]]Bj[\"{{{AHEf{C@bAIDj}}}{{L@f{HEhANBj}}}}\",[]]An[\"{{{AHEf{ANEb}}ABBf}HEh}\",[]]Ea[\"{{{AHEf{C@bABBl}}O@bAGJl{KOl{AODd}}ABAd{AHEf{C@b{A@`{Ll}}}}}{{KOl{B@D`}}}}\",[]]o[\"{CHlO@d}\",[]]o[\"{CHnO@f}\",[]]A`[\"{ABCbHEh}\",[]]Ba[\"{{{AHEf{C@bABBl}}ABCd}HEh}\",[]]Bh[\"{{{AHEf{AIEl}}{AHEf{CFj}}IOn}HEh}\",[]]Bh[\"{{{AHEf{BADb}}{AHEf{CFj}}IOn}HEh}\",[]]Bh[\"{{{AHEf{BCKf}}{AHEf{CFj}}IOn}HEh}\",[]]Bh[\"{{{AHEf{AIEn}}{AHEf{CFj}}IOn}HEh}\",[]]Bh[\"{{{AHEf{BADd}}{AHEf{CFj}}IOn}HEh}\",[]]Bh[\"{{{AHEf{BCKh}}{AHEf{CFj}}IOn}HEh}\",[]]A`[\"{AGInCKh}\",[]]o[\"{J@`CG`}\",[]]o[\"{J@bCG`}\",[]]Ce[\"{{{AHEf{C@bAIA`}}O@bO@bCG`CKh{AHEf{AOG`}}}HEh}\",[]]Cc[\"{{{AHEf{C@bMf}}O@bO@bCG`CKh{AHEf{AOG`}}}HEh}\",[]]Cd[\"{{{AHEf{C@bJ@h}}O@bO@bCG`CKh{AHEf{AOG`}}}HEh}\",[]]Cd[\"{{{AHEf{C@bO@n}}O@bO@bCG`CKh{AHEf{AOG`}}}HEh}\",[]]Ce[\"{{{AHEf{C@bAIAb}}O@bO@bCG`CKh{AHEf{AOGb}}}HEh}\",[]]Cc[\"{{{AHEf{C@bMh}}O@bO@bCG`CKh{AHEf{AOGb}}}HEh}\",[]]Cd[\"{{{AHEf{C@bJ@j}}O@bO@bCG`CKh{AHEf{AOGb}}}HEh}\",[]]Cd[\"{{{AHEf{C@bOA`}}O@bO@bCG`CKh{AHEf{AOGb}}}HEh}\",[]]o[\"{CHlO@d}\",[]]o[\"{CHnO@f}\",[]]o[\"{BCKnLl}\",[]]A`[\"{BB@lIOn}\",[]]A`[\"{BCGhIOn}\",[]]A`[\"{BBA`IOn}\",[]]A`[\"{BCGlIOn}\",[]]A`[\"{BAF`LAl}\",[]]Aa[\"{BAAjBBAd}\",[]]Bg[\"{{{AHEf{ABBj}}AGMn}{{L@h{HEh}}}}\",[]]A`[\"{ABCbHEh}\",[]]Cf[\"{{{AHEf{C@bABBl}}ABCd{AHEf{C@b{A@`{Ll}}}}}ABFl}\",[]]l[\"{O@d}\",[]]Aa[\"{AGJlAIDn}\",[]]l[\"{O@f}\",[]]Am[\"{{ABBhOb}{{L@j{HEh}}}}\",[]]B`[\"{{AOGjAIDn}{{L@h{ABBj}}}}\",[]]Bb[\"{AOGh{{L@f{HEh{Ml{JAd}}}}}}\",[]]Bk[\"{{{AHEf{BDCj}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{BAEf}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{AGMf}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{AID`}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{BAEd}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{AIFb}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{AOHf}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{BBAb}}}{{KOl{{AHEf{JAd}}}}}}\",[]]Bk[\"{{{AHEf{BBAd}}}{{KOl{{AHEf{JAd}}}}}}\",[]]A`[\"{ABFjKOl}\",[]]A`[\"{ABFlKOl}\",[]]A`[\"{ABFnKOl}\",[]]Bg[\"{{{AHEf{CIf}}}{{L@f{AICbAHOn}}}}\",[]]Aa[\"{AOFlAICd}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]A`[\"{ABEdKL`}\",[]]Aa[\"{BBAjABG`}\",[]]Aa[\"{BBAlABGb}\",[]]10Dh[\"{{{AHEf{NOl}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhANAn}}}}\",[]]Dh[\"{{{AHEf{NOn}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhANB`}}}}\",[]]Aj[\"{{{AHEf{AIA`}}}CG`}\",[]]Ah[\"{{{AHEf{Mf}}}CG`}\",[]]Ai[\"{{{AHEf{J@h}}}CG`}\",[]]Ai[\"{{{AHEf{O@n}}}CG`}\",[]]Aj[\"{{{AHEf{AIAb}}}CG`}\",[]]Ah[\"{{{AHEf{Mh}}}CG`}\",[]]Ai[\"{{{AHEf{J@j}}}CG`}\",[]]Ai[\"{{{AHEf{OA`}}}CG`}\",[]]Aj[\"{{{AHEf{BEMh}}}KL`}\",[]]Aj[\"{{{AHEf{BEMj}}}KL`}\",[]]Aj[\"{{{AHEf{BFMh}}}KL`}\",[]]Aj[\"{{{AHEf{BFNb}}}KL`}\",[]]n[\"{ObKL`}\",[]]n[\"{{}NNn}\",[]]0000o[\"{N`ABAh}\",[]]Ba[\"{{AHEf{AHEf{c}}}ABDj{}}\",[\"K\"]]0000000000000000000Cg[\"{{{AHEf{ABBj}}AIDn{AHEf{CFj}}}{{L@f{AI@hAOCd}}}}\",[]]Dl[\"{{{AHEf{C@bABBl}}O@bAOB`AIDn{AHEf{CFj}}}{{L@f{{KKn{BCHdAI@n}}AOCf}}}}\",[]]Dm[\"{{{AHEf{AGLb}}L@`CG`{AHEf{{KIl{Ll}}}}{AHEf{C@bABAd}}}{{L@f{HEhANAn}}}}\",[]]Ca[\"{{{AHEf{AGKd}}KL`{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]Dm[\"{{{AHEf{AGLd}}L@bCG`{AHEf{{KIl{Ll}}}}{AHEf{C@bABAd}}}{{L@f{HEhANB`}}}}\",[]]Ca[\"{{{AHEf{AGKf}}KL`{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]o[\"{{}ANE`}\",[]]n[\"{{}JDh}\",[]]o[\"{{}ANAd}\",[]]o[\"{{}B@Cb}\",[]]o[\"{{}B@Dd}\",[]]n[\"{{}LB`}\",[]]n[\"{{}L@`}\",[]]o[\"{{}ABG`}\",[]]o[\"{{}AIAh}\",[]]o[\"{{}AGM`}\",[]]o[\"{{}BBAj}\",[]]n[\"{{}OD`}\",[]]o[\"{{}AOBh}\",[]]o[\"{{}BBCl}\",[]]o[\"{{}BDFj}\",[]]o[\"{{}BDHh}\",[]]o[\"{{}ANBl}\",[]]o[\"{{}BABh}\",[]]o[\"{{}BENj}\",[]]o[\"{{}BCKf}\",[]]o[\"{{}AGIh}\",[]]o[\"{{}ANBb}\",[]]o[\"{{}B@Fj}\",[]]o[\"{{}BDBj}\",[]]o[\"{{}B@Cd}\",[]]o[\"{{}BFMh}\",[]]n[\"{{}LBb}\",[]]n[\"{{}L@b}\",[]]o[\"{{}AICd}\",[]]o[\"{{}AI@d}\",[]]o[\"{{}ABGb}\",[]]o[\"{{}AIAj}\",[]]o[\"{{}AGMb}\",[]]o[\"{{}BBAl}\",[]]n[\"{{}ODb}\",[]]o[\"{{}BAEh}\",[]]o[\"{{}AOC`}\",[]]o[\"{{}BBCn}\",[]]o[\"{{}BDFl}\",[]]o[\"{{}BDHj}\",[]]o[\"{{}ANBn}\",[]]o[\"{{}BABj}\",[]]o[\"{{}BENl}\",[]]o[\"{{}BFNb}\",[]]o[\"{{}BCKh}\",[]]o[\"{{}AGIj}\",[]]o[\"{{}ANBd}\",[]]o[\"{{}B@Fl}\",[]]o[\"{{}BDBl}\",[]]o[\"{{}ABEd}\",[]]n[\"{{}JDj}\",[]]o[\"{{}BBBd}\",[]]o[\"{{}B@Db}\",[]]Ak[\"{{{AHEf{B@G`}}}AOCl}\",[]]Ak[\"{{{AHEf{BBBl}}}AOCl}\",[]]Aa[\"{BFBdAOCl}\",[]]Aa[\"{BDKbAOCl}\",[]]A`[\"{CI`AOCl}\",[]]A`[\"{JCnAOCl}\",[]]A`[\"{JDbAOCl}\",[]]Aa[\"{BCKnAOCl}\",[]]Cg[\"{{{AHEf{AGLb}}L@`CG`{AHEf{C@b{KIl{Ll}}}}KL`}HEh}\",[]]Ca[\"{{{AHEf{AGKd}}KL`{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]Cg[\"{{{AHEf{AGLd}}L@bCG`{AHEf{C@b{KIl{Ll}}}}KL`}HEh}\",[]]Ca[\"{{{AHEf{AGKf}}KL`{AHEf{C@b{KIl{Ll}}}}}HEh}\",[]]Aj[\"{{{AHEf{AICl}}}CKh}\",[]]Aj[\"{{{AHEf{BE@d}}}CKh}\",[]]Ak[\"{{{AHEf{AIA`}}}BDBj}\",[]]Ai[\"{{{AHEf{Mf}}}BDBj}\",[]]Aj[\"{{{AHEf{J@h}}}BDBj}\",[]]Aj[\"{{{AHEf{O@n}}}BDBj}\",[]]Ak[\"{{{AHEf{AIAb}}}BDBl}\",[]]Ai[\"{{{AHEf{Mh}}}BDBl}\",[]]Aj[\"{{{AHEf{J@j}}}BDBl}\",[]]Aj[\"{{{AHEf{OA`}}}BDBl}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CFl}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CFl}{{AHEf{C@bBBCn}}}}\",[]]Bf[\"{{{AHEf{C@bAIA`}}O@bCG`CG`}HEh}\",[]]Bd[\"{{{AHEf{C@bMf}}O@bCG`CG`}HEh}\",[]]Bf[\"{{{AHEf{C@bAIAb}}O@bCG`CG`}HEh}\",[]]Bd[\"{{{AHEf{C@bMh}}O@bCG`CG`}HEh}\",[]]Aj[\"{{{AHEf{AI@l}}}KOb}\",[]]Bc[\"{{{AHEf{ABDh}}}{{KOl{L@`}}}}\",[]]Aa[\"{BFBdAOCl}\",[]]Aa[\"{BDKbAOCl}\",[]]A`[\"{CI`AOCl}\",[]]A`[\"{JCnAOCl}\",[]]Aa[\"{BCKnAOCl}\",[]]Di[\"{{{AHEf{AIDh}}}{{`{{KNl{}{{KOn{{L@f{{KOl{LB`}}AOHf}}}}}}CJbCJh}}}}\",[]]Bn[\"{{{AHEf{AIDj}}}{{L@f{{KOl{LBb}}AOC`}}}}\",[]]n[\"{ObKL`}\",[]]o[\"{JDhKL`}\",[]]Am[\"{{{AHEf{C@bAI@n}}}OCf}\",[]]Aj[\"{{{AHEf{AGLb}}}KL`}\",[]]Aj[\"{{{AHEf{AGLd}}}KL`}\",[]]A`[\"{AHEfLAn}\",[]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bd[\"{{{AHEf{BEGn}}}{{KOl{AI@l}}}}\",[]]Bn[\"{{{AHEf{C@bAOAl}}CFn}{{AHEf{C@bAOAl}}}}\",[]]Bn[\"{{{AHEf{C@bAOB`}}CFn}{{AHEf{C@bAOB`}}}}\",[]]A`[\"{BFBdCFn}\",[]]A`[\"{BDKbCFn}\",[]]o[\"{CI`CFn}\",[]]o[\"{JCnCFn}\",[]]A`[\"{AGInKOl}\",[]]Aa[\"{ABFnAHEf}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Aa[\"{BAEjABBf}\",[]]A`[\"{KMhBAEh}\",[]]Aa[\"{BBAjAIAh}\",[]]Aa[\"{BBAlAIAj}\",[]]10Bg[\"{{{AHEf{C@bc}}KL`}AOCj{MnJDf}}\",[\"\"]]Bg[\"{{{AHEf{C@bc}}KL`}AOCl{MnJDf}}\",[\"\"]]o[\"{{}BBBn}\",[]]o[\"{{}BBC`}\",[]]A`[\"{CG`BFMh}\",[]]Cd[\"{{{AHEf{CFj}}}{{L@j{ANAbc}}}{}}\",[\"FromStr::Err\"]]o[\"{CFnLB`}\",[]]o[\"{CFnLBb}\",[]]Al[\"{CG`{{L@f{LB`BEGh}}}}\",[]]Al[\"{CG`{{L@f{LBbBEGj}}}}\",[]]Aa[\"{BEFbANAl}\",[]]Aa[\"{BGAfB@E`}\",[]]Aa[\"{BEFdANAl}\",[]]Aa[\"{BGAhB@E`}\",[]]Af[\"{{}{{KOl{Ab}}}}\",[]]0000Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]Bo[\"{{{AHEf{C@bBDHh}}ABBf}{{AHEf{C@bBDHh}}}}\",[]]Bo[\"{{{AHEf{C@bBDHj}}ABBf}{{AHEf{C@bBDHj}}}}\",[]]Ao[\"{{{Ml{AIA`}}}{{Ml{Mb}}}}\",[]]Am[\"{{{Ml{Mf}}}{{Ml{Mb}}}}\",[]]An[\"{{{Ml{J@h}}}{{Ml{Mb}}}}\",[]]An[\"{{{Ml{O@n}}}{{Ml{Mb}}}}\",[]]Ao[\"{{{Ml{AIAb}}}{{Ml{Mb}}}}\",[]]Am[\"{{{Ml{Mh}}}{{Ml{Mb}}}}\",[]]An[\"{{{Ml{J@j}}}{{Ml{Mb}}}}\",[]]An[\"{{{Ml{OA`}}}{{Ml{Mb}}}}\",[]]Aj[\"{{{AHEf{BEGn}}}CKh}\",[]]Bo[\"{{{AHEf{C@bBENj}}ABBf}{{AHEf{C@bBENj}}}}\",[]]Bo[\"{{{AHEf{C@bBENl}}ABBf}{{AHEf{C@bBENl}}}}\",[]]Bc[\"{{{AHEf{AI@h}}}{{KOl{KO`}}}}\",[]]Bc[\"{{{AHEf{AI@l}}}{{KOl{KO`}}}}\",[]]Bc[\"{{{AHEf{ABCb}}}{{KOl{KO`}}}}\",[]]Bc[\"{{{AHEf{ABCd}}}{{KOl{KO`}}}}\",[]]A`[\"{AGJlKOl}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Bc[\"{{{AHEf{AGJd}}}{{KOl{KL`}}}}\",[]]Am[\"{{{AHEf{ANEb}}KL`}HEh}\",[]]Aj[\"{{{AHEf{AI@l}}}OAd}\",[]]Bg[\"{{{AHEf{AIDh}}}{{L@f{BNlAOBh}}}}\",[]]Bg[\"{{{AHEf{AIDj}}}{{L@f{BNlAOC`}}}}\",[]]A`[\"{B@DhKOl}\",[]]A`[\"{B@DjKOl}\",[]]A`[\"{AGInKOl}\",[]]A`[\"{AN@nKOl}\",[]]Ck[\"{{{AHEf{C@bBABh}}{KOl{{JE`{Ll}}}}}{{AHEf{C@bBABh}}}}\",[]]Ck[\"{{{AHEf{C@bBABj}}{KOl{{JE`{Ll}}}}}{{AHEf{C@bBABj}}}}\",[]]A`[\"{BDBjKOl}\",[]]A`[\"{BDBlKOl}\",[]]Ac[\"{AHEfc{}}\",[\"T\"]]0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Ao[\"{c{{L@f{e}}}{}{}}\",[\"U\",\"T\"]]00000000000000000000000000000000000000000000Al[\"{KL`{{L@f{LB`BEGh}}}}\",[]]Al[\"{HEf{{L@f{LB`BEGh}}}}\",[]]Al[\"{CG`{{L@f{LB`BEGh}}}}\",[]]333333333333333Aj[\"{ABBf{{L@f{ANBl}}}}\",[]]44444Ai[\"{CG`{{L@f{AGJn}}}}\",[]]555555555555555555555555555Bb[\"{{{Md{AOAh}}}{{L@f{BCJn}}}}\",[]]Aj[\"{AOAh{{L@f{BCJn}}}}\",[]]7Bb[\"{{{Md{AOGf}}}{{L@f{BCKb}}}}\",[]]Aj[\"{AOGf{{L@f{BCKb}}}}\",[]]9999999999999999999Al[\"{KL`{{L@f{LBbBEGj}}}}\",[]]Al[\"{HEf{{L@f{LBbBEGj}}}}\",[]]Al[\"{CG`{{L@f{LBbBEGj}}}}\",[]]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Bm[\"{AOAh{{L@f{BCK`c}}}{}}\",[\"TryFrom::Error\"]]Ce[\"{{{Md{AOAh}}}{{L@f{BCK`c}}}{}}\",[\"TryFrom::Error\"]]Ao[\"{c{{L@f{e}}}{}{}}\",[\"U\",\"T\"]]Bm[\"{AOGf{{L@f{BCKdc}}}{}}\",[\"TryFrom::Error\"]]Ce[\"{{{Md{AOGf}}}{{L@f{BCKdc}}}{}}\",[\"TryFrom::Error\"]]2222222222222222222222222222Aj[\"{{}{{L@f{c}}}{}}\",[\"U\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cc[\"{{{Oj{{AHEf{C@bc}}}}{AHEf{C@bNO`}}}CIn{}}\",[\"F\"]]00000000Cc[\"{{{AHEf{BAFb}}AIF`{AHEf{ABFn}}}{{L@h{HEh}}}}\",[]]Bk[\"{{{AHEf{BEMh}}AOCj}{{L@f{HEhAIAn}}}}\",[]]Bk[\"{{{AHEf{BEMj}}AOCl}{{L@f{HEhAIB`}}}}\",[]]0Bk[\"{{{AHEf{BFMh}}AOCl}{{L@f{HEhAIB`}}}}\",[]]Ak[\"{{{AHEf{AI@l}}}ABAb}\",[]]Bi[\"{{{AHEf{C@bAOHj}}}{{L@f{LB`JB`}}}}\",[]]Bi[\"{{{AHEf{C@bAOHj}}}{{L@f{CJdJB`}}}}\",[]]Bh[\"{{{AHEf{C@bAOHj}}}{{L@f{NbJB`}}}}\",[]]Bj[\"{{{AHEf{C@bAOHj}}}{{L@f{ABEhJB`}}}}\",[]]Bf[\"{{{AHEf{C@bAOHj}}}{{L@l{LBb}}}}\",[]]Bf[\"{{{AHEf{C@bAOHj}}}{{L@l{CJf}}}}\",[]]Be[\"{{{AHEf{C@bAOHj}}}{{L@l{Nd}}}}\",[]]Bg[\"{{{AHEf{C@bAOHj}}}{{L@l{ABEj}}}}\",[]]Aa[\"{ANAbBEGf}\",[]]Bc[\"{{{AHEf{AIA`}}}{{Ml{AIA`}}}}\",[]]Ba[\"{{{AHEf{Mf}}}{{Ml{AIA`}}}}\",[]]Bb[\"{{{AHEf{J@h}}}{{Ml{AIA`}}}}\",[]]Bb[\"{{{AHEf{O@n}}}{{Ml{AIA`}}}}\",[]]Bc[\"{{{AHEf{AIAb}}}{{Ml{AIAb}}}}\",[]]Ba[\"{{{AHEf{Mh}}}{{Ml{AIAb}}}}\",[]]Bb[\"{{{AHEf{J@j}}}{{Ml{AIAb}}}}\",[]]Bb[\"{{{AHEf{OA`}}}{{Ml{AIAb}}}}\",[]]A`[\"{ABG`CG`}\",[]]An[\"{{{AHEf{C@bAI@n}}}AGJd}\",[]]A`[\"{ABGbCG`}\",[]]C`[\"{{{AHEf{C@bAOCj}}}{{AHEf{C@b{KIl{Ll}}}}}}\",[]]C`[\"{{{AHEf{C@bAOCl}}}{{AHEf{C@b{KIl{Ll}}}}}}\",[]]Ah[\"{Ll{{KOl{AODb}}}}\",[]]Ah[\"{Ll{{KOl{AODd}}}}\",[]]Ah[\"{Ll{{KOl{AODf}}}}\",[]]A`[\"{ABEhCJd}\",[]]A`[\"{ABEjCJf}\",[]]Bi[\"{AI@h{{L@f{{KKn{AI@lBBDf}}AI@h}}}}\",[]]o[\"{CJdCKh}\",[]]o[\"{CJfCKh}\",[]]Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]21Aj[\"{{{AHEf{ABCb}}}CKh}\",[]]Aj[\"{{{AHEf{ABCd}}}CKh}\",[]]Bn[\"{{{AHEf{C@bAOGj}}CKh}{{AHEf{C@bAOGj}}}}\",[]]Bn[\"{{{AHEf{C@bAOGn}}CKh}{{AHEf{C@bAOGn}}}}\",[]]Bk[\"{{{AHEf{OBf}}O@b}{{Oj{{Ml{AHOf}}}}}}\",[]]Bl[\"{{{AHEf{AOHh}}O@b}{{Oj{{Ml{AHOf}}}}}}\",[]]Bl[\"{{{AHEf{ANDf}}O@b}{{Oj{{Ml{AHOf}}}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Ak[\"{{{AHEf{AI@l}}}ABDf}\",[]]Bc[\"{{{AHEf{AI@l}}AIDnAICb}ABDh}\",[]]Ce[\"{{{AHEf{C@bAI@n}}AGJlAICdO@b}{{L@f{L@bAGLh}}}}\",[]]43Bm[\"{{{AHEf{C@bAI@n}}L@b}{{L@f{HEhAI@d}}}}\",[]]Do[\"{{{Oj{{AHEf{C@bAICl}}}}{AHEf{C@bNO`}}{AHEf{C@bOB`}}}{{CIn{{L@h{HEh}}}}}}\",[]]Ee[\"{{{Oj{{AHEf{C@bAICl}}}}{AHEf{C@bNO`}}{AHEf{C@b{KIl{Ll}}}}}{{CIn{{L@h{KL`}}}}}}\",[]]Ec[\"{{{AHEf{C@bAICl}}{AHEf{C@bNO`}}{AHEf{C@b{KIl{Ll}}}}}{{CIn{{L@f{KL`AGMf}}}}}}\",[]]Fg[\"{{{AHEf{C@bBAA`}}{AHEf{C@bNO`}}{AHEf{C@b{KIl{AIBb}}}}{AHEf{C@b{KIl{ABEd}}}}}{{CIn{{L@h{KL`}}}}}}\",[]]Dm[\"{{{Oj{{AHEf{C@bAGMl}}}}{AHEf{ABFn}}{AHEf{C@bNO`}}}{{CIn{{L@h{HEh}}}}}}\",[]]:9Cd[\"{{{AHEf{C@bBABh}}{Md{NOl}}}{{AHEf{C@bBABh}}}}\",[]]Cd[\"{{{AHEf{C@bBABj}}{Md{NOn}}}{{AHEf{C@bBABj}}}}\",[]]Cj[\"{{{AHEf{AOGl}}CFnAOCj{AHEf{{KIl{Ll}}}}}{{JE`{Ll}}}}\",[]]Cj[\"{{{AHEf{BCKb}}CFnAOCj{AHEf{{KIl{Ll}}}}}{{JE`{Ll}}}}\",[]]Cj[\"{{{AHEf{AOH`}}CFnAOCl{AHEf{{KIl{Ll}}}}}{{JE`{Ll}}}}\",[]]Cj[\"{{{AHEf{BCKd}}CFnAOCl{AHEf{{KIl{Ll}}}}}{{JE`{Ll}}}}\",[]]Cj[\"{{{AHEf{BFHd}}CFnAOCh{AHEf{{KIl{Ll}}}}}{{JE`{Ll}}}}\",[]]Bb[\"{KL`{{KKn{KL`{KOl{KL`}}}}}}\",[]]00000Aj[\"{{{AHEf{AI@l}}}KL`}\",[]]A`[\"{AHEfLAl}\",[]]0000000000000000000000000000000000000000000000000000000Ce[\"{{{AHEf{C@bAOGj}}{Md{BDBn}}}{{AHEf{C@bAOGj}}}}\",[]]Ce[\"{{{AHEf{C@bAOGn}}{Md{BDC`}}}{{AHEf{C@bAOGn}}}}\",[]]A`[\"{BFBdJCd}\",[]]o[\"{AOGjMd}\",[]]o[\"{AOGnMd}\",[]]Aj[\"{{{AHEf{ABBj}}}HEh}\",[]]Ck[\"{{{AHEf{C@bAIDh}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhAIFb}}}}\",[]]n[\"{{}KL`}\",[]]Ak[\"{{{AHEf{AI@l}}}AGHj}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CKh}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CKh}{{AHEf{C@bBBCn}}}}\",[]]Bi[\"{{{AHEf{C@b}}}{{AHEf{C@bc}}}{}}\",[\"T\"]]000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Bc[\"{{AHEf{AHEf{C@bc}}}HEh{}}\",[\"T\"]]0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Cc[\"{{{AHEf{C@bAI@n}}O@bL@bLBb}{{L@f{HEhBAAf}}}}\",[]]A`[\"{AGInCKh}\",[]]B`[\"{{AHEf{AHEf{c}}}CKh{}}\",[\"K\"]]00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Aa[\"{BB@lBDJn}\",[]]A`[\"{BCGhLB`}\",[]]Aa[\"{BBA`BDK`}\",[]]A`[\"{BCGlLBb}\",[]]o[\"{KN`LBb}\",[]]o[\"{OBlLBb}\",[]]Aa[\"{BB@lAIBd}\",[]]k[\"{{}}\",[]]o[\"{LB`CG`}\",[]]o[\"{LBbCG`}\",[]]Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]Aj[\"{{{AHEf{B@Db}}}CKh}\",[]]Bd[\"{{{AHEf{BAA`}}}{{L@h{AIDn}}}}\",[]]Bd[\"{{{AHEf{ABBj}}}{{L@h{AIDn}}}}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]Cb[\"{{{AHEf{BBBd}}{AHEf{AIDf}}CG`}{{Md{ANEb}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CKh}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CKh}{{AHEf{C@bBBCn}}}}\",[]]Bg[\"{{{AHEf{AI@l}}L@`}{{KOl{AGM`}}}}\",[]]Bj[\"{{{AHEf{C@bAI@n}}L@b}{{KOl{AGMb}}}}\",[]]Aa[\"{AGHfAGMb}\",[]]Da[\"{{{Oj{{AHEf{C@bAIDh}}}}{AHEf{C@bNO`}}}{{CIn{{L@h{HEh}}}}}}\",[]]00Eb[\"{{{Oj{{AHEf{C@bAIDh}}}}{AHEf{C@bNO`}}{AHEf{{KIl{Ll}}}}}{{CIn{{L@h{KL`}}}}}}\",[]]Ef[\"{{{Oj{{AHEf{C@bAIDh}}}}{AHEf{C@bNO`}}{AHEf{{KIl{Ll}}}}}{{CIn{{L@f{KL`AIFb}}}}}}\",[]]1Bm[\"{{{AHEf{JDj}}{AHEf{CId}}}{{L@h{HEh}}}}\",[]]Cd[\"{{{AHEf{C@bAICl}}KL`}{{L@f{{KOl{J@`}}AGMf}}}}\",[]]Cd[\"{{{AHEf{C@bBE@d}}KL`}{{L@f{{KOl{J@`}}AGMf}}}}\",[]]Cn[\"{{{AHEf{C@bAICl}}{AHEf{C@b{KIl{Ll}}}}}{{L@f{HEhBAEd}}}}\",[]]Bj[\"{{{AHEf{CIf}}AICb}{{L@f{HEhBDJf}}}}\",[]]Bn[\"{{{AHEf{C@bAICf}}O@b}{{AHEf{C@bAICf}}}}\",[]]Bn[\"{{{AHEf{C@bAICh}}O@b}{{AHEf{C@bAICh}}}}\",[]]A`[\"{BAEjACn}\",[]]o[\"{JDhCG`}\",[]]o[\"{{}AIDn}\",[]]0o[\"{{}AHEf}\",[]]Bj[\"{{ABCb{Md{AOGj}}}{{L@f{AI@hBBAb}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Bh[\"{{{AHEf{AGIn}}AIDn}{{L@j{AGMn}}}}\",[]]A`[\"{AGM`CFl}\",[]]Aj[\"{{{AHEf{AI@n}}}CFl}\",[]]A`[\"{AGMbCFl}\",[]]Ce[\"{{{AHEf{C@bAICf}}{KOl{LAl}}}{{AHEf{C@bAICf}}}}\",[]]Ce[\"{{{AHEf{C@bAICh}}{KOl{LAl}}}{{AHEf{C@bAICh}}}}\",[]]Aa[\"{ABFjAIDn}\",[]]Aa[\"{ABFlAIDn}\",[]]Aa[\"{ABFnAIDn}\",[]]n[\"{ObCFl}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CFl}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CFl}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGInCFl}\",[]]Bo[\"{{{AHEf{C@bBBCl}}ABBf}{{AHEf{C@bBBCl}}}}\",[]]Bo[\"{{{AHEf{C@bBBCn}}ABBf}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGInKOl}\",[]]k[\"{{}}\",[]]0000000000Bh[\"{ABCbc{}}\",[\"IntoFuture::IntoFuture\"]]1A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]n[\"{ObKL`}\",[]]Ao[\"{{AHEfc}{{O@h{c}}}{}}\",[\"S\"]]0C`[\"{{{AHEf{C@bAIA`}}O@bCG`CKh{KOl{CG`}}}HEh}\",[]]Bn[\"{{{AHEf{C@bMf}}O@bCG`CKh{KOl{CG`}}}HEh}\",[]]C`[\"{{{AHEf{C@bAIAb}}O@bCG`CKh{KOl{CG`}}}HEh}\",[]]Bn[\"{{{AHEf{C@bMh}}O@bCG`CKh{KOl{CG`}}}HEh}\",[]]Bk[\"{{{AHEf{C@bJDj}}O@b{AHEf{BBBd}}}HEh}\",[]]A`[\"{BDBjKOl}\",[]]A`[\"{BDBlKOl}\",[]]Bn[\"{{{AHEf{LB`}}{AHEf{LB`}}}{{KOl{ABDj}}}}\",[]]Bn[\"{{{AHEf{L@`}}{AHEf{L@`}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{ANBl}}{AHEf{ANBl}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{AOCj}}{AHEf{AOCj}}}{{KOl{ABDj}}}}\",[]]Bn[\"{{{AHEf{CJd}}{AHEf{CJd}}}{{KOl{ABDj}}}}\",[]]Bl[\"{{{AHEf{Nb}}{AHEf{Nb}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{ABEh}}{AHEf{ABEh}}}{{KOl{ABDj}}}}\",[]]Bn[\"{{{AHEf{LBb}}{AHEf{LBb}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{BDCl}}{AHEf{BDCl}}}{{KOl{ABDj}}}}\",[]]Bn[\"{{{AHEf{L@b}}{AHEf{L@b}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{AGMh}}{AHEf{AGMh}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{B@Gj}}{AHEf{B@Gj}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{AIFd}}{AHEf{AIFd}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{ANBn}}{AHEf{ANBn}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{BCHd}}{AHEf{BCHd}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{BDCh}}{AHEf{BDCh}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{AOCl}}{AHEf{AOCl}}}{{KOl{ABDj}}}}\",[]]Bn[\"{{{AHEf{CJf}}{AHEf{CJf}}}{{KOl{ABDj}}}}\",[]]Bl[\"{{{AHEf{Nd}}{AHEf{Nd}}}{{KOl{ABDj}}}}\",[]]C`[\"{{{AHEf{ABEj}}{AHEf{ABEj}}}{{KOl{ABDj}}}}\",[]]Be[\"{{{AHEf{AI@l}}}{{ABE`{AGLl}}}}\",[]]Bk[\"{{{AHEf{AI@n}}L@b}{{L@f{AICdAI@d}}}}\",[]]Df[\"{{{AHEf{C@bAICl}}{AHEf{C@b{KIl{IOn}}}}}{{L@f{{KOl{KL`}}AGMf}}}}\",[]]Cc[\"{{{AHEf{C@bAICl}}KL`}{{L@f{{A@`{Ll}}BAEf}}}}\",[]]Bb[\"{{{AHEf{C@bAI@n}}ABEj}AICn}\",[]]Aj[\"{{{AHEf{AGKd}}}KL`}\",[]]Aj[\"{{{AHEf{AGKf}}}KL`}\",[]]Bb[\"{{{AHEf{C@bAI@n}}ABEj}AIDj}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CG`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CG`}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGInKOl}\",[]]A`[\"{B@DhKOl}\",[]]A`[\"{B@DjKOl}\",[]]Ce[\"{{{AHEf{C@bAOGj}}{Md{AIEd}}}{{AHEf{C@bAOGj}}}}\",[]]Ce[\"{{{AHEf{C@bAOGn}}{Md{AIEf}}}{{AHEf{C@bAOGn}}}}\",[]]Ce[\"{{{AHEf{C@bAOAl}}{Md{AIEl}}}{{AHEf{C@bAOAl}}}}\",[]]Ce[\"{{{AHEf{C@bAOB`}}{Md{AIEn}}}{{AHEf{C@bAOB`}}}}\",[]]n[\"{ObCG`}\",[]]Bn[\"{{{AHEf{C@bBDHh}}CFl}{{AHEf{C@bBDHh}}}}\",[]]Bn[\"{{{AHEf{C@bBDHj}}CFl}{{AHEf{C@bBDHj}}}}\",[]]Ak[\"{{{AHEf{AI@l}}}BEGn}\",[]]Ai[\"{{{Md{AOGl}}}AOGj}\",[]]Ai[\"{{{Md{AOH`}}}AOGn}\",[]]Aj[\"{{BBBnc}BBBnABF`}\",[\"\"]]Aj[\"{{BBC`c}BBC`ABF`}\",[\"\"]]Bm[\"{{{AHEf{C@bAIDh}}IOn}{{L@f{HEhAIFb}}}}\",[]]n[\"{{}KO`}\",[]]o[\"{NNnNNn}\",[]]0000Bd[\"{{{AHEf{BEMh}}}{{KOl{ABBf}}}}\",[]]Bd[\"{{{AHEf{BEMj}}}{{KOl{ABBf}}}}\",[]]Bd[\"{{{AHEf{BFMh}}}{{KOl{ABBf}}}}\",[]]Bd[\"{{{AHEf{BFNb}}}{{KOl{ABBf}}}}\",[]]Bd[\"{{{AHEf{AI@l}}}{{KOl{BBAb}}}}\",[]]Ck[\"{{{AHEf{ABBj}}AOAlAIDn{AHEf{CFj}}}{{L@f{AI@hAOCd}}}}\",[]]Ak[\"{{{AHEf{AOGb}}}ABBf}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]An[\"{{AICjCKh}{{L@j{KL`}}}}\",[]]Cj[\"{{{AHEf{OBh}}}{{KOl{{KKn{{Ml{AGKd}}{Ml{AGLb}}}}}}}}\",[]]Ck[\"{{{AHEf{AIEh}}}{{KOl{{KKn{{Ml{AGKd}}{Ml{AGLb}}}}}}}}\",[]]Cj[\"{{{AHEf{OBj}}}{{KOl{{KKn{{Ml{AGKf}}{Ml{AGLd}}}}}}}}\",[]]Ck[\"{{{AHEf{AIEj}}}{{KOl{{KKn{{Ml{AGKf}}{Ml{AGLd}}}}}}}}\",[]]A`[\"{BEFbA@`}\",[]]A`[\"{BGAfA@`}\",[]]A`[\"{BEFdA@`}\",[]]A`[\"{BGAhA@`}\",[]]An[\"{{{AHEf{C@bBEMh}}}AOCj}\",[]]An[\"{{{AHEf{C@bBEMj}}}AOCl}\",[]]An[\"{{{AHEf{C@bBFMh}}}AOCl}\",[]]An[\"{{{AHEf{C@bBFNb}}}AOCl}\",[]]Ak[\"{{{AHEf{BAFb}}}AOEh}\",[]]Ba[\"{{{AHEf{C@bAI@n}}BBAh}HEh}\",[]]Bo[\"{{{AHEf{C@bABBl}}BCHdB@Db}{{KOl{BBAh}}}}\",[]]B`[\"{{{AHEf{OBh}}AOCjCJd}CHl}\",[]]Bn[\"{{{AHEf{AOGl}}CFnAOCj}{{L@f{CHlBDKf}}}}\",[]]Ba[\"{{{AHEf{AIEh}}AOCjCJd}CHl}\",[]]Bn[\"{{{AHEf{BCKb}}CFnAOCj}{{L@f{CHlBDKf}}}}\",[]]B`[\"{{{AHEf{OBj}}AOClCJf}CHn}\",[]]Bn[\"{{{AHEf{AOH`}}CFnAOCl}{{L@f{CHnBDKl}}}}\",[]]Ba[\"{{{AHEf{AIEj}}AOClCJf}CHn}\",[]]Bn[\"{{{AHEf{BCKd}}CFnAOCl}{{L@f{CHnBDKl}}}}\",[]]Bn[\"{{{AHEf{BFHd}}CFnAOCh}{{L@f{CHnBDKl}}}}\",[]]Aj[\"{{}{{OBb{c}}}{}}\",[\"T\"]]0A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]Bn[\"{{{AHEf{C@bAOGj}}KL`}{{AHEf{C@bAOGj}}}}\",[]]Bn[\"{{{AHEf{C@bAOGn}}KL`}{{AHEf{C@bAOGn}}}}\",[]]Aj[\"{{{AHEf{BAA`}}}CKh}\",[]]0Aj[\"{{{AHEf{BAFb}}}CKh}\",[]]Bk[\"{{{AHEf{AI@n}}L@b}{{L@f{AGJlAI@d}}}}\",[]]Cb[\"{{{AHEf{BBBd}}{AHEf{AICj}}CG`}{{Md{ANEb}}}}\",[]]Ak[\"{{{AHEf{ABCb}}}AOCj}\",[]]Ak[\"{{{AHEf{ABCd}}}AOCl}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Bf[\"{{{AHEf{C@bAI@n}}}{{KOl{O@b}}}}\",[]]Ce[\"{{{AHEf{C@bBBCl}}{Md{ANCj}}}{{AHEf{C@bBBCl}}}}\",[]]Ce[\"{{{AHEf{C@bBBCn}}{Md{ANCl}}}{{AHEf{C@bBBCn}}}}\",[]]43A`[\"{ABFjKOl}\",[]]A`[\"{ABFlKOl}\",[]]A`[\"{ABFnKOl}\",[]]Ai[\"{{{AHEf{OCf}}}KL`}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]Bo[\"{{{AHEf{C@bBFMh}}ABBf}{{AHEf{C@bBFMh}}}}\",[]]Bo[\"{{{AHEf{C@bBFNb}}ABBf}{{AHEf{C@bBFNb}}}}\",[]]Bj[\"{{{AHEf{AIDh}}BNl}{{L@f{HEhAOBh}}}}\",[]]Bm[\"{{{AHEf{C@bAIDj}}BNl}{{L@f{HEhAOC`}}}}\",[]]>=A`[\"{JDhANE`}\",[]]A`[\"{ANAdJDh}\",[]]Bi[\"{{{Md{AOAh}}JDl}{{L@f{BCJnBEG`}}}}\",[]]Bi[\"{{{Md{AOGf}}JDl}{{L@f{BCKbBEG`}}}}\",[]]Bi[\"{{{Md{AOAh}}JDl}{{L@f{BCK`BEGb}}}}\",[]]Bi[\"{{{Md{AOGf}}JDl}{{L@f{BCKdBEGb}}}}\",[]]Co[\"{{{AHEf{C@bAIDh}}{AHEf{C@b{KIl{IOn}}}}}{{L@f{OD`AIFb}}}}\",[]]Co[\"{{{AHEf{C@bAIDj}}{AHEf{C@b{KIl{IOn}}}}}{{L@f{ODbAIFd}}}}\",[]]Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]A`[\"{AGInCKh}\",[]]E`[\"{{{AHEf{C@bBABh}}c}{{AHEf{C@bBABh}}}{{A`{}{{KOn{{Ml{BEMh}}}}}}CJbCJh}}\",[\"F\"]]E`[\"{{{AHEf{C@bBABj}}c}{{AHEf{C@bBABj}}}{{A`{}{{KOn{{Ml{BEMj}}}}}}CJbCJh}}\",[\"F\"]]Bi[\"{{{AHEf{BAA`}}}{{Oj{{Ml{AGMl}}}}}}\",[]]n[\"{ObCG`}\",[]]Aa[\"{ANE`AGKh}\",[]]76Aa[\"{AIDbABCb}\",[]]Aa[\"{AIDdABCd}\",[]]Cf[\"{{{AHEf{C@bBDFj}}{KOl{ABBf}}}{{AHEf{C@bBDFj}}}}\",[]]Cf[\"{{{AHEf{C@bBDFl}}{KOl{ABBf}}}{{AHEf{C@bBDFl}}}}\",[]]9;:An[\"{{{AHEf{ANEb}}ABBf}HEh}\",[]]B`[\"{{{AHEf{C@bAIA`}}CFl}HEh}\",[]]An[\"{{{AHEf{C@bMf}}CFl}HEh}\",[]]Ao[\"{{{AHEf{C@bJ@h}}CFl}HEh}\",[]]Ao[\"{{{AHEf{C@bO@n}}CFl}HEh}\",[]]B`[\"{{{AHEf{C@bAIAb}}CFl}HEh}\",[]]An[\"{{{AHEf{C@bMh}}CFl}HEh}\",[]]Ao[\"{{{AHEf{C@bJ@j}}CFl}HEh}\",[]]Ao[\"{{{AHEf{C@bOA`}}CFl}HEh}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]10Bh[\"{{{AHEf{AI@l}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bg[\"{{{AHEf{OBh}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bh[\"{{{AHEf{AIEh}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bg[\"{{{AHEf{OBj}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bh[\"{{{AHEf{AIEj}}}{{KOl{{Ml{Mb}}}}}}\",[]]Dm[\"{{{AHEf{C@bAICl}}{AHEf{C@bNO`}}{AHEf{C@bOB`}}}{{CIn{{L@f{HEhAGMf}}}}}}\",[]]Da[\"{{{Oj{{AHEf{C@bAIDh}}}}{AHEf{C@bNO`}}}{{CIn{{L@h{HEh}}}}}}\",[]]Db[\"{{{AHEf{C@bAI@n}}O@bAOEh{AHEf{C@b{A@`{Ll}}}}}{{KOl{ABFl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCl}}{AHEf{CFj}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{AHEf{CFj}}}{{AHEf{C@bBBCn}}}}\",[]]Ak[\"{{{AHEf{AI@l}}}AOFj}\",[]]Bj[\"{{{AHEf{AI@l}}IOn}{{L@f{HEhBDCj}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CKh}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CKh}{{AHEf{C@bBBCn}}}}\",[]]Ai[\"{{{AHEf{NOl}}}KL`}\",[]]Ai[\"{{{AHEf{NOn}}}KL`}\",[]]De[\"{{{Md{AOAn}}CFn{AHEf{CFj}}{AHEf{BE@b}}}{{L@f{{Ml{OBh}}AOCd}}}}\",[]]Bo[\"{{{Md{AOGl}}CFn{AHEf{BE@b}}}{{Ml{OBh}}}}\",[]]De[\"{{{Md{BCJn}}CFn{AHEf{CFj}}{AHEf{BE@b}}}{{L@f{{Ml{OBh}}AOCd}}}}\",[]]Bo[\"{{{Md{BCKb}}CFn{AHEf{BE@b}}}{{Ml{OBh}}}}\",[]]De[\"{{{Md{AOBb}}CFn{AHEf{CFj}}{AHEf{BE@b}}}{{L@f{{Ml{OBj}}AOCf}}}}\",[]]Bo[\"{{{Md{AOH`}}CFn{AHEf{BE@b}}}{{Ml{OBj}}}}\",[]]De[\"{{{Md{BCK`}}CFn{AHEf{CFj}}{AHEf{BE@b}}}{{L@f{{Ml{OBj}}AOCf}}}}\",[]]Bo[\"{{{Md{BCKd}}CFn{AHEf{BE@b}}}{{Ml{OBj}}}}\",[]]De[\"{{{Md{BFHb}}CFn{AHEf{CFj}}{AHEf{BE@b}}}{{L@f{{Ml{OBj}}AOCb}}}}\",[]]Bo[\"{{{Md{BFHd}}CFn{AHEf{BE@b}}}{{Ml{OBj}}}}\",[]]Bm[\"{KL`{{L@f{{KKn{KL`{KOl{KL`}}}}BDOf}}}}\",[]]0Cc[\"{{{AHEf{BDBn}}{AHEf{{KIl{Ll}}}}}{{Ml{NNd}}}}\",[]]Cc[\"{{{AHEf{BDC`}}{AHEf{{KIl{Ll}}}}}{{Ml{NNf}}}}\",[]]Bm[\"{{AIDnBAAbOb}{{L@j{{KKn{ABBhAI@j}}}}}}\",[]]Bd[\"{{{AHEf{AI@n}}}{{AHEf{OBj}}}}\",[]]A`[\"{ANAdJDh}\",[]]Cb[\"{{{AHEf{ANCj}}CJdAIDnAOCjO@b}{{KOl{AICf}}}}\",[]]Cb[\"{{{AHEf{BBBn}}CJdAIDnAOCjO@b}{{KOl{AICf}}}}\",[]]Cb[\"{{{AHEf{ANCl}}CJfAIDnAOClO@b}{{KOl{AICh}}}}\",[]]Cb[\"{{{AHEf{BBC`}}CJfAIDnAOClO@b}{{KOl{AICh}}}}\",[]]B`[\"{{{AHEf{C@bAI@n}}O@b}HEh}\",[]]Bo[\"{{{AHEf{C@bAI@h}}}{{L@f{{Ml{Mb}}BBAb}}}}\",[]]Bh[\"{{{AHEf{AI@l}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bg[\"{{{AHEf{OBh}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bh[\"{{{AHEf{AIEh}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bg[\"{{{AHEf{OBj}}}{{KOl{{Ml{Mb}}}}}}\",[]]Bh[\"{{{AHEf{AIEj}}}{{KOl{{Ml{Mb}}}}}}\",[]]o[\"{AIAhLl}\",[]]o[\"{AIAjLl}\",[]]Ai[\"{{{AHEf{CFj}}}CKh}\",[]]Aj[\"{{{AHEf{AIA`}}}CG`}\",[]]Ah[\"{{{AHEf{Mf}}}CG`}\",[]]Bn[\"{{{AHEf{C@bAGIh}}CG`}{{AHEf{C@bAGIh}}}}\",[]]Ai[\"{{{AHEf{J@h}}}CG`}\",[]]Bn[\"{{{AHEf{C@bANBb}}CG`}{{AHEf{C@bANBb}}}}\",[]]Ai[\"{{{AHEf{O@n}}}CG`}\",[]]Bn[\"{{{AHEf{C@bB@Fj}}CG`}{{AHEf{C@bB@Fj}}}}\",[]]Aj[\"{{{AHEf{AIAb}}}CG`}\",[]]Ah[\"{{{AHEf{Mh}}}CG`}\",[]]Bn[\"{{{AHEf{C@bAGIj}}CG`}{{AHEf{C@bAGIj}}}}\",[]]Ai[\"{{{AHEf{J@j}}}CG`}\",[]]Bn[\"{{{AHEf{C@bANBd}}CG`}{{AHEf{C@bANBd}}}}\",[]]Ai[\"{{{AHEf{OA`}}}CG`}\",[]]Bn[\"{{{AHEf{C@bB@Fl}}CG`}{{AHEf{C@bB@Fl}}}}\",[]]Aa[\"{AIClBE@d}\",[]]Ai[\"{{{AHEf{OBh}}}CKh}\",[]]Aj[\"{{{AHEf{AIEh}}}CKh}\",[]]Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]Ai[\"{{{AHEf{OBj}}}CKh}\",[]]Aj[\"{{{AHEf{AIEj}}}CKh}\",[]]Co[\"{{{AHEf{OBh}}AOCj{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}CKh}\",[]]D`[\"{{{AHEf{AIEh}}AOCj{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}CKh}\",[]]Co[\"{{{AHEf{OBj}}AOCl{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}CKh}\",[]]D`[\"{{{AHEf{AIEj}}AOCl{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}CKh}\",[]]Bn[\"{{{AHEf{C@bBDHh}}CFl}{{AHEf{C@bBDHh}}}}\",[]]Bn[\"{{{AHEf{C@bBDHj}}CFl}{{AHEf{C@bBDHj}}}}\",[]]Cc[\"{{{AHEf{C@bOBh}}}{{KOl{{O@d{{Ml{AGLb}}}}}}}}\",[]]Cd[\"{{{AHEf{C@bAIEh}}}{{KOl{{O@d{{Ml{AGLb}}}}}}}}\",[]]Cc[\"{{{AHEf{C@bOBj}}}{{KOl{{O@f{{Ml{AGLd}}}}}}}}\",[]]Cd[\"{{{AHEf{C@bAIEj}}}{{KOl{{O@f{{Ml{AGLd}}}}}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]De[\"{{{AHEf{C@bBBCl}}c{AHEf{CFj}}}{{AHEf{C@bBBCl}}}{{IOl{CId}}}}\",[\"\"]]De[\"{{{AHEf{C@bBBCn}}c{AHEf{CFj}}}{{AHEf{C@bBBCn}}}{{IOl{CId}}}}\",[\"\"]]Ci[\"{{{AHEf{C@bOBh}}{AHEf{{KIl{Ll}}}}}{{L@f{CKhJAn}}}}\",[]]Cj[\"{{{AHEf{C@bAIEh}}{AHEf{{KIl{Ll}}}}}{{L@f{CKhJAn}}}}\",[]]Cj[\"{{{AHEf{C@bOBj}}{AHEf{{KIl{Ll}}}}}{{L@f{CKhBAF`}}}}\",[]]Ck[\"{{{AHEf{C@bAIEj}}{AHEf{{KIl{Ll}}}}}{{L@f{CKhBAF`}}}}\",[]]n[\"{ObCKh}\",[]]Bn[\"{{{AHEf{C@bBBCl}}LB`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}LBb}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGInKOl}\",[]]Ca[\"{{{AHEf{C@bAICl}}}{{L@f{{KOl{LB`}}AID`}}}}\",[]]Ca[\"{{{AHEf{C@bBE@d}}}{{L@f{{KOl{LB`}}AID`}}}}\",[]]Ca[\"{{{AHEf{C@bAICn}}}{{L@f{{KOl{LBb}}AOC`}}}}\",[]]Ak[\"{{{AHEf{AI@h}}}AIDn}\",[]]Ak[\"{{{AHEf{AI@l}}}AIDn}\",[]]Ak[\"{{{AHEf{ABCb}}}AIDn}\",[]]Bg[\"{{{AHEf{CIf}}}{{L@f{AIDnAHOn}}}}\",[]]Ak[\"{{{AHEf{ABCd}}}AIDn}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]B`[\"{{LB`c}LB`{{CHj{LB`}}}}\",[\"\"]]B`[\"{{L@`c}L@`{{CHj{L@`}}}}\",[\"\"]]B`[\"{{LBbc}LBb{{CHj{LBb}}}}\",[\"\"]]B`[\"{{L@bc}L@b{{CHj{L@b}}}}\",[\"\"]]20Ae[\"{{ABBfCG`}ACn}\",[]]Bn[\"{{{AHEf{C@bBBCl}}ACl}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}ACl}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{JDhABBf}\",[]]B`[\"{{}{{AHEf{{KIl{BDOd}}}}}}\",[]]Ao[\"{{AHEf{A@Cj{C@bLl}}}HEh}\",[]]0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Am[\"{{}{{KOl{{Md{OBf}}}}}}\",[]]Bn[\"{{{AHEf{C@bBABh}}CKh}{{AHEf{C@bBABh}}}}\",[]]Bn[\"{{{AHEf{C@bBABj}}CKh}{{AHEf{C@bBABj}}}}\",[]]Aj[\"{{{AHEf{AGLb}}}CG`}\",[]]Aj[\"{{{AHEf{AGLd}}}CG`}\",[]]A`[\"{ABEdKOl}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]10Bf[\"{{{AHEf{CFj}}}{{L@j{CG`B@Fn}}}}\",[]]Bm[\"{{{AHEf{ABBj}}{Ml{BAA`}}}{{L@h{HEh}}}}\",[]]Ai[\"{AI@j{{L@j{HEh}}}}\",[]]Ci[\"{{{AHEf{OBd}}BAAbB@Gh{AHEf{Ob}}}{{KKn{AIDnABBh}}}}\",[]]Cb[\"{{{AHEf{C@bAI@n}}L@bAICd}{{L@f{AICdBDJh}}}}\",[]]Am[\"{{{AHEf{AI@l}}CG`}HEh}\",[]]B`[\"{{{AHEf{C@bAI@n}}CG`}HEh}\",[]]A`[\"{BAEhCKh}\",[]]B`[\"{{{AHEf{C@bJDh}}BAEj}HEh}\",[]]Aa[\"{ANE`AGKh}\",[]]Bm[\"{{{AHEf{OBf}}AGMn}{{L@h{{Ml{BAA`}}}}}}\",[]]Bn[\"{{{AHEf{AOHh}}AGMn}{{L@h{{Ml{BAA`}}}}}}\",[]]Bn[\"{{{AHEf{ANDf}}AGMn}{{L@h{{Ml{BAA`}}}}}}\",[]]Ci[\"{{{AHEf{C@bOBh}}{AHEf{C@b{A@`{Ll}}}}}{{KOl{CHl}}}}\",[]]Cj[\"{{{AHEf{C@bAIEh}}{AHEf{C@b{A@`{Ll}}}}}{{KOl{CHl}}}}\",[]]Ci[\"{{{AHEf{C@bOBj}}{AHEf{C@b{A@`{Ll}}}}}{{KOl{CHn}}}}\",[]]Cj[\"{{{AHEf{C@bAIEj}}{AHEf{C@b{A@`{Ll}}}}}{{KOl{CHn}}}}\",[]]Cb[\"{{{AHEf{ABFb}}HEfAIEbABBf}{{L@f{HEhBBCf}}}}\",[]]Cb[\"{{{AHEf{B@Cb}}HEfAIEbABBf}{{L@f{HEhBBCf}}}}\",[]]Cb[\"{{{AHEf{AOEj}}HEfAIEbABBf}{{L@f{HEhBBCf}}}}\",[]]Cb[\"{{{AHEf{ABFd}}HEfAIEbABBf}{{L@f{HEhBBCh}}}}\",[]]Cb[\"{{{AHEf{B@Cd}}HEfAIEbABBf}{{L@f{HEhBBCh}}}}\",[]]Cb[\"{{{AHEf{AOEl}}HEfAIEbABBf}{{L@f{HEhBBCh}}}}\",[]]Al[\"{{}{{L@f{AOAjBEGb}}}}\",[]]Bm[\"{{{AHEf{AI@l}}L@`}{{KOl{{Ml{AIA`}}}}}}\",[]]Bo[\"{{{AHEf{AI@n}}L@b}{{KOl{{AHEf{AIAb}}}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Aj[\"{{{AHEf{AI@l}}}HEh}\",[]]Am[\"{{{AHEf{C@bAI@n}}}HEh}\",[]]Be[\"{{{AHEf{AHOd}}}{{L@f{ObJAh}}}}\",[]]Bg[\"{{{AHEf{AHOd}}}{{L@f{AGInJAh}}}}\",[]]Be[\"{{{AHEf{AHOd}}}{{L@f{OdJAh}}}}\",[]]Be[\"{{{AHEf{AHOd}}}{{L@f{OfJAh}}}}\",[]]Be[\"{{{AHEf{AHOd}}}{{L@f{N`JAh}}}}\",[]]Bg[\"{{{AHEf{AHOd}}}{{L@f{ABAhJAh}}}}\",[]]Ak[\"{{{AHEf{BAFb}}}AOEh}\",[]]Cf[\"{{{AHEf{C@bBBCl}}{KOl{ANBl}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{KOl{ANBn}}}{{AHEf{C@bBBCn}}}}\",[]]<;Aj[\"{{{AHEf{ABBj}}}KL`}\",[]]Aj[\"{{{AHEf{ABBl}}}KL`}\",[]]Bc[\"{{{AHEf{AI@l}}AIDnAICb}ABDh}\",[]]Co[\"{{{AHEf{C@bAI@n}}AGJlAICdO@b}{{L@f{{KKn{L@bCKh}}AGLh}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CFn}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CFn}{{AHEf{C@bBBCn}}}}\",[]]Ai[\"{AI@j{{L@j{HEh}}}}\",[]]Bg[\"{{{AHEf{BAFb}}AIF`}{{L@h{KL`}}}}\",[]]A`[\"{AGInCG`}\",[]]10Ai[\"{{{AHEf{Ob}}}BBCj}\",[]]Ce[\"{{{AHEf{C@bAOGj}}{Md{BBCl}}}{{AHEf{C@bAOGj}}}}\",[]]Ce[\"{{{AHEf{C@bAOAl}}{Md{BBCl}}}{{AHEf{C@bAOAl}}}}\",[]]Ce[\"{{{AHEf{C@bAOGn}}{Md{BBCn}}}{{AHEf{C@bAOGn}}}}\",[]]Ce[\"{{{AHEf{C@bAOB`}}{Md{BBCn}}}{{AHEf{C@bAOB`}}}}\",[]]Aa[\"{AOGjBENj}\",[]]Aa[\"{AOGnBENl}\",[]]Bj[\"{{{A@`{BAAb}}B@Gh}{{L@f{AOGjJBb}}}}\",[]]Bj[\"{{{A@`{BAAb}}B@Gh}{{L@f{AOGnJBd}}}}\",[]]Co[\"{{{AHEf{C@bAIDh}}{AHEf{C@b{KIl{IOn}}}}}{{L@f{HEhAIFb}}}}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]A`[\"{BDBjCG`}\",[]]A`[\"{BDBlCG`}\",[]]Bc[\"{{{AHEf{AI@l}}}{{KOl{KL`}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]10Aj[\"{{{AHEf{AGJd}}}KL`}\",[]]Be[\"{{{AHEf{ABBj}}{KOl{AOGj}}}HEh}\",[]]Bn[\"{{{AHEf{C@bABBl}}{KOl{{Md{AOGn}}}}}HEh}\",[]]Bd[\"{{{AHEf{BDOd}}}{{KOl{B@Gf}}}}\",[]]o[\"{{}AHEf}\",[]]n[\"{{}NNn}\",[]]0000Bn[\"{{{AHEf{C@bBBCl}}KL`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}KL`}{{AHEf{C@bBBCn}}}}\",[]]o[\"{CG`LB`}\",[]]o[\"{CG`LBb}\",[]]A`[\"{B@DdCG`}\",[]]Bo[\"{{{AHEf{C@bBABh}}ABBf}{{AHEf{C@bBABh}}}}\",[]]Bo[\"{{{AHEf{C@bBABj}}ABBf}{{AHEf{C@bBABj}}}}\",[]]Ae[\"{{KL`CG`}B@Cb}\",[]]Ae[\"{{KL`CG`}B@Cd}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]6Bg[\"{{{AHEf{AI@n}}L@b}{{KOl{AICd}}}}\",[]]An[\"{{{AHEf{AI@l}}IOn}AOGd}\",[]]Am[\"{{{AHEf{AI@l}}LB`}HEh}\",[]]B`[\"{{{AHEf{C@bAI@n}}LBb}HEh}\",[]]Ce[\"{{{AHEf{C@bBABh}}{A@`{CFn}}}{{AHEf{C@bBABh}}}}\",[]]Ce[\"{{{AHEf{C@bBABj}}{A@`{CFn}}}{{AHEf{C@bBABj}}}}\",[]]Fg[\"{{{AHEf{BFBf}}{AHEf{BAAb}}{AHEf{{KIl{BAAb}}}}{AHEf{AIDl}}{AHEf{{KIl{Ll}}}}ABGd}{{L@f{BDJbJAf}}}}\",[]]Af[\"{{BBBnO@b}BBBn}\",[]]Af[\"{{BBC`O@b}BBC`}\",[]]?Al[\"{AOHj{{L@f{CJdJB`}}}}\",[]]Ak[\"{AOHj{{L@f{NbJB`}}}}\",[]]Am[\"{AOHj{{L@f{ABEhJB`}}}}\",[]]Ai[\"{AOHj{{L@l{CJf}}}}\",[]]Ah[\"{AOHj{{L@l{Nd}}}}\",[]]Aj[\"{AOHj{{L@l{ABEj}}}}\",[]]o[\"{NNnNNn}\",[]]Bo[\"{{{AHEf{C@bBDHh}}ABBf}{{AHEf{C@bBDHh}}}}\",[]]Bo[\"{{{AHEf{C@bBDHj}}ABBf}{{AHEf{C@bBDHj}}}}\",[]]Bb[\"{{{AHEf{OBh}}}{{KOl{CKh}}}}\",[]]Bc[\"{{{AHEf{AIEh}}}{{KOl{CKh}}}}\",[]]Bb[\"{{{AHEf{OBj}}}{{KOl{CKh}}}}\",[]]Bc[\"{{{AHEf{AIEj}}}{{KOl{CKh}}}}\",[]]Bg[\"{{{AHEf{AI@l}}}{{L@f{HEhBBAb}}}}\",[]]Cf[\"{{{AHEf{C@bBBCl}}{KOl{ABBf}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{KOl{ABBf}}}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]Bl[\"{{{AHEf{C@bAIA`}}O@bO@bCKhCKhCG`}HEh}\",[]]Bj[\"{{{AHEf{C@bMf}}O@bO@bCKhCKhCG`}HEh}\",[]]Bk[\"{{{AHEf{C@bJ@h}}O@bO@bCKhCKhCG`}HEh}\",[]]Bk[\"{{{AHEf{C@bO@n}}O@bO@bCKhCKhCG`}HEh}\",[]]Bl[\"{{{AHEf{C@bAIAb}}O@bO@bCKhCKhCG`}HEh}\",[]]Bj[\"{{{AHEf{C@bMh}}O@bO@bCKhCKhCG`}HEh}\",[]]Bk[\"{{{AHEf{C@bJ@j}}O@bO@bCKhCKhCG`}HEh}\",[]]Bk[\"{{{AHEf{C@bOA`}}O@bO@bCKhCKhCG`}HEh}\",[]]A`[\"{B@DdCG`}\",[]]Ak[\"{{{AHEf{OCf}}Nd}CG`}\",[]]Bi[\"{{{AHEf{C@bAIDf}}CG`}{{L@j{HEh}}}}\",[]]<;A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]10Cf[\"{{{AHEf{C@bBBCl}}{KOl{BDFj}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{KOl{BDFl}}}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGM`CG`}\",[]]A`[\"{AGMbCG`}\",[]]Bh[\"{{{AHEf{C@bAHOd}}}{{L@f{ObJAh}}}}\",[]]Bj[\"{{{AHEf{C@bAHOd}}}{{L@f{AGInJAh}}}}\",[]]Bh[\"{{{AHEf{C@bAHOd}}}{{L@f{OdJAh}}}}\",[]]Bh[\"{{{AHEf{C@bAHOd}}}{{L@f{OfJAh}}}}\",[]]Bh[\"{{{AHEf{C@bAHOd}}}{{L@f{N`JAh}}}}\",[]]Bj[\"{{{AHEf{C@bAHOd}}}{{L@f{ABAhJAh}}}}\",[]]Cc[\"{{{Md{AI@j}}CG`CKh}{{L@j{{KKn{BAEjBAEj}}}}}}\",[]]Bn[\"{{{AHEf{C@bAOGj}}CG`}{{AHEf{C@bAOGj}}}}\",[]]Bn[\"{{{AHEf{C@bAOGn}}CG`}{{AHEf{C@bAOGn}}}}\",[]]Aj[\"{{{AHEf{AI@l}}}CKh}\",[]]Ak[\"{{{AHEf{BAA`}}}AOEh}\",[]]0Ci[\"{{{AHEf{C@bBABh}}CFl}{{L@f{{AHEf{C@bBABh}}ANAh}}}}\",[]]Ci[\"{{{AHEf{C@bBABj}}CFl}{{L@f{{AHEf{C@bBABj}}ANAj}}}}\",[]]A`[\"{AGInCFl}\",[]]Cf[\"{{{AHEf{C@bBBCl}}{KOl{BDHh}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{KOl{BDHj}}}{{AHEf{C@bBBCn}}}}\",[]]Bg[\"{{{AHEf{C@bAI@n}}}{{KOl{B@Db}}}}\",[]]Cf[\"{{{AHEf{C@bAOGj}}{KOl{AOHb}}}{{AHEf{C@bAOGj}}}}\",[]]Cf[\"{{{AHEf{C@bAOGn}}{KOl{AOHb}}}{{AHEf{C@bAOGn}}}}\",[]]Cf[\"{{{AHEf{C@bAOGj}}{KOl{AOHd}}}{{AHEf{C@bAOGj}}}}\",[]]Cf[\"{{{AHEf{C@bAOGn}}{KOl{AOHd}}}{{AHEf{C@bAOGn}}}}\",[]]Cc[\"{{}{{L@f{{KKn{{A@`{BAAb}}B@Gh}}{Ml{JAd}}}}}}\",[]]Bn[\"{{{AHEf{C@bBDFj}}LB`}{{AHEf{C@bBDFj}}}}\",[]]Bn[\"{{{AHEf{C@bBDFl}}LBb}{{AHEf{C@bBDFl}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Bo[\"{{{AHEf{C@bAOGj}}ABBf}{{AHEf{C@bAOGj}}}}\",[]]Bo[\"{{{AHEf{C@bAOGn}}ABBf}{{AHEf{C@bAOGn}}}}\",[]]Ci[\"{{{AHEf{CIf}}{KOl{ABBf}}}{{L@f{{KOl{ABBf}}AHOn}}}}\",[]]Bj[\"{{{AHEf{BAFb}}AIF`KL`}{{L@h{HEh}}}}\",[]]054Bm[\"{{{AHEf{OBh}}}{{L@f{{KOl{BE@b}}JAn}}}}\",[]]Bn[\"{{{AHEf{AIEh}}}{{L@f{{KOl{BE@b}}JAn}}}}\",[]]Bn[\"{{{AHEf{OBj}}}{{L@f{{KOl{BE@b}}BAF`}}}}\",[]]Bo[\"{{{AHEf{AIEj}}}{{L@f{{KOl{BE@b}}BAF`}}}}\",[]]Aj[\"{{{AHEf{AGLb}}}CG`}\",[]]Aj[\"{{{AHEf{AGLd}}}CG`}\",[]]Aj[\"{{{AHEf{ABBl}}}CG`}\",[]]Bf[\"{{{AHEf{AGJl}}{AHEf{AGJl}}}CKh}\",[]]Am[\"{{{AHEf{C@bAI@n}}}HEh}\",[]]Bn[\"{{{AHEf{C@bB@Fj}}ACl}{{AHEf{C@bB@Fj}}}}\",[]]Bn[\"{{{AHEf{C@bB@Fl}}ACl}{{AHEf{C@bB@Fl}}}}\",[]]Ak[\"{{{AHEf{AGMl}}}AOEh}\",[]]0Bd[\"{{{AHEf{AI@l}}}{{ABE`{JBn}}}}\",[]]Cb[\"{{{AHEf{AI@n}}L@b}{{L@f{{KOl{AIDn}}AI@d}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Bn[\"{{{AHEf{C@bBBCl}}LB`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}LBb}{{AHEf{C@bBBCn}}}}\",[]]A`[\"{AGInKOl}\",[]]Bo[\"{{{AHEf{AGIn}}{AHEf{CFj}}}{{L@h{BBCj}}}}\",[]]Em[\"{{{AHEf{AI@l}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhBFIn}}}}\",[]]El[\"{{{AHEf{OBh}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhBFIn}}}}\",[]]Em[\"{{{AHEf{AIEh}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhBFIn}}}}\",[]]El[\"{{{AHEf{OBj}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhBFJ`}}}}\",[]]Em[\"{{{AHEf{AIEj}}{AHEf{C@b{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}{AHEf{{KIl{Ll}}}}}{{L@f{HEhBFJ`}}}}\",[]]Am[\"{{{AHEf{C@bAGJb}}}HEh}\",[]]0Al[\"{{{AHEf{AI@n}}Nd}CG`}\",[]]Bl[\"{{{AHEf{AI@l}}}{{ABEb{{KOl{AIDn}}}}}}\",[]]Bd[\"{{{AHEf{CIf}}}{{L@f{`AHOn}}}}\",[]]>=E`[\"{{{AHEf{BFBf}}{AHEf{{KIl{Ll}}}}{AHEf{BAAb}}{AHEf{BEMl}}}{{L@f{BFE`JAf}}}}\",[]]0o[\"{{}AOAl}\",[]]o[\"{{}AOB`}\",[]]Bf[\"{{{Md{B@H`}}}{{L@f{AOAlBEGl}}}}\",[]]Bf[\"{{{Md{B@H`}}}{{L@f{AOB`BEGl}}}}\",[]]Bn[\"{{{AHEf{C@bBDFj}}LB`}{{AHEf{C@bBDFj}}}}\",[]]Bn[\"{{{AHEf{C@bBDFl}}LBb}{{AHEf{C@bBDFl}}}}\",[]]o[\"{NNnNNn}\",[]]0000Aj[\"{{{AHEf{AI@n}}}CKh}\",[]]0Ci[\"{{{AHEf{CIf}}{KOl{ABBf}}}{{L@f{{KOl{ABBf}}AHOn}}}}\",[]]Cc[\"{{{AHEf{C@bOb}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Ce[\"{{{AHEf{C@bAGIn}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Cc[\"{{{AHEf{C@bOd}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Cc[\"{{{AHEf{C@bOf}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Cc[\"{{{AHEf{C@bN`}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Ce[\"{{{AHEf{C@bABAh}}{AHEf{AHOd}}}{{L@f{HEhJAh}}}}\",[]]Bo[\"{{{AHEf{C@bAOGj}}BENj}{{AHEf{C@bAOGj}}}}\",[]]Bo[\"{{{AHEf{C@bAOGn}}BENl}{{AHEf{C@bAOGn}}}}\",[]]Aj[\"{{{AHEf{BABh}}}CG`}\",[]]Aj[\"{{{AHEf{BABj}}}CG`}\",[]]Cc[\"{{{AHEf{C@bAOAl}}{Md{A`}}}{{AHEf{C@bAOAl}}}}\",[]]Cc[\"{{{AHEf{C@bAOB`}}{Md{A`}}}{{AHEf{C@bAOB`}}}}\",[]]Cj[\"{{BABh{KOl{AOGj}}{Ml{BAA`}}{Md{OBf}}}{{L@h{ABBj}}}}\",[]]Aj[\"{{{AHEf{ABCb}}}CKh}\",[]]Aj[\"{{{AHEf{ABCd}}}CKh}\",[]]Bn[\"{{{AHEf{C@bAI@n}}O@bAIBh}{{L@f{HEh`}}}}\",[]]Bd[\"{{{AHEf{BFBf}}}{{A@`{BBCb}}}}\",[]]Bj[\"{{{AHEf{AI@l}}AIDn}{{L@f{HEhJBh}}}}\",[]]Bm[\"{{{AHEf{C@bAI@n}}AIDn}{{L@f{HEhJBh}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}KL`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}KL`}{{AHEf{C@bBBCn}}}}\",[]]Bl[\"{{}{{L@f{{KKn{BAAbBDId}}{Ml{JAd}}}}}}\",[]]Ai[\"{AI@j{{L@j{HEh}}}}\",[]]A`[\"{AIAhCG`}\",[]]A`[\"{AIAjCG`}\",[]]Ba[\"{{{AHEf{C@bABBj}}AOAl}HEh}\",[]]D`[\"{{{AHEf{C@bAI@n}}L@b{KOl{ABBf}}}{{L@f{{KOl{ABBf}}AI@d}}}}\",[]]o[\"{{}AHEf}\",[]]Aj[\"{{{AHEf{AI@l}}}KL`}\",[]]Bn[\"{{{AHEf{C@bAOGj}}CG`}{{AHEf{C@bAOGj}}}}\",[]]Bn[\"{{{AHEf{C@bAOGn}}CG`}{{AHEf{C@bAOGn}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}LB`}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}LBb}{{AHEf{C@bBBCn}}}}\",[]]:Bb[\"{{{AHEf{C@bAI@n}}NdLBb}HEh}\",[]]Ak[\"{{}{{L@f{AOAlJBb}}}}\",[]]Ak[\"{{}{{L@f{AOB`JBd}}}}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CKh}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CKh}{{AHEf{C@bBBCn}}}}\",[]]65Cf[\"{{{AHEf{C@bOb}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Ch[\"{{{AHEf{C@bAGIn}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Cf[\"{{{AHEf{C@bOd}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Cf[\"{{{AHEf{C@bOf}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Cf[\"{{{AHEf{C@bN`}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Ch[\"{{{AHEf{C@bABAh}}{AHEf{C@bAHOd}}}{{L@f{HEhJAh}}}}\",[]]Bi[\"{{{AHEf{C@bAGJl}}{AHEf{AGJl}}}CKh}\",[]]n[\"{{}HEh}\",[]]Ce[\"{{{AHEf{C@bBBCl}}{KOl{KL`}}}{{AHEf{C@bBBCl}}}}\",[]]Ce[\"{{{AHEf{C@bBBCn}}{KOl{KL`}}}{{AHEf{C@bBBCn}}}}\",[]]Bn[\"{{{AHEf{AI@l}}}{{L@f{{A@`{AIDn}}JBh}}}}\",[]]Cd[\"{{{AHEf{C@bAI@n}}O@b}{{L@f{{A@`{AIDn}}JBh}}}}\",[]]Am[\"{{{AHEf{C@bAIA`}}}HEh}\",[]]Al[\"{{{AHEf{C@bJ@h}}}HEh}\",[]]Am[\"{{{AHEf{C@bAIAb}}}HEh}\",[]]Al[\"{{{AHEf{C@bJ@j}}}HEh}\",[]]Ai[\"{AI@j{{L@j{HEh}}}}\",[]]Bj[\"{{{AHEf{AI@l}}AIDn}{{L@f{HEhJBh}}}}\",[]]Bm[\"{{{AHEf{C@bAI@n}}AIDn}{{L@f{HEhJBh}}}}\",[]]D`[\"{{{AHEf{C@bAI@n}}L@b{KOl{ABBf}}}{{L@f{{KOl{ABBf}}AI@d}}}}\",[]]Ce[\"{{{AHEf{C@bBBCl}}{Md{BDBf}}}{{AHEf{C@bBBCl}}}}\",[]]Ce[\"{{{AHEf{C@bBBCn}}{Md{BDBh}}}{{AHEf{C@bBBCn}}}}\",[]]Cf[\"{{{AHEf{C@bBBCl}}{KOl{ABBf}}}{{AHEf{C@bBBCl}}}}\",[]]Cf[\"{{{AHEf{C@bBBCn}}{KOl{ABBf}}}{{AHEf{C@bBBCn}}}}\",[]]Aa[\"{B@DhAIBf}\",[]]Aa[\"{B@DjAIBf}\",[]]9Bn[\"{{{AHEf{C@bBBCl}}CKh}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CKh}{{AHEf{C@bBBCn}}}}\",[]]Am[\"{{{AHEf{AI@l}}LB`}HEh}\",[]]o[\"{NNnNNn}\",[]]Bn[\"{{{AHEf{C@bBBCl}}CFn}{{AHEf{C@bBBCl}}}}\",[]]Bn[\"{{{AHEf{C@bBBCn}}CFn}{{AHEf{C@bBBCn}}}}\",[]]3109854Bn[\"{{{AHEf{AI@l}}}{{L@f{{A@`{AIDn}}JBh}}}}\",[]]Bn[\"{{{AHEf{AI@n}}}{{L@f{{A@`{AIDn}}JBh}}}}\",[]]10A`[\"{BE@bKOl}\",[]]Bm[\"{{{AHEf{C@bBBCl}}Ll}{{AHEf{C@bBBCl}}}}\",[]]Bm[\"{{{AHEf{C@bBBCn}}Ll}{{AHEf{C@bBBCn}}}}\",[]]o[\"{{}AIBh}\",[]]") \ No newline at end of file diff --git a/pr/255/docs/search.index/generic_inverted_index/76f3213be5b5.js b/pr/255/docs/search.index/generic_inverted_index/76f3213be5b5.js new file mode 100644 index 000000000..a0bf05304 --- /dev/null +++ b/pr/255/docs/search.index/generic_inverted_index/76f3213be5b5.js @@ -0,0 +1 @@ +rb_("QUxuADswAAABAAC2AQIALQPdAEwE2AA7MAAAAQAAOgIpAPUBFgANAggAFwIAABoCAAAcAgAAHgIEACcCBQAuAgAAMwICADcCBQBAAgQARgIEAEwCAABOAgEAUQIBAFQCAgBYAgMAXQILAGoCBwB9Ag8AkgIDAJcCEgCrAgMAsAIDALUCBAC8AgYAxAIDAMkCBwDSAgQA2AIAANoCBQDhAgMA5gIDAOsCBgD1AgAA/gIIAAgDDwDBCXsALQvdAMMPAABnEAEAOzAAAAEAALsBDQBEBt0APQotAG0KAABvCg4AfwoFAIYKGQCiCgEApgoRALsKHgDbCgYA4wooAA4LAAARCxsAOzAAAAEAAP8ACwA2AgAAlgIAAAcDAADnBxMA2goAAOIKAAAMCwAAEAsAAHcO4ADIDwEA/w8BADswAAABAABiAQUAjwkAAA0LAAAPCwAAFQ1ZAXURBQA7MAAAAQAABgACAD8HAwBEBwIAOzAAAAEAACkABQAYAxQAEAYAADoHBABIBwwAigkBADswAAABAAAKAAIALQQAAAsMCQA7MAAAAQAADAABABwEDAABfAwAAAJhEQAAYhEAAAACxRAAAMYQAAAAAqcBAABDBwAAQ24AAAA7MAAAAQAA3QAMAD0KLQBtCgAAbwoOAH8KBQCGChkAogoBAKYKEQC7Ch4A2woGAOMKKAAOCwAAEQsbAA==") \ No newline at end of file diff --git a/pr/255/docs/search.index/generic_inverted_index/770510825e02.js b/pr/255/docs/search.index/generic_inverted_index/770510825e02.js deleted file mode 100644 index ec0c0e131..000000000 --- a/pr/255/docs/search.index/generic_inverted_index/770510825e02.js +++ /dev/null @@ -1 +0,0 @@ -rb_("QU1mADswAAABAACmAQIAFgPVACwE0AA7MAAAAQAAJQItAOYBFAD8AQgABgIBAAoCAAAMAgAADgICABQCAAAWAgYAIgIBACUCBgAtAgAAMAIEADYCAwA7AgAAPQIBAEACAQBDAgIARwICAEsCDABZAgUAaQIAAGsCDwB+AgAAgQIDAIYCEQCZAgIAnQIEAKMCAwCoAgAAqgIAAKwCBACyAgcAuwIDAMACAADCAgUAyQIEAM8CBADVAgUA3QIAAOcCCADxAg8Afwl2AN4K1QBJDwAA7A8BADswAAABAACrAQwAFQbVAPYJLAAmCg4ANgoEADwKGgBZCgAAXAoSAHIKHQCRCgUAmAokAL8KAADCChsAOzAAAAEAAPMACwAkAgAAhQIAAPACAACtBxMAkAoAAJcKAAC9CgAAwAoAAAoO1ABODwEAhQ8BADswAAABAABVAQUATQkAAL4KAADBCgAAtQxMAfkQBQA7MAAAAQAABQACAAgHAgAMBwIAOzAAAAEAACgABQABAxQA4gUAAAMHBAAQBwsASAkBADswAAABAAAJAAIADQQAALQLCAA7MAAAAQAACwABAP0DCwAAAuUQAADmEAAAAAJKEAAASxAAAAACmQEAAAsHAABDagAAADswAAABAADVAAsA9gksACYKDgA2CgQAPAoaAFkKAABcChIAcgodAJEKBQCYCiQAvwoAAMIKGwA=") \ No newline at end of file diff --git a/pr/255/docs/search.index/name/52ee5dc5acb9.js b/pr/255/docs/search.index/name/52ee5dc5acb9.js new file mode 100644 index 000000000..405f23b32 --- /dev/null +++ b/pr/255/docs/search.index/name/52ee5dc5acb9.js @@ -0,0 +1 @@ +rd_("b()b->bBi0bCe00bFnbIdbOkb[]beq00000000000000000000000000000000000000000000000000000000000000000000000000000bid0000000000000brtbtybu8cAck0cAnycArccBbr00cBoxcBufcClicDir0cErrcMAX000cNotcOpt00cOrdcPincUni0cVeccbbrccmp0000000000000000000cdir000cecn000cf32cf64cfmt000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cgetci32cimpcios0clen000clog0cmincmutcnew00000000000000000000000000000000000cnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdArgsdAsFddDropdEct000dEct100dFromdHashdIntodKeys0dLong0dNonedPath00dPing0dPolldReaddSenddSide0dSyncdVZipdZERO0dacks0daddr0dbooldbulkdcodedcwnd0ddataddrop0000dfrom00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnextdopen00dpath0dperfdping000dpoll00000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128dunitdvzip000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eAsRefeByteseChunk0eCloneeCloseeCubic00eDebugeDerefeError00000000000eEvent00eKnowneOther0eRangeeReset000eRetry0eShort0eSizedeStats0eSuiteeWriteearrayebenchebuild00000000ebytes00000ecauseeclone000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerror0eframe0eindex0eis_ce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats00000000etitle0etokenetokioetupleeusizeewrite00fAcceptfAckEcn0fAes128fAes256fBackupfBorrowfBufMutfChunksfClient00fClosed00fCrypto0fCursorfFuturefHasherfIpAddrfOpenBifOpened000fOptionfOutputfPathId0fResult00000fServer00fStream000fStringfTypeIdfVarInt0faccept000fborrow00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode000000000000fdst_ipfencode000000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0fon_ack0000000fpacket00frandomfreason00000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000fsrc_ip00fstatus0fstream0fstridefudp_rx0fudp_tx0fvarintfverify0fwindow0000000gAeadKey0gBlocked00gCommandgContextgDefaultgDisplaygFromStrgGeneral0gHmacKey0gInitialgInstantgKeyPair0gLayeredgMaxData0gNewReno00gOpenUnigPadding0gPathAck0gPathBufgReadBufgRequestgRuntime0gSession0gStopped0000gStreamsgToOwnedgTooLonggTryFromgTryIntogUnknowngWritten0gZeroRttgcid_len000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt000gdefault000000000000000000000000000000000000000000000000000gdrainedgdst_cid0000000gencrypt000giroh_hp0gis_0rtt0gmetrics0000000gmin_mtu0gon_sent000gopen_bigpath_idgpointergruntimegsrc_cid0000gstopped0gstreams000gtag_len0gtype_id00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgradegversion00000hAcceptBihBytesMuthChacha20hCommandshDatagram00hDerefMuthDisabled0hDurationhEndpoint00hFinished0hIncoming0hLayerExthLongTypehMAX_SIZE0hNO_ERROR0hNewToken0hOnClosedhOpenPathhOrderinghReadable0hReceiver0hRecvMetahResponsehStreamId0hTimedOut0hToStringhTokenLog0hTooLarge0hTransmit00hUdpStats0hUnixTimehWritable0hcong_alghcontentshdatagram0hdurationhendpoint0hfinalizehframe_rx0hframe_tx0hfrom_buf0hfrom_env0hfrom_keyhfrom_strhfrom_u320hfrom_u640hgot_type000hgroup_id0000hhas_0rtthincominghinterval0hinto_any0000000his_alivehlifetime0hlocal_ip0000hmax_data0hmax_sizehnew_renohon_byteshopen_unihpriority0hprotocol0hqlog_dirhresponsehrng_seed0hssthresh0hto_owned000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_from00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_into00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_poll000000000htry_sendhvalidate000iAbandoned0iAcceptUniiArbitraryiAsyncRead0iAvailable00iBbrConfig0iBorrowMutiClosePathiCommonOptiConnectediCriterioniDatagramsiDecodableiEncodableiFormatteriFourTupleiFrameType0iHandshakeiHeaderKey0iHistogramiMalformediMaxPathId0iMultipathiPacketKey0iPartialEqiPathErroriPathEvent00iPathStats0iReadError00iTryFutureiUdpSenderiUdpSocketiValueEnumiaccept_biiarbitrary0000000ias_rustlsiassemblericlone_box0000000idatagrams000ideref_mut0ifrom_bits00iinitiator0iinto_0rttiis_client0iis_closediis_server0imay_retry0imigration0inew_timer00inew_token0ion_closediopen_path0ipath_acks0iping_pathipoll_nextipoll_read00ipoll_recvipoll_sendireach_out0ireferenceireset_key0iretry_tag0000isize_hint00000istable_idito_string00000000000000000000000000000000000000000000000000000000000itoken_key0itoken_positransport00iwait_idleiwrite_alljArgMatchesjAsyncTimerjAsyncWrite0jBATCH_SIZEjClosedPath000jComparablejConnectingjConnection00jController0jEquivalent0jFrameStats0jIntoFuturejInvalidCid0jIoSliceMutjMaybeFrame0jNamedGroupjNonZeroU32jOtherErrorjPartialOrdjPathAckEcn0jPathStatus0jQlogConfig0jRecvStream00jResetErrorjRetryError0jSendStream00jServerNamejSocketAddrjStreamInfojSubcommandjSystemTimejTimeSource0jTlsSession0jTokenStore0jUdpSockRefjWriteError0jaccept_unijallow_spin0jborrow_mut00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclone_into000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclose_pathjcongestion000jconn_statsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jerror_code00000jframe_type0jinto_inner0jiroh_quinnjis_drained0jlocal_addr0jlost_bytes0jnew_senderjpad_to_mtu0jpath_stats00jpoll_closejpoll_flush0jpoll_write00jprint_jsonjquinn_perfjread_chunk0jread_exactjset_statusjstart_time0jthroughputjtotal_sizekAcceptErrorkCLIENT_ADDRkCipherSuitekClientStatskCloseReasonkConfigError0kContentTypekCryptoError0kCubicConfig0kDataBlocked0kFinishErrorkIdleTimeout0kIntoRequestkOutOfBounds0kPathAbandon0kQlogFactory0kResetStream0kSERVER_ADDRkSERVER_NAMEkSmolRuntimekStopSending0kStreamEvent0kStreamStats0kUnspecifiedkaccept_withkadd_address0kbind_socketkcertificatekcurrent_mtu00kdescription0kdestination00kinitial_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_handlekwith_crypto0kwith_prefix0kwrite_chunklAckFrequency0lAddressAddedlClientConfig00000lClosedStream000000lConnectError00lConnectionId00lDatagramInfolDecryptError0lEcnCodepoint00lEncryptError0lIllegalValuelImmediateAck0lLOCALHOST_V4lLastOpenPathlNatTraversallNonZeroUsizelNoneTokenLog0lObservedAddr0lPathResponse0lPathsBlocked0lReadDatagramlRemoteStatus0lRttEstimator0lSendDatagramlServerConfig00000lSocketAddrV4lSocketAddrV6lStoppedErrorlTokioRuntimelUnstructuredlaugment_args0000lcid_lifetime000lclose_reasonlconnect_withlconservativeldata_blocked0ldrain_streamlearly_crypto000lexpect_types000lgenerate_cid000lgro_segmentslhandle_event0linitial_keys00000000linto_request0llost_packets0lmax_incoming0lmay_fragment00lnetwork_pathlnew_receiverlnoprotection0lorig_dst_cid0lpath_abandon0lpoll_timeoutlqlog_factory0lreset_stream0lsegment_size00lsend_streamslsent_packets0lset_lifetime0lset_priority0lstop_sending0lstream_statslupload_statslwith_initial000lwrite_chunks0mAlertReceived0mBloomTokenLog0mCidsExhausted000mCloneToUninitmDatagramEventmEndpointEventmEndpointStatsmFinishedEarlymHandshakeData0mHandshakeDone0mHandshakeTypemINVALID_TOKEN0mInvalidHeadermLocallyClosed000mMaxStreamData0mMaxStreamsUni0mNewConnectionmNewRenoConfig0mParseIntErrormPartialDecodemPathChallenge0mPossibleValuemPrivateKeyDermReadableErrormRemoveAddress0mRootCertStoremStdSystemTime0mUnexpectedEndmaccepted_0rttmack_frequency00mbench_exports0mcid_generator00mcreate_sendermdata_transfermdownload_sizemduration_histmimmediate_ack0minto_incoming0mmax_ack_delay0mno_protectionmobserved_addr0mon_first_bytemon_mtu_update0000000mpath_response0mpaths_blocked0mpeer_identity0000mpoll_read_bufmpoll_shutdownmpoll_transmitmqlog_from_env0mread_datagrammsend_datagrammsend_fairness0msignature_len0mstart_session000000000mtry_size_hint0nAddIpv4Address0nAddIpv6Address0nAddressRemovednAsyncUdpSocketnCertificateDernClosePathError0nCommandFactorynConnectionLost000000nEndpointConfig0nFromArgMatchesnINTERNAL_ERROR0nIncomingFuturenInvalidFrameIdnInvalidMessage00nMaxStreamsBidi0nNO_VIABLE_PATH0nNoneTokenStore0nPeerMisbehaved00nReachOutAtIpv40nReachOutAtIpv60nReadExactErrornReadToEndErrornShouldTransmitnTransferResultnTransportError00nUdpSocketStatenaead_from_hkdf0nconnect_clientncrypto_sessionndownload_statsnfor_connection000nhandle_timeoutnhandshake_data00000nhandshake_done0nhas_subcommandninitial_window0000000000000ninto_unorderedniroh_quinn_udpnis_handshaking0000nis_valid_retry000nminimum_change0nnext_1rtt_keys000npath_challenge0nqlog_from_path0nread_handshake000nread_unorderednreceive_window00nreceived_reset00nremote_address0000nremove_address0nsaturating_add000nsaturating_sub0nthroughput_bpsntime_threshold0ntotal_durationnvalue_variantsoConnectionClose000oConnectionError0oConnectionEvent0oConnectionStats0oGetRandomFailedoNewConnectionId0oOpenStreamStatsoPathCidsBlocked0oProtectedHeader0oQlogFileFactory0oSignatureSchemeoSystemTimeErroroTokenReuseError0oTransportConfig00oTryFromIntErroroVersionMismatch0oZeroRttAcceptedoZeroRttRejected000obloom_token_logoclone_to_uninit000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000odefault_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`EndpointStopping0A`FINAL_SIZE_ERROR0A`InconsistentKeys00A`KEY_UPDATE_ERROR0A`MaxPathIdReachedA`ObservedIpv4Addr0A`ObservedIpv6Addr0A`PathStatusBackup0A`PeerIncompatible00A`QuicClientConfig0A`QuicServerConfig0A`TokenMemoryCache0A`TooManyAddressesA`ValidationFailedA`VersionNegotiate0A`check_and_insert00000A`configure_clientA`congestion_state0A`connection_close0A`force_key_update0A`from_arg_matches00000A`iroh_quinn_protoA`max_gso_segmentsA`max_idle_timeout0A`max_streams_bidi0A`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_ERROR0AaApplicationClosed0AaControllerFactory0AaControllerMetrics0AaHandshakeTokenKey0AaInvalidServerName0AaPacketDecodeError0AaSendDatagramError0AaStreamDataBlocked0AaStreamsBlockedUni0AaUnsupportedByPeer0Aacongestion_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_ERROR0AbServerCertVerifiedAbServerCertVerifierAbSetPathStatusError0AbStreamsBlockedBidi0AbTransportErrorCode0AbUnsupportedVersion00000Abcommand_for_update0000Abcrypto_buffer_size0Abfrom_u64_unchecked0Abignored_handshakesAbmin_reset_interval0Abnew_expected_items0Abpath_status_backup0Abrefused_handshakesAbremote_path_statusAbsend_datagram_waitAbset_receive_window0Absupported_versions0Abtoken_memory_cacheAbverify_server_certAbwith_start_instant0AcCongestionAlgorithmAcMaxRecursionReachedAcPathNewConnectionId0AcPathStatusAvailable0AcRemoteCidsExhaustedAcTransportParametersAcUnorderedRecvStreamAcUnsupportedNameType0AcWrongConnectionSideAcaccepted_handshakesAcarbitrary_take_rest00000Acaugment_subcommandsAcblack_hole_cooldown0Acearly_data_accepted000Achandshake_confirmedAckeep_alive_interval0Aclost_plpmtud_probes0Acon_congestion_event0000000Acoutgoing_handshakesAcremote_open_streamsAcsend_buffer_benches00Acsend_data_on_streamAcsent_plpmtud_probes0Acstream_data_blocked0Acstreams_blocked_uni0AdFRAME_ENCODING_ERROR0AdHandshakeNotComplete0AdInappropriateMessage000AdInvalidRemoteAddress00AdNoInitialCipherSuite0AdServerSideNotAllowedAdSupportedCipherSuiteAdVarIntBoundsExceeded0AdVerifierBuilderErrorAdWeakConnectionHandleAdack_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_limit0Aeincoming_buffer_bytesAeis_probably_same_pathAelocal_address_changedAeloss_reduction_factor0Aemax_transmit_segments0Aenat_traversal_updatesAepath_observed_addressAepath_status_available0Aestream_receive_window00AfCRYPTO_BUFFER_EXCEEDED0AfExtensionNotNegotiatedAfFailedToGetCurrentTime0AfFailedToGetRandomBytes0AfMultipathNotNegotiated00AfPathRetireConnectionId0AfProtectedInitialHeaderAfSkipServerVerificationAfbuild_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_negotiatedAgset_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_VERSIONSAjdatagram_send_buffer_spaceAjincoming_buffer_size_total0Ajmax_concurrent_uni_streams0Ajopen_unidirectional_streamAjset_max_concurrent_streamsAjtry_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_event000Alreceive_bidirectional_streamAlremove_nat_traversal_address0Alset_path_keep_alive_intervalAmFixedLengthConnectionIdParserAmInappropriateHandshakeMessage000Amcongestion_controller_factory0Amdefault_path_max_idle_timeout0Amnegotiated_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/255/docs/search.index/name/8263a00c4c8a.js b/pr/255/docs/search.index/name/8263a00c4c8a.js deleted file mode 100644 index 495d3832d..000000000 --- a/pr/255/docs/search.index/name/8263a00c4c8a.js +++ /dev/null @@ -1 +0,0 @@ -rd_("b()b->bBi0bCe00bFnbIdbOkb[]beq0000000000000000000000000000000000000000000000000000000000000000000000000bid0000000000000brtbtybu8cAck0cAnycArccBbr00cBoxcBufcClicDir0cErrcMAX000cNotcOpt00cOrdcPincUni0cVeccbbrccmp0000000000000000000cdir000cecn000cf32cf64cfmt00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cgetci32cimpcios0clen000clog0cmincmutcnew00000000000000000000000000000000000cnot0cnow000000crtt000crun0cstrcu16cu32cu64cudpdArgsdAsFddDropdEct000dEct100dFromdHashdIntodKeys0dLong0dPath00dPing0dPolldReaddSenddSide0dSyncdVZipdZERO0dacks0daddr0dbooldbulkdcodedcwnd0ddataddrop0000dfrom000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dhash00000000000000000000dinto000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dmain0000dnextdopen00dpath0dperfdping000dpoll0000000000000dqlogdread00drecv00dseal0dsend00dsent0dside0dsign0dsize00dsmoldspindstop00dtake00000du128dunitdvzip0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eAsRefeByteseChunk0eCloneeCloseeCubic00eDebugeDerefeError00000000000eEvent00eOther0eRangeeReset000eRetry0eShort0eSizedeStats0eSuiteeWriteearrayebenchebuild00000000ebytes00000ecauseeclone0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eclose000ecubicederef0eerror0eframe0eindex0eis_ce0elocal0eparse0epaths0eprint00ereset00eretry0esliceespawn00estats00000000etitle0etokenetokioetupleeusizeewrite00fAcceptfAckEcn0fAes128fAes256fBackupfBorrowfBufMutfChunksfClient00fClosed00fCrypto0fCursorfFuturefHasherfIpAddrfOpenBifOpened000fOptionfOutputfPathId0fResult00000fServer00fStream00fStringfTypeIdfVarInt0faccept000fborrow000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fchunks0fcipherfclient0000fclosedfcoding0fconfig0fcrypto0000000000fdecode00000000000fdst_ipfencode00000000000ffinish00fhandlefheader0fignore0finsert00000fkeylogfoffset0fon_ack0000000fpacket00frandomfreason00000frebindfrefuse0fremote00frustls00000fserver0000fsharedfsource00000000fsrc_ip00fstatus0fstream0fstridefudp_rx0fudp_tx0fvarintfverify0fwindow0000000gAeadKey0gBlocked00gCommandgContextgDefaultgDisplaygFromStrgGeneral0gHmacKey0gInitialgInstantgKeyPair0gLayeredgMaxData0gNewReno00gOpenUnigPadding0gPathAck0gPathBufgReadBufgRequestgRuntime0gSession0gStopped0000gStreamsgToOwnedgTooLonggTryFromgTryIntogWritten0gZeroRttgcid_len000gclientsgcommand00000gcompare0000000000000000000gconnect0gdecrypt000gdefault000000000000000000000000000000000000000000000000000gdrainedgdst_cid0000000gencrypt000giroh_hp0gis_0rtt0gmetrics0000000gmin_mtu0gon_sent000gopen_bigpath_idgpointergruntimegsrc_cid0000gstopped0gstreams000gtag_len0gtype_id000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000gupgradegversion00000hAcceptBihBytesMuthChacha20hCommandshDatagram00hDerefMuthDisabled0hDurationhEndpoint00hFinished0hIncoming0hLayerExthLongTypehMAX_SIZE0hNO_ERROR0hNewToken0hOnClosedhOpenPathhOrderinghReadable0hReceiver0hRecvMetahResponsehStreamId0hTimedOut0hToStringhTokenLog0hTooLarge0hTransmit00hUdpStats0hUnixTimehWritable0hcong_alghcontentshdatagram0hdurationhendpoint0hfinalizehframe_rx0hframe_tx0hfrom_buf0hfrom_env0hfrom_keyhfrom_strhfrom_u320hfrom_u640hgot_type000hgroup_id0000hhas_0rtthincominghinterval0hinto_any0000000his_alivehlifetime0hlocal_ip0000hmax_data0hmax_sizehnew_renohon_byteshopen_unihpriority0hprotocol0hqlog_dirhresponsehrng_seed0hssthresh0hto_owned0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_from000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_into000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000htry_poll00000000htry_sendhvalidate000iAbandoned0iAcceptUniiArbitraryiAsyncRead0iAvailable00iBbrConfig0iBorrowMutiCommonOptiConnectediCriterioniDatagramsiDecodableiEncodableiFormatteriFourTupleiFrameType0iHandshakeiHeaderKey0iHistogramiMalformediMaxPathId0iMultipathiPacketKey0iPartialEqiPathErroriPathEvent00iPathStats0iReadError00iTryFutureiUdpSenderiUdpSocketiValueEnumiaccept_biiarbitrary0000000ias_rustlsiassemblericlone_box0000000idatagrams000ideref_mut0ifrom_bits00iinitiator0iinto_0rttiis_client0iis_closediis_server0imay_retry0imigration0inew_timer00inew_token0ion_closediopen_path0ipath_acks0iping_pathipoll_read00ipoll_recvipoll_sendireach_out0ireferenceireset_key0iretry_tag0000isize_hint00000istable_idito_string0000000000000000000000000000000000000000000000000000000itoken_key0itoken_positransport00iwait_idleiwrite_alljArgMatchesjAsyncTimerjAsyncWrite0jBATCH_SIZEjClosedPath000jComparablejConnectingjConnection00jController0jEquivalent0jFrameStats0jIntoFuturejInvalidCid0jIoSliceMutjMaybeFramejNamedGroupjNonZeroU32jOtherErrorjPartialOrdjPathAckEcn0jPathStatus0jQlogConfig0jRecvStream00jResetErrorjRetryError0jSendStream00jServerNamejSocketAddrjSubcommandjSystemTimejTimeSource0jTlsSession0jTokenStore0jUdpSockRefjWriteError0jaccept_unijallow_spin0jborrow_mut000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclone_into0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jclose_pathjcongestion000jconn_statsjconnection0jequivalent00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000jerror_code00000jframe_type0jinto_inner0jiroh_quinnjis_drained0jlocal_addr0jlost_bytes0jnew_senderjpad_to_mtu0jpath_stats00jpoll_closejpoll_flush0jpoll_write00jprint_jsonjquinn_perfjread_chunk0jread_exactjset_statusjstart_time0jthroughputjtotal_sizekAcceptErrorkCLIENT_ADDRkCipherSuitekClientStatskCloseReasonkConfigError0kContentTypekCryptoError0kCubicConfig0kDataBlocked0kFinishErrorkIdleTimeout0kIntoRequestkOutOfBounds0kPathAbandon0kQlogFactory0kResetStream0kSERVER_ADDRkSERVER_NAMEkSmolRuntimekStopSending0kStreamEvent0kStreamStats0kUnspecifiedkaccept_withkadd_address0kbind_socketkcertificatekcurrent_mtu00kdescription0kdestination00kinitial_mtu000kinitial_rtt00kinto_future000000000000kmax_path_id0kmax_streamsknamed_layer0kon_end_acks000kon_intervalkpacing_rate0kpartial_cmp0000000000000000000kpath_eventskpath_statuskread_chunkskread_to_endkrecv_stream0ksample_size0ksend_bufferksend_stream0ksend_window00kserver_name0ktime_source0ktoken_store0kupload_sizekupper_bound0kweak_handlekwith_crypto0kwith_prefix0kwrite_chunklAckFrequency0lAddressAddedlClientConfig00000lClosedStream000000lConnectError00lConnectionId00lDecryptError0lEcnCodepoint00lEncryptError0lIllegalValuelImmediateAck0lLOCALHOST_V4lLastOpenPathlNatTraversallNonZeroUsizelNoneTokenLog0lObservedAddr0lPathResponse0lPathsBlocked0lReadDatagramlRemoteStatus0lRttEstimator0lSendDatagramlServerConfig00000lSocketAddrV4lSocketAddrV6lStoppedErrorlTokioRuntimelUnstructuredlaugment_args0000lcid_lifetime000lclose_reasonlconnect_withlconservativeldata_blocked0ldrain_streamlearly_crypto000lexpect_types000lgenerate_cid000lgro_segmentslhandle_event0linitial_keys00000000linto_request0llost_packets0lmax_incoming0lmay_fragment00lnetwork_pathlnew_receiverlnoprotection0lorig_dst_cid0lpath_abandon0lpoll_timeoutlqlog_factory0lreset_stream0lsegment_size00lsend_streamslsent_packets0lset_lifetime0lset_priority0lstop_sending0lstream_statslupload_statslwith_initial000lwrite_chunks0mAlertReceived0mBloomTokenLog0mCidsExhausted000mCloneToUninitmDatagramEventmEndpointEventmEndpointStatsmFinishedEarlymHandshakeData0mHandshakeDone0mHandshakeTypemINVALID_TOKEN0mInvalidHeadermLocallyClosed000mMaxStreamData0mMaxStreamsUni0mNewConnectionmNewRenoConfig0mParseIntErrormPartialDecodemPathChallenge0mPossibleValuemPrivateKeyDermReadableErrormRemoveAddress0mRootCertStoremStdSystemTime0mUnexpectedEndmaccepted_0rttmack_frequency00mbench_exports0mcid_generator00mcreate_sendermdata_transfermdownload_sizemduration_histmimmediate_ack0minto_incoming0mmax_ack_delay0mno_protectionmobserved_addr0mon_first_bytemon_mtu_update0000000mpath_response0mpaths_blocked0mpeer_identity0000mpoll_read_bufmpoll_shutdownmpoll_transmitmqlog_from_env0mread_datagrammsend_datagrammsend_fairness0msignature_len0mstart_session000000000mtry_size_hint0nAddIpv4Address0nAddIpv6Address0nAddressRemovednAsyncUdpSocketnCertificateDernClosePathError0nCommandFactorynConnectionLost000000nEndpointConfig0nFromArgMatchesnINTERNAL_ERROR0nIncomingFuturenInvalidMessage00nMaxStreamsBidi0nNO_VIABLE_PATH0nNoneTokenStore0nPeerMisbehaved00nReachOutAtIpv40nReachOutAtIpv60nReadExactErrornReadToEndErrornShouldTransmitnTransferResultnTransportError00nUdpSocketStatenaead_from_hkdf0nconnect_clientncrypto_sessionndownload_statsnfor_connection000nhandle_timeoutnhandshake_data00000nhandshake_done0nhas_subcommandninitial_window0000000000000ninto_unorderedniroh_quinn_udpnis_handshaking0000nis_valid_retry000nminimum_change0nnext_1rtt_keys000npath_challenge0nqlog_from_path0nread_handshake000nread_unorderednreceive_window00nreceived_reset00nremote_address0000nremove_address0nsaturating_add000nsaturating_sub0nthroughput_bpsntime_threshold0ntotal_durationnvalue_variantsoConnectionClose000oConnectionError0oConnectionEvent0oConnectionStats0oGetRandomFailedoNewConnectionId0oOpenStreamStatsoPathCidsBlocked0oProtectedHeader0oQlogFileFactory0oSignatureSchemeoSystemTimeErroroTokenReuseError0oTransportConfig00oTryFromIntErroroVersionMismatch0oZeroRttAcceptedoZeroRttRejected000obloom_token_logoclone_to_uninit0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000odefault_runtimeogrease_quic_bit0ointegrity_limit0ointerface_indexomax_stream_data0omax_streams_uni0oparse_byte_sizeorebind_abstractosend_unreliableoserver_endpointoset_path_statusoset_send_window0oshould_transmitostream_finishedothroughput_histowrap_udp_socket00owrite_handshake000A`ApplicationClose000A`CertificateErrorA`ConnectionClosed0A`ConnectionHandleA`DatagramReceivedA`EndpointStopping0A`FINAL_SIZE_ERROR0A`InconsistentKeys00A`KEY_UPDATE_ERROR0A`MaxPathIdReachedA`ObservedIpv4Addr0A`ObservedIpv6Addr0A`PathStatusBackup0A`PeerIncompatible00A`QuicClientConfig0A`QuicServerConfig0A`TokenMemoryCache0A`TooManyAddressesA`ValidationFailedA`VersionNegotiate0A`check_and_insert00000A`configure_clientA`congestion_state0A`connection_close0A`force_key_update0A`from_arg_matches00000A`iroh_quinn_protoA`max_gso_segmentsA`max_idle_timeout0A`max_streams_bidi0A`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_ERROR0AaApplicationClosed0AaControllerFactory0AaControllerMetrics0AaHandshakeTokenKey0AaInvalidServerName0AaPacketDecodeError0AaSendDatagramError0AaStreamDataBlocked0AaStreamsBlockedUni0AaUnsupportedByPeer0Aacongestion_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_ERROR0AbServerCertVerifiedAbServerCertVerifierAbSetPathStatusError0AbStreamsBlockedBidi0AbTransportErrorCode0AbUnsupportedVersion00000Abcommand_for_update0000Abcrypto_buffer_size0Abfrom_u64_unchecked0Abignored_handshakesAbmin_reset_interval0Abnew_expected_items0Abpath_status_backup0Abrefused_handshakesAbremote_path_statusAbsend_datagram_waitAbset_receive_window0Absupported_versions0Abtoken_memory_cacheAbverify_server_certAbwith_start_instant0AcCongestionAlgorithmAcMaxRecursionReachedAcPathNewConnectionId0AcPathStatusAvailable0AcRemoteCidsExhaustedAcTransportParametersAcUnorderedRecvStreamAcUnsupportedNameType0AcWrongConnectionSideAcaccepted_handshakesAcarbitrary_take_rest00000Acaugment_subcommandsAcblack_hole_cooldown0Acearly_data_accepted000Achandshake_confirmedAckeep_alive_interval0Aclost_plpmtud_probes0Acon_congestion_event0000000Acoutgoing_handshakesAcremote_open_streamsAcsend_buffer_benches00Acsend_data_on_streamAcsent_plpmtud_probes0Acstream_data_blocked0Acstreams_blocked_uni0AdFRAME_ENCODING_ERROR0AdHandshakeNotComplete0AdInappropriateMessage000AdInvalidRemoteAddress00AdNoInitialCipherSuite0AdServerSideNotAllowedAdSupportedCipherSuiteAdVarIntBoundsExceeded0AdVerifierBuilderErrorAdWeakConnectionHandleAdack_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_limit0Aeincoming_buffer_bytesAeis_probably_same_pathAelocal_address_changedAeloss_reduction_factor0Aemax_transmit_segments0Aenat_traversal_updatesAepath_observed_addressAepath_status_available0Aestream_receive_window00AfCRYPTO_BUFFER_EXCEEDED0AfExtensionNotNegotiatedAfFailedToGetCurrentTime0AfFailedToGetRandomBytes0AfMultipathNotNegotiated0AfPathRetireConnectionId0AfProtectedInitialHeaderAfSkipServerVerificationAfbuild_transport_configAfexport_keying_material0000Afget_into_many_segmentsAfget_loop_many_segmentsAfmax_concurrent_streamsAfobserved_external_addr0Afpath_new_connection_id0Afverify_tls12_signatureAfverify_tls13_signatureAfwith_platform_verifier0Afwith_root_certificates0AgCertRevocationListErrorAgHandshakeSignatureValidAgNoCertificatesPresented0AgPeerSentOversizedRecord0Agack_eliciting_threshold0Agaugment_args_for_update0000Aghas_pending_retransmitsAgis_multipath_negotiatedAgset_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_VERSIONSAjdatagram_send_buffer_spaceAjincoming_buffer_size_total0Ajmax_concurrent_uni_streams0Ajopen_unidirectional_streamAjset_max_concurrent_streamsAjtry_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_event000Alreceive_bidirectional_streamAlremove_nat_traversal_address0Alset_path_keep_alive_intervalAmFixedLengthConnectionIdParserAmInappropriateHandshakeMessage000Amcongestion_controller_factory0Amdefault_path_max_idle_timeout0Amnegotiated_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/255/docs/search.index/normalizedName/479d9533fdd1.js b/pr/255/docs/search.index/normalizedName/479d9533fdd1.js deleted file mode 100644 index bb1d7331c..000000000 --- a/pr/255/docs/search.index/normalizedName/479d9533fdd1.js +++ /dev/null @@ -1 +0,0 @@ -rd_("b()b->bbi0bce00bfnbidbokb[]beq000000000000000000000000000000000000000000000000000000000000000000000000033333333333333brtbtybu8cack0canycarccbbr00cboxcbufcclicdir0cerrcmax000cnotcopt00cordcpincuni0cvecbbi0bce00bfnbidbokb[]beq0000000000000000000000000000000000000000000000000000000000000000000000000000033333333333333brtbtybu8cack0canycarccbbr00cboxcbufcclicdir0cerrcmax000cnotcopt00cordcpincuni0cvecA`[5,\"iroh_quinn\"]Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::transport\"]Ae[10,\"tonic::request\"]Aa[10,\"iroh_quinn\"]Ch[10,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::qlog\"]Bl[5,\"iroh_quinn\",\"iroh_quinn::runtime::smol\"]Af[2,\"iroh_quinn_proto\"]Cn[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams\"]Ba[5,\"bench::stats\",\"bench::stats\"]Ao[5,\"perf::stats\",\"perf::stats\"]Ci[5,\"ring::error::unspecified\",\"ring::error::unspecified\"]f[3,\"\"]A`[2,\"iroh_quinn\"]Bb[2,\"iroh_quinn_proto::connection\"]1Co[5,\"rustls::client::client_conn\",\"rustls::client::client_conn\"]Ci[5,\"iroh_quinn_proto::config\",\"iroh_quinn_proto::config\"]?Ai[10,\"iroh_quinn::crypto\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Cj[10,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]A`[5,\"iroh_quinn\"]Cn[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams\"]Cm[6,\"iroh_quinn_proto::endpoint\",\"iroh_quinn_proto::endpoint\"]A`[6,\"iroh_quinn\"]Cc[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::endpoint\"]Ci[5,\"iroh_quinn_proto::shared\",\"iroh_quinn_proto::shared\"]5Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::frame\"]4Ca[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]Be[6,\"iroh_quinn_udp\",\"iroh_quinn_udp\"]Bm[8,\"core::num::nonzero\",\"core::num::nonzero\"]:C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token\"]Bb[15,\"iroh_quinn_proto::PathEvent\"]Bi[5,\"iroh_quinn\",\"iroh_quinn::connection\"]1Do[5,\"iroh_quinn_proto::connection::paths\",\"iroh_quinn_proto::connection::paths\"]Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::paths\"]2Co[5,\"rustls::server::server_conn\",\"rustls::server::server_conn\"]Ci[5,\"iroh_quinn_proto::config\",\"iroh_quinn_proto::config\"]A`[5,\"iroh_quinn\"]Ai[10,\"iroh_quinn::crypto\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Cj[10,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]Ce[5,\"core::net::socket_addr\",\"core::net::socket_addr\"]0Bj[6,\"iroh_quinn\",\"iroh_quinn::send_stream\"]Bm[5,\"iroh_quinn\",\"iroh_quinn::runtime::tokio\"]Cg[5,\"arbitrary::unstructured\",\"arbitrary::unstructured\"]j[2,\"perf\"]8Cj[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::bloom_token_log\"]Ab[10,\"core::clone\"]Cc[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::endpoint\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]Bg[5,\"iroh_quinn\",\"iroh_quinn::endpoint\"]B`[5,\"iroh_quinn::crypto::rustls\"]Di[5,\"iroh_quinn_proto::crypto::rustls\",\"iroh_quinn_proto::crypto::rustls\"]Bc[6,\"rustls::enums\",\"rustls::enums\"]Bb[15,\"iroh_quinn_proto::PathEvent\"]Al[5,\"iroh_quinn::congestion\"]Dk[5,\"iroh_quinn_proto::congestion\",\"iroh_quinn_proto::congestion::new_reno\"]Bi[5,\"core::num::error\",\"core::num::error\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]Ec[5,\"clap_builder::builder::possible_value\",\"clap_builder::builder::possible_value\"]Bi[6,\"rustls_pki_types\",\"rustls_pki_types\"]Dd[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams::recv\"]Cg[5,\"rustls::webpki::anchors\",\"rustls::webpki::anchors\"]A`[5,\"iroh_quinn\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Ci[5,\"iroh_quinn_proto::coding\",\"iroh_quinn_proto::coding\"]Af[2,\"iroh_quinn_proto\"]0f[3,\"\"]Bg[10,\"iroh_quinn\",\"iroh_quinn::runtime\"]Bi[5,\"rustls_pki_types\",\"rustls_pki_types\"]Da[6,\"iroh_quinn_proto::connection\",\"iroh_quinn_proto::connection\"]Ce[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection\"]Ak[10,\"clap_builder::derive\"]An[15,\"iroh_quinn_proto::Event\"]:91Bg[5,\"iroh_quinn\",\"iroh_quinn::incoming\"]C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::frame\"]Bc[6,\"rustls::error\",\"rustls::error\"]=C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token\"]1Bj[6,\"iroh_quinn\",\"iroh_quinn::recv_stream\"]0Cn[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams\"]Ba[5,\"bench::stats\",\"bench::stats\"]Af[5,\"iroh_quinn_proto\"]Bj[5,\"iroh_quinn_udp\",\"iroh_quinn_udp::imp\"]?A`[5,\"iroh_quinn\"]8A`[6,\"iroh_quinn\"]=Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]2Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::stats\"]Ba[5,\"rustls::rand\",\"rustls::rand\"]Ao[5,\"perf::stats\",\"perf::stats\"]Af[2,\"iroh_quinn_proto\"]Ca[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]7Cg[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::qlog\"]Bc[6,\"rustls::enums\",\"rustls::enums\"]Ak[5,\"std::time\",\"std::time\"]:C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token\"]Do[5,\"iroh_quinn_proto::config::transport\",\"iroh_quinn_proto::config::transport\"]A`[5,\"iroh_quinn\"]Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::transport\"]Ae[10,\"tonic::request\"]Aa[10,\"iroh_quinn\"]Ch[10,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::qlog\"]Bl[5,\"iroh_quinn\",\"iroh_quinn::runtime::smol\"]Af[2,\"iroh_quinn_proto\"]Cn[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams\"]Ba[5,\"bench::stats\",\"bench::stats\"]Ao[5,\"perf::stats\",\"perf::stats\"]Ci[5,\"ring::error::unspecified\",\"ring::error::unspecified\"]f[3,\"\"]A`[2,\"iroh_quinn\"]Bb[2,\"iroh_quinn_proto::connection\"]1Co[5,\"rustls::client::client_conn\",\"rustls::client::client_conn\"]Ci[5,\"iroh_quinn_proto::config\",\"iroh_quinn_proto::config\"]?Ai[10,\"iroh_quinn::crypto\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Cj[10,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]A`[5,\"iroh_quinn\"]Cn[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams\"]Cm[6,\"iroh_quinn_proto::endpoint\",\"iroh_quinn_proto::endpoint\"]A`[6,\"iroh_quinn\"]Cc[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::endpoint\"]Ci[5,\"iroh_quinn_proto::shared\",\"iroh_quinn_proto::shared\"]5Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]3Ca[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]Be[6,\"iroh_quinn_udp\",\"iroh_quinn_udp\"]Bm[8,\"core::num::nonzero\",\"core::num::nonzero\"]9C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token\"]Bb[15,\"iroh_quinn_proto::PathEvent\"]Bi[5,\"iroh_quinn\",\"iroh_quinn::connection\"]1Do[5,\"iroh_quinn_proto::connection::paths\",\"iroh_quinn_proto::connection::paths\"]Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::paths\"]2Co[5,\"rustls::server::server_conn\",\"rustls::server::server_conn\"]Ci[5,\"iroh_quinn_proto::config\",\"iroh_quinn_proto::config\"]A`[5,\"iroh_quinn\"]Ai[10,\"iroh_quinn::crypto\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Cj[10,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]Ce[5,\"core::net::socket_addr\",\"core::net::socket_addr\"]0Bj[6,\"iroh_quinn\",\"iroh_quinn::send_stream\"]Bm[5,\"iroh_quinn\",\"iroh_quinn::runtime::tokio\"]Cg[5,\"arbitrary::unstructured\",\"arbitrary::unstructured\"]j[2,\"perf\"]8Cj[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::bloom_token_log\"]Ab[10,\"core::clone\"]Cc[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::endpoint\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]Bg[5,\"iroh_quinn\",\"iroh_quinn::endpoint\"]B`[5,\"iroh_quinn::crypto::rustls\"]Di[5,\"iroh_quinn_proto::crypto::rustls\",\"iroh_quinn_proto::crypto::rustls\"]Bc[6,\"rustls::enums\",\"rustls::enums\"]Bb[15,\"iroh_quinn_proto::PathEvent\"]Al[5,\"iroh_quinn::congestion\"]Dk[5,\"iroh_quinn_proto::congestion\",\"iroh_quinn_proto::congestion::new_reno\"]Bi[5,\"core::num::error\",\"core::num::error\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]Ec[5,\"clap_builder::builder::possible_value\",\"clap_builder::builder::possible_value\"]Bi[6,\"rustls_pki_types\",\"rustls_pki_types\"]Dd[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::streams::recv\"]Cg[5,\"rustls::webpki::anchors\",\"rustls::webpki::anchors\"]A`[5,\"iroh_quinn\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Ci[5,\"iroh_quinn_proto::coding\",\"iroh_quinn_proto::coding\"]Af[2,\"iroh_quinn_proto\"]0f[3,\"\"]Bg[10,\"iroh_quinn\",\"iroh_quinn::runtime\"]Bi[5,\"rustls_pki_types\",\"rustls_pki_types\"]Da[6,\"iroh_quinn_proto::connection\",\"iroh_quinn_proto::connection\"]Ce[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection\"]Ak[10,\"clap_builder::derive\"]An[15,\"iroh_quinn_proto::Event\"]:91Bg[5,\"iroh_quinn\",\"iroh_quinn::incoming\"]Bc[6,\"rustls::error\",\"rustls::error\"]A`[5,\"iroh_quinn\"]C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::frame\"]A`[6,\"iroh_quinn\"]=Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::shared\"]3Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::stats\"]Ba[5,\"rustls::rand\",\"rustls::rand\"]Ao[5,\"perf::stats\",\"perf::stats\"]Af[2,\"iroh_quinn_proto\"]Ca[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]8Cg[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::qlog\"]Bc[6,\"rustls::enums\",\"rustls::enums\"]Ak[5,\"std::time\",\"std::time\"];C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token\"]Do[5,\"iroh_quinn_proto::config::transport\",\"iroh_quinn_proto::config::transport\"]=Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::transport\"]Bi[5,\"core::num::error\",\"core::num::error\"]Bi[5,\"iroh_quinn\",\"iroh_quinn::connection\"]9A`[5,\"iroh_quinn\"]C`[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::frame\"]Bc[6,\"rustls::error\",\"rustls::error\"]Cc[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::endpoint\"]11B`[5,\"iroh_quinn::crypto::rustls\"]Di[5,\"iroh_quinn_proto::crypto::rustls\",\"iroh_quinn_proto::crypto::rustls\"]105Cm[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::token_memory_cache\"]Bh[15,\"iroh_quinn_proto::ProtectedHeader\"]f[3,\"\"]Am[10,\"iroh_quinn::congestion\"]Db[10,\"iroh_quinn_proto::congestion\",\"iroh_quinn_proto::congestion\"]Al[5,\"iroh_quinn::congestion\"]Da[5,\"iroh_quinn_proto::congestion\",\"iroh_quinn_proto::congestion\"]Ai[10,\"iroh_quinn::crypto\"]Cj[10,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]Af[2,\"iroh_quinn_proto\"]Ca[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]Bi[6,\"iroh_quinn\",\"iroh_quinn::connection\"]D`[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::datagrams\"]:A`[5,\"iroh_quinn\"]Cl[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config::transport\"]Cb[10,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]21Bi[5,\"rustls_pki_types\",\"rustls_pki_types\"]Be[5,\"rustls::verify\",\"rustls::verify\"]Ae[10,\"rustls::verify\"]Do[6,\"iroh_quinn_proto::connection::paths\",\"iroh_quinn_proto::connection::paths\"]Cl[6,\"iroh_quinn_proto\",\"iroh_quinn_proto::connection::paths\"]7Af[5,\"iroh_quinn_proto\"]Bj[15,\"iroh_quinn_proto::PacketDecodeError\"]Ah[5,\"iroh_quinn::crypto\"]Ci[5,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]?Aa[6,\"perf\",\"perf\"]Ak[5,\"arbitrary\",\"arbitrary\"]Ee[5,\"iroh_quinn_proto::transport_parameters\",\"iroh_quinn_proto::transport_parameters\"]Bj[5,\"iroh_quinn\",\"iroh_quinn::recv_stream\"]Bo[2,\"iroh_quinn_proto::connection::send_buffer\"]Be[2,\"iroh_quinn_proto::bench_exports\"]Bh[15,\"iroh_quinn::crypto::rustls::Error\"]Bn[15,\"iroh_quinn_proto::crypto::rustls::Error\"]B`[5,\"iroh_quinn::crypto::rustls\"]Di[5,\"iroh_quinn_proto::crypto::rustls\",\"iroh_quinn_proto::crypto::rustls\"]Be[6,\"rustls::suites\",\"rustls::suites\"]A`[5,\"iroh_quinn\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::varint\"]Be[6,\"rustls::webpki\",\"rustls::webpki\"]Bi[5,\"iroh_quinn\",\"iroh_quinn::connection\"]Af[2,\"iroh_quinn_proto\"]Aa[10,\"iroh_quinn\"]Ci[10,\"iroh_quinn_proto\",\"iroh_quinn_proto::cid_generator\"]Be[5,\"rustls::verify\",\"rustls::verify\"]7Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::config\"]Ca[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::packet\"]Ao[5,\"certificate\",\"certificate\"]Bc[6,\"rustls::error\",\"rustls::error\"]4Bm[5,\"perf::noprotection\",\"perf::noprotection\"]01Ah[5,\"iroh_quinn::crypto\"]Ci[5,\"iroh_quinn_proto::crypto\",\"iroh_quinn_proto::crypto\"]Ce[5,\"rustls::crypto::cipher\",\"rustls::crypto::cipher\"]Ch[5,\"iroh_quinn_proto\",\"iroh_quinn_proto::cid_generator\"]07Bh[15,\"iroh_quinn::crypto::rustls::Error\"]Bn[15,\"iroh_quinn_proto::crypto::rustls::Error\"]") \ No newline at end of file diff --git a/pr/255/docs/search.index/root.js b/pr/255/docs/search.index/root.js index 169f35e33..d3debb1f1 100644 --- a/pr/255/docs/search.index/root.js +++ b/pr/255/docs/search.index/root.js @@ -1 +1 @@ -rr_('{"normalizedName":{"I":"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","N":"ACJj","E":"OjAAAAAAAAA=","H":"R52VM/3R"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"ijgfzyvU"},"name":{"N":"ACJj","E":"OjAAAAAAAAA=","H":"gmOgDEyK"},"path":{"N":"B@j","E":"OzAAAAEAAJ8RsAACAAQACQAAAAsAWQBmAAEAbAAAAHIABAB9AAEAgQAbAJ8A1QB3AQgAgQEyALgBAAC8AQUAyAEAAMsBAgDPAQAA1QEFAN0BFwL2AwAA+AMRAAsEAgAPBAMAFAQKACAECQAsBNAABQUAABcFAQAaBQMAHwUAACEFAAApBYoAtQUBALgFAAC6BQgAxAUIAM4FAgDUBQcA4AUCAOQFBADsBQIA8AUDAPsFAQAHBgUAEQbcAO8GBAD1BgAA9wYAAPoGOgA2Bw4ARwcDAEwHAwBRBxQAZwcJAHMHAgB7BwEAfwcAAIQHAQCIBwAAigcDAJYHAwCcBwAAoQdmAAkIEgAeCAYAJgjhAAoJAAAMCQEAEAkBABcJAAAcCQUAJgkAACoJAAAtCQEAMgkBADsJBQBDCRgAXQkUAHMJTgLDCwAAyQsBAM8LAADYCwAA3AsDAOkLAADwCwkA+wsHAAQMJQArDEgAdQwDAH0MAAB/DAEAlgwBALIMUAEFDgIACg7eAOoOEgD+DgcABw8AABIPAQAYDwMAHg8DACMPAQAqDwMALw8/AHAPAgB1DxUAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ8xAPgPHwAaEAMAIhAAACUQAQAoEAIALBAHADgQAQA9EAEAQxADAEgQAABKEAIAThA4AI0QBQCWEAEAmhAFAKMQBQCtEAEAsRAhANQQMAAGEQAAChEAAA8RAQASEQEAIBEBACMRAwAoEZIAvBEAAL8RAQDCEQQAyBEKANQRAQDcEQEA3xETAPQRHQAYEgEAHhIRADESAgA2EgMAOxIHAEUSAwBKEgUAVBIBAFkSAABbEgEAXhIWAHYSAgB7EgQAghIfAKQSCwCyEgQAuRIAAL8SJQDmEgQA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"jwNIbELx"},"entry":{"N":"ABJf","E":"OjAAAAEAAAAAAAMBEAAAAAAAAQAHAAgACgBlAGgAaQBtAG4AdwB7AHwAfwCAAJ0AngB1AXYBgAG0AbUBtgG3AbkBugG7AcIBwwHEAccByQHOAdAB0wHUAdsB9QMKBA4EEwQfBCoEKwT9BP4EAQUCBQYFBwUIBQkFCgULBQwFDQUOBQ8FFAUZBR4FIAUiBSUFJgUnBbQFtwW5BcMFzQXRBdIF0wXcBd0F3gXfBekF6gXvBfQF9QX2BfcF+QX6Bf0F/gUBBgIGAwYEBgUGDQYOBu4G9Ab2BvgG+QY1B0UHRgdLB1AHZgd2B3cHeAd5B3oHgAeDB44HjweQB5EHlQebB50HngcICBwIHQglCAkJDwkSCRMJFgkaCSQJJQknCSgJLwk5CToJQQlCCVwJcgnCC8ULxgvHC8gLzQvQC9QL2wviC+QL5QvsC+4L7wv6CwMMKgx0DHkMewx8DH4MggyEDIkMigyNDI4MkAyRDJIMkwyUDJUMmAycDKIMpQymDKcMqAwDDgQOCA4JDgoPDQ8XDyUPKQ9vD3MPdA+LD4wPmA+bD6sPrg+1D7cPug+7D8APwQ/ED/cPHhAnECsQNhA6EDsQPxBHEEkQiBCJEIsQjBCVEJkQohAOERQRGBEZERwRHxEnEb4RxxHTEd4RGhJJElASURJSElgSdRJ6EqISoxKwErESuhK9EuUS7RImEycTTRNWE4oTixM=","H":"6/FXEJon"},"desc":{"N":"FIk","E":"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","H":"7igw/4ee"},"function":{"N":"A@Df","E":"OzAAAAEAAGMDVwAAAAoAZQAbAJ0AAQB1AQEAgAEAALQBIgDbAQEA9QMAAPcDAAAKBAAADgQAABMEAAAfBAAAKgQBAP0EKwC0BQAAtwUAALkFAADDBQAAzQUAANEFAwDZBQAA3AUDAOMFLQDuBgAA8QYAAPQGAgD4BgIA/gYAADUHAABFBwYATgcAAFAHAABmBwAAcQcwAAgIAQAcCAEAJQgAAAgJMwBBCQEAXAkAAHIJAADCCy0A+gsAAAMMAAAqDAAAdAwAAHkMAwB+DDMAAw4DAAgOAQDpDgAA/Q4AAAYPAAAIDxcAIg8HAC4PAABvDwAAcw8BAIgPHwCpDxsA9w8BABYQLABHEAIATRAAAIIQLgDTEAAABBEjALoRJQDzEQAADhIVADASAAAyEhMARxIWAHUSAAB5EgsAohICAKwSEgDlEgAA6BIAAOsSCgAGEwwAJhMFAD4TAwBLEwsAaxMFAIkTBAA=","H":"4L0CD+5+"},"type":{"N":"AIn","E":"OzAAAAEAAAsSkgACAAQACQAAAAsAWQBmAAEAbAAAAHIABQB7AAAAfQABAIAAHACfANUAdgEJAIEBMgC4AQEAuwEIAMgBAADLAQIAzwEAANQBBgDcAU0CLATQAAEFAAAFBQIADAUBABQFAAAXBQEAGgUDAB8FAAAhBQAAKAWkAM4FDwDgBQIA5AUFAOwFAgDwBQMA+wUBAAcGBQARBl8BcwcCAHgHBAB/BwAAhAcBAIgHAACKBwMAlgcDAJsHAwChB3oAHQjqAAoJAAAMCQEADwkCABcJAAAaCQAAHAkFACYJAAAqCQAALQkBADIJAQA7CYYCwwsAAMULAgDJCwEAzQsAAM8LAADYCwAA3AsDAOILAADkCwAA6QsAAOwLAADvCzoAKwxNAHsMAgB/DAEAggwAAIkMAQCNDAAAlQwCAKcMAACyDFMCBw8AABIPAQAXDwQAHg8DACMPAgAqD2AAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ9SABoQBAAiEAAAJRABACgQAgAsEAcAOBABAD0QAQBDEEMAixAAAI0QBQCVEAIAmhAFAKMQBQCtEAEAsRBTAAYRAAAKEQAADxEBABIRAgAgEQEAIxGXALwRAAC/EQEAwhEEAMgRCgDUEQEA3BEBAN8RMgAYEgIAHhIVADYSAwA7EgcARRIDAEoSBQBREgAAVBIBAFkSAABbEgEAXhIaAHsSBACCEi0AshIEALkSAAC/EisA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"I7Zgg8Ac"},"alias":{"N":"`","E":"OzAAAAEAAKkTAQAAAKkT","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"dwUQgl4C"}}') \ No newline at end of file +rr_('{"normalizedName":{"I":"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","N":"ADBk","E":"OjAAAAAAAAA=","H":"nN3o7qhY"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"ijgfzyvU"},"name":{"N":"ADBk","E":"OjAAAAAAAAA=","H":"Uu5dxay5"},"path":{"N":"BAb","E":"OzAAAAEAABgStAACAAQACQAAAAsAXQBqAAEAcAAAAHYABACBAAEAhQAbAKMA3wCFAQgAjwEyAMYBAADKAQUA1gEBANoBAgDeAQAA5AEFAOwBJwIVBAAAFwQSACsEAgAvBAMANAQKAEAECQBMBNgALQUAAD8FAgBDBQMASAUAAEoFAABSBY8A4wUBAOYFAADoBQgA8gUIAPwFAgACBgcADgYCABIGBAAaBgIAHgYDACkGAQA1BgIAOQYCAEAG5AAmBwQALAcAAC4HAAAxBzwAbwcOAIAHAwCFBwMAigcUAKAHCQCsBwIAtAcBALgHAAC9BwEAwQcAAMMHAwDPBwMA1QcAANgHAADbB2YAQwgSAFgIBgBgCOkATAkAAE4JAQBSCQEAWQkAAF4JBQBoCQAAbAkAAG8JAQB0CQEAfQkFAIUJGACfCRQAtQlkAhsMAAAhDAEAKAwAADEMAAA1DAMAQgwAAEkMCQBUDAcAXQwmAIUMTADTDAMA2wwAAN0MAQD1DAEAEg1dAXIOAgB3DuoAYw8SAHcPBwCADwAAiw8BAJEPAwCXDwMAnA8BAKMPAwCoD0AA6g8CAO8PFQALEAEADhACABkQAQAeEAcAKhAEADEQAABAEDEAcxAfAJUQAwCdEAAAoBABAKMQAgCnEAcAsxABALgQAQC+EAMAwxAAAMUQAgDJEDgACBEFABERAQAWEQUAHxEFACkRAQAtESEAUBEwAIIRAACGEQAAixEBAI4RAQCcEQEAnxEDAKQRlgA8EgAAPhIAAEESAQBEEgQAShIKAFYSAQBeEgEAYRITAHYSHQCaEgEAoBIRALMSAgC4EgMAvRIHAMcSAwDMEgUA1hIBANsSAADdEgEA4BIWAPgSAgD9EgQABBMfACYTCwA0EwQAOxMAAEETJQBoEwQAcBMFAHgTGACSEwEAlhMQAKkTFwDDEwoA0RMFANgTEwDtEwMA8hMXAA0UHQA=","H":"PgNH/3DO"},"entry":{"N":"ACBg","E":"OjAAAAEAAAAAAAMBEAAAAAAAAQAHAAgACgBpAGwAbQBxAHIAewB/AIAAgwCEAKEAogCDAYQBjgHCAcMBxAHFAccByAHJAdAB0QHSAdUB2AHdAd8B4gHjAeoBFAQqBC4EMwQ/BEoESwQlBSYFKQUqBS4FLwUwBTEFMgUzBTQFNQU2BTcFPAVCBUcFSQVLBU4FTwVQBeIF5QXnBfEF+wX/BQAGAQYKBgsGDAYNBhcGGAYdBiIGIwYkBiUGJwYoBisGLAYvBjAGMQYyBjMGOAY8Bj0GJQcrBy0HLwcwB24Hfgd/B4QHiQefB68HsAexB7IHswe5B7wHxwfIB8kHygfOB9QH1gfXB0IIVghXCF8ISwlRCVQJVQlYCVwJZglnCWkJaglxCXsJfAmDCYQJngm0CRoMHQweDB8MIAwlDCkMLQw0DDsMPQw+DEUMRwxIDFMMXAyEDNIM1wzZDNoM3AzgDOIM5wzoDOsM7gzvDPEM8gzzDPQM9wz7DAENBA0FDQcNCA1wDnEOdQ52DoMPhg+QD54Pog/pD+0P7g8FEAYQEhAVECYQKRAwEDIQNRA2EDsQPBA/EHIQmRCiEKYQsRC1ELYQuhDCEMQQAxEEEQYRBxEQERURHhGKEZARlBGVEZgRmxGjEUASSRJVEmASnBLLEtIS0xLUEtoS9xL8EiQTJRMyEzMTPBM/E2cTbxOnE6gTzhPXEwsUDBQ=","H":"I+idi+fo"},"desc":{"N":"FKb","E":"OzAAAAEAAHgNfgEAAAEABwABAAoATgBnAAAAaQAEAHAAAwB7AAEAfgACAIMAFQChAOAAgwEBAI4BAgCwAQQAuAEBALsBAADAAQkA0AECANUBAADYAQAA2wECAN8BAADiAQEA5gEBAOoBAQDwAQQADAIAABYCAAAYAgEAGwIAAB0CAAAjAgMALQIAAC8CAwA2AgAAPQICAEUCAABLAgAATQIAAFACAABTAgAAVwIAAFwCAABpAgAAcgIKAI0CBACWAgAAqgIAAK8CAAC0AgAAugIBAMMCAADIAgAA0QIAANcCAADZAgAA4AIAAOUCAADqAgAA8gICAPYCBwAHAwAAGAMUAAsEBAAUBAAAFgQAABgEAAAaBAAAHAQMACoEAAAuBAAAMAQAADMEAAA8BAAAPwQAAEUEAQBIBN4AKQUBAC0FCgA8BQAAQgUAAEcFAABJBQAASwUGAFMFAgBXBQMAYgV7AOIFAwDnBQAA8AUBAPMFAgD7BQAA/QUFAAcGAAAKBgMAEgYDABcGAQAdBgAAIAYFACcGAQArBgEALwYEADgGAQA7BgIARAbdACUHAQAoBwEAKwcAAC0HAAAvBwEAMwcAADcHAAA6BwgARAcBAEgHCwBXBwAAXgcBAGEHAQBnBwIAawcDAH4HAgCCBwAAhAcBAIcHCwCYBwEAnwcAAKMHAgCnBwIArwcEALkHAAC8BwIAwQcAAMMHBwDOBwAA1AcAANYHAQDeBwAA4QcZAAEIMAAzCAEAQggAAEcIAgBLCAIAUQgAAFMIAABWCAEAXwgAAGEIAABlCN0ASwkEAFEJAABUCQEAWAkAAFwJAABiCQEAZgkBAGkJAQBxCQAAewkBAIAJBACPCQAAmAkEAJ4JAACiCQIApgkCALEJAQC0CQEAwQmpAG0KAABvCkgAuwpZARkMAQAdDAMAJQwAACcMAAApDAAALQwAAC8MAQA0DAAANgwBADsMAAA9DAEARQwAAEcMAQBKDAkAVQwCAFkMAwBgDAEAcgwDAHkMAQB8DAIAggwCAIgMAACKDAcAkww7ANIMAADXDAAA2QwBANwMAADgDAAA4gwAAOcMAQDrDAAA7gwBAPEMBgD7DAAAAQ0AAAQNBAAVDVkBcA4BAHUO4gBpDwAAbw8CAHMPAwB9DwEAgA8DAIYPAACLDwEAkA8AAJMPAQCXDwMAnA8CAKAPAgCkDwMAtw8PAMgPAQDLDwAAzQ8BANEPEwDpDwAA7Q8BAAIQAQAFEAEAEhAAABUQAAAYEAAAIRACACYQAAApEAAAKxADADAQAAAyEAAANRABADsQAQA/EAUARxABAEwQAgBQEAAAUhAAAFkQAQBgEAEAZBAEAHEQAgB2EAEAexABAIcQAwCZEAAAoBACAKYQAACqEAMAsRAAALMQAwC4EAIAvxABAMIQAADEEAAAyBAAAMoQAgDSEAIA1hACANoQBgDnEAAA8xABAPcQCQADEQEABhEBABARAAAVEQAAGBEBAB4RAAAhEQMAKBEAADERAAAzEQAANREAADoRAAA8EQMAQREAAEMRAABFEQAASBEAAEoRAABMEQAAUREAAFQRAABWEQAAWBEAAFwRAABeEQIAZBEAAGYRAABzEQEAexEAAH4RAgCCEQAAihECAI4RAgCUEQEAmBEAAJsRAACjEXwAJhIEACwSAAAyEgEANRIBADgSAAA6EgAAPBIAAD4SAABAEgAASRIAAE8SBgBgEgAAYxIBAGYSAgBrEgEAbxIFAHkSAQCBEgAAhhIAAJwSAACgEgMAqxIDALISAQDIEgAAyxICANISAgDWEgEA2hIAAOASBADuEgEA9xIBAPsSBQAIEwYAEhMAABQTAAAbEwIAHxMCACQTAQAnEwAAKhMDADITAQA8EwAAPxMAAEUTBgBbEwAAXhMBAGUTAgBpEwAAbBMAAG8TAACDEwEAkhMBAJUTAQCZEwAAmxMAAKETAwCnEwEArxMEALcTBQDBEwEAyxMAAM4TAADXEwAA3BMDAOgTAAD2EwUA/RMAAAMUAAAFFAEACxQBABUUAAAZFAAA","H":"1ZNicnVY"},"function":{"N":"A@Kl","E":"OzAAAAEAAG4DVwAAAAoAaQAbAKEAAQCDAQEAjgEAAMIBIwDqAQEAFAQAABYEAAAqBAAALgQAADMEAAA/BAAASgQBACUFLADiBQAA5QUAAOcFAADxBQAA+wUAAP8FAwAHBgAACgYDABEGLgAlBwAAKAcAACsHAgAvBwIANQcAAG4HAAB+BwYAhwcAAIkHAACfBwAAqgcxAEIIAQBWCAEAXwgAAEoJMwCDCQEAngkAALQJAAAaDC4AUwwAAFwMAACEDAAA0gwAANcMAwDcDDUAcA4DAHUOAQBiDwAAdg8AAH8PAACBDxcAmw8HAKcPAADpDwAA7Q8BAAIQIAAkEBsAchABAJEQLADCEAIAyBAAAP0QLwBPEQAAgBEjADsSJgB1EgAAkBIVALISAAC0EhMAyRIWAPcSAAD7EgsAJBMCAC4TEgBnEwAAahMAAG0TCgCIEw0ApxMFAL8TAwDMEwsA7BMFAAoUBAA=","H":"ChinwWjj"},"type":{"N":"AJe","E":"OzAAAAEAAIUSlAACAAQACQAAAAsAXQBqAAEAcAAAAHYABQB/AAAAgQABAIQAHACjAN8AhAEJAI8BMgDGAQEAyQEIANYBAQDaAQIA3gEAAOMBBgDrAV4CTATYACkFAAAtBQIANAUBADwFAAA/BQIAQwUDAEgFAABKBQAAUQWpAPwFDwAOBgIAEgYFABoGAgAeBgMAKQYBADUGBgBABmkBrAcCALEHBAC4BwAAvQcBAMEHAADDBwMAzwcDANQHBADbB3oAVwjyAEwJAABOCQEAUQkCAFkJAABcCQAAXgkFAGgJAABsCQAAbwkBAHQJAQB9CZwCGwwAAB0MAgAhDAEAJQwAACgMAAAxDAAANQwDADsMAAA9DAAAQgwAAEUMAABIDDsAhQxRANkMAgDdDAEA4AwAAOcMAQDrDAAA9AwCAAcNAAASDWwCgA8AAIsPAQCQDwQAlw8DAJwPAgCjD2EACxABAA4QAgAZEAEAHhAHACoQBAAxEAAAQBBSAJUQBACdEAAAoBABAKMQAgCnEAcAsxABALgQAQC+EEMABhEAAAgRBQAQEQIAFhEFAB8RBQApEQEALRFTAIIRAACGEQAAixEBAI4RAgCcEQEAnxGbADwSAAA+EgAAQRIBAEQSBABKEgoAVhIBAF4SAQBhEjIAmhICAKASFQC4EgMAvRIHAMcSAwDMEgUA0xIAANYSAQDbEgAA3RIBAOASGgD9EgQABBMtADQTBAA7EwAAQRMrAHATBQB4ExgAkhMBAJYTEACpExcAwxMKANETBQDYExMA7RMDAPITFwANFB0A","H":"zLWo5og7"},"alias":{"N":"`","E":"OzAAAAEAACoUAQAAACoU","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"dvMhO+W1"}}') \ No newline at end of file diff --git a/pr/255/docs/search.index/type/23b66083c01c.js b/pr/255/docs/search.index/type/23b66083c01c.js deleted file mode 100644 index 38339f9a5..000000000 --- a/pr/255/docs/search.index/type/23b66083c01c.js +++ /dev/null @@ -1 +0,0 @@ -rd_("CAo[\"\",\"ADswAAABAAAFAAIA7AMEAHwTAAACIgcAAEAHAAA6MAAAAQAAAAAACgAQAAAAsgGzAccFdwyrEesR/xFcE2cThROUEzowAAABAAAAAAAYABAAAADhAeIB4wHkAeUB+gPGBcsF8gYeB0wHcwlZEK4R7BFxEvoSGRMaE4ETghODE4QTlxObEzswAAABAAAIAREA+AMAAMUFAAAjBwAAPwcAAE8HAAAyDAUAiw12AOEPAABaEAcAuhAAACgRdgCvEQAAsREAAC4SAAByEgAAkxIAAF8TAAA6MAAAAQAAAAAAHAAQAAAAyAXOBc8F0AUcBx0HJAclByYHJwcoBykHvgu/C8ALwQsODPwOAQ8KEHEQqhGlEuES4hJXE1sTaBOGEzswAAABAAA6ABQAAQMUABUEAAAhBAIAsAUBALMFAADJBQEA4gUAABAHCwAWCAMAvQsAACIMAABUDwAAhw8AAAsQAACAEAEAsxAAAC8SAADZEgAAWBMAAIcTAAA7MAAAAQAAVQAMAMAAPABkAQEAFAQAAMQHAADGBwAABQgAAAcIAADUDwMA4BEFAMkSAAA2EwUASRMAADswAAABAAAVAAcA/AMAAHgMAAACDgAAUA8DAKwRAACYEgcAdRMFADswAAABAAARAAgAGgQBAC0HBwAECAAABggAAPYOAgAADwAAbBAAAA0SAAADZwcAAGgHAAD8EQAAAxEEAAASBAAAJwwAAAXCBwAAwwcAAMUHAAAjDAAAaxAAAAA7MAAAAQAABQACAJkBAAAUEwQAAAABFAYAAA==\"]Bo[\"AAAAAAAAAAACRBMAAEUTAAAAAAAAAkoQAABLEAAA\",\"\"]0Bg[\"\",\"AAAFVgkAAFcJAABYCQAAWQkAAFoJAAA=\"]AIg[\"AAAAAAKKAQAAmgEAAAAABLAFAACxBQAAsRAAALIQAAAExAcAAMYHAAAFCAAABwgAADswAAABAAANAAUA4AUBAHsJAQAtDAQAeAwAAOcQAwA6MAAAAQAAAAAADAAQAAAAkgEaBBsEBAgGCAAPFBAVENkQ2hDbENwQDRIECwQAAGcHAABoBwAAbQ8AAAQRBAAAEgQAACATAAAhEwAABRAEAADDBwAAxQcAAPkOAAD7DgAAAyQMAAAlDAAA+g4AADowAAABAAAAAAAIABAAAACZAfID9AMLBxQTFRMWExcTGBMBdhIAAAEmDAAA\",\"AAAAAQMRAAAAArUFAAC2BQAAAAIHDAAACAwAAAAFLQwAAC4MAAAvDAAAMAwAADEMAAAAAAAAAALyAwAA9AMAAA==\"]ANk[\"AAAEHgIAAIACAAD7BgAA/wYAAAMJDAAACgwAAAsMAAACigEAAJoBAAA7MAAAAQAAdgABACgRdgAABrAFAACxBQAAsRAAALIQAACnEwAAqBMAAATEBwAAxgcAAAUIAAAHCAAAOzAAAAEAABIABwDgBQEAQQcAAHsJAQAtDAQAeAwAAOcQAwC2EQMAOjAAAAEAAAAAAAkAEAAAAJIBGgQbBAQIBggAD9kQ2hDbENwQBQsEAADMBQAAZwcAAGgHAABtEAAABBEEAAASBAAAIBMAACETAAAEwwcAAMUHAAD5DgAA+w4AAAQfBwAAJAwAACUMAAD6DgAAOzAAAAEAAAYAAwDyAwAA9AMAABQTBAABdhIAAAABFAYAAA==\",\"AAAAAAACtQUAALYFAAAAAgcMAAAIDAAAAW4PAAAFLQwAAC4MAAAvDAAAMAwAADEMAAAAAAAAAALyAwAA9AMAAAAAAzgHAADBEAAAwhAAAA==\"]Dc[\"\",\"AAAAADswAAABAAAHAAEAXwkHADswAAABAAAJAAIAZhAEALwQBAAAAbsQAAA=\"]AHi[\"AAAAOjAAAAEAAAAAAAcAEAAAAIcBiQGWAZgBowGkAYMPhA8EjQEAAJ8BAABXCgAAWgoAADowAAABAAAAAAAJABAAAACIAY4BjwGXAaABoQG+CsEKJBMlEzswAAABAAAMAAMAKQUHACoPAAAQEAMABncQAAB5EAAAexAAAH0QAAB/EAAALxIAADswAAABAAAVAAoAfQEBAIQBAAArDAEAcQwBAHsPAwD+DwEABRIDAMkSAABEEwEAjhMBAAFGEwAAAZIBAAAFdhAAAHgQAAB6EAAAfBAAAH4QAAAAAAAAAAABFAYAAA==\",\"AAABggEAAAIxBQAAnxEAAAAAAALwDgAA9g8AAAAAAAAAAAAAAAAE/QYAAAEHAAB1DAAAdgwAAA==\",1]Fk[\"AAAABGMFAABqBwAADQgAAMUQAAACYAkAAPwLAAABWxAAAAABFwgAAAHvAAAAAlEPAACZEgAAAS4HAAA=\",\"AAAAAWMFAAABjQEAAA==\"]Fk[\"AAAABKQFAABuBwAAEQgAAMwQAAACZAkAAAAMAAABXxAAAAFmAQAAARkIAAAAAlMPAACdEgAAATIHAAA=\",\"AAAAAaQFAAABnwEAAA==\"]AEa[\"AAAAAoUBAACRAQAAOzAAAAEAAAcAAQBfCQcAAATOBQAAzwUAANAFAACqEQAAAAABRhMAAAAAAAJKEAAASxAAAA==\",\"AAAAADswAAABAAAQAAMA8gYAAF8JBwD7CwcAOzAAAAEAAAsABABPBwAATBAAAGYQBAC8EAQAOzAAAAEAAA8ABQApBQcAGAwCALMRAgDnEQAAWxMAADowAAABAAAAAAAMABAAAAB3EHkQexB9EH8QsRCyELsQ3xDgEOEQ4hDZEgTUDwAA1Q8AANYPAADXDwAAAAAFdhAAAHgQAAB6EAAAfBAAAH4QAAAAAAAAAAABFAYAAA==\",1]Ec[\"AAAAAAAAOzAAAAEAAAUAAgAIBwIADAcCADswAAABAAAGAAIAAwcEAEgJAQADDQQAAMEFAADCBQAA\",\"\"]Dg[\"AAAAAAAAAAABOhMAAAF5EwAAAAAAAAAAAAABrAcAAA==\",\"AAAAAAAB8REAAAHHEgAA\"]Eo[\"AAAAAWEFAAABjAEAAAIlAAAAhgAAAAFcDwAAAQYDAAAC6gAAAOsAAAA=\",\"AAABlQAAAAFhBQAAAYcSAAAAAfMLAAA=\"]Ic[\"AAAAAZwFAAADngEAAKESAAAbEwAAAkwAAACTAAAABlMBAABUAQAA8wMAABMGAABpDwAAaBMAAAETAwAA\",\"AAABlgAAAAKcBQAAihIAAAAB9wsAAAAAAAAAAAAAAAAAAAKXAAAAmAAAAA==\"]Ik[\"AAAAAjkFAAAEEgAAAUwHAAAB7wYAAAGfAAAAAbMQAAABNhMAAAKsEQAAdRMAAAAAAAAAAAAAOjAAAAEAAAAAAAgAEAAAANUF7QamByYINw9ND38PThDrEA==\",\"AAAAATkFAAAAAe0RAAABwxIAAA==\"]Ck[\"AAAAAbIBAAAAAAAAATgTAAABdxMAAA==\",\"AAAAAAAB7xEAAAHFEgAA\"]Ck[\"AAAAAbMBAAAAAAAAATkTAAABeBMAAA==\",\"AAAAAAAB8BEAAAHGEgAA\"]Jk[\"AAAAAAAABMgFAADOBQAAzwUAANAFAAAAOzAAAAEAAAgAAQC0CwgAOzAAAAEAAAwAAQD8AwwABPYOAAD3DgAA+A4AAGwQAAAAAScMAAADIwwAAPkOAAD7DgAAAiQMAAD6DgAA\",\"AAAAAAABTBAAAAMYDAAAGQwAABoMAAA=\"]Mg[\"AAAAAAAAAgsSAAAMEgAAAAJzEgAAdBIAAAVBBwAAthEAALcRAAC4EQAAuREAAAACzAUAAG0QAAACEQQAABIEAAAAAR8HAAAAAAABFAYAAA==\",\"AAAAAALEBQAAShMAAAAFfxMAAKITAACjEwAApBMAAKUTAAAB2RIAAAJuDwAAgBMAAAAAAAAAAAAAAATYDwAA2Q8AANoPAADbDwAA\"]Bg[\"AAAAAAAAAAQAEQAAAREAAPsSAAD8EgAA\",\"\"]Bk[\"\",\"AAAAAf8QAAAAAAAAAAAAAAAAAAAAAAEEDwAA\"]Cc[\"AAAAAAAAAQoQAAABCxAAAA==\",\"AAAAAAACdQkAAHYJAAA=\"]FHk[\"AAAAADswAAABAAAUAAoA4QEEAPoDAADYBQAAKAgAAAUMAADcDwMA7BEAAPoSAAAZEwEAgRMDADswAAABAADcAREACQQAAA8EAAAjBwAA9QsDALUMTAFwDwAAdQ8AAOEPAAD9DwAAWhAHALoQAAAoEXYArxEAALERAAByEgAA1BIAAF8TAAA7MAAAAQAArgAPAJ8AIAD9AGYAZgENAPMDAADIBQAAEwYAAAgHAgAMBwIAHAcBAPELAwD0DgAApRIAAMMSBQBoEwAAexMAADswAAABAACdAEAAAQMUAAwEAAAWBAEAIQQCALMFAADJBQEA4gUAAAMHBAAQBwsAFAgFAAIJAQBICQEAXQkBAGgJAQAHDAEAFgwBACIMAACzDAEA8Q4BAAIPAQA4DwEAOw8BAFQPAAB2DwEAgA8BAIcPAADiDwAA8A8BAAgQAQALEAAAchABALsQAADGEAAAyBAAAMoQAADNEAAAzxAAANEQAADdEAUA7BABAO8QAgAAEQEAoBEBAP0RAQAvEgAAYxIBAGgSAQCNEgEAyhIBANoSAQDeEgEA+xIBAAMTAQAsEwEAPBMBAFgTAgBjEwMAcRMDAIcTAACVEwEAmRMBAJwTAQCgEwEApxMBADswAAABAACMACUAwAA8AGQBAQB9AQEA8QMAAA0EAAAUBAAAwQUBANoFAQDEBwAAxgcAAAUIAAAHCAAAtAsIACsMAQBxDAEA/g4BADIPAQBuDwAAew8DAP4PAQBUEAEAbhABAK0RAAD1EQEABRIDAHMSAQCUEgEAvxIBANISAQDVEgMANhMFAEQTAQBJEwAAfRMBAIATAACOEwMAnhMBADswAAABAAAwAA0A/AMMAOAFAQBBBwAAewkBAB8MAAB4DAAAAg4AAFAPAwDnEAMAthEDAJgSBwDPEgEAdRMFADowAAABAAAAAAAVABAAAAAaBBsELQcuBy8HMAcxBzIHMwc0BwQIBgj2DvcO+A4ADxQQFRBsEA0SYBOIEwcLBAAAzAUAAG0PAABtEAAA5RAAAOYQAAD8EQAAAxEEAAASBAAAJwwAADowAAABAAAAAAAJABAAAAAQBMIHwwfFByMM+Q77DkoQSxBrEAQfBwAAJAwAACUMAAD6DgAAOjAAAAEAAAAAAAcAEAAAAPID9AMLBxQTFRMWExcTGBMAASYMAAABFAYAAA==\",\"AAAAAAA7MAAAAQAA1QABALUM1QAAOjAAAAEAAAAAAFkAEAAAABYEFwQUCBUIAgkDCV0JXgloCWkJBwwIDBYMFwyzDLQM8Q7yDgIPAw84DzkPOw88D3YPdw+AD4EP8A/xDwgQCRByEHMQxhDIEMoQzRDPENEQ3RDeEOwQ7RAAEQERoBGhEf0R/hFjEmQSaBJpEo0SjhLKEssS2hLbEt4S3xL7EvwSAxMEEywTLRM8Ez0TWRNaE2MTZBNlE2YTcRNyE3MTdBOVE5YTmROaE5wTnROgE6ETpxOoEzswAAABAAAvABQAfQEBANoFAQArDAEAcQwBADIPAQB7DwMA/g8BAFQQAQBuEAEA9REBAAUSAwBzEgEAlBIBAL8SAQDSEgEA1RIDAEQTAQB9EwEAjhMDAJ4TAQAEewkAAHwJAADPEgAA0BIAAAAC5RAAAOYQAAAAAkoQAABLEAAAAALyAwAA9AMAAA==\"]Ho[\"AAAAAcMQAAAAA8UFAABNCQAAqREAADswAAABAAAMAAMAJAQFACQHBQATEwAAAAPBBwAAbhAAAG8QAAABzw8AAAAHdhAAAHgQAAB6EAAAfBAAAH4QAADlEAAA5hAAAAABwgcAAA==\",\"\"]Lk[\"AAACHwIAAH0CAAAAAo0BAACfAQAAOzAAAAEAAAsAAwCOAQEAoAEBAFoQBwA7MAAAAQAABwABACkFBwA6MAAAAQAAAAAABwAQAAAAFAgVCDgPOQ+AD4EP3RDeEAACzxIAANASAAA=\",\"AAAAATAPAAAAAAAAAAAAAAAAAAAAAAUvDwAAMQ8AADcPAAA6DwAA0RIAAA==\"]AAg[\"AAAEHQIAAH8CAABOCQAATwkAAASDAQAAiwEAAJABAACdAQAAAiQCAACFAgAAAAA6MAAAAQAAAAAAEwAQAAAAFgQXBAIJAwnkD+YP6A/qD+sPdxB5EHsQfRB/EP0R/hGZE5oTnBOdEwJzEgAAdBIAAAUtDAAALgwAAC8MAAAwDAAAMQwAAAAFdhAAAHgQAAB6EAAAfBAAAH4QAAAAAAACmQEAAAsHAAA=\",\"AAAAAAAAAAAAAAAAAAAAAAAABAQJAAAFCQAABgkAAAcJAAA=\"]BKo[\"AAADTAkAAGUSAABmEgAABYEBAAA7CgAA/xAAAGoSAABrEgAAOjAAAAEAAAAAAAcAEAAAAIwBngFQCVEJJQpxCpcKrhEBrxEAAAGlEgAAOjAAAAEAAAAAABEAEAAAABYIFwgYCBkI8A52D3cP9g/GEMgQyhDNEM8Q0RDKEssSYxNkEwHJEgAAOzAAAAEAAAsAAgBQDwMAmBIHADswAAABAAAJAAMALQcHAAQIAAAGCAAAAAACwwcAAMUHAAA=\",\"AAAEuwUAALwFAADnDgAA6A4AADswAAABAAAWAAoAaQcHAMQQAQDHEAAAyRAAAMsQAQDOEAAA0BAAAKIRAQD2EgIAQhMBAAKhEgAAGxMAAAGpEQAAAAAAAAAAAAAAAAAAOjAAAAEAAAAAAG0AEAAAAHcBeAF6AXsB1wHYAd4B3wH5A/sDHAQzBTYF/AYABysHLAdfB2AHPgk/CW8JcAkEDAYMGwwcDCAMIQwoDCkM7g7vDgUPKw8sD0sPTA9/D9EP0g/uD+8P+w/8DwAQARAGEAcQDBANEEQQRRBOEFAQURBXEFgQYhBjEGQQZRDjEOQQ9xD4EKURphGnEagR6RHqEfcR+BEBEgMSJBIlEiYSJxIpEioSKxIsEmcSbBJtEm4ShRKWEpcSoBKmEqcSqBKpEqoSqxLBEsIS3BLdEuMS5BIBEwITHhMfE10TXhM=\"]Ac[\"AAAAAAHwAgAA\",\"\"]Ca[\"AAAAAAIkAgAAhQIAADswAAABAAAFAAEA+RAFAA==\",\"\",1]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAAAiAHAAA2BwAA\",\"AAAAAAAC4w8AAOUPAAAAAuQPAADmDwAAAAK2EQAAtxEAAA==\"]Eo[\"AAAAAAAAAAAAAAAAAAAAAAAAAiEHAAA3BwAA\",\"AAAAAAAC5w8AAOkPAAAAA+gPAADqDwAA6w8AAAACuBEAALkRAAA=\"]Ck[\"AAAAAAAAAAAAAAAAAAAAAAAABWQAAAB7AQAAAAgAACAIAAAGCQAA\",\"\"]Bg[\"AAAAAAAAAfwOAAAAAAAAAuUQAADmEAAA\",\"\"]Ek[\"AAAAAVUAAAAABfgDAACyBQAAXQcAAPUQAAAdEwAAAq4AAAABDwAAAALgEgAANRMAAA==\",\"AAAAAAAB9gMAAA==\"]Hk[\"\",\"AAAAAAAAAAA7MAAAAQAACAABALQLCAA7MAAAAQAADAABAPwDDAAE9g4AAPcOAAD4DgAAbBAAAAABJwwAAAQjDAAA+Q4AAPsOAABrEAAAAyQMAAAlDAAA+g4AAAAAASYMAAA=\"]Co[\"AAAAAAAAAAAAAAAAAAJKEAAASxAAAA==\",\"AAAAAAAAAAAAAAABIwgAAA==\"]Hk[\"AAADpQEAAA8MAAASDAAAAWAFAAABjAEAAAQkAAAAhQAAAOMPAADlDwAAAVsPAAABBQMAAAPpAAAAthAAALcQAAA=\",\"AAACpQEAAAwMAAACGAQAAGAFAAABhhIAAAAB8gsAAA==\"]Hk[\"AAADpgEAABAMAAATDAAAAZsFAAABngEAAARLAAAAkgAAAOcPAADpDwAAAlIBAABoDwAAARIDAAADDQQAALgQAAC5EAAA\",\"AAACpgEAAA0MAAADGQQAAJsFAACJEgAAAAH2CwAA\"]2ALk[\"AAAAAAHTDwAAAAA6MAAAAQAAAAAAEAAQAAAADAQWDBcMswy0DPEO8g5yEHMQoBGhEXETchOVE5YToBOhEwIUBAAAyRIAADswAAABAAALAAIAUA8DAJgSBwA7MAAAAQAACAACAJIBAAAtBwcAAAAAAAKZAQAACwcAAA==\",\"AAAHvQUAAL4FAAAPDAAAEAwAABIMAAATDAAAsBEAADowAAABAAAAAAAXABAAAAAKCAsIWwlnCREMFAwVDOoO6w7yD/MP9A9DEMMQ1BDVENYQ1xDYEMwSMxM0E0cTSBM7MAAAAQAA2AACAAoO1ACPEgMAOzAAAAEAAEoAAgALAEkA+RIAAAF7EwAAAAAE5xAAAOgQAADpEAAA6hAAAATZEAAA2hAAANsQAADcEAAAAfwRAAAAAAAAAAAHIAQAANUFAAAqBwAABw4AAEYQAABWEAAA6xAAAA==\"]Cc[\"AAAAAAIkCgAAcAoAAAAAADswAAABAAAFAAEA4BEFAA==\",\"\"]BNc[\"\",\"ADswAAABAAAFAAIA7AMEAHwTAAACIgcAAEAHAAA6MAAAAQAAAAAACgAQAAAAsgGzAccFdwyrEesR/xFcE2cThROUEzowAAABAAAAAAAYABAAAADhAeIB4wHkAeUB+gPGBcsF8gYeB0wHcwlZEK4R7BFxEvoSGRMaE4ETghODE4QTlxObEzswAAABAAACARAA+AMAAMUFAAAjBwAAPwcAAE8HAACLDXYA4Q8AAFoQBwC6EAAAKBF2AK8RAACxEQAALhIAAHISAACTEgAAXxMAADowAAABAAAAAAAaABAAAADIBc4FzwXQBRwHHQckByUHJgcnBygHKQe+C78LwAvBC/wOAQ8KEHEQqhGlEuES4hJXE2gThhM7MAAAAQAANgARAAEDFAAVBAAAIQQCALAFAQCzBQAAyQUBAOIFAAAQBwsAFggDAL0LAAAiDAAAVA8AAIcPAAALEAAALxIAAFgTAACHEwAAOzAAAAEAAFAACgDAADwAZAEBABQEAADEBwAAxgcAAAUIAAAHCAAA4BEFADYTBQBJEwAAOzAAAAEAABQABgD8AwAAeAwAAAIOAABQDwMAmBIHAHUTBQA7MAAAAQAAEQAIABoEAQAtBwcABAgAAAYIAAD2DgIAAA8AAGwQAAANEgAAAmcHAABoBwAAAxEEAAASBAAAJwwAAATDBwAAxQcAACMMAABrEAAAAAUUEwAAFRMAABYTAAAXEwAAGBMAAA==\"]Bc[\"AAAAAAAAAAAAAAAC5RAAAOYQAAA=\",\"\"]Kc[\"AAAAAAFwEgAAADswAAABAAAGAAIAJAcFAHEQAAACswUAAIcPAAABFAQAAAADFBAAABUQAAANEgAAAW0PAAA=\",\"AAAAAAABDwQAADswAAABAAAFAAEAJAQFAAAAAAAAAAAAAAAAB+ABAAAyBQAANQUAADkHAAA6BwAAOwcAADwHAAA=\"]Do[\"AAAAAAABFQAAAAAAAcQAAAAAAAAAAAAAAAACMgUAACsHAAA=\",\"AAAAAAAAAAAC/g4AAP8OAAA=\"]Dk[\"AAAAAAABKwAAAAEDAQAAAAAAAAAAAAAAAAACNQUAACwHAAA=\",\"AAAAAAAAAAAB8QMAAA==\"]Ac[\"AAABLgIAAA==\",\"\"]Fg[\"AAAABGUFAABrBwAADggAAMcQAAADYQkAAP0LAACCEwAAAVwQAAAAAAHxAAAAAZoSAAABLwcAAA==\",\"AAAAAWUFAAAAAY4BAAA=\"]Fg[\"AAAABKYFAABvBwAAEggAAM4QAAADZQkAAAEMAACEEwAAAWAQAAABaAEAAAAAAZ4SAAABMwcAAA==\",\"AAAAAaYFAAAAAaABAAA=\"]Bk[\"\",\"AAAAAAAAAAA7MAAAAQAAPgACAMAAPABkAQEA\"]Ck[\"\",\"AAAAAAHyBgAAOzAAAAEAAAkAAgBPBwAAUQcIAAFbEwAAAdkSAAA=\"]Bo[\"\",\"AAAAAAAAAAAAAAAAAiATAAAhEwAAAAAAAXYSAAA=\"]Eo[\"\",\"AAAAAAA7MAAAAQAABQABAO0RBQA7MAAAAQAABQABAMMSBQAAOzAAAAEAAAUAAQA2EwUAOzAAAAEAAAUAAQB1EwUA\"]Ck[\"AAACLwIAAD8CAAA=\",\"AAAAAAAAAuYSAADnEgAAAAAC5xAAAOgQAAA=\"]Cg[\"\",\"AAAAAAOGEgAAhxIAAIgSAAAABPELAADyCwAA8wsAAPQLAAA=\"]Eo[\"AAAAAWoFAAAAASgAAAAAAAL7AAAA/AAAAA==\",\"AAA7MAAAAQAACgACAF8CCQBqAgAAAmoFAABpEwAAAAABCxIAAA==\"]Eo[\"AAAAAaMFAAAAAVMAAAAAAAJkAQAAZQEAAA==\",\"AAA7MAAAAQAACgACANsCAQDeAggAAqMFAABqEwAAAAABDBIAAA==\"]Dg[\"AAABvwIAAAGhBQAAAAFRAAAAAl0BAABeAQAA\",\"AAABzgIAAAGhBQAAAAAAAAENBAAA\"]Eo[\"AAAAAAAAAm0BAABuAQAA\",\"AAAAAAAAB1cTAAB/EwAAhhMAAKITAACjEwAApBMAAKUTAAACWBMAAIcTAAABgBMAAA==\"]Bk[\"AAAAAAAAASYBAAA=\",\"AAABnAIAAAAAAQkEAAA=\"]Bo[\"AAAAAaoFAAAAAAFvAQAA\",\"AAAAAaoFAAAB/xIAAA==\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAXMMAAA=\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAwEIAAAhCAAABwkAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAiAEAAACCAAA\",\"\"]Cc[\"AAAAAAAAAAJICQAASQkAAAAAAAAAAAACmQEAAAsHAAA=\",\"\"]Fo[\"AAAAAAACxQUAALERAAAAAAAAAAAAAAAAAAAEJwgAAAUPAAAOEAAAAhEAAA==\",\"AAHIBwAAAAAAAAAAAAAAAAAAAAAAAAIPEAAAtRAAAA==\"]Bk[\"AAAAAccFAAAAAAH8DgAAAVQPAAA=\",\"AAH5BwAA\"]Bg[\"AAAAAAAABBAQAAAREAAAEhAAABMQAAA=\",\"\"]Ag[\"AAAAAoUBAACRAQAA\",\"\"]Do[\"AAAAAAAAAAAAAnsJAAB8CQAAAZIBAAA=\",\"AAAAAAAAAAAABS0MAAAuDAAALwwAADAMAAAxDAAA\"]AGc[\"AAAAAAKKAQAAmgEAAAAABLAFAACxBQAAsRAAALIQAAAExAcAAMYHAAAFCAAABwgAADswAAABAAALAAQA4AUBAC0MBAB4DAAA5xADADowAAABAAAAAAALABAAAAAaBBsEBAgGCAAPFBAVENkQ2hDbENwQDRIECwQAAGcHAABoBwAAbQ8AAAQRBAAAEgQAACATAAAhEwAABRAEAADDBwAAxQcAAPkOAAD7DgAAAyQMAAAlDAAA+g4AADowAAABAAAAAAAIABAAAACZAfID9AMLBxQTFRMWExcTGBMBdhIAAAEmDAAA\",\"AAAAAQMRAAAAArUFAAC2BQAAAAIHDAAACAwAAAAAAAAAAAAC8gMAAPQDAAA=\"]Hm[\"\",\"AAAAAAA7MAAAAQAABQABADIMBQACDgwAAFsTAAAEgBAAAIEQAACzEAAA2RIAAAXUDwAA1Q8AANYPAADXDwAAyRIAAAGsEQAAAAH8EQAAAAHCBwAAAAGZAQAAAAABFAYAAA==\",1]ANc[\"AAACkwEAAJwBAAAGgwEAAIsBAACQAQAAnQEAAGoSAABrEgAABMYFAABzCQAAIwoAAG8KAAA7MAAAAQAABQABADIMBQAC4RIAAOISAAA6MAAAAQAAAAAACQAQAAAASAlJCfAP8Q+AEIEQYxJkElkTWhM6MAAAAQAAAAAACQAQAAAA8QPEB8YHBQgHCP4O/w5uD30TfhMAAgQIAAAGCAAA\",\"AAAAOjAAAAEAAAAAABAAEAAAAHkBogejB6QHpQcpCCoIOAxxD3IPBRB0EHUQ+RH6ES0SYhMDcQkAANMPAAAoEgAAOzAAAAEAAAcAAwAyDAUAABIAAAISAAAAAoAQAACBEAAAAALgBQAA4QUAAAACCwQAAG0PAAAAAxAEAAD5DgAA+w4AAAMkDAAAJQwAAPoOAAAAAAImDAAAfQwAADowAAABAAAAAAALABAAAAB8AR0EHgQ0BTcF6wbsBmEHpgcmCCcITQ8=\"]Bg[\"AAAAAAAAAAAAAQcEAAA=\",\"AAAAAREGAAA=\"]Bk[\"AAAAAAAAADswAAABAAAMAAIA4gUAABAHCwA=\",\"\"]Cc[\"AAABQwkAAAAB5QEAAAAAAAHxAwAA\",\"AAAAAAAAAAEMBAAA\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAloAAADjDgAA\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAQsHAAA=\",\"\"]Cm[\"AAAAAAAAA84FAADPBQAA0AUAAA==\",\"AAAAAAAAAAAAAAABIwgAAA==\",1]Bg[\"AAAAAAAAADswAAABAAAUAAEAAQMUAA==\",\"\"]Ck[\"\",\"AAAAAARqCQAAawkAAGwJAABtCQAAAAAAAAAAAAAAAAAAAagPAAA=\"]Bg[\"AAAAAAAAAAAAAQIEAAA=\",\"AAAAARoIAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAVkAAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAZcAAAA=\",\"\"]BMa[\"AAAAAAABLhIAAAABLxIAADowAAABAAAAAAAaABAAAACEAdoF2wUyDzMPVBBVEPUR9hGUEpUSvxLAEtIS0xLVEtYS1xLYEuASNRN9E34TkBORE54TnxM7MAAAAQAABgADAHsJAQBQDwMARhMAAAOSAQAAYBMAAIgTAAAAAAABHwcAAAAAAAEUBgAA\",\"AAAFVgkAAFcJAABYCQAAWQkAAFoJAAAECQwAAAoMAAALDAAAnxEAADswAAABAAARAAgAGwgAAAEJAABqCQMAcQkAAMoPBAAoEgAAMRIAAI8SAwA7MAAAAQAAIgAOAK4BAACwAQAA9gMAAAkEAAAPBAAAUQcIADIMBQDzDgAA/Q8AAGYQBAC8EAQAbxIAANQSAAAcEwAAOzAAAAEAACMACQDzAwAAJAQFABMGAAAkCAAA9A4AAFcPEwDnEQEA5hIBAOkSAQA7MAAAAQAACgAFAOIPAACAEAEA3xADAO8QAgAAEwAAOzAAAAEAAAwABgDxAwAA/g4BANQPAwC2EAMA4BIAADUTAAAEthEAALcRAAC4EQAAuREAAAJgEwAAiBMAAAQLBAAAIwgAAG0PAABtEAAAAAABHwcAAAGZAQAAAAA6MAAAAQAAAAAAHQAQAAAAmQCaAJsAnAACBw8HWgdbB1wHPAluCXcJeAl5CXoJfQl+CT0PVQ9WD3gPeQ96DwIQAxAEEO4QpBEFE6YT\",1]Co[\"AAAAAAAAAAAAAAAAAAJKEAAASxAAAA==\",\"AAAAAAAAAAAAAAABIwgAAA==\"]Jg[\"AAAAAUgFAAAABxYAAACCAAAArgEAAPYDAADzDgAA+hAAAP0QAAACWA8AAOcRAAACAgMAABEHAAACxQAAAMYAAAAAAQQIAAAAAAHDBwAA\",\"AAHNBwAAAAJVAAAASAUAAAIkAgAAGwgAAAL6EAAA/RAAAAABBAcAAA==\"]Og[\"AAAAAW4FAAAABi0AAACKAAAAsAEAAPwQAAD+EAAAbxIAAAcGAQAABwEAAPQOAABgDwAAbA8AAPUPAADoEQAABAoDAAAWBwAAIgwAAAATAAABrREAAAECDgAAAwYIAABgEwAAiBMAAAAAAcUHAAA=\",\"AAHiBwAAAAFuBQAAAoUCAADEBQAAAvwQAAD+EAAAAQkHAAAAAAEfDAAAAAH8EQAAAAAAAAAAOzAAAAEAAAUAAQBZAAUA\"]Bo[\"\",\"AAAAAAAAOzAAAAEAAJUAAwCfACAA/QBmAGYBDQA=\"]CDi[\"\",\"AAA7MAAAAQAA1QABAN4K1QA7MAAAAQAA3AALAPYJLAAmCjAAWAoBAFsKEwByCh0AkQoFAJgKJAC/CgAAwgobAOYRAABpEwEAOjAAAAEAAAAAABMAEAAAAMsFEgbyBlAJUQkjCiQKJQpXCloKbwpwCnEKkAqXCr0KwAqGEocSiBI6MAAAAQAAAAAAEgAQAAAA+AOyBU8HXQd1CXYJvgrBCvUQ7RHuEe8R8BHxEfIRkxIdEyQTJRM6MAAAAQAAAAAAKQAQAAAAHAcdByQIvgu/C8ALwQvxC/IL8wv0Cw4MAQ8qD2wP9Q8KEBAQERASEBMQcRALEgwSwxLEEsUSxhLHEsgS5hLnEukS6hJXE1sTfxOGE6IToxOkE6UTOjAAAAEAAAAAABwAEAAAAAwEIQQiBCMEyQXKBQMHBAcFBwYHBwciDIcP5A/mD+gP6g/rDwsQgBCBELsQ7xDwEPEQ2RIAE1gThxM7MAAAAQAAWAAPAMAAPABkAQEA8QMAAA0EAAAUBAAAwQUBAMEHAAD+DgEAbg8AAK0RAADgEQUA4BIAADUTBgBJEwAAgBMAADswAAABAAARAAgA4AUBAB8MAAB4DAAAAg4AAM8PAADnEAMAzxIBAHUTBQAGAA8AABQQAAAVEAAADRIAAGATAACIEwAAOjAAAAEAAAAAAAsAEAAAAAsEzAVnB2gHIwhtD3YQeBB6EHwQfhD8EQQRBAAAEgQAACATAAAhEwAABMIHAADDBwAAxQcAAGsQAAACJQwAAPoOAAA6MAAAAQAAAAAACAAQAAAAmQHyA/QDCwcUExUTFhMXExgTAXYSAAAAARQGAAA=\",1]Le[\"\",\"AAAAAqIBAADwBgAAA00HAADsDgAA7Q4AAAM/BwAAABIAAAISAAA6MAAAAQAAAAAABwAQAAAA/A6qEbMRtBG1EeES4hITEwIVBAAAvQsAAAGEAQAAAUYTAAAE9g4AAPcOAAD4DgAAbBAAAAABJwwAAAQQBAAAIwwAAPkOAAD7DgAAASQMAAAAAAEmDAAA\",1]Fo[\"\",\"AAAAOjAAAAEAAAAAAAcAEAAAALIBswGrEf8RXBNnE4UTlBMCTAcAANMPAAAE7wYAAE0JAAAtDwAAqREAAAGlEgAAAbMQAAAByRIAAA==\"]Cg[\"\",\"AAAAA4kSAACKEgAAixIAAAAE9QsAAPYLAAD3CwAA+AsAAA==\"]Bk[\"\",\"AAAAAAAAOzAAAAEAAAUAAgAIBwIADAcCAA==\"]Fc[\"AAAAAZsBAAAAAAAABNoFAADbBQAAMg8AADMPAAA=\",\"AAA7MAAAAQAANwABADkMNwAAAAAAAAAAAAAAAAAAAAABPQcAAA==\"]Ao[\"\",\"AAA7MAAAAQAA1QABACsI1QA=\"]AAc[\"AAAENQIAAEYCAABKAgAA5w4AAAFGBQAAA3ESAACXEwAAmxMAAAMTAAAAgQAAAPkQAAABVw8AADowAAABAAAAAAAMABAAAAABAyEEIgSwBbEFyQUQB+wQ2hIDEywTZRNzEwLAAAAAwQAAAA==\",\"AAHMBwAAOzAAAAEAAAYAAwAdAgQATgkAAGUSAAABRgUAAARQCQAAIwoAACQKAAAlCgAAAfkQAAAB8QsAAAMDBwAA7xAAAPAQAAAAAAABIwgAAAAAAAAAAAHgDgAA\"]AAo[\"AAAEogIAAMECAADIAgAA6A4AAAFrBQAAAAQpAAAAiAAAAPsQAAByEgAABP8AAAAAAQAAXg8AAGgTAAA6MAAAAQAAAAAACgAQAAAACAMjBLMFygUVB+0Q2xIEEy0TZhN0EwABAg4AAA==\",\"AAHhBwAAB3sCAAB8AgAAfQIAAH8CAACAAgAATwkAAGYSAAABawUAAARRCQAAbwoAAHAKAABxCgAAAvULAAD7EAAAAggHAAAkCAAAAfEQAAAAAAAAAAAAAAAAA+IOAADjDgAA5A4AAA==\"]Cg[\"AAAAAAAAAAAAAAAAAREEAAAAAAHyAwAA\",\"AAAAAAAAAAGxEAAA\"]Cg[\"AAAAAAAAAAAAAAAAARIEAAAAAAH0AwAA\",\"AAAAAAAAAAGyEAAA\"]Fo[\"AAA7MAAAAQAACwAEAMUPBACMEgAALhMEAJgTAAA=\",\"ADswAAABAAAJAAIApwcEAF4SBAA7MAAAAQAACwAEAMUPBACMEgAALhMEAJgTAAA=\"]Hk[\"AAAAAAAAAAA7MAAAAQAACAABALQLCAA7MAAAAQAADAABAPwDDAAE9g4AAPcOAAD4DgAAbBAAAAABJwwAAAQjDAAA+Q4AAPsOAABrEAAAAyQMAAAlDAAA+g4AAAAAASYMAAA=\",\"\"]Cc[\"AAAAAocBAAB0EAAAAAAAAAErDAAAAAEaBAAAAWcHAAA=\",\"\"]Cc[\"AAAAApYBAAB1EAAAAAAAAAEsDAAAAAEbBAAAAWgHAAA=\",\"\"]AAo[\"AAAAAncSAAB4EgAAAAWOAQAAjwEAAKABAAChAQAAuhAAADswAAABAAALAAMAKQUHAMgFAAAYDAIAOjAAAAEAAAAAAAcAEAAAALMFFggXCBgIGQgCDwMPVA8GthAAALcQAAC4EAAAuRAAAEkTAACAEwAAOzAAAAEAAA0ABAAfDAAAAg4AAFAPAwCYEgcAOzAAAAEAAAcAAQAtBwcAAm0QAAD8EQAAAAHCBwAAAR8HAAAAAAABFAYAAA==\",\"AAAAA6gBAACpAQAAqgEAAAAB/Q8AAA==\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACvwUAAEIHAAA=\",\"AAAAAAAAAALfEAAA4BAAAAAAAAAAAAAAAAACIAcAADYHAAA=\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAACwAUAAEQHAAA=\",\"AAAAAAAAAALhEAAA4hAAAAAAAAAAAAAAAAACIQcAADcHAAA=\"]Ak[\"\",\"AAAAAAJODwAATw8AAA==\"]Eo[\"AAAABGcFAABsBwAADwgAAMkQAAACYgkAAP4LAAABXRAAAAAAAfMAAAABmxIAAAEwBwAA\",\"AAAAAWcFAAAAAY8BAAA=\"]Eo[\"AAAABKgFAABwBwAAEwgAANAQAAACZgkAAAIMAAABYRAAAAFqAQAAAAABnxIAAAE0BwAA\",\"AAAAAagFAAAAAaEBAAA=\"]Bg[\"AAAAAAAAAAAAAQEEAAA=\",\"AAAAAXQJAAA=\"]Ag[\"AAAChgEAAJUBAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAIjDAAAaxAAAA==\",\"\"]Ag[\"\",\"AAAC7A8AAO0PAAA=\"]Bc[\"AAAAAAAAAAAAAawRAAA=\",\"AAFjAAAA\"]Dg[\"AAAAAqgBAACpAQAAAAADzgUAABgMAACzEQAAAAGEAQAAAUYTAAA=\",\"AAAAAZ8RAAA=\"]Hg[\"AAAAAdQQAAABjxIAAAPjDwAAZxAAAL0QAAAB5hIAAAHfEAAAAdQPAAAC5xAAALYRAAAB2RAAAAAAAAABFRMAAA==\",\"AAAAAAAAAAJ3EAAAeRAAAAAAAAJ2EAAAeBAAAA==\"]Ig[\"AAAAAdcQAAABkRIAAAPnDwAAaRAAAL8QAAAB6RIAAAHhEAAAAdYPAAAC6RAAALgRAAAB2xAAAAAAAAABFxMAAA==\",\"AAAAAAG0EAAAAAADexAAAH0QAAB/EAAAAAAAA3oQAAB8EAAAfhAAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAmIAAADkDgAA\",\"\"]Cc[\"AAAAAQUQAAABoRIAAAAC8wMAABMGAAA=\",\"AAAAAAEoCAAA\"]Ek[\"AAAAAU0FAAAAARgAAAAAAAHLAAAAAAAAAAAAAAAAAjQFAADrBgAA\",\"AAHSBwAAAAFNBQAAAAAAAAAAARQQAAA=\"]Ek[\"AAAAAXoFAAAAATUAAAABFwEAAAAAAAAAAAAAAAAAAjcFAADsBgAA\",\"AAHpBwAAAAF6BQAAAAAAAAAAARUQAAA=\"]Be[\"AAAAAAA7MAAAAQAAdgABACgRdgA=\",\"\",1]Bg[\"AAAAAAAAAAAAAQQEAAA=\",\"AAAAAfALAAA=\"]Ec[\"AAAAAAAAAAAAAAAAAALDBwAAxQcAAAEfBwAAApkBAAALBwAA\",\"AAAAAAAAAAAAAAAAAAAAAZkBAAA=\"]Dk[\"AAAAAAAAAAABOxMAAAF6EwAA\",\"AAAAAAAB8hEAAAHIEgAAAAAAAAAAAAAAAAABrAcAAA==\"]Dc[\"AAAAAY4FAAAAAAE4AQAAARgHAAAAAAAAAAAAAAAAAeABAAA=\",\"AAAAAY4FAAA=\"]ABc[\"AAAAA4EBAAA1CgAA/xAAAAMeBwAAkAoAAFkQAAAAADowAAABAAAAAAANABAAAABdCV4JaAlpCTsPPA8IEAkQaBJpEo0SjhLeEt8SOzAAAAEAAA8ABwBUEAEA4BEFAJQSAQDgEgAANRMAAJATAQCeEwEAAAJgEwAAiBMAAA==\",\"AAAAA3QBAAB/AQAA0A8AAATKDwAAyw8AAMwPAADNDwAAAq4BAACwAQAAAAAC4BIAADUTAAAAAmATAACIEwAAAAAAAAAAAASvAQAAsQEAAEAJAAACEQAA\"]Bk[\"AAAAAAFMBwAA\",\"AAAAAAAAAAGzEAAAAAGsEQAA\"]Hg[\"AAAABT4FAADXBQAAEQYAAHcMAAD5EQAAAe0OAAADPwcAAC4SAABfEwAAAqgAAACqEQAAAbEFAAABwQcAAAHPDwAA\",\"AAAAAj4FAADwBgAAAU0HAAAAAAABhAEAAAFGEwAA\"]Gg[\"AAAAAvoRAAD4EgAAAfcGAAABIwcAAAH+AAAAAuIPAAAvEgAAAAFBBwAAAAHMBQAAAAHCBwAAAR8HAAAAAAABFAYAAA==\",\"AAAAAAAAAAAAAAGSAQAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWEAAAA=\",\"\"]Fc[\"AAADIgcAAEAHAABJDwAABBQMAAD5DwAA9BAAAEcTAAAE4gEAAMsFAAASBgAAbAkAAAACqgAAACoPAAA=\",\"AAABUhAAAA==\"]Fc[\"AAAABBUMAAD6DwAA9hAAAEgTAAABbQkAAAEjBwAAAToBAAAAAAFBBwAAAAHMBQAAAAAAAAAAARQGAAA=\",\"AAABUxAAAA==\"]Dg[\"AAAAAZMFAAAAAUUAAAABQwEAAA==\",\"AAAAAZMFAAAAAAAAAAAAAAAAAAAAAAFkAAAA\"]Bk[\"AAAAAAHhAQAAAAAAAAH+AwAA\",\"AAAAAR0MAAA=\"]Cc[\"AAAAAAEbCAAAAAAAAAH/AwAA\",\"AAAAAAACHgwAAPsRAAA=\"]Dk[\"\",\"AAAAADswAAABAAATAAEArQcTADswAAABAAATAAEAgQATADswAAABAAATAAEAVw8TAA==\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAV8AAAA=\",\"\"]Ak[\"\",\"AAAAAAJrDwAA/xIAAA==\"]Ag[\"\",\"AAAAAAABHBMAAA==\"]Fg[\"AAAAAasFAAAAAAFxAQAAAAAAAAAAARAEAAAAAAABJgwAAAabAAAAfAEAANoBAAAPBwAAYQcAAKQRAAA=\",\"AAH4BwAAAAGrBQAA\"]Ho[\"AAAElQAAACACAAC7BQAADAwAAAFiBQAAAAImAAAAhwAAAAFdDwAAAgcDAAAUBwAAAuwAAADtAAAA\",\"AAABSgIAAARWAAAAVwAAAFgAAABiBQAAAowBAACIEgAAAAH0CwAAAQcHAAA=\"]Kk[\"AAAElgAAAHsCAAC8BQAADQwAAAGdBQAAAARNAAAAlAAAAHAPAAB1DwAAA1UBAABWAQAAag8AAAIUAwAAGgcAAA==\",\"AAAByAIAAAKdBQAAixIAAAGeAQAAAfgLAAAD8wMAABMGAAANBwAAAAAAAAAAAAAAAAAEXwAAAGAAAABhAAAAYgAAAA==\"]Ak[\"AAAAAAKFDwAAhg8AAA==\",\"\"]Ao[\"AAAAAAAAAAACfQEAAOARAAA=\",\"\"]Ao[\"AAAAAAAAAAACfgEAAOMRAAA=\",\"\"]Dc[\"AAAAAAAAAAAB7gAAAAAAAAAAAAAAAAWZAAAAHQQAAFoHAAA0DwAAAhAAAA==\",\"\"]Fc[\"AAAAAAAAAVcBAAAAAAAAAAAAAAAAAAWaAAAAHgQAAFsHAAA1DwAAAxAAAA==\",\"AAAAAAAAAAAAAUEHAAAAAswFAABtEAAA\"]Fc[\"AAAAAawFAAAAAAFyAQAAAhUEAAC9CwAAAAAAAAEnDAAAAAAAAAAFnAAAAFwHAAA9CQAANg8AAAQQAAA=\",\"AAAAAawFAAA=\"]Fk[\"AAAAAUkFAAAAAAAAAccAAAAAAAAAAAAAAAADdwEAADMFAAAEDAAA\",\"AAHOBwAAAAFJBQAAAAAAAAAAAAAAAAAAAAACYgcAAGQHAAA=\"]Fk[\"AAAAAXQFAAAAAAEPAQAAAAAAAAAAAAAAAAADeAEAADYFAAAGDAAA\",\"AAHlBwAAAAF0BQAAAAAAAAAAAAAAAAAAAAACYwcAAGUHAAA=\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAF2EgAA\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWAAAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlsAAAD1DgAA\",\"\"]Bg[\"AAAAAAAAAAAAAQMEAAA=\",\"AAAAAbIMAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAZgAAAA=\",\"\"]Dk[\"AAAAAWQFAAABjQEAAAABKgUAAAHGEAAAAfAAAAA=\",\"AAHbBwAAAAFkBQAAAAAAAcYQAAA=\"]Dk[\"AAAAAaUFAAABnwEAAAACZwEAAC4FAAABzRAAAA==\",\"AAH0BwAAAAGlBQAAAAAAAc0QAAA=\"]Hc[\"AAAAAAABLQ8AAAETEwAAAAE3EwAAAXYTAAAAAAAAAAAAADowAAABAAAAAAANABAAAAAqBzwJeQkHDjoPPQ94D0YQVhDuEAESAxLREgUT\",\"AAAAAAAB7hEAAAHEEgAA\"]Ak[\"AAAAAAIZEwAAGhMAAA==\",\"\"]Cg[\"AAAAAS0SAAABcQkAAAEPBAAAAAABFAQAAA==\",\"AAAAAAEFDAAA\"]Ag[\"\",\"AAAAAAAAAQ4HAAA=\"]Ag[\"AAAAAAAAAAEbBwAA\",\"\"]Dk[\"AAAAAAAAOzAAAAEAAJUAAwCfACAA/QBmAGYBDQAAOzAAAAEAAD4AAgDAADwAZAEBAA==\",\"\"]Gg[\"AAAAAZ4FAAAAAk4AAAD5EgAAA1gBAABZAQAAexMAAAEVAwAAAAEfDAAAAAH8EQAAAAABHwcAAAAAAAJDBwAAbgkAAA==\",\"AAAAAZ4FAAAAAAH1DwAA\"]Dk[\"AAAAAVkFAAAAAR0AAAAAARIHAAAC2wAAANwAAAA=\",\"AAAAAlkFAAA7CgAAAAAAAQUHAAA=\"]Dk[\"AAAAAYsFAAAAAUAAAAACMgEAADMBAAABFwcAAA==\",\"AAAAAYsFAAABlwoAAAABCgcAAA==\"]Ck[\"AAAAAXEPAAAAAAAAAsQHAAAFCAAA\",\"AAAAAAAAAAAC1A8AANUPAAA=\"]Ck[\"AAAAAXIPAAAAAAAAAsYHAAAHCAAA\",\"AAAAAAAAAAAC1g8AANcPAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAk8QAACyEQAA\"]Ek[\"AAAAAykIAACiEQAA9hIAAAAAAAAAAAEECAAAAAABwwcAAA==\",\"AAAAAAAAAALfEAAA4BAAAALUDwAA1Q8AAA==\"]Ek[\"AAAAAyoIAACjEQAA9xIAAAAAAAAAAAEGCAAAAAABxQcAAA==\",\"AAAAAAAAAALhEAAA4hAAAALWDwAA1w8AAA==\"]Eg[\"AAAAAYAFAAAAATwAAAACIgEAACMBAAA=\",\"AAAAAYAFAAAAAAAAAAEfDAAAAAH8EQAAAAAAAAAAAbgFAAA=\"]Ac[\"\",\"AAAAAAFrDwAA\"]Cc[\"AAABnAIAAAFxBQAAAAEvAAAAAQoBAAA=\",\"AAAAAXEFAAA=\"]Gg[\"AAAAAUsFAAAAARcAAAAAAAHJAAAAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAAK8B3gHuDi8P7g8GECQSlhKmEsES\",\"AAHQBwAAAAFLBQAAAAHzDgAA\"]Ho[\"AAAAAXYFAAAAATIAAAABEQEAAAAAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAALEB3wHvDjEP7w8HECUSlxKnEsIS\",\"AAHnBwAAAAF2BQAAAAAB9A4AAAAAAAAAAAAAAAAAAfUOAAA=\"]Gk[\"AAACBQIAAA0CAAABQQUAAAACDgAAAFMHAAACswAAALQAAAA=\",\"AAACCAIAAAkCAAABQQUAAAAAAAAC/g4AAP8OAAAAAAILBAAAbQ8AAAABaxAAAAElDAAA\"]Do[\"AAAAAXgFAAAAAjMAAACLAAAAAxMBAAAUAQAAYQ8AAAELAwAA\",\"AAAAAXgFAAAAAAAAAfEDAAA=\"]Ck[\"AAAAAv0SAAD+EgAAAAAAAAAAAAABJwwAAA==\",\"AAAAAAABTBAAAA==\"]Co[\"AAAAAAABPwcAAAOzEQAAtBEAALURAAAAAYQBAAA=\",\"AAAAAAABLQ8AAA==\"]JLi[\"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\",1]Eo[\"AAAAAAA7MAAAAQAABQABAO0RBQA7MAAAAQAABQABAMMSBQAAOzAAAAEAAAUAAQA2EwUAOzAAAAEAAAUAAQB1EwUA\",\"\"]Ck[\"AAAAAAAAAcgFAAAAAAH8AwAA\",\"AAAAAAAAAxgMAAAZDAAAGgwAAA==\"]Cc[\"\",\"AAAAAAAE+AMAAF0HAAD1EAAAHRMAAAAAAuASAAA1EwAA\"]Fc[\"AAAAAXMFAAAAATEAAAACDQEAAA4BAAA=\",\"AAHkBwAAAAFzBQAAAAACbA8AAPUPAAACIgwAAAATAAAAAAJgEwAAiBMAAA==\"]Eo[\"AAAAAfIQAAABagkAAAACowAAAA4MAAABuxAAAAABAAQAAA==\",\"AAAAAAESBgAAAAIODAAAKg8AAAABwQcAAAHPDwAA\"]Dk[\"AAAABqsRAAD/EQAAXBMAAGcTAACFEwAAlBMAAAAAAAAByRIAAA==\",\"AAAAAAAAAAGzEAAA\"]A@g[\"AAAAOjAAAAEAAAAAAA8AEAAAABgEOwXWBfMGGgh0CfALHQw4DLIMgg9wEPMQ6xHMEmITOjAAAAEAAAAAAAkAEAAAAGsJaw/OD64RKBJwEnES/xKXE5sTOjAAAAEAAAAAAAgAEAAAAK4B9gMeDPMOZhC8EPsRkxIcEzowAAABAAAAAAAHABAAAACkAHEQ5xFXE38ThhOiE6QTAbAFAAAAAAAAAAAAARQTAAA=\",\"AAAAATsFAAABAQkAAAABDgwAAA==\"]ACk[\"AAAAOjAAAAEAAAAAAAgAEAAAABkEWwkRDOoOMA9DENYQMxM0EzowAAABAAAAAAAIABAAAAD6A8QF2AUoCAUMtBDsEfoSGxM6MAAAAQAAAAAACgAQAAAAsAEJBHAPdQ/hD/0PuhCvEW8SchLUEjowAAABAAAAAAAHABAAAAD9APQObA/1D+gRaBOjE6UTBbMFAAAiDAAAABMAAFgTAACHEwAAA60RAABJEwAAgBMAAAIfDAAAAg4AAAJgEwAAiBMAAAJtEAAA/BEAAA==\",\"AAAAAAAAAAAAAAAAAAHCBwAAAAAAAAEUBgAA\"]Ho[\"AAAAA2kHAAAMCAAAxBAAAANfCQAA+wsAAIETAAABWhAAAAABFggAAAACUA8AAJgSAAABLQcAAA==\",\"AAAAAAT7CwAA/AsAAP0LAAD+CwAAAAUpBQAAKgUAACsFAAAsBQAA5xEAAA==\"]Ho[\"AAAAA20HAAAQCAAAyxAAAANjCQAA/wsAAIMTAAABXhAAAAABGAgAAAACUg8AAJwSAAABMQcAAA==\",\"AAAAAAT/CwAAAAwAAAEMAAACDAAAAAUtBQAALgUAAC8FAAAwBQAA6BEAAA==\"]Mc[\"AAAAAUoFAAAAAAAAAcgAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAA1wH5A/wGXwc+CW8JGwwgDCgMKw9LD9EP+w8AEAwQRBBQEFcQYhBkEMEQ4xD3EKURpxHpEfcRKRIrEmwSqBKqEtwS4xIBEx4TXRM=\",\"AAHPBwAAAAFKBQAAAAAAAAAAAAAAAAAAAAACRAkAAEYJAAA=\"]Mc[\"AAAAAXUFAAAAAAEQAQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAA2AH7AwAHYAc/CXAJHAwhDCkMLA9MD9IP/A8BEA0QRRBREFgQYxBlEMIQ5BD4EKYRqBHqEfgRKhIsEm0SqRKrEt0S5BICEx8TXhM=\",\"AAHmBwAAAAF1BQAAAAAAAAAAAAAAAAAAAAACRQkAAEcJAAA=\"]Ag[\"\",\"AAAAAAAAAb4LAAA=\"]Ck[\"AAAAAZkFAAAAAAFPAQAA\",\"AAAAAZkFAAAAAAO/CwAAwAsAAMELAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAEQBAAAAAAAASYMAAA=\",\"\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAeUOAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAApITAACTEwAA\"]Ck[\"AAAAAAAAAAABSRMAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAABqRMAAA==\"]Ag[\"AAACagIAAOACAAA=\",\"\"]Cc[\"AAAAAAACHgwAAPsRAAABAQ8AAA==\",\"AAAAAAABXQcAAA==\"]Gc[\"AAAAAXAFAAAAAS4AAAABCQEAAAABrREAAAEfDAAAAAH8EQAA\",\"AAHjBwAAAAFwBQAAAAFvEgAAAWwPAAAAAa0RAAAAAAAAAAAAAAABXgcAAA==\"]Do[\"AAAAAAAAAAECDwAAAtoFAAAyDwAA\",\"AAAAAYUBAAAAAAABAg8AAATaBQAAMg8AALYQAAC3EAAA\"]Do[\"AAAAAAAAAAEDDwAAAtsFAAAzDwAA\",\"AAAAAZEBAAAAAAABAw8AAATbBQAAMw8AALgQAAC5EAAA\"]Ao[\"AAAAAAHTDwAAAAAB9g8AAA==\",\"\"]Gc[\"AAAB0hAAAAJWAAAACggAAAHjAQAAAAGvAAAAAiEEAADvEAAAAv4OAABuDwAAAAEADwAAAgsEAABtDwAAAAIjDAAAaxAAAAIkDAAAJQwAAA==\",\"\"]Cc[\"AAAAAAAAAAMMBAAAIwQAAPEQAAA=\",\"AAAAAAABcA8AAA==\"]Ec[\"AAABCAIAAAFCBQAAAAIPAAAAVAcAAAK1AAAAtgAAAA==\",\"AAABCwIAAAFCBQAAAAAAAu8QAADwEAAA\"]Bo[\"AAABUhAAAAAAAAKrAAAArAAAAA==\",\"AAAAAAHLBQAA\"]Ck[\"AAABUxAAAAAAAAI+AQAAPwEAAA==\",\"AAAAAAAAAAAAAAABzAUAAA==\"]Ao[\"AAAAAAAAAaUSAAAB8A4AAA==\",\"\"]Hg[\"AAAAAVgAAAAB5AEAAAF1CQAAA7sAAAAcBwAAChAAAALJBQAAhw8AAAAC4AUAAHgMAAAG9g4AAPcOAAD4DgAAFBAAAGwQAAANEgAAASMIAAAAAvkOAAD7DgAAAfoOAAA=\",\"\"]Dk[\"AAAAAAABdgkAAAIdBwAAJAgAAALKBQAACxAAAAAB4QUAAAEVEAAA\",\"AAAAAAABdQ8AAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAF2EgAA\",\"\"]AAg[\"AAAAAfAGAAABTQcAAATvBgAAHgwAAC0PAAD7EQAAAlcTAACGEwAAA7MQAABYEwAAhxMAAAXBBwAAthAAALcQAAC4EAAAuRAAAAHPDwAAAAAAAcIHAAA=\",\"AAAABPIQAADzEAAA9BAAAPYQAAAC7A4AAO0OAAAC9RAAABwTAAAFfxMAAKITAACjEwAApBMAAKUTAAABABMAAAGAEwAAAawRAAAAAAAAAAAAAgcPAAAgDwAABtkBAADaAQAAQwcAADQPAAA1DwAANg8AAA==\"]Dc[\"AAAAAAAAAAA7MAAAAQAABQABAOARBQA=\",\"AAAABKcBAACrAQAArAEAAK0BAAA=\"]Ao[\"AAAAAacBAAAAAAAAAXsPAAA=\",\"\"]Ao[\"AAAAAawBAAAAAAAAAXwPAAA=\",\"\"]Eo[\"AAAAAdUQAAABkBIAAAPlDwAAaBAAAL4QAAAB5xIAAAHgEAAAAdUPAAAC6BAAALcRAAAB2hAAAAAAAAABFhMAAA==\",\"\"]Eo[\"AAAAAdgQAAABkhIAAAPpDwAAahAAAMAQAAAB6hIAAAHiEAAAAdcPAAAC6hAAALkRAAAB3BAAAAAAAAABGBMAAA==\",\"\"]Bc[\"AAAAAAAAAiQEAAAkBwAAAAF9DwAA\",\"\"]Bc[\"AAAAAAAAAicEAAAnBwAAAAF+DwAA\",\"\"]Ec[\"AAAAAaIBAAAAAgASAAACEgAAAuESAADiEgAAAhUEAAC9CwAAAAAAAAABEAQAAA==\",\"AAAAAAHwAgAA\"]Gg[\"AAAAAUQFAAAAAhEAAABWBwAAArwAAAC9AAAA\",\"AAADEQIAABICAAATAgAAAUQFAAAAAAABhw8AAAAC4AUAAHgMAAACFBAAAA0SAAAAAAAB+g4AAA==\"]Eg[\"AAAAAXsFAAAAAjYAAACNAAAAAxgBAAAZAQAAYw8AAAENAwAA\",\"AAAAAXsFAAAAAAAAAAHhBQAAARUQAAA=\"]Ec[\"AAAAAAAAAT0BAAAAAAAAAAAAAAAAAAI4BQAAegkAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAARQGAAA=\"]Ec[\"AAAB+QsAAAE6BQAAAAELAAAAAaAAAAA=\",\"AAAAAToFAAAAAU0JAAAAAAAAAAAAAAAAAAAB7QYAAA==\"]Dg[\"AAAAAAHGBQAAAAAAAAAAAAAAAAAAAAIPEAAAtRAAAA==\",\"AAHJBwAAAAAAAe8GAAA=\"]Ac[\"AAABLAIAAA==\",\"\"]Do[\"AAAAAVgFAAAAARwAAAAAAALZAAAA2gAAAA==\",\"AAACOgIAADwCAAABWAUAAAAAAAAAAc8SAAA=\"]Dk[\"AAAAAYoFAAAAAT8AAAACMAEAADEBAAA=\",\"AAACpwIAAKkCAAABigUAAAAAAAAAAdASAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAlIJAABUCQAA\"]Dk[\"AAAAAAAAAAAB9wAAAA==\",\"AAABWAIAAAAAAAAAAAAAAWcHAAABEQQAAAHDBwAAAAHyAwAA\"]Dg[\"AAAAAAAAAWABAAA=\",\"AAAB1AIAAAAAAAAAAAAAAWgHAAABEgQAAAHFBwAAAAH0AwAA\"]Dk[\"AAAAAWYFAAAAAY4BAAABKwUAAAHIEAAAAfIAAAA=\",\"AAHcBwAAAAFmBQAAAAAAAcgQAAA=\"]Dk[\"AAAAAacFAAAAAaABAAACaQEAAC8FAAABzxAAAA==\",\"AAH1BwAAAAGnBQAAAAAAAc8QAAA=\"]Ck[\"AAAAAXwFAAAAATcAAAACGgEAABsBAAA=\",\"AAAAAXwFAAAAAAEdBwAA\"]Eg[\"AAAAAVMFAAAAAhsAAACDAAAAAVkPAAABAwMAAALUAAAA9REAAA==\",\"AAHXBwAAATUCAAACUwUAADUKAAA=\"]Eg[\"AAAAAYUFAAAAAj4AAACOAAAAAisBAABkDwAAAQ4DAAAB9hEAAA==\",\"AAHvBwAAAaICAAABhQUAAAGQCgAA\"]Ao[\"AAAAAAAAAAAC/g8AALYQAAA=\",\"\"]Ao[\"AAAAAAAAAAAC/w8AALgQAAA=\",\"\"]Bg[\"AAAAAAAABLoAAADQBQAAGgwAALURAAA=\",\"\"]Ak[\"AAAAAAABOAAAAAEcAQAA\",\"\"]Do[\"AAAAAAAAAAAAAAAAAAAAAAAAAk8QAACyEQAA\",\"AAHHBwAAAAAAAAAAAAAAAAAAAAAAAAEOEAAA\"]Cg[\"AAAAAAMeBwAAcwkAAFkQAAA=\",\"AAAAAAAAAALwDgAA9g8AAA==\"]Ag[\"AAACWAIAANQCAAA=\",\"\"]Cc[\"AAAAAVgKAAACVwoAAL0KAAABvgoAAAIQEAAAEhAAAA==\",\"\"]Ac[\"\",\"AAAAAeYRAAA=\"]Gk[\"AAAAAVcFAAAAAV8TAAAAAQIJAAAE2AAAAH0PAAAGEgAARBMAAAHPDwAA\",\"AAEiEwAAAAOJAQAAVwUAAGkTAAAAASQTAAAAAQIJAAADfQ8AAAYSAABEEwAA\"]Bc[\"AAAAAYkBAAAAAAAAAAAAAXYQAAA=\",\"\"]Gk[\"AAAAAYkFAAAAAAEvAQAAAQMJAAADfg8AAAgSAABFEwAAAAAAAAHCBwAA\",\"AAEjEwAAAAOYAQAAiQUAAGoTAAAAASUTAAAAAQMJAAADfg8AAAgSAABFEwAA\"]Bc[\"AAAAAZgBAAAAAAAAAAAAAXoQAAA=\",\"\"]Fg[\"AAABEwIAAAFOBQAAAAEZAAAAAAACzAAAAM0AAAA=\",\"AAHTBwAAAAFOBQAAAAF1CQAAAhwHAAAKEAAAAyEEAAAiBAAAyQUAAA==\"]Eo[\"AAAAAX4FAAAAAToAAAACHgEAAB8BAAA=\",\"AAHrBwAAAAF+BQAAAAF2CQAAASQIAAAEIwQAAMoFAAALEAAA8RAAAA==\"]Ao[\"\",\"AAAAAAAAAAAAAAABfhAAAA==\"]Ek[\"AAAAAVwFAAAAASAAAAAAAALhAAAA4gAAAA==\",\"AAABQgIAAAFcBQAAAAAAAAHBBwAAAc8PAAAAAnYQAAB4EAAA\"]Eg[\"AAAAAZAFAAAAAUQAAAACOwEAADwBAAA=\",\"AAABsQIAAAGQBQAAAAAAAAAAAAJ6EAAAfBAAAAABwgcAAA==\"]Ao[\"AAAAAAAAAAHrDwAAAAExDAAA\",\"\"]Jk[\"AAAAAV0FAAAABSEAAACEAAAAtQUAAOMPAADlDwAAAr4LAABaDwAABAQDAAAHDAAA5A8AAOYPAAAE4wAAAOQAAAC2EAAAtxAAAAItDAAALgwAAALZEAAA2hAAAA==\",\"AAAAAl0FAAD5DwAAAooBAADcDwAAAAABSAkAAA==\"]Og[\"AAAAAZUFAAAABUcAAACRAAAAtgUAAOcPAADpDwAABkgBAABJAQAAvwsAAMALAADBCwAAZw8AAAQRAwAACAwAAOgPAADqDwAAArgQAAC5EAAAAi8MAAAwDAAAAtsQAADcEAAA\",\"AAAABJUFAAD8BwAA/QcAAPoPAAAEmgEAAN0PAADeDwAA3w8AAAAAAUkJAAACwQUAAMIFAAAAAAAAAAAAAAA7MAAAAQAACgACAP4HBQAeCAQA\"]Ck[\"AAABvQUAAAFeBQAAAAEiAAAAAAAB5QAAAA==\",\"AAAAAl4FAAAJDAAA\"]Dg[\"AAABvgUAAAGWBQAAAAFIAAAAAUoBAAAAAAAAAAAAAR8HAAA=\",\"AAAAApYFAAAKDAAA\"]Cc[\"AAAAAa0FAAAAAVQAAAABcwEAAA==\",\"AAAAAq0FAAALDAAA\"]Dg[\"AAAAAAAAAAAAAAABbRAAAA==\",\"AAAABuAPAAD0EQAAzRIAAM4SAAD9EgAA/hIAAA==\"]Ak[\"AAAAAAAAAAAB4hEAAA==\",\"\"]Ak[\"AAAAAAAAAAAB5REAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAl4AAADZAQAA\",\"\"]Bg[\"AAAAAAAAAAAAAQUEAAA=\",\"AAAAAXAQAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAl0AAABeBwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAQtBwAALgcAAC8HAAAwBwAA\",\"\"]Ec[\"AAAABHQBAAB/AQAAbwUAANAPAAAAAAEIAQAAAAAABDEHAAAyBwAAMwcAADQHAAA=\",\"AAAAAW8FAAA=\"]Bg[\"AAAAAAAAAAAAAQYEAAA=\",\"AAAAAAFwEgAA\"]Cc[\"AAAAAVsKAAACWgoAAMAKAAABwQoAAAIREAAAExAAAA==\",\"\"]Ag[\"AAAAAAABTwcAAA==\",\"\"]No[\"AAAAAVUFAAABTQcAAAEuEgAAASoPAAAGFgwAAPAPAADKEgAA3hIAADwTAABjEwAAB9YAAACEAQAAcQwAAHsPAAAFEgAA1RIAANcSAAABRhMAAAAAAAAAAAAAA/0GAAB1DAAACRIAAA==\",\"AAAAAlUFAACDDwAAAAGIAQAAAQsSAAAGFgwAAPAPAADKEgAA3hIAADwTAABjEwAABXEMAAB7DwAABRIAANUSAADXEgAA\"]Bo[\"AAAAAYMPAAAAAYgBAAAAAuQPAAB3EAAAAAEtDAAA\",\"\"]Nc[\"AAAAAYcFAAAAAAEtAQAABxcMAADxDwAALxIAAMsSAADfEgAAPRMAAGQTAAAFcgwAAHwPAAAHEgAA1hIAANgSAAAAAZIBAAAAAAAAAAAABBQGAAABBwAAdgwAAAoSAAA=\",\"AAAAAocFAACEDwAAAAGXAQAAAQwSAAAGFwwAAPEPAADLEgAA3xIAAD0TAABkEwAABXIMAAB8DwAABxIAANYSAADYEgAA\"]Bo[\"AAAAAYQPAAAAAZcBAAAAAugPAAB7EAAAAAEvDAAA\",\"\"]Ao[\"AAAAAAAAAAAC1RIAANYSAAA=\",\"\"]Ao[\"AAAAAAAAAAAC1xIAANgSAAA=\",\"\"]Ec[\"AAABEgIAAAFFBQAAAAISAAAAVwcAAAK+AAAAvwAAAA==\",\"AAABFQIAAAFFBQAAAAAAAAAAAAEjCAAA\"]Bk[\"AAAAAaoBAAAAAAS5AAAAzwUAABkMAAC0EQAA\",\"\"]Ek[\"AAAAA4kSAACKEgAAixIAAAOGEgAAhxIAAIgSAAAE9QsAAPYLAAD3CwAA+AsAAATxCwAA8gsAAPMLAAD0CwAA\",\"\"]Cc[\"AAAAAAAAAAAB4REAAA==\",\"AAHKBwAAAAKDAQAAahIAAA==\"]Cc[\"AAAAAAAAAAAB5BEAAA==\",\"AAHfBwAAAAKQAQAAaxIAAA==\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAABHwcAAA==\"]Cg[\"AAAAAesOAAAAAAFHAQAAAeIPAAA=\",\"AAH7BwAAAAAAAdQSAAA=\"]Ek[\"AAAAAT8FAAAAAAGpAAAAAAAAAAAAAAAAAAAEZxIAAG4SAACFEgAAoBIAAA==\",\"AAHLBwAAAAI/BQAA1wUAAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3cJAAB5DwAAkhMAAA==\",\"\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3gJAAB6DwAAkxMAAA==\",\"\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAlMJAABVCQAA\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlwAAAC4BQAA\",\"\"]Ec[\"AAAAAWgFAAAAAY8BAAABLAUAAALKEAAA+xIAAAH0AAAA\",\"AAHdBwAAAAFoBQAAAAAAAsoQAAD7EgAA\"]Ec[\"AAAAAakFAAAAAaEBAAACawEAADAFAAAC0RAAAPwSAAA=\",\"AAH2BwAAAAGpBQAAAAAAAtEQAAD8EgAA\"]Ag[\"\",\"AAAAAAABqREAAA==\"]Co[\"AAAAAnkBAAD8BwAAAAABQAEAAA==\",\"AAAAAAAAAAAAAAAAAAAAAZkBAAA=\"]Ac[\"\",\"AAAAAAExEgAA\"]Cg[\"AAAAAAAAAgsSAAAMEgAAAAABrBEAAA==\",\"AAAAAAAAAAHZEgAA\"]Do[\"AAAAAXkFAAAAAjQAAACMAAAAAxUBAAAWAQAAYg8AAAEMAwAA\",\"AAAAAXkFAAAAAAABDAQAAA==\"]Ak[\"AAAAAAACJBMAACUTAAA=\",\"\"]Ac[\"AAAAAasBAAA=\",\"\"]Ac[\"AAAAAa0BAAA=\",\"\"]Eo[\"AAACugIAAM4CAAABnwUAAAABTwAAAAJaAQAAWwEAAA==\",\"AAAAAZ8FAAAAAAAFAwcAAAQHAAAFBwAABgcAAAcHAAA=\"]Fk[\"AAAABPIPAADzDwAAzRIAAM4SAAAB7A4AAAFMEAAAAaoRAAAAAAFGEwAAAAAAAAAAAAEmDAAA\",\"AAAAAAAAA7MRAAC0EQAAtREAAA==\"]Fc[\"AAAAAAAB7wYAAAILEgAADBIAAAGzEAAAAAGsEQAAAAACIBMAACETAAAAAAABdhIAAA==\",\"AAAAAAAAAVsTAAAB2RIAAA==\"]Ag[\"\",\"AAAAAAABsgUAAA==\"]Co[\"AAAAAYEFAAAAAT0AAAACJAEAACUBAAA=\",\"AAAAAYEFAAAAAAAAAAECDgAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAT4HAAA=\",\"\"]Jc[\"AAAAAlQFAABCEwAAAAAAAqARAABoEgAABNUAAACEAQAAKwwAAHMSAAADewkAAM8SAABGEwAAAAAAAUoQAAA=\",\"AAHYBwAAAAKHAQAAVAUAAAAAAAKgEQAAaBIAAAIrDAAAcxIAAAJ7CQAAzxIAAAAAAAFKEAAA\"]Jg[\"AAAAAoYFAABDEwAAAAABLAEAAAKhEQAAaRIAAAIsDAAAdBIAAAJ8CQAA0BIAAAGSAQAAAAABSxAAAA==\",\"AAHwBwAAAAKWAQAAhgUAAAH3BgAAAAACoREAAGkSAAACLAwAAHQSAAACfAkAANASAAAAAAABSxAAAA==\"]Ao[\"AAAAAAAAAa0AAAAAAAEIBAAA\",\"\"]Ag[\"AAACaAIAANsCAAA=\",\"\"]Ak[\"AAAAAAAAAiUEAAAlBwAA\",\"\"]Ak[\"AAAAAAAAAigEAAAoBwAA\",\"\"]Ag[\"AAACZwIAAOQCAAA=\",\"\"]Dk[\"AAAAAUMFAAAAAhAAAABVBwAAArcAAAC4AAAA\",\"AAABDQIAAAFDBQAAAAAAAAAAAQAPAAA=\"]Dg[\"AAAAAUAFAAAAAg0AAABSBwAAArEAAACyAAAA\",\"AAABBQIAAAFABQAAAAAAAAFuDwAA\"]Co[\"AAABsBEAAAF9BQAAAAE5AAAAAR0BAAA=\",\"AAHqBwAAAUMJAAABfQUAAA==\"]Ec[\"AAAAAAABsREAAAGhAAAAAAAAAAAAAAAAAAADHAQAAEAJAAAEDwAA\",\"AAAAAYEBAAAAAAAAAckSAAA=\"]Hk[\"AAACmAIAAKsCAAABlwUAAAABSQAAAAJLAQAATAEAAAAAAAAAAAAAAAAABN0BAAC6BQAAAgcAAD0HAAA=\",\"AAABvwIAAAKbAQAAlwUAAAAAAukSAADqEgAAAAAC6RAAAOoQAAA=\"]Fc[\"AAAAA+APAAD0DwAA9BEAAAACABIAAAISAAADcAEAAOESAADiEgAAAhUEAAC9CwAAAAAAAAABEAQAAA==\",\"AAAAAaIBAAA=\"]Eg[\"AAAAAVoFAAAAAR4AAAAAAALdAAAA3gAAAAAAAAAAAAAAAAM5BwAA3w4AAOUOAAA=\",\"AAABPwIAAAFaBQAA\"]Eg[\"AAAAAYwFAAAAAUEAAAACNAEAADUBAAAAAAAAAAAAAAAAAAM7BwAA4Q4AAOYOAAA=\",\"AAABqwIAAAGMBQAA\"]Hk[\"AAAF+wEAAAkCAAALAgAAEQIAABUCAAABTwUAAAACGgAAAFgHAAAAAALOAAAAzwAAAA==\",\"AAADLAIAAC4CAAAvAgAAAk8FAADzBgAAAhIGAADODwAAAZMSAAABKg8AAAG7EAAA\"]Ek[\"AAAAAX8FAAAAAjsAAABZBwAAAiABAAAhAQAA\",\"AAABmAIAAAF/BQAAAAAAAAAAAAAAAAAAAAACOAUAAD4HAAA=\"]Bk[\"AAAAAAAB4Q8AAAFGAQAA\",\"AAAAAAAAAAHiDwAA\"]Ek[\"AAAAAUwFAAAAAAAAAcoAAAAAAAAAAAAAAAAEYgcAAGQHAABECQAARgkAAA==\",\"AAHRBwAAAAJMBQAA1gUAAA==\"]Ek[\"AAAAAXcFAAAAAAESAQAAAAAAAAAAAAAAAAAEYwcAAGUHAABFCQAARwkAAA==\",\"AAHoBwAAAAF3BQAAAdgFAAA=\"]Ag[\"AAACYQIAAOECAAA=\",\"\"]Cg[\"AAAAAa8FAAAAAAAD8A4AAFQPAAD2DwAA\",\"AAH6BwAAAAGvBQAA\"]Dc[\"AAAAApEFAAD9BwAAAAABQQEAAA==\",\"AAAAAZEFAAAAAAAAAAAAAAAAAAELBwAA\"]Dg[\"AAAAAXcSAAABhQ8AAAAAAALQAAAAtxAAAA==\",\"AAFKCQAAAYYBAAABdxIAAAGFDwAA\"]Dg[\"AAAAAXgSAAABhg8AAAABJwEAAAABuRAAAA==\",\"AAFLCQAAAZUBAAABeBIAAAGGDwAA\"]Ac[\"\",\"AAAAAAFKEwAA\"]Ag[\"AAACYgIAAOICAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAD4BEAAOERAADiEQAA\"]Bc[\"\",\"AAAAAAAAAAAD4xEAAOQRAADlEQAA\"]Ak[\"\",\"AAAAAQQSAAAAAAETEwAA\"]ADc[\"AAAAAVAFAAAAAAA6MAAAAQAAAAAAFAAQAAAAFAizDPEOOA87D3YPchDsEAAR/RFjEgMTWRNlE3ETcxOVE5kTnBOgE6cTOjAAAAEAAAAAAAwAEAAAANEA/g9uEPURBRIGEpQSvxLSEn0TjhOQE54TAAAB5RAAAA==\",\"AAHUBwAAAAFQBQAAAAAAOjAAAAEAAAAAABQAEAAAABQIswzxDjgPOw92D3IQ7BAAEf0RYxIDE1kTZRNxE3MTlROZE5wToBOnEzowAAABAAAAAAAJABAAAAD+D24Q9RGUEr8S0hJ9E44TkBOeEwAAAeUQAAA=\"]ADc[\"AAAAAYIFAAAAAAEoAQAAOjAAAAEAAAAAABQAEAAAABUItAzyDjkPPA93D3MQ7RABEf4RZBIEE1oTZhNyE3QTlhOaE50ToROoEzowAAABAAAAAAALABAAAAD/D28Q9hEHEggSlRLAEtMSfhOPE5ETnxMAAAHmEAAA\",\"AAHsBwAAAAGCBQAAAAAAOjAAAAEAAAAAABQAEAAAABUItAzyDjkPPA93D3MQ7RABEf4RZBIEE1oTZhNyE3QTlhOaE50ToROoEzowAAABAAAAAAAJABAAAAD/D28Q9hGVEsAS0xJ+E48TkROfEwAAAeYQAAA=\"]Ag[\"AAACOgIAAKcCAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAf0DAAA=\",\"AAAAAAAAAQ4MAAA=\"]Do[\"AAAAAVsFAAAAAR8AAAAAAALfAAAA4AAAAAAAAAAAAAAAAAI6BwAA4A4AAA==\",\"AAAAAVsFAAA=\"]Do[\"AAAAAY0FAAAAAUIAAAACNgEAADcBAAAAAAAAAAAAAAAAAAI8BwAA4g4AAA==\",\"AAAAAY0FAAA=\"]Ag[\"AAACZQIAAOYCAAA=\",\"\"]Fc[\"AAAAAY8FAAAAAkMAAACPAAAAAjkBAABlDwAAAg8DAADiDwAA\",\"AAAAAY8FAAAAAAAAAAAAAAABwgcAAAAAAAABFAYAAA==\"]Ag[\"AAACXwIAAN8CAAA=\",\"\"]Ag[\"AAACZgIAAOUCAAA=\",\"\"]Ck[\"AAAAAAAAAAAAAAABeBAAAA==\",\"AAAAAVgKAAABVwoAAAABEBAAAA==\"]Co[\"AAAAAaMBAAAAAAAAAAAAAXwQAAA=\",\"AAAAAAG9CgAAAb4KAAABEhAAAA==\"]Dc[\"AAAAAAAAAALmDwAAeRAAAAABLgwAAA==\",\"AAAAAVsKAAABWgoAAAABERAAAA==\"]Dg[\"AAAAAaQBAAAAAAAC6g8AAH0QAAAAATAMAAA=\",\"AAAAAAHACgAAAcEKAAABExAAAA==\"]Cc[\"AAAAAAAAAiYEAAAmBwAAAAHoAAAA\",\"AAHaBwAAAAGLAQAA\"]Cc[\"AAAAAAAAA1EBAAApBAAAKQcAAA==\",\"AAHzBwAAAAGdAQAA\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAzgHAAADCAAAIggAAA==\",\"\"]Ao[\"AAAAAAAAASkFAAAAAY4TAAA=\",\"\"]Bk[\"AAAAAAAAAS0FAAAAAY8TAAA=\",\"AAAAATEFAAA=\"]Eg[\"AAAAAAAAAAAB9QAAAAAAAAAAAAAAAAN9CQAAVQ8AACYSAAA=\",\"AAHeBwAAAAQMCAAADQgAAA4IAAAPCAAA\"]Eg[\"AAAAAAAAAWwBAAAAAAAAAAAAAAAAAAN+CQAAVg8AACcSAAA=\",\"AAH3BwAAAAQQCAAAEQgAABIIAAATCAAA\"]Bc[\"AAAAAAABiAEAAAABsRAAAAFxDAAA\",\"\"]Bc[\"AAAAAAABlwEAAAABshAAAAFyDAAA\",\"\"]Fo[\"AAAAAZQFAAAAAkYAAACQAAAAA0QBAABFAQAAZg8AAAEQAwAA\",\"AAABugIAAAGUBQAAAAAAAALBBQAAwgUAAAAAAAAAAAKZAQAACwcAAA==\"]Dg[\"AAAAAT0FAAAAAgwAAABRBwAAAqYAAACnAAAA\",\"AAAB+wEAAAE9BQAAAAABcRAAAA==\"]Do[\"AAAAAW0FAAAAAiwAAACJAAAAAwQBAAAFAQAAXw8AAAEJAwAA\",\"AAAAAW0FAAAAAAAAARQEAAA=\"]Ek[\"AAAAAVEFAAAAAAAC2hIAACwTAAAD0gAAAFQQAAC/EgAA\",\"AAHVBwAAAAFRBQAAAAAAAtoSAAAsEwAAAVQQAAA=\"]Ek[\"AAAAAYMFAAAAAAEpAQAAAtsSAAAtEwAAAlUQAADAEgAA\",\"AAHtBwAAAAGDBQAAAAAAAtsSAAAtEwAAAVUQAAA=\"]Bo[\"AAAAAAAAAAABwQUAAAAAAAAAAAKZAQAACwcAAA==\",\"\"]Fg[\"AAAAAVIFAAAAAAAEXQkAAIAPAADdEAAAjRIAAALTAAAA0hIAAA==\",\"AAHWBwAAAAFSBQAAAAAABF0JAACADwAA3RAAAI0SAAA=\"]Fg[\"AAAAAYQFAAAAAAEqAQAABF4JAACBDwAA3hAAAI4SAAAB0xIAAA==\",\"AAHuBwAAAAGEBQAAAAAABF4JAACBDwAA3hAAAI4SAAA=\"]Ag[\"\",\"AAAAAAAAAVsTAAA=\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAAAAF2EgAA\"]Ag[\"\",\"AAAAAAAAAQEPAAA=\"]Co[\"AAAAAXIFAAAAATAAAAACCwEAAAwBAAA=\",\"AAAAAXIFAAAAAAAAAa0RAAA=\"]Fg[\"AAABIQIAAAFfBQAAAAEjAAAAAAETBwAAAuYAAADnAAAA\",\"AAACRgIAAPsGAAABXwUAAAAAAAEGBwAAAAAAAAAAAAAAAAHfDgAA\"]Gc[\"AAABfAIAAAKbAQAAmAUAAAABSgAAAAJNAQAATgEAAAEZBwAA\",\"AAACwQIAAP8GAAABmAUAAAAAAQwHAAAAAAAAAAAAAAAAAALdAQAA4Q4AAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA/8HAAAfCAAABQkAAA==\",\"\"]Cg[\"AAABQgIAAAAAAAAAAfgAAAA=\",\"AAAAAAAAAALkDwAA5g8AAA==\"]Cg[\"AAABsQIAAAAAAAFhAQAA\",\"AAAAAAAAAAPoDwAA6g8AAOsPAAA=\"]Bo[\"AAAAAjEFAACuBQAAATESAAA=\",\"AAAAAq4FAAADEQAA\"]Ao[\"\",\"AAAAAAAAAAKAEAAAgRAAAA==\"]Io[\"AAAAAaAFAAAAAVAAAAABXAEAAAbiBQAAdxAAAHkQAAB7EAAAfRAAAH8QAAAAAAAFdhAAAHgQAAB6EAAAfBAAAH4QAAAAAAAAAAABphMAAA==\",\"AAAAAaAFAAAAAATmEgAA5xIAAOkSAADqEgAAAAENBAAA\"]Co[\"AAAAAlcAAAALCAAAAAABsAAAAAIiBAAA8BAAAAH/DgAA\",\"AAAB0hAAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlIJAADYDwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlQJAADaDwAA\",\"\"]Co[\"AAAAAWkFAAAAAAAAAvkAAAD6AAAA\",\"AAAAAWkFAAAAAAIQEAAAERAAAA==\"]Dc[\"AAAAAaIFAAAAAAJiAQAAYwEAAA==\",\"AAAAAqIFAADmEQAAAAACEhAAABMQAAA=\"]Ac[\"\",\"AAAB+QsAAA==\"]Ec[\"AAABPAIAAAFHBQAAAAEUAAAAAAACwgAAAMMAAAA=\",\"AAAAAUcFAAAEUAkAACMKAAAkCgAAJQoAAA==\"]Do[\"AAABqQIAAAFsBQAAAAEqAAAAAgEBAAACAQAA\",\"AAAAAWwFAAAEUQkAAG8KAABwCgAAcQoAAA==\"]Ak[\"\",\"AAAAAAACJBMAACUTAAA=\"]Cg[\"AAAAAjwFAABnCQAAAQEJAAAAAaUAAAA=\",\"AAAAAjwFAACCDwAA\"]Cg[\"AAAAAaIHAAACyg8AANwPAAAAAb4LAAAAAAAAAAABShAAAA==\",\"\"]Ck[\"AAAAAaMHAAACyw8AAN0PAAAAAr8LAADACwAAAAAAAAAAAUsQAAA=\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAiATAAAhEwAA\",\"\"]Fo[\"AAAAAVYFAAAAAAADFgQAAGgJAAA8EwAAAtcAAAB9AQAA\",\"AAHZBwAAAAFWBQAAAAAAAhYEAABoCQAAAX0BAAAAAAAAAAAAAAABCRIAAA==\"]Fo[\"AAAAAYgFAAAAAAEuAQAAAxcEAABpCQAAPRMAAAF+AQAA\",\"AAHxBwAAAAGIBQAAAAAAAhcEAABpCQAAAX4BAAAAAAAAAAAAAAABChIAAA==\"]Ec[\"AAAAAZIFAAAAAAFCAQAAAAAAAAAAAAAAAAAFegEAAP4HAAAeCAAABAkAAHMMAAA=\",\"AAAAAZIFAAA=\"]Dg[\"AAAAAAFKEwAAAAGiAAAAAAAAAAACIBMAACETAAAAAAABdhIAAA==\",\"AAABggEAAA==\"]Ag[\"AAACZAIAANwCAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAiATAAAhEwAA\"]Bk[\"AAAAAAAAAAAAAAABfhAAAA==\",\"AAAAAaMBAAA=\"]Cc[\"AAAAAAAAAALrDwAAfxAAAAABMQwAAA==\",\"AAAAAaQBAAA=\"]Ag[\"AAACYwIAAOMCAAA=\",\"\"]Dg[\"AAAAAAABJwAAAAAAAfYAAAA=\",\"AAAAAAAAAAAAAAAAAAAAAxQTAAAVEwAAFhMAAA==\"]Ck[\"AAAAAAABUgAAAAFfAQAA\",\"AAAAAAAAAAAAAAAAAAAAAhcTAAAYEwAA\"]Ag[\"AAACYAIAAN4CAAA=\",\"\"]Do[\"AAAAAaQHAAACzA8AAN4PAAAAAcELAAABCBAAAA==\",\"AAKUAQAA4AcAAAFMCQAAAAAAAAEIEAAA\"]Ec[\"AAAAApoFAAClBwAAAs0PAADfDwAAAAFQAQAAAQkQAAA=\",\"AAHyBwAAAZwBAAABmgUAAAAAAAEJEAAA\"]Bg[\"AAAAAAAAAAABwgUAAA==\",\"AAABkwEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlMJAADZDwAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAlUJAADbDwAA\",\"\"]") \ No newline at end of file diff --git a/pr/255/docs/search.index/type/ccb5a8e6883b.js b/pr/255/docs/search.index/type/ccb5a8e6883b.js new file mode 100644 index 000000000..b4b4c404b --- /dev/null +++ b/pr/255/docs/search.index/type/ccb5a8e6883b.js @@ -0,0 +1 @@ +rd_("CAk[\"\",\"ADswAAABAAAFAAIACwQEAP0TAAACWwcAAHkHAAA6MAAAAQAAAAAACgAQAAAAwAHBAfUF1QwsEm0SgRLdE+gTBhQVFDowAAABAAAAAAAZABAAAADwAfEB8gHzAfQBGQT0BfkFKQdXB4UHtQnUEC8SbhLzEnwTnBOdE+ATAhQDFAQUBRQYFBwUOzAAAAEAABEBEAAXBAAA8wUAAFwHAAB4BwAAiAcAAIwMBQDzDXsAXBAAANUQBwA2EQAApBF7ADASAAAyEgAAsBIAAPQSAAAVEwAAOjAAAAEAAAAAABwAEAAAAPYF/AX9Bf4FVQdWB10HXgdfB2AHYQdiBxYMFwwYDBkMZwx1D3oPhRDsECsSJxNjE2QT2BPcE+kTBxQ7MAAAAQAAOwAUABgDFAA1BAAAQQQCAN4FAQDhBQAA9wUBABAGAABIBwwAUAgDABUMAAB7DAAAzg8AAAEQAACGEAAA+xABAC8RAACxEgAAWxMAANkTAAAIFAAAOzAAAAEAAFYADADEAD0AcgEBADQEAAD+BwAAAAgAAD8IAABBCAAATxADAGISBQBLEwAAtxMFAMoTAAA7MAAAAQAAFQAHABsEAADWDAAAbw4AAMoPAwAtEgAAGhMHAPYTBQA7MAAAAQAAEQAIADoEAQBmBwcAPggAAEAIAABvDwIAeQ8AAOcQAACPEgAAA6AHAAChBwAAfhIAAAMxBAAAMgQAAIEMAAAF/AcAAP0HAAD/BwAAfgwAAOYQAAAAOzAAAAEAAAUAAgCnAQAAlxMEAAAAAUMGAAA=\"]Bo[\"AAAAAAAAAAACxRMAAMYTAAAAAAAAAsUQAADGEAAA\",\"\"]0Bg[\"\",\"AAAFmAkAAJkJAACaCQAAmwkAAJwJAAA=\"]AIg[\"AAAAAAKYAQAAqAEAAAAABN4FAADfBQAALREAAC4RAAAE/gcAAAAIAAA/CAAAQQgAADswAAABAAANAAUADgYBAL0JAQCHDAQA1gwAAGMRAwA6MAAAAQAAAAAACwAQAAAAOgQ7BD4IQAh5D48QkBBVEVYRVxFYEY8SBCsEAACgBwAAoQcAAOcPAAAEMQQAADIEAACjEwAApBMAAAUwBAAA/QcAAP8HAABzDwAAdA8AAAN9DAAAfwwAAHIPAAA6MAAAAQAAAAAACAAQAAAApwERBBMEQweXE5gTmROaE5sTAfgSAAABgAwAAA==\",\"AAAAAX8RAAAAAuMFAADkBQAAAAJgDAAAYQwAAAAFhwwAAIgMAACJDAAAigwAAIsMAAAAAAAAAAIRBAAAEwQAAA==\"]ANg[\"AAAEMQIAAJACAAAyBwAANgcAAANiDAAAYwwAAGQMAAACmAEAAKgBAAA7MAAAAQAAewABAKQRewAABt4FAADfBQAALREAAC4RAAAoFAAAKRQAAAT+BwAAAAgAAD8IAABBCAAAOzAAAAEAABIABwAOBgEAegcAAL0JAQCHDAQA1gwAAGMRAwA3EgMAOjAAAAEAAAAAAAgAEAAAADoEOwQ+CEAIeQ9VEVYRVxFYEQUrBAAA+gUAAKAHAAChBwAA6BAAAAQxBAAAMgQAAKMTAACkEwAABP0HAAD/BwAAcw8AAHQPAAAEWAcAAH0MAAB/DAAAcg8AADswAAABAAAGAAMAEQQAABMEAACXEwQAAfgSAAAAAUMGAAA=\",\"AAAAAAAC4wUAAOQFAAAAAmAMAABhDAAAAegPAAAFhwwAAIgMAACJDAAAigwAAIsMAAAAAAAAAAIRBAAAEwQAAAAAA3EHAAA9EQAAPhEAAA==\"]Dc[\"\",\"AAAAADswAAABAAAHAAEAoQkHADswAAABAAAJAAIA4RAEADgRBAAAATcRAAA=\"]AHi[\"AAAAOjAAAAEAAAAAAAcAEAAAAJUBlwGkAaYBsQGyAf0P/g8EmwEAAK0BAACgCgAApAoAADowAAABAAAAAAAJABAAAACWAZwBnQGlAa4BrwENCw8LpROmEzswAAABAAAMAAMAUgUHAKMPAACLEAMAB6ABAADyEAAA9BAAAPYQAAD4EAAA+hAAALESAAA7MAAAAQAAFQAKAIsBAQCSAQAAhQwBAM8MAQD1DwMAeRABAIcSAwBLEwAAxRMBAA8UAQABxxMAAAAF8RAAAPMQAAD1EAAA9xAAAPkQAAAAAAAAAAABQwYAAA==\",\"AAABkAEAAAJaBQAAIBIAAAAAAAJpDwAAcRAAAAAAAAAAAAAAAAAENAcAADgHAADTDAAA1AwAAA==\",1]Fk[\"AAAABI0FAACjBwAARwgAAEERAAACogkAAFUMAAAB1hAAAAABUQgAAAH0AAAAAssPAAAbEwAAAWcHAAA=\",\"AAAAAY0FAAABmwEAAA==\"]Fk[\"AAAABNIFAACnBwAASwgAAEgRAAACpgkAAFkMAAAB2hAAAAF0AQAAAVMIAAAAAs0PAAAfEwAAAWsHAAA=\",\"AAAAAdIFAAABrQEAAA==\"]AEa[\"AAAAApMBAACfAQAAOzAAAAEAAAcAAQChCQcAAAT8BQAA/QUAAP4FAAArEgAAAAABxxMAAAAAAALFEAAAxhAAAA==\",\"AAAAADswAAABAAAQAAMAKQcAAKEJBwBUDAcAOzAAAAEAAAsABACIBwAAxxAAAOEQBAA4EQQAOzAAAAEAAA8ABQBSBQcAcQwCADQSAgBpEgAA3BMAADowAAABAAAAAAAMABAAAADyEPQQ9hD4EPoQLREuETcRWxFcEV0RXhFbEwRPEAAAUBAAAFEQAABSEAAAAAAF8RAAAPMQAAD1EAAA9xAAAPkQAAAAAAAAAAABQwYAAA==\",1]Ec[\"AAAAAAAAOzAAAAEAAAYAAgA/BwMARAcCADswAAABAAAGAAIAOgcEAIoJAQADLQQAAO8FAADwBQAA\",\"\"]Dg[\"AAAAAAAAAAABuxMAAAH6EwAAAAAAAAAAAAAB5gcAAA==\",\"AAAAAAABcxIAAAFJEwAA\"]Eo[\"AAAAAYsFAAABmgEAAAIlAAAAigAAAAHWDwAAAR0DAAAC7wAAAPAAAAA=\",\"AAABmQAAAAGLBQAAAQkTAAAAAUwMAAA=\"]Ic[\"AAAAAcoFAAADrAEAACMTAACeEwAAAlAAAACXAAAABmEBAABiAQAAEgQAAEIGAADjDwAA6RMAAAEqAwAA\",\"AAABmgAAAALKBQAADBMAAAABUAwAAAAAAAAAAAAAAAAAAAKbAAAAnAAAAA==\"]Ik[\"AAAAAmIFAACGEgAAAYUHAAABJgcAAAGjAAAAAS8RAAABtxMAAAItEgAA9hMAAAAAAAAAAAAAOjAAAAEAAAAAAAgAEAAAAAMGJAfgB2AIsA/HD/kPyRBnEQ==\",\"AAAAAWIFAAAAAW8SAAABRRMAAA==\"]Ck[\"AAAAAcABAAAAAAAAAbkTAAAB+BMAAA==\",\"AAAAAAABcRIAAAFHEwAA\"]Ck[\"AAAAAcEBAAAAAAAAAboTAAAB+RMAAA==\",\"AAAAAAABchIAAAFIEwAA\"]Kc[\"AAAAAAAABPYFAAD8BQAA/QUAAP4FAAAAOzAAAAEAAAkAAQALDAkAOzAAAAEAAA0AAQAbBA0ABXwMAABvDwAAcA8AAHEPAADnEAAAAAGBDAAAA34MAABzDwAAdA8AAAJ9DAAAcg8AAA==\",\"AAAAAAABxxAAAANxDAAAcgwAAHMMAAA=\"]Mg[\"AAAAAAAAAo0SAACOEgAAAAL1EgAA9hIAAAV6BwAANxIAADgSAAA5EgAAOhIAAAAC+gUAAOgQAAACMQQAADIEAAAAAVgHAAAAAAABQwYAAA==\",\"AAAAAALyBQAAyxMAAAAFABQAACMUAAAkFAAAJRQAACYUAAABWxMAAALoDwAAARQAAAAAAAAAAAAAAARTEAAAVBAAAFUQAABWEAAA\"]Bg[\"AAAAAAAAAAR8EQAAfREAAH0TAAB+EwAA\",\"\"]Bk[\"\",\"AAAAAXsRAAAAAAAAAAAAAAAAAAAAAAF9DwAA\"]Cc[\"AAAAAAAAAYUQAAABhhAAAA==\",\"AAAAAAACtwkAALgJAAA=\"]FHg[\"AAAAADswAAABAAAUAAoA8AEEABkEAAAGBgAAYggAAF4MAABXEAMAbhIAAHwTAACcEwEAAhQDADswAAABAADtARAAKQQAAC8EAABcBwAATgwDABUNWQHqDwAA7w8AAFwQAAB4EAAA1RAHADYRAACkEXsAMBIAADISAAD0EgAAVhMAADswAAABAAC4AA8AowAgAAIBbwB0AQ0AEgQAAPYFAABCBgAAPwcDAEQHAgBVBwEASgwDAG0PAAAnEwAARRMFAOkTAAD8EwAAOzAAAAEAAJ4AQAAYAxQALAQAADYEAQBBBAIA4QUAAPcFAQAQBgAAOgcEAEgHDABOCAUARAkBAIoJAQCfCQEAqgkBAGAMAQBvDAEAewwAABMNAQBqDwEAew8BALEPAQC0DwEAzg8AAPAPAQD6DwEAARAAAF0QAABrEAEAgxABAIYQAADtEAEANxEAAEIRAABEEQAARhEAAEkRAABLEQAATREAAFkRBQBoEQEAaxECAHwRAQAhEgEAfxIBALESAADlEgEA6hIBAA8TAQBMEwEAXBMBAGATAQB9EwEAhRMBAK0TAQC9EwEA2RMCAOQTAwDyEwMACBQAABYUAQAaFAEAHRQBACEUAQAoFAEAOzAAAAEAAI4AJQDEAD0AcgEBAIsBAQAQBAAALQQAADQEAADvBQEACAYBAP4HAAAACAAAPwgAAEEIAAALDAkAhQwBAM8MAQB3DwEAqw8BAOgPAAD1DwMAeRABAM8QAQDpEAEALhIAAHcSAQCHEgMA9RIBABYTAQBBEwEAVBMBAFcTAwC3EwUAxRMBAMoTAAD+EwEAARQAAA8UAwAfFAEAOzAAAAEAADEADQAbBA0ADgYBAHoHAAC9CQEAeAwAANYMAABvDgAAyg8DAGMRAwA3EgMAGhMHAFETAQD2EwUAOjAAAAEAAAAAABYAEAAAADoEOwRmB2cHaAdpB2oHawdsB20HPghACHwMbw9wD3EPeQ+PEJAQ5xCPEuETCRQHKwQAAPoFAADnDwAA6BAAAGERAABiEQAAfhIAAAMxBAAAMgQAAIEMAAA6MAAAAQAAAAAACQAQAAAAMAT8B/0H/wd+DHMPdA/FEMYQ5hAEWAcAAH0MAAB/DAAAcg8AADowAAABAAAAAAAHABAAAAARBBMEQweXE5gTmROaE5sTAAGADAAAAUMGAAA=\",\"AAAAAAA7MAAAAQAA3QABABUN3QAAOjAAAAEAAAAAAFkAEAAAADYENwROCE8IRAlFCZ8JoAmqCasJYAxhDG8McAwTDRQNag9rD3sPfA+xD7IPtA+1D/AP8Q/6D/sPaxBsEIMQhBDtEO4QQhFEEUYRSRFLEU0RWRFaEWgRaRF8EX0RIRIiEn8SgBLlEuYS6hLrEg8TEBNME00TXBNdE2ATYRN9E34ThROGE60TrhO9E74T2hPbE+QT5RPmE+cT8hPzE/QT9RMWFBcUGhQbFB0UHhQhFCIUKBQpFDswAAABAAAvABQAiwEBAAgGAQCFDAEAzwwBAKsPAQD1DwMAeRABAM8QAQDpEAEAdxIBAIcSAwD1EgEAFhMBAEETAQBUEwEAVxMDAMUTAQD+EwEADxQDAB8UAQAEvQkAAL4JAABREwAAUhMAAAACYREAAGIRAAAAAsUQAADGEAAAAAIRBAAAEwQAAA==\"]Ho[\"AAAAAT8RAAAAA/MFAACPCQAAKhIAADswAAABAAAMAAMARAQFAF0HBQCWEwAAAAP7BwAA6RAAAOoQAAABShAAAAAH8RAAAPMQAAD1EAAA9xAAAPkQAABhEQAAYhEAAAAB/AcAAA==\",\"\"]Lk[\"AAACMgIAAJECAAAAApsBAACtAQAAOzAAAAEAAAsAAwCcAQEArgEBANUQBwA7MAAAAQAABwABAFIFBwA6MAAAAQAAAAAABwAQAAAATghPCLEPsg/6D/sPWRFaEQACURMAAFITAAA=\",\"AAAAAakPAAAAAAAAAAAAAAAAAAAAAAWoDwAAqg8AALAPAACzDwAAUxMAAA==\"]AAg[\"AAAELwIAAI0CAACQCQAAkQkAAASRAQAAmQEAAJ4BAACrAQAAAjYCAACWAgAAAAA6MAAAAQAAAAAAEwAQAAAANgQ3BEQJRQlfEGEQYxBlEGYQ8hD0EPYQ+BD6EH8SgBIaFBsUHRQeFAL1EgAA9hIAAAWHDAAAiAwAAIkMAACKDAAAiwwAAAAF8RAAAPMQAAD1EAAA9xAAAPkQAAAAAAACpwEAAEMHAAA=\",\"AAAAAAAAAAAAAAAAAAAAAAAABEYJAABHCQAASAkAAEkJAAA=\"]BKo[\"AAADjgkAAOcSAADoEgAABY8BAACFCgAAexEAAOwSAADtEgAAOjAAAAEAAAAAAAcAEAAAAJoBrAGSCZMJawq4CuIKLxIBMBIAAAEnEwAAOjAAAAEAAAAAABEAEAAAAFAIUQhSCFMIaQ/wD/EPcRBCEUQRRhFJEUsRTRFME00T5BPlEwFLEwAAOzAAAAEAAAsAAgDKDwMAGhMHADswAAABAAAJAAMAZgcHAD4IAABACAAAAAAC/QcAAP8HAAA=\",\"AAAE6QUAAOoFAABgDwAAYQ8AADswAAABAAAWAAoAogcHAEARAQBDEQAARREAAEcRAQBKEQAATBEAACMSAQB4EwIAwxMBAAIjEwAAnhMAAAEqEgAAAAAAAAAAAAAAAAAAOjAAAAEAAAAAAG0AEAAAAIUBhgGIAYkB5gHnAe0B7gEYBBoEPARcBV8FMwc3B2QHZQeYB5kHgAmBCbEJsgldDF8MdAx1DHkMegyCDIMMZw9oD34PpA+lD8UPxg/5D0wQTRBpEGoQdhB3EHsQfBCBEIIQhxCIEL8QwBDJEMsQzBDSENMQ3RDeEN8Q4BBfEWARcxF0ESYSJxIoEikSaxJsEnkSehKDEoUSphKnEqgSqRKrEqwSrRKuEukS7hLvEvASBxMYExkTIhMoEykTKhMrEywTLRNDE0QTXhNfE2UTZhODE4QToROiE94T3xM=\"]Ac[\"AAAAAAEHAwAA\",\"\"]Ca[\"AAAAAAI2AgAAlgIAADswAAABAAAFAAEAdREFAA==\",\"\",1]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAAAlkHAABvBwAA\",\"AAAAAAACXhAAAGAQAAAAAl8QAABhEAAAAAI3EgAAOBIAAA==\"]Eo[\"AAAAAAAAAAAAAAAAAAAAAAAAAloHAABwBwAA\",\"AAAAAAACYhAAAGQQAAAAA2MQAABlEAAAZhAAAAACORIAADoSAAA=\"]Ck[\"AAAAAAAAAAAAAAAAAAAAAAAABWgAAACJAQAAOggAAFoIAABICQAA\",\"\"]Bg[\"AAAAAAAAAXUPAAAAAAAAAmERAABiEQAA\",\"\"]Ek[\"AAAAAVkAAAAABRcEAADgBQAAlgcAAHERAACgEwAAArIAAAB6DwAAAAJiEwAAthMAAA==\",\"AAAAAAABFQQAAA==\"]Ho[\"\",\"AAAAAAAAAAA7MAAAAQAACQABAAsMCQA7MAAAAQAADQABABsEDQAFfAwAAG8PAABwDwAAcQ8AAOcQAAAAAYEMAAAEfgwAAHMPAAB0DwAA5hAAAAN9DAAAfwwAAHIPAAAAAAGADAAA\"]Co[\"AAAAAAAAAAAAAAAAAALFEAAAxhAAAA==\",\"AAAAAAAAAAAAAAABXQgAAA==\"]Hk[\"AAADswEAAGgMAABrDAAAAYoFAAABmgEAAAQkAAAAiQAAAF4QAABgEAAAAdUPAAABHAMAAAPuAAAAMhEAADMRAAA=\",\"AAACswEAAGUMAAACOAQAAIoFAAABCBMAAAABSwwAAA==\"]Hk[\"AAADtAEAAGkMAABsDAAAAckFAAABrAEAAARPAAAAlgAAAGIQAABkEAAAAmABAADiDwAAASkDAAADLQQAADQRAAA1EQAA\",\"AAACtAEAAGYMAAADOQQAAMkFAAALEwAAAAFPDAAA\"]2ALg[\"AAAAAAFOEAAAAAA6MAAAAQAAAAAAEQAQAAAAoAEsBG8McAwTDRQNag9rD+0Q7hAhEiIS8hPzExYUFxQhFCIUAjQEAABLEwAAOzAAAAEAAAsAAgDKDwMAGhMHADswAAABAAAHAAEAZgcHAAAAAAACpwEAAEMHAAA=\",\"AAAH6wUAAOwFAABoDAAAaQwAAGsMAABsDAAAMRIAADowAAABAAAAAAAXABAAAABECEUInQmpCWoMbQxuDGMPZA9tEG4QbxC+ED8RUBFREVIRUxFUEU4TtBO1E8gTyRM7MAAAAQAA5AACAHcO4AAREwMAOzAAAAEAAE4AAgALAE0AexMAAAH8EwAAAAAEYxEAAGQRAABlEQAAZhEAAARVEQAAVhEAAFcRAABYEQAAAX4SAAAAAAAAAAAHQAQAAAMGAABjBwAAdA4AAMEQAADREAAAZxEAAA==\"]Cc[\"AAAAAAJuCgAAuQoAAAAAADswAAABAAAFAAEAYhIFAA==\",\"\"]BMo[\"\",\"ADswAAABAAAFAAIACwQEAP0TAAACWwcAAHkHAAA6MAAAAQAAAAAACgAQAAAAwAHBAfUF1QwsEm0SgRLdE+gTBhQVFDowAAABAAAAAAAZABAAAADwAfEB8gHzAfQBGQT0BfkFKQdXB4UHtQnUEC8SbhLzEnwTnBOdE+ATAhQDFAQUBRQYFBwUOzAAAAEAAAsBDwAXBAAA8wUAAFwHAAB4BwAAiAcAAPMNewBcEAAA1RAHADYRAACkEXsAMBIAADISAACwEgAA9BIAABUTAAA6MAAAAQAAAAAAGgAQAAAA9gX8Bf0F/gVVB1YHXQdeB18HYAdhB2IHFgwXDBgMGQx1D3oPhRDsECsSJxNjE2QT2BPpEwcUOzAAAAEAADcAEQAYAxQANQQAAEEEAgDeBQEA4QUAAPcFAQAQBgAASAcMAFAIAwAVDAAAewwAAM4PAAABEAAAhhAAALESAADZEwAACBQAADswAAABAABRAAoAxAA9AHIBAQA0BAAA/gcAAAAIAAA/CAAAQQgAAGISBQC3EwUAyhMAADswAAABAAAUAAYAGwQAANYMAABvDgAAyg8DABoTBwD2EwUAOzAAAAEAABEACAA6BAEAZgcHAD4IAABACAAAbw8CAHkPAADnEAAAjxIAAAKgBwAAoQcAAAMxBAAAMgQAAIEMAAAE/QcAAP8HAAB+DAAA5hAAAAAFlxMAAJgTAACZEwAAmhMAAJsTAAA=\"]Bc[\"AAAAAAAAAAAAAAACYREAAGIRAAA=\",\"\"]Kc[\"AAAAAAHyEgAAADswAAABAAAGAAIAXQcFAOwQAAAC4QUAAAEQAAABNAQAAAADjxAAAJAQAACPEgAAAecPAAA=\",\"AAAAAAABLwQAADswAAABAAAFAAEARAQFAAAAAAAAAAAAAAAAB+8BAABbBQAAXgUAAHIHAABzBwAAdAcAAHUHAAA=\"]Do[\"AAAAAAABFQAAAAAAAcgAAAAAAAAAAAAAAAACWwUAAGQHAAA=\",\"AAAAAAAAAAACdw8AAHgPAAA=\"]Dk[\"AAAAAAABKwAAAAEIAQAAAAAAAAAAAAAAAAACXgUAAGUHAAA=\",\"AAAAAAAAAAABEAQAAA==\"]Ac[\"AAABPwIAAA==\",\"\"]Fg[\"AAAABI8FAACkBwAASAgAAEMRAAADowkAAFYMAAADFAAAAdcQAAAAAAH2AAAAARwTAAABaAcAAA==\",\"AAAAAY8FAAAAAZwBAAA=\"]Fg[\"AAAABNQFAACoBwAATAgAAEoRAAADpwkAAFoMAAAFFAAAAdsQAAABdgEAAAAAASATAAABbAcAAA==\",\"AAAAAdQFAAAAAa4BAAA=\"]Bk[\"\",\"AAAAAAAAAAA7MAAAAQAAPwACAMQAPQByAQEA\"]Ck[\"\",\"AAAAAAEpBwAAOzAAAAEAAAkAAgCIBwAAigcIAAHcEwAAAVsTAAA=\"]Bo[\"\",\"AAAAAAAAAAAAAAAAAqMTAACkEwAAAAAAAfgSAAA=\"]Eo[\"\",\"AAAAAAA7MAAAAQAABQABAG8SBQA7MAAAAQAABQABAEUTBQAAOzAAAAEAAAUAAQC3EwUAOzAAAAEAAAUAAQD2EwUA\"]Ck[\"AAACPgIAAFACAAA=\",\"AAAAAAAAAmgTAABpEwAAAAACYxEAAGQRAAA=\"]Cg[\"\",\"AAAAAAMIEwAACRMAAAoTAAAABEoMAABLDAAATAwAAE0MAAA=\"]Eg[\"AAAAAZQFAAAAASgAAAAAAAIAAQAAAQEAAA==\",\"AAA7MAAAAQAACgABAHICCgAClAUAAOoTAAAAAAGNEgAA\"]Eo[\"AAAAAdEFAAAAAVcAAAAAAAJyAQAAcwEAAA==\",\"AAA7MAAAAQAACgACAPICAgD2AgcAAtEFAADrEwAAAAABjhIAAA==\"]Dg[\"AAAB1wIAAAHPBQAAAAFVAAAAAmsBAABsAQAA\",\"AAAB5QIAAAHPBQAAAAAAAAEtBAAA\"]Eo[\"AAAAAAAAAnsBAAB8AQAA\",\"AAAAAAAAB9gTAAAAFAAABxQAACMUAAAkFAAAJRQAACYUAAAC2RMAAAgUAAABARQAAA==\"]Bk[\"AAAAAAAAAS0BAAA=\",\"AAABrwIAAAAAASkEAAA=\"]Bo[\"AAAAAdgFAAAAAAF9AQAA\",\"AAAAAdgFAAABgRMAAA==\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAdEMAAA=\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAzsIAABbCAAASQkAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAkAEAAA8CAAA\",\"\"]Cc[\"AAAAAAAAAAKKCQAAiwkAAAAAAAAAAAACpwEAAEMHAAA=\",\"\"]Fo[\"AAAAAAAC8wUAADISAAAAAAAAAAAAAAAAAAAEYQgAAH4PAACJEAAAfhEAAA==\",\"AAECCAAAAAAAAAAAAAAAAAAAAAAAAAKKEAAAMREAAA==\"]Bk[\"AAAAAfUFAAAAAAF1DwAAAc4PAAA=\",\"AAEzCAAA\"]Bg[\"AAAAAAAABIsQAACMEAAAjRAAAI4QAAA=\",\"\"]Ag[\"AAAAApMBAACfAQAA\",\"\"]Dg[\"AAAAAAAAAAAAAr0JAAC+CQAA\",\"AAAAAAAAAAAABYcMAACIDAAAiQwAAIoMAACLDAAA\"]AGc[\"AAAAAAKYAQAAqAEAAAAABN4FAADfBQAALREAAC4RAAAE/gcAAAAIAAA/CAAAQQgAADswAAABAAALAAQADgYBAIcMBADWDAAAYxEDADowAAABAAAAAAALABAAAAA6BDsEPghACHkPjxCQEFURVhFXEVgRjxIEKwQAAKAHAAChBwAA5w8AAAQxBAAAMgQAAKMTAACkEwAABTAEAAD9BwAA/wcAAHMPAAB0DwAAA30MAAB/DAAAcg8AADowAAABAAAAAAAIABAAAACnAREEEwRDB5cTmBOZE5oTmxMB+BIAAAGADAAA\",\"AAAAAX8RAAAAAuMFAADkBQAAAAJgDAAAYQwAAAAAAAAAAAACEQQAABMEAAA=\"]Hm[\"\",\"AAAAAAA7MAAAAQAABQABAIwMBQACZwwAANwTAAAE+xAAAPwQAAAvEQAAWxMAAAVPEAAAUBAAAFEQAABSEAAASxMAAAEtEgAAAAF+EgAAAAH8BwAAAAGnAQAAAAABQwYAAA==\",1]ANc[\"AAACoQEAAKoBAAAGkQEAAJkBAACeAQAAqwEAAOwSAADtEgAABPQFAAC1CQAAbAoAALoKAAA7MAAAAQAABQABAIwMBQACYxMAAGQTAAA6MAAAAQAAAAAACQAQAAAAigmLCWsQbBD7EPwQ5RLmEtoT2xM6MAAAAQAAAAAACQAQAAAAEAT+BwAIPwhBCHcPeA/oD/4T/xMAAj4IAABACAAA\",\"AAAAOjAAAAEAAAAAABAAEAAAAIcB3AfdB94H3wdjCGQIkgzrD+wPgBDvEPAQexJ8Eq8S4xMDswkAAE4QAACqEgAAOzAAAAEAAAcAAwCMDAUAghIAAIQSAAAAAvsQAAD8EAAAAAIOBgAADwYAAAACKwQAAOcPAAAAAzAEAABzDwAAdA8AAAN9DAAAfwwAAHIPAAAAAAKADAAA2wwAADowAAABAAAAAAALABAAAACKAT0EPgRdBWAFIgcjB5oH4AdgCGEIxw8=\"]Bg[\"AAAAAAAAAAAAAScEAAA=\",\"AAAAAUAGAAA=\"]Bk[\"AAAAAAAAADswAAABAAANAAIAEAYAAEgHDAA=\",\"\"]Cc[\"AAABhQkAAAAB9AEAAAAAAAEQBAAA\",\"AAAAAAAAAAEsBAAA\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAl4AAABcDwAA\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAUMHAAA=\",\"\"]Cm[\"AAAAAAAAA/wFAAD9BQAA/gUAAA==\",\"AAAAAAAAAAAAAAABXQgAAA==\",1]Bg[\"AAAAAAAAADswAAABAAAUAAEAGAMUAA==\",\"\"]Ck[\"\",\"AAAAAASsCQAArQkAAK4JAACvCQAAAAAAAAAAAAAAAAAAASMQAAA=\"]Bg[\"AAAAAAAAAAAAASIEAAA=\",\"AAAAAVQIAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAV0AAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAZsAAAA=\",\"\"]BMi[\"AAAAAAABsBIAAAACoAEAALESAAA6MAAAAQAAAAAAGgAQAAAAkgEIBgkGqw+sD88Q0BB3EngSFhMXE0ETQhNUE1UTVxNYE1kTWhNiE7YT/hP/ExEUEhQfFCAUOzAAAAEAAAYAAwC9CQEAyg8DAMcTAAAC4RMAAAkUAAAAAAABWAcAAAAAAAFDBgAA\",\"AAAFmAkAAJkJAACaCQAAmwkAAJwJAAAEYgwAAGMMAABkDAAAIBIAADswAAABAAARAAgAVQgAAEMJAACsCQMAswkAAEUQBACqEgAAsxIAABETAwA7MAAAAQAAIgAOALwBAAC+AQAAFQQAACkEAAAvBAAAigcIAIwMBQBsDwAAeBAAAOEQBAA4EQQA8RIAAFYTAACfEwAAOzAAAAEAACMACQASBAAARAQFAEIGAABeCAAAbQ8AANEPEwBpEgEAaBMBAGsTAQA7MAAAAQAACgAFAF0QAAD7EAEAWxEDAGsRAgCCEwAAOzAAAAEAAAwABgAQBAAAdw8BAE8QAwAyEQMAYhMAALYTAAAENxIAADgSAAA5EgAAOhIAAAN8DAAA4RMAAAkUAAAEKwQAAF0IAADnDwAA6BAAAAAAAVgHAAABpwEAAAAAOjAAAAEAAAAAAB0AEAAAAJ0AngCfAKAAOQdHB5MHlAeVB34JsAm5CboJuwm8Cb8JwAm2D88P0A/yD/MP9A99EH4QfxBqESUShxMnFA==\",1]Co[\"AAAAAAAAAAAAAAAAAALFEAAAxhAAAA==\",\"AAAAAAAAAAAAAAABXQgAAA==\"]Jg[\"AAAAAXEFAAAABxYAAACGAAAAvAEAABUEAABsDwAAdhEAAHkRAAAC0g8AAGkSAAACGQMAAEkHAAACyQAAAMoAAAAAAT4IAAAAAAH9BwAA\",\"AAEHCAAAAAJZAAAAcQUAAAI2AgAAVQgAAAJ2EQAAeREAAAABOwcAAA==\"]Og[\"AAAAAZgFAAAABi0AAACOAAAAvgEAAHgRAAB6EQAA8RIAAAcLAQAADAEAAG0PAADaDwAA5g8AAHAQAABqEgAABCEDAABOBwAAewwAAIITAAABLhIAAAFvDgAAA0AIAADhEwAACRQAAAAAAf8HAAA=\",\"AAEcCAAAAAGYBQAAApYCAADyBQAAAngRAAB6EQAAAUAHAAAAAAF4DAAAAAF+EgAAAAAAAAAAOzAAAAEAAAUAAQBdAAUA\"]Bo[\"\",\"AAAAAAAAOzAAAAEAAJ4AAwCjACAAAgFvAHQBDQA=\"]CDm[\"\",\"AAA7MAAAAQAA3QABAC0L3QA7MAAAAQAA5AAMAD0KLQBtCgAAbwowAKEKAgClChIAuwoeANsKBgDjCigADgsAABELGwBoEgAA6hMBADowAAABAAAAAAATABAAAAD5BUEGKQeSCZMJawpsCm4KoAqkCrgKuQq6CtoK4goMCxALCBMJEwoTOjAAAAEAAAAAABIAEAAAABcE4AWIB5YHtwm4CQ0LDwtxEW8ScBJxEnIScxJ0EhUToBOlE6YTOjAAAAEAAAAAACkAEAAAAFUHVgdeCBYMFwwYDBkMSgxLDEwMTQxnDHoPow/mD3AQhRCLEIwQjRCOEOwQjRKOEkUTRhNHE0gTSRNKE2gTaRNrE2wT2BPcEwAUBxQjFCQUJRQmFDowAAABAAAAAAAcABAAAAAsBEEEQgRDBPcF+AU6BzsHPAc9Bz4HewwBEF8QYRBjEGUQZhCGEPsQ/BA3EWsRbBFtEVsTghPZEwgUOzAAAAEAAFkADwDEAD0AcgEBABAEAAAtBAAANAQAAO8FAQD7BwAAdw8BAOgPAAAuEgAAYhIFAGITAAC2EwYAyhMAAAEUAAA7MAAAAQAAEQAIAA4GAQB4DAAA1gwAAG8OAABKEAAAYxEDAFETAQD2EwUABnkPAACPEAAAkBAAAI8SAADhEwAACRQAADowAAABAAAAAAALABAAAAArBPoFoAehB10I5w/xEPMQ9RD3EPkQfhIEMQQAADIEAACjEwAApBMAAAT8BwAA/QcAAP8HAADmEAAAAn8MAAByDwAAOjAAAAEAAAAAAAgAEAAAAKcBEQQTBEMHlxOYE5kTmhObEwH4EgAAAAFDBgAA\",1]Le[\"\",\"AAAAArABAAAnBwAAA4YHAABlDwAAZg8AAAN4BwAAghIAAIQSAAA6MAAAAQAAAAAABwAQAAAAdQ8rEjQSNRI2EmMTZBOWEwI1BAAAFQwAAAGSAQAAAccTAAAEbw8AAHAPAABxDwAA5xAAAAABgQwAAAQwBAAAfgwAAHMPAAB0DwAAAX0MAAAAAAGADAAA\",1]Fo[\"\",\"AAAAOjAAAAEAAAAAAAcAEAAAAMABwQEsEoES3RPoEwYUFRQChQcAAE4QAAAEJgcAAI8JAACmDwAAKhIAAAEnEwAAAS8RAAABSxMAAA==\"]Cg[\"\",\"AAAAAwsTAAAMEwAADRMAAAAETgwAAE8MAABQDAAAUQwAAA==\"]Bk[\"\",\"AAAAAAAAOzAAAAEAAAYAAgA/BwMARAcCAA==\"]Fc[\"AAAAAakBAAAAAAAABAgGAAAJBgAAqw8AAKwPAAA=\",\"AAA7MAAAAQAAOwABAJMMOwAAAAAAAAAAAAAAAAAAAAABdgcAAA==\"]Ao[\"\",\"AAA7MAAAAQAA3QABAGUI3QA=\"]AAk[\"AAAERQIAAFcCAABcAgAAYA8AAAFvBQAAA/MSAAAYFAAAHBQAAAMTAAAAhQAAAHURAAAB0Q8AADowAAABAAAAAAAMABAAAAAYA0EEQgTeBd8F9wVIB2gRXBOFE60T5hP0EwLEAAAAxQAAAA==\",\"AAEGCAAABy0CAAAvAgAAMAIAADECAAAyAgAAkAkAAOcSAAABbwUAAASSCQAAawoAAGwKAABuCgAAAXURAAABSgwAAAM6BwAAaxEAAGwRAAAAAAABXQgAAAAAAAAAAAFZDwAA\"]AAg[\"AAAEtAIAANkCAADgAgAAYQ8AAAGVBQAAAAQpAAAAjAAAAHcRAAD0EgAABAQBAAAFAQAA2A8AAOkTAAA6MAAAAQAAAAAACgAQAAAAHwNDBOEF+AVNB2kRXROGE64T5xP1EwABbw4AAA==\",\"AAEbCAAAOzAAAAEAAAYAAwCNAgQAkQkAAOgSAAABlQUAAASTCQAAuAoAALkKAAC6CgAAAk4MAAB3EQAAAj8HAABeCAAAAW0RAAAAAAAAAAAAAAAAA1sPAABcDwAAXQ8AAA==\"]Cg[\"AAAAAAAAAAAAAAAAATEEAAAAAAERBAAA\",\"AAAAAAAAAAEtEQAA\"]Cg[\"AAAAAAAAAAAAAAAAATIEAAAAAAETBAAA\",\"AAAAAAAAAAEuEQAA\"]Fo[\"AAA7MAAAAQAACwAEAEAQBAAOEwAArxMEABkUAAA=\",\"ADswAAABAAAJAAIA4QcEAOASBAA7MAAAAQAACwAEAEAQBAAOEwAArxMEABkUAAA=\"]Ho[\"AAAAAAAAAAA7MAAAAQAACQABAAsMCQA7MAAAAQAADQABABsEDQAFfAwAAG8PAABwDwAAcQ8AAOcQAAAAAYEMAAAEfgwAAHMPAAB0DwAA5hAAAAN9DAAAfwwAAHIPAAAAAAGADAAA\",\"\"]Cc[\"AAAAApUBAADvEAAAAAAAAAGFDAAAAAE6BAAAAaAHAAA=\",\"\"]Cc[\"AAAAAqQBAADwEAAAAAAAAAGGDAAAAAE7BAAAAaEHAAA=\",\"\"]AAo[\"AAAAAvkSAAD6EgAAAAWcAQAAnQEAAK4BAACvAQAANhEAADswAAABAAALAAMAUgUHAPYFAABxDAIAOjAAAAEAAAAAAAcAEAAAAOEFUAhRCFIIUwh7D3wPzg8GMhEAADMRAAA0EQAANREAAMoTAAABFAAAOzAAAAEAAA0ABAB4DAAAbw4AAMoPAwAaEwcAOzAAAAEAAAcAAQBmBwcAAugQAAB+EgAAAAH8BwAAAVgHAAAAAAABQwYAAA==\",\"AAAAA7YBAAC3AQAAuAEAAAABeBAAAA==\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAC7QUAAHsHAAA=\",\"AAAAAAAAAAJbEQAAXBEAAAAAAAAAAAAAAAACWQcAAG8HAAA=\"]Ek[\"AAAAAAAAAAAAAAAAAAAAAAAC7gUAAH0HAAA=\",\"AAAAAAAAAAJdEQAAXhEAAAAAAAAAAAAAAAACWgcAAHAHAAA=\"]Ak[\"\",\"AAAAAALIDwAAyQ8AAA==\"]Eo[\"AAAABJEFAAClBwAASQgAAEURAAACpAkAAFcMAAAB2BAAAAAAAfgAAAABHRMAAAFpBwAA\",\"AAAAAZEFAAAAAZ0BAAA=\"]Eo[\"AAAABNYFAACpBwAATQgAAEwRAAACqAkAAFsMAAAB3BAAAAF4AQAAAAABIRMAAAFtBwAA\",\"AAAAAdYFAAAAAa8BAAA=\"]Bg[\"AAAAAAAAAAAAASEEAAA=\",\"AAAAAbYJAAA=\"]Ag[\"AAAClAEAAKMBAAA=\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAJ+DAAA5hAAAA==\",\"\"]Ag[\"\",\"AAACZxAAAGgQAAA=\"]Bc[\"AAAAAAAAAAAAAS0SAAA=\",\"AAFnAAAA\"]Dg[\"AAAAArYBAAC3AQAAAAAD/AUAAHEMAAA0EgAAAAGSAQAAAccTAAA=\",\"AAAAASASAAA=\"]Hg[\"AAAAAVARAAABERMAAANeEAAA4hAAADkRAAABaBMAAAFbEQAAAU8QAAACYxEAADcSAAABVREAAAAAAAABmBMAAA==\",\"AAAAAAAAAALyEAAA9BAAAAAAAALxEAAA8xAAAA==\"]Ig[\"AAAAAVMRAAABExMAAANiEAAA5BAAADsRAAABaxMAAAFdEQAAAVEQAAACZREAADkSAAABVxEAAAAAAAABmhMAAA==\",\"AAAAAAEwEQAAAAAD9hAAAPgQAAD6EAAAAAAAA/UQAAD3EAAA+RAAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAmYAAABdDwAA\",\"\"]Cc[\"AAAAAYAQAAABIxMAAAACEgQAAEIGAAA=\",\"AAAAAAFiCAAA\"]Ek[\"AAAAAXYFAAAAARgAAAAAAAHPAAAAAAAAAAAAAAAAAl0FAAAiBwAA\",\"AAEMCAAAAAF2BQAAAAAAAAAAAY8QAAA=\"]Ek[\"AAAAAaQFAAAAATUAAAABHAEAAAAAAAAAAAAAAAAAAmAFAAAjBwAA\",\"AAEjCAAAAAGkBQAAAAAAAAAAAZAQAAA=\"]Be[\"AAAAAAA7MAAAAQAAewABAKQRewA=\",\"\",1]Bg[\"AAAAAAAAAAAAASQEAAA=\",\"AAAAAUkMAAA=\"]Ec[\"AAAAAAAAAAAAAAAAAAL9BwAA/wcAAAFYBwAAAqcBAABDBwAA\",\"AAAAAAAAAAAAAAAAAAAAAacBAAA=\"]Dk[\"AAAAAAAAAAABvBMAAAH7EwAA\",\"AAAAAAABdBIAAAFKEwAAAAAAAAAAAAAAAAAB5gcAAA==\"]Dc[\"AAAAAbwFAAAAAAFGAQAAAVEHAAAAAAAAAAAAAAAAAe8BAAA=\",\"AAAAAbwFAAA=\"]ABc[\"AAAAA48BAAB+CgAAexEAAANXBwAA2goAANQQAAAAADowAAABAAAAAAANABAAAACfCaAJqgmrCbQPtQ+DEIQQ6hLrEg8TEBNgE2ETOzAAAAEAAA8ABwDPEAEAYhIFABYTAQBiEwAAthMAABEUAQAfFAEAAALhEwAACRQAAA==\",\"AAAAA4IBAACNAQAASxAAAARFEAAARhAAAEcQAABIEAAAArwBAAC+AQAAAAACYhMAALYTAAAAAuETAAAJFAAAAAAAAAAAAAS9AQAAvwEAAIIJAAB+EQAA\"]Bk[\"AAAAAAGFBwAA\",\"AAAAAAAAAAEvEQAAAAEtEgAA\"]Hg[\"AAAABWcFAAAFBgAAQAYAANUMAAB7EgAAAmYPAADgEwAAAngHAACwEgAAAqwAAAArEgAAAd8FAAAB+wcAAAFKEAAA\",\"AAAAAmcFAAAnBwAAAYYHAAAAAAABkgEAAAHHEwAA\"]Gc[\"AAAAAnwSAAB6EwAAAS4HAAABXAcAAAEDAQAAAl0QAACxEgAAAAF6BwAAAAH6BQAAAAH8BwAAAVgHAAAAAAABQwYAAA==\",\"AAAAAAAAAAGgAQAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWUAAAA=\",\"\"]Fc[\"AAADWwcAAHkHAADDDwAABG0MAAB0EAAAcBEAAMgTAAAE8QEAAPkFAABBBgAArgkAAAACrgAAAKMPAAA=\",\"AAABzRAAAA==\"]Fc[\"AAAABG4MAAB1EAAAchEAAMkTAAABrwkAAAFcBwAAAUgBAAAAAAF6BwAAAAH6BQAAAAAAAAAAAUMGAAA=\",\"AAABzhAAAA==\"]Dg[\"AAAAAcEFAAAAAUkAAAABUQEAAA==\",\"AAAAAcEFAAAAAAAAAAAAAAAAAAAAAAFoAAAA\"]Bk[\"AAAAAAHwAQAAAAAAAAEdBAAA\",\"AAAAAXYMAAA=\"]Cc[\"AAAAAAFVCAAAAAAAAAEeBAAA\",\"AAAAAAACdwwAAH0SAAA=\"]Dk[\"\",\"AAAAADswAAABAAATAAEA5wcTADswAAABAAATAAEAhQATADswAAABAAATAAEA0Q8TAA==\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWMAAAA=\",\"\"]Ak[\"\",\"AAAAAALlDwAAgRMAAA==\"]Ag[\"\",\"AAAAAAABnxMAAA==\"]Fg[\"AAAAAdkFAAAAAAF/AQAAAAAAAAAAATAEAAAAAAABgAwAAAafAAAAigEAAOkBAABHBwAAmgcAACUSAAA=\",\"AAEyCAAAAAHZBQAA\"]Ho[\"AAAEmQAAADACAADpBQAAZQwAAAGMBQAAAAImAAAAiwAAAAHXDwAAAh4DAABMBwAAAvEAAADyAAAA\",\"AAABXAIAAARaAAAAWwAAAFwAAACMBQAAApoBAAAKEwAAAAFNDAAAAT4HAAA=\"]Kk[\"AAAEmgAAAI4CAADqBQAAZgwAAAHLBQAAAARRAAAAmAAAAOoPAADvDwAAA2MBAABkAQAA5A8AAAIrAwAAUwcAAA==\",\"AAAB4AIAAALLBQAADRMAAAGsAQAAAVEMAAADEgQAAEIGAABFBwAAAAAAAAAAAAAAAAAEYwAAAGQAAABlAAAAZgAAAA==\"]Ak[\"AAAAAAL/DwAAABAAAA==\",\"\"]Ao[\"AAAAAAAAAAACiwEAAGISAAA=\",\"\"]Ao[\"AAAAAAAAAAACjAEAAGUSAAA=\",\"\"]Dc[\"AAAAAAAAAAAB8wAAAAAAAAAAAAAAAAWdAAAAPQQAAJMHAACtDwAAfRAAAA==\",\"\"]Fc[\"AAAAAAAAAWUBAAAAAAAAAAAAAAAAAAWeAAAAPgQAAJQHAACuDwAAfhAAAA==\",\"AAAAAAAAAAAAAXoHAAAAAvoFAADoEAAA\"]Fc[\"AAAAAdoFAAAAAAGAAQAAAjUEAAAVDAAAAAAAAAGBDAAAAAAAAAAFoAAAAJUHAAB/CQAArw8AAH8QAAA=\",\"AAAAAdoFAAA=\"]Fk[\"AAAAAXIFAAAAAAAAAcsAAAAAAAAAAAAAAAADhQEAAFwFAABdDAAA\",\"AAEICAAAAAFyBQAAAAAAAAAAAAAAAAAAAAACmwcAAJ0HAAA=\"]Fk[\"AAAAAZ4FAAAAAAEUAQAAAAAAAAAAAAAAAAADhgEAAF8FAABfDAAA\",\"AAEfCAAAAAGeBQAAAAAAAAAAAAAAAAAAAAACnAcAAJ4HAAA=\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAH4EgAA\",\"\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAWQAAAA=\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAl8AAABuDwAA\",\"\"]Bg[\"AAAAAAAAAAAAASMEAAA=\",\"AAAAARINAAA=\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAZwAAAA=\",\"\"]Dk[\"AAAAAY4FAAABmwEAAAABUwUAAAFCEQAAAfUAAAA=\",\"AAEVCAAAAAGOBQAAAAAAAUIRAAA=\"]Dk[\"AAAAAdMFAAABrQEAAAACdQEAAFcFAAABSREAAA==\",\"AAEuCAAAAAHTBQAAAAAAAUkRAAA=\"]Bk[\"AAAAAAAAAAAAAR8EAAA=\",\"AAAAAAAB4AUAAA==\"]Hc[\"AAAAAAABpg8AAAGWEwAAAAG4EwAAAfcTAAAAAAAAAAAAADowAAABAAAAAAANABAAAABjB34Juwl0DrMPtg/yD8EQ0RBqEYMShRJTE4cT\",\"AAAAAAABcBIAAAFGEwAA\"]Ak[\"AAAAAAKcEwAAnRMAAA==\",\"\"]Cg[\"AAAAAa8SAAABswkAAAEvBAAAAAABNAQAAA==\",\"AAAAAAFeDAAA\"]Ag[\"\",\"AAAAAAAAAUYHAAA=\"]Ag[\"AAAAAAAAAAFUBwAA\",\"\"]Dk[\"AAAAAAAAOzAAAAEAAJ4AAwCjACAAAgFvAHQBDQAAOzAAAAEAAD8AAgDEAD0AcgEBAA==\",\"\"]Gg[\"AAAAAcwFAAAAAlIAAAB7EwAAA2YBAABnAQAA/BMAAAEsAwAAAAF4DAAAAAF+EgAAAAABWAcAAAAAAAJ8BwAAsAkAAA==\",\"AAAAAcwFAAAAAAFwEAAA\"]Dk[\"AAAAAYIFAAAAAR0AAAAAAUoHAAAC3wAAAOAAAAA=\",\"AAAAAoIFAACFCgAAAAAAATwHAAA=\"]Dk[\"AAAAAbYFAAAAAUAAAAACOQEAADoBAAABTwcAAA==\",\"AAAAAbYFAAAB4goAAAABQQcAAA==\"]Ck[\"AAAAAesPAAAAAAAAAv4HAAA/CAAA\",\"AAAAAAAAAAACTxAAAFAQAAA=\"]Ck[\"AAAAAewPAAAAAAAAAgAIAABBCAAA\",\"AAAAAAAAAAACURAAAFIQAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAsoQAAAzEgAA\"]Ek[\"AAAAA2MIAAAjEgAAeBMAAAAAAAAAAAE+CAAAAAAB/QcAAA==\",\"AAAAAAAAAAJbEQAAXBEAAAJPEAAAUBAAAA==\"]Ek[\"AAAAA2QIAAAkEgAAeRMAAAAAAAAAAAFACAAAAAAB/wcAAA==\",\"AAAAAAAAAAJdEQAAXhEAAAJREAAAUhAAAA==\"]Eg[\"AAAAAaoFAAAAATwAAAACJwEAACgBAAA=\",\"AAAAAaoFAAAAAAAAAAF4DAAAAAF+EgAAAAAAAAAAAeYFAAA=\"]Ac[\"\",\"AAAAAAHlDwAA\"]Cc[\"AAABrwIAAAGbBQAAAAEvAAAAAQ8BAAA=\",\"AAAAAZsFAAA=\"]Gg[\"AAAAAXQFAAAAARcAAAAAAAHNAAAAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAAL0B7QFnD6gPaRCBEKYSGBMoE0MT\",\"AAEKCAAAAAF0BQAAAAFsDwAA\"]Ho[\"AAAAAaAFAAAAATIAAAABFgEAAAAAAAAAAAAAAAAAOjAAAAEAAAAAAAkAEAAAAL8B7gFoD6oPahCCEKcSGRMpE0QT\",\"AAEhCAAAAAGgBQAAAAABbQ8AAAAAAAAAAAAAAAAAAW4PAAA=\"]Gk[\"AAACFgIAAB0CAAABagUAAAACDgAAAIwHAAACtwAAALgAAAA=\",\"AAACGAIAABkCAAABagUAAAAAAAACdw8AAHgPAAAAAAIrBAAA5w8AAAAB5hAAAAF/DAAA\"]Do[\"AAAAAaIFAAAAAjMAAACPAAAAAxgBAAAZAQAA2w8AAAEiAwAA\",\"AAAAAaIFAAAAAAAAARAEAAA=\"]Ck[\"AAAAAn8TAACAEwAAAAAAAAAAAAABgQwAAA==\",\"AAAAAAABxxAAAA==\"]Co[\"AAAAAAABeAcAAAM0EgAANRIAADYSAAAAAZIBAAA=\",\"AAAAAAABpg8AAA==\"]JMa[\"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\",1]Eo[\"AAAAAAA7MAAAAQAABQABAG8SBQA7MAAAAQAABQABAEUTBQAAOzAAAAEAAAUAAQC3EwUAOzAAAAEAAAUAAQD2EwUA\",\"\"]Ck[\"AAAAAAAAAfYFAAAAAAEbBAAA\",\"AAAAAAAAA3EMAAByDAAAcwwAAA==\"]Cc[\"\",\"AAAAAAAEFwQAAJYHAABxEQAAoBMAAAAAAmITAAC2EwAA\"]Fc[\"AAAAAZ0FAAAAATEAAAACEgEAABMBAAA=\",\"AAEeCAAAAAGdBQAAAAAC5g8AAHAQAAACewwAAIITAAAAAALhEwAACRQAAA==\"]Eo[\"AAAAAW4RAAABrAkAAAACpwAAAGcMAAABNxEAAAABIAQAAA==\",\"AAAAAAFBBgAAAAJnDAAAow8AAAAB+wcAAAFKEAAA\"]Dk[\"AAAABiwSAACBEgAA3RMAAOgTAAAGFAAAFRQAAAAAAAABSxMAAA==\",\"AAAAAAAAAAEvEQAA\"]A@g[\"AAAAOjAAAAEAAAAAAA8AEAAAADgEZAUEBioHVAi2CUkMdgySDBIN/A/rEG8RbRJOE+MTOjAAAAEAAAAAAAkAEAAAAK0J5Q9JEC8SqhLyEvMSgRMYFBwUOjAAAAEAAAAAAAgAEAAAALwBFQR3DGwP4RA4EX0SFROfEzowAAABAAAAAAAHABAAAACoAOwQaRLYEwAUBxQjFCUUAd4FAAAAAAAAAAAAAZcTAAA=\",\"AAAAAWQFAAABQwkAAAABZwwAAA==\"]ACk[\"AAAAOjAAAAEAAAAAAAgAEAAAADkEnQlqDGMPqQ++EFIRtBO1EzowAAABAAAAAAAIABAAAAAZBPIFBgZiCF4MMBFuEnwTnhM6MAAAAQAAAAAACgAQAAAAvgEpBOoP7w9cEHgQNhEwEvES9BJWEzowAAABAAAAAAAHABAAAAACAW0P5g9wEGoS6RMkFCYUBeEFAAB7DAAAghMAANkTAAAIFAAAAy4SAADKEwAAARQAAAJ4DAAAbw4AAALhEwAACRQAAALoEAAAfhIAAA==\",\"AAAAAAAAAAAAAAAAAAH8BwAAAAAAAAFDBgAA\"]Ho[\"AAAAA6IHAABGCAAAQBEAAAOhCQAAVAwAAAIUAAAB1RAAAAABUAgAAAACyg8AABoTAAABZgcAAA==\",\"AAAAAARUDAAAVQwAAFYMAABXDAAAAAVSBQAAUwUAAFQFAABVBQAAaRIAAA==\"]Ho[\"AAAAA6YHAABKCAAARxEAAAOlCQAAWAwAAAQUAAAB2RAAAAABUggAAAACzA8AAB4TAAABagcAAA==\",\"AAAAAARYDAAAWQwAAFoMAABbDAAAAAVWBQAAVwUAAFgFAABZBQAAahIAAA==\"]Mc[\"AAAAAXMFAAAAAAAAAcwAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAA5gEYBDMHmAeACbEJdAx5DIIMpA/FD0wQdhB7EIcQvxDLENIQ3RDfED0RXxFzESYSKBJrEnkSqxKtEu4SKhMsE14TZRODE6ET3hM=\",\"AAEJCAAAAAFzBQAAAAAAAAAAAAAAAAAAAAAChgkAAIgJAAA=\"]Mc[\"AAAAAZ8FAAAAAAEVAQAAAAAAAAAAAAAAAAA6MAAAAQAAAAAAJAAQAAAA5wEaBDcHmQeBCbIJdQx6DIMMpQ/GD00QdxB8EIgQwBDMENMQ3hDgED4RYBF0EScSKRJsEnoSrBKuEu8SKxMtE18TZhOEE6IT3xM=\",\"AAEgCAAAAAGfBQAAAAAAAAAAAAAAAAAAAAAChwkAAIkJAAA=\"]Cc[\"AAAAAYkFAAAAAAAAAewAAAA=\",\"AAAAAYkFAAAAAAEWDAAA\"]Ck[\"AAAAAccFAAAAAAFdAQAA\",\"AAAAAccFAAAAAAMXDAAAGAwAABkMAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAEwBAAAAAAAAYAMAAA=\",\"\"]Bg[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAV4PAAA=\"]Eo[\"AAAAAbcFAAAAAUIAAAACPAEAAD0BAAABUAcAAA==\",\"AAAAAbcFAAAAAAFCBwAAAAAAAAAAAAAAAAAC6AUAAF8PAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAAhMUAAAUFAAA\"]Ck[\"AAAAAAAAAAAByhMAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAABKhQAAA==\"]Ag[\"AAACfAIAAPgCAAA=\",\"\"]Cc[\"AAAAAAACdwwAAH0SAAABeg8AAA==\",\"AAAAAAABlgcAAA==\"]Gc[\"AAAAAZoFAAAAAS4AAAABDgEAAAABLhIAAAF4DAAAAAF+EgAA\",\"AAEdCAAAAAGaBQAAAAHxEgAAAeYPAAAAAS4SAAAAAAAAAAAAAAABlwcAAA==\"]Do[\"AAAAAAAAAAF7DwAAAggGAACrDwAA\",\"AAAAAZMBAAAAAAABew8AAAQIBgAAqw8AADIRAAAzEQAA\"]Do[\"AAAAAAAAAAF8DwAAAgkGAACsDwAA\",\"AAAAAZ8BAAAAAAABfA8AAAQJBgAArA8AADQRAAA1EQAA\"]Ao[\"AAAAAAFOEAAAAAABcRAAAA==\",\"\"]Gc[\"AAABThEAAAJaAAAARAgAAAHyAQAAAAGzAAAAAkEEAABrEQAAAncPAADoDwAAAAF5DwAAAisEAADnDwAAAAJ+DAAA5hAAAAJ9DAAAfwwAAA==\",\"\"]Cc[\"AAAAAAAAAAMsBAAAQwQAAG0RAAA=\",\"AAAAAAAB6g8AAA==\"]Ec[\"AAABGQIAAAFrBQAAAAIPAAAAjQcAAAK5AAAAugAAAA==\",\"AAABGwIAAAFrBQAAAAAAAmsRAABsEQAA\"]Bo[\"AAABzRAAAAAAAAKvAAAAsAAAAA==\",\"AAAAAAH5BQAA\"]Ck[\"AAABzhAAAAAAAAJMAQAATQEAAA==\",\"AAAAAAAAAAAAAAAB+gUAAA==\"]Ao[\"AAAAAAAAAScTAAABaQ8AAA==\",\"\"]Hg[\"AAAAAVwAAAAB8wEAAAG3CQAAA78AAABVBwAAhRAAAAL3BQAAARAAAAACDgYAANYMAAAGbw8AAHAPAABxDwAAjxAAAOcQAACPEgAAAV0IAAAAAnMPAAB0DwAAAXIPAAA=\",\"\"]Dk[\"AAAAAAABuAkAAAJWBwAAXggAAAL4BQAAhhAAAAABDwYAAAGQEAAA\",\"AAAAAAAB7w8AAA==\"]Bc[\"AAAAAAAAAAAAAAAAAAAAAAH4EgAA\",\"\"]AAg[\"AAAAAScHAAABhgcAAAQmBwAAdwwAAKYPAAB9EgAAAtgTAAAHFAAAAy8RAADZEwAACBQAAAX7BwAAMhEAADMRAAA0EQAANREAAAFKEAAAAAAAAfwHAAA=\",\"AAAABG4RAABvEQAAcBEAAHIRAAACZQ8AAGYPAAACcREAAJ8TAAAFABQAACMUAAAkFAAAJRQAACYUAAABghMAAAEBFAAAAS0SAAAAAAAAAAAAAoAPAACZDwAABugBAADpAQAAfAcAAK0PAACuDwAArw8AAA==\"]Cc[\"AAAAAbgFAAAAAUMAAAACPgEAAD8BAAA=\",\"AAAAAbgFAAA=\"]Dc[\"AAAAAAAAAAA7MAAAAQAABQABAGISBQA=\",\"AAAABLUBAAC5AQAAugEAALsBAAA=\"]Ao[\"AAAAAbUBAAAAAAAAAfUPAAA=\",\"\"]Ao[\"AAAAAboBAAAAAAAAAfYPAAA=\",\"\"]Eo[\"AAAAAVERAAABEhMAAANgEAAA4xAAADoRAAABaRMAAAFcEQAAAVAQAAACZBEAADgSAAABVhEAAAAAAAABmRMAAA==\",\"\"]Eo[\"AAAAAVQRAAABFBMAAANkEAAA5RAAADwRAAABbBMAAAFeEQAAAVIQAAACZhEAADoSAAABWBEAAAAAAAABmxMAAA==\",\"\"]Bc[\"AAAAAAAAAkQEAABdBwAAAAH3DwAA\",\"\"]Bc[\"AAAAAAAAAkcEAABgBwAAAAH4DwAA\",\"\"]Ec[\"AAAAAbABAAAAAoISAACEEgAAAmMTAABkEwAAAjUEAAAVDAAAAAAAAAABMAQAAA==\",\"AAAAAAEHAwAA\"]Gg[\"AAAAAW0FAAAAAhEAAACPBwAAAsAAAADBAAAA\",\"AAADIwIAACQCAAAlAgAAAW0FAAAAAAABARAAAAACDgYAANYMAAACjxAAAI8SAAAAAAABcg8AAA==\"]Eg[\"AAAAAaUFAAAAAjYAAACRAAAAAx0BAAAeAQAA3Q8AAAEkAwAA\",\"AAAAAaUFAAAAAAAAAAEPBgAAAZAQAAA=\"]Ec[\"AAAAAAAAAUsBAAAAAAAAAAAAAAAAAAJhBQAAvAkAAA==\",\"AAAAAAAAAAAAAAAAAAAAAAAAAUMGAAA=\"]Ec[\"AAABUgwAAAFjBQAAAAELAAAAAaQAAAA=\",\"AAAAAWMFAAAAAY8JAAAAAAAAAAAAAAAAAAABJAcAAA==\"]Dg[\"AAAAAAH0BQAAAAAAAAAAAAAAAAAAAAKKEAAAMREAAA==\",\"AAEDCAAAAAAAASYHAAA=\"]Ac[\"AAABPQIAAA==\",\"\"]Do[\"AAAAAYEFAAAAARwAAAAAAALdAAAA3gAAAA==\",\"AAACSwIAAE0CAAABgQUAAAAAAAAAAVETAAA=\"]Dk[\"AAAAAbUFAAAAAT8AAAACNwEAADgBAAA=\",\"AAACugIAALsCAAABtQUAAAAAAAAAAVITAAA=\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAApQJAACWCQAA\"]Dk[\"AAAAAAAAAAAB/AAAAA==\",\"AAABaQIAAAAAAAAAAAAAAaAHAAABMQQAAAH9BwAAAAERBAAA\"]Dg[\"AAAAAAAAAW4BAAA=\",\"AAAB6gIAAAAAAAAAAAAAAaEHAAABMgQAAAH/BwAAAAETBAAA\"]Dk[\"AAAAAZAFAAAAAZwBAAABVAUAAAFEEQAAAfcAAAA=\",\"AAEWCAAAAAGQBQAAAAAAAUQRAAA=\"]Dk[\"AAAAAdUFAAAAAa4BAAACdwEAAFgFAAABSxEAAA==\",\"AAEvCAAAAAHVBQAAAAAAAUsRAAA=\"]Ck[\"AAAAAaYFAAAAATcAAAACHwEAACABAAA=\",\"AAAAAaYFAAAAAAFWBwAA\"]Eg[\"AAAAAXwFAAAAAhsAAACHAAAAAdMPAAABGgMAAALYAAAAdxIAAA==\",\"AAERCAAAAUUCAAACfAUAAH4KAAA=\"]Eg[\"AAAAAbAFAAAAAj4AAACSAAAAAjIBAADeDwAAASUDAAABeBIAAA==\",\"AAEpCAAAAbQCAAABsAUAAAHaCgAA\"]Ao[\"AAAAAAAAAAACeRAAADIRAAA=\",\"\"]Ao[\"AAAAAAAAAAACehAAADQRAAA=\",\"\"]Bg[\"AAAAAAAABL4AAAD+BQAAcwwAADYSAAA=\",\"\"]Ak[\"AAAAAAABOAAAAAEhAQAA\",\"\"]Do[\"AAAAAAAAAAAAAAAAAAAAAAAAAsoQAAAzEgAA\",\"AAEBCAAAAAAAAAAAAAAAAAAAAAAAAAGJEAAA\"]Cg[\"AAAAAANXBwAAtQkAANQQAAA=\",\"AAAAAAAAAAJpDwAAcRAAAA==\"]Ag[\"AAACaQIAAOoCAAA=\",\"\"]Cc[\"AAAAAaEKAAACoAoAAAwLAAABDQsAAAKLEAAAjRAAAA==\",\"\"]Ac[\"\",\"AAAAAWgSAAA=\"]Gg[\"AAAAAYAFAAAB4BMAAAAAAUQJAAAE3AAAAPcPAACIEgAAxRMAAAFKEAAA\",\"AAAAA5cBAACABQAA6hMAAAABpRMAAAABRAkAAAP3DwAAiBIAAMUTAAA=\"]Bc[\"AAAAAZcBAAAAAAAAAAAAAfEQAAA=\",\"\"]Gg[\"AAAAAbQFAAAAAAE2AQAAAUUJAAAD+A8AAIoSAADGEwAAAAAAAAH8BwAA\",\"AAAAA6YBAAC0BQAA6xMAAAABphMAAAABRQkAAAP4DwAAihIAAMYTAAA=\"]Bc[\"AAAAAaYBAAAAAAAAAAAAAfUQAAA=\",\"\"]Fg[\"AAABJQIAAAF3BQAAAAEZAAAAAAAC0AAAANEAAAA=\",\"AAENCAAAAAF3BQAAAAG3CQAAAlUHAACFEAAAA0EEAABCBAAA9wUAAA==\"]Eo[\"AAAAAagFAAAAAToAAAACIwEAACQBAAA=\",\"AAElCAAAAAGoBQAAAAG4CQAAAV4IAAAEQwQAAPgFAACGEAAAbREAAA==\"]Ao[\"\",\"AAAAAAAAAAAAAAAB+RAAAA==\"]Ek[\"AAAAAYUFAAAAASAAAAAAAALlAAAA5gAAAA==\",\"AAABUwIAAAGFBQAAAAAAAAH7BwAAAUoQAAAAAvEQAADzEAAA\"]Eg[\"AAAAAb4FAAAAAUgAAAACSQEAAEoBAAA=\",\"AAAByAIAAAG+BQAAAAAAAAAAAAL1EAAA9xAAAAAB/AcAAA==\"]Ao[\"AAAAAAAAAAFmEAAAAAGLDAAA\",\"\"]Jk[\"AAAAAYYFAAAABSEAAACIAAAA4wUAAF4QAABgEAAAAhYMAADUDwAABBsDAABgDAAAXxAAAGEQAAAE5wAAAOgAAAAyEQAAMxEAAAKHDAAAiAwAAAJVEQAAVhEAAA==\",\"AAAAAoYFAAB0EAAAApgBAABXEAAAAAABigkAAA==\"]Og[\"AAAAAcMFAAAABUsAAACVAAAA5AUAAGIQAABkEAAABlYBAABXAQAAFwwAABgMAAAZDAAA4Q8AAAQoAwAAYQwAAGMQAABlEAAAAjQRAAA1EQAAAokMAACKDAAAAlcRAABYEQAA\",\"AAAABMMFAAA2CAAANwgAAHUQAAAEqAEAAFgQAABZEAAAWhAAAAAAAYsJAAAC7wUAAPAFAAAAAAAAAAAAAAA7MAAAAQAACgACADgIBQBYCAQA\"]Cc[\"AAAAAbkFAAAAAUQAAAACQAEAAEEBAAA=\",\"AAAAAbkFAAA=\"]Ck[\"AAAB6wUAAAGHBQAAAAEiAAAAAAAB6QAAAA==\",\"AAAAAocFAABiDAAA\"]Dg[\"AAAB7AUAAAHEBQAAAAFMAAAAAVgBAAAAAAAAAAAAAVgHAAA=\",\"AAAAAsQFAABjDAAA\"]Cc[\"AAAAAdsFAAAAAVgAAAABgQEAAA==\",\"AAAAAtsFAABkDAAA\"]Dg[\"AAAAAAAAAAAAAAAB6BAAAA==\",\"AAAABlsQAAB2EgAATxMAAFATAAB/EwAAgBMAAA==\"]Ak[\"AAAAAAAAAAABZBIAAA==\",\"\"]Ak[\"AAAAAAAAAAABZxIAAA==\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAmIAAADoAQAA\",\"\"]Bg[\"AAAAAAAAAAAAASUEAAA=\",\"AAAAAesQAAA=\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAmEAAACXBwAA\",\"\"]Bk[\"AAAAAAAAAAAAAARmBwAAZwcAAGgHAABpBwAA\",\"\"]Ec[\"AAAABIIBAACNAQAAmQUAAEsQAAAAAAENAQAAAAAABGoHAABrBwAAbAcAAG0HAAA=\",\"AAAAAZkFAAA=\"]Bg[\"AAAAAAAAAAAAASYEAAA=\",\"AAAAAAHyEgAA\"]Cc[\"AAAAAaUKAAACpAoAABALAAABDwsAAAKMEAAAjhAAAA==\",\"\"]Ag[\"AAAAAAABiAcAAA==\",\"\"]No[\"AAAAAX4FAAABhgcAAAGwEgAAAaMPAAAGbwwAAGsQAABMEwAAYBMAAL0TAADkEwAAB9oAAACSAQAAzwwAAPUPAACHEgAAVxMAAFkTAAABxxMAAAAAAAAAAAAAAzQHAADTDAAAixIAAA==\",\"AAAAAn4FAAD9DwAAAAGWAQAAAY0SAAAGbwwAAGsQAABMEwAAYBMAAL0TAADkEwAABc8MAAD1DwAAhxIAAFcTAABZEwAA\"]Bo[\"AAAAAf0PAAAAAZYBAAAAAl8QAADyEAAAAAGHDAAA\",\"\"]Nc[\"AAAAAbIFAAAAAAE0AQAAOjAAAAEAAAAAAAcAEAAAAKABcAxsELESTRNhE74T5RMF0AwAAPYPAACJEgAAWBMAAFoTAAAAAAAAAAAAAAAEQwYAADgHAADUDAAAjBIAAA==\",\"AAAAArIFAAD+DwAAAAGlAQAAAY4SAAAGcAwAAGwQAABNEwAAYRMAAL4TAADlEwAABdAMAAD2DwAAiRIAAFgTAABaEwAA\"]Bo[\"AAAAAf4PAAAAAaUBAAAAAmMQAAD2EAAAAAGJDAAA\",\"\"]Ao[\"AAAAAAAAAAACVxMAAFgTAAA=\",\"\"]Ao[\"AAAAAAAAAAACWRMAAFoTAAA=\",\"\"]Ec[\"AAABJAIAAAFuBQAAAAISAAAAkAcAAALCAAAAwwAAAA==\",\"AAABJgIAAAFuBQAAAAAAAAAAAAFdCAAA\"]Bk[\"AAAAAbgBAAAAAAS9AAAA/QUAAHIMAAA1EgAA\",\"\"]Ek[\"AAAAAwsTAAAMEwAADRMAAAMIEwAACRMAAAoTAAAETgwAAE8MAABQDAAAUQwAAARKDAAASwwAAEwMAABNDAAA\",\"\"]Cc[\"AAAAAAAAAAABYxIAAA==\",\"AAEECAAAAAKRAQAA7BIAAA==\"]Cc[\"AAAAAAAAAAABZhIAAA==\",\"AAEZCAAAAAKeAQAA7RIAAA==\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAABWAcAAA==\"]Cg[\"AAAAAWQPAAAAAAFVAQAAAV0QAAA=\",\"AAE1CAAAAAAAAVYTAAA=\"]Ek[\"AAAAAWgFAAAAAAGtAAAAAAAAAAAAAAAAAAAE6RIAAPASAAAHEwAAIhMAAA==\",\"AAEFCAAAAAJoBQAABQYAAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA7kJAADzDwAAExQAAA==\",\"\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA7oJAAD0DwAAFBQAAA==\",\"\"]Bk[\"\",\"AAAAAAAAAAAAAAAAAAAAAAAAApUJAACXCQAA\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAAmAAAADmBQAA\",\"\"]Ec[\"AAAAAZIFAAAAAZ0BAAABVQUAAAJGEQAAfRMAAAH5AAAA\",\"AAEXCAAAAAGSBQAAAAAAAkYRAAB9EwAA\"]Ec[\"AAAAAdcFAAAAAa8BAAACeQEAAFkFAAACTREAAH4TAAA=\",\"AAEwCAAAAAHXBQAAAAAAAk0RAAB+EwAA\"]Ag[\"\",\"AAAAAAABKhIAAA==\"]Co[\"AAAAAocBAAA2CAAAAAABTgEAAA==\",\"AAAAAAAAAAAAAAAAAAAAAacBAAA=\"]Ac[\"\",\"AAAAAAGzEgAA\"]Cg[\"AAAAAAAAAo0SAACOEgAAAAABLRIAAA==\",\"AAAAAAAAAAFbEwAA\"]Do[\"AAAAAaMFAAAAAjQAAACQAAAAAxoBAAAbAQAA3A8AAAEjAwAA\",\"AAAAAaMFAAAAAAABLAQAAA==\"]Ak[\"AAAAAAACpRMAAKYTAAA=\",\"\"]Ac[\"AAAAAbkBAAA=\",\"\"]Ac[\"AAAAAbsBAAA=\",\"\"]Eo[\"AAAC0QIAAOUCAAABzQUAAAABUwAAAAJoAQAAaQEAAA==\",\"AAAAAc0FAAAAAAAFOgcAADsHAAA8BwAAPQcAAD4HAAA=\"]Fk[\"AAAABG0QAABuEAAATxMAAFATAAABZQ8AAAHHEAAAASsSAAAAAAHHEwAAAAAAAAAAAAGADAAA\",\"AAAAAAAAAzQSAAA1EgAANhIAAA==\"]Fc[\"AAAAAAABJgcAAAKNEgAAjhIAAAEvEQAAAAEtEgAAAAACoxMAAKQTAAAAAAAB+BIAAA==\",\"AAAAAAAAAdwTAAABWxMAAA==\"]Ag[\"\",\"AAAAAAAB4AUAAA==\"]Co[\"AAAAAasFAAAAAT0AAAACKQEAACoBAAA=\",\"AAAAAasFAAAAAAAAAAFvDgAA\"]Bg[\"AAAAAAAAAAAAAAAAAAAAAAAAAXcHAAA=\",\"\"]Jc[\"AAAAAn0FAADDEwAAAAAAAiESAADqEgAABNkAAACSAQAAhQwAAPUSAAADvQkAAFETAADHEwAAAAAAAcUQAAA=\",\"AAESCAAAAAKVAQAAfQUAAAAAAAIhEgAA6hIAAAKFDAAA9RIAAAK9CQAAURMAAAAAAAHFEAAA\"]Jg[\"AAAAArEFAADEEwAAAAABMwEAAAOgAQAAIhIAAOsSAAAChgwAAPYSAAACvgkAAFITAAAAAAABxhAAAA==\",\"AAEqCAAAAAKkAQAAsQUAAAEuBwAAAAACIhIAAOsSAAAChgwAAPYSAAACvgkAAFITAAAAAAABxhAAAA==\"]Ao[\"AAAAAAAAAbEAAAAAAAEoBAAA\",\"\"]Ak[\"AAAAAAABQQAAAAE7AQAA\",\"\"]Ag[\"AAACdAIAAPsCAAA=\",\"\"]Ak[\"AAAAAAAAAkUEAABeBwAA\",\"\"]Ak[\"AAAAAAAAAkgEAABhBwAA\",\"\"]Ag[\"AAACdQIAAPwCAAA=\",\"\"]Dk[\"AAAAAWwFAAAAAhAAAACOBwAAArsAAAC8AAAA\",\"AAABHQIAAAFsBQAAAAAAAAAAAXkPAAA=\"]Dg[\"AAAAAWkFAAAAAg0AAACLBwAAArUAAAC2AAAA\",\"AAABFgIAAAFpBQAAAAAAAAHoDwAA\"]Co[\"AAABMRIAAAGnBQAAAAE5AAAAASIBAAA=\",\"AAEkCAAAAYUJAAABpwUAAA==\"]Ec[\"AAAAAAABMhIAAAGlAAAAAAAAAAAAAAAAAAADPAQAAIIJAAB9DwAA\",\"AAAAAY8BAAAAAAAAAUsTAAA=\"]Hk[\"AAACqgIAAMMCAAABxQUAAAABTQAAAAJZAQAAWgEAAAAAAAAAAAAAAAAABOwBAADoBQAAOQcAAHYHAAA=\",\"AAAB1wIAAAKpAQAAxQUAAAAAAmsTAABsEwAAAAACZREAAGYRAAA=\"]Fc[\"AAAAA1sQAABvEAAAdhIAAAACghIAAIQSAAADfgEAAGMTAABkEwAAAjUEAAAVDAAAAAAAAAABMAQAAA==\",\"AAAAAbABAAA=\"]Eg[\"AAAAAYMFAAAAAR4AAAAAAALhAAAA4gAAAAAAAAAAAAAAAANyBwAAWA8AAF4PAAA=\",\"AAABUAIAAAGDBQAA\"]Eg[\"AAAAAboFAAAAAUUAAAACQgEAAEMBAAAAAAAAAAAAAAAAAAN0BwAAWg8AAF8PAAA=\",\"AAABwwIAAAG6BQAA\"]Hk[\"AAAFDAIAABgCAAAbAgAAIwIAACYCAAABeAUAAAACGgAAAJEHAAAAAALSAAAA0wAAAA==\",\"AAADPQIAAD4CAAA/AgAAAngFAAAqBwAAAkEGAABJEAAAARUTAAABow8AAAE3EQAA\"]Ek[\"AAAAAakFAAAAAjsAAACSBwAAAiUBAAAmAQAA\",\"AAABqgIAAAGpBQAAAAAAAAAAAAAAAAAAAAACYQUAAHcHAAA=\"]Bk[\"AAAAAAABXBAAAAFUAQAA\",\"AAAAAAAAAAFdEAAA\"]Ek[\"AAAAAXUFAAAAAAAAAc4AAAAAAAAAAAAAAAAEmwcAAJ0HAACGCQAAiAkAAA==\",\"AAELCAAAAAJ1BQAABAYAAA==\"]Ek[\"AAAAAaEFAAAAAAEXAQAAAAAAAAAAAAAAAAAEnAcAAJ4HAACHCQAAiQkAAA==\",\"AAEiCAAAAAGhBQAAAQYGAAA=\"]Ag[\"AAACewIAAPMCAAA=\",\"\"]Cg[\"AAAAAd0FAAAAAAADaQ8AAM4PAABxEAAA\",\"AAE0CAAAAAHdBQAA\"]Dc[\"AAAAAr8FAAA3CAAAAAABTwEAAA==\",\"AAAAAb8FAAAAAAAAAAAAAAAAAAFDBwAA\"]Dg[\"AAAAAfkSAAAB/w8AAAAAAALUAAAAMxEAAA==\",\"AAGMCQAAAZQBAAAB+RIAAAH/DwAA\"]Dg[\"AAAAAfoSAAABABAAAAABLgEAAAABNREAAA==\",\"AAGNCQAAAaMBAAAB+hIAAAEAEAAA\"]Ac[\"\",\"AAAAAAHLEwAA\"]Ag[\"AAACegIAAPQCAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAADYhIAAGMSAABkEgAA\"]Bc[\"\",\"AAAAAAAAAAADZRIAAGYSAABnEgAA\"]Ak[\"\",\"AAAAAYYSAAAAAAGWEwAA\"]ADc[\"AAAAAXkFAAAAAAA6MAAAAQAAAAAAFAAQAAAATggTDWoPsQ+0D/AP7RBoEXwRfxLlEoUT2hPmE/IT9BMWFBoUHRQhFCgUOjAAAAEAAAAAAAwAEAAAANUAeRDpEHcShxKIEhYTQRNUE/4TDxQRFB8UAAABYREAAA==\",\"AAEOCAAAAAF5BQAAAAAAOjAAAAEAAAAAABQAEAAAAE4IEw1qD7EPtA/wD+0QaBF8EX8S5RKFE9oT5hPyE/QTFhQaFB0UIRQoFDowAAABAAAAAAAJABAAAAB5EOkQdxIWE0ETVBP+Ew8UERQfFAAAAWERAAA=\"]ADc[\"AAAAAa0FAAAAAAEvAQAAOjAAAAEAAAAAABQAEAAAAE8IFA1rD7IPtQ/xD+4QaRF9EYAS5hKGE9sT5xPzE/UTFxQbFB4UIhQpFDowAAABAAAAAAALABAAAAB6EOoQeBKJEooSFxNCE1UT/xMQFBIUIBQAAAFiEQAA\",\"AAEmCAAAAAGtBQAAAAAAOjAAAAEAAAAAABQAEAAAAE8IFA1rD7IPtQ/xD+4QaRF9EYAS5hKGE9sT5xPzE/UTFxQbFB4UIhQpFDowAAABAAAAAAAJABAAAAB6EOoQeBIXE0ITVRP/ExAUEhQgFAAAAWIRAAA=\"]Ag[\"AAACTQIAALoCAAA=\",\"\"]Bk[\"AAAAAAAAAAAAARwEAAA=\",\"AAAAAAAAAWcMAAA=\"]Bk[\"AAAAAAAAAAAAAAF8DAAA\",\"AAAAAAABoBMAAA==\"]Do[\"AAAAAYQFAAAAAR8AAAAAAALjAAAA5AAAAAAAAAAAAAAAAAJzBwAAWQ8AAA==\",\"AAAAAYQFAAA=\"]Do[\"AAAAAbsFAAAAAUYAAAACRAEAAEUBAAAAAAAAAAAAAAAAAAJ1BwAAWw8AAA==\",\"AAAAAbsFAAA=\"]Ag[\"AAACdwIAAPICAAA=\",\"\"]Fc[\"AAAAAb0FAAAAAkcAAACTAAAAAkcBAADfDwAAAiYDAABdEAAA\",\"AAAAAb0FAAAAAAAAAAAAAAAB/AcAAAAAAAABQwYAAA==\"]Ag[\"AAACcwIAAPoCAAA=\",\"\"]Ag[\"AAACdgIAAP0CAAA=\",\"\"]Ck[\"AAAAAAAAAAAAAAAB8xAAAA==\",\"AAAAAaEKAAABoAoAAAABixAAAA==\"]Co[\"AAAAAbEBAAAAAAAAAAAAAfcQAAA=\",\"AAAAAAEMCwAAAQ0LAAABjRAAAA==\"]Dc[\"AAAAAAAAAAJhEAAA9BAAAAABiAwAAA==\",\"AAAAAaUKAAABpAoAAAABjBAAAA==\"]Dg[\"AAAAAbIBAAAAAAACZRAAAPgQAAAAAYoMAAA=\",\"AAAAAAEQCwAAAQ8LAAABjhAAAA==\"]Cc[\"AAAAAAAAAkYEAABfBwAAAAHtAAAA\",\"AAEUCAAAAAGZAQAA\"]Cc[\"AAAAAAAAA18BAABJBAAAYgcAAA==\",\"AAEtCAAAAAGrAQAA\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAA3EHAAA9CAAAXAgAAA==\",\"\"]Ao[\"AAAAAAAAAVIFAAAAAQ8UAAA=\",\"\"]Bk[\"AAAAAAAAAVYFAAAAARAUAAA=\",\"AAAAAVoFAAA=\"]Eg[\"AAAAAAAAAAAB+gAAAAAAAAAAAAAAAAO/CQAAzw8AAKgSAAA=\",\"AAEYCAAAAARGCAAARwgAAEgIAABJCAAA\"]Eg[\"AAAAAAAAAXoBAAAAAAAAAAAAAAAAAAPACQAA0A8AAKkSAAA=\",\"AAExCAAAAARKCAAASwgAAEwIAABNCAAA\"]Bc[\"AAAAAAABlgEAAAABLREAAAHPDAAA\",\"\"]Bc[\"AAAAAAABpQEAAAABLhEAAAHQDAAA\",\"\"]Fo[\"AAAAAcIFAAAAAkoAAACUAAAAA1IBAABTAQAA4A8AAAEnAwAA\",\"AAAB0QIAAAHCBQAAAAAAAALvBQAA8AUAAAAAAAAAAAKnAQAAQwcAAA==\"]Dg[\"AAAAAWYFAAAAAgwAAACKBwAAAqoAAACrAAAA\",\"AAABDAIAAAFmBQAAAAAB7BAAAA==\"]Do[\"AAAAAZcFAAAAAiwAAACNAAAAAwkBAAAKAQAA2Q8AAAEgAwAA\",\"AAAAAZcFAAAAAAAAATQEAAA=\"]Ek[\"AAAAAXoFAAAAAAACXBMAAK0TAAAD1gAAAM8QAABBEwAA\",\"AAEPCAAAAAF6BQAAAAAAAlwTAACtEwAAAc8QAAA=\"]Ek[\"AAAAAa4FAAAAAAEwAQAAAl0TAACuEwAAAtAQAABCEwAA\",\"AAEnCAAAAAGuBQAAAAAAAl0TAACuEwAAAdAQAAA=\"]Bo[\"AAAAAAAAAAAB7wUAAAAAAAAAAAKnAQAAQwcAAA==\",\"\"]Fg[\"AAAAAXsFAAAAAAAEnwkAAPoPAABZEQAADxMAAALXAAAAVBMAAA==\",\"AAEQCAAAAAF7BQAAAAAABJ8JAAD6DwAAWREAAA8TAAA=\"]Fg[\"AAAAAa8FAAAAAAExAQAABKAJAAD7DwAAWhEAABATAAABVRMAAA==\",\"AAEoCAAAAAGvBQAAAAAABKAJAAD7DwAAWhEAABATAAA=\"]Ag[\"\",\"AAAAAAAAAdwTAAA=\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAAAAAAH4EgAA\"]Ag[\"\",\"AAAAAAAAAXoPAAA=\"]Co[\"AAAAAZwFAAAAATAAAAACEAEAABEBAAA=\",\"AAAAAZwFAAAAAAAAAS4SAAA=\"]Fg[\"AAABLQIAAAGIBQAAAAEjAAAAAAFLBwAAAuoAAADrAAAA\",\"AAACVwIAADIHAAABiAUAAAAAAAE9BwAAAAAAAAAAAAAAAAFYDwAA\"]Gc[\"AAABjwIAAAKpAQAAxgUAAAABTgAAAAJbAQAAXAEAAAFSBwAA\",\"AAAC2QIAADYHAAABxgUAAAAAAUQHAAAAAAAAAAAAAAAAAALsAQAAWg8AAA==\"]Cc[\"AAAAAAAAAAAAAAAAAAAAAAAAAzkIAABZCAAARwkAAA==\",\"\"]Cg[\"AAABUwIAAAAAAAAAAf0AAAA=\",\"AAAAAAAAAAJfEAAAYRAAAA==\"]Cg[\"AAAByAIAAAAAAAFvAQAA\",\"AAAAAAAAAANjEAAAZRAAAGYQAAA=\"]Bo[\"AAAAAloFAADcBQAAAbMSAAA=\",\"AAAAAtwFAAB/EQAA\"]Ao[\"\",\"AAAAAAAAAAL7EAAA/BAAAA==\"]Io[\"AAAAAc4FAAAAAVQAAAABagEAAAYQBgAA8hAAAPQQAAD2EAAA+BAAAPoQAAAAAAAF8RAAAPMQAAD1EAAA9xAAAPkQAAAAAAAAAAABJxQAAA==\",\"AAAAAc4FAAAAAARoEwAAaRMAAGsTAABsEwAAAAEtBAAA\"]Co[\"AAAAAlsAAABFCAAAAAABtAAAAAJCBAAAbBEAAAF4DwAA\",\"AAABThEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAApQJAABTEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAApYJAABVEAAA\",\"\"]Co[\"AAAAAZMFAAAAAAAAAv4AAAD/AAAA\",\"AAAAAZMFAAAAAAKLEAAAjBAAAA==\"]Dc[\"AAAAAdAFAAAAAAJwAQAAcQEAAA==\",\"AAAAAtAFAABoEgAAAAACjRAAAI4QAAA=\"]Ac[\"\",\"AAABUgwAAA==\"]Ec[\"AAABSwIAAAFwBQAAAAEUAAAAAAACxgAAAMcAAAA=\",\"AAAAAXAFAAAEkgkAAGsKAABsCgAAbgoAAA==\"]Do[\"AAABuwIAAAGWBQAAAAEqAAAAAgYBAAAHAQAA\",\"AAAAAZYFAAAEkwkAALgKAAC5CgAAugoAAA==\"]Ak[\"\",\"AAAAAAACpRMAAKYTAAA=\"]Cg[\"AAAAAmUFAACpCQAAAUMJAAAAAakAAAA=\",\"AAAAAmUFAAD8DwAA\"]Cg[\"AAAAAdwHAAACRRAAAFcQAAAAARYMAAAAAAAAAAABxRAAAA==\",\"\"]Ck[\"AAAAAd0HAAACRhAAAFgQAAAAAhcMAAAYDAAAAAAAAAAAAcYQAAA=\",\"\"]Bc[\"AAAAAAAAAAAAAAAAAqMTAACkEwAA\",\"\"]Fo[\"AAAAAX8FAAAAAAADNgQAAKoJAAC9EwAAAtsAAACLAQAA\",\"AAETCAAAAAF/BQAAAAAAAjYEAACqCQAAAYsBAAAAAAAAAAAAAAABixIAAA==\"]Fo[\"AAAAAbMFAAAAAAE1AQAAAzcEAACrCQAAvhMAAAGMAQAA\",\"AAErCAAAAAGzBQAAAAAAAjcEAACrCQAAAYwBAAAAAAAAAAAAAAABjBIAAA==\"]Ck[\"AAAAAawFAAAAAAIrAQAALAEAAA==\",\"AAAAAawFAAAAAAAAAcoTAAA=\"]Ec[\"AAAAAcAFAAAAAAFQAQAAAAAAAAAAAAAAAAAFiAEAADgIAABYCAAARgkAANEMAAA=\",\"AAAAAcAFAAA=\"]Dg[\"AAAAAAHLEwAAAAGmAAAAAAAAAAACoxMAAKQTAAAAAAAB+BIAAA==\",\"AAABkAEAAA==\"]Ag[\"AAACeAIAAPkCAAA=\",\"\"]Bc[\"\",\"AAAAAAAAAAAAAAAAAqMTAACkEwAA\"]Bk[\"AAAAAAAAAAAAAAAB+RAAAA==\",\"AAAAAbEBAAA=\"]Cc[\"AAAAAAAAAAJmEAAA+hAAAAABiwwAAA==\",\"AAAAAbIBAAA=\"]Ag[\"AAACeQIAAPcCAAA=\",\"\"]Dg[\"AAAAAAABJwAAAAAAAfsAAAA=\",\"AAAAAAAAAAAAAAAAAAAAA5cTAACYEwAAmRMAAA==\"]Ck[\"AAAAAAABVgAAAAFtAQAA\",\"AAAAAAAAAAAAAAAAAAAAApoTAACbEwAA\"]Ag[\"AAACcgIAAPYCAAA=\",\"\"]Do[\"AAAAAd4HAAACRxAAAFkQAAAAARkMAAABgxAAAA==\",\"AAKiAQAAGggAAAGOCQAAAAAAAAGDEAAA\"]Ec[\"AAAAAsgFAADfBwAAAkgQAABaEAAAAAFeAQAAAYQQAAA=\",\"AAEsCAAAAaoBAAAByAUAAAAAAAGEEAAA\"]Bg[\"AAAAAAAAAAAB8AUAAA==\",\"AAABoQEAAA==\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAApUJAABUEAAA\",\"\"]Bk[\"AAAAAAAAAAAAAAAAAAAAAAAAApcJAABWEAAA\",\"\"]") \ No newline at end of file diff --git a/pr/255/docs/src/bench/lib.rs.html b/pr/255/docs/src/bench/lib.rs.html index 95cda99f5..57f932cf2 100644 --- a/pr/255/docs/src/bench/lib.rs.html +++ b/pr/255/docs/src/bench/lib.rs.html @@ -235,9 +235,9 @@ 235 pub fn as_rustls(self) -> rustls::SupportedCipherSuite { 236 use rustls::crypto::ring::cipher_suite; 237 match self { -238 CipherSuite::Aes128 => cipher_suite::TLS13_AES_128_GCM_SHA256, -239 CipherSuite::Aes256 => cipher_suite::TLS13_AES_256_GCM_SHA384, -240 CipherSuite::Chacha20 => cipher_suite::TLS13_CHACHA20_POLY1305_SHA256, +238 Self::Aes128 => cipher_suite::TLS13_AES_128_GCM_SHA256, +239 Self::Aes256 => cipher_suite::TLS13_AES_256_GCM_SHA384, +240 Self::Chacha20 => cipher_suite::TLS13_CHACHA20_POLY1305_SHA256, 241 } 242 } 243} @@ -247,9 +247,9 @@ 247 248 fn from_str(s: &str) -> Result<Self, Self::Err> { 249 match s.to_lowercase().as_str() { -250 "aes128" => Ok(CipherSuite::Aes128), -251 "aes256" => Ok(CipherSuite::Aes256), -252 "chacha20" => Ok(CipherSuite::Chacha20), +250 "aes128" => Ok(Self::Aes128), +251 "aes256" => Ok(Self::Aes256), +252 "chacha20" => Ok(Self::Chacha20), 253 _ => Err(anyhow::anyhow!("Unknown cipher suite {}", s)), 254 } 255 } diff --git a/pr/255/docs/src/bench/stats.rs.html b/pr/255/docs/src/bench/stats.rs.html index 959a01e82..b8c881d8d 100644 --- a/pr/255/docs/src/bench/stats.rs.html +++ b/pr/255/docs/src/bench/stats.rs.html @@ -82,7 +82,7 @@ 82impl TransferResult { 83 pub fn new(duration: Duration, size: u64) -> Self { 84 let throughput = throughput_bps(duration, size); -85 TransferResult { +85 Self { 86 duration, 87 size, 88 throughput, diff --git a/pr/255/docs/src/bulk/bulk.rs.html b/pr/255/docs/src/bulk/bulk.rs.html index 26522c25b..c6990807c 100644 --- a/pr/255/docs/src/bulk/bulk.rs.html +++ b/pr/255/docs/src/bulk/bulk.rs.html @@ -204,7 +204,7 @@ 204} 205 206impl ClientStats { -207 pub fn print(&self, client_id: usize) { +207 fn print(&self, client_id: usize) { 208 println!(); 209 println!("Client {client_id} stats:"); 210 diff --git a/pr/255/docs/src/iroh_quinn/connection.rs.html b/pr/255/docs/src/iroh_quinn/connection.rs.html index a209854c2..24441184a 100644 --- a/pr/255/docs/src/iroh_quinn/connection.rs.html +++ b/pr/255/docs/src/iroh_quinn/connection.rs.html @@ -211,7 +211,7 @@ 211 212impl Future for Connecting { 213 type Output = Result<Connection, ConnectionError>; -214 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +214 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 215 Pin::new(&mut self.connected).poll(cx).map(|_| { 216 let conn = self.conn.take().unwrap(); 217 let inner = conn.state.lock("connecting"); @@ -236,7 +236,7 @@ 236 237impl Future for ZeroRttAccepted { 238 type Output = bool; -239 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +239 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 240 Pin::new(&mut self.0).poll(cx).map(|x| x.unwrap_or(false)) 241 } 242} @@ -258,7 +258,7 @@ 258impl Future for ConnectionDriver { 259 type Output = Result<(), io::Error>; 260 -261 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +261 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 262 let conn = &mut *self.0.state.lock("poll"); 263 264 let span = debug_span!("drive", id = conn.handle.0); @@ -1384,7 +1384,7 @@ 1384 } 1385 } 1386 -1387 fn drive_transmit(&mut self, cx: &mut Context) -> io::Result<bool> { +1387 fn drive_transmit(&mut self, cx: &mut Context<'_>) -> io::Result<bool> { 1388 let now = self.runtime.now(); 1389 let mut transmits = 0; 1390 @@ -1452,7 +1452,7 @@ 1452 fn process_conn_events( 1453 &mut self, 1454 shared: &Shared, -1455 cx: &mut Context, +1455 cx: &mut Context<'_>, 1456 ) -> Result<(), ConnectionError> { 1457 loop { 1458 match self.conn_events.poll_recv(cx) { @@ -1571,7 +1571,7 @@ 1571 } 1572 } 1573 -1574 fn drive_timer(&mut self, cx: &mut Context) -> bool { +1574 fn drive_timer(&mut self, cx: &mut Context<'_>) -> bool { 1575 // Check whether we need to (re)set the timer. If so, we must poll again to ensure the 1576 // timer is registered with the runtime (and check whether it's already 1577 // expired). @@ -1700,7 +1700,7 @@ 1700} 1701 1702impl fmt::Debug for State { -1703 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +1703 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1704 f.debug_struct("State").field("inner", &self.inner).finish() 1705 } 1706} diff --git a/pr/255/docs/src/iroh_quinn/endpoint.rs.html b/pr/255/docs/src/iroh_quinn/endpoint.rs.html index db47b564f..ec64a1c49 100644 --- a/pr/255/docs/src/iroh_quinn/endpoint.rs.html +++ b/pr/255/docs/src/iroh_quinn/endpoint.rs.html @@ -54,881 +54,880 @@ 54#[derive(Debug, Clone)] 55pub struct Endpoint { 56 pub(crate) inner: EndpointRef, -57 pub(crate) default_client_config: Option<ClientConfig>, -58 runtime: Arc<dyn Runtime>, -59} -60 -61impl Endpoint { -62 /// Helper to construct an endpoint for use with outgoing connections only -63 /// -64 /// Note that `addr` is the *local* address to bind to, which should usually be a wildcard -65 /// address like `0.0.0.0:0` or `[::]:0`, which allow communication with any reachable IPv4 or -66 /// IPv6 address respectively from an OS-assigned port. -67 /// -68 /// If an IPv6 address is provided, attempts to make the socket dual-stack so as to allow -69 /// communication with both IPv4 and IPv6 addresses. As such, calling `Endpoint::client` with -70 /// the address `[::]:0` is a reasonable default to maximize the ability to connect to other -71 /// address. For example: -72 /// -73 /// ``` -74 /// iroh_quinn::Endpoint::client((std::net::Ipv6Addr::UNSPECIFIED, 0).into()); -75 /// ``` -76 /// -77 /// Some environments may not allow creation of dual-stack sockets, in which case an IPv6 -78 /// client will only be able to connect to IPv6 servers. An IPv4 client is never dual-stack. -79 #[cfg(all( -80 not(wasm_browser), -81 any(feature = "runtime-tokio", feature = "runtime-smol"), -82 any(feature = "aws-lc-rs", feature = "ring"), // `EndpointConfig::default()` is only available with these -83 ))] -84 pub fn client(addr: SocketAddr) -> io::Result<Self> { -85 let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; -86 if addr.is_ipv6() { -87 if let Err(e) = socket.set_only_v6(false) { -88 tracing::debug!(%e, "unable to make socket dual-stack"); -89 } -90 } -91 socket.bind(&addr.into())?; -92 let runtime = -93 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?; -94 Self::new_with_abstract_socket( -95 EndpointConfig::default(), -96 None, -97 runtime.wrap_udp_socket(socket.into())?, -98 runtime, -99 ) -100 } -101 -102 /// Returns relevant stats from this Endpoint -103 pub fn stats(&self) -> EndpointStats { -104 self.inner.state.lock().unwrap().stats -105 } -106 -107 /// Helper to construct an endpoint for use with both incoming and outgoing connections -108 /// -109 /// Platform defaults for dual-stack sockets vary. For example, any socket bound to a wildcard -110 /// IPv6 address on Windows will not by default be able to communicate with IPv4 -111 /// addresses. Portable applications should bind an address that matches the family they wish to -112 /// communicate within. -113 #[cfg(all( -114 not(wasm_browser), -115 any(feature = "runtime-tokio", feature = "runtime-smol"), -116 any(feature = "aws-lc-rs", feature = "ring"), // `EndpointConfig::default()` is only available with these -117 ))] -118 pub fn server(config: ServerConfig, addr: SocketAddr) -> io::Result<Self> { -119 let socket = std::net::UdpSocket::bind(addr)?; -120 let runtime = -121 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?; -122 Self::new_with_abstract_socket( -123 EndpointConfig::default(), -124 Some(config), -125 runtime.wrap_udp_socket(socket)?, -126 runtime, -127 ) -128 } -129 -130 /// Construct an endpoint with arbitrary configuration and socket -131 #[cfg(not(wasm_browser))] -132 pub fn new( -133 config: EndpointConfig, -134 server_config: Option<ServerConfig>, -135 socket: std::net::UdpSocket, -136 runtime: Arc<dyn Runtime>, -137 ) -> io::Result<Self> { -138 let socket = runtime.wrap_udp_socket(socket)?; -139 Self::new_with_abstract_socket(config, server_config, socket, runtime) -140 } -141 -142 /// Construct an endpoint with arbitrary configuration and pre-constructed abstract socket -143 /// -144 /// Useful when `socket` has additional state (e.g. sidechannels) attached for which shared -145 /// ownership is needed. -146 pub fn new_with_abstract_socket( -147 config: EndpointConfig, -148 server_config: Option<ServerConfig>, -149 socket: Box<dyn AsyncUdpSocket>, -150 runtime: Arc<dyn Runtime>, -151 ) -> io::Result<Self> { -152 let addr = socket.local_addr()?; -153 let allow_mtud = !socket.may_fragment(); -154 let rc = EndpointRef::new( -155 socket, -156 proto::Endpoint::new( -157 Arc::new(config), -158 server_config.map(Arc::new), -159 allow_mtud, -160 None, -161 ), -162 addr.is_ipv6(), -163 runtime.clone(), -164 ); -165 let driver = EndpointDriver(rc.clone()); -166 runtime.spawn(Box::pin( -167 async { -168 if let Err(e) = driver.await { -169 tracing::error!("I/O error: {}", e); -170 } -171 } -172 .instrument(Span::current()), -173 )); -174 Ok(Self { -175 inner: rc, -176 default_client_config: None, -177 runtime, -178 }) -179 } -180 -181 /// Get the next incoming connection attempt from a client -182 /// -183 /// Yields [`Incoming`]s, or `None` if the endpoint is [`close`](Self::close)d. [`Incoming`] -184 /// can be `await`ed to obtain the final [`Connection`](crate::Connection), or used to e.g. -185 /// filter connection attempts or force address validation, or converted into an intermediate -186 /// `Connecting` future which can be used to e.g. send 0.5-RTT data. -187 pub fn accept(&self) -> Accept<'_> { -188 Accept { -189 endpoint: self, -190 notify: self.inner.shared.incoming.notified(), -191 } -192 } -193 -194 /// Set the client configuration used by `connect` -195 pub fn set_default_client_config(&mut self, config: ClientConfig) { -196 self.default_client_config = Some(config); -197 } -198 -199 /// Connect to a remote endpoint -200 /// -201 /// `server_name` must be covered by the certificate presented by the server. This prevents a -202 /// connection from being intercepted by an attacker with a valid certificate for some other -203 /// server. -204 /// -205 /// May fail immediately due to configuration errors, or in the future if the connection could -206 /// not be established. -207 pub fn connect(&self, addr: SocketAddr, server_name: &str) -> Result<Connecting, ConnectError> { -208 let config = match &self.default_client_config { -209 Some(config) => config.clone(), -210 None => return Err(ConnectError::NoDefaultClientConfig), -211 }; +57 runtime: Arc<dyn Runtime>, +58} +59 +60impl Endpoint { +61 /// Helper to construct an endpoint for use with outgoing connections only +62 /// +63 /// Note that `addr` is the *local* address to bind to, which should usually be a wildcard +64 /// address like `0.0.0.0:0` or `[::]:0`, which allow communication with any reachable IPv4 or +65 /// IPv6 address respectively from an OS-assigned port. +66 /// +67 /// If an IPv6 address is provided, attempts to make the socket dual-stack so as to allow +68 /// communication with both IPv4 and IPv6 addresses. As such, calling `Endpoint::client` with +69 /// the address `[::]:0` is a reasonable default to maximize the ability to connect to other +70 /// address. For example: +71 /// +72 /// ``` +73 /// iroh_quinn::Endpoint::client((std::net::Ipv6Addr::UNSPECIFIED, 0).into()); +74 /// ``` +75 /// +76 /// Some environments may not allow creation of dual-stack sockets, in which case an IPv6 +77 /// client will only be able to connect to IPv6 servers. An IPv4 client is never dual-stack. +78 #[cfg(all( +79 not(wasm_browser), +80 any(feature = "runtime-tokio", feature = "runtime-smol"), +81 any(feature = "aws-lc-rs", feature = "ring"), // `EndpointConfig::default()` is only available with these +82 ))] +83 pub fn client(addr: SocketAddr) -> io::Result<Self> { +84 let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; +85 if addr.is_ipv6() { +86 if let Err(e) = socket.set_only_v6(false) { +87 tracing::debug!(%e, "unable to make socket dual-stack"); +88 } +89 } +90 socket.bind(&addr.into())?; +91 let runtime = +92 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?; +93 Self::new_with_abstract_socket( +94 EndpointConfig::default(), +95 None, +96 runtime.wrap_udp_socket(socket.into())?, +97 runtime, +98 ) +99 } +100 +101 /// Returns relevant stats from this Endpoint +102 pub fn stats(&self) -> EndpointStats { +103 self.inner.state.lock().unwrap().stats +104 } +105 +106 /// Helper to construct an endpoint for use with both incoming and outgoing connections +107 /// +108 /// Platform defaults for dual-stack sockets vary. For example, any socket bound to a wildcard +109 /// IPv6 address on Windows will not by default be able to communicate with IPv4 +110 /// addresses. Portable applications should bind an address that matches the family they wish to +111 /// communicate within. +112 #[cfg(all( +113 not(wasm_browser), +114 any(feature = "runtime-tokio", feature = "runtime-smol"), +115 any(feature = "aws-lc-rs", feature = "ring"), // `EndpointConfig::default()` is only available with these +116 ))] +117 pub fn server(config: ServerConfig, addr: SocketAddr) -> io::Result<Self> { +118 let socket = std::net::UdpSocket::bind(addr)?; +119 let runtime = +120 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?; +121 Self::new_with_abstract_socket( +122 EndpointConfig::default(), +123 Some(config), +124 runtime.wrap_udp_socket(socket)?, +125 runtime, +126 ) +127 } +128 +129 /// Construct an endpoint with arbitrary configuration and socket +130 #[cfg(not(wasm_browser))] +131 pub fn new( +132 config: EndpointConfig, +133 server_config: Option<ServerConfig>, +134 socket: std::net::UdpSocket, +135 runtime: Arc<dyn Runtime>, +136 ) -> io::Result<Self> { +137 let socket = runtime.wrap_udp_socket(socket)?; +138 Self::new_with_abstract_socket(config, server_config, socket, runtime) +139 } +140 +141 /// Construct an endpoint with arbitrary configuration and pre-constructed abstract socket +142 /// +143 /// Useful when `socket` has additional state (e.g. sidechannels) attached for which shared +144 /// ownership is needed. +145 pub fn new_with_abstract_socket( +146 config: EndpointConfig, +147 server_config: Option<ServerConfig>, +148 socket: Box<dyn AsyncUdpSocket>, +149 runtime: Arc<dyn Runtime>, +150 ) -> io::Result<Self> { +151 let addr = socket.local_addr()?; +152 let allow_mtud = !socket.may_fragment(); +153 let rc = EndpointRef::new( +154 socket, +155 proto::Endpoint::new(Arc::new(config), server_config.map(Arc::new), allow_mtud), +156 addr.is_ipv6(), +157 runtime.clone(), +158 ); +159 let driver = EndpointDriver(rc.clone()); +160 runtime.spawn(Box::pin( +161 async { +162 if let Err(e) = driver.await { +163 tracing::error!("I/O error: {}", e); +164 } +165 } +166 .instrument(Span::current()), +167 )); +168 Ok(Self { inner: rc, runtime }) +169 } +170 +171 /// Get the next incoming connection attempt from a client +172 /// +173 /// Yields [`Incoming`]s, or `None` if the endpoint is [`close`](Self::close)d. [`Incoming`] +174 /// can be `await`ed to obtain the final [`Connection`](crate::Connection), or used to e.g. +175 /// filter connection attempts or force address validation, or converted into an intermediate +176 /// `Connecting` future which can be used to e.g. send 0.5-RTT data. +177 pub fn accept(&self) -> Accept<'_> { +178 Accept { +179 endpoint: self, +180 notify: self.inner.shared.incoming.notified(), +181 } +182 } +183 +184 /// Set the client configuration used by `connect` +185 pub fn set_default_client_config(&self, config: ClientConfig) { +186 self.inner.0.state.lock().unwrap().default_client_config = Some(config); +187 } +188 +189 /// Connect to a remote endpoint +190 /// +191 /// `server_name` must be covered by the certificate presented by the server. This prevents a +192 /// connection from being intercepted by an attacker with a valid certificate for some other +193 /// server. +194 /// +195 /// May fail immediately due to configuration errors, or in the future if the connection could +196 /// not be established. +197 pub fn connect(&self, addr: SocketAddr, server_name: &str) -> Result<Connecting, ConnectError> { +198 let Some(config) = self +199 .inner +200 .0 +201 .state +202 .lock() +203 .unwrap() +204 .default_client_config +205 .clone() +206 else { +207 return Err(ConnectError::NoDefaultClientConfig); +208 }; +209 +210 self.connect_with(config, addr, server_name) +211 } 212 -213 self.connect_with(config, addr, server_name) -214 } -215 -216 /// Connect to a remote endpoint using a custom configuration. -217 /// -218 /// See [`connect()`] for details. -219 /// -220 /// [`connect()`]: Endpoint::connect -221 pub fn connect_with( -222 &self, -223 config: ClientConfig, -224 addr: SocketAddr, -225 server_name: &str, -226 ) -> Result<Connecting, ConnectError> { -227 let mut endpoint = self.inner.state.lock().unwrap(); -228 if endpoint.driver_lost || endpoint.recv_state.connections.close.is_some() { -229 return Err(ConnectError::EndpointStopping); +213 /// Connect to a remote endpoint using a custom configuration. +214 /// +215 /// See [`connect()`] for details. +216 /// +217 /// [`connect()`]: Endpoint::connect +218 pub fn connect_with( +219 &self, +220 config: ClientConfig, +221 addr: SocketAddr, +222 server_name: &str, +223 ) -> Result<Connecting, ConnectError> { +224 let mut endpoint = self.inner.state.lock().unwrap(); +225 if endpoint.driver_lost || endpoint.recv_state.connections.close.is_some() { +226 return Err(ConnectError::EndpointStopping); +227 } +228 if addr.is_ipv6() && !endpoint.ipv6 { +229 return Err(ConnectError::InvalidRemoteAddress(addr)); 230 } -231 if addr.is_ipv6() && !endpoint.ipv6 { -232 return Err(ConnectError::InvalidRemoteAddress(addr)); -233 } -234 let addr = if endpoint.ipv6 { -235 SocketAddr::V6(ensure_ipv6(addr)) -236 } else { -237 addr -238 }; -239 -240 let (ch, conn) = endpoint -241 .inner -242 .connect(self.runtime.now(), config, addr, server_name)?; -243 -244 let sender = endpoint.socket.create_sender(); -245 endpoint.stats.outgoing_handshakes += 1; -246 Ok(endpoint -247 .recv_state -248 .connections -249 .insert(ch, conn, sender, self.runtime.clone())) -250 } -251 -252 /// Switch to a new UDP socket -253 /// -254 /// See [`Endpoint::rebind_abstract()`] for details. -255 #[cfg(not(wasm_browser))] -256 pub fn rebind(&self, socket: std::net::UdpSocket) -> io::Result<()> { -257 self.rebind_abstract(self.runtime.wrap_udp_socket(socket)?) -258 } -259 -260 /// Switch to a new UDP socket +231 let addr = if endpoint.ipv6 { +232 SocketAddr::V6(ensure_ipv6(addr)) +233 } else { +234 addr +235 }; +236 +237 let (ch, conn) = endpoint +238 .inner +239 .connect(self.runtime.now(), config, addr, server_name)?; +240 +241 let sender = endpoint.socket.create_sender(); +242 endpoint.stats.outgoing_handshakes += 1; +243 Ok(endpoint +244 .recv_state +245 .connections +246 .insert(ch, conn, sender, self.runtime.clone())) +247 } +248 +249 /// Switch to a new UDP socket +250 /// +251 /// See [`Endpoint::rebind_abstract()`] for details. +252 #[cfg(not(wasm_browser))] +253 pub fn rebind(&self, socket: std::net::UdpSocket) -> io::Result<()> { +254 self.rebind_abstract(self.runtime.wrap_udp_socket(socket)?) +255 } +256 +257 /// Switch to a new UDP socket +258 /// +259 /// Allows the endpoint's address to be updated live, affecting all active connections. Incoming +260 /// connections and connections to servers unreachable from the new address will be lost. 261 /// -262 /// Allows the endpoint's address to be updated live, affecting all active connections. Incoming -263 /// connections and connections to servers unreachable from the new address will be lost. -264 /// -265 /// On error, the old UDP socket is retained. -266 pub fn rebind_abstract(&self, socket: Box<dyn AsyncUdpSocket>) -> io::Result<()> { -267 let addr = socket.local_addr()?; -268 let mut inner = self.inner.state.lock().unwrap(); -269 inner.prev_socket = Some(mem::replace(&mut inner.socket, socket)); -270 inner.ipv6 = addr.is_ipv6(); -271 -272 // Update connection socket references -273 for sender in inner.recv_state.connections.senders.values() { -274 // Ignoring errors from dropped connections -275 let _ = sender.send(ConnectionEvent::Rebind(inner.socket.create_sender())); -276 } -277 if let Some(driver) = inner.driver.take() { -278 // Ensure the driver can register for wake-ups from the new socket -279 driver.wake(); -280 } +262 /// On error, the old UDP socket is retained. +263 pub fn rebind_abstract(&self, socket: Box<dyn AsyncUdpSocket>) -> io::Result<()> { +264 let addr = socket.local_addr()?; +265 let mut inner = self.inner.state.lock().unwrap(); +266 inner.prev_socket = Some(mem::replace(&mut inner.socket, socket)); +267 inner.ipv6 = addr.is_ipv6(); +268 +269 // Update connection socket references +270 for sender in inner.recv_state.connections.senders.values() { +271 // Ignoring errors from dropped connections +272 let _ = sender.send(ConnectionEvent::Rebind(inner.socket.create_sender())); +273 } +274 if let Some(driver) = inner.driver.take() { +275 // Ensure the driver can register for wake-ups from the new socket +276 driver.wake(); +277 } +278 +279 Ok(()) +280 } 281 -282 Ok(()) -283 } -284 -285 /// Replace the server configuration, affecting new incoming connections only -286 /// -287 /// Useful for e.g. refreshing TLS certificates without disrupting existing connections. -288 pub fn set_server_config(&self, server_config: Option<ServerConfig>) { -289 self.inner -290 .state -291 .lock() -292 .unwrap() -293 .inner -294 .set_server_config(server_config.map(Arc::new)) -295 } -296 -297 /// Get the local `SocketAddr` the underlying socket is bound to -298 pub fn local_addr(&self) -> io::Result<SocketAddr> { -299 self.inner.state.lock().unwrap().socket.local_addr() -300 } -301 -302 /// Get the number of connections that are currently open -303 pub fn open_connections(&self) -> usize { -304 self.inner.state.lock().unwrap().inner.open_connections() -305 } -306 -307 /// Close all of this endpoint's connections immediately and cease accepting new connections. -308 /// -309 /// See [`Connection::close()`] for details. -310 /// -311 /// [`Connection::close()`]: crate::Connection::close -312 pub fn close(&self, error_code: VarInt, reason: &[u8]) { -313 let reason = Bytes::copy_from_slice(reason); -314 let mut endpoint = self.inner.state.lock().unwrap(); -315 endpoint.recv_state.connections.close = Some((error_code, reason.clone())); -316 for sender in endpoint.recv_state.connections.senders.values() { -317 // Ignoring errors from dropped connections -318 let _ = sender.send(ConnectionEvent::Close { -319 error_code, -320 reason: reason.clone(), -321 }); -322 } -323 self.inner.shared.incoming.notify_waiters(); -324 } -325 -326 /// Wait for all connections on the endpoint to be cleanly shut down -327 /// -328 /// Waiting for this condition before exiting ensures that a good-faith effort is made to notify -329 /// peers of recent connection closes, whereas exiting immediately could force them to wait out -330 /// the idle timeout period. +282 /// Replace the server configuration, affecting new incoming connections only +283 /// +284 /// Useful for e.g. refreshing TLS certificates without disrupting existing connections. +285 pub fn set_server_config(&self, server_config: Option<ServerConfig>) { +286 self.inner +287 .state +288 .lock() +289 .unwrap() +290 .inner +291 .set_server_config(server_config.map(Arc::new)) +292 } +293 +294 /// Get the local `SocketAddr` the underlying socket is bound to +295 pub fn local_addr(&self) -> io::Result<SocketAddr> { +296 self.inner.state.lock().unwrap().socket.local_addr() +297 } +298 +299 /// Get the number of connections that are currently open +300 pub fn open_connections(&self) -> usize { +301 self.inner.state.lock().unwrap().inner.open_connections() +302 } +303 +304 /// Close all of this endpoint's connections immediately and cease accepting new connections. +305 /// +306 /// See [`Connection::close()`] for details. +307 /// +308 /// [`Connection::close()`]: crate::Connection::close +309 pub fn close(&self, error_code: VarInt, reason: &[u8]) { +310 let reason = Bytes::copy_from_slice(reason); +311 let mut endpoint = self.inner.state.lock().unwrap(); +312 endpoint.recv_state.connections.close = Some((error_code, reason.clone())); +313 for sender in endpoint.recv_state.connections.senders.values() { +314 // Ignoring errors from dropped connections +315 let _ = sender.send(ConnectionEvent::Close { +316 error_code, +317 reason: reason.clone(), +318 }); +319 } +320 self.inner.shared.incoming.notify_waiters(); +321 } +322 +323 /// Wait for all connections on the endpoint to be cleanly shut down +324 /// +325 /// Waiting for this condition before exiting ensures that a good-faith effort is made to notify +326 /// peers of recent connection closes, whereas exiting immediately could force them to wait out +327 /// the idle timeout period. +328 /// +329 /// Does not proactively close existing connections or cause incoming connections to be +330 /// rejected. Consider calling [`close()`] if that is desired. 331 /// -332 /// Does not proactively close existing connections or cause incoming connections to be -333 /// rejected. Consider calling [`close()`] if that is desired. -334 /// -335 /// [`close()`]: Endpoint::close -336 pub async fn wait_idle(&self) { -337 loop { -338 { -339 let endpoint = &mut *self.inner.state.lock().unwrap(); -340 if endpoint.recv_state.connections.is_empty() { -341 break; -342 } -343 // Construct future while lock is held to avoid race -344 self.inner.shared.idle.notified() -345 } -346 .await; -347 } -348 } -349} -350 -351/// Statistics on [Endpoint] activity -352#[non_exhaustive] -353#[derive(Debug, Default, Copy, Clone)] -354pub struct EndpointStats { -355 /// Cumulative number of Quic handshakes accepted by this [Endpoint] -356 pub accepted_handshakes: u64, -357 /// Cumulative number of Quic handshakes sent from this [Endpoint] -358 pub outgoing_handshakes: u64, -359 /// Cumulative number of Quic handshakes refused on this [Endpoint] -360 pub refused_handshakes: u64, -361 /// Cumulative number of Quic handshakes ignored on this [Endpoint] -362 pub ignored_handshakes: u64, -363} -364 -365/// A future that drives IO on an endpoint -366/// -367/// This task functions as the switch point between the UDP socket object and the -368/// `Endpoint` responsible for routing datagrams to their owning `Connection`. -369/// In order to do so, it also facilitates the exchange of different types of events -370/// flowing between the `Endpoint` and the tasks managing `Connection`s. As such, -371/// running this task is necessary to keep the endpoint's connections running. -372/// -373/// `EndpointDriver` futures terminate when all clones of the `Endpoint` have been dropped, or when -374/// an I/O error occurs. -375#[must_use = "endpoint drivers must be spawned for I/O to occur"] -376#[derive(Debug)] -377pub(crate) struct EndpointDriver(pub(crate) EndpointRef); +332 /// [`close()`]: Endpoint::close +333 pub async fn wait_idle(&self) { +334 loop { +335 { +336 let endpoint = &mut *self.inner.state.lock().unwrap(); +337 if endpoint.recv_state.connections.is_empty() { +338 break; +339 } +340 // Construct future while lock is held to avoid race +341 self.inner.shared.idle.notified() +342 } +343 .await; +344 } +345 } +346} +347 +348/// Statistics on [Endpoint] activity +349#[non_exhaustive] +350#[derive(Debug, Default, Copy, Clone)] +351pub struct EndpointStats { +352 /// Cumulative number of Quic handshakes accepted by this [Endpoint] +353 pub accepted_handshakes: u64, +354 /// Cumulative number of Quic handshakes sent from this [Endpoint] +355 pub outgoing_handshakes: u64, +356 /// Cumulative number of Quic handshakes refused on this [Endpoint] +357 pub refused_handshakes: u64, +358 /// Cumulative number of Quic handshakes ignored on this [Endpoint] +359 pub ignored_handshakes: u64, +360} +361 +362/// A future that drives IO on an endpoint +363/// +364/// This task functions as the switch point between the UDP socket object and the +365/// `Endpoint` responsible for routing datagrams to their owning `Connection`. +366/// In order to do so, it also facilitates the exchange of different types of events +367/// flowing between the `Endpoint` and the tasks managing `Connection`s. As such, +368/// running this task is necessary to keep the endpoint's connections running. +369/// +370/// `EndpointDriver` futures terminate when all clones of the `Endpoint` have been dropped, or when +371/// an I/O error occurs. +372#[must_use = "endpoint drivers must be spawned for I/O to occur"] +373#[derive(Debug)] +374pub(crate) struct EndpointDriver(pub(crate) EndpointRef); +375 +376impl Future for EndpointDriver { +377 type Output = Result<(), io::Error>; 378 -379impl Future for EndpointDriver { -380 type Output = Result<(), io::Error>; -381 -382 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { -383 let mut endpoint = self.0.state.lock().unwrap(); -384 if endpoint.driver.is_none() { -385 endpoint.driver = Some(cx.waker().clone()); -386 } -387 -388 let now = endpoint.runtime.now(); -389 let mut keep_going = false; -390 keep_going |= endpoint.drive_recv(cx, now)?; -391 keep_going |= endpoint.handle_events(cx, &self.0.shared); -392 -393 if !endpoint.recv_state.incoming.is_empty() { -394 self.0.shared.incoming.notify_waiters(); -395 } -396 -397 if endpoint.ref_count == 0 && endpoint.recv_state.connections.is_empty() { -398 Poll::Ready(Ok(())) -399 } else { -400 drop(endpoint); -401 // If there is more work to do schedule the endpoint task again. -402 // `wake_by_ref()` is called outside the lock to minimize -403 // lock contention on a multithreaded runtime. -404 if keep_going { -405 cx.waker().wake_by_ref(); -406 } -407 Poll::Pending -408 } -409 } -410} -411 -412impl Drop for EndpointDriver { -413 fn drop(&mut self) { -414 let mut endpoint = self.0.state.lock().unwrap(); -415 endpoint.driver_lost = true; -416 self.0.shared.incoming.notify_waiters(); -417 // Drop all outgoing channels, signaling the termination of the endpoint to the associated -418 // connections. -419 endpoint.recv_state.connections.senders.clear(); -420 } -421} -422 -423#[derive(Debug)] -424pub(crate) struct EndpointInner { -425 pub(crate) state: Mutex<State>, -426 pub(crate) shared: Shared, -427} -428 -429impl EndpointInner { -430 pub(crate) fn accept( -431 &self, -432 incoming: proto::Incoming, -433 server_config: Option<Arc<ServerConfig>>, -434 ) -> Result<Connecting, ConnectionError> { -435 let mut state = self.state.lock().unwrap(); -436 let mut response_buffer = Vec::new(); -437 let now = state.runtime.now(); -438 match state -439 .inner -440 .accept(incoming, now, &mut response_buffer, server_config) -441 { -442 Ok((handle, conn)) => { -443 state.stats.accepted_handshakes += 1; -444 let sender = state.socket.create_sender(); -445 let runtime = state.runtime.clone(); -446 Ok(state -447 .recv_state -448 .connections -449 .insert(handle, conn, sender, runtime)) -450 } -451 Err(error) => { -452 if let Some(transmit) = error.response { -453 respond(transmit, &response_buffer, &mut state.sender); -454 } -455 Err(error.cause) -456 } -457 } -458 } -459 -460 pub(crate) fn refuse(&self, incoming: proto::Incoming) { -461 let mut state = self.state.lock().unwrap(); -462 state.stats.refused_handshakes += 1; -463 let mut response_buffer = Vec::new(); -464 let transmit = state.inner.refuse(incoming, &mut response_buffer); -465 respond(transmit, &response_buffer, &mut state.sender); -466 } -467 -468 pub(crate) fn retry(&self, incoming: proto::Incoming) -> Result<(), proto::RetryError> { -469 let mut state = self.state.lock().unwrap(); -470 let mut response_buffer = Vec::new(); -471 let transmit = state.inner.retry(incoming, &mut response_buffer)?; -472 respond(transmit, &response_buffer, &mut state.sender); -473 Ok(()) -474 } -475 -476 pub(crate) fn ignore(&self, incoming: proto::Incoming) { -477 let mut state = self.state.lock().unwrap(); -478 state.stats.ignored_handshakes += 1; -479 state.inner.ignore(incoming); -480 } -481} -482 -483#[derive(Debug)] -484pub(crate) struct State { -485 socket: Box<dyn AsyncUdpSocket>, -486 sender: Pin<Box<dyn UdpSender>>, -487 /// During an active migration, abandoned_socket receives traffic -488 /// until the first packet arrives on the new socket. -489 prev_socket: Option<Box<dyn AsyncUdpSocket>>, -490 inner: proto::Endpoint, -491 recv_state: RecvState, -492 driver: Option<Waker>, -493 ipv6: bool, -494 events: mpsc::UnboundedReceiver<(ConnectionHandle, EndpointEvent)>, -495 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver -496 ref_count: usize, -497 driver_lost: bool, -498 runtime: Arc<dyn Runtime>, -499 stats: EndpointStats, -500} -501 -502#[derive(Debug)] -503pub(crate) struct Shared { -504 incoming: Notify, -505 idle: Notify, -506} -507 -508impl State { -509 fn drive_recv(&mut self, cx: &mut Context, now: Instant) -> Result<bool, io::Error> { -510 let get_time = || self.runtime.now(); -511 self.recv_state.recv_limiter.start_cycle(get_time); -512 if let Some(socket) = &mut self.prev_socket { -513 // We don't care about the `PollProgress` from old sockets. -514 let poll_res = self.recv_state.poll_socket( -515 cx, -516 &mut self.inner, -517 &mut **socket, -518 &mut self.sender, -519 &*self.runtime, -520 now, -521 ); -522 if poll_res.is_err() { -523 self.prev_socket = None; -524 } -525 }; -526 let poll_res = self.recv_state.poll_socket( -527 cx, -528 &mut self.inner, -529 &mut *self.socket, -530 &mut self.sender, -531 &*self.runtime, -532 now, -533 ); -534 self.recv_state.recv_limiter.finish_cycle(get_time); -535 let poll_res = poll_res?; -536 if poll_res.received_connection_packet { -537 // Traffic has arrived on self.socket, therefore there is no need for the abandoned -538 // one anymore. TODO: Account for multiple outgoing connections. -539 self.prev_socket = None; -540 } -541 Ok(poll_res.keep_going) -542 } -543 -544 fn handle_events(&mut self, cx: &mut Context, shared: &Shared) -> bool { -545 for _ in 0..IO_LOOP_BOUND { -546 let (ch, event) = match self.events.poll_recv(cx) { -547 Poll::Ready(Some(x)) => x, -548 Poll::Ready(None) => unreachable!("EndpointInner owns one sender"), -549 Poll::Pending => { -550 return false; -551 } -552 }; -553 -554 if event.is_drained() { -555 self.recv_state.connections.senders.remove(&ch); -556 if self.recv_state.connections.is_empty() { -557 shared.idle.notify_waiters(); -558 } -559 } -560 let Some(event) = self.inner.handle_event(ch, event) else { -561 continue; -562 }; -563 // Ignoring errors from dropped connections that haven't yet been cleaned up -564 let _ = self -565 .recv_state -566 .connections -567 .senders -568 .get_mut(&ch) -569 .unwrap() -570 .send(ConnectionEvent::Proto(event)); -571 } -572 -573 true -574 } -575} -576 -577impl Drop for State { -578 fn drop(&mut self) { -579 for incoming in self.recv_state.incoming.drain(..) { -580 self.inner.ignore(incoming); -581 } -582 } -583} -584 -585fn respond( -586 transmit: proto::Transmit, -587 response_buffer: &[u8], -588 sender: &mut Pin<Box<dyn UdpSender>>, -589) { -590 // Send if there's kernel buffer space; otherwise, drop it -591 // -592 // As an endpoint-generated packet, we know this is an -593 // immediate, stateless response to an unconnected peer, -594 // one of: -595 // -596 // - A version negotiation response due to an unknown version -597 // - A `CLOSE` due to a malformed or unwanted connection attempt -598 // - A stateless reset due to an unrecognized connection -599 // - A `Retry` packet due to a connection attempt when -600 // `use_retry` is set -601 // -602 // In each case, a well-behaved peer can be trusted to retry a -603 // few times, which is guaranteed to produce the same response -604 // from us. Repeated failures might at worst cause a peer's new -605 // connection attempt to time out, which is acceptable if we're -606 // under such heavy load that there's never room for this code -607 // to transmit. This is morally equivalent to the packet getting -608 // lost due to congestion further along the link, which -609 // similarly relies on peer retries for recovery. -610 -611 // Copied from rust 1.85's std::task::Waker::noop() implementation for backwards compatibility -612 const NOOP: RawWaker = { -613 const VTABLE: RawWakerVTable = RawWakerVTable::new( -614 // Cloning just returns a new no-op raw waker -615 |_| NOOP, -616 // `wake` does nothing +379 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { +380 let mut endpoint = self.0.state.lock().unwrap(); +381 if endpoint.driver.is_none() { +382 endpoint.driver = Some(cx.waker().clone()); +383 } +384 +385 let now = endpoint.runtime.now(); +386 let mut keep_going = false; +387 keep_going |= endpoint.drive_recv(cx, now)?; +388 keep_going |= endpoint.handle_events(cx, &self.0.shared); +389 +390 if !endpoint.recv_state.incoming.is_empty() { +391 self.0.shared.incoming.notify_waiters(); +392 } +393 +394 if endpoint.ref_count == 0 && endpoint.recv_state.connections.is_empty() { +395 Poll::Ready(Ok(())) +396 } else { +397 drop(endpoint); +398 // If there is more work to do schedule the endpoint task again. +399 // `wake_by_ref()` is called outside the lock to minimize +400 // lock contention on a multithreaded runtime. +401 if keep_going { +402 cx.waker().wake_by_ref(); +403 } +404 Poll::Pending +405 } +406 } +407} +408 +409impl Drop for EndpointDriver { +410 fn drop(&mut self) { +411 let mut endpoint = self.0.state.lock().unwrap(); +412 endpoint.driver_lost = true; +413 self.0.shared.incoming.notify_waiters(); +414 // Drop all outgoing channels, signaling the termination of the endpoint to the associated +415 // connections. +416 endpoint.recv_state.connections.senders.clear(); +417 } +418} +419 +420#[derive(Debug)] +421pub(crate) struct EndpointInner { +422 pub(crate) state: Mutex<State>, +423 pub(crate) shared: Shared, +424} +425 +426impl EndpointInner { +427 pub(crate) fn accept( +428 &self, +429 incoming: proto::Incoming, +430 server_config: Option<Arc<ServerConfig>>, +431 ) -> Result<Connecting, ConnectionError> { +432 let mut state = self.state.lock().unwrap(); +433 let mut response_buffer = Vec::new(); +434 let now = state.runtime.now(); +435 match state +436 .inner +437 .accept(incoming, now, &mut response_buffer, server_config) +438 { +439 Ok((handle, conn)) => { +440 state.stats.accepted_handshakes += 1; +441 let sender = state.socket.create_sender(); +442 let runtime = state.runtime.clone(); +443 Ok(state +444 .recv_state +445 .connections +446 .insert(handle, conn, sender, runtime)) +447 } +448 Err(error) => { +449 if let Some(transmit) = error.response { +450 respond(transmit, &response_buffer, &mut state.sender); +451 } +452 Err(error.cause) +453 } +454 } +455 } +456 +457 pub(crate) fn refuse(&self, incoming: proto::Incoming) { +458 let mut state = self.state.lock().unwrap(); +459 state.stats.refused_handshakes += 1; +460 let mut response_buffer = Vec::new(); +461 let transmit = state.inner.refuse(incoming, &mut response_buffer); +462 respond(transmit, &response_buffer, &mut state.sender); +463 } +464 +465 pub(crate) fn retry(&self, incoming: proto::Incoming) -> Result<(), proto::RetryError> { +466 let mut state = self.state.lock().unwrap(); +467 let mut response_buffer = Vec::new(); +468 let transmit = state.inner.retry(incoming, &mut response_buffer)?; +469 respond(transmit, &response_buffer, &mut state.sender); +470 Ok(()) +471 } +472 +473 pub(crate) fn ignore(&self, incoming: proto::Incoming) { +474 let mut state = self.state.lock().unwrap(); +475 state.stats.ignored_handshakes += 1; +476 state.inner.ignore(incoming); +477 } +478} +479 +480#[derive(Debug)] +481pub(crate) struct State { +482 socket: Box<dyn AsyncUdpSocket>, +483 sender: Pin<Box<dyn UdpSender>>, +484 /// During an active migration, abandoned_socket receives traffic +485 /// until the first packet arrives on the new socket. +486 prev_socket: Option<Box<dyn AsyncUdpSocket>>, +487 inner: proto::Endpoint, +488 recv_state: RecvState, +489 driver: Option<Waker>, +490 ipv6: bool, +491 events: mpsc::UnboundedReceiver<(ConnectionHandle, EndpointEvent)>, +492 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver +493 ref_count: usize, +494 driver_lost: bool, +495 runtime: Arc<dyn Runtime>, +496 stats: EndpointStats, +497 default_client_config: Option<ClientConfig>, +498} +499 +500#[derive(Debug)] +501pub(crate) struct Shared { +502 incoming: Notify, +503 idle: Notify, +504} +505 +506impl State { +507 fn drive_recv(&mut self, cx: &mut Context<'_>, now: Instant) -> Result<bool, io::Error> { +508 let get_time = || self.runtime.now(); +509 self.recv_state.recv_limiter.start_cycle(get_time); +510 if let Some(socket) = &mut self.prev_socket { +511 // We don't care about the `PollProgress` from old sockets. +512 let poll_res = self.recv_state.poll_socket( +513 cx, +514 &mut self.inner, +515 &mut **socket, +516 &mut self.sender, +517 &*self.runtime, +518 now, +519 ); +520 if poll_res.is_err() { +521 self.prev_socket = None; +522 } +523 }; +524 let poll_res = self.recv_state.poll_socket( +525 cx, +526 &mut self.inner, +527 &mut *self.socket, +528 &mut self.sender, +529 &*self.runtime, +530 now, +531 ); +532 self.recv_state.recv_limiter.finish_cycle(get_time); +533 let poll_res = poll_res?; +534 if poll_res.received_connection_packet { +535 // Traffic has arrived on self.socket, therefore there is no need for the abandoned +536 // one anymore. TODO: Account for multiple outgoing connections. +537 self.prev_socket = None; +538 } +539 Ok(poll_res.keep_going) +540 } +541 +542 fn handle_events(&mut self, cx: &mut Context<'_>, shared: &Shared) -> bool { +543 for _ in 0..IO_LOOP_BOUND { +544 let (ch, event) = match self.events.poll_recv(cx) { +545 Poll::Ready(Some(x)) => x, +546 Poll::Ready(None) => unreachable!("EndpointInner owns one sender"), +547 Poll::Pending => { +548 return false; +549 } +550 }; +551 +552 if event.is_drained() { +553 self.recv_state.connections.senders.remove(&ch); +554 if self.recv_state.connections.is_empty() { +555 shared.idle.notify_waiters(); +556 } +557 } +558 let Some(event) = self.inner.handle_event(ch, event) else { +559 continue; +560 }; +561 // Ignoring errors from dropped connections that haven't yet been cleaned up +562 let _ = self +563 .recv_state +564 .connections +565 .senders +566 .get_mut(&ch) +567 .unwrap() +568 .send(ConnectionEvent::Proto(event)); +569 } +570 +571 true +572 } +573} +574 +575impl Drop for State { +576 fn drop(&mut self) { +577 for incoming in self.recv_state.incoming.drain(..) { +578 self.inner.ignore(incoming); +579 } +580 } +581} +582 +583fn respond( +584 transmit: proto::Transmit, +585 response_buffer: &[u8], +586 sender: &mut Pin<Box<dyn UdpSender>>, +587) { +588 // Send if there's kernel buffer space; otherwise, drop it +589 // +590 // As an endpoint-generated packet, we know this is an +591 // immediate, stateless response to an unconnected peer, +592 // one of: +593 // +594 // - A version negotiation response due to an unknown version +595 // - A `CLOSE` due to a malformed or unwanted connection attempt +596 // - A stateless reset due to an unrecognized connection +597 // - A `Retry` packet due to a connection attempt when +598 // `use_retry` is set +599 // +600 // In each case, a well-behaved peer can be trusted to retry a +601 // few times, which is guaranteed to produce the same response +602 // from us. Repeated failures might at worst cause a peer's new +603 // connection attempt to time out, which is acceptable if we're +604 // under such heavy load that there's never room for this code +605 // to transmit. This is morally equivalent to the packet getting +606 // lost due to congestion further along the link, which +607 // similarly relies on peer retries for recovery. +608 +609 // Copied from rust 1.85's std::task::Waker::noop() implementation for backwards compatibility +610 const NOOP: RawWaker = { +611 const VTABLE: RawWakerVTable = RawWakerVTable::new( +612 // Cloning just returns a new no-op raw waker +613 |_| NOOP, +614 // `wake` does nothing +615 |_| {}, +616 // `wake_by_ref` does nothing 617 |_| {}, -618 // `wake_by_ref` does nothing +618 // Dropping does nothing as we don't allocate anything 619 |_| {}, -620 // Dropping does nothing as we don't allocate anything -621 |_| {}, -622 ); -623 RawWaker::new(std::ptr::null(), &VTABLE) -624 }; -625 // SAFETY: Copied from rust stdlib, the NOOP waker is thread-safe and doesn't violate the RawWakerVTable contract, -626 // it doesn't access the data pointer at all. -627 let waker = unsafe { Waker::from_raw(NOOP) }; -628 let mut cx = Context::from_waker(&waker); -629 _ = sender.as_mut().poll_send( -630 &udp_transmit(&transmit, &response_buffer[..transmit.size]), -631 &mut cx, -632 ); -633} -634 -635#[inline] -636fn proto_ecn(ecn: udp::EcnCodepoint) -> proto::EcnCodepoint { -637 match ecn { -638 udp::EcnCodepoint::Ect0 => proto::EcnCodepoint::Ect0, -639 udp::EcnCodepoint::Ect1 => proto::EcnCodepoint::Ect1, -640 udp::EcnCodepoint::Ce => proto::EcnCodepoint::Ce, -641 } -642} -643 -644#[derive(Debug)] -645struct ConnectionSet { -646 /// Senders for communicating with the endpoint's connections -647 senders: FxHashMap<ConnectionHandle, mpsc::UnboundedSender<ConnectionEvent>>, -648 /// Stored to give out clones to new ConnectionInners -649 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -650 /// Set if the endpoint has been manually closed -651 close: Option<(VarInt, Bytes)>, -652} -653 -654impl ConnectionSet { -655 fn insert( -656 &mut self, -657 handle: ConnectionHandle, -658 conn: proto::Connection, -659 sender: Pin<Box<dyn UdpSender>>, -660 runtime: Arc<dyn Runtime>, -661 ) -> Connecting { -662 let (send, recv) = mpsc::unbounded_channel(); -663 if let Some((error_code, ref reason)) = self.close { -664 send.send(ConnectionEvent::Close { -665 error_code, -666 reason: reason.clone(), -667 }) -668 .unwrap(); -669 } -670 self.senders.insert(handle, send); -671 Connecting::new(handle, conn, self.sender.clone(), recv, sender, runtime) -672 } -673 -674 fn is_empty(&self) -> bool { -675 self.senders.is_empty() -676 } -677} -678 -679pub(crate) fn ensure_ipv6(x: SocketAddr) -> SocketAddrV6 { -680 match x { -681 SocketAddr::V6(x) => x, -682 SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0), -683 } -684} -685 -686pin_project! { -687 /// Future produced by [`Endpoint::accept`] -688 pub struct Accept<'a> { -689 endpoint: &'a Endpoint, -690 #[pin] -691 notify: Notified<'a>, -692 } -693} -694 -695impl Future for Accept<'_> { -696 type Output = Option<Incoming>; -697 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { -698 let mut this = self.project(); -699 let mut endpoint = this.endpoint.inner.state.lock().unwrap(); -700 if endpoint.driver_lost { -701 return Poll::Ready(None); -702 } -703 if let Some(incoming) = endpoint.recv_state.incoming.pop_front() { -704 // Release the mutex lock on endpoint so cloning it doesn't deadlock -705 drop(endpoint); -706 let incoming = Incoming::new(incoming, this.endpoint.inner.clone()); -707 return Poll::Ready(Some(incoming)); -708 } -709 if endpoint.recv_state.connections.close.is_some() { -710 return Poll::Ready(None); -711 } -712 loop { -713 match this.notify.as_mut().poll(ctx) { -714 // `state` lock ensures we didn't race with readiness -715 Poll::Pending => return Poll::Pending, -716 // Spurious wakeup, get a new future -717 Poll::Ready(()) => this -718 .notify -719 .set(this.endpoint.inner.shared.incoming.notified()), -720 } -721 } -722 } -723} -724 -725#[derive(Debug)] -726pub(crate) struct EndpointRef(Arc<EndpointInner>); -727 -728impl EndpointRef { -729 pub(crate) fn new( -730 socket: Box<dyn AsyncUdpSocket>, -731 inner: proto::Endpoint, -732 ipv6: bool, -733 runtime: Arc<dyn Runtime>, -734 ) -> Self { -735 let (sender, events) = mpsc::unbounded_channel(); -736 let recv_state = RecvState::new(sender, socket.max_receive_segments(), &inner); -737 let sender = socket.create_sender(); -738 Self(Arc::new(EndpointInner { -739 shared: Shared { -740 incoming: Notify::new(), -741 idle: Notify::new(), -742 }, -743 state: Mutex::new(State { -744 socket, -745 sender, -746 prev_socket: None, -747 inner, -748 ipv6, -749 events, -750 driver: None, -751 ref_count: 0, -752 driver_lost: false, -753 recv_state, -754 runtime, -755 stats: EndpointStats::default(), -756 }), -757 })) -758 } -759} -760 -761impl Clone for EndpointRef { -762 fn clone(&self) -> Self { -763 self.0.state.lock().unwrap().ref_count += 1; -764 Self(self.0.clone()) -765 } -766} -767 -768impl Drop for EndpointRef { -769 fn drop(&mut self) { -770 let endpoint = &mut *self.0.state.lock().unwrap(); -771 if let Some(x) = endpoint.ref_count.checked_sub(1) { -772 endpoint.ref_count = x; -773 if x == 0 { -774 // If the driver is about to be on its own, ensure it can shut down if the last -775 // connection is gone. -776 if let Some(task) = endpoint.driver.take() { -777 task.wake(); -778 } -779 } -780 } -781 } -782} -783 -784impl std::ops::Deref for EndpointRef { -785 type Target = EndpointInner; -786 fn deref(&self) -> &Self::Target { -787 &self.0 -788 } -789} -790 -791/// State directly involved in handling incoming packets -792struct RecvState { -793 incoming: VecDeque<proto::Incoming>, -794 connections: ConnectionSet, -795 recv_buf: Box<[u8]>, -796 recv_limiter: WorkLimiter, -797} -798 -799impl RecvState { -800 fn new( -801 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -802 max_receive_segments: NonZeroUsize, -803 endpoint: &proto::Endpoint, -804 ) -> Self { -805 let recv_buf = vec![ -806 0; -807 endpoint.config().get_max_udp_payload_size().min(64 * 1024) as usize -808 * max_receive_segments.get() -809 * BATCH_SIZE -810 ]; -811 Self { -812 connections: ConnectionSet { -813 senders: FxHashMap::default(), -814 sender, -815 close: None, -816 }, -817 incoming: VecDeque::new(), -818 recv_buf: recv_buf.into(), -819 recv_limiter: WorkLimiter::new(RECV_TIME_BOUND), -820 } -821 } -822 -823 fn poll_socket( -824 &mut self, -825 cx: &mut Context, -826 endpoint: &mut proto::Endpoint, -827 socket: &mut dyn AsyncUdpSocket, -828 sender: &mut Pin<Box<dyn UdpSender>>, -829 runtime: &dyn Runtime, -830 now: Instant, -831 ) -> Result<PollProgress, io::Error> { -832 let mut received_connection_packet = false; -833 let mut metas = [RecvMeta::default(); BATCH_SIZE]; -834 let mut iovs: [IoSliceMut; BATCH_SIZE] = { -835 let mut bufs = self -836 .recv_buf -837 .chunks_mut(self.recv_buf.len() / BATCH_SIZE) -838 .map(IoSliceMut::new); -839 -840 // expect() safe as self.recv_buf is chunked into BATCH_SIZE items -841 // and iovs will be of size BATCH_SIZE, thus from_fn is called -842 // exactly BATCH_SIZE times. -843 std::array::from_fn(|_| bufs.next().expect("BATCH_SIZE elements")) -844 }; -845 loop { -846 match socket.poll_recv(cx, &mut iovs, &mut metas) { -847 Poll::Ready(Ok(msgs)) => { -848 self.recv_limiter.record_work(msgs); -849 for (meta, buf) in metas.iter().zip(iovs.iter()).take(msgs) { -850 let mut data: BytesMut = buf[0..meta.len].into(); -851 while !data.is_empty() { -852 let buf = data.split_to(meta.stride.min(data.len())); -853 let mut response_buffer = Vec::new(); -854 let addresses = FourTuple { -855 remote: meta.addr, -856 local_ip: meta.dst_ip, -857 }; -858 match endpoint.handle( -859 now, -860 addresses, -861 meta.ecn.map(proto_ecn), -862 buf, -863 &mut response_buffer, -864 ) { -865 Some(DatagramEvent::NewConnection(incoming)) => { -866 if self.connections.close.is_none() { -867 self.incoming.push_back(incoming); -868 } else { -869 let transmit = -870 endpoint.refuse(incoming, &mut response_buffer); -871 respond(transmit, &response_buffer, sender); -872 } -873 } -874 Some(DatagramEvent::ConnectionEvent(handle, event)) => { -875 // Ignoring errors from dropped connections that haven't yet been cleaned up -876 received_connection_packet = true; -877 let _ = self -878 .connections -879 .senders -880 .get_mut(&handle) -881 .unwrap() -882 .send(ConnectionEvent::Proto(event)); -883 } -884 Some(DatagramEvent::Response(transmit)) => { -885 respond(transmit, &response_buffer, sender); -886 } -887 None => {} -888 } -889 } -890 } -891 } -892 Poll::Pending => { -893 return Ok(PollProgress { -894 received_connection_packet, -895 keep_going: false, -896 }); -897 } -898 // Ignore ECONNRESET as it's undefined in QUIC and may be injected by an -899 // attacker -900 Poll::Ready(Err(ref e)) if e.kind() == io::ErrorKind::ConnectionReset => { -901 continue; -902 } -903 Poll::Ready(Err(e)) => { -904 return Err(e); -905 } -906 } -907 if !self.recv_limiter.allow_work(|| runtime.now()) { -908 return Ok(PollProgress { -909 received_connection_packet, -910 keep_going: true, -911 }); -912 } -913 } -914 } -915} -916 -917impl fmt::Debug for RecvState { -918 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -919 f.debug_struct("RecvState") -920 .field("incoming", &self.incoming) -921 .field("connections", &self.connections) -922 // recv_buf too large -923 .field("recv_limiter", &self.recv_limiter) -924 .finish_non_exhaustive() -925 } -926} -927 -928#[derive(Default)] -929struct PollProgress { -930 /// Whether a datagram was routed to an existing connection -931 received_connection_packet: bool, -932 /// Whether datagram handling was interrupted early by the work limiter for fairness -933 keep_going: bool, -934}

\ No newline at end of file +620 ); +621 RawWaker::new(std::ptr::null(), &VTABLE) +622 }; +623 // SAFETY: Copied from rust stdlib, the NOOP waker is thread-safe and doesn't violate the RawWakerVTable contract, +624 // it doesn't access the data pointer at all. +625 let waker = unsafe { Waker::from_raw(NOOP) }; +626 let mut cx = Context::from_waker(&waker); +627 _ = sender.as_mut().poll_send( +628 &udp_transmit(&transmit, &response_buffer[..transmit.size]), +629 &mut cx, +630 ); +631} +632 +633#[inline] +634fn proto_ecn(ecn: udp::EcnCodepoint) -> proto::EcnCodepoint { +635 match ecn { +636 udp::EcnCodepoint::Ect0 => proto::EcnCodepoint::Ect0, +637 udp::EcnCodepoint::Ect1 => proto::EcnCodepoint::Ect1, +638 udp::EcnCodepoint::Ce => proto::EcnCodepoint::Ce, +639 } +640} +641 +642#[derive(Debug)] +643struct ConnectionSet { +644 /// Senders for communicating with the endpoint's connections +645 senders: FxHashMap<ConnectionHandle, mpsc::UnboundedSender<ConnectionEvent>>, +646 /// Stored to give out clones to new ConnectionInners +647 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +648 /// Set if the endpoint has been manually closed +649 close: Option<(VarInt, Bytes)>, +650} +651 +652impl ConnectionSet { +653 fn insert( +654 &mut self, +655 handle: ConnectionHandle, +656 conn: proto::Connection, +657 sender: Pin<Box<dyn UdpSender>>, +658 runtime: Arc<dyn Runtime>, +659 ) -> Connecting { +660 let (send, recv) = mpsc::unbounded_channel(); +661 if let Some((error_code, ref reason)) = self.close { +662 send.send(ConnectionEvent::Close { +663 error_code, +664 reason: reason.clone(), +665 }) +666 .unwrap(); +667 } +668 self.senders.insert(handle, send); +669 Connecting::new(handle, conn, self.sender.clone(), recv, sender, runtime) +670 } +671 +672 fn is_empty(&self) -> bool { +673 self.senders.is_empty() +674 } +675} +676 +677pub(crate) fn ensure_ipv6(x: SocketAddr) -> SocketAddrV6 { +678 match x { +679 SocketAddr::V6(x) => x, +680 SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0), +681 } +682} +683 +684pin_project! { +685 /// Future produced by [`Endpoint::accept`] +686 pub struct Accept<'a> { +687 endpoint: &'a Endpoint, +688 #[pin] +689 notify: Notified<'a>, +690 } +691} +692 +693impl Future for Accept<'_> { +694 type Output = Option<Incoming>; +695 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> { +696 let mut this = self.project(); +697 let mut endpoint = this.endpoint.inner.state.lock().unwrap(); +698 if endpoint.driver_lost { +699 return Poll::Ready(None); +700 } +701 if let Some(incoming) = endpoint.recv_state.incoming.pop_front() { +702 // Release the mutex lock on endpoint so cloning it doesn't deadlock +703 drop(endpoint); +704 let incoming = Incoming::new(incoming, this.endpoint.inner.clone()); +705 return Poll::Ready(Some(incoming)); +706 } +707 if endpoint.recv_state.connections.close.is_some() { +708 return Poll::Ready(None); +709 } +710 loop { +711 match this.notify.as_mut().poll(ctx) { +712 // `state` lock ensures we didn't race with readiness +713 Poll::Pending => return Poll::Pending, +714 // Spurious wakeup, get a new future +715 Poll::Ready(()) => this +716 .notify +717 .set(this.endpoint.inner.shared.incoming.notified()), +718 } +719 } +720 } +721} +722 +723#[derive(Debug)] +724pub(crate) struct EndpointRef(Arc<EndpointInner>); +725 +726impl EndpointRef { +727 pub(crate) fn new( +728 socket: Box<dyn AsyncUdpSocket>, +729 inner: proto::Endpoint, +730 ipv6: bool, +731 runtime: Arc<dyn Runtime>, +732 ) -> Self { +733 let (sender, events) = mpsc::unbounded_channel(); +734 let recv_state = RecvState::new(sender, socket.max_receive_segments(), &inner); +735 let sender = socket.create_sender(); +736 Self(Arc::new(EndpointInner { +737 shared: Shared { +738 incoming: Notify::new(), +739 idle: Notify::new(), +740 }, +741 state: Mutex::new(State { +742 socket, +743 sender, +744 prev_socket: None, +745 inner, +746 ipv6, +747 events, +748 driver: None, +749 ref_count: 0, +750 driver_lost: false, +751 recv_state, +752 runtime, +753 stats: EndpointStats::default(), +754 default_client_config: None, +755 }), +756 })) +757 } +758} +759 +760impl Clone for EndpointRef { +761 fn clone(&self) -> Self { +762 self.0.state.lock().unwrap().ref_count += 1; +763 Self(self.0.clone()) +764 } +765} +766 +767impl Drop for EndpointRef { +768 fn drop(&mut self) { +769 let endpoint = &mut *self.0.state.lock().unwrap(); +770 if let Some(x) = endpoint.ref_count.checked_sub(1) { +771 endpoint.ref_count = x; +772 if x == 0 { +773 // If the driver is about to be on its own, ensure it can shut down if the last +774 // connection is gone. +775 if let Some(task) = endpoint.driver.take() { +776 task.wake(); +777 } +778 } +779 } +780 } +781} +782 +783impl std::ops::Deref for EndpointRef { +784 type Target = EndpointInner; +785 fn deref(&self) -> &Self::Target { +786 &self.0 +787 } +788} +789 +790/// State directly involved in handling incoming packets +791struct RecvState { +792 incoming: VecDeque<proto::Incoming>, +793 connections: ConnectionSet, +794 recv_buf: Box<[u8]>, +795 recv_limiter: WorkLimiter, +796} +797 +798impl RecvState { +799 fn new( +800 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +801 max_receive_segments: NonZeroUsize, +802 endpoint: &proto::Endpoint, +803 ) -> Self { +804 let recv_buf = vec![ +805 0; +806 endpoint.config().get_max_udp_payload_size().min(64 * 1024) as usize +807 * max_receive_segments.get() +808 * BATCH_SIZE +809 ]; +810 Self { +811 connections: ConnectionSet { +812 senders: FxHashMap::default(), +813 sender, +814 close: None, +815 }, +816 incoming: VecDeque::new(), +817 recv_buf: recv_buf.into(), +818 recv_limiter: WorkLimiter::new(RECV_TIME_BOUND), +819 } +820 } +821 +822 fn poll_socket( +823 &mut self, +824 cx: &mut Context<'_>, +825 endpoint: &mut proto::Endpoint, +826 socket: &mut dyn AsyncUdpSocket, +827 sender: &mut Pin<Box<dyn UdpSender>>, +828 runtime: &dyn Runtime, +829 now: Instant, +830 ) -> Result<PollProgress, io::Error> { +831 let mut received_connection_packet = false; +832 let mut metas = [RecvMeta::default(); BATCH_SIZE]; +833 let mut iovs: [IoSliceMut<'_>; BATCH_SIZE] = { +834 let mut bufs = self +835 .recv_buf +836 .chunks_mut(self.recv_buf.len() / BATCH_SIZE) +837 .map(IoSliceMut::new); +838 +839 // expect() safe as self.recv_buf is chunked into BATCH_SIZE items +840 // and iovs will be of size BATCH_SIZE, thus from_fn is called +841 // exactly BATCH_SIZE times. +842 std::array::from_fn(|_| bufs.next().expect("BATCH_SIZE elements")) +843 }; +844 loop { +845 match socket.poll_recv(cx, &mut iovs, &mut metas) { +846 Poll::Ready(Ok(msgs)) => { +847 self.recv_limiter.record_work(msgs); +848 for (meta, buf) in metas.iter().zip(iovs.iter()).take(msgs) { +849 let mut data: BytesMut = buf[0..meta.len].into(); +850 while !data.is_empty() { +851 let buf = data.split_to(meta.stride.min(data.len())); +852 let mut response_buffer = Vec::new(); +853 let addresses = FourTuple { +854 remote: meta.addr, +855 local_ip: meta.dst_ip, +856 }; +857 match endpoint.handle( +858 now, +859 addresses, +860 meta.ecn.map(proto_ecn), +861 buf, +862 &mut response_buffer, +863 ) { +864 Some(DatagramEvent::NewConnection(incoming)) => { +865 if self.connections.close.is_none() { +866 self.incoming.push_back(incoming); +867 } else { +868 let transmit = +869 endpoint.refuse(incoming, &mut response_buffer); +870 respond(transmit, &response_buffer, sender); +871 } +872 } +873 Some(DatagramEvent::ConnectionEvent(handle, event)) => { +874 // Ignoring errors from dropped connections that haven't yet been cleaned up +875 received_connection_packet = true; +876 let _ = self +877 .connections +878 .senders +879 .get_mut(&handle) +880 .unwrap() +881 .send(ConnectionEvent::Proto(event)); +882 } +883 Some(DatagramEvent::Response(transmit)) => { +884 respond(transmit, &response_buffer, sender); +885 } +886 None => {} +887 } +888 } +889 } +890 } +891 Poll::Pending => { +892 return Ok(PollProgress { +893 received_connection_packet, +894 keep_going: false, +895 }); +896 } +897 // Ignore ECONNRESET as it's undefined in QUIC and may be injected by an +898 // attacker +899 Poll::Ready(Err(ref e)) if e.kind() == io::ErrorKind::ConnectionReset => { +900 continue; +901 } +902 Poll::Ready(Err(e)) => { +903 return Err(e); +904 } +905 } +906 if !self.recv_limiter.allow_work(|| runtime.now()) { +907 return Ok(PollProgress { +908 received_connection_packet, +909 keep_going: true, +910 }); +911 } +912 } +913 } +914} +915 +916impl fmt::Debug for RecvState { +917 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +918 f.debug_struct("RecvState") +919 .field("incoming", &self.incoming) +920 .field("connections", &self.connections) +921 // recv_buf too large +922 .field("recv_limiter", &self.recv_limiter) +923 .finish_non_exhaustive() +924 } +925} +926 +927#[derive(Default)] +928struct PollProgress { +929 /// Whether a datagram was routed to an existing connection +930 received_connection_packet: bool, +931 /// Whether datagram handling was interrupted early by the work limiter for fairness +932 keep_going: bool, +933}
\ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn/incoming.rs.html b/pr/255/docs/src/iroh_quinn/incoming.rs.html index a9d589515..666f6fccd 100644 --- a/pr/255/docs/src/iroh_quinn/incoming.rs.html +++ b/pr/255/docs/src/iroh_quinn/incoming.rs.html @@ -134,7 +134,7 @@ 134impl Future for IncomingFuture { 135 type Output = Result<Connection, ConnectionError>; 136 -137 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +137 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 138 match &mut self.0 { 139 Ok(connecting) => Pin::new(connecting).poll(cx), 140 Err(e) => Poll::Ready(Err(e.clone())), diff --git a/pr/255/docs/src/iroh_quinn/lib.rs.html b/pr/255/docs/src/iroh_quinn/lib.rs.html index 2411dab70..bd0410251 100644 --- a/pr/255/docs/src/iroh_quinn/lib.rs.html +++ b/pr/255/docs/src/iroh_quinn/lib.rs.html @@ -38,103 +38,101 @@ 38//! with a domain name--then as with TLS, self-signed certificates can be used to provide 39//! encryption alone. 40#![warn(missing_docs)] -41#![warn(unreachable_pub)] -42#![warn(clippy::use_self)] +41 +42use std::pin::Pin; 43 -44use std::pin::Pin; -45 -46mod connection; -47mod endpoint; -48mod incoming; -49mod mutex; -50mod path; -51mod recv_stream; -52mod runtime; -53mod send_stream; -54mod work_limiter; -55 -56#[cfg(not(wasm_browser))] -57pub(crate) use std::time::{Duration, Instant}; -58#[cfg(wasm_browser)] -59pub(crate) use web_time::{Duration, Instant}; -60 -61#[cfg(feature = "bloom")] -62pub use proto::BloomTokenLog; -63pub use proto::{ -64 AckFrequencyConfig, ApplicationClose, Chunk, ClientConfig, ClosedStream, ConfigError, -65 ConnectError, ConnectionClose, ConnectionError, ConnectionId, ConnectionIdGenerator, -66 ConnectionStats, Dir, EcnCodepoint, EndpointConfig, FrameStats, FrameType, IdleTimeout, -67 MtuDiscoveryConfig, NoneTokenLog, NoneTokenStore, PathId, PathStats, ServerConfig, Side, -68 StdSystemTime, StreamId, TimeSource, TokenLog, TokenMemoryCache, TokenReuseError, TokenStore, -69 Transmit, TransportConfig, TransportErrorCode, UdpStats, ValidationTokenConfig, VarInt, -70 VarIntBoundsExceeded, Written, congestion, crypto, -71}; -72#[cfg(feature = "qlog")] -73pub use proto::{QlogConfig, QlogFactory, QlogFileFactory}; -74#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))] -75pub use rustls; -76pub use udp; -77 -78pub use crate::connection::{ -79 AcceptBi, AcceptUni, Connecting, Connection, OnClosed, OpenBi, OpenUni, ReadDatagram, -80 SendDatagram, SendDatagramError, WeakConnectionHandle, ZeroRttAccepted, -81}; -82pub use crate::endpoint::{Accept, Endpoint, EndpointStats}; -83pub use crate::incoming::{Incoming, IncomingFuture, RetryError}; -84pub use crate::path::{OpenPath, Path}; -85pub use crate::recv_stream::{ -86 ReadError, ReadExactError, ReadToEndError, RecvStream, ResetError, UnorderedRecvStream, -87}; -88#[cfg(feature = "runtime-smol")] -89pub use crate::runtime::SmolRuntime; -90#[cfg(feature = "runtime-tokio")] -91pub use crate::runtime::TokioRuntime; -92#[cfg(any(feature = "runtime-tokio", feature = "runtime-smol"))] -93pub use crate::runtime::default_runtime; -94pub use crate::runtime::{AsyncTimer, AsyncUdpSocket, Runtime, UdpSender}; -95pub use crate::send_stream::{SendStream, StoppedError, WriteError}; -96 -97#[cfg(test)] -98mod tests; -99 -100#[derive(Debug)] -101enum ConnectionEvent { -102 Close { -103 error_code: VarInt, -104 reason: bytes::Bytes, -105 }, -106 Proto(proto::ConnectionEvent), -107 Rebind(Pin<Box<dyn UdpSender>>), -108} -109 -110fn udp_transmit<'a>(t: &proto::Transmit, buffer: &'a [u8]) -> udp::Transmit<'a> { -111 udp::Transmit { -112 destination: t.destination, -113 ecn: t.ecn.map(udp_ecn), -114 contents: buffer, -115 segment_size: t.segment_size, -116 src_ip: t.src_ip, -117 } -118} -119 -120fn udp_ecn(ecn: proto::EcnCodepoint) -> udp::EcnCodepoint { -121 match ecn { -122 proto::EcnCodepoint::Ect0 => udp::EcnCodepoint::Ect0, -123 proto::EcnCodepoint::Ect1 => udp::EcnCodepoint::Ect1, -124 proto::EcnCodepoint::Ce => udp::EcnCodepoint::Ce, -125 } -126} -127 -128/// Maximum number of datagrams processed in send/recv calls to make before moving on to other processing -129/// -130/// This helps ensure we don't starve anything when the CPU is slower than the link. -131/// Value is selected by picking a low number which didn't degrade throughput in benchmarks. -132const IO_LOOP_BOUND: usize = 160; -133 -134/// The maximum amount of time that should be spent in `recvmsg()` calls per endpoint iteration -135/// -136/// 50us are chosen so that an endpoint iteration with a 50us sendmsg limit blocks -137/// the runtime for a maximum of about 100us. -138/// Going much lower does not yield any noticeable difference, since a single `recvmmsg` -139/// batch of size 32 was observed to take 30us on some systems. -140const RECV_TIME_BOUND: Duration = Duration::from_micros(50); \ No newline at end of file +44mod connection; +45mod endpoint; +46mod incoming; +47mod mutex; +48mod path; +49mod recv_stream; +50mod runtime; +51mod send_stream; +52mod work_limiter; +53 +54#[cfg(not(wasm_browser))] +55pub(crate) use std::time::{Duration, Instant}; +56#[cfg(wasm_browser)] +57pub(crate) use web_time::{Duration, Instant}; +58 +59#[cfg(feature = "bloom")] +60pub use proto::BloomTokenLog; +61pub use proto::{ +62 AckFrequencyConfig, ApplicationClose, Chunk, ClientConfig, ClosedStream, ConfigError, +63 ConnectError, ConnectionClose, ConnectionError, ConnectionId, ConnectionIdGenerator, +64 ConnectionStats, Dir, EcnCodepoint, EndpointConfig, FrameStats, FrameType, IdleTimeout, +65 InvalidCid, MtuDiscoveryConfig, NoneTokenLog, NoneTokenStore, PathId, PathStats, ServerConfig, +66 Side, StdSystemTime, StreamId, TimeSource, TokenLog, TokenMemoryCache, TokenReuseError, +67 TokenStore, Transmit, TransportConfig, TransportErrorCode, UdpStats, ValidationTokenConfig, +68 VarInt, VarIntBoundsExceeded, Written, congestion, crypto, +69}; +70#[cfg(feature = "qlog")] +71pub use proto::{QlogConfig, QlogFactory, QlogFileFactory}; +72#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))] +73pub use rustls; +74pub use udp; +75 +76pub use crate::connection::{ +77 AcceptBi, AcceptUni, Connecting, Connection, OnClosed, OpenBi, OpenUni, ReadDatagram, +78 SendDatagram, SendDatagramError, WeakConnectionHandle, ZeroRttAccepted, +79}; +80pub use crate::endpoint::{Accept, Endpoint, EndpointStats}; +81pub use crate::incoming::{Incoming, IncomingFuture, RetryError}; +82pub use crate::path::{AddressDiscovery, ClosePath, OpenPath, Path}; +83pub use crate::recv_stream::{ +84 ReadError, ReadExactError, ReadToEndError, RecvStream, ResetError, UnorderedRecvStream, +85}; +86#[cfg(feature = "runtime-smol")] +87pub use crate::runtime::SmolRuntime; +88#[cfg(feature = "runtime-tokio")] +89pub use crate::runtime::TokioRuntime; +90#[cfg(any(feature = "runtime-tokio", feature = "runtime-smol"))] +91pub use crate::runtime::default_runtime; +92pub use crate::runtime::{AsyncTimer, AsyncUdpSocket, Runtime, UdpSender}; +93pub use crate::send_stream::{SendStream, StoppedError, WriteError}; +94 +95#[cfg(test)] +96mod tests; +97 +98#[derive(Debug)] +99enum ConnectionEvent { +100 Close { +101 error_code: VarInt, +102 reason: bytes::Bytes, +103 }, +104 Proto(proto::ConnectionEvent), +105 Rebind(Pin<Box<dyn UdpSender>>), +106} +107 +108fn udp_transmit<'a>(t: &proto::Transmit, buffer: &'a [u8]) -> udp::Transmit<'a> { +109 udp::Transmit { +110 destination: t.destination, +111 ecn: t.ecn.map(udp_ecn), +112 contents: buffer, +113 segment_size: t.segment_size, +114 src_ip: t.src_ip, +115 } +116} +117 +118fn udp_ecn(ecn: proto::EcnCodepoint) -> udp::EcnCodepoint { +119 match ecn { +120 proto::EcnCodepoint::Ect0 => udp::EcnCodepoint::Ect0, +121 proto::EcnCodepoint::Ect1 => udp::EcnCodepoint::Ect1, +122 proto::EcnCodepoint::Ce => udp::EcnCodepoint::Ce, +123 } +124} +125 +126/// Maximum number of datagrams processed in send/recv calls to make before moving on to other processing +127/// +128/// This helps ensure we don't starve anything when the CPU is slower than the link. +129/// Value is selected by picking a low number which didn't degrade throughput in benchmarks. +130const IO_LOOP_BOUND: usize = 160; +131 +132/// The maximum amount of time that should be spent in `recvmsg()` calls per endpoint iteration +133/// +134/// 50us are chosen so that an endpoint iteration with a 50us sendmsg limit blocks +135/// the runtime for a maximum of about 100us. +136/// Going much lower does not yield any noticeable difference, since a single `recvmmsg` +137/// batch of size 32 was observed to take 30us on some systems. +138const RECV_TIME_BOUND: Duration = Duration::from_micros(50); \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn/recv_stream.rs.html b/pr/255/docs/src/iroh_quinn/recv_stream.rs.html index 327272bc9..2aad2b8ca 100644 --- a/pr/255/docs/src/iroh_quinn/recv_stream.rs.html +++ b/pr/255/docs/src/iroh_quinn/recv_stream.rs.html @@ -107,7 +107,7 @@ 107 /// [`finish`]: crate::SendStream::finish 108 pub fn poll_read( 109 &mut self, -110 cx: &mut Context, +110 cx: &mut Context<'_>, 111 buf: &mut [u8], 112 ) -> Poll<Result<usize, ReadError>> { 113 let mut buf = ReadBuf::new(buf); @@ -129,7 +129,7 @@ 129 /// [`finish`]: crate::SendStream::finish 130 pub fn poll_read_buf( 131 &mut self, -132 cx: &mut Context, +132 cx: &mut Context<'_>, 133 buf: &mut ReadBuf<'_>, 134 ) -> Poll<Result<(), ReadError>> { 135 if buf.remaining() == 0 { @@ -187,7 +187,7 @@ 187 /// when the stream becomes readable or is closed. 188 fn poll_read_chunk( 189 &mut self, -190 cx: &mut Context, +190 cx: &mut Context<'_>, 191 max_length: usize, 192 ordered: bool, 193 ) -> Poll<Result<Option<Chunk>, ReadError>> { @@ -214,7 +214,7 @@ 214 /// Foundation of [`Self::read_chunks`] 215 fn poll_read_chunks( 216 &mut self, -217 cx: &mut Context, +217 cx: &mut Context<'_>, 218 bufs: &mut [Bytes], 219 ) -> Poll<Result<Option<usize>, ReadError>> { 220 if bufs.is_empty() { @@ -342,12 +342,12 @@ 342 /// reading: the amount of data read, and the status after the final read call. 343 fn poll_read_generic<T, U>( 344 &mut self, -345 cx: &mut Context, +345 cx: &mut Context<'_>, 346 ordered: bool, 347 mut read_fn: T, 348 ) -> Poll<Result<Option<U>, ReadError>> 349 where -350 T: FnMut(&mut Chunks) -> ReadStatus<U>, +350 T: FnMut(&mut Chunks<'_>) -> ReadStatus<U>, 351 { 352 use proto::ReadError::*; 353 if self.all_data_read { @@ -514,7 +514,7 @@ 514 515impl Future for ReadToEnd<'_> { 516 type Output = Result<Vec<u8>, ReadToEndError>; -517 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +517 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 518 loop { 519 match ready!(self.stream.poll_read_chunk(cx, usize::MAX, false))? { 520 Some(chunk) => { @@ -559,7 +559,7 @@ 559impl futures_io::AsyncRead for RecvStream { 560 fn poll_read( 561 self: Pin<&mut Self>, -562 cx: &mut Context, +562 cx: &mut Context<'_>, 563 buf: &mut [u8], 564 ) -> Poll<io::Result<usize>> { 565 let mut buf = ReadBuf::new(buf); @@ -679,7 +679,7 @@ 679impl Future for Read<'_> { 680 type Output = Result<Option<usize>, ReadError>; 681 -682 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +682 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 683 let this = self.get_mut(); 684 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?; 685 match this.buf.filled().len() { @@ -699,7 +699,7 @@ 699 700impl Future for ReadExact<'_> { 701 type Output = Result<(), ReadExactError>; -702 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +702 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 703 let this = self.get_mut(); 704 let mut remaining = this.buf.remaining(); 705 while remaining > 0 { @@ -736,7 +736,7 @@ 736 737impl Future for ReadChunk<'_> { 738 type Output = Result<Option<Chunk>, ReadError>; -739 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +739 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 740 let (max_length, ordered) = (self.max_length, self.ordered); 741 self.stream.poll_read_chunk(cx, max_length, ordered) 742 } @@ -752,7 +752,7 @@ 752 753impl Future for ReadChunks<'_> { 754 type Output = Result<Option<usize>, ReadError>; -755 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { +755 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 756 let this = self.get_mut(); 757 this.stream.poll_read_chunks(cx, this.bufs) 758 } diff --git a/pr/255/docs/src/iroh_quinn/runtime/mod.rs.html b/pr/255/docs/src/iroh_quinn/runtime/mod.rs.html index 9b510729f..20b0650f5 100644 --- a/pr/255/docs/src/iroh_quinn/runtime/mod.rs.html +++ b/pr/255/docs/src/iroh_quinn/runtime/mod.rs.html @@ -37,7 +37,7 @@ 37 /// Update the timer to expire at `i` 38 fn reset(self: Pin<&mut Self>, i: Instant); 39 /// Check whether the timer has expired, and register to be woken if not -40 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()>; +40 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>; 41} 42 43/// Abstract implementation of a UDP socket for runtime independence @@ -57,7 +57,7 @@ 57 /// Receive UDP datagrams, or register to be woken if receiving may succeed in the future 58 fn poll_recv( 59 &mut self, -60 cx: &mut Context, +60 cx: &mut Context<'_>, 61 bufs: &mut [IoSliceMut<'_>], 62 meta: &mut [RecvMeta], 63 ) -> Poll<io::Result<usize>>; @@ -96,8 +96,8 @@ 96 /// unlike [`Future::poll`], so calling it again after readiness should not panic. 97 fn poll_send( 98 self: Pin<&mut Self>, -99 transmit: &Transmit, -100 cx: &mut Context, +99 transmit: &Transmit<'_>, +100 cx: &mut Context<'_>, 101 ) -> Poll<io::Result<()>>; 102 103 /// Maximum number of datagrams that a [`Transmit`] may encode. @@ -161,8 +161,8 @@ 161{ 162 fn poll_send( 163 self: Pin<&mut Self>, -164 transmit: &udp::Transmit, -165 cx: &mut Context, +164 transmit: &udp::Transmit<'_>, +165 cx: &mut Context<'_>, 166 ) -> Poll<io::Result<()>> { 167 let mut this = self.project(); 168 loop { @@ -210,7 +210,7 @@ 210 /// If not write-ready, this is allowed to return [`std::io::ErrorKind::WouldBlock`]. 211 /// 212 /// The [`UdpSenderHelper`] will use this to implement [`UdpSender::poll_send`]. -213 fn try_send(&self, transmit: &udp::Transmit) -> io::Result<()>; +213 fn try_send(&self, transmit: &udp::Transmit<'_>) -> io::Result<()>; 214 215 /// See [`UdpSender::max_transmit_segments`]. 216 fn max_transmit_segments(&self) -> NonZeroUsize; diff --git a/pr/255/docs/src/iroh_quinn/runtime/smol.rs.html b/pr/255/docs/src/iroh_quinn/runtime/smol.rs.html index aa772e08f..61fb58950 100644 --- a/pr/255/docs/src/iroh_quinn/runtime/smol.rs.html +++ b/pr/255/docs/src/iroh_quinn/runtime/smol.rs.html @@ -36,7 +36,7 @@ 36 self.set_at(t) 37 } 38 -39 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { +39 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { 40 Future::poll(self, cx).map(|_| ()) 41 } 42} @@ -61,7 +61,7 @@ 61 self.inner.max_gso_segments() 62 } 63 -64 fn try_send(&self, transmit: &udp::Transmit) -> io::Result<()> { +64 fn try_send(&self, transmit: &udp::Transmit<'_>) -> io::Result<()> { 65 self.inner.send((&self.io).into(), transmit) 66 } 67} @@ -76,7 +76,7 @@ 76 77 fn poll_recv( 78 &mut self, -79 cx: &mut Context, +79 cx: &mut Context<'_>, 80 bufs: &mut [io::IoSliceMut<'_>], 81 meta: &mut [udp::RecvMeta], 82 ) -> Poll<io::Result<usize>> { diff --git a/pr/255/docs/src/iroh_quinn/runtime/tokio.rs.html b/pr/255/docs/src/iroh_quinn/runtime/tokio.rs.html index 48ba2180b..a981b3445 100644 --- a/pr/255/docs/src/iroh_quinn/runtime/tokio.rs.html +++ b/pr/255/docs/src/iroh_quinn/runtime/tokio.rs.html @@ -45,7 +45,7 @@ 45 fn reset(self: Pin<&mut Self>, t: Instant) { 46 Self::reset(self, t.into()) 47 } -48 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { +48 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { 49 Future::poll(self, cx) 50 } 51} @@ -61,7 +61,7 @@ 61 self.inner.max_gso_segments() 62 } 63 -64 fn try_send(&self, transmit: &udp::Transmit) -> io::Result<()> { +64 fn try_send(&self, transmit: &udp::Transmit<'_>) -> io::Result<()> { 65 self.io.try_io(Interest::WRITABLE, || { 66 self.inner.send((&self.io).into(), transmit) 67 }) @@ -78,7 +78,7 @@ 78 79 fn poll_recv( 80 &mut self, -81 cx: &mut Context, +81 cx: &mut Context<'_>, 82 bufs: &mut [std::io::IoSliceMut<'_>], 83 meta: &mut [udp::RecvMeta], 84 ) -> Poll<io::Result<usize>> { diff --git a/pr/255/docs/src/iroh_quinn/send_stream.rs.html b/pr/255/docs/src/iroh_quinn/send_stream.rs.html index b21a2cdd1..0cbbea68f 100644 --- a/pr/255/docs/src/iroh_quinn/send_stream.rs.html +++ b/pr/255/docs/src/iroh_quinn/send_stream.rs.html @@ -134,310 +134,318 @@ 134 Ok(()) 135 } 136 -137 fn execute_poll<F, R>(&mut self, cx: &mut Context, write_fn: F) -> Poll<Result<R, WriteError>> -138 where -139 F: FnOnce(&mut proto::SendStream) -> Result<R, proto::WriteError>, -140 { -141 use proto::WriteError::*; -142 let mut conn = self.conn.state.lock("SendStream::poll_write"); -143 if self.is_0rtt { -144 conn.check_0rtt() -145 .map_err(|()| WriteError::ZeroRttRejected)?; -146 } -147 if let Some(ref x) = conn.error { -148 return Poll::Ready(Err(WriteError::ConnectionLost(x.clone()))); -149 } -150 -151 let result = match write_fn(&mut conn.inner.send_stream(self.stream)) { -152 Ok(result) => result, -153 Err(Blocked) => { -154 conn.blocked_writers.insert(self.stream, cx.waker().clone()); -155 return Poll::Pending; -156 } -157 Err(Stopped(error_code)) => { -158 return Poll::Ready(Err(WriteError::Stopped(error_code))); -159 } -160 Err(ClosedStream) => { -161 return Poll::Ready(Err(WriteError::ClosedStream)); -162 } -163 }; -164 -165 conn.wake(); -166 Poll::Ready(Ok(result)) -167 } +137 fn execute_poll<F, R>( +138 &mut self, +139 cx: &mut Context<'_>, +140 write_fn: F, +141 ) -> Poll<Result<R, WriteError>> +142 where +143 F: FnOnce(&mut proto::SendStream<'_>) -> Result<R, proto::WriteError>, +144 { +145 use proto::WriteError::*; +146 let mut conn = self.conn.state.lock("SendStream::poll_write"); +147 if self.is_0rtt { +148 conn.check_0rtt() +149 .map_err(|()| WriteError::ZeroRttRejected)?; +150 } +151 if let Some(ref x) = conn.error { +152 return Poll::Ready(Err(WriteError::ConnectionLost(x.clone()))); +153 } +154 +155 let result = match write_fn(&mut conn.inner.send_stream(self.stream)) { +156 Ok(result) => result, +157 Err(Blocked) => { +158 conn.blocked_writers.insert(self.stream, cx.waker().clone()); +159 return Poll::Pending; +160 } +161 Err(Stopped(error_code)) => { +162 return Poll::Ready(Err(WriteError::Stopped(error_code))); +163 } +164 Err(ClosedStream) => { +165 return Poll::Ready(Err(WriteError::ClosedStream)); +166 } +167 }; 168 -169 /// Notify the peer that no more data will ever be written to this stream -170 /// -171 /// It is an error to write to a [`SendStream`] after `finish()`ing it. [`reset()`](Self::reset) -172 /// may still be called after `finish` to abandon transmission of any stream data that might -173 /// still be buffered. +169 conn.wake(); +170 Poll::Ready(Ok(result)) +171 } +172 +173 /// Notify the peer that no more data will ever be written to this stream 174 /// -175 /// To wait for the peer to receive all buffered stream data, see [`stopped()`](Self::stopped). -176 /// -177 /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously -178 /// called. This error is harmless and serves only to indicate that the caller may have -179 /// incorrect assumptions about the stream's state. -180 pub fn finish(&mut self) -> Result<(), ClosedStream> { -181 let mut conn = self.conn.state.lock("finish"); -182 match conn.inner.send_stream(self.stream).finish() { -183 Ok(()) => { -184 conn.wake(); -185 Ok(()) -186 } -187 Err(FinishError::ClosedStream) => Err(ClosedStream::default()), -188 // Harmless. If the application needs to know about stopped streams at this point, it -189 // should call `stopped`. -190 Err(FinishError::Stopped(_)) => Ok(()), -191 } -192 } -193 -194 /// Close the send stream immediately. -195 /// -196 /// No new data can be written after calling this method. Locally buffered data is dropped, and -197 /// previously transmitted data will no longer be retransmitted if lost. If an attempt has -198 /// already been made to finish the stream, the peer may still receive all written data. +175 /// It is an error to write to a [`SendStream`] after `finish()`ing it. [`reset()`](Self::reset) +176 /// may still be called after `finish` to abandon transmission of any stream data that might +177 /// still be buffered. +178 /// +179 /// To wait for the peer to receive all buffered stream data, see [`stopped()`](Self::stopped). +180 /// +181 /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously +182 /// called. This error is harmless and serves only to indicate that the caller may have +183 /// incorrect assumptions about the stream's state. +184 pub fn finish(&mut self) -> Result<(), ClosedStream> { +185 let mut conn = self.conn.state.lock("finish"); +186 match conn.inner.send_stream(self.stream).finish() { +187 Ok(()) => { +188 conn.wake(); +189 Ok(()) +190 } +191 Err(FinishError::ClosedStream) => Err(ClosedStream::default()), +192 // Harmless. If the application needs to know about stopped streams at this point, it +193 // should call `stopped`. +194 Err(FinishError::Stopped(_)) => Ok(()), +195 } +196 } +197 +198 /// Close the send stream immediately. 199 /// -200 /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously -201 /// called. This error is harmless and serves only to indicate that the caller may have -202 /// incorrect assumptions about the stream's state. -203 pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream> { -204 let mut conn = self.conn.state.lock("SendStream::reset"); -205 if self.is_0rtt && conn.check_0rtt().is_err() { -206 return Ok(()); -207 } -208 conn.inner.send_stream(self.stream).reset(error_code)?; -209 conn.wake(); -210 Ok(()) -211 } -212 -213 /// Set the priority of the send stream -214 /// -215 /// Every send stream has an initial priority of 0. Locally buffered data from streams with -216 /// higher priority will be transmitted before data from streams with lower priority. Changing -217 /// the priority of a stream with pending data may only take effect after that data has been -218 /// transmitted. Using many different priority levels per connection may have a negative -219 /// impact on performance. -220 pub fn set_priority(&self, priority: i32) -> Result<(), ClosedStream> { -221 let mut conn = self.conn.state.lock("SendStream::set_priority"); -222 conn.inner.send_stream(self.stream).set_priority(priority)?; -223 Ok(()) -224 } -225 -226 /// Get the priority of the send stream -227 pub fn priority(&self) -> Result<i32, ClosedStream> { -228 let mut conn = self.conn.state.lock("SendStream::priority"); -229 conn.inner.send_stream(self.stream).priority() -230 } -231 -232 /// Completes when the peer stops the stream or reads the stream to completion -233 /// -234 /// Yields `Some` with the stop error code if the peer stops the stream. Yields `None` if the -235 /// local side [`finish()`](Self::finish)es the stream and then the peer acknowledges receipt -236 /// of all stream data (although not necessarily the processing of it), after which the peer -237 /// closing the stream is no longer meaningful. -238 /// -239 /// For a variety of reasons, the peer may not send acknowledgements immediately upon receiving -240 /// data. As such, relying on `stopped` to know when the peer has read a stream to completion -241 /// may introduce more latency than using an application-level response of some sort. -242 pub fn stopped( -243 &self, -244 ) -> impl Future<Output = Result<Option<VarInt>, StoppedError>> + Send + Sync + 'static { -245 let conn = self.conn.clone(); -246 let stream = self.stream; -247 let is_0rtt = self.is_0rtt; -248 async move { -249 loop { -250 // The `Notify::notified` future needs to be created while the lock is being held, -251 // otherwise a wakeup could be missed if triggered in between releasing the lock -252 // and creating the future. -253 // The lock may only be held in a block without `await`s, otherwise the future -254 // becomes `!Send`. `Notify::notified` is lifetime-bound to `Notify`, therefore -255 // we need to declare `notify` outside of the block, and initialize it inside. -256 let notify; -257 { -258 let mut conn = conn.state.lock("SendStream::stopped"); -259 if let Some(output) = send_stream_stopped(&mut conn, stream, is_0rtt) { -260 return output; -261 } -262 -263 notify = conn.stopped.entry(stream).or_default().clone(); -264 notify.notified() -265 } -266 .await -267 } -268 } -269 } -270 -271 /// Get the identity of this stream -272 pub fn id(&self) -> StreamId { -273 self.stream -274 } -275 -276 /// Attempt to write bytes from buf into the stream. -277 /// -278 /// On success, returns Poll::Ready(Ok(num_bytes_written)). -279 /// -280 /// If the stream is not ready for writing, the method returns Poll::Pending and arranges -281 /// for the current task (via cx.waker().wake_by_ref()) to receive a notification when the -282 /// stream becomes writable or is closed. -283 pub fn poll_write( -284 self: Pin<&mut Self>, -285 cx: &mut Context, -286 buf: &[u8], -287 ) -> Poll<Result<usize, WriteError>> { -288 pin!(self.get_mut().write(buf)).as_mut().poll(cx) -289 } -290} -291 -292/// Check if a send stream is stopped. -293/// -294/// Returns `Some` if the stream is stopped or the connection is closed. -295/// Returns `None` if the stream is not stopped. -296fn send_stream_stopped( -297 conn: &mut State, -298 stream: StreamId, -299 is_0rtt: bool, -300) -> Option<Result<Option<VarInt>, StoppedError>> { -301 if is_0rtt && conn.check_0rtt().is_err() { -302 return Some(Err(StoppedError::ZeroRttRejected)); -303 } -304 match conn.inner.send_stream(stream).stopped() { -305 Err(ClosedStream { .. }) => Some(Ok(None)), -306 Ok(Some(error_code)) => Some(Ok(Some(error_code))), -307 Ok(None) => conn.error.clone().map(|error| Err(error.into())), -308 } -309} -310 -311#[cfg(feature = "futures-io")] -312impl futures_io::AsyncWrite for SendStream { -313 fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> { -314 self.poll_write(cx, buf).map_err(Into::into) -315 } -316 -317 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<io::Result<()>> { -318 Poll::Ready(Ok(())) -319 } -320 -321 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<io::Result<()>> { -322 Poll::Ready(self.get_mut().finish().map_err(Into::into)) +200 /// No new data can be written after calling this method. Locally buffered data is dropped, and +201 /// previously transmitted data will no longer be retransmitted if lost. If an attempt has +202 /// already been made to finish the stream, the peer may still receive all written data. +203 /// +204 /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously +205 /// called. This error is harmless and serves only to indicate that the caller may have +206 /// incorrect assumptions about the stream's state. +207 pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream> { +208 let mut conn = self.conn.state.lock("SendStream::reset"); +209 if self.is_0rtt && conn.check_0rtt().is_err() { +210 return Ok(()); +211 } +212 conn.inner.send_stream(self.stream).reset(error_code)?; +213 conn.wake(); +214 Ok(()) +215 } +216 +217 /// Set the priority of the send stream +218 /// +219 /// Every send stream has an initial priority of 0. Locally buffered data from streams with +220 /// higher priority will be transmitted before data from streams with lower priority. Changing +221 /// the priority of a stream with pending data may only take effect after that data has been +222 /// transmitted. Using many different priority levels per connection may have a negative +223 /// impact on performance. +224 pub fn set_priority(&self, priority: i32) -> Result<(), ClosedStream> { +225 let mut conn = self.conn.state.lock("SendStream::set_priority"); +226 conn.inner.send_stream(self.stream).set_priority(priority)?; +227 Ok(()) +228 } +229 +230 /// Get the priority of the send stream +231 pub fn priority(&self) -> Result<i32, ClosedStream> { +232 let mut conn = self.conn.state.lock("SendStream::priority"); +233 conn.inner.send_stream(self.stream).priority() +234 } +235 +236 /// Completes when the peer stops the stream or reads the stream to completion +237 /// +238 /// Yields `Some` with the stop error code if the peer stops the stream. Yields `None` if the +239 /// local side [`finish()`](Self::finish)es the stream and then the peer acknowledges receipt +240 /// of all stream data (although not necessarily the processing of it), after which the peer +241 /// closing the stream is no longer meaningful. +242 /// +243 /// For a variety of reasons, the peer may not send acknowledgements immediately upon receiving +244 /// data. As such, relying on `stopped` to know when the peer has read a stream to completion +245 /// may introduce more latency than using an application-level response of some sort. +246 pub fn stopped( +247 &self, +248 ) -> impl Future<Output = Result<Option<VarInt>, StoppedError>> + Send + Sync + 'static { +249 let conn = self.conn.clone(); +250 let stream = self.stream; +251 let is_0rtt = self.is_0rtt; +252 async move { +253 loop { +254 // The `Notify::notified` future needs to be created while the lock is being held, +255 // otherwise a wakeup could be missed if triggered in between releasing the lock +256 // and creating the future. +257 // The lock may only be held in a block without `await`s, otherwise the future +258 // becomes `!Send`. `Notify::notified` is lifetime-bound to `Notify`, therefore +259 // we need to declare `notify` outside of the block, and initialize it inside. +260 let notify; +261 { +262 let mut conn = conn.state.lock("SendStream::stopped"); +263 if let Some(output) = send_stream_stopped(&mut conn, stream, is_0rtt) { +264 return output; +265 } +266 +267 notify = conn.stopped.entry(stream).or_default().clone(); +268 notify.notified() +269 } +270 .await +271 } +272 } +273 } +274 +275 /// Get the identity of this stream +276 pub fn id(&self) -> StreamId { +277 self.stream +278 } +279 +280 /// Attempt to write bytes from buf into the stream. +281 /// +282 /// On success, returns Poll::Ready(Ok(num_bytes_written)). +283 /// +284 /// If the stream is not ready for writing, the method returns Poll::Pending and arranges +285 /// for the current task (via cx.waker().wake_by_ref()) to receive a notification when the +286 /// stream becomes writable or is closed. +287 pub fn poll_write( +288 self: Pin<&mut Self>, +289 cx: &mut Context<'_>, +290 buf: &[u8], +291 ) -> Poll<Result<usize, WriteError>> { +292 pin!(self.get_mut().write(buf)).as_mut().poll(cx) +293 } +294} +295 +296/// Check if a send stream is stopped. +297/// +298/// Returns `Some` if the stream is stopped or the connection is closed. +299/// Returns `None` if the stream is not stopped. +300fn send_stream_stopped( +301 conn: &mut State, +302 stream: StreamId, +303 is_0rtt: bool, +304) -> Option<Result<Option<VarInt>, StoppedError>> { +305 if is_0rtt && conn.check_0rtt().is_err() { +306 return Some(Err(StoppedError::ZeroRttRejected)); +307 } +308 match conn.inner.send_stream(stream).stopped() { +309 Err(ClosedStream { .. }) => Some(Ok(None)), +310 Ok(Some(error_code)) => Some(Ok(Some(error_code))), +311 Ok(None) => conn.error.clone().map(|error| Err(error.into())), +312 } +313} +314 +315#[cfg(feature = "futures-io")] +316impl futures_io::AsyncWrite for SendStream { +317 fn poll_write( +318 self: Pin<&mut Self>, +319 cx: &mut Context<'_>, +320 buf: &[u8], +321 ) -> Poll<io::Result<usize>> { +322 self.poll_write(cx, buf).map_err(Into::into) 323 } -324} -325 -326impl tokio::io::AsyncWrite for SendStream { -327 fn poll_write( -328 self: Pin<&mut Self>, -329 cx: &mut Context<'_>, -330 buf: &[u8], -331 ) -> Poll<io::Result<usize>> { -332 self.poll_write(cx, buf).map_err(Into::into) -333 } -334 -335 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<io::Result<()>> { -336 Poll::Ready(Ok(())) -337 } -338 -339 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<io::Result<()>> { -340 Poll::Ready(self.get_mut().finish().map_err(Into::into)) +324 +325 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { +326 Poll::Ready(Ok(())) +327 } +328 +329 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { +330 Poll::Ready(self.get_mut().finish().map_err(Into::into)) +331 } +332} +333 +334impl tokio::io::AsyncWrite for SendStream { +335 fn poll_write( +336 self: Pin<&mut Self>, +337 cx: &mut Context<'_>, +338 buf: &[u8], +339 ) -> Poll<io::Result<usize>> { +340 self.poll_write(cx, buf).map_err(Into::into) 341 } -342} -343 -344impl Drop for SendStream { -345 fn drop(&mut self) { -346 let mut conn = self.conn.state.lock("SendStream::drop"); -347 -348 // clean up any previously registered wakers -349 conn.blocked_writers.remove(&self.stream); -350 -351 if conn.error.is_some() || (self.is_0rtt && conn.check_0rtt().is_err()) { -352 return; -353 } -354 match conn.inner.send_stream(self.stream).finish() { -355 Ok(()) => conn.wake(), -356 Err(FinishError::Stopped(reason)) => { -357 if conn.inner.send_stream(self.stream).reset(reason).is_ok() { -358 conn.wake(); -359 } -360 } -361 // Already finished or reset, which is fine. -362 Err(FinishError::ClosedStream) => {} -363 } -364 } -365} -366 -367/// Errors that arise from writing to a stream -368#[derive(Debug, Error, Clone, PartialEq, Eq)] -369pub enum WriteError { -370 /// The peer is no longer accepting data on this stream -371 /// -372 /// Carries an application-defined error code. -373 #[error("sending stopped by peer: error {0}")] -374 Stopped(VarInt), -375 /// The connection was lost -376 #[error("connection lost")] -377 ConnectionLost(#[from] ConnectionError), -378 /// The stream has already been finished or reset -379 #[error("closed stream")] -380 ClosedStream, -381 /// This was a 0-RTT stream and the server rejected it -382 /// -383 /// Can only occur on clients for 0-RTT streams, which can be opened using -384 /// [`Connecting::into_0rtt()`]. -385 /// -386 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt() -387 #[error("0-RTT rejected")] -388 ZeroRttRejected, -389} -390 -391impl From<ClosedStream> for WriteError { -392 #[inline] -393 fn from(_: ClosedStream) -> Self { -394 Self::ClosedStream -395 } -396} -397 -398impl From<StoppedError> for WriteError { -399 fn from(x: StoppedError) -> Self { -400 match x { -401 StoppedError::ConnectionLost(e) => Self::ConnectionLost(e), -402 StoppedError::ZeroRttRejected => Self::ZeroRttRejected, -403 } -404 } -405} -406 -407impl From<WriteError> for io::Error { -408 fn from(x: WriteError) -> Self { -409 use WriteError::*; -410 let kind = match x { -411 Stopped(_) | ZeroRttRejected => io::ErrorKind::ConnectionReset, -412 ConnectionLost(_) | ClosedStream => io::ErrorKind::NotConnected, -413 }; -414 Self::new(kind, x) -415 } -416} -417 -418/// Errors that arise while monitoring for a send stream stop from the peer -419#[derive(Debug, Error, Clone, PartialEq, Eq)] -420pub enum StoppedError { -421 /// The connection was lost -422 #[error("connection lost")] -423 ConnectionLost(#[from] ConnectionError), -424 /// This was a 0-RTT stream and the server rejected it -425 /// -426 /// Can only occur on clients for 0-RTT streams, which can be opened using -427 /// [`Connecting::into_0rtt()`]. -428 /// -429 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt() -430 #[error("0-RTT rejected")] -431 ZeroRttRejected, -432} -433 -434impl From<StoppedError> for io::Error { -435 fn from(x: StoppedError) -> Self { -436 use StoppedError::*; -437 let kind = match x { -438 ZeroRttRejected => io::ErrorKind::ConnectionReset, -439 ConnectionLost(_) => io::ErrorKind::NotConnected, -440 }; -441 Self::new(kind, x) -442 } -443} \ No newline at end of file +342 +343 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { +344 Poll::Ready(Ok(())) +345 } +346 +347 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { +348 Poll::Ready(self.get_mut().finish().map_err(Into::into)) +349 } +350} +351 +352impl Drop for SendStream { +353 fn drop(&mut self) { +354 let mut conn = self.conn.state.lock("SendStream::drop"); +355 +356 // clean up any previously registered wakers +357 conn.blocked_writers.remove(&self.stream); +358 +359 if conn.error.is_some() || (self.is_0rtt && conn.check_0rtt().is_err()) { +360 return; +361 } +362 match conn.inner.send_stream(self.stream).finish() { +363 Ok(()) => conn.wake(), +364 Err(FinishError::Stopped(reason)) => { +365 if conn.inner.send_stream(self.stream).reset(reason).is_ok() { +366 conn.wake(); +367 } +368 } +369 // Already finished or reset, which is fine. +370 Err(FinishError::ClosedStream) => {} +371 } +372 } +373} +374 +375/// Errors that arise from writing to a stream +376#[derive(Debug, Error, Clone, PartialEq, Eq)] +377pub enum WriteError { +378 /// The peer is no longer accepting data on this stream +379 /// +380 /// Carries an application-defined error code. +381 #[error("sending stopped by peer: error {0}")] +382 Stopped(VarInt), +383 /// The connection was lost +384 #[error("connection lost")] +385 ConnectionLost(#[from] ConnectionError), +386 /// The stream has already been finished or reset +387 #[error("closed stream")] +388 ClosedStream, +389 /// This was a 0-RTT stream and the server rejected it +390 /// +391 /// Can only occur on clients for 0-RTT streams, which can be opened using +392 /// [`Connecting::into_0rtt()`]. +393 /// +394 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt() +395 #[error("0-RTT rejected")] +396 ZeroRttRejected, +397} +398 +399impl From<ClosedStream> for WriteError { +400 #[inline] +401 fn from(_: ClosedStream) -> Self { +402 Self::ClosedStream +403 } +404} +405 +406impl From<StoppedError> for WriteError { +407 fn from(x: StoppedError) -> Self { +408 match x { +409 StoppedError::ConnectionLost(e) => Self::ConnectionLost(e), +410 StoppedError::ZeroRttRejected => Self::ZeroRttRejected, +411 } +412 } +413} +414 +415impl From<WriteError> for io::Error { +416 fn from(x: WriteError) -> Self { +417 use WriteError::*; +418 let kind = match x { +419 Stopped(_) | ZeroRttRejected => io::ErrorKind::ConnectionReset, +420 ConnectionLost(_) | ClosedStream => io::ErrorKind::NotConnected, +421 }; +422 Self::new(kind, x) +423 } +424} +425 +426/// Errors that arise while monitoring for a send stream stop from the peer +427#[derive(Debug, Error, Clone, PartialEq, Eq)] +428pub enum StoppedError { +429 /// The connection was lost +430 #[error("connection lost")] +431 ConnectionLost(#[from] ConnectionError), +432 /// This was a 0-RTT stream and the server rejected it +433 /// +434 /// Can only occur on clients for 0-RTT streams, which can be opened using +435 /// [`Connecting::into_0rtt()`]. +436 /// +437 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt() +438 #[error("0-RTT rejected")] +439 ZeroRttRejected, +440} +441 +442impl From<StoppedError> for io::Error { +443 fn from(x: StoppedError) -> Self { +444 use StoppedError::*; +445 let kind = match x { +446 ZeroRttRejected => io::ErrorKind::ConnectionReset, +447 ConnectionLost(_) => io::ErrorKind::NotConnected, +448 }; +449 Self::new(kind, x) +450 } +451} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/config/mod.rs.html b/pr/255/docs/src/iroh_quinn_proto/config/mod.rs.html index f0a2971c4..093d67514 100644 --- a/pr/255/docs/src/iroh_quinn_proto/config/mod.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/config/mod.rs.html @@ -627,77 +627,70 @@ 627#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))] 628impl ClientConfig { 629 /// Create a client configuration that trusts the platform's native roots -630 #[deprecated(since = "0.11.13", note = "use `try_with_platform_verifier()` instead")] -631 #[cfg(feature = "platform-verifier")] -632 pub fn with_platform_verifier() -> Self { -633 Self::try_with_platform_verifier().expect("use try_with_platform_verifier() instead") -634 } -635 -636 /// Create a client configuration that trusts the platform's native roots -637 #[cfg(feature = "platform-verifier")] -638 pub fn try_with_platform_verifier() -> Result<Self, rustls::Error> { -639 Ok(Self::new(Arc::new( -640 crypto::rustls::QuicClientConfig::with_platform_verifier()?, -641 ))) -642 } -643 -644 /// Create a client configuration that trusts specified trust anchors -645 pub fn with_root_certificates( -646 roots: Arc<rustls::RootCertStore>, -647 ) -> Result<Self, rustls::client::VerifierBuilderError> { -648 Ok(Self::new(Arc::new(crypto::rustls::QuicClientConfig::new( -649 WebPkiServerVerifier::builder_with_provider(roots, configured_provider()).build()?, -650 )))) -651 } -652} -653 -654impl fmt::Debug for ClientConfig { -655 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { -656 fmt.debug_struct("ClientConfig") -657 .field("transport", &self.transport) -658 // crypto not debug -659 // token_store not debug -660 .field("version", &self.version) -661 .finish_non_exhaustive() -662 } -663} -664 -665/// Errors in the configuration of an endpoint -666#[derive(Debug, Error, Clone, PartialEq, Eq)] -667#[non_exhaustive] -668pub enum ConfigError { -669 /// Value exceeds supported bounds -670 #[error("value exceeds supported bounds")] -671 OutOfBounds, -672} -673 -674impl From<TryFromIntError> for ConfigError { -675 fn from(_: TryFromIntError) -> Self { -676 Self::OutOfBounds -677 } -678} -679 -680impl From<VarIntBoundsExceeded> for ConfigError { -681 fn from(_: VarIntBoundsExceeded) -> Self { -682 Self::OutOfBounds -683 } -684} -685 -686/// Object to get current [`SystemTime`] -687/// -688/// This exists to allow system time to be mocked in tests, or wherever else desired. -689pub trait TimeSource: Send + Sync { -690 /// Get [`SystemTime::now()`](SystemTime::now) or the mocked equivalent -691 fn now(&self) -> SystemTime; -692} -693 -694/// Default implementation of [`TimeSource`] -695/// -696/// Implements `now` by calling [`SystemTime::now()`](SystemTime::now). -697pub struct StdSystemTime; -698 -699impl TimeSource for StdSystemTime { -700 fn now(&self) -> SystemTime { -701 SystemTime::now() -702 } -703} \ No newline at end of file +630 #[cfg(feature = "platform-verifier")] +631 pub fn try_with_platform_verifier() -> Result<Self, rustls::Error> { +632 Ok(Self::new(Arc::new( +633 crypto::rustls::QuicClientConfig::with_platform_verifier()?, +634 ))) +635 } +636 +637 /// Create a client configuration that trusts specified trust anchors +638 pub fn with_root_certificates( +639 roots: Arc<rustls::RootCertStore>, +640 ) -> Result<Self, rustls::client::VerifierBuilderError> { +641 Ok(Self::new(Arc::new(crypto::rustls::QuicClientConfig::new( +642 WebPkiServerVerifier::builder_with_provider(roots, configured_provider()).build()?, +643 )))) +644 } +645} +646 +647impl fmt::Debug for ClientConfig { +648 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +649 fmt.debug_struct("ClientConfig") +650 .field("transport", &self.transport) +651 // crypto not debug +652 // token_store not debug +653 .field("version", &self.version) +654 .finish_non_exhaustive() +655 } +656} +657 +658/// Errors in the configuration of an endpoint +659#[derive(Debug, Error, Clone, PartialEq, Eq)] +660#[non_exhaustive] +661pub enum ConfigError { +662 /// Value exceeds supported bounds +663 #[error("value exceeds supported bounds")] +664 OutOfBounds, +665} +666 +667impl From<TryFromIntError> for ConfigError { +668 fn from(_: TryFromIntError) -> Self { +669 Self::OutOfBounds +670 } +671} +672 +673impl From<VarIntBoundsExceeded> for ConfigError { +674 fn from(_: VarIntBoundsExceeded) -> Self { +675 Self::OutOfBounds +676 } +677} +678 +679/// Object to get current [`SystemTime`] +680/// +681/// This exists to allow system time to be mocked in tests, or wherever else desired. +682pub trait TimeSource: Send + Sync { +683 /// Get [`SystemTime::now()`](SystemTime::now) or the mocked equivalent +684 fn now(&self) -> SystemTime; +685} +686 +687/// Default implementation of [`TimeSource`] +688/// +689/// Implements `now` by calling [`SystemTime::now()`](SystemTime::now). +690pub struct StdSystemTime; +691 +692impl TimeSource for StdSystemTime { +693 fn now(&self) -> SystemTime { +694 SystemTime::now() +695 } +696} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/congestion/bbr/mod.rs.html b/pr/255/docs/src/iroh_quinn_proto/congestion/bbr/mod.rs.html index 5290f93a7..fb51be2b0 100644 --- a/pr/255/docs/src/iroh_quinn_proto/congestion/bbr/mod.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/congestion/bbr/mod.rs.html @@ -235,413 +235,417 @@ 235 } 236 237 if self.mode == Mode::ProbeRtt { -238 if self.exit_probe_rtt_at.is_none() { -239 // If the window has reached the appropriate size, schedule exiting -240 // ProbeRtt. The CWND during ProbeRtt is -241 // kMinimumCongestionWindow, but we allow an extra packet since QUIC -242 // checks CWND before sending a packet. -243 if bytes_in_flight < self.get_probe_rtt_cwnd() + self.current_mtu { -244 const K_PROBE_RTT_TIME: Duration = Duration::from_millis(200); -245 self.exit_probe_rtt_at = Some(now + K_PROBE_RTT_TIME); -246 } -247 } else if is_round_start && now >= self.exit_probe_rtt_at.unwrap() { -248 if !self.is_at_full_bandwidth { -249 self.enter_startup_mode(); -250 } else { -251 self.enter_probe_bandwidth_mode(now); -252 } -253 } -254 } -255 -256 self.exiting_quiescence = false; -257 } -258 -259 fn get_target_cwnd(&self, gain: f32) -> u64 { -260 let bw = self.max_bandwidth.get_estimate(); -261 let bdp = self.min_rtt.as_micros() as u64 * bw; -262 let bdpf = bdp as f64; -263 let cwnd = ((gain as f64 * bdpf) / 1_000_000f64) as u64; -264 // BDP estimate will be zero if no bandwidth samples are available yet. -265 if cwnd == 0 { -266 return self.init_cwnd; -267 } -268 cwnd.max(self.min_cwnd) -269 } -270 -271 fn get_probe_rtt_cwnd(&self) -> u64 { -272 const K_MODERATE_PROBE_RTT_MULTIPLIER: f32 = 0.75; -273 if PROBE_RTT_BASED_ON_BDP { -274 return self.get_target_cwnd(K_MODERATE_PROBE_RTT_MULTIPLIER); -275 } -276 self.min_cwnd -277 } -278 -279 fn calculate_pacing_rate(&mut self) { -280 let bw = self.max_bandwidth.get_estimate(); -281 if bw == 0 { -282 return; -283 } -284 let target_rate = (bw as f64 * self.pacing_gain as f64) as u64; -285 if self.is_at_full_bandwidth { -286 self.pacing_rate = target_rate; -287 return; -288 } -289 -290 // Pace at the rate of initial_window / RTT as soon as RTT measurements are -291 // available. -292 if self.pacing_rate == 0 && self.min_rtt.as_nanos() != 0 { -293 self.pacing_rate = -294 BandwidthEstimation::bw_from_delta(self.init_cwnd, self.min_rtt).unwrap(); -295 return; -296 } -297 -298 // Do not decrease the pacing rate during startup. -299 if self.pacing_rate < target_rate { -300 self.pacing_rate = target_rate; -301 } -302 } -303 -304 fn calculate_cwnd(&mut self, bytes_acked: u64, excess_acked: u64) { -305 if self.mode == Mode::ProbeRtt { -306 return; -307 } -308 let mut target_window = self.get_target_cwnd(self.cwnd_gain); -309 if self.is_at_full_bandwidth { -310 // Add the max recently measured ack aggregation to CWND. -311 target_window += self.ack_aggregation.max_ack_height.get(); -312 } else { -313 // Add the most recent excess acked. Because CWND never decreases in -314 // STARTUP, this will automatically create a very localized max filter. -315 target_window += excess_acked; -316 } -317 // Instead of immediately setting the target CWND as the new one, BBR grows -318 // the CWND towards |target_window| by only increasing it |bytes_acked| at a -319 // time. -320 if self.is_at_full_bandwidth { -321 self.cwnd = target_window.min(self.cwnd + bytes_acked); -322 } else if (self.cwnd_gain < target_window as f32) || (self.acked_bytes < self.init_cwnd) { -323 // If the connection is not yet out of startup phase, do not decrease -324 // the window. -325 self.cwnd += bytes_acked; -326 } -327 -328 // Enforce the limits on the congestion window. -329 if self.cwnd < self.min_cwnd { -330 self.cwnd = self.min_cwnd; -331 } -332 } -333 -334 fn calculate_recovery_window(&mut self, bytes_acked: u64, bytes_lost: u64, in_flight: u64) { -335 if !self.recovery_state.in_recovery() { -336 return; -337 } -338 // Set up the initial recovery window. -339 if self.recovery_window == 0 { -340 self.recovery_window = self.min_cwnd.max(in_flight + bytes_acked); -341 return; -342 } -343 -344 // Remove losses from the recovery window, while accounting for a potential -345 // integer underflow. -346 if self.recovery_window >= bytes_lost { -347 self.recovery_window -= bytes_lost; -348 } else { -349 // k_max_segment_size = current_mtu -350 self.recovery_window = self.current_mtu; -351 } -352 // In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH, -353 // release additional |bytes_acked| to achieve a slow-start-like behavior. -354 if self.recovery_state == RecoveryState::Growth { -355 self.recovery_window += bytes_acked; -356 } -357 -358 // Sanity checks. Ensure that we always allow to send at least an MSS or -359 // |bytes_acked| in response, whichever is larger. -360 self.recovery_window = self -361 .recovery_window -362 .max(in_flight + bytes_acked) -363 .max(self.min_cwnd); -364 } -365 -366 /// <https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control#section-4.3.2.2> -367 fn check_if_full_bw_reached(&mut self, app_limited: bool) { -368 if app_limited { -369 return; -370 } -371 let target = (self.bw_at_last_round as f64 * K_STARTUP_GROWTH_TARGET as f64) as u64; -372 let bw = self.max_bandwidth.get_estimate(); -373 if bw >= target { -374 self.bw_at_last_round = bw; -375 self.round_wo_bw_gain = 0; -376 self.ack_aggregation.max_ack_height.reset(); -377 return; -378 } -379 -380 self.round_wo_bw_gain += 1; -381 if self.round_wo_bw_gain >= K_ROUND_TRIPS_WITHOUT_GROWTH_BEFORE_EXITING_STARTUP as u64 -382 || (self.recovery_state.in_recovery()) -383 { -384 self.is_at_full_bandwidth = true; -385 } -386 } -387} -388 -389impl Controller for Bbr { -390 fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64) { -391 self.max_sent_packet_number = last_packet_number; -392 self.max_bandwidth.on_sent(now, bytes); -393 } -394 -395 fn on_ack( -396 &mut self, -397 now: Instant, -398 sent: Instant, -399 bytes: u64, -400 app_limited: bool, -401 rtt: &RttEstimator, -402 ) { -403 self.max_bandwidth -404 .on_ack(now, sent, bytes, self.round_count, app_limited); -405 self.acked_bytes += bytes; -406 if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > rtt.min() { -407 self.min_rtt = rtt.min(); -408 } -409 } -410 -411 fn on_end_acks( -412 &mut self, -413 now: Instant, -414 in_flight: u64, -415 app_limited: bool, -416 largest_packet_num_acked: Option<u64>, -417 ) { -418 let bytes_acked = self.max_bandwidth.bytes_acked_this_window(); -419 let excess_acked = self.ack_aggregation.update_ack_aggregation_bytes( -420 bytes_acked, -421 now, -422 self.round_count, -423 self.max_bandwidth.get_estimate(), -424 ); -425 self.max_bandwidth.end_acks(self.round_count, app_limited); -426 if let Some(largest_acked_packet) = largest_packet_num_acked { -427 self.max_acked_packet_number = largest_acked_packet; -428 } -429 -430 let mut is_round_start = false; -431 if bytes_acked > 0 { -432 is_round_start = -433 self.max_acked_packet_number > self.current_round_trip_end_packet_number; -434 if is_round_start { -435 self.current_round_trip_end_packet_number = self.max_sent_packet_number; -436 self.round_count += 1; -437 } -438 } -439 -440 self.update_recovery_state(is_round_start); -441 -442 if self.mode == Mode::ProbeBw { -443 self.update_gain_cycle_phase(now, in_flight); -444 } +238 match self.exit_probe_rtt_at { +239 None => { +240 // If the window has reached the appropriate size, schedule exiting +241 // ProbeRtt. The CWND during ProbeRtt is +242 // kMinimumCongestionWindow, but we allow an extra packet since QUIC +243 // checks CWND before sending a packet. +244 if bytes_in_flight < self.get_probe_rtt_cwnd() + self.current_mtu { +245 const K_PROBE_RTT_TIME: Duration = Duration::from_millis(200); +246 self.exit_probe_rtt_at = Some(now + K_PROBE_RTT_TIME); +247 } +248 } +249 Some(exit_time) if is_round_start && now >= exit_time => { +250 if !self.is_at_full_bandwidth { +251 self.enter_startup_mode(); +252 } else { +253 self.enter_probe_bandwidth_mode(now); +254 } +255 } +256 Some(_) => {} +257 } +258 } +259 +260 self.exiting_quiescence = false; +261 } +262 +263 fn get_target_cwnd(&self, gain: f32) -> u64 { +264 let bw = self.max_bandwidth.get_estimate(); +265 let bdp = self.min_rtt.as_micros() as u64 * bw; +266 let bdpf = bdp as f64; +267 let cwnd = ((gain as f64 * bdpf) / 1_000_000f64) as u64; +268 // BDP estimate will be zero if no bandwidth samples are available yet. +269 if cwnd == 0 { +270 return self.init_cwnd; +271 } +272 cwnd.max(self.min_cwnd) +273 } +274 +275 fn get_probe_rtt_cwnd(&self) -> u64 { +276 const K_MODERATE_PROBE_RTT_MULTIPLIER: f32 = 0.75; +277 if PROBE_RTT_BASED_ON_BDP { +278 return self.get_target_cwnd(K_MODERATE_PROBE_RTT_MULTIPLIER); +279 } +280 self.min_cwnd +281 } +282 +283 fn calculate_pacing_rate(&mut self) { +284 let bw = self.max_bandwidth.get_estimate(); +285 if bw == 0 { +286 return; +287 } +288 let target_rate = (bw as f64 * self.pacing_gain as f64) as u64; +289 if self.is_at_full_bandwidth { +290 self.pacing_rate = target_rate; +291 return; +292 } +293 +294 // Pace at the rate of initial_window / RTT as soon as RTT measurements are +295 // available. +296 if self.pacing_rate == 0 && self.min_rtt.as_nanos() != 0 { +297 self.pacing_rate = +298 BandwidthEstimation::bw_from_delta(self.init_cwnd, self.min_rtt).unwrap(); +299 return; +300 } +301 +302 // Do not decrease the pacing rate during startup. +303 if self.pacing_rate < target_rate { +304 self.pacing_rate = target_rate; +305 } +306 } +307 +308 fn calculate_cwnd(&mut self, bytes_acked: u64, excess_acked: u64) { +309 if self.mode == Mode::ProbeRtt { +310 return; +311 } +312 let mut target_window = self.get_target_cwnd(self.cwnd_gain); +313 if self.is_at_full_bandwidth { +314 // Add the max recently measured ack aggregation to CWND. +315 target_window += self.ack_aggregation.max_ack_height.get(); +316 } else { +317 // Add the most recent excess acked. Because CWND never decreases in +318 // STARTUP, this will automatically create a very localized max filter. +319 target_window += excess_acked; +320 } +321 // Instead of immediately setting the target CWND as the new one, BBR grows +322 // the CWND towards |target_window| by only increasing it |bytes_acked| at a +323 // time. +324 if self.is_at_full_bandwidth { +325 self.cwnd = target_window.min(self.cwnd + bytes_acked); +326 } else if (self.cwnd_gain < target_window as f32) || (self.acked_bytes < self.init_cwnd) { +327 // If the connection is not yet out of startup phase, do not decrease +328 // the window. +329 self.cwnd += bytes_acked; +330 } +331 +332 // Enforce the limits on the congestion window. +333 if self.cwnd < self.min_cwnd { +334 self.cwnd = self.min_cwnd; +335 } +336 } +337 +338 fn calculate_recovery_window(&mut self, bytes_acked: u64, bytes_lost: u64, in_flight: u64) { +339 if !self.recovery_state.in_recovery() { +340 return; +341 } +342 // Set up the initial recovery window. +343 if self.recovery_window == 0 { +344 self.recovery_window = self.min_cwnd.max(in_flight + bytes_acked); +345 return; +346 } +347 +348 // Remove losses from the recovery window, while accounting for a potential +349 // integer underflow. +350 if self.recovery_window >= bytes_lost { +351 self.recovery_window -= bytes_lost; +352 } else { +353 // k_max_segment_size = current_mtu +354 self.recovery_window = self.current_mtu; +355 } +356 // In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH, +357 // release additional |bytes_acked| to achieve a slow-start-like behavior. +358 if self.recovery_state == RecoveryState::Growth { +359 self.recovery_window += bytes_acked; +360 } +361 +362 // Sanity checks. Ensure that we always allow to send at least an MSS or +363 // |bytes_acked| in response, whichever is larger. +364 self.recovery_window = self +365 .recovery_window +366 .max(in_flight + bytes_acked) +367 .max(self.min_cwnd); +368 } +369 +370 /// <https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control#section-4.3.2.2> +371 fn check_if_full_bw_reached(&mut self, app_limited: bool) { +372 if app_limited { +373 return; +374 } +375 let target = (self.bw_at_last_round as f64 * K_STARTUP_GROWTH_TARGET as f64) as u64; +376 let bw = self.max_bandwidth.get_estimate(); +377 if bw >= target { +378 self.bw_at_last_round = bw; +379 self.round_wo_bw_gain = 0; +380 self.ack_aggregation.max_ack_height.reset(); +381 return; +382 } +383 +384 self.round_wo_bw_gain += 1; +385 if self.round_wo_bw_gain >= K_ROUND_TRIPS_WITHOUT_GROWTH_BEFORE_EXITING_STARTUP as u64 +386 || (self.recovery_state.in_recovery()) +387 { +388 self.is_at_full_bandwidth = true; +389 } +390 } +391} +392 +393impl Controller for Bbr { +394 fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64) { +395 self.max_sent_packet_number = last_packet_number; +396 self.max_bandwidth.on_sent(now, bytes); +397 } +398 +399 fn on_ack( +400 &mut self, +401 now: Instant, +402 sent: Instant, +403 bytes: u64, +404 app_limited: bool, +405 rtt: &RttEstimator, +406 ) { +407 self.max_bandwidth +408 .on_ack(now, sent, bytes, self.round_count, app_limited); +409 self.acked_bytes += bytes; +410 if self.is_min_rtt_expired(now, app_limited) || self.min_rtt > rtt.min() { +411 self.min_rtt = rtt.min(); +412 } +413 } +414 +415 fn on_end_acks( +416 &mut self, +417 now: Instant, +418 in_flight: u64, +419 app_limited: bool, +420 largest_packet_num_acked: Option<u64>, +421 ) { +422 let bytes_acked = self.max_bandwidth.bytes_acked_this_window(); +423 let excess_acked = self.ack_aggregation.update_ack_aggregation_bytes( +424 bytes_acked, +425 now, +426 self.round_count, +427 self.max_bandwidth.get_estimate(), +428 ); +429 self.max_bandwidth.end_acks(self.round_count, app_limited); +430 if let Some(largest_acked_packet) = largest_packet_num_acked { +431 self.max_acked_packet_number = largest_acked_packet; +432 } +433 +434 let mut is_round_start = false; +435 if bytes_acked > 0 { +436 is_round_start = +437 self.max_acked_packet_number > self.current_round_trip_end_packet_number; +438 if is_round_start { +439 self.current_round_trip_end_packet_number = self.max_sent_packet_number; +440 self.round_count += 1; +441 } +442 } +443 +444 self.update_recovery_state(is_round_start); 445 -446 if is_round_start && !self.is_at_full_bandwidth { -447 self.check_if_full_bw_reached(app_limited); +446 if self.mode == Mode::ProbeBw { +447 self.update_gain_cycle_phase(now, in_flight); 448 } 449 -450 self.maybe_exit_startup_or_drain(now, in_flight); -451 -452 self.maybe_enter_or_exit_probe_rtt(now, is_round_start, in_flight, app_limited); +450 if is_round_start && !self.is_at_full_bandwidth { +451 self.check_if_full_bw_reached(app_limited); +452 } 453 -454 // After the model is updated, recalculate the pacing rate and congestion window. -455 self.calculate_pacing_rate(); -456 self.calculate_cwnd(bytes_acked, excess_acked); -457 self.calculate_recovery_window(bytes_acked, self.loss_state.lost_bytes, in_flight); -458 -459 self.prev_in_flight_count = in_flight; -460 self.loss_state.reset(); -461 } +454 self.maybe_exit_startup_or_drain(now, in_flight); +455 +456 self.maybe_enter_or_exit_probe_rtt(now, is_round_start, in_flight, app_limited); +457 +458 // After the model is updated, recalculate the pacing rate and congestion window. +459 self.calculate_pacing_rate(); +460 self.calculate_cwnd(bytes_acked, excess_acked); +461 self.calculate_recovery_window(bytes_acked, self.loss_state.lost_bytes, in_flight); 462 -463 fn on_congestion_event( -464 &mut self, -465 _now: Instant, -466 _sent: Instant, -467 _is_persistent_congestion: bool, -468 _is_ecn: bool, -469 lost_bytes: u64, -470 ) { -471 self.loss_state.lost_bytes += lost_bytes; -472 } -473 -474 fn on_mtu_update(&mut self, new_mtu: u16) { -475 self.current_mtu = new_mtu as u64; -476 self.min_cwnd = calculate_min_window(self.current_mtu); -477 self.init_cwnd = self.config.initial_window.max(self.min_cwnd); -478 self.cwnd = self.cwnd.max(self.min_cwnd); -479 } -480 -481 fn window(&self) -> u64 { -482 if self.mode == Mode::ProbeRtt { -483 return self.get_probe_rtt_cwnd(); -484 } else if self.recovery_state.in_recovery() && self.mode != Mode::Startup { -485 return self.cwnd.min(self.recovery_window); -486 } -487 self.cwnd -488 } -489 -490 fn metrics(&self) -> ControllerMetrics { -491 ControllerMetrics { -492 congestion_window: self.window(), -493 ssthresh: None, -494 pacing_rate: Some(self.pacing_rate * 8), -495 } -496 } -497 -498 fn clone_box(&self) -> Box<dyn Controller> { -499 Box::new(self.clone()) +463 self.prev_in_flight_count = in_flight; +464 self.loss_state.reset(); +465 } +466 +467 fn on_congestion_event( +468 &mut self, +469 _now: Instant, +470 _sent: Instant, +471 _is_persistent_congestion: bool, +472 _is_ecn: bool, +473 lost_bytes: u64, +474 ) { +475 self.loss_state.lost_bytes += lost_bytes; +476 } +477 +478 fn on_mtu_update(&mut self, new_mtu: u16) { +479 self.current_mtu = new_mtu as u64; +480 self.min_cwnd = calculate_min_window(self.current_mtu); +481 self.init_cwnd = self.config.initial_window.max(self.min_cwnd); +482 self.cwnd = self.cwnd.max(self.min_cwnd); +483 } +484 +485 fn window(&self) -> u64 { +486 if self.mode == Mode::ProbeRtt { +487 return self.get_probe_rtt_cwnd(); +488 } else if self.recovery_state.in_recovery() && self.mode != Mode::Startup { +489 return self.cwnd.min(self.recovery_window); +490 } +491 self.cwnd +492 } +493 +494 fn metrics(&self) -> ControllerMetrics { +495 ControllerMetrics { +496 congestion_window: self.window(), +497 ssthresh: None, +498 pacing_rate: Some(self.pacing_rate * 8), +499 } 500 } 501 -502 fn initial_window(&self) -> u64 { -503 self.config.initial_window +502 fn clone_box(&self) -> Box<dyn Controller> { +503 Box::new(self.clone()) 504 } 505 -506 fn into_any(self: Box<Self>) -> Box<dyn Any> { -507 self -508 } -509} -510 -511/// Configuration for the [`Bbr`] congestion controller -512#[derive(Debug, Clone)] -513pub struct BbrConfig { -514 initial_window: u64, -515} -516 -517impl BbrConfig { -518 /// Default limit on the amount of outstanding data in bytes. -519 /// -520 /// Recommended value: `min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))` -521 pub fn initial_window(&mut self, value: u64) -> &mut Self { -522 self.initial_window = value; -523 self -524 } -525} -526 -527impl Default for BbrConfig { -528 fn default() -> Self { -529 Self { -530 initial_window: K_MAX_INITIAL_CONGESTION_WINDOW * BASE_DATAGRAM_SIZE, -531 } -532 } -533} -534 -535impl ControllerFactory for BbrConfig { -536 fn build(self: Arc<Self>, _now: Instant, current_mtu: u16) -> Box<dyn Controller> { -537 Box::new(Bbr::new(self, current_mtu)) -538 } -539} -540 -541#[derive(Debug, Default, Copy, Clone)] -542struct AckAggregationState { -543 max_ack_height: MinMax, -544 aggregation_epoch_start_time: Option<Instant>, -545 aggregation_epoch_bytes: u64, -546} -547 -548impl AckAggregationState { -549 fn update_ack_aggregation_bytes( -550 &mut self, -551 newly_acked_bytes: u64, -552 now: Instant, -553 round: u64, -554 max_bandwidth: u64, -555 ) -> u64 { -556 // Compute how many bytes are expected to be delivered, assuming max -557 // bandwidth is correct. -558 let expected_bytes_acked = max_bandwidth -559 * now -560 .saturating_duration_since(self.aggregation_epoch_start_time.unwrap_or(now)) -561 .as_micros() as u64 -562 / 1_000_000; -563 -564 // Reset the current aggregation epoch as soon as the ack arrival rate is -565 // less than or equal to the max bandwidth. -566 if self.aggregation_epoch_bytes <= expected_bytes_acked { -567 // Reset to start measuring a new aggregation epoch. -568 self.aggregation_epoch_bytes = newly_acked_bytes; -569 self.aggregation_epoch_start_time = Some(now); -570 return 0; -571 } -572 -573 // Compute how many extra bytes were delivered vs max bandwidth. -574 // Include the bytes most recently acknowledged to account for stretch acks. -575 self.aggregation_epoch_bytes += newly_acked_bytes; -576 let diff = self.aggregation_epoch_bytes - expected_bytes_acked; -577 self.max_ack_height.update_max(round, diff); -578 diff -579 } -580} -581 -582#[derive(Debug, Clone, Copy, Eq, PartialEq)] -583enum Mode { -584 // Startup phase of the connection. -585 Startup, -586 // After achieving the highest possible bandwidth during the startup, lower -587 // the pacing rate in order to drain the queue. -588 Drain, -589 // Cruising mode. -590 ProbeBw, -591 // Temporarily slow down sending in order to empty the buffer and measure -592 // the real minimum RTT. -593 ProbeRtt, -594} -595 -596// Indicates how the congestion control limits the amount of bytes in flight. -597#[derive(Debug, Clone, Copy, Eq, PartialEq)] -598enum RecoveryState { -599 // Do not limit. -600 NotInRecovery, -601 // Allow an extra outstanding byte for each byte acknowledged. -602 Conservation, -603 // Allow two extra outstanding bytes for each byte acknowledged (slow -604 // start). -605 Growth, -606} -607 -608impl RecoveryState { -609 pub(super) fn in_recovery(&self) -> bool { -610 !matches!(self, Self::NotInRecovery) -611 } -612} -613 -614#[derive(Debug, Clone, Default)] -615struct LossState { -616 lost_bytes: u64, -617} -618 -619impl LossState { -620 pub(super) fn reset(&mut self) { -621 self.lost_bytes = 0; -622 } -623 -624 pub(super) fn has_losses(&self) -> bool { -625 self.lost_bytes != 0 -626 } -627} -628 -629fn calculate_min_window(current_mtu: u64) -> u64 { -630 4 * current_mtu +506 fn initial_window(&self) -> u64 { +507 self.config.initial_window +508 } +509 +510 fn into_any(self: Box<Self>) -> Box<dyn Any> { +511 self +512 } +513} +514 +515/// Configuration for the [`Bbr`] congestion controller +516#[derive(Debug, Clone)] +517pub struct BbrConfig { +518 initial_window: u64, +519} +520 +521impl BbrConfig { +522 /// Default limit on the amount of outstanding data in bytes. +523 /// +524 /// Recommended value: `min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))` +525 pub fn initial_window(&mut self, value: u64) -> &mut Self { +526 self.initial_window = value; +527 self +528 } +529} +530 +531impl Default for BbrConfig { +532 fn default() -> Self { +533 Self { +534 initial_window: K_MAX_INITIAL_CONGESTION_WINDOW * BASE_DATAGRAM_SIZE, +535 } +536 } +537} +538 +539impl ControllerFactory for BbrConfig { +540 fn build(self: Arc<Self>, _now: Instant, current_mtu: u16) -> Box<dyn Controller> { +541 Box::new(Bbr::new(self, current_mtu)) +542 } +543} +544 +545#[derive(Debug, Default, Copy, Clone)] +546struct AckAggregationState { +547 max_ack_height: MinMax, +548 aggregation_epoch_start_time: Option<Instant>, +549 aggregation_epoch_bytes: u64, +550} +551 +552impl AckAggregationState { +553 fn update_ack_aggregation_bytes( +554 &mut self, +555 newly_acked_bytes: u64, +556 now: Instant, +557 round: u64, +558 max_bandwidth: u64, +559 ) -> u64 { +560 // Compute how many bytes are expected to be delivered, assuming max +561 // bandwidth is correct. +562 let expected_bytes_acked = max_bandwidth +563 * now +564 .saturating_duration_since(self.aggregation_epoch_start_time.unwrap_or(now)) +565 .as_micros() as u64 +566 / 1_000_000; +567 +568 // Reset the current aggregation epoch as soon as the ack arrival rate is +569 // less than or equal to the max bandwidth. +570 if self.aggregation_epoch_bytes <= expected_bytes_acked { +571 // Reset to start measuring a new aggregation epoch. +572 self.aggregation_epoch_bytes = newly_acked_bytes; +573 self.aggregation_epoch_start_time = Some(now); +574 return 0; +575 } +576 +577 // Compute how many extra bytes were delivered vs max bandwidth. +578 // Include the bytes most recently acknowledged to account for stretch acks. +579 self.aggregation_epoch_bytes += newly_acked_bytes; +580 let diff = self.aggregation_epoch_bytes - expected_bytes_acked; +581 self.max_ack_height.update_max(round, diff); +582 diff +583 } +584} +585 +586#[derive(Debug, Clone, Copy, Eq, PartialEq)] +587enum Mode { +588 // Startup phase of the connection. +589 Startup, +590 // After achieving the highest possible bandwidth during the startup, lower +591 // the pacing rate in order to drain the queue. +592 Drain, +593 // Cruising mode. +594 ProbeBw, +595 // Temporarily slow down sending in order to empty the buffer and measure +596 // the real minimum RTT. +597 ProbeRtt, +598} +599 +600// Indicates how the congestion control limits the amount of bytes in flight. +601#[derive(Debug, Clone, Copy, Eq, PartialEq)] +602enum RecoveryState { +603 // Do not limit. +604 NotInRecovery, +605 // Allow an extra outstanding byte for each byte acknowledged. +606 Conservation, +607 // Allow two extra outstanding bytes for each byte acknowledged (slow +608 // start). +609 Growth, +610} +611 +612impl RecoveryState { +613 pub(super) fn in_recovery(&self) -> bool { +614 !matches!(self, Self::NotInRecovery) +615 } +616} +617 +618#[derive(Debug, Clone, Default)] +619struct LossState { +620 lost_bytes: u64, +621} +622 +623impl LossState { +624 pub(super) fn reset(&mut self) { +625 self.lost_bytes = 0; +626 } +627 +628 pub(super) fn has_losses(&self) -> bool { +629 self.lost_bytes != 0 +630 } 631} 632 -633// The gain used for the STARTUP, equal to 2/ln(2). -634const K_DEFAULT_HIGH_GAIN: f32 = 2.885; -635// The newly derived CWND gain for STARTUP, 2. -636const K_DERIVED_HIGH_CWNDGAIN: f32 = 2.0; -637// The cycle of gains used during the ProbeBw stage. -638const K_PACING_GAIN: [f32; 8] = [1.25, 0.75, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; -639 -640const K_STARTUP_GROWTH_TARGET: f32 = 1.25; -641const K_ROUND_TRIPS_WITHOUT_GROWTH_BEFORE_EXITING_STARTUP: u8 = 3; -642 -643// Do not allow initial congestion window to be greater than 200 packets. -644const K_MAX_INITIAL_CONGESTION_WINDOW: u64 = 200; -645 -646const PROBE_RTT_BASED_ON_BDP: bool = true; -647const DRAIN_TO_TARGET: bool = true; \ No newline at end of file +633fn calculate_min_window(current_mtu: u64) -> u64 { +634 4 * current_mtu +635} +636 +637// The gain used for the STARTUP, equal to 2/ln(2). +638const K_DEFAULT_HIGH_GAIN: f32 = 2.885; +639// The newly derived CWND gain for STARTUP, 2. +640const K_DERIVED_HIGH_CWNDGAIN: f32 = 2.0; +641// The cycle of gains used during the ProbeBw stage. +642const K_PACING_GAIN: [f32; 8] = [1.25, 0.75, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; +643 +644const K_STARTUP_GROWTH_TARGET: f32 = 1.25; +645const K_ROUND_TRIPS_WITHOUT_GROWTH_BEFORE_EXITING_STARTUP: u8 = 3; +646 +647// Do not allow initial congestion window to be greater than 200 packets. +648const K_MAX_INITIAL_CONGESTION_WINDOW: u64 = 200; +649 +650const PROBE_RTT_BASED_ON_BDP: bool = true; +651const DRAIN_TO_TARGET: bool = true; \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/assembler.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/assembler.rs.html index 92fc59de0..fd61c9cb1 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/assembler.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/assembler.rs.html @@ -335,7 +335,7 @@ 335 336/// Error indicating that an ordered read was performed on a stream after an unordered read 337#[derive(Debug)] -338pub struct IllegalOrderedRead; +338pub(crate) struct IllegalOrderedRead; 339 340#[cfg(test)] 341mod test { diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/datagrams.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/datagrams.rs.html index 6419a431a..6248844ea 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/datagrams.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/datagrams.rs.html @@ -146,70 +146,75 @@ 146 147 /// Discard outgoing datagrams with a payload larger than `max_payload` bytes 148 /// -149 /// Used to ensure that reductions in MTU don't get us stuck in a state where we have a datagram -150 /// queued but can't send it. -151 pub(super) fn drop_oversized(&mut self, max_payload: usize) { -152 self.outgoing.retain(|datagram| { -153 let result = datagram.data.len() < max_payload; -154 if !result { -155 trace!( -156 "dropping {} byte datagram violating {} byte limit", -157 datagram.data.len(), -158 max_payload -159 ); -160 self.outgoing_total -= datagram.data.len(); -161 } -162 result -163 }); -164 } -165 -166 /// Attempt to write a datagram frame into `buf`, consuming it from `self.outgoing` -167 /// -168 /// Returns whether a frame was written. At most `max_size` bytes will be written, including -169 /// framing. -170 pub(super) fn write(&mut self, buf: &mut impl BufMut) -> bool { -171 let datagram = match self.outgoing.pop_front() { -172 Some(x) => x, -173 None => return false, -174 }; -175 -176 if buf.remaining_mut() < datagram.size(true) { -177 // Future work: we could be more clever about cramming small datagrams into -178 // mostly-full packets when a larger one is queued first -179 self.outgoing.push_front(datagram); -180 return false; -181 } -182 -183 trace!(len = datagram.data.len(), "DATAGRAM"); -184 -185 self.outgoing_total -= datagram.data.len(); -186 datagram.encode(buf); -187 true -188 } +149 /// Returns whether any datagrams were dropped. +150 /// +151 /// Used to ensure that reductions in MTU don't get us stuck in a state where we have a datagram +152 /// queued but can't send it. +153 pub(super) fn drop_oversized(&mut self, max_payload: usize) -> bool { +154 let mut dropped_any = false; +155 self.outgoing.retain(|datagram| { +156 let result = datagram.data.len() < max_payload; +157 if !result { +158 trace!( +159 "dropping {} byte datagram violating {} byte limit", +160 datagram.data.len(), +161 max_payload +162 ); +163 self.outgoing_total -= datagram.data.len(); +164 dropped_any = true; +165 } +166 result +167 }); +168 dropped_any +169 } +170 +171 /// Attempt to write a datagram frame into `buf`, consuming it from `self.outgoing` +172 /// +173 /// Returns whether a frame was written. At most `max_size` bytes will be written, including +174 /// framing. +175 pub(super) fn write(&mut self, buf: &mut impl BufMut) -> bool { +176 let datagram = match self.outgoing.pop_front() { +177 Some(x) => x, +178 None => return false, +179 }; +180 +181 if buf.remaining_mut() < datagram.size(true) { +182 // Future work: we could be more clever about cramming small datagrams into +183 // mostly-full packets when a larger one is queued first +184 self.outgoing.push_front(datagram); +185 return false; +186 } +187 +188 trace!(len = datagram.data.len(), "DATAGRAM"); 189 -190 pub(super) fn recv(&mut self) -> Option<Bytes> { -191 let x = self.incoming.pop_front()?.data; -192 self.recv_buffered -= x.len(); -193 Some(x) -194 } -195} -196 -197/// Errors that can arise when sending a datagram -198#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -199pub enum SendDatagramError { -200 /// The peer does not support receiving datagram frames -201 #[error("datagrams not supported by peer")] -202 UnsupportedByPeer, -203 /// Datagram support is disabled locally -204 #[error("datagram support disabled")] -205 Disabled, -206 /// The datagram is larger than the connection can currently accommodate -207 /// -208 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been -209 /// exceeded. -210 #[error("datagram too large")] -211 TooLarge, -212 /// Send would block -213 #[error("datagram send blocked")] -214 Blocked(Bytes), -215} \ No newline at end of file +190 self.outgoing_total -= datagram.data.len(); +191 datagram.encode(buf); +192 true +193 } +194 +195 pub(super) fn recv(&mut self) -> Option<Bytes> { +196 let x = self.incoming.pop_front()?.data; +197 self.recv_buffered -= x.len(); +198 Some(x) +199 } +200} +201 +202/// Errors that can arise when sending a datagram +203#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +204pub enum SendDatagramError { +205 /// The peer does not support receiving datagram frames +206 #[error("datagrams not supported by peer")] +207 UnsupportedByPeer, +208 /// Datagram support is disabled locally +209 #[error("datagram support disabled")] +210 Disabled, +211 /// The datagram is larger than the connection can currently accommodate +212 /// +213 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been +214 /// exceeded. +215 #[error("datagram too large")] +216 TooLarge, +217 /// Send would block +218 #[error("datagram send blocked")] +219 Blocked(Bytes), +220} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/mod.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/mod.rs.html index 6234f0d93..53bc4d0a6 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/mod.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/mod.rs.html @@ -164,2147 +164,2147 @@ 164 /// deterministically select the next PathId to send on. 165 // TODO(flub): well does it really? But deterministic is nice for now. 166 paths: BTreeMap<PathId, PathState>, -167 /// Incremented every time we see a new path +167 /// Counter to uniquely identify every [`PathData`] created in this connection. 168 /// -169 /// Stored separately from `path.generation` to account for aborted migrations -170 path_counter: u64, -171 /// Whether MTU detection is supported in this environment -172 allow_mtud: bool, -173 state: State, -174 side: ConnectionSide, -175 /// Whether or not 0-RTT was enabled during the handshake. Does not imply acceptance. -176 zero_rtt_enabled: bool, -177 /// Set if 0-RTT is supported, then cleared when no longer needed. -178 zero_rtt_crypto: Option<ZeroRttCrypto>, -179 key_phase: bool, -180 /// How many packets are in the current key phase. Used only for `Data` space. -181 key_phase_size: u64, -182 /// Transport parameters set by the peer -183 peer_params: TransportParameters, -184 /// Source ConnectionId of the first packet received from the peer -185 orig_rem_cid: ConnectionId, -186 /// Destination ConnectionId sent by the client on the first Initial -187 initial_dst_cid: ConnectionId, -188 /// The value that the server included in the Source Connection ID field of a Retry packet, if -189 /// one was received -190 retry_src_cid: Option<ConnectionId>, -191 /// Events returned by [`Connection::poll`] -192 events: VecDeque<Event>, -193 endpoint_events: VecDeque<EndpointEventInner>, -194 /// Whether the spin bit is in use for this connection -195 spin_enabled: bool, -196 /// Outgoing spin bit state -197 spin: bool, -198 /// Packet number spaces: initial, handshake, 1-RTT -199 spaces: [PacketSpace; 3], -200 /// Highest usable [`SpaceId`] -201 highest_space: SpaceId, -202 /// 1-RTT keys used prior to a key update -203 prev_crypto: Option<PrevCrypto>, -204 /// 1-RTT keys to be used for the next key update -205 /// -206 /// These are generated in advance to prevent timing attacks and/or DoS by third-party attackers -207 /// spoofing key updates. -208 next_crypto: Option<KeyPair<Box<dyn PacketKey>>>, -209 accepted_0rtt: bool, -210 /// Whether the idle timer should be reset the next time an ack-eliciting packet is transmitted. -211 permit_idle_reset: bool, -212 /// Negotiated idle timeout -213 idle_timeout: Option<Duration>, -214 timers: TimerTable, -215 /// Number of packets received which could not be authenticated -216 authentication_failures: u64, -217 -218 // -219 // Queued non-retransmittable 1-RTT data -220 // -221 /// If the CONNECTION_CLOSE frame needs to be sent -222 close: bool, -223 -224 // -225 // ACK frequency -226 // -227 ack_frequency: AckFrequencyState, -228 -229 // -230 // Congestion Control -231 // -232 /// Whether the most recently received packet had an ECN codepoint set -233 receiving_ecn: bool, -234 /// Number of packets authenticated -235 total_authed_packets: u64, -236 /// Whether the last `poll_transmit` call yielded no data because there was -237 /// no outgoing application data. -238 app_limited: bool, -239 -240 // -241 // ObservedAddr -242 // -243 /// Sequence number for the next observed address frame sent to the peer. -244 next_observed_addr_seq_no: VarInt, -245 -246 streams: StreamsState, -247 /// Surplus remote CIDs for future use on new paths -248 /// -249 /// These are given out before multiple paths exist, also for paths that will never -250 /// exist. So if multipath is supported the number of paths here will be higher than -251 /// the actual number of paths in use. -252 rem_cids: FxHashMap<PathId, CidQueue>, -253 /// Attributes of CIDs generated by local endpoint -254 /// -255 /// Any path that is allowed to be opened is present in this map, as well as the already -256 /// opened paths. However since CIDs are issued async by the endpoint driver via -257 /// connection events it can not be used to know if CIDs have been issued for a path or -258 /// not. See [`Connection::max_path_id_with_cids`] for this. -259 local_cid_state: FxHashMap<PathId, CidState>, -260 /// State of the unreliable datagram extension -261 datagrams: DatagramState, -262 /// Connection level statistics -263 stats: ConnectionStats, -264 /// Path level statistics -265 path_stats: FxHashMap<PathId, PathStats>, -266 /// QUIC version used for the connection. -267 version: u32, -268 -269 // -270 // Multipath -271 // -272 /// Maximum number of concurrent paths -273 /// -274 /// Initially set from the [`TransportConfig::max_concurrent_multipath_paths`]. Even -275 /// when multipath is disabled this will be set to 1, it is not used in that case -276 /// though. -277 max_concurrent_paths: NonZeroU32, -278 /// Local maximum [`PathId`] to be used -279 /// -280 /// This is initially set to [`TransportConfig::get_initial_max_path_id`] when multipath -281 /// is negotiated, or to [`PathId::ZERO`] otherwise. This is essentially the value of -282 /// the highest MAX_PATH_ID frame sent. -283 /// -284 /// Any path with an ID equal or below this [`PathId`] is either: -285 /// -286 /// - Abandoned, if it is also in [`Connection::abandoned_paths`]. -287 /// - Open, in this case it is present in [`Connection::paths`] -288 /// - Not yet opened, if it is in neither of these two places. -289 /// -290 /// Note that for not-yet-open there may or may not be any CIDs issued. See -291 /// [`Connection::max_path_id_with_cids`]. -292 local_max_path_id: PathId, -293 /// Remote's maximum [`PathId`] to be used -294 /// -295 /// This is initially set to the peer's [`TransportParameters::initial_max_path_id`] when -296 /// multipath is negotiated, or to [`PathId::ZERO`] otherwise. A peer may increase this limit -297 /// by sending [`Frame::MaxPathId`] frames. -298 remote_max_path_id: PathId, -299 /// The greatest [`PathId`] we have issued CIDs for -300 /// -301 /// CIDs are only issued for `min(local_max_path_id, remote_max_path_id)`. It is not -302 /// possible to use [`Connection::local_cid_state`] to know if CIDs have been issued -303 /// since they are issued asynchronously by the endpoint driver. -304 max_path_id_with_cids: PathId, -305 /// The paths already abandoned -306 /// -307 /// They may still have some state left in [`Connection::paths`] or -308 /// [`Connection::local_cid_state`] since some of this has to be kept around for some -309 /// time after a path is abandoned. -310 // TODO(flub): Make this a more efficient data structure. Like ranges of abandoned -311 // paths. Or a set together with a minimum. Or something. -312 abandoned_paths: FxHashSet<PathId>, -313 -314 iroh_hp: iroh_hp::State, -315 qlog: QlogSink, -316} -317 -318#[derive(Debug)] -319enum PollPathStatus { -320 Send, -321 SendTransmit { transmit: Transmit }, -322 NothingToSend { congestion_blocked: bool }, +169 /// Each [`PathData`] gets a [`PathData::generation`] that is unique among all +170 /// [`PathData`]s created in the lifetime of this connection. This helps identify the +171 /// correct path when RFC9000-style migrations happen, even when they are +172 /// aborted. +173 /// +174 /// Multipath does not change this, each path can also undergo RFC9000-style +175 /// migrations. So a single multipath path ID could see several [`PathData`]s each with +176 /// their unique [`PathData::generation]. +177 path_generation_counter: u64, +178 /// Whether MTU detection is supported in this environment +179 allow_mtud: bool, +180 state: State, +181 side: ConnectionSide, +182 /// Whether or not 0-RTT was enabled during the handshake. Does not imply acceptance. +183 zero_rtt_enabled: bool, +184 /// Set if 0-RTT is supported, then cleared when no longer needed. +185 zero_rtt_crypto: Option<ZeroRttCrypto>, +186 key_phase: bool, +187 /// How many packets are in the current key phase. Used only for `Data` space. +188 key_phase_size: u64, +189 /// Transport parameters set by the peer +190 peer_params: TransportParameters, +191 /// Source ConnectionId of the first packet received from the peer +192 orig_rem_cid: ConnectionId, +193 /// Destination ConnectionId sent by the client on the first Initial +194 initial_dst_cid: ConnectionId, +195 /// The value that the server included in the Source Connection ID field of a Retry packet, if +196 /// one was received +197 retry_src_cid: Option<ConnectionId>, +198 /// Events returned by [`Connection::poll`] +199 events: VecDeque<Event>, +200 endpoint_events: VecDeque<EndpointEventInner>, +201 /// Whether the spin bit is in use for this connection +202 spin_enabled: bool, +203 /// Outgoing spin bit state +204 spin: bool, +205 /// Packet number spaces: initial, handshake, 1-RTT +206 spaces: [PacketSpace; 3], +207 /// Highest usable [`SpaceId`] +208 highest_space: SpaceId, +209 /// 1-RTT keys used prior to a key update +210 prev_crypto: Option<PrevCrypto>, +211 /// 1-RTT keys to be used for the next key update +212 /// +213 /// These are generated in advance to prevent timing attacks and/or DoS by third-party attackers +214 /// spoofing key updates. +215 next_crypto: Option<KeyPair<Box<dyn PacketKey>>>, +216 accepted_0rtt: bool, +217 /// Whether the idle timer should be reset the next time an ack-eliciting packet is transmitted. +218 permit_idle_reset: bool, +219 /// Negotiated idle timeout +220 idle_timeout: Option<Duration>, +221 timers: TimerTable, +222 /// Number of packets received which could not be authenticated +223 authentication_failures: u64, +224 +225 // +226 // Queued non-retransmittable 1-RTT data +227 // +228 /// If the CONNECTION_CLOSE frame needs to be sent +229 close: bool, +230 +231 // +232 // ACK frequency +233 // +234 ack_frequency: AckFrequencyState, +235 +236 // +237 // Congestion Control +238 // +239 /// Whether the most recently received packet had an ECN codepoint set +240 receiving_ecn: bool, +241 /// Number of packets authenticated +242 total_authed_packets: u64, +243 /// Whether the last `poll_transmit` call yielded no data because there was +244 /// no outgoing application data. +245 app_limited: bool, +246 +247 // +248 // ObservedAddr +249 // +250 /// Sequence number for the next observed address frame sent to the peer. +251 next_observed_addr_seq_no: VarInt, +252 +253 streams: StreamsState, +254 /// Surplus remote CIDs for future use on new paths +255 /// +256 /// These are given out before multiple paths exist, also for paths that will never +257 /// exist. So if multipath is supported the number of paths here will be higher than +258 /// the actual number of paths in use. +259 rem_cids: FxHashMap<PathId, CidQueue>, +260 /// Attributes of CIDs generated by local endpoint +261 /// +262 /// Any path that is allowed to be opened is present in this map, as well as the already +263 /// opened paths. However since CIDs are issued async by the endpoint driver via +264 /// connection events it can not be used to know if CIDs have been issued for a path or +265 /// not. See [`Connection::max_path_id_with_cids`] for this. +266 local_cid_state: FxHashMap<PathId, CidState>, +267 /// State of the unreliable datagram extension +268 datagrams: DatagramState, +269 /// Connection level statistics +270 stats: ConnectionStats, +271 /// Path level statistics +272 path_stats: FxHashMap<PathId, PathStats>, +273 /// QUIC version used for the connection. +274 version: u32, +275 +276 // +277 // Multipath +278 // +279 /// Maximum number of concurrent paths +280 /// +281 /// Initially set from the [`TransportConfig::max_concurrent_multipath_paths`]. Even +282 /// when multipath is disabled this will be set to 1, it is not used in that case +283 /// though. +284 max_concurrent_paths: NonZeroU32, +285 /// Local maximum [`PathId`] to be used +286 /// +287 /// This is initially set to [`TransportConfig::get_initial_max_path_id`] when multipath +288 /// is negotiated, or to [`PathId::ZERO`] otherwise. This is essentially the value of +289 /// the highest MAX_PATH_ID frame sent. +290 /// +291 /// Any path with an ID equal or below this [`PathId`] is either: +292 /// +293 /// - Abandoned, if it is also in [`Connection::abandoned_paths`]. +294 /// - Open, in this case it is present in [`Connection::paths`] +295 /// - Not yet opened, if it is in neither of these two places. +296 /// +297 /// Note that for not-yet-open there may or may not be any CIDs issued. See +298 /// [`Connection::max_path_id_with_cids`]. +299 local_max_path_id: PathId, +300 /// Remote's maximum [`PathId`] to be used +301 /// +302 /// This is initially set to the peer's [`TransportParameters::initial_max_path_id`] when +303 /// multipath is negotiated, or to [`PathId::ZERO`] otherwise. A peer may increase this limit +304 /// by sending [`Frame::MaxPathId`] frames. +305 remote_max_path_id: PathId, +306 /// The greatest [`PathId`] we have issued CIDs for +307 /// +308 /// CIDs are only issued for `min(local_max_path_id, remote_max_path_id)`. It is not +309 /// possible to use [`Connection::local_cid_state`] to know if CIDs have been issued +310 /// since they are issued asynchronously by the endpoint driver. +311 max_path_id_with_cids: PathId, +312 /// The paths already abandoned +313 /// +314 /// They may still have some state left in [`Connection::paths`] or +315 /// [`Connection::local_cid_state`] since some of this has to be kept around for some +316 /// time after a path is abandoned. +317 // TODO(flub): Make this a more efficient data structure. Like ranges of abandoned +318 // paths. Or a set together with a minimum. Or something. +319 abandoned_paths: FxHashSet<PathId>, +320 +321 iroh_hp: iroh_hp::State, +322 qlog: QlogSink, 323} 324 325#[derive(Debug)] -326enum PollPathSpaceStatus { -327 NextSpace, -328 Send { last_packet_number: Option<u64> }, -329 SendTransmit { transmit: Transmit }, -330 NothingToSend { congestion_blocked: bool }, -331} -332 -333impl Connection { -334 pub(crate) fn new( -335 endpoint_config: Arc<EndpointConfig>, -336 config: Arc<TransportConfig>, -337 init_cid: ConnectionId, -338 loc_cid: ConnectionId, -339 rem_cid: ConnectionId, -340 network_path: FourTuple, -341 crypto: Box<dyn crypto::Session>, -342 cid_gen: &dyn ConnectionIdGenerator, -343 now: Instant, -344 version: u32, -345 allow_mtud: bool, -346 rng_seed: [u8; 32], -347 side_args: SideArgs, -348 qlog: QlogSink, -349 ) -> Self { -350 let pref_addr_cid = side_args.pref_addr_cid(); -351 let path_validated = side_args.path_validated(); -352 let connection_side = ConnectionSide::from(side_args); -353 let side = connection_side.side(); -354 let mut rng = StdRng::from_seed(rng_seed); -355 let initial_space = { -356 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut rng); -357 space.crypto = Some(crypto.initial_keys(init_cid, side)); -358 space -359 }; -360 let handshake_space = PacketSpace::new(now, SpaceId::Handshake, &mut rng); -361 #[cfg(test)] -362 let data_space = match config.deterministic_packet_numbers { -363 true => PacketSpace::new_deterministic(now, SpaceId::Data), -364 false => PacketSpace::new(now, SpaceId::Data, &mut rng), -365 }; -366 #[cfg(not(test))] -367 let data_space = PacketSpace::new(now, SpaceId::Data, &mut rng); -368 let state = State::handshake(state::Handshake { -369 rem_cid_set: side.is_server(), -370 expected_token: Bytes::new(), -371 client_hello: None, -372 allow_server_migration: side.is_client(), -373 }); -374 let local_cid_state = FxHashMap::from_iter([( -375 PathId::ZERO, -376 CidState::new( -377 cid_gen.cid_len(), -378 cid_gen.cid_lifetime(), -379 now, -380 if pref_addr_cid.is_some() { 2 } else { 1 }, -381 ), -382 )]); -383 -384 let mut path = PathData::new(network_path, allow_mtud, None, 0, now, &config); -385 // TODO(@divma): consider if we want to delay this until the path is validated -386 path.open = true; -387 let mut this = Self { -388 endpoint_config, -389 crypto, -390 handshake_cid: loc_cid, -391 rem_handshake_cid: rem_cid, -392 local_cid_state, -393 paths: BTreeMap::from_iter([( -394 PathId::ZERO, -395 PathState { -396 data: path, -397 prev: None, -398 }, -399 )]), -400 path_counter: 0, -401 allow_mtud, -402 state, -403 side: connection_side, -404 zero_rtt_enabled: false, -405 zero_rtt_crypto: None, -406 key_phase: false, -407 // A small initial key phase size ensures peers that don't handle key updates correctly -408 // fail sooner rather than later. It's okay for both peers to do this, as the first one -409 // to perform an update will reset the other's key phase size in `update_keys`, and a -410 // simultaneous key update by both is just like a regular key update with a really fast -411 // response. Inspired by quic-go's similar behavior of performing the first key update -412 // at the 100th short-header packet. -413 key_phase_size: rng.random_range(10..1000), -414 peer_params: TransportParameters::default(), -415 orig_rem_cid: rem_cid, -416 initial_dst_cid: init_cid, -417 retry_src_cid: None, -418 events: VecDeque::new(), -419 endpoint_events: VecDeque::new(), -420 spin_enabled: config.allow_spin && rng.random_ratio(7, 8), -421 spin: false, -422 spaces: [initial_space, handshake_space, data_space], -423 highest_space: SpaceId::Initial, -424 prev_crypto: None, -425 next_crypto: None, -426 accepted_0rtt: false, -427 permit_idle_reset: true, -428 idle_timeout: match config.max_idle_timeout { -429 None | Some(VarInt(0)) => None, -430 Some(dur) => Some(Duration::from_millis(dur.0)), -431 }, -432 timers: TimerTable::default(), -433 authentication_failures: 0, -434 close: false, -435 -436 ack_frequency: AckFrequencyState::new(get_max_ack_delay( -437 &TransportParameters::default(), -438 )), -439 -440 app_limited: false, -441 receiving_ecn: false, -442 total_authed_packets: 0, -443 -444 next_observed_addr_seq_no: 0u32.into(), -445 -446 streams: StreamsState::new( -447 side, -448 config.max_concurrent_uni_streams, -449 config.max_concurrent_bidi_streams, -450 config.send_window, -451 config.receive_window, -452 config.stream_receive_window, -453 ), -454 datagrams: DatagramState::default(), -455 config, -456 rem_cids: FxHashMap::from_iter([(PathId::ZERO, CidQueue::new(rem_cid))]), -457 rng, -458 stats: ConnectionStats::default(), -459 path_stats: Default::default(), -460 version, -461 -462 // peer params are not yet known, so multipath is not enabled -463 max_concurrent_paths: NonZeroU32::MIN, -464 local_max_path_id: PathId::ZERO, -465 remote_max_path_id: PathId::ZERO, -466 max_path_id_with_cids: PathId::ZERO, -467 abandoned_paths: Default::default(), +326enum PollPathStatus { +327 Send, +328 SendTransmit { transmit: Transmit }, +329 NothingToSend { congestion_blocked: bool }, +330} +331 +332#[derive(Debug)] +333enum PollPathSpaceStatus { +334 NextSpace, +335 Send { last_packet_number: Option<u64> }, +336 SendTransmit { transmit: Transmit }, +337 NothingToSend { congestion_blocked: bool }, +338} +339 +340impl Connection { +341 pub(crate) fn new( +342 endpoint_config: Arc<EndpointConfig>, +343 config: Arc<TransportConfig>, +344 init_cid: ConnectionId, +345 loc_cid: ConnectionId, +346 rem_cid: ConnectionId, +347 network_path: FourTuple, +348 crypto: Box<dyn crypto::Session>, +349 cid_gen: &dyn ConnectionIdGenerator, +350 now: Instant, +351 version: u32, +352 allow_mtud: bool, +353 rng_seed: [u8; 32], +354 side_args: SideArgs, +355 qlog: QlogSink, +356 ) -> Self { +357 let pref_addr_cid = side_args.pref_addr_cid(); +358 let path_validated = side_args.path_validated(); +359 let connection_side = ConnectionSide::from(side_args); +360 let side = connection_side.side(); +361 let mut rng = StdRng::from_seed(rng_seed); +362 let initial_space = { +363 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut rng); +364 space.crypto = Some(crypto.initial_keys(init_cid, side)); +365 space +366 }; +367 let handshake_space = PacketSpace::new(now, SpaceId::Handshake, &mut rng); +368 #[cfg(test)] +369 let data_space = match config.deterministic_packet_numbers { +370 true => PacketSpace::new_deterministic(now, SpaceId::Data), +371 false => PacketSpace::new(now, SpaceId::Data, &mut rng), +372 }; +373 #[cfg(not(test))] +374 let data_space = PacketSpace::new(now, SpaceId::Data, &mut rng); +375 let state = State::handshake(state::Handshake { +376 rem_cid_set: side.is_server(), +377 expected_token: Bytes::new(), +378 client_hello: None, +379 allow_server_migration: side.is_client(), +380 }); +381 let local_cid_state = FxHashMap::from_iter([( +382 PathId::ZERO, +383 CidState::new( +384 cid_gen.cid_len(), +385 cid_gen.cid_lifetime(), +386 now, +387 if pref_addr_cid.is_some() { 2 } else { 1 }, +388 ), +389 )]); +390 +391 let mut path = PathData::new(network_path, allow_mtud, None, 0, now, &config); +392 // TODO(@divma): consider if we want to delay this until the path is validated +393 path.open = true; +394 let mut this = Self { +395 endpoint_config, +396 crypto, +397 handshake_cid: loc_cid, +398 rem_handshake_cid: rem_cid, +399 local_cid_state, +400 paths: BTreeMap::from_iter([( +401 PathId::ZERO, +402 PathState { +403 data: path, +404 prev: None, +405 }, +406 )]), +407 path_generation_counter: 0, +408 allow_mtud, +409 state, +410 side: connection_side, +411 zero_rtt_enabled: false, +412 zero_rtt_crypto: None, +413 key_phase: false, +414 // A small initial key phase size ensures peers that don't handle key updates correctly +415 // fail sooner rather than later. It's okay for both peers to do this, as the first one +416 // to perform an update will reset the other's key phase size in `update_keys`, and a +417 // simultaneous key update by both is just like a regular key update with a really fast +418 // response. Inspired by quic-go's similar behavior of performing the first key update +419 // at the 100th short-header packet. +420 key_phase_size: rng.random_range(10..1000), +421 peer_params: TransportParameters::default(), +422 orig_rem_cid: rem_cid, +423 initial_dst_cid: init_cid, +424 retry_src_cid: None, +425 events: VecDeque::new(), +426 endpoint_events: VecDeque::new(), +427 spin_enabled: config.allow_spin && rng.random_ratio(7, 8), +428 spin: false, +429 spaces: [initial_space, handshake_space, data_space], +430 highest_space: SpaceId::Initial, +431 prev_crypto: None, +432 next_crypto: None, +433 accepted_0rtt: false, +434 permit_idle_reset: true, +435 idle_timeout: match config.max_idle_timeout { +436 None | Some(VarInt(0)) => None, +437 Some(dur) => Some(Duration::from_millis(dur.0)), +438 }, +439 timers: TimerTable::default(), +440 authentication_failures: 0, +441 close: false, +442 +443 ack_frequency: AckFrequencyState::new(get_max_ack_delay( +444 &TransportParameters::default(), +445 )), +446 +447 app_limited: false, +448 receiving_ecn: false, +449 total_authed_packets: 0, +450 +451 next_observed_addr_seq_no: 0u32.into(), +452 +453 streams: StreamsState::new( +454 side, +455 config.max_concurrent_uni_streams, +456 config.max_concurrent_bidi_streams, +457 config.send_window, +458 config.receive_window, +459 config.stream_receive_window, +460 ), +461 datagrams: DatagramState::default(), +462 config, +463 rem_cids: FxHashMap::from_iter([(PathId::ZERO, CidQueue::new(rem_cid))]), +464 rng, +465 stats: ConnectionStats::default(), +466 path_stats: Default::default(), +467 version, 468 -469 // iroh's nat traversal -470 iroh_hp: Default::default(), -471 qlog, -472 }; -473 if path_validated { -474 this.on_path_validated(PathId::ZERO); -475 } -476 if side.is_client() { -477 // Kick off the connection -478 this.write_crypto(); -479 this.init_0rtt(now); -480 } -481 this.qlog -482 .emit_tuple_assigned(PathId::ZERO, network_path, now); -483 this -484 } -485 -486 /// Returns the next time at which `handle_timeout` should be called -487 /// -488 /// The value returned may change after: -489 /// - the application performed some I/O on the connection -490 /// - a call was made to `handle_event` -491 /// - a call to `poll_transmit` returned `Some` -492 /// - a call was made to `handle_timeout` -493 #[must_use] -494 pub fn poll_timeout(&mut self) -> Option<Instant> { -495 self.timers.peek() -496 } -497 -498 /// Returns application-facing events -499 /// -500 /// Connections should be polled for events after: -501 /// - a call was made to `handle_event` -502 /// - a call was made to `handle_timeout` -503 #[must_use] -504 pub fn poll(&mut self) -> Option<Event> { -505 if let Some(x) = self.events.pop_front() { -506 return Some(x); -507 } -508 -509 if let Some(event) = self.streams.poll() { -510 return Some(Event::Stream(event)); -511 } -512 -513 if let Some(reason) = self.state.take_error() { -514 return Some(Event::ConnectionLost { reason }); -515 } -516 -517 None -518 } +469 // peer params are not yet known, so multipath is not enabled +470 max_concurrent_paths: NonZeroU32::MIN, +471 local_max_path_id: PathId::ZERO, +472 remote_max_path_id: PathId::ZERO, +473 max_path_id_with_cids: PathId::ZERO, +474 abandoned_paths: Default::default(), +475 +476 // iroh's nat traversal +477 iroh_hp: Default::default(), +478 qlog, +479 }; +480 if path_validated { +481 this.on_path_validated(PathId::ZERO); +482 } +483 if side.is_client() { +484 // Kick off the connection +485 this.write_crypto(); +486 this.init_0rtt(now); +487 } +488 this.qlog +489 .emit_tuple_assigned(PathId::ZERO, network_path, now); +490 this +491 } +492 +493 /// Returns the next time at which `handle_timeout` should be called +494 /// +495 /// The value returned may change after: +496 /// - the application performed some I/O on the connection +497 /// - a call was made to `handle_event` +498 /// - a call to `poll_transmit` returned `Some` +499 /// - a call was made to `handle_timeout` +500 #[must_use] +501 pub fn poll_timeout(&mut self) -> Option<Instant> { +502 self.timers.peek() +503 } +504 +505 /// Returns application-facing events +506 /// +507 /// Connections should be polled for events after: +508 /// - a call was made to `handle_event` +509 /// - a call was made to `handle_timeout` +510 #[must_use] +511 pub fn poll(&mut self) -> Option<Event> { +512 if let Some(x) = self.events.pop_front() { +513 return Some(x); +514 } +515 +516 if let Some(event) = self.streams.poll() { +517 return Some(Event::Stream(event)); +518 } 519 -520 /// Return endpoint-facing events -521 #[must_use] -522 pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent> { -523 self.endpoint_events.pop_front().map(EndpointEvent) -524 } -525 -526 /// Provide control over streams -527 #[must_use] -528 pub fn streams(&mut self) -> Streams<'_> { -529 Streams { -530 state: &mut self.streams, -531 conn_state: &self.state, -532 } -533 } -534 -535 /// Provide control over streams -536 #[must_use] -537 pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_> { -538 assert!(id.dir() == Dir::Bi || id.initiator() != self.side.side()); -539 RecvStream { -540 id, -541 state: &mut self.streams, -542 pending: &mut self.spaces[SpaceId::Data].pending, -543 } -544 } -545 -546 /// Provide control over streams -547 #[must_use] -548 pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_> { -549 assert!(id.dir() == Dir::Bi || id.initiator() == self.side.side()); -550 SendStream { -551 id, -552 state: &mut self.streams, -553 pending: &mut self.spaces[SpaceId::Data].pending, -554 conn_state: &self.state, -555 } -556 } -557 -558 /// Opens a new path only if no path on the same network path currently exists. -559 /// -560 /// This comparison will use [`FourTuple::is_probably_same_path`] on the given `network_path` -561 /// and pass it existing path's network paths. -562 /// -563 /// This means that you can pass `local_ip: None` to make the comparison only compare -564 /// remote addresses. -565 /// -566 /// This avoids having to guess which local interface will be used to communicate with the -567 /// remote, should it not be known yet. We assume that if we already have a path to the remote, -568 /// the OS is likely to use the same interface to talk to said remote. +520 if let Some(reason) = self.state.take_error() { +521 return Some(Event::ConnectionLost { reason }); +522 } +523 +524 None +525 } +526 +527 /// Return endpoint-facing events +528 #[must_use] +529 pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent> { +530 self.endpoint_events.pop_front().map(EndpointEvent) +531 } +532 +533 /// Provide control over streams +534 #[must_use] +535 pub fn streams(&mut self) -> Streams<'_> { +536 Streams { +537 state: &mut self.streams, +538 conn_state: &self.state, +539 } +540 } +541 +542 /// Provide control over streams +543 #[must_use] +544 pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_> { +545 assert!(id.dir() == Dir::Bi || id.initiator() != self.side.side()); +546 RecvStream { +547 id, +548 state: &mut self.streams, +549 pending: &mut self.spaces[SpaceId::Data].pending, +550 } +551 } +552 +553 /// Provide control over streams +554 #[must_use] +555 pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_> { +556 assert!(id.dir() == Dir::Bi || id.initiator() == self.side.side()); +557 SendStream { +558 id, +559 state: &mut self.streams, +560 pending: &mut self.spaces[SpaceId::Data].pending, +561 conn_state: &self.state, +562 } +563 } +564 +565 /// Opens a new path only if no path on the same network path currently exists. +566 /// +567 /// This comparison will use [`FourTuple::is_probably_same_path`] on the given `network_path` +568 /// and pass it existing path's network paths. 569 /// -570 /// See also [`open_path`]. Returns `(path_id, true)` if the path already existed. `(path_id, -571 /// false)` if was opened. +570 /// This means that you can pass `local_ip: None` to make the comparison only compare +571 /// remote addresses. 572 /// -573 /// [`open_path`]: Connection::open_path -574 pub fn open_path_ensure( -575 &mut self, -576 network_path: FourTuple, -577 initial_status: PathStatus, -578 now: Instant, -579 ) -> Result<(PathId, bool), PathError> { -580 Ok( -581 match self -582 .paths -583 .iter() -584 .find(|(_id, path)| network_path.is_probably_same_path(&path.data.network_path)) -585 { -586 Some((path_id, _state)) => (*path_id, true), -587 None => (self.open_path(network_path, initial_status, now)?, false), -588 }, -589 ) -590 } -591 -592 /// Opens a new path -593 /// -594 /// Further errors might occur and they will be emitted in [`PathEvent::LocallyClosed`] events. -595 /// When the path is opened it will be reported as an [`PathEvent::Opened`]. -596 pub fn open_path( -597 &mut self, -598 network_path: FourTuple, -599 initial_status: PathStatus, -600 now: Instant, -601 ) -> Result<PathId, PathError> { -602 if !self.is_multipath_negotiated() { -603 return Err(PathError::MultipathNotNegotiated); -604 } -605 if self.side().is_server() { -606 return Err(PathError::ServerSideNotAllowed); -607 } -608 -609 let max_abandoned = self.abandoned_paths.iter().max().copied(); -610 let max_used = self.paths.keys().last().copied(); -611 let path_id = max_abandoned -612 .max(max_used) -613 .unwrap_or(PathId::ZERO) -614 .saturating_add(1u8); +573 /// This avoids having to guess which local interface will be used to communicate with the +574 /// remote, should it not be known yet. We assume that if we already have a path to the remote, +575 /// the OS is likely to use the same interface to talk to said remote. +576 /// +577 /// See also [`open_path`]. Returns `(path_id, true)` if the path already existed. `(path_id, +578 /// false)` if was opened. +579 /// +580 /// [`open_path`]: Connection::open_path +581 pub fn open_path_ensure( +582 &mut self, +583 network_path: FourTuple, +584 initial_status: PathStatus, +585 now: Instant, +586 ) -> Result<(PathId, bool), PathError> { +587 Ok( +588 match self +589 .paths +590 .iter() +591 .find(|(_id, path)| network_path.is_probably_same_path(&path.data.network_path)) +592 { +593 Some((path_id, _state)) => (*path_id, true), +594 None => (self.open_path(network_path, initial_status, now)?, false), +595 }, +596 ) +597 } +598 +599 /// Opens a new path +600 /// +601 /// Further errors might occur and they will be emitted in [`PathEvent::LocallyClosed`] events. +602 /// When the path is opened it will be reported as an [`PathEvent::Opened`]. +603 pub fn open_path( +604 &mut self, +605 network_path: FourTuple, +606 initial_status: PathStatus, +607 now: Instant, +608 ) -> Result<PathId, PathError> { +609 if !self.is_multipath_negotiated() { +610 return Err(PathError::MultipathNotNegotiated); +611 } +612 if self.side().is_server() { +613 return Err(PathError::ServerSideNotAllowed); +614 } 615 -616 if Some(path_id) > self.max_path_id() { -617 return Err(PathError::MaxPathIdReached); -618 } -619 if path_id > self.remote_max_path_id { -620 self.spaces[SpaceId::Data].pending.paths_blocked = true; -621 return Err(PathError::MaxPathIdReached); -622 } -623 if self.rem_cids.get(&path_id).map(CidQueue::active).is_none() { -624 self.spaces[SpaceId::Data] -625 .pending -626 .path_cids_blocked -627 .push(path_id); -628 return Err(PathError::RemoteCidsExhausted); +616 let max_abandoned = self.abandoned_paths.iter().max().copied(); +617 let max_used = self.paths.keys().last().copied(); +618 let path_id = max_abandoned +619 .max(max_used) +620 .unwrap_or(PathId::ZERO) +621 .saturating_add(1u8); +622 +623 if Some(path_id) > self.max_path_id() { +624 return Err(PathError::MaxPathIdReached); +625 } +626 if path_id > self.remote_max_path_id { +627 self.spaces[SpaceId::Data].pending.paths_blocked = true; +628 return Err(PathError::MaxPathIdReached); 629 } -630 -631 let path = self.ensure_path(path_id, network_path, now, None); -632 path.status.local_update(initial_status); -633 -634 Ok(path_id) -635 } -636 -637 /// Closes a path by sending a PATH_ABANDON frame -638 /// -639 /// This will not allow closing the last path. It does allow closing paths which have -640 /// not yet been opened, as e.g. is the case when receiving a PATH_ABANDON from the peer -641 /// for a path that was never opened locally. -642 pub fn close_path( -643 &mut self, -644 now: Instant, -645 path_id: PathId, -646 error_code: VarInt, -647 ) -> Result<(), ClosePathError> { -648 if self.abandoned_paths.contains(&path_id) -649 || Some(path_id) > self.max_path_id() -650 || !self.paths.contains_key(&path_id) -651 { -652 return Err(ClosePathError::ClosedPath); -653 } -654 if self -655 .paths -656 .iter() -657 // Would there be any remaining, non-abandoned, validated paths -658 .any(|(id, path)| { -659 *id != path_id && !self.abandoned_paths.contains(id) && path.data.validated -660 }) -661 .not() -662 { -663 return Err(ClosePathError::LastOpenPath); -664 } -665 -666 // Send PATH_ABANDON -667 self.spaces[SpaceId::Data] -668 .pending -669 .path_abandon -670 .insert(path_id, error_code.into()); -671 -672 // Remove pending NEW CIDs for this path -673 let pending_space = &mut self.spaces[SpaceId::Data].pending; -674 pending_space.new_cids.retain(|cid| cid.path_id != path_id); -675 pending_space.path_cids_blocked.retain(|&id| id != path_id); -676 pending_space.path_status.retain(|&id| id != path_id); -677 -678 // Cleanup retransmits across ALL paths (CIDs for path_id may have been transmitted on other paths) -679 for space in self.spaces[SpaceId::Data].iter_paths_mut() { -680 for sent_packet in space.sent_packets.values_mut() { -681 if let Some(retransmits) = sent_packet.retransmits.get_mut() { -682 retransmits.new_cids.retain(|cid| cid.path_id != path_id); -683 retransmits.path_cids_blocked.retain(|&id| id != path_id); -684 retransmits.path_status.retain(|&id| id != path_id); -685 } -686 } -687 } -688 -689 // Consider remotely issued CIDs as retired. -690 // Technically we don't have to do this just yet. We only need to do this *after* -691 // the ABANDON_PATH frame is sent, allowing us to still send it on the -692 // to-be-abandoned path. However it is recommended to send it on another path, and -693 // we do not allow abandoning the last path anyway. -694 self.rem_cids.remove(&path_id); -695 self.endpoint_events -696 .push_back(EndpointEventInner::RetireResetToken(path_id)); -697 -698 let pto = self.pto_max_path(SpaceId::Data, false); -699 -700 let path = self.paths.get_mut(&path_id).expect("checked above"); -701 -702 // We record the time after which receiving data on this path generates a transport error. -703 path.data.last_allowed_receive = Some(now + 3 * pto); -704 self.abandoned_paths.insert(path_id); -705 -706 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8)); -707 -708 // The peer MUST respond with a corresponding PATH_ABANDON frame. -709 // If we receive packets on the abandoned path after 3 * PTO we trigger a transport error. -710 // In any case, we completely discard the path after 6 * PTO whether we receive a -711 // PATH_ABANDON or not. -712 self.timers.set( -713 Timer::PerPath(path_id, PathTimer::DiscardPath), -714 now + 6 * pto, -715 self.qlog.with_time(now), -716 ); -717 Ok(()) -718 } -719 -720 /// Gets the [`PathData`] for a known [`PathId`]. -721 /// -722 /// Will panic if the path_id does not reference any known path. -723 #[track_caller] -724 fn path_data(&self, path_id: PathId) -> &PathData { -725 if let Some(data) = self.paths.get(&path_id) { -726 &data.data -727 } else { -728 panic!( -729 "unknown path: {path_id}, currently known paths: {:?}", -730 self.paths.keys().collect::<Vec<_>>() -731 ); -732 } -733 } -734 -735 /// Gets a reference to the [`PathData`] for a [`PathId`] -736 fn path(&self, path_id: PathId) -> Option<&PathData> { -737 self.paths.get(&path_id).map(|path_state| &path_state.data) -738 } -739 -740 /// Gets a mutable reference to the [`PathData`] for a [`PathId`] -741 fn path_mut(&mut self, path_id: PathId) -> Option<&mut PathData> { -742 self.paths -743 .get_mut(&path_id) -744 .map(|path_state| &mut path_state.data) +630 if self.rem_cids.get(&path_id).map(CidQueue::active).is_none() { +631 self.spaces[SpaceId::Data] +632 .pending +633 .path_cids_blocked +634 .insert(path_id); +635 return Err(PathError::RemoteCidsExhausted); +636 } +637 +638 let path = self.ensure_path(path_id, network_path, now, None); +639 path.status.local_update(initial_status); +640 +641 Ok(path_id) +642 } +643 +644 /// Closes a path by sending a PATH_ABANDON frame +645 /// +646 /// This will not allow closing the last path. It does allow closing paths which have +647 /// not yet been opened, as e.g. is the case when receiving a PATH_ABANDON from the peer +648 /// for a path that was never opened locally. +649 pub fn close_path( +650 &mut self, +651 now: Instant, +652 path_id: PathId, +653 error_code: VarInt, +654 ) -> Result<(), ClosePathError> { +655 if self.abandoned_paths.contains(&path_id) +656 || Some(path_id) > self.max_path_id() +657 || !self.paths.contains_key(&path_id) +658 { +659 return Err(ClosePathError::ClosedPath); +660 } +661 if self +662 .paths +663 .iter() +664 // Would there be any remaining, non-abandoned, validated paths +665 .any(|(id, path)| { +666 *id != path_id && !self.abandoned_paths.contains(id) && path.data.validated +667 }) +668 .not() +669 { +670 return Err(ClosePathError::LastOpenPath); +671 } +672 +673 // Send PATH_ABANDON +674 self.spaces[SpaceId::Data] +675 .pending +676 .path_abandon +677 .insert(path_id, error_code.into()); +678 +679 // Remove pending NEW CIDs for this path +680 let pending_space = &mut self.spaces[SpaceId::Data].pending; +681 pending_space.new_cids.retain(|cid| cid.path_id != path_id); +682 pending_space.path_cids_blocked.retain(|&id| id != path_id); +683 pending_space.path_status.retain(|&id| id != path_id); +684 +685 // Cleanup retransmits across ALL paths (CIDs for path_id may have been transmitted on other paths) +686 for space in self.spaces[SpaceId::Data].iter_paths_mut() { +687 for sent_packet in space.sent_packets.values_mut() { +688 if let Some(retransmits) = sent_packet.retransmits.get_mut() { +689 retransmits.new_cids.retain(|cid| cid.path_id != path_id); +690 retransmits.path_cids_blocked.retain(|&id| id != path_id); +691 retransmits.path_status.retain(|&id| id != path_id); +692 } +693 } +694 } +695 +696 // Consider remotely issued CIDs as retired. +697 // Technically we don't have to do this just yet. We only need to do this *after* +698 // the ABANDON_PATH frame is sent, allowing us to still send it on the +699 // to-be-abandoned path. However it is recommended to send it on another path, and +700 // we do not allow abandoning the last path anyway. +701 self.rem_cids.remove(&path_id); +702 self.endpoint_events +703 .push_back(EndpointEventInner::RetireResetToken(path_id)); +704 +705 let pto = self.pto_max_path(SpaceId::Data, false); +706 +707 let path = self.paths.get_mut(&path_id).expect("checked above"); +708 +709 // We record the time after which receiving data on this path generates a transport error. +710 path.data.last_allowed_receive = Some(now + 3 * pto); +711 self.abandoned_paths.insert(path_id); +712 +713 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8)); +714 +715 // The peer MUST respond with a corresponding PATH_ABANDON frame. +716 // If we receive packets on the abandoned path after 3 * PTO we trigger a transport error. +717 // In any case, we completely discard the path after 6 * PTO whether we receive a +718 // PATH_ABANDON or not. +719 self.timers.set( +720 Timer::PerPath(path_id, PathTimer::DiscardPath), +721 now + 6 * pto, +722 self.qlog.with_time(now), +723 ); +724 Ok(()) +725 } +726 +727 /// Gets the [`PathData`] for a known [`PathId`]. +728 /// +729 /// Will panic if the path_id does not reference any known path. +730 #[track_caller] +731 fn path_data(&self, path_id: PathId) -> &PathData { +732 if let Some(data) = self.paths.get(&path_id) { +733 &data.data +734 } else { +735 panic!( +736 "unknown path: {path_id}, currently known paths: {:?}", +737 self.paths.keys().collect::<Vec<_>>() +738 ); +739 } +740 } +741 +742 /// Gets a reference to the [`PathData`] for a [`PathId`] +743 fn path(&self, path_id: PathId) -> Option<&PathData> { +744 self.paths.get(&path_id).map(|path_state| &path_state.data) 745 } 746 -747 /// Returns all known paths. -748 /// -749 /// There is no guarantee any of these paths are open or usable. -750 pub fn paths(&self) -> Vec<PathId> { -751 self.paths.keys().copied().collect() +747 /// Gets a mutable reference to the [`PathData`] for a [`PathId`] +748 fn path_mut(&mut self, path_id: PathId) -> Option<&mut PathData> { +749 self.paths +750 .get_mut(&path_id) +751 .map(|path_state| &mut path_state.data) 752 } 753 -754 /// Gets the local [`PathStatus`] for a known [`PathId`] -755 pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath> { -756 self.path(path_id) -757 .map(PathData::local_status) -758 .ok_or(ClosedPath { _private: () }) +754 /// Returns all known paths. +755 /// +756 /// There is no guarantee any of these paths are open or usable. +757 pub fn paths(&self) -> Vec<PathId> { +758 self.paths.keys().copied().collect() 759 } 760 -761 /// Returns the path's network path represented as a 4-tuple. -762 pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath> { +761 /// Gets the local [`PathStatus`] for a known [`PathId`] +762 pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath> { 763 self.path(path_id) -764 .map(|path| path.network_path) +764 .map(PathData::local_status) 765 .ok_or(ClosedPath { _private: () }) 766 } 767 -768 /// Sets the [`PathStatus`] for a known [`PathId`] -769 /// -770 /// Returns the previous path status on success. -771 pub fn set_path_status( -772 &mut self, -773 path_id: PathId, -774 status: PathStatus, -775 ) -> Result<PathStatus, SetPathStatusError> { -776 if !self.is_multipath_negotiated() { -777 return Err(SetPathStatusError::MultipathNotNegotiated); -778 } -779 let path = self -780 .path_mut(path_id) -781 .ok_or(SetPathStatusError::ClosedPath)?; -782 let prev = match path.status.local_update(status) { -783 Some(prev) => { -784 self.spaces[SpaceId::Data] -785 .pending -786 .path_status -787 .insert(path_id); -788 prev -789 } -790 None => path.local_status(), -791 }; -792 Ok(prev) -793 } -794 -795 /// Returns the remote path status -796 // TODO(flub): Probably should also be some kind of path event? Not even sure if I like -797 // this as an API, but for now it allows me to write a test easily. -798 // TODO(flub): Technically this should be a Result<Option<PathSTatus>>? -799 pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus> { -800 self.path(path_id).and_then(|path| path.remote_status()) -801 } -802 -803 /// Sets the max_idle_timeout for a specific path -804 /// -805 /// See [`TransportConfig::default_path_max_idle_timeout`] for details. -806 /// -807 /// Returns the previous value of the setting. -808 pub fn set_path_max_idle_timeout( -809 &mut self, -810 path_id: PathId, -811 timeout: Option<Duration>, -812 ) -> Result<Option<Duration>, ClosedPath> { -813 let path = self -814 .paths -815 .get_mut(&path_id) -816 .ok_or(ClosedPath { _private: () })?; -817 Ok(std::mem::replace(&mut path.data.idle_timeout, timeout)) -818 } -819 -820 /// Sets the keep_alive_interval for a specific path -821 /// -822 /// See [`TransportConfig::default_path_keep_alive_interval`] for details. -823 /// -824 /// Returns the previous value of the setting. -825 pub fn set_path_keep_alive_interval( -826 &mut self, -827 path_id: PathId, -828 interval: Option<Duration>, -829 ) -> Result<Option<Duration>, ClosedPath> { -830 let path = self -831 .paths -832 .get_mut(&path_id) -833 .ok_or(ClosedPath { _private: () })?; -834 Ok(std::mem::replace(&mut path.data.keep_alive, interval)) -835 } -836 -837 /// Gets the [`PathData`] for a known [`PathId`]. -838 /// -839 /// Will panic if the path_id does not reference any known path. -840 #[track_caller] -841 fn path_data_mut(&mut self, path_id: PathId) -> &mut PathData { -842 &mut self.paths.get_mut(&path_id).expect("known path").data -843 } -844 -845 /// Find an open, validated path that's on the same network path as the given network path. -846 /// -847 /// Returns the first path matching, even if there's multiple. -848 fn find_validated_path_on_network_path( -849 &self, -850 network_path: FourTuple, -851 ) -> Option<(&PathId, &PathState)> { -852 self.paths.iter().find(|(path_id, path_state)| { -853 path_state.data.validated -854 // Would this use the same network path, if network_path were used to send right now? -855 && network_path.is_probably_same_path(&path_state.data.network_path) -856 && !self.abandoned_paths.contains(path_id) -857 }) -858 // TODO(@divma): we might want to ensure the path has been recently active to consider the -859 // address validated -860 // matheus23: Perhaps looking at !self.abandoned_paths.contains(path_id) is enough, given keep-alives? -861 } -862 -863 fn ensure_path( -864 &mut self, -865 path_id: PathId, -866 network_path: FourTuple, -867 now: Instant, -868 pn: Option<u64>, -869 ) -> &mut PathData { -870 let valid_path = self.find_validated_path_on_network_path(network_path); -871 let validated = valid_path.is_some(); -872 let initial_rtt = valid_path.map(|(_, path)| path.data.rtt.conservative()); -873 let vacant_entry = match self.paths.entry(path_id) { -874 btree_map::Entry::Vacant(vacant_entry) => vacant_entry, -875 btree_map::Entry::Occupied(occupied_entry) => { -876 return &mut occupied_entry.into_mut().data; -877 } -878 }; -879 -880 debug!(%validated, %path_id, %network_path, "path added"); -881 let peer_max_udp_payload_size = -882 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); -883 self.path_counter = self.path_counter.wrapping_add(1); -884 let mut data = PathData::new( -885 network_path, -886 self.allow_mtud, -887 Some(peer_max_udp_payload_size), -888 self.path_counter, -889 now, -890 &self.config, -891 ); -892 -893 data.validated = validated; -894 if let Some(initial_rtt) = initial_rtt { -895 data.rtt.reset_initial_rtt(initial_rtt); -896 } -897 -898 let pto = self.ack_frequency.max_ack_delay_for_pto() + data.rtt.pto_base(); -899 self.timers.set( -900 Timer::PerPath(path_id, PathTimer::PathOpen), -901 now + 3 * pto, -902 self.qlog.with_time(now), -903 ); +768 /// Returns the path's network path represented as a 4-tuple. +769 pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath> { +770 self.path(path_id) +771 .map(|path| path.network_path) +772 .ok_or(ClosedPath { _private: () }) +773 } +774 +775 /// Sets the [`PathStatus`] for a known [`PathId`] +776 /// +777 /// Returns the previous path status on success. +778 pub fn set_path_status( +779 &mut self, +780 path_id: PathId, +781 status: PathStatus, +782 ) -> Result<PathStatus, SetPathStatusError> { +783 if !self.is_multipath_negotiated() { +784 return Err(SetPathStatusError::MultipathNotNegotiated); +785 } +786 let path = self +787 .path_mut(path_id) +788 .ok_or(SetPathStatusError::ClosedPath)?; +789 let prev = match path.status.local_update(status) { +790 Some(prev) => { +791 self.spaces[SpaceId::Data] +792 .pending +793 .path_status +794 .insert(path_id); +795 prev +796 } +797 None => path.local_status(), +798 }; +799 Ok(prev) +800 } +801 +802 /// Returns the remote path status +803 // TODO(flub): Probably should also be some kind of path event? Not even sure if I like +804 // this as an API, but for now it allows me to write a test easily. +805 // TODO(flub): Technically this should be a Result<Option<PathSTatus>>? +806 pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus> { +807 self.path(path_id).and_then(|path| path.remote_status()) +808 } +809 +810 /// Sets the max_idle_timeout for a specific path +811 /// +812 /// See [`TransportConfig::default_path_max_idle_timeout`] for details. +813 /// +814 /// Returns the previous value of the setting. +815 pub fn set_path_max_idle_timeout( +816 &mut self, +817 path_id: PathId, +818 timeout: Option<Duration>, +819 ) -> Result<Option<Duration>, ClosedPath> { +820 let path = self +821 .paths +822 .get_mut(&path_id) +823 .ok_or(ClosedPath { _private: () })?; +824 Ok(std::mem::replace(&mut path.data.idle_timeout, timeout)) +825 } +826 +827 /// Sets the keep_alive_interval for a specific path +828 /// +829 /// See [`TransportConfig::default_path_keep_alive_interval`] for details. +830 /// +831 /// Returns the previous value of the setting. +832 pub fn set_path_keep_alive_interval( +833 &mut self, +834 path_id: PathId, +835 interval: Option<Duration>, +836 ) -> Result<Option<Duration>, ClosedPath> { +837 let path = self +838 .paths +839 .get_mut(&path_id) +840 .ok_or(ClosedPath { _private: () })?; +841 Ok(std::mem::replace(&mut path.data.keep_alive, interval)) +842 } +843 +844 /// Gets the [`PathData`] for a known [`PathId`]. +845 /// +846 /// Will panic if the path_id does not reference any known path. +847 #[track_caller] +848 fn path_data_mut(&mut self, path_id: PathId) -> &mut PathData { +849 &mut self.paths.get_mut(&path_id).expect("known path").data +850 } +851 +852 /// Find an open, validated path that's on the same network path as the given network path. +853 /// +854 /// Returns the first path matching, even if there's multiple. +855 fn find_validated_path_on_network_path( +856 &self, +857 network_path: FourTuple, +858 ) -> Option<(&PathId, &PathState)> { +859 self.paths.iter().find(|(path_id, path_state)| { +860 path_state.data.validated +861 // Would this use the same network path, if network_path were used to send right now? +862 && network_path.is_probably_same_path(&path_state.data.network_path) +863 && !self.abandoned_paths.contains(path_id) +864 }) +865 // TODO(@divma): we might want to ensure the path has been recently active to consider the +866 // address validated +867 // matheus23: Perhaps looking at !self.abandoned_paths.contains(path_id) is enough, given keep-alives? +868 } +869 +870 fn ensure_path( +871 &mut self, +872 path_id: PathId, +873 network_path: FourTuple, +874 now: Instant, +875 pn: Option<u64>, +876 ) -> &mut PathData { +877 let valid_path = self.find_validated_path_on_network_path(network_path); +878 let validated = valid_path.is_some(); +879 let initial_rtt = valid_path.map(|(_, path)| path.data.rtt.conservative()); +880 let vacant_entry = match self.paths.entry(path_id) { +881 btree_map::Entry::Vacant(vacant_entry) => vacant_entry, +882 btree_map::Entry::Occupied(occupied_entry) => { +883 return &mut occupied_entry.into_mut().data; +884 } +885 }; +886 +887 debug!(%validated, %path_id, %network_path, "path added"); +888 let peer_max_udp_payload_size = +889 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); +890 self.path_generation_counter = self.path_generation_counter.wrapping_add(1); +891 let mut data = PathData::new( +892 network_path, +893 self.allow_mtud, +894 Some(peer_max_udp_payload_size), +895 self.path_generation_counter, +896 now, +897 &self.config, +898 ); +899 +900 data.validated = validated; +901 if let Some(initial_rtt) = initial_rtt { +902 data.rtt.reset_initial_rtt(initial_rtt); +903 } 904 -905 // for the path to be opened we need to send a packet on the path. Sending a challenge -906 // guarantees this -907 data.send_new_challenge = true; -908 -909 let path = vacant_entry.insert(PathState { data, prev: None }); -910 -911 let mut pn_space = spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng); -912 if let Some(pn) = pn { -913 pn_space.dedup.insert(pn); -914 } -915 self.spaces[SpaceId::Data] -916 .number_spaces -917 .insert(path_id, pn_space); -918 self.qlog.emit_tuple_assigned(path_id, network_path, now); -919 &mut path.data -920 } -921 -922 /// Returns packets to transmit -923 /// -924 /// Connections should be polled for transmit after: -925 /// - the application performed some I/O on the connection -926 /// - a call was made to `handle_event` -927 /// - a call was made to `handle_timeout` -928 /// -929 /// `max_datagrams` specifies how many datagrams can be returned inside a -930 /// single Transmit using GSO. This must be at least 1. -931 #[must_use] -932 pub fn poll_transmit( -933 &mut self, -934 now: Instant, -935 max_datagrams: NonZeroUsize, -936 buf: &mut Vec<u8>, -937 ) -> Option<Transmit> { -938 if let Some(probing) = self -939 .iroh_hp -940 .server_side_mut() -941 .ok() -942 .and_then(iroh_hp::ServerState::next_probe) -943 { -944 let destination = probing.remote(); -945 trace!(%destination, "RAND_DATA packet"); -946 let token: u64 = self.rng.random(); -947 buf.put_u64(token); -948 probing.finish(token); -949 return Some(Transmit { -950 destination, -951 ecn: None, -952 size: 8, -953 segment_size: None, -954 src_ip: None, -955 }); -956 } -957 -958 let max_datagrams = match self.config.enable_segmentation_offload { -959 false => NonZeroUsize::MIN, -960 true => max_datagrams, -961 }; -962 -963 // Each call to poll_transmit can only send datagrams to one destination, because -964 // all datagrams in a GSO batch are for the same destination. Therefore only -965 // datagrams for one Path ID are produced for each poll_transmit call. -966 -967 // TODO(flub): this is wishful thinking and not actually implemented, but perhaps it -968 // should be: +905 let pto = self.ack_frequency.max_ack_delay_for_pto() + data.rtt.pto_base(); +906 self.timers.set( +907 Timer::PerPath(path_id, PathTimer::PathOpen), +908 now + 3 * pto, +909 self.qlog.with_time(now), +910 ); +911 +912 // for the path to be opened we need to send a packet on the path. Sending a challenge +913 // guarantees this +914 data.send_new_challenge = true; +915 +916 let path = vacant_entry.insert(PathState { data, prev: None }); +917 +918 let mut pn_space = spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng); +919 if let Some(pn) = pn { +920 pn_space.dedup.insert(pn); +921 } +922 self.spaces[SpaceId::Data] +923 .number_spaces +924 .insert(path_id, pn_space); +925 self.qlog.emit_tuple_assigned(path_id, network_path, now); +926 &mut path.data +927 } +928 +929 /// Returns packets to transmit +930 /// +931 /// Connections should be polled for transmit after: +932 /// - the application performed some I/O on the connection +933 /// - a call was made to `handle_event` +934 /// - a call was made to `handle_timeout` +935 /// +936 /// `max_datagrams` specifies how many datagrams can be returned inside a +937 /// single Transmit using GSO. This must be at least 1. +938 #[must_use] +939 pub fn poll_transmit( +940 &mut self, +941 now: Instant, +942 max_datagrams: NonZeroUsize, +943 buf: &mut Vec<u8>, +944 ) -> Option<Transmit> { +945 if let Some(probing) = self +946 .iroh_hp +947 .server_side_mut() +948 .ok() +949 .and_then(iroh_hp::ServerState::next_probe) +950 { +951 let destination = probing.remote(); +952 trace!(%destination, "RAND_DATA packet"); +953 let token: u64 = self.rng.random(); +954 buf.put_u64(token); +955 probing.finish(token); +956 return Some(Transmit { +957 destination, +958 ecn: None, +959 size: 8, +960 segment_size: None, +961 src_ip: None, +962 }); +963 } +964 +965 let max_datagrams = match self.config.enable_segmentation_offload { +966 false => NonZeroUsize::MIN, +967 true => max_datagrams, +968 }; 969 -970 // First, if we have to send a close, select a path for that. -971 // Next, all paths that have a PATH_CHALLENGE or PATH_RESPONSE pending. -972 -973 // For all, open, validated and AVAILABLE paths: -974 // - Is the path congestion blocked or pacing blocked? -975 // - call maybe_queue_ to ensure a tail-loss probe would be sent? -976 // - do we need to send a close message? -977 // - call can_send -978 // Once there's nothing more to send on the AVAILABLE paths, do the same for BACKUP paths +970 // Each call to poll_transmit can only send datagrams to one destination, because +971 // all datagrams in a GSO batch are for the same destination. Therefore only +972 // datagrams for one Path ID are produced for each poll_transmit call. +973 +974 // TODO(flub): this is wishful thinking and not actually implemented, but perhaps it +975 // should be: +976 +977 // First, if we have to send a close, select a path for that. +978 // Next, all paths that have a PATH_CHALLENGE or PATH_RESPONSE pending. 979 -980 // Check whether we need to send a close message -981 let close = match self.state.as_type() { -982 StateType::Drained => { -983 self.app_limited = true; -984 return None; -985 } -986 StateType::Draining | StateType::Closed => { -987 // self.close is only reset once the associated packet had been -988 // encoded successfully -989 if !self.close { -990 self.app_limited = true; -991 return None; -992 } -993 true -994 } -995 _ => false, -996 }; -997 -998 // Check whether we need to send an ACK_FREQUENCY frame -999 if let Some(config) = &self.config.ack_frequency_config { -1000 let rtt = self -1001 .paths -1002 .values() -1003 .map(|p| p.data.rtt.get()) -1004 .min() -1005 .expect("one path exists"); -1006 self.spaces[SpaceId::Data].pending.ack_frequency = self -1007 .ack_frequency -1008 .should_send_ack_frequency(rtt, config, &self.peer_params) -1009 && self.highest_space == SpaceId::Data -1010 && self.peer_supports_ack_frequency(); -1011 } -1012 -1013 // If there is any open, validated and available path we only want to send frames to -1014 // any backup path that must be sent on that backup path exclusively. -1015 let have_available_path = self.paths.iter().any(|(id, path)| { -1016 path.data.validated -1017 && path.data.local_status() == PathStatus::Available -1018 && self.rem_cids.contains_key(id) -1019 }); -1020 -1021 // TODO: how to avoid the allocation? Cannot use a for loop because of borrowing -1022 let path_ids: Vec<_> = self.paths.keys().copied().collect(); -1023 -1024 let mut transmit = TransmitBuf::new( -1025 buf, -1026 max_datagrams, -1027 self.path_data(path_ids[0]).current_mtu().into(), -1028 ); -1029 -1030 let mut congestion_blocked = false; -1031 -1032 for &path_id in &path_ids { -1033 // Update per path state -1034 transmit.set_segment_size(self.path_data(path_id).current_mtu().into()); -1035 -1036 if let Some(challenge) = self.send_prev_path_challenge(now, &mut transmit, path_id) { -1037 return Some(challenge); -1038 } -1039 -1040 match self.poll_transmit_path(now, &mut transmit, path_id, have_available_path, close) { -1041 PollPathStatus::SendTransmit { transmit } => { -1042 return Some(transmit); -1043 } -1044 PollPathStatus::Send => { -1045 let transmit = self.build_transmit(path_id, transmit); -1046 return Some(transmit); -1047 } -1048 PollPathStatus::NothingToSend { -1049 congestion_blocked: cb, -1050 } => { -1051 // TODO: congestion blocked should be per path? how to deal with this better -1052 -1053 // move to next path -1054 if cb { -1055 // note congestion block -1056 congestion_blocked = true; -1057 } -1058 } -1059 } -1060 // Nothing more to send. -1061 trace!(%path_id, "nothing to send on path"); -1062 } -1063 -1064 // We didn't produce any application data packet -1065 debug_assert!( -1066 transmit.is_empty(), -1067 "there was data in the transmit, but it was not sent" -1068 ); -1069 self.app_limited = !congestion_blocked; +980 // For all, open, validated and AVAILABLE paths: +981 // - Is the path congestion blocked or pacing blocked? +982 // - call maybe_queue_ to ensure a tail-loss probe would be sent? +983 // - do we need to send a close message? +984 // - call can_send +985 // Once there's nothing more to send on the AVAILABLE paths, do the same for BACKUP paths +986 +987 // Check whether we need to send a close message +988 let close = match self.state.as_type() { +989 StateType::Drained => { +990 self.app_limited = true; +991 return None; +992 } +993 StateType::Draining | StateType::Closed => { +994 // self.close is only reset once the associated packet had been +995 // encoded successfully +996 if !self.close { +997 self.app_limited = true; +998 return None; +999 } +1000 true +1001 } +1002 _ => false, +1003 }; +1004 +1005 // Check whether we need to send an ACK_FREQUENCY frame +1006 if let Some(config) = &self.config.ack_frequency_config { +1007 let rtt = self +1008 .paths +1009 .values() +1010 .map(|p| p.data.rtt.get()) +1011 .min() +1012 .expect("one path exists"); +1013 self.spaces[SpaceId::Data].pending.ack_frequency = self +1014 .ack_frequency +1015 .should_send_ack_frequency(rtt, config, &self.peer_params) +1016 && self.highest_space == SpaceId::Data +1017 && self.peer_supports_ack_frequency(); +1018 } +1019 +1020 // If there is any open, validated and available path we only want to send frames to +1021 // any backup path that must be sent on that backup path exclusively. +1022 let have_available_path = self.paths.iter().any(|(id, path)| { +1023 path.data.validated +1024 && path.data.local_status() == PathStatus::Available +1025 && self.rem_cids.contains_key(id) +1026 }); +1027 +1028 // TODO: how to avoid the allocation? Cannot use a for loop because of borrowing +1029 let path_ids: Vec<_> = self.paths.keys().copied().collect(); +1030 +1031 let mut transmit = TransmitBuf::new( +1032 buf, +1033 max_datagrams, +1034 self.path_data(path_ids[0]).current_mtu().into(), +1035 ); +1036 +1037 let mut congestion_blocked = false; +1038 +1039 for &path_id in &path_ids { +1040 // Update per path state +1041 transmit.set_segment_size(self.path_data(path_id).current_mtu().into()); +1042 +1043 if let Some(challenge) = self.send_prev_path_challenge(now, &mut transmit, path_id) { +1044 return Some(challenge); +1045 } +1046 +1047 match self.poll_transmit_path(now, &mut transmit, path_id, have_available_path, close) { +1048 PollPathStatus::SendTransmit { transmit } => { +1049 return Some(transmit); +1050 } +1051 PollPathStatus::Send => { +1052 let transmit = self.build_transmit(path_id, transmit); +1053 return Some(transmit); +1054 } +1055 PollPathStatus::NothingToSend { +1056 congestion_blocked: cb, +1057 } => { +1058 // TODO: congestion blocked should be per path? how to deal with this better +1059 +1060 // move to next path +1061 if cb { +1062 // note congestion block +1063 congestion_blocked = true; +1064 } +1065 } +1066 } +1067 // Nothing more to send. +1068 trace!(%path_id, "nothing to send on path"); +1069 } 1070 -1071 if self.state.is_established() { -1072 // Try MTU probing now -1073 for path_id in path_ids { -1074 // Update per path state -1075 transmit.set_segment_size(self.path_data(path_id).current_mtu().into()); -1076 self.poll_transmit_mtu_probe(now, &mut transmit, path_id); -1077 if !transmit.is_empty() { -1078 let transmit = self.build_transmit(path_id, transmit); -1079 return Some(transmit); -1080 } -1081 } -1082 } -1083 -1084 None -1085 } -1086 -1087 fn build_transmit(&mut self, path_id: PathId, transmit: TransmitBuf<'_>) -> Transmit { -1088 debug_assert!( -1089 !transmit.is_empty(), -1090 "must not be called with an empty transmit buffer" -1091 ); -1092 -1093 let network_path = self.path_data(path_id).network_path; -1094 trace!( -1095 segment_size = transmit.segment_size(), -1096 last_datagram_len = transmit.len() % transmit.segment_size(), -1097 %network_path, -1098 "sending {} bytes in {} datagrams", -1099 transmit.len(), -1100 transmit.num_datagrams() -1101 ); -1102 self.path_data_mut(path_id) -1103 .inc_total_sent(transmit.len() as u64); -1104 -1105 self.stats -1106 .udp_tx -1107 .on_sent(transmit.num_datagrams() as u64, transmit.len()); -1108 -1109 Transmit { -1110 destination: network_path.remote, -1111 size: transmit.len(), -1112 ecn: if self.path_data(path_id).sending_ecn { -1113 Some(EcnCodepoint::Ect0) -1114 } else { -1115 None -1116 }, -1117 segment_size: match transmit.num_datagrams() { -1118 1 => None, -1119 _ => Some(transmit.segment_size()), -1120 }, -1121 src_ip: network_path.local_ip, -1122 } -1123 } -1124 -1125 /// poll_transmit logic for a specific path -1126 #[must_use] -1127 fn poll_transmit_path( -1128 &mut self, -1129 now: Instant, -1130 transmit: &mut TransmitBuf<'_>, -1131 path_id: PathId, -1132 have_available_path: bool, -1133 close: bool, -1134 ) -> PollPathStatus { -1135 // Check if there is at least one active CID to use for sending -1136 let Some(remote_cid) = self.rem_cids.get(&path_id).map(CidQueue::active) else { -1137 self.on_remote_cids_exhausted(now, path_id); -1138 -1139 return PollPathStatus::NothingToSend { -1140 congestion_blocked: false, -1141 }; -1142 }; -1143 -1144 // Whether this packet can be coalesced with another one in the same datagram. -1145 let mut coalesce = true; -1146 -1147 // Whether the last packet in the datagram must be padded so the datagram takes up -1148 // to at least MIN_INITIAL_SIZE, or to the maximum segment size if this is smaller. -1149 let mut pad_datagram = PadDatagram::No; +1071 // We didn't produce any application data packet +1072 debug_assert!( +1073 transmit.is_empty(), +1074 "there was data in the transmit, but it was not sent" +1075 ); +1076 self.app_limited = !congestion_blocked; +1077 +1078 if self.state.is_established() { +1079 // Try MTU probing now +1080 for path_id in path_ids { +1081 // Update per path state +1082 transmit.set_segment_size(self.path_data(path_id).current_mtu().into()); +1083 self.poll_transmit_mtu_probe(now, &mut transmit, path_id); +1084 if !transmit.is_empty() { +1085 let transmit = self.build_transmit(path_id, transmit); +1086 return Some(transmit); +1087 } +1088 } +1089 } +1090 +1091 None +1092 } +1093 +1094 fn build_transmit(&mut self, path_id: PathId, transmit: TransmitBuf<'_>) -> Transmit { +1095 debug_assert!( +1096 !transmit.is_empty(), +1097 "must not be called with an empty transmit buffer" +1098 ); +1099 +1100 let network_path = self.path_data(path_id).network_path; +1101 trace!( +1102 segment_size = transmit.segment_size(), +1103 last_datagram_len = transmit.len() % transmit.segment_size(), +1104 %network_path, +1105 "sending {} bytes in {} datagrams", +1106 transmit.len(), +1107 transmit.num_datagrams() +1108 ); +1109 self.path_data_mut(path_id) +1110 .inc_total_sent(transmit.len() as u64); +1111 +1112 self.stats +1113 .udp_tx +1114 .on_sent(transmit.num_datagrams() as u64, transmit.len()); +1115 +1116 Transmit { +1117 destination: network_path.remote, +1118 size: transmit.len(), +1119 ecn: if self.path_data(path_id).sending_ecn { +1120 Some(EcnCodepoint::Ect0) +1121 } else { +1122 None +1123 }, +1124 segment_size: match transmit.num_datagrams() { +1125 1 => None, +1126 _ => Some(transmit.segment_size()), +1127 }, +1128 src_ip: network_path.local_ip, +1129 } +1130 } +1131 +1132 /// poll_transmit logic for a specific path +1133 #[must_use] +1134 fn poll_transmit_path( +1135 &mut self, +1136 now: Instant, +1137 transmit: &mut TransmitBuf<'_>, +1138 path_id: PathId, +1139 have_available_path: bool, +1140 close: bool, +1141 ) -> PollPathStatus { +1142 // Check if there is at least one active CID to use for sending +1143 let Some(remote_cid) = self.rem_cids.get(&path_id).map(CidQueue::active) else { +1144 self.on_remote_cids_exhausted(now, path_id); +1145 +1146 return PollPathStatus::NothingToSend { +1147 congestion_blocked: false, +1148 }; +1149 }; 1150 -1151 // The packet number of the last built packet. -1152 let mut last_packet_number = None; +1151 // Whether this packet can be coalesced with another one in the same datagram. +1152 let mut coalesce = true; 1153 -1154 // Iterate over the available spaces -1155 for space_id in SpaceId::iter() { -1156 // Only Path0 uses non Data space ids -1157 if path_id != PathId::ZERO && space_id != SpaceId::Data { -1158 continue; -1159 } +1154 // Whether the last packet in the datagram must be padded so the datagram takes up +1155 // to at least MIN_INITIAL_SIZE, or to the maximum segment size if this is smaller. +1156 let mut pad_datagram = PadDatagram::No; +1157 +1158 // The packet number of the last built packet. +1159 let mut last_packet_number = None; 1160 -1161 let res = self.poll_transmit_path_space( -1162 now, -1163 transmit, -1164 path_id, -1165 space_id, -1166 remote_cid, -1167 have_available_path, -1168 close, -1169 &mut coalesce, -1170 &mut pad_datagram, -1171 ); -1172 match res { -1173 PollPathSpaceStatus::Send { -1174 last_packet_number: lp, -1175 } => { -1176 last_packet_number = lp; -1177 break; -1178 } -1179 PollPathSpaceStatus::SendTransmit { transmit } => { -1180 return PollPathStatus::SendTransmit { transmit }; -1181 } -1182 PollPathSpaceStatus::NothingToSend { congestion_blocked } => { -1183 return PollPathStatus::NothingToSend { congestion_blocked }; -1184 } -1185 PollPathSpaceStatus::NextSpace => { -1186 // moving onto the next space -1187 } -1188 } -1189 } -1190 -1191 if let Some(last_packet_number) = last_packet_number { -1192 // Note that when sending in multiple packet spaces the last packet number will -1193 // be the one from the highest packet space. -1194 self.path_data_mut(path_id).congestion.on_sent( -1195 now, -1196 transmit.len() as u64, -1197 last_packet_number, -1198 ); -1199 } -1200 -1201 self.qlog.emit_recovery_metrics( -1202 path_id, -1203 &mut self.paths.get_mut(&path_id).unwrap().data, -1204 now, -1205 ); -1206 -1207 if transmit.is_empty() { -1208 PollPathStatus::NothingToSend { -1209 congestion_blocked: false, -1210 } -1211 } else { -1212 PollPathStatus::Send -1213 } -1214 } -1215 -1216 /// poll_transmit logic for a path_id - space_id combination -1217 #[must_use] -1218 fn poll_transmit_path_space( -1219 &mut self, -1220 now: Instant, -1221 transmit: &mut TransmitBuf<'_>, -1222 path_id: PathId, -1223 space_id: SpaceId, -1224 remote_cid: ConnectionId, -1225 have_available_path: bool, -1226 close: bool, -1227 coalesce: &mut bool, -1228 pad_datagram: &mut PadDatagram, -1229 ) -> PollPathSpaceStatus { -1230 let mut last_packet_number = None; -1231 -1232 loop { -1233 // Determine if anything can be sent in this packet number space (SpaceId + PathId). -1234 let max_packet_size = if transmit.datagram_remaining_mut() > 0 { -1235 // We are trying to coalesce another packet into this datagram. -1236 transmit.datagram_remaining_mut() -1237 } else { -1238 // A new datagram needs to be started. -1239 transmit.segment_size() -1240 }; -1241 -1242 let can_send = self.space_can_send(space_id, path_id, max_packet_size, close); -1243 -1244 let path_should_send = { -1245 let path_exclusive_only = space_id == SpaceId::Data -1246 && have_available_path -1247 && self.path_data(path_id).local_status() == PathStatus::Backup; -1248 let path_should_send = if path_exclusive_only { -1249 can_send.path_exclusive -1250 } else { -1251 !can_send.is_empty() -1252 }; -1253 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; -1254 path_should_send || needs_loss_probe -1255 }; -1256 -1257 if !path_should_send && space_id < SpaceId::Data { -1258 if self.spaces[space_id].crypto.is_some() { -1259 trace!(?space_id, %path_id, "nothing to send in space"); -1260 } -1261 return PollPathSpaceStatus::NextSpace; -1262 } +1161 // Iterate over the available spaces +1162 for space_id in SpaceId::iter() { +1163 // Only Path0 uses non Data space ids +1164 if path_id != PathId::ZERO && space_id != SpaceId::Data { +1165 continue; +1166 } +1167 +1168 let res = self.poll_transmit_path_space( +1169 now, +1170 transmit, +1171 path_id, +1172 space_id, +1173 remote_cid, +1174 have_available_path, +1175 close, +1176 &mut coalesce, +1177 &mut pad_datagram, +1178 ); +1179 match res { +1180 PollPathSpaceStatus::Send { +1181 last_packet_number: lp, +1182 } => { +1183 last_packet_number = lp; +1184 break; +1185 } +1186 PollPathSpaceStatus::SendTransmit { transmit } => { +1187 return PollPathStatus::SendTransmit { transmit }; +1188 } +1189 PollPathSpaceStatus::NothingToSend { congestion_blocked } => { +1190 return PollPathStatus::NothingToSend { congestion_blocked }; +1191 } +1192 PollPathSpaceStatus::NextSpace => { +1193 // moving onto the next space +1194 } +1195 } +1196 } +1197 +1198 if let Some(last_packet_number) = last_packet_number { +1199 // Note that when sending in multiple packet spaces the last packet number will +1200 // be the one from the highest packet space. +1201 self.path_data_mut(path_id).congestion.on_sent( +1202 now, +1203 transmit.len() as u64, +1204 last_packet_number, +1205 ); +1206 } +1207 +1208 self.qlog.emit_recovery_metrics( +1209 path_id, +1210 &mut self.paths.get_mut(&path_id).unwrap().data, +1211 now, +1212 ); +1213 +1214 if transmit.is_empty() { +1215 PollPathStatus::NothingToSend { +1216 congestion_blocked: false, +1217 } +1218 } else { +1219 PollPathStatus::Send +1220 } +1221 } +1222 +1223 /// poll_transmit logic for a path_id - space_id combination +1224 #[must_use] +1225 fn poll_transmit_path_space( +1226 &mut self, +1227 now: Instant, +1228 transmit: &mut TransmitBuf<'_>, +1229 path_id: PathId, +1230 space_id: SpaceId, +1231 remote_cid: ConnectionId, +1232 have_available_path: bool, +1233 close: bool, +1234 coalesce: &mut bool, +1235 pad_datagram: &mut PadDatagram, +1236 ) -> PollPathSpaceStatus { +1237 let mut last_packet_number = None; +1238 +1239 loop { +1240 // Determine if anything can be sent in this packet number space (SpaceId + PathId). +1241 let max_packet_size = if transmit.datagram_remaining_mut() > 0 { +1242 // We are trying to coalesce another packet into this datagram. +1243 transmit.datagram_remaining_mut() +1244 } else { +1245 // A new datagram needs to be started. +1246 transmit.segment_size() +1247 }; +1248 +1249 let can_send = self.space_can_send(space_id, path_id, max_packet_size, close); +1250 +1251 let path_should_send = { +1252 let path_exclusive_only = space_id == SpaceId::Data +1253 && have_available_path +1254 && self.path_data(path_id).local_status() == PathStatus::Backup; +1255 let path_should_send = if path_exclusive_only { +1256 can_send.path_exclusive +1257 } else { +1258 !can_send.is_empty() +1259 }; +1260 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; +1261 path_should_send || needs_loss_probe +1262 }; 1263 -1264 let send_blocked = if path_should_send && transmit.datagram_remaining_mut() == 0 { -1265 // Only check congestion control if a new datagram is needed. -1266 self.path_congestion_check(space_id, path_id, transmit, &can_send, now) -1267 } else { -1268 PathBlocked::No -1269 }; +1264 if !path_should_send && space_id < SpaceId::Data { +1265 if self.spaces[space_id].crypto.is_some() { +1266 trace!(?space_id, %path_id, "nothing to send in space"); +1267 } +1268 return PollPathSpaceStatus::NextSpace; +1269 } 1270 -1271 // Whether congestion control stopped the next packet from being sent. Further -1272 // packets could still be built, as e.g. tail-loss probes are not congestion -1273 // limited. -1274 let congestion_blocked = if send_blocked != PathBlocked::No { -1275 trace!(?space_id, %path_id, ?send_blocked, "congestion blocked"); -1276 true -1277 } else { -1278 false -1279 }; -1280 if send_blocked != PathBlocked::No && space_id < SpaceId::Data { -1281 // Higher spaces might still have tail-loss probes to send, which are not -1282 // congestion blocked. -1283 return PollPathSpaceStatus::NextSpace; -1284 } -1285 if !path_should_send || send_blocked != PathBlocked::No { -1286 // Nothing more to send on this path, check the next path if possible. -1287 -1288 // If there are any datagrams in the transmit, packets for another path can -1289 // not be built. -1290 if transmit.num_datagrams() > 0 { -1291 return PollPathSpaceStatus::Send { last_packet_number }; -1292 } -1293 -1294 return PollPathSpaceStatus::NothingToSend { congestion_blocked }; -1295 } -1296 -1297 if transmit.datagram_remaining_mut() == 0 { -1298 if transmit.num_datagrams() >= transmit.max_datagrams().get() { -1299 // No more datagrams allowed -1300 return PollPathSpaceStatus::Send { last_packet_number }; -1301 } -1302 -1303 match self.spaces[space_id].for_path(path_id).loss_probes { -1304 0 => transmit.start_new_datagram(), -1305 _ => { -1306 // We need something to send for a tail-loss probe. -1307 let request_immediate_ack = -1308 space_id == SpaceId::Data && self.peer_supports_ack_frequency(); -1309 self.spaces[space_id].maybe_queue_probe( -1310 path_id, -1311 request_immediate_ack, -1312 &self.streams, -1313 ); -1314 -1315 self.spaces[space_id].for_path(path_id).loss_probes -= 1; -1316 -1317 // Clamp the datagram to at most the minimum MTU to ensure that loss -1318 // probes can get through and enable recovery even if the path MTU -1319 // has shrank unexpectedly. -1320 transmit.start_new_datagram_with_size(std::cmp::min( -1321 usize::from(INITIAL_MTU), -1322 transmit.segment_size(), -1323 )); -1324 } -1325 } -1326 trace!(count = transmit.num_datagrams(), "new datagram started"); -1327 *coalesce = true; -1328 *pad_datagram = PadDatagram::No; -1329 } -1330 -1331 // If coalescing another packet into the existing datagram, there should -1332 // still be enough space for a whole packet. -1333 if transmit.datagram_start_offset() < transmit.len() { -1334 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE); -1335 } -1336 -1337 // -1338 // From here on, we've determined that a packet will definitely be sent. -1339 // -1340 -1341 if self.spaces[SpaceId::Initial].crypto.is_some() -1342 && space_id == SpaceId::Handshake -1343 && self.side.is_client() -1344 { -1345 // A client stops both sending and processing Initial packets when it -1346 // sends its first Handshake packet. -1347 self.discard_space(now, SpaceId::Initial); -1348 } -1349 if let Some(ref mut prev) = self.prev_crypto { -1350 prev.update_unacked = false; -1351 } -1352 -1353 let mut qlog = QlogSentPacket::default(); -1354 let Some(mut builder) = PacketBuilder::new( -1355 now, -1356 space_id, -1357 path_id, -1358 remote_cid, -1359 transmit, -1360 can_send.other, -1361 self, -1362 &mut qlog, -1363 ) else { -1364 return PollPathSpaceStatus::NothingToSend { congestion_blocked }; -1365 }; -1366 last_packet_number = Some(builder.exact_number); -1367 *coalesce = *coalesce && !builder.short_header; -1368 -1369 if space_id == SpaceId::Initial && (self.side.is_client() || can_send.other) { -1370 // https://www.rfc-editor.org/rfc/rfc9000.html#section-14.1 -1371 *pad_datagram |= PadDatagram::ToMinMtu; -1372 } -1373 if space_id == SpaceId::Data && self.config.pad_to_mtu { -1374 *pad_datagram |= PadDatagram::ToSegmentSize; -1375 } -1376 -1377 if can_send.close { -1378 trace!("sending CONNECTION_CLOSE"); -1379 // Encode ACKs before the ConnectionClose message, to give the receiver -1380 // a better approximate on what data has been processed. This is -1381 // especially important with ack delay, since the peer might not -1382 // have gotten any other ACK for the data earlier on. -1383 let mut sent_frames = SentFrames::default(); -1384 let is_multipath_negotiated = self.is_multipath_negotiated(); -1385 for path_id in self.spaces[space_id] -1386 .number_spaces -1387 .iter() -1388 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty()) -1389 .map(|(&path_id, _)| path_id) -1390 .collect::<Vec<_>>() -1391 { -1392 Self::populate_acks( -1393 now, -1394 self.receiving_ecn, -1395 &mut sent_frames, -1396 path_id, -1397 space_id, -1398 &mut self.spaces[space_id], -1399 is_multipath_negotiated, -1400 &mut builder.frame_space_mut(), -1401 &mut self.stats, -1402 &mut qlog, -1403 ); -1404 } -1405 -1406 // Since there only 64 ACK frames there will always be enough space -1407 // to encode the ConnectionClose frame too. However we still have the -1408 // check here to prevent crashes if something changes. -1409 debug_assert!( -1410 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND, -1411 "ACKs should leave space for ConnectionClose" -1412 ); -1413 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() { -1414 let max_frame_size = builder.frame_space_remaining(); -1415 match self.state.as_type() { -1416 StateType::Closed => { -1417 let reason: Close = -1418 self.state.as_closed().expect("checked").clone().into(); -1419 if space_id == SpaceId::Data || reason.is_transport_layer() { -1420 reason -1421 .encoder(max_frame_size) -1422 .encode(&mut builder.frame_space_mut()); -1423 qlog.frame(&Frame::Close(reason)); -1424 } else { -1425 let frame = frame::ConnectionClose { -1426 error_code: TransportErrorCode::APPLICATION_ERROR, -1427 frame_type: frame::MaybeFrame::None, -1428 reason: Bytes::new(), -1429 }; -1430 frame.encode(&mut builder.frame_space_mut(), max_frame_size); -1431 qlog.frame(&Frame::Close(frame::Close::Connection(frame))); -1432 } -1433 } -1434 StateType::Draining => { -1435 let frame = frame::ConnectionClose { -1436 error_code: TransportErrorCode::NO_ERROR, -1437 frame_type: frame::MaybeFrame::None, -1438 reason: Bytes::new(), -1439 }; -1440 frame.encode(&mut builder.frame_space_mut(), max_frame_size); -1441 qlog.frame(&Frame::Close(frame::Close::Connection(frame))); -1442 } -1443 _ => unreachable!( -1444 "tried to make a close packet when the connection wasn't closed" -1445 ), -1446 }; -1447 } -1448 builder.finish_and_track(now, self, path_id, sent_frames, *pad_datagram, qlog); -1449 if space_id == self.highest_space { -1450 // Don't send another close packet. Even with multipath we only send -1451 // CONNECTION_CLOSE on a single path since we expect our paths to work. -1452 self.close = false; -1453 // `CONNECTION_CLOSE` is the final packet -1454 return PollPathSpaceStatus::Send { last_packet_number }; -1455 } else { -1456 // Send a close frame in every possible space for robustness, per -1457 // RFC9000 "Immediate Close during the Handshake". Don't bother trying -1458 // to send anything else. -1459 return PollPathSpaceStatus::NextSpace; -1460 } -1461 } -1462 -1463 // Send an off-path PATH_RESPONSE. Prioritized over on-path data to ensure that -1464 // path validation can occur while the link is saturated. -1465 if space_id == SpaceId::Data && builder.buf.num_datagrams() == 1 { -1466 let path = self.path_data_mut(path_id); -1467 if let Some((token, network_path)) = -1468 path.path_responses.pop_off_path(path.network_path) -1469 { -1470 // TODO(flub): We need to use the right CID! We shouldn't use the same -1471 // CID as the current active one for the path. Though see also -1472 // https://github.com/quinn-rs/quinn/issues/2184 -1473 let response = frame::PathResponse(token); -1474 trace!(%response, "(off-path)"); -1475 builder.frame_space_mut().write(response); -1476 qlog.frame(&Frame::PathResponse(response)); -1477 self.stats.frame_tx.path_response += 1; -1478 builder.finish_and_track( -1479 now, -1480 self, -1481 path_id, -1482 SentFrames { -1483 non_retransmits: true, -1484 ..SentFrames::default() -1485 }, -1486 PadDatagram::ToMinMtu, -1487 qlog, -1488 ); -1489 self.stats.udp_tx.on_sent(1, transmit.len()); -1490 return PollPathSpaceStatus::SendTransmit { -1491 transmit: Transmit { -1492 destination: network_path.remote, -1493 size: transmit.len(), -1494 ecn: None, -1495 segment_size: None, -1496 src_ip: network_path.local_ip, -1497 }, -1498 }; -1499 } -1500 } -1501 -1502 let sent_frames = { -1503 let path_exclusive_only = have_available_path -1504 && self.path_data(path_id).local_status() == PathStatus::Backup; -1505 let pn = builder.exact_number; -1506 self.populate_packet( -1507 now, -1508 space_id, -1509 path_id, -1510 path_exclusive_only, -1511 &mut builder.frame_space_mut(), -1512 pn, -1513 &mut qlog, -1514 ) -1515 }; -1516 -1517 // ACK-only packets should only be sent when explicitly allowed. If we write them due to -1518 // any other reason, there is a bug which leads to one component announcing write -1519 // readiness while not writing any data. This degrades performance. The condition is -1520 // only checked if the full MTU is available and when potentially large fixed-size -1521 // frames aren't queued, so that lack of space in the datagram isn't the reason for just -1522 // writing ACKs. -1523 debug_assert!( -1524 !(sent_frames.is_ack_only(&self.streams) -1525 && !can_send.acks -1526 && can_send.other -1527 && builder.buf.segment_size() -1528 == self.path_data(path_id).current_mtu() as usize -1529 && self.datagrams.outgoing.is_empty()), -1530 "SendableFrames was {can_send:?}, but only ACKs have been written" -1531 ); -1532 if sent_frames.requires_padding { -1533 *pad_datagram |= PadDatagram::ToMinMtu; -1534 } -1535 -1536 for (path_id, _pn) in sent_frames.largest_acked.iter() { -1537 self.spaces[space_id] -1538 .for_path(*path_id) -1539 .pending_acks -1540 .acks_sent(); -1541 self.timers.stop( -1542 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), -1543 self.qlog.with_time(now), -1544 ); -1545 } -1546 -1547 // Now we need to finish the packet. Before we do so we need to know if we will -1548 // be coalescing the next packet into this one, or will be ending the datagram -1549 // as well. Because if this is the last packet in the datagram more padding -1550 // might be needed because of the packet type, or to fill the GSO segment size. -1551 -1552 // Are we allowed to coalesce AND is there enough space for another *packet* in -1553 // this datagram AND is there another packet to send in this or the next space? -1554 if *coalesce -1555 && builder -1556 .buf -1557 .datagram_remaining_mut() -1558 .saturating_sub(builder.predict_packet_end()) -1559 > MIN_PACKET_SPACE -1560 && self.has_next_send_space(space_id, path_id, builder.buf, close) -1561 { -1562 // We can append/coalesce the next packet into the current -1563 // datagram. Finish the current packet without adding extra padding. -1564 builder.finish_and_track(now, self, path_id, sent_frames, PadDatagram::No, qlog); -1565 } else { -1566 // We need a new datagram for the next packet. Finish the current -1567 // packet with padding. -1568 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) { -1569 // If too many padding bytes would be required to continue the -1570 // GSO batch after this packet, end the GSO batch here. Ensures -1571 // that fixed-size frames with heterogeneous sizes -1572 // (e.g. application datagrams) won't inadvertently waste large -1573 // amounts of bandwidth. The exact threshold is a bit arbitrary -1574 // and might benefit from further tuning, though there's no -1575 // universally optimal value. -1576 const MAX_PADDING: usize = 32; -1577 if builder.buf.datagram_remaining_mut() -1578 > builder.predict_packet_end() + MAX_PADDING -1579 { -1580 trace!( -1581 "GSO truncated by demand for {} padding bytes", -1582 builder.buf.datagram_remaining_mut() - builder.predict_packet_end() -1583 ); -1584 builder.finish_and_track( -1585 now, -1586 self, -1587 path_id, -1588 sent_frames, -1589 PadDatagram::No, -1590 qlog, -1591 ); -1592 return PollPathSpaceStatus::Send { last_packet_number }; -1593 } -1594 -1595 // Pad the current datagram to GSO segment size so it can be -1596 // included in the GSO batch. -1597 builder.finish_and_track( -1598 now, -1599 self, -1600 path_id, -1601 sent_frames, -1602 PadDatagram::ToSegmentSize, -1603 qlog, -1604 ); -1605 } else { -1606 builder.finish_and_track(now, self, path_id, sent_frames, *pad_datagram, qlog); -1607 } -1608 if transmit.num_datagrams() == 1 { -1609 transmit.clip_datagram_size(); -1610 } -1611 } -1612 } -1613 } -1614 -1615 fn on_remote_cids_exhausted(&mut self, now: Instant, path_id: PathId) { -1616 if self.abandoned_paths.contains(&path_id) { -1617 trace!(%path_id, "remote CIDs retired for abandoned path"); -1618 return; +1271 let send_blocked = if path_should_send && transmit.datagram_remaining_mut() == 0 { +1272 // Only check congestion control if a new datagram is needed. +1273 self.path_congestion_check(space_id, path_id, transmit, &can_send, now) +1274 } else { +1275 PathBlocked::No +1276 }; +1277 +1278 // Whether congestion control stopped the next packet from being sent. Further +1279 // packets could still be built, as e.g. tail-loss probes are not congestion +1280 // limited. +1281 let congestion_blocked = if send_blocked != PathBlocked::No { +1282 trace!(?space_id, %path_id, ?send_blocked, "congestion blocked"); +1283 true +1284 } else { +1285 false +1286 }; +1287 if send_blocked != PathBlocked::No && space_id < SpaceId::Data { +1288 // Higher spaces might still have tail-loss probes to send, which are not +1289 // congestion blocked. +1290 return PollPathSpaceStatus::NextSpace; +1291 } +1292 if !path_should_send || send_blocked != PathBlocked::No { +1293 // Nothing more to send on this path, check the next path if possible. +1294 +1295 // If there are any datagrams in the transmit, packets for another path can +1296 // not be built. +1297 if transmit.num_datagrams() > 0 { +1298 return PollPathSpaceStatus::Send { last_packet_number }; +1299 } +1300 +1301 return PollPathSpaceStatus::NothingToSend { congestion_blocked }; +1302 } +1303 +1304 if transmit.datagram_remaining_mut() == 0 { +1305 if transmit.num_datagrams() >= transmit.max_datagrams().get() { +1306 // No more datagrams allowed +1307 return PollPathSpaceStatus::Send { last_packet_number }; +1308 } +1309 +1310 match self.spaces[space_id].for_path(path_id).loss_probes { +1311 0 => transmit.start_new_datagram(), +1312 _ => { +1313 // We need something to send for a tail-loss probe. +1314 let request_immediate_ack = +1315 space_id == SpaceId::Data && self.peer_supports_ack_frequency(); +1316 self.spaces[space_id].maybe_queue_probe( +1317 path_id, +1318 request_immediate_ack, +1319 &self.streams, +1320 ); +1321 +1322 self.spaces[space_id].for_path(path_id).loss_probes -= 1; +1323 +1324 // Clamp the datagram to at most the minimum MTU to ensure that loss +1325 // probes can get through and enable recovery even if the path MTU +1326 // has shrank unexpectedly. +1327 transmit.start_new_datagram_with_size(std::cmp::min( +1328 usize::from(INITIAL_MTU), +1329 transmit.segment_size(), +1330 )); +1331 } +1332 } +1333 trace!(count = transmit.num_datagrams(), "new datagram started"); +1334 *coalesce = true; +1335 *pad_datagram = PadDatagram::No; +1336 } +1337 +1338 // If coalescing another packet into the existing datagram, there should +1339 // still be enough space for a whole packet. +1340 if transmit.datagram_start_offset() < transmit.len() { +1341 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE); +1342 } +1343 +1344 // +1345 // From here on, we've determined that a packet will definitely be sent. +1346 // +1347 +1348 if self.spaces[SpaceId::Initial].crypto.is_some() +1349 && space_id == SpaceId::Handshake +1350 && self.side.is_client() +1351 { +1352 // A client stops both sending and processing Initial packets when it +1353 // sends its first Handshake packet. +1354 self.discard_space(now, SpaceId::Initial); +1355 } +1356 if let Some(ref mut prev) = self.prev_crypto { +1357 prev.update_unacked = false; +1358 } +1359 +1360 let mut qlog = QlogSentPacket::default(); +1361 let Some(mut builder) = PacketBuilder::new( +1362 now, +1363 space_id, +1364 path_id, +1365 remote_cid, +1366 transmit, +1367 can_send.other, +1368 self, +1369 &mut qlog, +1370 ) else { +1371 return PollPathSpaceStatus::NothingToSend { congestion_blocked }; +1372 }; +1373 last_packet_number = Some(builder.exact_number); +1374 *coalesce = *coalesce && !builder.short_header; +1375 +1376 if space_id == SpaceId::Initial && (self.side.is_client() || can_send.other) { +1377 // https://www.rfc-editor.org/rfc/rfc9000.html#section-14.1 +1378 *pad_datagram |= PadDatagram::ToMinMtu; +1379 } +1380 if space_id == SpaceId::Data && self.config.pad_to_mtu { +1381 *pad_datagram |= PadDatagram::ToSegmentSize; +1382 } +1383 +1384 if can_send.close { +1385 trace!("sending CONNECTION_CLOSE"); +1386 // Encode ACKs before the ConnectionClose message, to give the receiver +1387 // a better approximate on what data has been processed. This is +1388 // especially important with ack delay, since the peer might not +1389 // have gotten any other ACK for the data earlier on. +1390 let mut sent_frames = SentFrames::default(); +1391 let is_multipath_negotiated = self.is_multipath_negotiated(); +1392 for path_id in self.spaces[space_id] +1393 .number_spaces +1394 .iter() +1395 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty()) +1396 .map(|(&path_id, _)| path_id) +1397 .collect::<Vec<_>>() +1398 { +1399 Self::populate_acks( +1400 now, +1401 self.receiving_ecn, +1402 &mut sent_frames, +1403 path_id, +1404 space_id, +1405 &mut self.spaces[space_id], +1406 is_multipath_negotiated, +1407 &mut builder.frame_space_mut(), +1408 &mut self.stats, +1409 &mut qlog, +1410 ); +1411 } +1412 +1413 // Since there only 64 ACK frames there will always be enough space +1414 // to encode the ConnectionClose frame too. However we still have the +1415 // check here to prevent crashes if something changes. +1416 debug_assert!( +1417 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND, +1418 "ACKs should leave space for ConnectionClose" +1419 ); +1420 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() { +1421 let max_frame_size = builder.frame_space_remaining(); +1422 match self.state.as_type() { +1423 StateType::Closed => { +1424 let reason: Close = +1425 self.state.as_closed().expect("checked").clone().into(); +1426 if space_id == SpaceId::Data || reason.is_transport_layer() { +1427 reason +1428 .encoder(max_frame_size) +1429 .encode(&mut builder.frame_space_mut()); +1430 qlog.frame(&Frame::Close(reason)); +1431 } else { +1432 let frame = frame::ConnectionClose { +1433 error_code: TransportErrorCode::APPLICATION_ERROR, +1434 frame_type: frame::MaybeFrame::None, +1435 reason: Bytes::new(), +1436 }; +1437 frame.encode(&mut builder.frame_space_mut(), max_frame_size); +1438 qlog.frame(&Frame::Close(frame::Close::Connection(frame))); +1439 } +1440 } +1441 StateType::Draining => { +1442 let frame = frame::ConnectionClose { +1443 error_code: TransportErrorCode::NO_ERROR, +1444 frame_type: frame::MaybeFrame::None, +1445 reason: Bytes::new(), +1446 }; +1447 frame.encode(&mut builder.frame_space_mut(), max_frame_size); +1448 qlog.frame(&Frame::Close(frame::Close::Connection(frame))); +1449 } +1450 _ => unreachable!( +1451 "tried to make a close packet when the connection wasn't closed" +1452 ), +1453 }; +1454 } +1455 builder.finish_and_track(now, self, path_id, sent_frames, *pad_datagram, qlog); +1456 if space_id == self.highest_space { +1457 // Don't send another close packet. Even with multipath we only send +1458 // CONNECTION_CLOSE on a single path since we expect our paths to work. +1459 self.close = false; +1460 // `CONNECTION_CLOSE` is the final packet +1461 return PollPathSpaceStatus::Send { last_packet_number }; +1462 } else { +1463 // Send a close frame in every possible space for robustness, per +1464 // RFC9000 "Immediate Close during the Handshake". Don't bother trying +1465 // to send anything else. +1466 return PollPathSpaceStatus::NextSpace; +1467 } +1468 } +1469 +1470 // Send an off-path PATH_RESPONSE. Prioritized over on-path data to ensure that +1471 // path validation can occur while the link is saturated. +1472 if space_id == SpaceId::Data && builder.buf.num_datagrams() == 1 { +1473 let path = self.path_data_mut(path_id); +1474 if let Some((token, network_path)) = +1475 path.path_responses.pop_off_path(path.network_path) +1476 { +1477 // TODO(flub): We need to use the right CID! We shouldn't use the same +1478 // CID as the current active one for the path. Though see also +1479 // https://github.com/quinn-rs/quinn/issues/2184 +1480 let response = frame::PathResponse(token); +1481 trace!(%response, "(off-path)"); +1482 builder.frame_space_mut().write(response); +1483 qlog.frame(&Frame::PathResponse(response)); +1484 self.stats.frame_tx.path_response += 1; +1485 builder.finish_and_track( +1486 now, +1487 self, +1488 path_id, +1489 SentFrames { +1490 non_retransmits: true, +1491 ..SentFrames::default() +1492 }, +1493 PadDatagram::ToMinMtu, +1494 qlog, +1495 ); +1496 self.stats.udp_tx.on_sent(1, transmit.len()); +1497 return PollPathSpaceStatus::SendTransmit { +1498 transmit: Transmit { +1499 destination: network_path.remote, +1500 size: transmit.len(), +1501 ecn: None, +1502 segment_size: None, +1503 src_ip: network_path.local_ip, +1504 }, +1505 }; +1506 } +1507 } +1508 +1509 let sent_frames = { +1510 let path_exclusive_only = have_available_path +1511 && self.path_data(path_id).local_status() == PathStatus::Backup; +1512 let pn = builder.exact_number; +1513 self.populate_packet( +1514 now, +1515 space_id, +1516 path_id, +1517 path_exclusive_only, +1518 &mut builder.frame_space_mut(), +1519 pn, +1520 &mut qlog, +1521 ) +1522 }; +1523 +1524 // ACK-only packets should only be sent when explicitly allowed. If we write them due to +1525 // any other reason, there is a bug which leads to one component announcing write +1526 // readiness while not writing any data. This degrades performance. The condition is +1527 // only checked if the full MTU is available and when potentially large fixed-size +1528 // frames aren't queued, so that lack of space in the datagram isn't the reason for just +1529 // writing ACKs. +1530 debug_assert!( +1531 !(sent_frames.is_ack_only(&self.streams) +1532 && !can_send.acks +1533 && can_send.other +1534 && builder.buf.segment_size() +1535 == self.path_data(path_id).current_mtu() as usize +1536 && self.datagrams.outgoing.is_empty()), +1537 "SendableFrames was {can_send:?}, but only ACKs have been written" +1538 ); +1539 if sent_frames.requires_padding { +1540 *pad_datagram |= PadDatagram::ToMinMtu; +1541 } +1542 +1543 for (path_id, _pn) in sent_frames.largest_acked.iter() { +1544 self.spaces[space_id] +1545 .for_path(*path_id) +1546 .pending_acks +1547 .acks_sent(); +1548 self.timers.stop( +1549 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), +1550 self.qlog.with_time(now), +1551 ); +1552 } +1553 +1554 // Now we need to finish the packet. Before we do so we need to know if we will +1555 // be coalescing the next packet into this one, or will be ending the datagram +1556 // as well. Because if this is the last packet in the datagram more padding +1557 // might be needed because of the packet type, or to fill the GSO segment size. +1558 +1559 // Are we allowed to coalesce AND is there enough space for another *packet* in +1560 // this datagram AND is there another packet to send in this or the next space? +1561 if *coalesce +1562 && builder +1563 .buf +1564 .datagram_remaining_mut() +1565 .saturating_sub(builder.predict_packet_end()) +1566 > MIN_PACKET_SPACE +1567 && self.has_next_send_space(space_id, path_id, builder.buf, close) +1568 { +1569 // We can append/coalesce the next packet into the current +1570 // datagram. Finish the current packet without adding extra padding. +1571 builder.finish_and_track(now, self, path_id, sent_frames, PadDatagram::No, qlog); +1572 } else { +1573 // We need a new datagram for the next packet. Finish the current +1574 // packet with padding. +1575 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) { +1576 // If too many padding bytes would be required to continue the +1577 // GSO batch after this packet, end the GSO batch here. Ensures +1578 // that fixed-size frames with heterogeneous sizes +1579 // (e.g. application datagrams) won't inadvertently waste large +1580 // amounts of bandwidth. The exact threshold is a bit arbitrary +1581 // and might benefit from further tuning, though there's no +1582 // universally optimal value. +1583 const MAX_PADDING: usize = 32; +1584 if builder.buf.datagram_remaining_mut() +1585 > builder.predict_packet_end() + MAX_PADDING +1586 { +1587 trace!( +1588 "GSO truncated by demand for {} padding bytes", +1589 builder.buf.datagram_remaining_mut() - builder.predict_packet_end() +1590 ); +1591 builder.finish_and_track( +1592 now, +1593 self, +1594 path_id, +1595 sent_frames, +1596 PadDatagram::No, +1597 qlog, +1598 ); +1599 return PollPathSpaceStatus::Send { last_packet_number }; +1600 } +1601 +1602 // Pad the current datagram to GSO segment size so it can be +1603 // included in the GSO batch. +1604 builder.finish_and_track( +1605 now, +1606 self, +1607 path_id, +1608 sent_frames, +1609 PadDatagram::ToSegmentSize, +1610 qlog, +1611 ); +1612 } else { +1613 builder.finish_and_track(now, self, path_id, sent_frames, *pad_datagram, qlog); +1614 } +1615 if transmit.num_datagrams() == 1 { +1616 transmit.clip_datagram_size(); +1617 } +1618 } 1619 } -1620 -1621 let error = PathError::RemoteCidsExhausted; -1622 debug!(?error, %path_id, "no active CID for path"); -1623 self.events -1624 .push_back(Event::Path(PathEvent::LocallyClosed { id: path_id, error })); -1625 // Locally we should have refused to open this path, the remote should -1626 // have given us CIDs for this path before opening it. So we can always -1627 // abandon this here. -1628 self.close_path( -1629 now, -1630 path_id, -1631 TransportErrorCode::NO_CID_AVAILABLE_FOR_PATH.into(), -1632 ) -1633 .ok(); -1634 self.spaces[SpaceId::Data] -1635 .pending -1636 .path_cids_blocked -1637 .push(path_id); -1638 } -1639 -1640 fn poll_transmit_mtu_probe( -1641 &mut self, -1642 now: Instant, -1643 transmit: &mut TransmitBuf<'_>, -1644 path_id: PathId, -1645 ) { -1646 let Some((active_cid, probe_size)) = self.get_mtu_probe_data(now, path_id) else { -1647 return; -1648 }; -1649 -1650 // We are definitely sending a DPLPMTUD probe. -1651 debug_assert_eq!(transmit.num_datagrams(), 0); -1652 transmit.start_new_datagram_with_size(probe_size as usize); -1653 -1654 let mut qlog = QlogSentPacket::default(); -1655 let Some(mut builder) = PacketBuilder::new( -1656 now, -1657 SpaceId::Data, -1658 path_id, -1659 active_cid, -1660 transmit, -1661 true, -1662 self, -1663 &mut qlog, -1664 ) else { -1665 return; -1666 }; -1667 -1668 // We implement MTU probes as ping packets padded up to the probe size -1669 trace!(?probe_size, "writing MTUD probe"); -1670 trace!("PING"); -1671 builder.frame_space_mut().write(frame::FrameType::Ping); -1672 qlog.frame(&Frame::Ping); -1673 self.stats.frame_tx.ping += 1; +1620 } +1621 +1622 fn on_remote_cids_exhausted(&mut self, now: Instant, path_id: PathId) { +1623 if self.abandoned_paths.contains(&path_id) { +1624 trace!(%path_id, "remote CIDs retired for abandoned path"); +1625 return; +1626 } +1627 +1628 let error = PathError::RemoteCidsExhausted; +1629 debug!(?error, %path_id, "no active CID for path"); +1630 self.events +1631 .push_back(Event::Path(PathEvent::LocallyClosed { id: path_id, error })); +1632 // Locally we should have refused to open this path, the remote should +1633 // have given us CIDs for this path before opening it. So we can always +1634 // abandon this here. +1635 self.close_path( +1636 now, +1637 path_id, +1638 TransportErrorCode::NO_CID_AVAILABLE_FOR_PATH.into(), +1639 ) +1640 .ok(); +1641 self.spaces[SpaceId::Data] +1642 .pending +1643 .path_cids_blocked +1644 .insert(path_id); +1645 } +1646 +1647 fn poll_transmit_mtu_probe( +1648 &mut self, +1649 now: Instant, +1650 transmit: &mut TransmitBuf<'_>, +1651 path_id: PathId, +1652 ) { +1653 let Some((active_cid, probe_size)) = self.get_mtu_probe_data(now, path_id) else { +1654 return; +1655 }; +1656 +1657 // We are definitely sending a DPLPMTUD probe. +1658 debug_assert_eq!(transmit.num_datagrams(), 0); +1659 transmit.start_new_datagram_with_size(probe_size as usize); +1660 +1661 let mut qlog = QlogSentPacket::default(); +1662 let Some(mut builder) = PacketBuilder::new( +1663 now, +1664 SpaceId::Data, +1665 path_id, +1666 active_cid, +1667 transmit, +1668 true, +1669 self, +1670 &mut qlog, +1671 ) else { +1672 return; +1673 }; 1674 -1675 // If supported by the peer, we want no delays to the probe's ACK -1676 if self.peer_supports_ack_frequency() { -1677 trace!("IMMEDIATE_ACK"); -1678 builder -1679 .frame_space_mut() -1680 .write(frame::FrameType::ImmediateAck); -1681 self.stats.frame_tx.immediate_ack += 1; -1682 qlog.frame(&Frame::ImmediateAck); -1683 } -1684 -1685 let sent_frames = SentFrames { -1686 non_retransmits: true, -1687 ..Default::default() -1688 }; -1689 builder.finish_and_track( -1690 now, -1691 self, -1692 path_id, -1693 sent_frames, -1694 PadDatagram::ToSize(probe_size), -1695 qlog, -1696 ); -1697 -1698 self.path_stats -1699 .entry(path_id) -1700 .or_default() -1701 .sent_plpmtud_probes += 1; -1702 } -1703 -1704 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> { -1705 // We MTU probe all paths for which all of the following is true: -1706 // - We have an active destination CID for the path. -1707 // - The remote address *and* path are validated. -1708 // - The path is not abandoned. -1709 // - The MTU Discovery subsystem wants to probe the path. -1710 let active_cid = self.rem_cids.get(&path_id).map(CidQueue::active)?; -1711 let is_eligible = self.path_data(path_id).validated -1712 && !self.path_data(path_id).is_validating_path() -1713 && !self.abandoned_paths.contains(&path_id); -1714 -1715 if !is_eligible { -1716 return None; -1717 } -1718 let next_pn = self.spaces[SpaceId::Data] -1719 .for_path(path_id) -1720 .peek_tx_number(); -1721 let probe_size = self -1722 .path_data_mut(path_id) -1723 .mtud -1724 .poll_transmit(now, next_pn)?; -1725 -1726 Some((active_cid, probe_size)) -1727 } -1728 -1729 /// Returns if there is anext packet space which has data to send -1730 /// -1731 /// This takes into account the space available to frames in the next datagram. -1732 // TODO(flub): This duplication is not nice. -1733 fn has_next_send_space( -1734 &mut self, -1735 current_space_id: SpaceId, -1736 path_id: PathId, -1737 buf: &TransmitBuf<'_>, -1738 close: bool, -1739 ) -> bool { -1740 // Number of bytes available for frames if this is a 1-RTT packet. We're guaranteed -1741 // to be able to send an individual frame at least this large in the next 1-RTT -1742 // packet. This could be generalized to support every space, but it's only needed to -1743 // handle large fixed-size frames, which only exist in 1-RTT (application -1744 // datagrams). We don't account for coalesced packets potentially occupying space -1745 // because frames can always spill into the next datagram. -1746 let mut space_id = current_space_id; -1747 loop { -1748 let can_send = self.space_can_send(space_id, path_id, buf.segment_size(), close); -1749 if !can_send.is_empty() || (close && self.spaces[space_id].crypto.is_some()) { -1750 return true; -1751 } -1752 let Some(next_space) = space_id.next() else { -1753 break; -1754 }; -1755 space_id = next_space; -1756 } -1757 false -1758 } -1759 -1760 /// Checks if creating a new datagram would be blocked by congestion control -1761 fn path_congestion_check( -1762 &mut self, -1763 space_id: SpaceId, -1764 path_id: PathId, -1765 transmit: &TransmitBuf<'_>, -1766 can_send: &SendableFrames, -1767 now: Instant, -1768 ) -> PathBlocked { -1769 // Anti-amplification is only based on `total_sent`, which gets updated after -1770 // the transmit is sent. Therefore we pass the amount of bytes for datagrams -1771 // that are already created, as well as 1 byte for starting another datagram. If -1772 // there is any anti-amplification budget left, we always allow a full MTU to be -1773 // sent (see https://github.com/quinn-rs/quinn/issues/1082). -1774 if self.side().is_server() -1775 && self -1776 .path_data(path_id) -1777 .anti_amplification_blocked(transmit.len() as u64 + 1) -1778 { -1779 trace!(?space_id, %path_id, "blocked by anti-amplification"); -1780 return PathBlocked::AntiAmplification; -1781 } -1782 -1783 // Congestion control check. -1784 // Tail loss probes must not be blocked by congestion, or a deadlock could arise. -1785 let bytes_to_send = transmit.segment_size() as u64; -1786 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; -1787 -1788 if can_send.other && !need_loss_probe && !can_send.close { -1789 let path = self.path_data(path_id); -1790 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() { -1791 trace!(?space_id, %path_id, "blocked by congestion control"); -1792 return PathBlocked::Congestion; -1793 } -1794 } -1795 -1796 // Pacing check. -1797 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) { -1798 self.timers.set( -1799 Timer::PerPath(path_id, PathTimer::Pacing), -1800 delay, -1801 self.qlog.with_time(now), -1802 ); -1803 // Loss probes and CONNECTION_CLOSE should be subject to pacing, even though -1804 // they are not congestion controlled. -1805 trace!(?space_id, %path_id, "blocked by pacing"); -1806 return PathBlocked::Pacing; -1807 } -1808 -1809 PathBlocked::No -1810 } -1811 -1812 /// Send PATH_CHALLENGE for a previous path if necessary -1813 /// -1814 /// QUIC-TRANSPORT section 9.3.3 -1815 /// <https://www.rfc-editor.org/rfc/rfc9000.html#name-off-path-packet-forwarding> -1816 fn send_prev_path_challenge( -1817 &mut self, -1818 now: Instant, -1819 buf: &mut TransmitBuf<'_>, -1820 path_id: PathId, -1821 ) -> Option<Transmit> { -1822 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?; -1823 // TODO (matheus23): We could use !prev_path.is_validating() here instead to -1824 // (possibly) also re-send challenges when they get lost. -1825 if !prev_path.send_new_challenge { -1826 return None; -1827 }; -1828 prev_path.send_new_challenge = false; -1829 let network_path = prev_path.network_path; -1830 let token = self.rng.random(); -1831 let info = paths::SentChallengeInfo { -1832 sent_instant: now, -1833 network_path, +1675 // We implement MTU probes as ping packets padded up to the probe size +1676 trace!(?probe_size, "writing MTUD probe"); +1677 trace!("PING"); +1678 builder.frame_space_mut().write(frame::FrameType::Ping); +1679 qlog.frame(&Frame::Ping); +1680 self.stats.frame_tx.ping += 1; +1681 +1682 // If supported by the peer, we want no delays to the probe's ACK +1683 if self.peer_supports_ack_frequency() { +1684 trace!("IMMEDIATE_ACK"); +1685 builder +1686 .frame_space_mut() +1687 .write(frame::FrameType::ImmediateAck); +1688 self.stats.frame_tx.immediate_ack += 1; +1689 qlog.frame(&Frame::ImmediateAck); +1690 } +1691 +1692 let sent_frames = SentFrames { +1693 non_retransmits: true, +1694 ..Default::default() +1695 }; +1696 builder.finish_and_track( +1697 now, +1698 self, +1699 path_id, +1700 sent_frames, +1701 PadDatagram::ToSize(probe_size), +1702 qlog, +1703 ); +1704 +1705 self.path_stats +1706 .entry(path_id) +1707 .or_default() +1708 .sent_plpmtud_probes += 1; +1709 } +1710 +1711 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> { +1712 // We MTU probe all paths for which all of the following is true: +1713 // - We have an active destination CID for the path. +1714 // - The remote address *and* path are validated. +1715 // - The path is not abandoned. +1716 // - The MTU Discovery subsystem wants to probe the path. +1717 let active_cid = self.rem_cids.get(&path_id).map(CidQueue::active)?; +1718 let is_eligible = self.path_data(path_id).validated +1719 && !self.path_data(path_id).is_validating_path() +1720 && !self.abandoned_paths.contains(&path_id); +1721 +1722 if !is_eligible { +1723 return None; +1724 } +1725 let next_pn = self.spaces[SpaceId::Data] +1726 .for_path(path_id) +1727 .peek_tx_number(); +1728 let probe_size = self +1729 .path_data_mut(path_id) +1730 .mtud +1731 .poll_transmit(now, next_pn)?; +1732 +1733 Some((active_cid, probe_size)) +1734 } +1735 +1736 /// Returns if there is anext packet space which has data to send +1737 /// +1738 /// This takes into account the space available to frames in the next datagram. +1739 // TODO(flub): This duplication is not nice. +1740 fn has_next_send_space( +1741 &mut self, +1742 current_space_id: SpaceId, +1743 path_id: PathId, +1744 buf: &TransmitBuf<'_>, +1745 close: bool, +1746 ) -> bool { +1747 // Number of bytes available for frames if this is a 1-RTT packet. We're guaranteed +1748 // to be able to send an individual frame at least this large in the next 1-RTT +1749 // packet. This could be generalized to support every space, but it's only needed to +1750 // handle large fixed-size frames, which only exist in 1-RTT (application +1751 // datagrams). We don't account for coalesced packets potentially occupying space +1752 // because frames can always spill into the next datagram. +1753 let mut space_id = current_space_id; +1754 loop { +1755 let can_send = self.space_can_send(space_id, path_id, buf.segment_size(), close); +1756 if !can_send.is_empty() || (close && self.spaces[space_id].crypto.is_some()) { +1757 return true; +1758 } +1759 let Some(next_space) = space_id.next() else { +1760 break; +1761 }; +1762 space_id = next_space; +1763 } +1764 false +1765 } +1766 +1767 /// Checks if creating a new datagram would be blocked by congestion control +1768 fn path_congestion_check( +1769 &mut self, +1770 space_id: SpaceId, +1771 path_id: PathId, +1772 transmit: &TransmitBuf<'_>, +1773 can_send: &SendableFrames, +1774 now: Instant, +1775 ) -> PathBlocked { +1776 // Anti-amplification is only based on `total_sent`, which gets updated after +1777 // the transmit is sent. Therefore we pass the amount of bytes for datagrams +1778 // that are already created, as well as 1 byte for starting another datagram. If +1779 // there is any anti-amplification budget left, we always allow a full MTU to be +1780 // sent (see https://github.com/quinn-rs/quinn/issues/1082). +1781 if self.side().is_server() +1782 && self +1783 .path_data(path_id) +1784 .anti_amplification_blocked(transmit.len() as u64 + 1) +1785 { +1786 trace!(?space_id, %path_id, "blocked by anti-amplification"); +1787 return PathBlocked::AntiAmplification; +1788 } +1789 +1790 // Congestion control check. +1791 // Tail loss probes must not be blocked by congestion, or a deadlock could arise. +1792 let bytes_to_send = transmit.segment_size() as u64; +1793 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0; +1794 +1795 if can_send.other && !need_loss_probe && !can_send.close { +1796 let path = self.path_data(path_id); +1797 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() { +1798 trace!(?space_id, %path_id, "blocked by congestion control"); +1799 return PathBlocked::Congestion; +1800 } +1801 } +1802 +1803 // Pacing check. +1804 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) { +1805 self.timers.set( +1806 Timer::PerPath(path_id, PathTimer::Pacing), +1807 delay, +1808 self.qlog.with_time(now), +1809 ); +1810 // Loss probes and CONNECTION_CLOSE should be subject to pacing, even though +1811 // they are not congestion controlled. +1812 trace!(?space_id, %path_id, "blocked by pacing"); +1813 return PathBlocked::Pacing; +1814 } +1815 +1816 PathBlocked::No +1817 } +1818 +1819 /// Send PATH_CHALLENGE for a previous path if necessary +1820 /// +1821 /// QUIC-TRANSPORT section 9.3.3 +1822 /// <https://www.rfc-editor.org/rfc/rfc9000.html#name-off-path-packet-forwarding> +1823 fn send_prev_path_challenge( +1824 &mut self, +1825 now: Instant, +1826 buf: &mut TransmitBuf<'_>, +1827 path_id: PathId, +1828 ) -> Option<Transmit> { +1829 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?; +1830 // TODO (matheus23): We could use !prev_path.is_validating() here instead to +1831 // (possibly) also re-send challenges when they get lost. +1832 if !prev_path.send_new_challenge { +1833 return None; 1834 }; -1835 prev_path.challenges_sent.insert(token, info); -1836 debug_assert_eq!( -1837 self.highest_space, -1838 SpaceId::Data, -1839 "PATH_CHALLENGE queued without 1-RTT keys" -1840 ); -1841 buf.start_new_datagram_with_size(MIN_INITIAL_SIZE as usize); -1842 -1843 // Use the previous CID to avoid linking the new path with the previous path. We -1844 // don't bother accounting for possible retirement of that prev_cid because this is -1845 // sent once, immediately after migration, when the CID is known to be valid. Even -1846 // if a post-migration packet caused the CID to be retired, it's fair to pretend -1847 // this is sent first. -1848 debug_assert_eq!(buf.datagram_start_offset(), 0); -1849 let mut qlog = QlogSentPacket::default(); -1850 let mut builder = PacketBuilder::new( -1851 now, -1852 SpaceId::Data, -1853 path_id, -1854 *prev_cid, -1855 buf, -1856 false, -1857 self, -1858 &mut qlog, -1859 )?; -1860 let challenge = frame::PathChallenge(token); -1861 trace!(%challenge, "validating previous path"); -1862 qlog.frame(&Frame::PathChallenge(challenge)); -1863 builder.frame_space_mut().write(challenge); -1864 self.stats.frame_tx.path_challenge += 1; -1865 -1866 // An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame -1867 // to at least the smallest allowed maximum datagram size of 1200 bytes, -1868 // unless the anti-amplification limit for the path does not permit -1869 // sending a datagram of this size -1870 builder.pad_to(MIN_INITIAL_SIZE); -1871 -1872 builder.finish(self, now, qlog); -1873 self.stats.udp_tx.on_sent(1, buf.len()); -1874 -1875 Some(Transmit { -1876 destination: network_path.remote, -1877 size: buf.len(), -1878 ecn: None, -1879 segment_size: None, -1880 src_ip: network_path.local_ip, -1881 }) -1882 } -1883 -1884 /// Indicate what types of frames are ready to send for the given space -1885 /// -1886 /// *packet_size* is the number of bytes available to build the next packet. *close* -1887 /// *indicates whether a CONNECTION_CLOSE frame needs to be sent. -1888 fn space_can_send( -1889 &mut self, -1890 space_id: SpaceId, -1891 path_id: PathId, -1892 packet_size: usize, -1893 close: bool, -1894 ) -> SendableFrames { -1895 let pn = self.spaces[SpaceId::Data] -1896 .for_path(path_id) -1897 .peek_tx_number(); -1898 let frame_space_1rtt = packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id)); -1899 if self.spaces[space_id].crypto.is_none() -1900 && (space_id != SpaceId::Data -1901 || self.zero_rtt_crypto.is_none() -1902 || self.side.is_server()) -1903 { -1904 // No keys available for this space -1905 return SendableFrames::empty(); -1906 } -1907 let mut can_send = self.spaces[space_id].can_send(path_id, &self.streams); -1908 if space_id == SpaceId::Data { -1909 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt); -1910 } -1911 -1912 can_send.close = close && self.spaces[space_id].crypto.is_some(); -1913 -1914 can_send -1915 } -1916 -1917 /// Process `ConnectionEvent`s generated by the associated `Endpoint` -1918 /// -1919 /// Will execute protocol logic upon receipt of a connection event, in turn preparing signals -1920 /// (including application `Event`s, `EndpointEvent`s and outgoing datagrams) that should be -1921 /// extracted through the relevant methods. -1922 pub fn handle_event(&mut self, event: ConnectionEvent) { -1923 use ConnectionEventInner::*; -1924 match event.0 { -1925 Datagram(DatagramConnectionEvent { -1926 now, -1927 network_path, -1928 path_id, -1929 ecn, -1930 first_decode, -1931 remaining, -1932 }) => { -1933 let span = trace_span!("pkt", %path_id); -1934 let _guard = span.enter(); -1935 -1936 if self.update_network_path_or_discard(network_path, path_id) { -1937 // A return value of true indicates we should discard this packet. -1938 return; -1939 } -1940 -1941 let was_anti_amplification_blocked = self -1942 .path(path_id) -1943 .map(|path| path.anti_amplification_blocked(1)) -1944 .unwrap_or(true); // if we don't know about this path it's eagerly considered as unvalidated -1945 // TODO(@divma): revisit this -1946 -1947 self.stats.udp_rx.datagrams += 1; -1948 self.stats.udp_rx.bytes += first_decode.len() as u64; -1949 let data_len = first_decode.len(); -1950 -1951 self.handle_decode(now, network_path, path_id, ecn, first_decode); -1952 // The current `path` might have changed inside `handle_decode` since the packet -1953 // could have triggered a migration. The packet might also belong to an unknown -1954 // path and have been rejected. Make sure the data received is accounted for the -1955 // most recent path by accessing `path` after `handle_decode`. -1956 if let Some(path) = self.path_mut(path_id) { -1957 path.inc_total_recvd(data_len as u64); -1958 } -1959 -1960 if let Some(data) = remaining { -1961 self.stats.udp_rx.bytes += data.len() as u64; -1962 self.handle_coalesced(now, network_path, path_id, ecn, data); -1963 } -1964 -1965 if let Some(path) = self.paths.get_mut(&path_id) { -1966 self.qlog -1967 .emit_recovery_metrics(path_id, &mut path.data, now); -1968 } -1969 -1970 if was_anti_amplification_blocked { -1971 // A prior attempt to set the loss detection timer may have failed due to -1972 // anti-amplification, so ensure it's set now. Prevents a handshake deadlock if -1973 // the server's first flight is lost. -1974 self.set_loss_detection_timer(now, path_id); +1835 prev_path.send_new_challenge = false; +1836 let network_path = prev_path.network_path; +1837 let token = self.rng.random(); +1838 let info = paths::SentChallengeInfo { +1839 sent_instant: now, +1840 network_path, +1841 }; +1842 prev_path.challenges_sent.insert(token, info); +1843 debug_assert_eq!( +1844 self.highest_space, +1845 SpaceId::Data, +1846 "PATH_CHALLENGE queued without 1-RTT keys" +1847 ); +1848 buf.start_new_datagram_with_size(MIN_INITIAL_SIZE as usize); +1849 +1850 // Use the previous CID to avoid linking the new path with the previous path. We +1851 // don't bother accounting for possible retirement of that prev_cid because this is +1852 // sent once, immediately after migration, when the CID is known to be valid. Even +1853 // if a post-migration packet caused the CID to be retired, it's fair to pretend +1854 // this is sent first. +1855 debug_assert_eq!(buf.datagram_start_offset(), 0); +1856 let mut qlog = QlogSentPacket::default(); +1857 let mut builder = PacketBuilder::new( +1858 now, +1859 SpaceId::Data, +1860 path_id, +1861 *prev_cid, +1862 buf, +1863 false, +1864 self, +1865 &mut qlog, +1866 )?; +1867 let challenge = frame::PathChallenge(token); +1868 trace!(%challenge, "validating previous path"); +1869 qlog.frame(&Frame::PathChallenge(challenge)); +1870 builder.frame_space_mut().write(challenge); +1871 self.stats.frame_tx.path_challenge += 1; +1872 +1873 // An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame +1874 // to at least the smallest allowed maximum datagram size of 1200 bytes, +1875 // unless the anti-amplification limit for the path does not permit +1876 // sending a datagram of this size +1877 builder.pad_to(MIN_INITIAL_SIZE); +1878 +1879 builder.finish(self, now, qlog); +1880 self.stats.udp_tx.on_sent(1, buf.len()); +1881 +1882 Some(Transmit { +1883 destination: network_path.remote, +1884 size: buf.len(), +1885 ecn: None, +1886 segment_size: None, +1887 src_ip: network_path.local_ip, +1888 }) +1889 } +1890 +1891 /// Indicate what types of frames are ready to send for the given space +1892 /// +1893 /// *packet_size* is the number of bytes available to build the next packet. *close* +1894 /// *indicates whether a CONNECTION_CLOSE frame needs to be sent. +1895 fn space_can_send( +1896 &mut self, +1897 space_id: SpaceId, +1898 path_id: PathId, +1899 packet_size: usize, +1900 close: bool, +1901 ) -> SendableFrames { +1902 let pn = self.spaces[SpaceId::Data] +1903 .for_path(path_id) +1904 .peek_tx_number(); +1905 let frame_space_1rtt = packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id)); +1906 if self.spaces[space_id].crypto.is_none() +1907 && (space_id != SpaceId::Data +1908 || self.zero_rtt_crypto.is_none() +1909 || self.side.is_server()) +1910 { +1911 // No keys available for this space +1912 return SendableFrames::empty(); +1913 } +1914 let mut can_send = self.spaces[space_id].can_send(path_id, &self.streams); +1915 if space_id == SpaceId::Data { +1916 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt); +1917 } +1918 +1919 can_send.close = close && self.spaces[space_id].crypto.is_some(); +1920 +1921 can_send +1922 } +1923 +1924 /// Process `ConnectionEvent`s generated by the associated `Endpoint` +1925 /// +1926 /// Will execute protocol logic upon receipt of a connection event, in turn preparing signals +1927 /// (including application `Event`s, `EndpointEvent`s and outgoing datagrams) that should be +1928 /// extracted through the relevant methods. +1929 pub fn handle_event(&mut self, event: ConnectionEvent) { +1930 use ConnectionEventInner::*; +1931 match event.0 { +1932 Datagram(DatagramConnectionEvent { +1933 now, +1934 network_path, +1935 path_id, +1936 ecn, +1937 first_decode, +1938 remaining, +1939 }) => { +1940 let span = trace_span!("pkt", %path_id); +1941 let _guard = span.enter(); +1942 +1943 if self.update_network_path_or_discard(network_path, path_id) { +1944 // A return value of true indicates we should discard this packet. +1945 return; +1946 } +1947 +1948 let was_anti_amplification_blocked = self +1949 .path(path_id) +1950 .map(|path| path.anti_amplification_blocked(1)) +1951 .unwrap_or(true); // if we don't know about this path it's eagerly considered as unvalidated +1952 // TODO(@divma): revisit this +1953 +1954 self.stats.udp_rx.datagrams += 1; +1955 self.stats.udp_rx.bytes += first_decode.len() as u64; +1956 let data_len = first_decode.len(); +1957 +1958 self.handle_decode(now, network_path, path_id, ecn, first_decode); +1959 // The current `path` might have changed inside `handle_decode` since the packet +1960 // could have triggered a migration. The packet might also belong to an unknown +1961 // path and have been rejected. Make sure the data received is accounted for the +1962 // most recent path by accessing `path` after `handle_decode`. +1963 if let Some(path) = self.path_mut(path_id) { +1964 path.inc_total_recvd(data_len as u64); +1965 } +1966 +1967 if let Some(data) = remaining { +1968 self.stats.udp_rx.bytes += data.len() as u64; +1969 self.handle_coalesced(now, network_path, path_id, ecn, data); +1970 } +1971 +1972 if let Some(path) = self.paths.get_mut(&path_id) { +1973 self.qlog +1974 .emit_recovery_metrics(path_id, &mut path.data, now); 1975 } -1976 } -1977 NewIdentifiers(ids, now, cid_len, cid_lifetime) => { -1978 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default(); -1979 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id)); -1980 let cid_state = self -1981 .local_cid_state -1982 .entry(path_id) -1983 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0)); -1984 cid_state.new_cids(&ids, now); -1985 -1986 ids.into_iter().rev().for_each(|frame| { -1987 self.spaces[SpaceId::Data].pending.new_cids.push(frame); -1988 }); -1989 // Always update Timer::PushNewCid -1990 self.reset_cid_retirement(now); -1991 } -1992 } -1993 } -1994 -1995 /// Updates the network path for `path_id`. -1996 /// -1997 /// Returns true if a packet coming in for this `path_id` over given `network_path` should be discarded. -1998 /// Returns false if the path was updated and the packet doesn't need to be discarded. -1999 fn update_network_path_or_discard(&mut self, network_path: FourTuple, path_id: PathId) -> bool { -2000 let remote_may_migrate = self.side.remote_may_migrate(&self.state); -2001 let local_ip_may_migrate = self.side.is_client(); -2002 // If this packet could initiate a migration and we're a client or a server that -2003 // forbids migration, drop the datagram. This could be relaxed to heuristically -2004 // permit NAT-rebinding-like migration. -2005 if let Some(known_path) = self.path_mut(path_id) { -2006 if network_path.remote != known_path.network_path.remote && !remote_may_migrate { -2007 trace!( -2008 %path_id, -2009 %network_path, -2010 %known_path.network_path, -2011 "discarding packet from unrecognized peer" -2012 ); -2013 return true; -2014 } -2015 -2016 if known_path.network_path.local_ip.is_some() -2017 && network_path.local_ip.is_some() -2018 && known_path.network_path.local_ip != network_path.local_ip -2019 && !local_ip_may_migrate -2020 { -2021 trace!( -2022 %path_id, -2023 %network_path, -2024 %known_path.network_path, -2025 "discarding packet sent to incorrect interface" -2026 ); -2027 return true; -2028 } -2029 // If the datagram indicates that we've changed our local IP, we update it. -2030 // This is alluded to in Section 5.2 of the Multipath RFC draft 18: -2031 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-18.html#name-using-multiple-paths-on-the -2032 // > Client receives the packet, recognizes a path migration, updates the source address of path 2 to 192.0.2.1. -2033 if let Some(local_ip) = network_path.local_ip { -2034 if known_path -2035 .network_path -2036 .local_ip -2037 .is_some_and(|ip| ip != local_ip) -2038 { -2039 debug!( -2040 %path_id, -2041 %network_path, -2042 %known_path.network_path, -2043 "path's local address seemingly migrated" -2044 ); -2045 } -2046 // We update the address without path validation on the client side. -2047 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-18.html#section-5.1 -2048 // > Servers observing a 4-tuple change will perform path validation (see Section 9 of [QUIC-TRANSPORT]). -2049 // This sounds like it's *only* the server endpoints that do this. -2050 // TODO(matheus23): We should still consider doing a proper migration on the client side in the future. -2051 // For now, this preserves the behavior of this code pre 4-tuple tracking. -2052 known_path.network_path.local_ip = Some(local_ip); -2053 } -2054 } -2055 false -2056 } -2057 -2058 /// Process timer expirations -2059 /// -2060 /// Executes protocol logic, potentially preparing signals (including application `Event`s, -2061 /// `EndpointEvent`s and outgoing datagrams) that should be extracted through the relevant -2062 /// methods. -2063 /// -2064 /// It is most efficient to call this immediately after the system clock reaches the latest -2065 /// `Instant` that was output by `poll_timeout`; however spurious extra calls will simply -2066 /// no-op and therefore are safe. -2067 pub fn handle_timeout(&mut self, now: Instant) { -2068 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) { -2069 // TODO(@divma): remove `at` when the unicorn is born -2070 trace!(?timer, at=?now, "timeout"); -2071 match timer { -2072 Timer::Conn(timer) => match timer { -2073 ConnTimer::Close => { -2074 self.state.move_to_drained(None); -2075 self.endpoint_events.push_back(EndpointEventInner::Drained); -2076 } -2077 ConnTimer::Idle => { -2078 self.kill(ConnectionError::TimedOut); -2079 } -2080 ConnTimer::KeepAlive => { -2081 trace!("sending keep-alive"); -2082 self.ping(); +1976 +1977 if was_anti_amplification_blocked { +1978 // A prior attempt to set the loss detection timer may have failed due to +1979 // anti-amplification, so ensure it's set now. Prevents a handshake deadlock if +1980 // the server's first flight is lost. +1981 self.set_loss_detection_timer(now, path_id); +1982 } +1983 } +1984 NewIdentifiers(ids, now, cid_len, cid_lifetime) => { +1985 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default(); +1986 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id)); +1987 let cid_state = self +1988 .local_cid_state +1989 .entry(path_id) +1990 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0)); +1991 cid_state.new_cids(&ids, now); +1992 +1993 ids.into_iter().rev().for_each(|frame| { +1994 self.spaces[SpaceId::Data].pending.new_cids.push(frame); +1995 }); +1996 // Always update Timer::PushNewCid +1997 self.reset_cid_retirement(now); +1998 } +1999 } +2000 } +2001 +2002 /// Updates the network path for `path_id`. +2003 /// +2004 /// Returns true if a packet coming in for this `path_id` over given `network_path` should be discarded. +2005 /// Returns false if the path was updated and the packet doesn't need to be discarded. +2006 fn update_network_path_or_discard(&mut self, network_path: FourTuple, path_id: PathId) -> bool { +2007 let remote_may_migrate = self.side.remote_may_migrate(&self.state); +2008 let local_ip_may_migrate = self.side.is_client(); +2009 // If this packet could initiate a migration and we're a client or a server that +2010 // forbids migration, drop the datagram. This could be relaxed to heuristically +2011 // permit NAT-rebinding-like migration. +2012 if let Some(known_path) = self.path_mut(path_id) { +2013 if network_path.remote != known_path.network_path.remote && !remote_may_migrate { +2014 trace!( +2015 %path_id, +2016 %network_path, +2017 %known_path.network_path, +2018 "discarding packet from unrecognized peer" +2019 ); +2020 return true; +2021 } +2022 +2023 if known_path.network_path.local_ip.is_some() +2024 && network_path.local_ip.is_some() +2025 && known_path.network_path.local_ip != network_path.local_ip +2026 && !local_ip_may_migrate +2027 { +2028 trace!( +2029 %path_id, +2030 %network_path, +2031 %known_path.network_path, +2032 "discarding packet sent to incorrect interface" +2033 ); +2034 return true; +2035 } +2036 // If the datagram indicates that we've changed our local IP, we update it. +2037 // This is alluded to in Section 5.2 of the Multipath RFC draft 18: +2038 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-18.html#name-using-multiple-paths-on-the +2039 // > Client receives the packet, recognizes a path migration, updates the source address of path 2 to 192.0.2.1. +2040 if let Some(local_ip) = network_path.local_ip { +2041 if known_path +2042 .network_path +2043 .local_ip +2044 .is_some_and(|ip| ip != local_ip) +2045 { +2046 debug!( +2047 %path_id, +2048 %network_path, +2049 %known_path.network_path, +2050 "path's local address seemingly migrated" +2051 ); +2052 } +2053 // We update the address without path validation on the client side. +2054 // https://www.ietf.org/archive/id/draft-ietf-quic-multipath-18.html#section-5.1 +2055 // > Servers observing a 4-tuple change will perform path validation (see Section 9 of [QUIC-TRANSPORT]). +2056 // This sounds like it's *only* the server endpoints that do this. +2057 // TODO(matheus23): We should still consider doing a proper migration on the client side in the future. +2058 // For now, this preserves the behavior of this code pre 4-tuple tracking. +2059 known_path.network_path.local_ip = Some(local_ip); +2060 } +2061 } +2062 false +2063 } +2064 +2065 /// Process timer expirations +2066 /// +2067 /// Executes protocol logic, potentially preparing signals (including application `Event`s, +2068 /// `EndpointEvent`s and outgoing datagrams) that should be extracted through the relevant +2069 /// methods. +2070 /// +2071 /// It is most efficient to call this immediately after the system clock reaches the latest +2072 /// `Instant` that was output by `poll_timeout`; however spurious extra calls will simply +2073 /// no-op and therefore are safe. +2074 pub fn handle_timeout(&mut self, now: Instant) { +2075 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) { +2076 // TODO(@divma): remove `at` when the unicorn is born +2077 trace!(?timer, at=?now, "timeout"); +2078 match timer { +2079 Timer::Conn(timer) => match timer { +2080 ConnTimer::Close => { +2081 self.state.move_to_drained(None); +2082 self.endpoint_events.push_back(EndpointEventInner::Drained); 2083 } -2084 ConnTimer::KeyDiscard => { -2085 self.zero_rtt_crypto = None; -2086 self.prev_crypto = None; -2087 } -2088 ConnTimer::PushNewCid => { -2089 while let Some((path_id, when)) = self.next_cid_retirement() { -2090 if when > now { -2091 break; -2092 } -2093 match self.local_cid_state.get_mut(&path_id) { -2094 None => error!(%path_id, "No local CID state for path"), -2095 Some(cid_state) => { -2096 // Update `retire_prior_to` field in NEW_CONNECTION_ID frame -2097 let num_new_cid = cid_state.on_cid_timeout().into(); -2098 if !self.state.is_closed() { -2099 trace!( -2100 "push a new CID to peer RETIRE_PRIOR_TO field {}", -2101 cid_state.retire_prior_to() -2102 ); -2103 self.endpoint_events.push_back( -2104 EndpointEventInner::NeedIdentifiers( -2105 path_id, -2106 now, -2107 num_new_cid, -2108 ), +2084 ConnTimer::Idle => { +2085 self.kill(ConnectionError::TimedOut); +2086 } +2087 ConnTimer::KeepAlive => { +2088 trace!("sending keep-alive"); +2089 self.ping(); +2090 } +2091 ConnTimer::KeyDiscard => { +2092 self.zero_rtt_crypto = None; +2093 self.prev_crypto = None; +2094 } +2095 ConnTimer::PushNewCid => { +2096 while let Some((path_id, when)) = self.next_cid_retirement() { +2097 if when > now { +2098 break; +2099 } +2100 match self.local_cid_state.get_mut(&path_id) { +2101 None => error!(%path_id, "No local CID state for path"), +2102 Some(cid_state) => { +2103 // Update `retire_prior_to` field in NEW_CONNECTION_ID frame +2104 let num_new_cid = cid_state.on_cid_timeout().into(); +2105 if !self.state.is_closed() { +2106 trace!( +2107 "push a new CID to peer RETIRE_PRIOR_TO field {}", +2108 cid_state.retire_prior_to() 2109 ); -2110 } -2111 } -2112 } -2113 } -2114 } -2115 }, -2116 // TODO: add path_id as span somehow -2117 Timer::PerPath(path_id, timer) => { -2118 let span = trace_span!("per-path timer fired", %path_id, ?timer); -2119 let _guard = span.enter(); -2120 match timer { -2121 PathTimer::PathIdle => { -2122 self.close_path(now, path_id, TransportErrorCode::NO_ERROR.into()) -2123 .ok(); -2124 } -2125 -2126 PathTimer::PathKeepAlive => { -2127 trace!("sending keep-alive on path"); -2128 self.ping_path(path_id).ok(); -2129 } -2130 PathTimer::LossDetection => { -2131 self.on_loss_detection_timeout(now, path_id); -2132 self.qlog.emit_recovery_metrics( -2133 path_id, -2134 &mut self.paths.get_mut(&path_id).unwrap().data, -2135 now, -2136 ); -2137 } -2138 PathTimer::PathValidation => { -2139 let Some(path) = self.paths.get_mut(&path_id) else { -2140 continue; -2141 }; -2142 self.timers.stop( -2143 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -2144 self.qlog.with_time(now), -2145 ); -2146 debug!("path validation failed"); -2147 if let Some((_, prev)) = path.prev.take() { -2148 path.data = prev; -2149 } -2150 path.data.challenges_sent.clear(); -2151 path.data.send_new_challenge = false; -2152 } -2153 PathTimer::PathChallengeLost => { -2154 let Some(path) = self.paths.get_mut(&path_id) else { -2155 continue; -2156 }; -2157 trace!("path challenge deemed lost"); -2158 path.data.send_new_challenge = true; +2110 self.endpoint_events.push_back( +2111 EndpointEventInner::NeedIdentifiers( +2112 path_id, +2113 now, +2114 num_new_cid, +2115 ), +2116 ); +2117 } +2118 } +2119 } +2120 } +2121 } +2122 }, +2123 // TODO: add path_id as span somehow +2124 Timer::PerPath(path_id, timer) => { +2125 let span = trace_span!("per-path timer fired", %path_id, ?timer); +2126 let _guard = span.enter(); +2127 match timer { +2128 PathTimer::PathIdle => { +2129 self.close_path(now, path_id, TransportErrorCode::NO_ERROR.into()) +2130 .ok(); +2131 } +2132 +2133 PathTimer::PathKeepAlive => { +2134 trace!("sending keep-alive on path"); +2135 self.ping_path(path_id).ok(); +2136 } +2137 PathTimer::LossDetection => { +2138 self.on_loss_detection_timeout(now, path_id); +2139 self.qlog.emit_recovery_metrics( +2140 path_id, +2141 &mut self.paths.get_mut(&path_id).unwrap().data, +2142 now, +2143 ); +2144 } +2145 PathTimer::PathValidation => { +2146 let Some(path) = self.paths.get_mut(&path_id) else { +2147 continue; +2148 }; +2149 self.timers.stop( +2150 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +2151 self.qlog.with_time(now), +2152 ); +2153 debug!("path validation failed"); +2154 if let Some((_, prev)) = path.prev.take() { +2155 path.data = prev; +2156 } +2157 path.data.challenges_sent.clear(); +2158 path.data.send_new_challenge = false; 2159 } -2160 PathTimer::PathOpen => { +2160 PathTimer::PathChallengeLost => { 2161 let Some(path) = self.paths.get_mut(&path_id) else { 2162 continue; 2163 }; -2164 path.data.challenges_sent.clear(); -2165 path.data.send_new_challenge = false; -2166 self.timers.stop( -2167 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -2168 self.qlog.with_time(now), -2169 ); -2170 debug!("new path validation failed"); -2171 if let Err(err) = self.close_path( -2172 now, -2173 path_id, -2174 TransportErrorCode::PATH_UNSTABLE_OR_POOR.into(), -2175 ) { -2176 warn!(?err, "failed closing path"); -2177 } -2178 -2179 self.events.push_back(Event::Path(PathEvent::LocallyClosed { -2180 id: path_id, -2181 error: PathError::ValidationFailed, -2182 })); -2183 } -2184 PathTimer::Pacing => trace!("pacing timer expired"), -2185 PathTimer::MaxAckDelay => { -2186 trace!("max ack delay reached"); -2187 // This timer is only armed in the Data space -2188 self.spaces[SpaceId::Data] -2189 .for_path(path_id) -2190 .pending_acks -2191 .on_max_ack_delay_timeout() -2192 } -2193 PathTimer::DiscardPath => { -2194 // The path was abandoned and 3*PTO has expired since. Clean up all -2195 // remaining state and install stateless reset token. -2196 self.timers.stop_per_path(path_id, self.qlog.with_time(now)); -2197 if let Some(loc_cid_state) = self.local_cid_state.remove(&path_id) { -2198 let (min_seq, max_seq) = loc_cid_state.active_seq(); -2199 for seq in min_seq..=max_seq { -2200 self.endpoint_events.push_back( -2201 EndpointEventInner::RetireConnectionId( -2202 now, path_id, seq, false, -2203 ), -2204 ); -2205 } -2206 } -2207 self.discard_path(path_id, now); -2208 } -2209 } -2210 } -2211 } -2212 } -2213 } -2214 -2215 /// Close a connection immediately -2216 /// -2217 /// This does not ensure delivery of outstanding data. It is the application's responsibility to -2218 /// call this only when all important communications have been completed, e.g. by calling -2219 /// [`SendStream::finish`] on outstanding streams and waiting for the corresponding -2220 /// [`StreamEvent::Finished`] event. -2221 /// -2222 /// If [`Streams::send_streams`] returns 0, all outstanding stream data has been -2223 /// delivered. There may still be data from the peer that has not been received. -2224 /// -2225 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished -2226 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) { -2227 self.close_inner( -2228 now, -2229 Close::Application(frame::ApplicationClose { error_code, reason }), -2230 ) -2231 } -2232 -2233 fn close_inner(&mut self, now: Instant, reason: Close) { -2234 let was_closed = self.state.is_closed(); -2235 if !was_closed { -2236 self.close_common(); -2237 self.set_close_timer(now); -2238 self.close = true; -2239 self.state.move_to_closed_local(reason); -2240 } -2241 } -2242 -2243 /// Control datagrams -2244 pub fn datagrams(&mut self) -> Datagrams<'_> { -2245 Datagrams { conn: self } -2246 } -2247 -2248 /// Returns connection statistics -2249 pub fn stats(&mut self) -> ConnectionStats { -2250 self.stats.clone() -2251 } -2252 -2253 /// Returns path statistics -2254 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { -2255 let path = self.paths.get(&path_id)?; -2256 let stats = self.path_stats.entry(path_id).or_default(); -2257 stats.rtt = path.data.rtt.get(); -2258 stats.cwnd = path.data.congestion.window(); -2259 stats.current_mtu = path.data.mtud.current_mtu(); -2260 Some(*stats) -2261 } -2262 -2263 /// Ping the remote endpoint -2264 /// -2265 /// Causes an ACK-eliciting packet to be transmitted on the connection. -2266 pub fn ping(&mut self) { -2267 // TODO(flub): This is very brute-force: it pings *all* the paths. Instead it would -2268 // be nice if we could only send a single packet for this. -2269 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() { -2270 path_data.ping_pending = true; -2271 } -2272 } -2273 -2274 /// Ping the remote endpoint over a specific path -2275 /// -2276 /// Causes an ACK-eliciting packet to be transmitted on the path. -2277 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> { -2278 let path_data = self.spaces[self.highest_space] -2279 .number_spaces -2280 .get_mut(&path) -2281 .ok_or(ClosedPath { _private: () })?; -2282 path_data.ping_pending = true; -2283 Ok(()) -2284 } -2285 -2286 /// Update traffic keys spontaneously -2287 /// -2288 /// This can be useful for testing key updates, as they otherwise only happen infrequently. -2289 pub fn force_key_update(&mut self) { -2290 if !self.state.is_established() { -2291 debug!("ignoring forced key update in illegal state"); -2292 return; -2293 } -2294 if self.prev_crypto.is_some() { -2295 // We already just updated, or are currently updating, the keys. Concurrent key updates -2296 // are illegal. -2297 debug!("ignoring redundant forced key update"); -2298 return; -2299 } -2300 self.update_keys(None, false); -2301 } -2302 -2303 // Compatibility wrapper for quinn < 0.11.7. Remove for 0.12. -2304 #[doc(hidden)] -2305 #[deprecated] -2306 pub fn initiate_key_update(&mut self) { -2307 self.force_key_update(); +2164 trace!("path challenge deemed lost"); +2165 path.data.send_new_challenge = true; +2166 } +2167 PathTimer::PathOpen => { +2168 let Some(path) = self.paths.get_mut(&path_id) else { +2169 continue; +2170 }; +2171 path.data.challenges_sent.clear(); +2172 path.data.send_new_challenge = false; +2173 self.timers.stop( +2174 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +2175 self.qlog.with_time(now), +2176 ); +2177 debug!("new path validation failed"); +2178 if let Err(err) = self.close_path( +2179 now, +2180 path_id, +2181 TransportErrorCode::PATH_UNSTABLE_OR_POOR.into(), +2182 ) { +2183 warn!(?err, "failed closing path"); +2184 } +2185 +2186 self.events.push_back(Event::Path(PathEvent::LocallyClosed { +2187 id: path_id, +2188 error: PathError::ValidationFailed, +2189 })); +2190 } +2191 PathTimer::Pacing => trace!("pacing timer expired"), +2192 PathTimer::MaxAckDelay => { +2193 trace!("max ack delay reached"); +2194 // This timer is only armed in the Data space +2195 self.spaces[SpaceId::Data] +2196 .for_path(path_id) +2197 .pending_acks +2198 .on_max_ack_delay_timeout() +2199 } +2200 PathTimer::DiscardPath => { +2201 // The path was abandoned and 3*PTO has expired since. Clean up all +2202 // remaining state and install stateless reset token. +2203 self.timers.stop_per_path(path_id, self.qlog.with_time(now)); +2204 if let Some(loc_cid_state) = self.local_cid_state.remove(&path_id) { +2205 let (min_seq, max_seq) = loc_cid_state.active_seq(); +2206 for seq in min_seq..=max_seq { +2207 self.endpoint_events.push_back( +2208 EndpointEventInner::RetireConnectionId( +2209 now, path_id, seq, false, +2210 ), +2211 ); +2212 } +2213 } +2214 self.discard_path(path_id, now); +2215 } +2216 } +2217 } +2218 } +2219 } +2220 } +2221 +2222 /// Close a connection immediately +2223 /// +2224 /// This does not ensure delivery of outstanding data. It is the application's responsibility to +2225 /// call this only when all important communications have been completed, e.g. by calling +2226 /// [`SendStream::finish`] on outstanding streams and waiting for the corresponding +2227 /// [`StreamEvent::Finished`] event. +2228 /// +2229 /// If [`Streams::send_streams`] returns 0, all outstanding stream data has been +2230 /// delivered. There may still be data from the peer that has not been received. +2231 /// +2232 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished +2233 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) { +2234 self.close_inner( +2235 now, +2236 Close::Application(frame::ApplicationClose { error_code, reason }), +2237 ) +2238 } +2239 +2240 fn close_inner(&mut self, now: Instant, reason: Close) { +2241 let was_closed = self.state.is_closed(); +2242 if !was_closed { +2243 self.close_common(); +2244 self.set_close_timer(now); +2245 self.close = true; +2246 self.state.move_to_closed_local(reason); +2247 } +2248 } +2249 +2250 /// Control datagrams +2251 pub fn datagrams(&mut self) -> Datagrams<'_> { +2252 Datagrams { conn: self } +2253 } +2254 +2255 /// Returns connection statistics +2256 pub fn stats(&mut self) -> ConnectionStats { +2257 self.stats.clone() +2258 } +2259 +2260 /// Returns path statistics +2261 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> { +2262 let path = self.paths.get(&path_id)?; +2263 let stats = self.path_stats.entry(path_id).or_default(); +2264 stats.rtt = path.data.rtt.get(); +2265 stats.cwnd = path.data.congestion.window(); +2266 stats.current_mtu = path.data.mtud.current_mtu(); +2267 Some(*stats) +2268 } +2269 +2270 /// Ping the remote endpoint +2271 /// +2272 /// Causes an ACK-eliciting packet to be transmitted on the connection. +2273 pub fn ping(&mut self) { +2274 // TODO(flub): This is very brute-force: it pings *all* the paths. Instead it would +2275 // be nice if we could only send a single packet for this. +2276 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() { +2277 path_data.ping_pending = true; +2278 } +2279 } +2280 +2281 /// Ping the remote endpoint over a specific path +2282 /// +2283 /// Causes an ACK-eliciting packet to be transmitted on the path. +2284 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> { +2285 let path_data = self.spaces[self.highest_space] +2286 .number_spaces +2287 .get_mut(&path) +2288 .ok_or(ClosedPath { _private: () })?; +2289 path_data.ping_pending = true; +2290 Ok(()) +2291 } +2292 +2293 /// Update traffic keys spontaneously +2294 /// +2295 /// This can be useful for testing key updates, as they otherwise only happen infrequently. +2296 pub fn force_key_update(&mut self) { +2297 if !self.state.is_established() { +2298 debug!("ignoring forced key update in illegal state"); +2299 return; +2300 } +2301 if self.prev_crypto.is_some() { +2302 // We already just updated, or are currently updating, the keys. Concurrent key updates +2303 // are illegal. +2304 debug!("ignoring redundant forced key update"); +2305 return; +2306 } +2307 self.update_keys(None, false); 2308 } 2309 2310 /// Get a session reference @@ -3053,3901 +3053,3907 @@ 3053 if path.mtud.black_hole_detected(now) { 3054 path.congestion.on_mtu_update(path.mtud.current_mtu()); 3055 if let Some(max_datagram_size) = self.datagrams().max_size() { -3056 self.datagrams.drop_oversized(max_datagram_size); -3057 } -3058 self.path_stats -3059 .entry(path_id) -3060 .or_default() -3061 .black_holes_detected += 1; -3062 } -3063 -3064 // Don't apply congestion penalty for lost ack-only packets -3065 let lost_ack_eliciting = -3066 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes; -3067 -3068 if lost_ack_eliciting { -3069 self.path_stats -3070 .entry(path_id) -3071 .or_default() -3072 .congestion_events += 1; -3073 self.path_data_mut(path_id).congestion.on_congestion_event( -3074 now, -3075 largest_lost_sent, -3076 in_persistent_congestion, -3077 false, -3078 size_of_lost_packets, -3079 ); -3080 } -3081 } -3082 -3083 // Handle a lost MTU probe -3084 if let Some(packet) = lost_mtu_probe { -3085 let info = self.spaces[SpaceId::Data] -3086 .for_path(path_id) -3087 .take(packet) -3088 .unwrap(); // safe: lost_mtu_probe is omitted from lost_packets, and -3089 // therefore must not have been removed yet -3090 self.paths -3091 .get_mut(&path_id) -3092 .unwrap() -3093 .remove_in_flight(&info); -3094 self.path_data_mut(path_id).mtud.on_probe_lost(); -3095 self.path_stats -3096 .entry(path_id) -3097 .or_default() -3098 .lost_plpmtud_probes += 1; -3099 } -3100 } -3101 -3102 /// Returns the earliest time packets should be declared lost for all spaces on a path. -3103 /// -3104 /// If a path has an acknowledged packet with any prior un-acknowledged packets, the -3105 /// earliest un-acknowledged packet can be declared lost after a timeout has elapsed. -3106 /// The time returned is when this packet should be declared lost. -3107 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> { -3108 SpaceId::iter() -3109 .filter_map(|id| { -3110 self.spaces[id] -3111 .number_spaces -3112 .get(&path_id) -3113 .and_then(|pns| pns.loss_time) -3114 .map(|time| (time, id)) -3115 }) -3116 .min_by_key(|&(time, _)| time) -3117 } -3118 -3119 /// Returns the earliest next PTO should fire for all spaces on a path. -3120 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> { -3121 let path = self.path(path_id)?; -3122 let pto_count = path.pto_count; -3123 let backoff = 2u32.pow(pto_count.min(MAX_BACKOFF_EXPONENT)); -3124 let mut duration = path.rtt.pto_base() * backoff; -3125 -3126 if path_id == PathId::ZERO -3127 && path.in_flight.ack_eliciting == 0 -3128 && !self.peer_completed_address_validation(PathId::ZERO) -3129 { -3130 // Address Validation during Connection Establishment: -3131 // https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1. To prevent a -3132 // deadlock if an Initial or Handshake packet from the server is lost and the -3133 // server can not send more due to its anti-amplification limit the client must -3134 // send another packet on PTO. -3135 let space = match self.highest_space { -3136 SpaceId::Handshake => SpaceId::Handshake, -3137 _ => SpaceId::Initial, -3138 }; -3139 -3140 return Some((now + duration, space)); -3141 } -3142 -3143 let mut result = None; -3144 for space in SpaceId::iter() { -3145 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else { -3146 continue; -3147 }; -3148 -3149 if !pns.has_in_flight() { -3150 continue; -3151 } -3152 if space == SpaceId::Data { -3153 // Skip ApplicationData until handshake completes. -3154 if self.is_handshaking() { -3155 return result; -3156 } -3157 // Include max_ack_delay and backoff for ApplicationData. -3158 duration += self.ack_frequency.max_ack_delay_for_pto() * backoff; -3159 } -3160 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else { -3161 continue; -3162 }; -3163 let pto = last_ack_eliciting + duration; -3164 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) { -3165 if path.anti_amplification_blocked(1) { -3166 // Nothing would be able to be sent. -3167 continue; -3168 } -3169 if path.in_flight.ack_eliciting == 0 { -3170 // Nothing ack-eliciting, no PTO to arm/fire. -3171 continue; -3172 } -3173 result = Some((pto, space)); -3174 } -3175 } -3176 result -3177 } -3178 -3179 fn peer_completed_address_validation(&self, path: PathId) -> bool { -3180 // TODO(flub): This logic needs updating for multipath -3181 if self.side.is_server() || self.state.is_closed() { -3182 return true; -3183 } -3184 // The server is guaranteed to have validated our address if any of our handshake or 1-RTT -3185 // packets are acknowledged or we've seen HANDSHAKE_DONE and discarded handshake keys. -3186 self.spaces[SpaceId::Handshake] -3187 .path_space(PathId::ZERO) -3188 .and_then(|pns| pns.largest_acked_packet) -3189 .is_some() -3190 || self.spaces[SpaceId::Data] -3191 .path_space(path) -3192 .and_then(|pns| pns.largest_acked_packet) -3193 .is_some() -3194 || (self.spaces[SpaceId::Data].crypto.is_some() -3195 && self.spaces[SpaceId::Handshake].crypto.is_none()) -3196 } -3197 -3198 /// Resets the the [`PathTimer::LossDetection`] timer to the next instant it may be needed -3199 /// -3200 /// The timer must fire if either: -3201 /// - An ack-eliciting packet we sent needs to be declared lost. -3202 /// - A tail-loss probe needs to be sent. -3203 /// -3204 /// See [`Connection::on_loss_detection_timeout`] for details. -3205 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) { -3206 if self.state.is_closed() { -3207 // No loss detection takes place on closed connections, and `close_common` already -3208 // stopped time timer. Ensure we don't restart it inadvertently, e.g. in response to a -3209 // reordered packet being handled by state-insensitive code. -3210 return; -3211 } -3212 -3213 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) { -3214 // Time threshold loss detection. -3215 self.timers.set( -3216 Timer::PerPath(path_id, PathTimer::LossDetection), -3217 loss_time, -3218 self.qlog.with_time(now), -3219 ); -3220 return; -3221 } -3222 -3223 // Determine which PN space to arm PTO for. -3224 // Calculate PTO duration -3225 if let Some((timeout, _)) = self.pto_time_and_space(now, path_id) { -3226 self.timers.set( -3227 Timer::PerPath(path_id, PathTimer::LossDetection), -3228 timeout, -3229 self.qlog.with_time(now), -3230 ); -3231 } else { -3232 self.timers.stop( -3233 Timer::PerPath(path_id, PathTimer::LossDetection), +3056 if self.datagrams.drop_oversized(max_datagram_size) +3057 && self.datagrams.send_blocked +3058 { +3059 self.datagrams.send_blocked = false; +3060 self.events.push_back(Event::DatagramsUnblocked); +3061 } +3062 } +3063 self.path_stats +3064 .entry(path_id) +3065 .or_default() +3066 .black_holes_detected += 1; +3067 } +3068 +3069 // Don't apply congestion penalty for lost ack-only packets +3070 let lost_ack_eliciting = +3071 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes; +3072 +3073 if lost_ack_eliciting { +3074 self.path_stats +3075 .entry(path_id) +3076 .or_default() +3077 .congestion_events += 1; +3078 self.path_data_mut(path_id).congestion.on_congestion_event( +3079 now, +3080 largest_lost_sent, +3081 in_persistent_congestion, +3082 false, +3083 size_of_lost_packets, +3084 ); +3085 } +3086 } +3087 +3088 // Handle a lost MTU probe +3089 if let Some(packet) = lost_mtu_probe { +3090 let info = self.spaces[SpaceId::Data] +3091 .for_path(path_id) +3092 .take(packet) +3093 .unwrap(); // safe: lost_mtu_probe is omitted from lost_packets, and +3094 // therefore must not have been removed yet +3095 self.paths +3096 .get_mut(&path_id) +3097 .unwrap() +3098 .remove_in_flight(&info); +3099 self.path_data_mut(path_id).mtud.on_probe_lost(); +3100 self.path_stats +3101 .entry(path_id) +3102 .or_default() +3103 .lost_plpmtud_probes += 1; +3104 } +3105 } +3106 +3107 /// Returns the earliest time packets should be declared lost for all spaces on a path. +3108 /// +3109 /// If a path has an acknowledged packet with any prior un-acknowledged packets, the +3110 /// earliest un-acknowledged packet can be declared lost after a timeout has elapsed. +3111 /// The time returned is when this packet should be declared lost. +3112 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> { +3113 SpaceId::iter() +3114 .filter_map(|id| { +3115 self.spaces[id] +3116 .number_spaces +3117 .get(&path_id) +3118 .and_then(|pns| pns.loss_time) +3119 .map(|time| (time, id)) +3120 }) +3121 .min_by_key(|&(time, _)| time) +3122 } +3123 +3124 /// Returns the earliest next PTO should fire for all spaces on a path. +3125 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> { +3126 let path = self.path(path_id)?; +3127 let pto_count = path.pto_count; +3128 let backoff = 2u32.pow(pto_count.min(MAX_BACKOFF_EXPONENT)); +3129 let mut duration = path.rtt.pto_base() * backoff; +3130 +3131 if path_id == PathId::ZERO +3132 && path.in_flight.ack_eliciting == 0 +3133 && !self.peer_completed_address_validation(PathId::ZERO) +3134 { +3135 // Address Validation during Connection Establishment: +3136 // https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1. To prevent a +3137 // deadlock if an Initial or Handshake packet from the server is lost and the +3138 // server can not send more due to its anti-amplification limit the client must +3139 // send another packet on PTO. +3140 let space = match self.highest_space { +3141 SpaceId::Handshake => SpaceId::Handshake, +3142 _ => SpaceId::Initial, +3143 }; +3144 +3145 return Some((now + duration, space)); +3146 } +3147 +3148 let mut result = None; +3149 for space in SpaceId::iter() { +3150 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else { +3151 continue; +3152 }; +3153 +3154 if !pns.has_in_flight() { +3155 continue; +3156 } +3157 if space == SpaceId::Data { +3158 // Skip ApplicationData until handshake completes. +3159 if self.is_handshaking() { +3160 return result; +3161 } +3162 // Include max_ack_delay and backoff for ApplicationData. +3163 duration += self.ack_frequency.max_ack_delay_for_pto() * backoff; +3164 } +3165 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else { +3166 continue; +3167 }; +3168 let pto = last_ack_eliciting + duration; +3169 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) { +3170 if path.anti_amplification_blocked(1) { +3171 // Nothing would be able to be sent. +3172 continue; +3173 } +3174 if path.in_flight.ack_eliciting == 0 { +3175 // Nothing ack-eliciting, no PTO to arm/fire. +3176 continue; +3177 } +3178 result = Some((pto, space)); +3179 } +3180 } +3181 result +3182 } +3183 +3184 fn peer_completed_address_validation(&self, path: PathId) -> bool { +3185 // TODO(flub): This logic needs updating for multipath +3186 if self.side.is_server() || self.state.is_closed() { +3187 return true; +3188 } +3189 // The server is guaranteed to have validated our address if any of our handshake or 1-RTT +3190 // packets are acknowledged or we've seen HANDSHAKE_DONE and discarded handshake keys. +3191 self.spaces[SpaceId::Handshake] +3192 .path_space(PathId::ZERO) +3193 .and_then(|pns| pns.largest_acked_packet) +3194 .is_some() +3195 || self.spaces[SpaceId::Data] +3196 .path_space(path) +3197 .and_then(|pns| pns.largest_acked_packet) +3198 .is_some() +3199 || (self.spaces[SpaceId::Data].crypto.is_some() +3200 && self.spaces[SpaceId::Handshake].crypto.is_none()) +3201 } +3202 +3203 /// Resets the the [`PathTimer::LossDetection`] timer to the next instant it may be needed +3204 /// +3205 /// The timer must fire if either: +3206 /// - An ack-eliciting packet we sent needs to be declared lost. +3207 /// - A tail-loss probe needs to be sent. +3208 /// +3209 /// See [`Connection::on_loss_detection_timeout`] for details. +3210 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) { +3211 if self.state.is_closed() { +3212 // No loss detection takes place on closed connections, and `close_common` already +3213 // stopped time timer. Ensure we don't restart it inadvertently, e.g. in response to a +3214 // reordered packet being handled by state-insensitive code. +3215 return; +3216 } +3217 +3218 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) { +3219 // Time threshold loss detection. +3220 self.timers.set( +3221 Timer::PerPath(path_id, PathTimer::LossDetection), +3222 loss_time, +3223 self.qlog.with_time(now), +3224 ); +3225 return; +3226 } +3227 +3228 // Determine which PN space to arm PTO for. +3229 // Calculate PTO duration +3230 if let Some((timeout, _)) = self.pto_time_and_space(now, path_id) { +3231 self.timers.set( +3232 Timer::PerPath(path_id, PathTimer::LossDetection), +3233 timeout, 3234 self.qlog.with_time(now), 3235 ); -3236 } -3237 } -3238 -3239 /// The maximum probe timeout across all paths -3240 /// -3241 /// If `is_closing` is set to `true` it will filter out paths that have not yet been used. -3242 /// -3243 /// See [`Connection::pto`] -3244 fn pto_max_path(&self, space: SpaceId, is_closing: bool) -> Duration { -3245 match space { -3246 SpaceId::Initial | SpaceId::Handshake => self.pto(space, PathId::ZERO), -3247 SpaceId::Data => self -3248 .paths -3249 .iter() -3250 .filter_map(|(path_id, state)| { -3251 if is_closing && state.data.total_sent == 0 && state.data.total_recvd == 0 { -3252 // If we are closing and haven't sent anything yet, do not include -3253 None -3254 } else { -3255 let pto = self.pto(space, *path_id); -3256 Some(pto) -3257 } -3258 }) -3259 .max() -3260 .expect("there should be one at least path"), -3261 } -3262 } -3263 -3264 /// Probe Timeout -3265 /// -3266 /// The PTO is logically the time in which you'd expect to receive an acknowledgement -3267 /// for a packet. So approximately RTT + max_ack_delay. -3268 fn pto(&self, space: SpaceId, path_id: PathId) -> Duration { -3269 let max_ack_delay = match space { -3270 SpaceId::Initial | SpaceId::Handshake => Duration::ZERO, -3271 SpaceId::Data => self.ack_frequency.max_ack_delay_for_pto(), -3272 }; -3273 self.path_data(path_id).rtt.pto_base() + max_ack_delay -3274 } -3275 -3276 fn on_packet_authenticated( -3277 &mut self, -3278 now: Instant, -3279 space_id: SpaceId, -3280 path_id: PathId, -3281 ecn: Option<EcnCodepoint>, -3282 packet: Option<u64>, -3283 spin: bool, -3284 is_1rtt: bool, -3285 ) { -3286 self.total_authed_packets += 1; -3287 if let Some(last_allowed_receive) = self -3288 .paths -3289 .get(&path_id) -3290 .and_then(|path| path.data.last_allowed_receive) -3291 { -3292 if now > last_allowed_receive { -3293 warn!("received data on path which we abandoned more than 3 * PTO ago"); -3294 // The peer failed to respond with a PATH_ABANDON in time. -3295 if !self.state.is_closed() { -3296 // TODO(flub): What should the error code be? -3297 self.state.move_to_closed(TransportError::NO_ERROR( -3298 "peer failed to respond with PATH_ABANDON in time", -3299 )); -3300 self.close_common(); -3301 self.set_close_timer(now); -3302 self.close = true; -3303 } -3304 return; -3305 } -3306 } -3307 -3308 self.reset_keep_alive(path_id, now); -3309 self.reset_idle_timeout(now, space_id, path_id); -3310 self.permit_idle_reset = true; -3311 self.receiving_ecn |= ecn.is_some(); -3312 if let Some(x) = ecn { -3313 let space = &mut self.spaces[space_id]; -3314 space.for_path(path_id).ecn_counters += x; -3315 -3316 if x.is_ce() { -3317 space -3318 .for_path(path_id) -3319 .pending_acks -3320 .set_immediate_ack_required(); -3321 } -3322 } -3323 -3324 let packet = match packet { -3325 Some(x) => x, -3326 None => return, -3327 }; -3328 match &self.side { -3329 ConnectionSide::Client { .. } => { -3330 // If we received a handshake packet that authenticated, then we're talking to -3331 // the real server. From now on we should no longer allow the server to migrate -3332 // its address. -3333 if space_id == SpaceId::Handshake { -3334 if let Some(hs) = self.state.as_handshake_mut() { -3335 hs.allow_server_migration = false; -3336 } -3337 } -3338 } -3339 ConnectionSide::Server { .. } => { -3340 if self.spaces[SpaceId::Initial].crypto.is_some() && space_id == SpaceId::Handshake -3341 { -3342 // A server stops sending and processing Initial packets when it receives its first Handshake packet. -3343 self.discard_space(now, SpaceId::Initial); -3344 } -3345 if self.zero_rtt_crypto.is_some() && is_1rtt { -3346 // Discard 0-RTT keys soon after receiving a 1-RTT packet -3347 self.set_key_discard_timer(now, space_id) -3348 } -3349 } -3350 } -3351 let space = self.spaces[space_id].for_path(path_id); -3352 space.pending_acks.insert_one(packet, now); -3353 if packet >= space.rx_packet.unwrap_or_default() { -3354 space.rx_packet = Some(packet); -3355 // Update outgoing spin bit, inverting iff we're the client -3356 self.spin = self.side.is_client() ^ spin; -3357 } -3358 } -3359 -3360 /// Resets the idle timeout timers -3361 /// -3362 /// Without multipath there is only the connection-wide idle timeout. When multipath is -3363 /// enabled there is an additional per-path idle timeout. -3364 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceId, path_id: PathId) { -3365 // First reset the global idle timeout. -3366 if let Some(timeout) = self.idle_timeout { -3367 if self.state.is_closed() { -3368 self.timers -3369 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)); -3370 } else { -3371 let dt = cmp::max(timeout, 3 * self.pto_max_path(space, false)); -3372 self.timers.set( -3373 Timer::Conn(ConnTimer::Idle), -3374 now + dt, -3375 self.qlog.with_time(now), -3376 ); -3377 } -3378 } -3379 -3380 // Now handle the per-path state -3381 if let Some(timeout) = self.path_data(path_id).idle_timeout { -3382 if self.state.is_closed() { -3383 self.timers.stop( -3384 Timer::PerPath(path_id, PathTimer::PathIdle), -3385 self.qlog.with_time(now), -3386 ); -3387 } else { -3388 let dt = cmp::max(timeout, 3 * self.pto(space, path_id)); -3389 self.timers.set( -3390 Timer::PerPath(path_id, PathTimer::PathIdle), -3391 now + dt, -3392 self.qlog.with_time(now), -3393 ); -3394 } -3395 } -3396 } -3397 -3398 /// Resets both the [`ConnTimer::KeepAlive`] and [`PathTimer::PathKeepAlive`] timers -3399 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) { -3400 if !self.state.is_established() { -3401 return; -3402 } -3403 -3404 if let Some(interval) = self.config.keep_alive_interval { -3405 self.timers.set( -3406 Timer::Conn(ConnTimer::KeepAlive), -3407 now + interval, -3408 self.qlog.with_time(now), -3409 ); -3410 } -3411 -3412 if let Some(interval) = self.path_data(path_id).keep_alive { -3413 self.timers.set( -3414 Timer::PerPath(path_id, PathTimer::PathKeepAlive), -3415 now + interval, -3416 self.qlog.with_time(now), -3417 ); -3418 } -3419 } -3420 -3421 /// Sets the timer for when a previously issued CID should be retired next -3422 fn reset_cid_retirement(&mut self, now: Instant) { -3423 if let Some((_path, t)) = self.next_cid_retirement() { -3424 self.timers.set( -3425 Timer::Conn(ConnTimer::PushNewCid), -3426 t, -3427 self.qlog.with_time(now), -3428 ); -3429 } -3430 } -3431 -3432 /// The next time when a previously issued CID should be retired -3433 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> { -3434 self.local_cid_state -3435 .iter() -3436 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t))) -3437 .min_by_key(|(_path_id, timeout)| *timeout) -3438 } -3439 -3440 /// Handle the already-decrypted first packet from the client -3441 /// -3442 /// Decrypting the first packet in the `Endpoint` allows stateless packet handling to be more -3443 /// efficient. -3444 pub(crate) fn handle_first_packet( -3445 &mut self, -3446 now: Instant, -3447 network_path: FourTuple, -3448 ecn: Option<EcnCodepoint>, -3449 packet_number: u64, -3450 packet: InitialPacket, -3451 remaining: Option<BytesMut>, -3452 ) -> Result<(), ConnectionError> { -3453 let span = trace_span!("first recv"); -3454 let _guard = span.enter(); -3455 debug_assert!(self.side.is_server()); -3456 let len = packet.header_data.len() + packet.payload.len(); -3457 let path_id = PathId::ZERO; -3458 self.path_data_mut(path_id).total_recvd = len as u64; -3459 -3460 if let Some(hs) = self.state.as_handshake_mut() { -3461 hs.expected_token = packet.header.token.clone(); -3462 } else { -3463 unreachable!("first packet must be delivered in Handshake state"); -3464 } -3465 -3466 // The first packet is always on PathId::ZERO -3467 self.on_packet_authenticated( -3468 now, -3469 SpaceId::Initial, -3470 path_id, -3471 ecn, -3472 Some(packet_number), -3473 false, -3474 false, -3475 ); -3476 -3477 let packet: Packet = packet.into(); -3478 -3479 let mut qlog = QlogRecvPacket::new(len); -3480 qlog.header(&packet.header, Some(packet_number), path_id); +3236 } else { +3237 self.timers.stop( +3238 Timer::PerPath(path_id, PathTimer::LossDetection), +3239 self.qlog.with_time(now), +3240 ); +3241 } +3242 } +3243 +3244 /// The maximum probe timeout across all paths +3245 /// +3246 /// If `is_closing` is set to `true` it will filter out paths that have not yet been used. +3247 /// +3248 /// See [`Connection::pto`] +3249 fn pto_max_path(&self, space: SpaceId, is_closing: bool) -> Duration { +3250 match space { +3251 SpaceId::Initial | SpaceId::Handshake => self.pto(space, PathId::ZERO), +3252 SpaceId::Data => self +3253 .paths +3254 .iter() +3255 .filter_map(|(path_id, state)| { +3256 if is_closing && state.data.total_sent == 0 && state.data.total_recvd == 0 { +3257 // If we are closing and haven't sent anything yet, do not include +3258 None +3259 } else { +3260 let pto = self.pto(space, *path_id); +3261 Some(pto) +3262 } +3263 }) +3264 .max() +3265 .expect("there should be one at least path"), +3266 } +3267 } +3268 +3269 /// Probe Timeout +3270 /// +3271 /// The PTO is logically the time in which you'd expect to receive an acknowledgement +3272 /// for a packet. So approximately RTT + max_ack_delay. +3273 fn pto(&self, space: SpaceId, path_id: PathId) -> Duration { +3274 let max_ack_delay = match space { +3275 SpaceId::Initial | SpaceId::Handshake => Duration::ZERO, +3276 SpaceId::Data => self.ack_frequency.max_ack_delay_for_pto(), +3277 }; +3278 self.path_data(path_id).rtt.pto_base() + max_ack_delay +3279 } +3280 +3281 fn on_packet_authenticated( +3282 &mut self, +3283 now: Instant, +3284 space_id: SpaceId, +3285 path_id: PathId, +3286 ecn: Option<EcnCodepoint>, +3287 packet: Option<u64>, +3288 spin: bool, +3289 is_1rtt: bool, +3290 ) { +3291 self.total_authed_packets += 1; +3292 if let Some(last_allowed_receive) = self +3293 .paths +3294 .get(&path_id) +3295 .and_then(|path| path.data.last_allowed_receive) +3296 { +3297 if now > last_allowed_receive { +3298 warn!("received data on path which we abandoned more than 3 * PTO ago"); +3299 // The peer failed to respond with a PATH_ABANDON in time. +3300 if !self.state.is_closed() { +3301 // TODO(flub): What should the error code be? +3302 self.state.move_to_closed(TransportError::NO_ERROR( +3303 "peer failed to respond with PATH_ABANDON in time", +3304 )); +3305 self.close_common(); +3306 self.set_close_timer(now); +3307 self.close = true; +3308 } +3309 return; +3310 } +3311 } +3312 +3313 self.reset_keep_alive(path_id, now); +3314 self.reset_idle_timeout(now, space_id, path_id); +3315 self.permit_idle_reset = true; +3316 self.receiving_ecn |= ecn.is_some(); +3317 if let Some(x) = ecn { +3318 let space = &mut self.spaces[space_id]; +3319 space.for_path(path_id).ecn_counters += x; +3320 +3321 if x.is_ce() { +3322 space +3323 .for_path(path_id) +3324 .pending_acks +3325 .set_immediate_ack_required(); +3326 } +3327 } +3328 +3329 let packet = match packet { +3330 Some(x) => x, +3331 None => return, +3332 }; +3333 match &self.side { +3334 ConnectionSide::Client { .. } => { +3335 // If we received a handshake packet that authenticated, then we're talking to +3336 // the real server. From now on we should no longer allow the server to migrate +3337 // its address. +3338 if space_id == SpaceId::Handshake { +3339 if let Some(hs) = self.state.as_handshake_mut() { +3340 hs.allow_server_migration = false; +3341 } +3342 } +3343 } +3344 ConnectionSide::Server { .. } => { +3345 if self.spaces[SpaceId::Initial].crypto.is_some() && space_id == SpaceId::Handshake +3346 { +3347 // A server stops sending and processing Initial packets when it receives its first Handshake packet. +3348 self.discard_space(now, SpaceId::Initial); +3349 } +3350 if self.zero_rtt_crypto.is_some() && is_1rtt { +3351 // Discard 0-RTT keys soon after receiving a 1-RTT packet +3352 self.set_key_discard_timer(now, space_id) +3353 } +3354 } +3355 } +3356 let space = self.spaces[space_id].for_path(path_id); +3357 space.pending_acks.insert_one(packet, now); +3358 if packet >= space.rx_packet.unwrap_or_default() { +3359 space.rx_packet = Some(packet); +3360 // Update outgoing spin bit, inverting iff we're the client +3361 self.spin = self.side.is_client() ^ spin; +3362 } +3363 } +3364 +3365 /// Resets the idle timeout timers +3366 /// +3367 /// Without multipath there is only the connection-wide idle timeout. When multipath is +3368 /// enabled there is an additional per-path idle timeout. +3369 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceId, path_id: PathId) { +3370 // First reset the global idle timeout. +3371 if let Some(timeout) = self.idle_timeout { +3372 if self.state.is_closed() { +3373 self.timers +3374 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)); +3375 } else { +3376 let dt = cmp::max(timeout, 3 * self.pto_max_path(space, false)); +3377 self.timers.set( +3378 Timer::Conn(ConnTimer::Idle), +3379 now + dt, +3380 self.qlog.with_time(now), +3381 ); +3382 } +3383 } +3384 +3385 // Now handle the per-path state +3386 if let Some(timeout) = self.path_data(path_id).idle_timeout { +3387 if self.state.is_closed() { +3388 self.timers.stop( +3389 Timer::PerPath(path_id, PathTimer::PathIdle), +3390 self.qlog.with_time(now), +3391 ); +3392 } else { +3393 let dt = cmp::max(timeout, 3 * self.pto(space, path_id)); +3394 self.timers.set( +3395 Timer::PerPath(path_id, PathTimer::PathIdle), +3396 now + dt, +3397 self.qlog.with_time(now), +3398 ); +3399 } +3400 } +3401 } +3402 +3403 /// Resets both the [`ConnTimer::KeepAlive`] and [`PathTimer::PathKeepAlive`] timers +3404 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) { +3405 if !self.state.is_established() { +3406 return; +3407 } +3408 +3409 if let Some(interval) = self.config.keep_alive_interval { +3410 self.timers.set( +3411 Timer::Conn(ConnTimer::KeepAlive), +3412 now + interval, +3413 self.qlog.with_time(now), +3414 ); +3415 } +3416 +3417 if let Some(interval) = self.path_data(path_id).keep_alive { +3418 self.timers.set( +3419 Timer::PerPath(path_id, PathTimer::PathKeepAlive), +3420 now + interval, +3421 self.qlog.with_time(now), +3422 ); +3423 } +3424 } +3425 +3426 /// Sets the timer for when a previously issued CID should be retired next +3427 fn reset_cid_retirement(&mut self, now: Instant) { +3428 if let Some((_path, t)) = self.next_cid_retirement() { +3429 self.timers.set( +3430 Timer::Conn(ConnTimer::PushNewCid), +3431 t, +3432 self.qlog.with_time(now), +3433 ); +3434 } +3435 } +3436 +3437 /// The next time when a previously issued CID should be retired +3438 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> { +3439 self.local_cid_state +3440 .iter() +3441 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t))) +3442 .min_by_key(|(_path_id, timeout)| *timeout) +3443 } +3444 +3445 /// Handle the already-decrypted first packet from the client +3446 /// +3447 /// Decrypting the first packet in the `Endpoint` allows stateless packet handling to be more +3448 /// efficient. +3449 pub(crate) fn handle_first_packet( +3450 &mut self, +3451 now: Instant, +3452 network_path: FourTuple, +3453 ecn: Option<EcnCodepoint>, +3454 packet_number: u64, +3455 packet: InitialPacket, +3456 remaining: Option<BytesMut>, +3457 ) -> Result<(), ConnectionError> { +3458 let span = trace_span!("first recv"); +3459 let _guard = span.enter(); +3460 debug_assert!(self.side.is_server()); +3461 let len = packet.header_data.len() + packet.payload.len(); +3462 let path_id = PathId::ZERO; +3463 self.path_data_mut(path_id).total_recvd = len as u64; +3464 +3465 if let Some(hs) = self.state.as_handshake_mut() { +3466 hs.expected_token = packet.header.token.clone(); +3467 } else { +3468 unreachable!("first packet must be delivered in Handshake state"); +3469 } +3470 +3471 // The first packet is always on PathId::ZERO +3472 self.on_packet_authenticated( +3473 now, +3474 SpaceId::Initial, +3475 path_id, +3476 ecn, +3477 Some(packet_number), +3478 false, +3479 false, +3480 ); 3481 -3482 self.process_decrypted_packet( -3483 now, -3484 network_path, -3485 path_id, -3486 Some(packet_number), -3487 packet, -3488 &mut qlog, -3489 )?; -3490 self.qlog.emit_packet_received(qlog, now); -3491 if let Some(data) = remaining { -3492 self.handle_coalesced(now, network_path, path_id, ecn, data); -3493 } -3494 -3495 self.qlog.emit_recovery_metrics( -3496 path_id, -3497 &mut self.paths.get_mut(&path_id).unwrap().data, -3498 now, -3499 ); -3500 -3501 Ok(()) -3502 } -3503 -3504 fn init_0rtt(&mut self, now: Instant) { -3505 let (header, packet) = match self.crypto.early_crypto() { -3506 Some(x) => x, -3507 None => return, -3508 }; -3509 if self.side.is_client() { -3510 match self.crypto.transport_parameters() { -3511 Ok(params) => { -3512 let params = params -3513 .expect("crypto layer didn't supply transport parameters with ticket"); -3514 // Certain values must not be cached -3515 let params = TransportParameters { -3516 initial_src_cid: None, -3517 original_dst_cid: None, -3518 preferred_address: None, -3519 retry_src_cid: None, -3520 stateless_reset_token: None, -3521 min_ack_delay: None, -3522 ack_delay_exponent: TransportParameters::default().ack_delay_exponent, -3523 max_ack_delay: TransportParameters::default().max_ack_delay, -3524 initial_max_path_id: None, -3525 ..params -3526 }; -3527 self.set_peer_params(params); -3528 self.qlog.emit_peer_transport_params_restored(self, now); -3529 } -3530 Err(e) => { -3531 error!("session ticket has malformed transport parameters: {}", e); -3532 return; -3533 } -3534 } -3535 } -3536 trace!("0-RTT enabled"); -3537 self.zero_rtt_enabled = true; -3538 self.zero_rtt_crypto = Some(ZeroRttCrypto { header, packet }); -3539 } -3540 -3541 fn read_crypto( -3542 &mut self, -3543 space: SpaceId, -3544 crypto: &frame::Crypto, -3545 payload_len: usize, -3546 ) -> Result<(), TransportError> { -3547 let expected = if !self.state.is_handshake() { -3548 SpaceId::Data -3549 } else if self.highest_space == SpaceId::Initial { -3550 SpaceId::Initial -3551 } else { -3552 // On the server, self.highest_space can be Data after receiving the client's first -3553 // flight, but we expect Handshake CRYPTO until the handshake is complete. -3554 SpaceId::Handshake -3555 }; -3556 // We can't decrypt Handshake packets when highest_space is Initial, CRYPTO frames in 0-RTT -3557 // packets are illegal, and we don't process 1-RTT packets until the handshake is -3558 // complete. Therefore, we will never see CRYPTO data from a later-than-expected space. -3559 debug_assert!(space <= expected, "received out-of-order CRYPTO data"); -3560 -3561 let end = crypto.offset + crypto.data.len() as u64; -3562 if space < expected && end > self.spaces[space].crypto_stream.bytes_read() { -3563 warn!( -3564 "received new {:?} CRYPTO data when expecting {:?}", -3565 space, expected -3566 ); -3567 return Err(TransportError::PROTOCOL_VIOLATION( -3568 "new data at unexpected encryption level", -3569 )); -3570 } -3571 -3572 let space = &mut self.spaces[space]; -3573 let max = end.saturating_sub(space.crypto_stream.bytes_read()); -3574 if max > self.config.crypto_buffer_size as u64 { -3575 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED("")); -3576 } -3577 -3578 space -3579 .crypto_stream -3580 .insert(crypto.offset, crypto.data.clone(), payload_len); -3581 while let Some(chunk) = space.crypto_stream.read(usize::MAX, true) { -3582 trace!("consumed {} CRYPTO bytes", chunk.bytes.len()); -3583 if self.crypto.read_handshake(&chunk.bytes)? { -3584 self.events.push_back(Event::HandshakeDataReady); -3585 } -3586 } -3587 -3588 Ok(()) -3589 } -3590 -3591 fn write_crypto(&mut self) { -3592 loop { -3593 let space = self.highest_space; -3594 let mut outgoing = Vec::new(); -3595 if let Some(crypto) = self.crypto.write_handshake(&mut outgoing) { -3596 match space { -3597 SpaceId::Initial => { -3598 self.upgrade_crypto(SpaceId::Handshake, crypto); -3599 } -3600 SpaceId::Handshake => { -3601 self.upgrade_crypto(SpaceId::Data, crypto); -3602 } -3603 _ => unreachable!("got updated secrets during 1-RTT"), -3604 } -3605 } -3606 if outgoing.is_empty() { -3607 if space == self.highest_space { -3608 break; -3609 } else { -3610 // Keys updated, check for more data to send -3611 continue; -3612 } -3613 } -3614 let offset = self.spaces[space].crypto_offset; -3615 let outgoing = Bytes::from(outgoing); -3616 if let Some(hs) = self.state.as_handshake_mut() { -3617 if space == SpaceId::Initial && offset == 0 && self.side.is_client() { -3618 hs.client_hello = Some(outgoing.clone()); -3619 } -3620 } -3621 self.spaces[space].crypto_offset += outgoing.len() as u64; -3622 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space); -3623 self.spaces[space].pending.crypto.push_back(frame::Crypto { -3624 offset, -3625 data: outgoing, -3626 }); -3627 } -3628 } -3629 -3630 /// Switch to stronger cryptography during handshake -3631 fn upgrade_crypto(&mut self, space: SpaceId, crypto: Keys) { -3632 debug_assert!( -3633 self.spaces[space].crypto.is_none(), -3634 "already reached packet space {space:?}" -3635 ); -3636 trace!("{:?} keys ready", space); -3637 if space == SpaceId::Data { -3638 // Precompute the first key update -3639 self.next_crypto = Some( -3640 self.crypto -3641 .next_1rtt_keys() -3642 .expect("handshake should be complete"), -3643 ); -3644 } -3645 -3646 self.spaces[space].crypto = Some(crypto); -3647 debug_assert!(space as usize > self.highest_space as usize); -3648 self.highest_space = space; -3649 if space == SpaceId::Data && self.side.is_client() { -3650 // Discard 0-RTT keys because 1-RTT keys are available. -3651 self.zero_rtt_crypto = None; -3652 } -3653 } -3654 -3655 fn discard_space(&mut self, now: Instant, space_id: SpaceId) { -3656 debug_assert!(space_id != SpaceId::Data); -3657 trace!("discarding {:?} keys", space_id); -3658 if space_id == SpaceId::Initial { -3659 // No longer needed -3660 if let ConnectionSide::Client { token, .. } = &mut self.side { -3661 *token = Bytes::new(); -3662 } -3663 } -3664 let space = &mut self.spaces[space_id]; -3665 space.crypto = None; -3666 let pns = space.for_path(PathId::ZERO); -3667 pns.time_of_last_ack_eliciting_packet = None; -3668 pns.loss_time = None; -3669 pns.loss_probes = 0; -3670 let sent_packets = mem::take(&mut pns.sent_packets); -3671 let path = self.paths.get_mut(&PathId::ZERO).unwrap(); -3672 for (_, packet) in sent_packets.into_iter() { -3673 path.data.remove_in_flight(&packet); -3674 } -3675 -3676 self.set_loss_detection_timer(now, PathId::ZERO) -3677 } -3678 -3679 fn handle_coalesced( -3680 &mut self, -3681 now: Instant, -3682 network_path: FourTuple, -3683 path_id: PathId, -3684 ecn: Option<EcnCodepoint>, -3685 data: BytesMut, -3686 ) { -3687 self.path_data_mut(path_id) -3688 .inc_total_recvd(data.len() as u64); -3689 let mut remaining = Some(data); -3690 let cid_len = self -3691 .local_cid_state -3692 .values() -3693 .map(|cid_state| cid_state.cid_len()) -3694 .next() -3695 .expect("one cid_state must exist"); -3696 while let Some(data) = remaining { -3697 match PartialDecode::new( -3698 data, -3699 &FixedLengthConnectionIdParser::new(cid_len), -3700 &[self.version], -3701 self.endpoint_config.grease_quic_bit, -3702 ) { -3703 Ok((partial_decode, rest)) => { -3704 remaining = rest; -3705 self.handle_decode(now, network_path, path_id, ecn, partial_decode); -3706 } -3707 Err(e) => { -3708 trace!("malformed header: {}", e); -3709 return; -3710 } -3711 } -3712 } -3713 } -3714 -3715 fn handle_decode( -3716 &mut self, -3717 now: Instant, -3718 network_path: FourTuple, -3719 path_id: PathId, -3720 ecn: Option<EcnCodepoint>, -3721 partial_decode: PartialDecode, -3722 ) { -3723 let qlog = QlogRecvPacket::new(partial_decode.len()); -3724 if let Some(decoded) = packet_crypto::unprotect_header( -3725 partial_decode, -3726 &self.spaces, -3727 self.zero_rtt_crypto.as_ref(), -3728 self.peer_params.stateless_reset_token, -3729 ) { -3730 self.handle_packet( -3731 now, -3732 network_path, -3733 path_id, -3734 ecn, -3735 decoded.packet, -3736 decoded.stateless_reset, -3737 qlog, -3738 ); -3739 } -3740 } -3741 -3742 fn handle_packet( -3743 &mut self, -3744 now: Instant, -3745 network_path: FourTuple, -3746 path_id: PathId, -3747 ecn: Option<EcnCodepoint>, -3748 packet: Option<Packet>, -3749 stateless_reset: bool, -3750 mut qlog: QlogRecvPacket, -3751 ) { -3752 self.stats.udp_rx.ios += 1; -3753 if let Some(ref packet) = packet { -3754 trace!( -3755 "got {:?} packet ({} bytes) from {} using id {}", -3756 packet.header.space(), -3757 packet.payload.len() + packet.header_data.len(), -3758 network_path, -3759 packet.header.dst_cid(), -3760 ); -3761 } -3762 -3763 if self.is_handshaking() { -3764 if path_id != PathId::ZERO { -3765 debug!(%network_path, %path_id, "discarding multipath packet during handshake"); -3766 return; -3767 } -3768 if network_path != self.path_data_mut(path_id).network_path { -3769 if let Some(hs) = self.state.as_handshake() { -3770 if hs.allow_server_migration { -3771 trace!(%network_path, prev = %self.path_data(path_id).network_path, "server migrated to new remote"); -3772 self.path_data_mut(path_id).network_path = network_path; -3773 self.qlog.emit_tuple_assigned(path_id, network_path, now); -3774 } else { -3775 debug!("discarding packet with unexpected remote during handshake"); -3776 return; -3777 } -3778 } else { -3779 debug!("discarding packet with unexpected remote during handshake"); -3780 return; -3781 } -3782 } -3783 } -3784 -3785 let was_closed = self.state.is_closed(); -3786 let was_drained = self.state.is_drained(); -3787 -3788 let decrypted = match packet { -3789 None => Err(None), -3790 Some(mut packet) => self -3791 .decrypt_packet(now, path_id, &mut packet) -3792 .map(move |number| (packet, number)), -3793 }; -3794 let result = match decrypted { -3795 _ if stateless_reset => { -3796 debug!("got stateless reset"); -3797 Err(ConnectionError::Reset) -3798 } -3799 Err(Some(e)) => { -3800 warn!("illegal packet: {}", e); -3801 Err(e.into()) -3802 } -3803 Err(None) => { -3804 debug!("failed to authenticate packet"); -3805 self.authentication_failures += 1; -3806 let integrity_limit = self.spaces[self.highest_space] -3807 .crypto -3808 .as_ref() -3809 .unwrap() -3810 .packet -3811 .local -3812 .integrity_limit(); -3813 if self.authentication_failures > integrity_limit { -3814 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into()) -3815 } else { -3816 return; -3817 } -3818 } -3819 Ok((packet, number)) => { -3820 qlog.header(&packet.header, number, path_id); -3821 let span = match number { -3822 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn), -3823 None => trace_span!("recv", space = ?packet.header.space()), -3824 }; -3825 let _guard = span.enter(); -3826 -3827 let dedup = self.spaces[packet.header.space()] -3828 .path_space_mut(path_id) -3829 .map(|pns| &mut pns.dedup); -3830 if number.zip(dedup).is_some_and(|(n, d)| d.insert(n)) { -3831 debug!("discarding possible duplicate packet"); -3832 self.qlog.emit_packet_received(qlog, now); -3833 return; -3834 } else if self.state.is_handshake() && packet.header.is_short() { -3835 // TODO: SHOULD buffer these to improve reordering tolerance. -3836 trace!("dropping short packet during handshake"); +3482 let packet: Packet = packet.into(); +3483 +3484 let mut qlog = QlogRecvPacket::new(len); +3485 qlog.header(&packet.header, Some(packet_number), path_id); +3486 +3487 self.process_decrypted_packet( +3488 now, +3489 network_path, +3490 path_id, +3491 Some(packet_number), +3492 packet, +3493 &mut qlog, +3494 )?; +3495 self.qlog.emit_packet_received(qlog, now); +3496 if let Some(data) = remaining { +3497 self.handle_coalesced(now, network_path, path_id, ecn, data); +3498 } +3499 +3500 self.qlog.emit_recovery_metrics( +3501 path_id, +3502 &mut self.paths.get_mut(&path_id).unwrap().data, +3503 now, +3504 ); +3505 +3506 Ok(()) +3507 } +3508 +3509 fn init_0rtt(&mut self, now: Instant) { +3510 let (header, packet) = match self.crypto.early_crypto() { +3511 Some(x) => x, +3512 None => return, +3513 }; +3514 if self.side.is_client() { +3515 match self.crypto.transport_parameters() { +3516 Ok(params) => { +3517 let params = params +3518 .expect("crypto layer didn't supply transport parameters with ticket"); +3519 // Certain values must not be cached +3520 let params = TransportParameters { +3521 initial_src_cid: None, +3522 original_dst_cid: None, +3523 preferred_address: None, +3524 retry_src_cid: None, +3525 stateless_reset_token: None, +3526 min_ack_delay: None, +3527 ack_delay_exponent: TransportParameters::default().ack_delay_exponent, +3528 max_ack_delay: TransportParameters::default().max_ack_delay, +3529 initial_max_path_id: None, +3530 ..params +3531 }; +3532 self.set_peer_params(params); +3533 self.qlog.emit_peer_transport_params_restored(self, now); +3534 } +3535 Err(e) => { +3536 error!("session ticket has malformed transport parameters: {}", e); +3537 return; +3538 } +3539 } +3540 } +3541 trace!("0-RTT enabled"); +3542 self.zero_rtt_enabled = true; +3543 self.zero_rtt_crypto = Some(ZeroRttCrypto { header, packet }); +3544 } +3545 +3546 fn read_crypto( +3547 &mut self, +3548 space: SpaceId, +3549 crypto: &frame::Crypto, +3550 payload_len: usize, +3551 ) -> Result<(), TransportError> { +3552 let expected = if !self.state.is_handshake() { +3553 SpaceId::Data +3554 } else if self.highest_space == SpaceId::Initial { +3555 SpaceId::Initial +3556 } else { +3557 // On the server, self.highest_space can be Data after receiving the client's first +3558 // flight, but we expect Handshake CRYPTO until the handshake is complete. +3559 SpaceId::Handshake +3560 }; +3561 // We can't decrypt Handshake packets when highest_space is Initial, CRYPTO frames in 0-RTT +3562 // packets are illegal, and we don't process 1-RTT packets until the handshake is +3563 // complete. Therefore, we will never see CRYPTO data from a later-than-expected space. +3564 debug_assert!(space <= expected, "received out-of-order CRYPTO data"); +3565 +3566 let end = crypto.offset + crypto.data.len() as u64; +3567 if space < expected && end > self.spaces[space].crypto_stream.bytes_read() { +3568 warn!( +3569 "received new {:?} CRYPTO data when expecting {:?}", +3570 space, expected +3571 ); +3572 return Err(TransportError::PROTOCOL_VIOLATION( +3573 "new data at unexpected encryption level", +3574 )); +3575 } +3576 +3577 let space = &mut self.spaces[space]; +3578 let max = end.saturating_sub(space.crypto_stream.bytes_read()); +3579 if max > self.config.crypto_buffer_size as u64 { +3580 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED("")); +3581 } +3582 +3583 space +3584 .crypto_stream +3585 .insert(crypto.offset, crypto.data.clone(), payload_len); +3586 while let Some(chunk) = space.crypto_stream.read(usize::MAX, true) { +3587 trace!("consumed {} CRYPTO bytes", chunk.bytes.len()); +3588 if self.crypto.read_handshake(&chunk.bytes)? { +3589 self.events.push_back(Event::HandshakeDataReady); +3590 } +3591 } +3592 +3593 Ok(()) +3594 } +3595 +3596 fn write_crypto(&mut self) { +3597 loop { +3598 let space = self.highest_space; +3599 let mut outgoing = Vec::new(); +3600 if let Some(crypto) = self.crypto.write_handshake(&mut outgoing) { +3601 match space { +3602 SpaceId::Initial => { +3603 self.upgrade_crypto(SpaceId::Handshake, crypto); +3604 } +3605 SpaceId::Handshake => { +3606 self.upgrade_crypto(SpaceId::Data, crypto); +3607 } +3608 _ => unreachable!("got updated secrets during 1-RTT"), +3609 } +3610 } +3611 if outgoing.is_empty() { +3612 if space == self.highest_space { +3613 break; +3614 } else { +3615 // Keys updated, check for more data to send +3616 continue; +3617 } +3618 } +3619 let offset = self.spaces[space].crypto_offset; +3620 let outgoing = Bytes::from(outgoing); +3621 if let Some(hs) = self.state.as_handshake_mut() { +3622 if space == SpaceId::Initial && offset == 0 && self.side.is_client() { +3623 hs.client_hello = Some(outgoing.clone()); +3624 } +3625 } +3626 self.spaces[space].crypto_offset += outgoing.len() as u64; +3627 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space); +3628 self.spaces[space].pending.crypto.push_back(frame::Crypto { +3629 offset, +3630 data: outgoing, +3631 }); +3632 } +3633 } +3634 +3635 /// Switch to stronger cryptography during handshake +3636 fn upgrade_crypto(&mut self, space: SpaceId, crypto: Keys) { +3637 debug_assert!( +3638 self.spaces[space].crypto.is_none(), +3639 "already reached packet space {space:?}" +3640 ); +3641 trace!("{:?} keys ready", space); +3642 if space == SpaceId::Data { +3643 // Precompute the first key update +3644 self.next_crypto = Some( +3645 self.crypto +3646 .next_1rtt_keys() +3647 .expect("handshake should be complete"), +3648 ); +3649 } +3650 +3651 self.spaces[space].crypto = Some(crypto); +3652 debug_assert!(space as usize > self.highest_space as usize); +3653 self.highest_space = space; +3654 if space == SpaceId::Data && self.side.is_client() { +3655 // Discard 0-RTT keys because 1-RTT keys are available. +3656 self.zero_rtt_crypto = None; +3657 } +3658 } +3659 +3660 fn discard_space(&mut self, now: Instant, space_id: SpaceId) { +3661 debug_assert!(space_id != SpaceId::Data); +3662 trace!("discarding {:?} keys", space_id); +3663 if space_id == SpaceId::Initial { +3664 // No longer needed +3665 if let ConnectionSide::Client { token, .. } = &mut self.side { +3666 *token = Bytes::new(); +3667 } +3668 } +3669 let space = &mut self.spaces[space_id]; +3670 space.crypto = None; +3671 let pns = space.for_path(PathId::ZERO); +3672 pns.time_of_last_ack_eliciting_packet = None; +3673 pns.loss_time = None; +3674 pns.loss_probes = 0; +3675 let sent_packets = mem::take(&mut pns.sent_packets); +3676 let path = self.paths.get_mut(&PathId::ZERO).unwrap(); +3677 for (_, packet) in sent_packets.into_iter() { +3678 path.data.remove_in_flight(&packet); +3679 } +3680 +3681 self.set_loss_detection_timer(now, PathId::ZERO) +3682 } +3683 +3684 fn handle_coalesced( +3685 &mut self, +3686 now: Instant, +3687 network_path: FourTuple, +3688 path_id: PathId, +3689 ecn: Option<EcnCodepoint>, +3690 data: BytesMut, +3691 ) { +3692 self.path_data_mut(path_id) +3693 .inc_total_recvd(data.len() as u64); +3694 let mut remaining = Some(data); +3695 let cid_len = self +3696 .local_cid_state +3697 .values() +3698 .map(|cid_state| cid_state.cid_len()) +3699 .next() +3700 .expect("one cid_state must exist"); +3701 while let Some(data) = remaining { +3702 match PartialDecode::new( +3703 data, +3704 &FixedLengthConnectionIdParser::new(cid_len), +3705 &[self.version], +3706 self.endpoint_config.grease_quic_bit, +3707 ) { +3708 Ok((partial_decode, rest)) => { +3709 remaining = rest; +3710 self.handle_decode(now, network_path, path_id, ecn, partial_decode); +3711 } +3712 Err(e) => { +3713 trace!("malformed header: {}", e); +3714 return; +3715 } +3716 } +3717 } +3718 } +3719 +3720 fn handle_decode( +3721 &mut self, +3722 now: Instant, +3723 network_path: FourTuple, +3724 path_id: PathId, +3725 ecn: Option<EcnCodepoint>, +3726 partial_decode: PartialDecode, +3727 ) { +3728 let qlog = QlogRecvPacket::new(partial_decode.len()); +3729 if let Some(decoded) = packet_crypto::unprotect_header( +3730 partial_decode, +3731 &self.spaces, +3732 self.zero_rtt_crypto.as_ref(), +3733 self.peer_params.stateless_reset_token, +3734 ) { +3735 self.handle_packet( +3736 now, +3737 network_path, +3738 path_id, +3739 ecn, +3740 decoded.packet, +3741 decoded.stateless_reset, +3742 qlog, +3743 ); +3744 } +3745 } +3746 +3747 fn handle_packet( +3748 &mut self, +3749 now: Instant, +3750 network_path: FourTuple, +3751 path_id: PathId, +3752 ecn: Option<EcnCodepoint>, +3753 packet: Option<Packet>, +3754 stateless_reset: bool, +3755 mut qlog: QlogRecvPacket, +3756 ) { +3757 self.stats.udp_rx.ios += 1; +3758 if let Some(ref packet) = packet { +3759 trace!( +3760 "got {:?} packet ({} bytes) from {} using id {}", +3761 packet.header.space(), +3762 packet.payload.len() + packet.header_data.len(), +3763 network_path, +3764 packet.header.dst_cid(), +3765 ); +3766 } +3767 +3768 if self.is_handshaking() { +3769 if path_id != PathId::ZERO { +3770 debug!(%network_path, %path_id, "discarding multipath packet during handshake"); +3771 return; +3772 } +3773 if network_path != self.path_data_mut(path_id).network_path { +3774 if let Some(hs) = self.state.as_handshake() { +3775 if hs.allow_server_migration { +3776 trace!(%network_path, prev = %self.path_data(path_id).network_path, "server migrated to new remote"); +3777 self.path_data_mut(path_id).network_path = network_path; +3778 self.qlog.emit_tuple_assigned(path_id, network_path, now); +3779 } else { +3780 debug!("discarding packet with unexpected remote during handshake"); +3781 return; +3782 } +3783 } else { +3784 debug!("discarding packet with unexpected remote during handshake"); +3785 return; +3786 } +3787 } +3788 } +3789 +3790 let was_closed = self.state.is_closed(); +3791 let was_drained = self.state.is_drained(); +3792 +3793 let decrypted = match packet { +3794 None => Err(None), +3795 Some(mut packet) => self +3796 .decrypt_packet(now, path_id, &mut packet) +3797 .map(move |number| (packet, number)), +3798 }; +3799 let result = match decrypted { +3800 _ if stateless_reset => { +3801 debug!("got stateless reset"); +3802 Err(ConnectionError::Reset) +3803 } +3804 Err(Some(e)) => { +3805 warn!("illegal packet: {}", e); +3806 Err(e.into()) +3807 } +3808 Err(None) => { +3809 debug!("failed to authenticate packet"); +3810 self.authentication_failures += 1; +3811 let integrity_limit = self.spaces[self.highest_space] +3812 .crypto +3813 .as_ref() +3814 .unwrap() +3815 .packet +3816 .local +3817 .integrity_limit(); +3818 if self.authentication_failures > integrity_limit { +3819 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into()) +3820 } else { +3821 return; +3822 } +3823 } +3824 Ok((packet, number)) => { +3825 qlog.header(&packet.header, number, path_id); +3826 let span = match number { +3827 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn), +3828 None => trace_span!("recv", space = ?packet.header.space()), +3829 }; +3830 let _guard = span.enter(); +3831 +3832 let dedup = self.spaces[packet.header.space()] +3833 .path_space_mut(path_id) +3834 .map(|pns| &mut pns.dedup); +3835 if number.zip(dedup).is_some_and(|(n, d)| d.insert(n)) { +3836 debug!("discarding possible duplicate packet"); 3837 self.qlog.emit_packet_received(qlog, now); 3838 return; -3839 } else { -3840 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header { -3841 if let Some(hs) = self.state.as_handshake() { -3842 if self.side.is_server() && token != &hs.expected_token { -3843 // Clients must send the same retry token in every Initial. Initial -3844 // packets can be spoofed, so we discard rather than killing the -3845 // connection. -3846 warn!("discarding Initial with invalid retry token"); -3847 self.qlog.emit_packet_received(qlog, now); -3848 return; -3849 } -3850 } -3851 } -3852 -3853 if !self.state.is_closed() { -3854 let spin = match packet.header { -3855 Header::Short { spin, .. } => spin, -3856 _ => false, -3857 }; -3858 -3859 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) { -3860 // Only the client is allowed to open paths -3861 self.ensure_path(path_id, network_path, now, number); -3862 } -3863 if self.paths.contains_key(&path_id) { -3864 self.on_packet_authenticated( -3865 now, -3866 packet.header.space(), -3867 path_id, -3868 ecn, -3869 number, -3870 spin, -3871 packet.header.is_1rtt(), -3872 ); -3873 } -3874 } -3875 -3876 let res = self.process_decrypted_packet( -3877 now, -3878 network_path, -3879 path_id, -3880 number, -3881 packet, -3882 &mut qlog, -3883 ); -3884 -3885 self.qlog.emit_packet_received(qlog, now); -3886 res -3887 } -3888 } -3889 }; -3890 -3891 // State transitions for error cases -3892 if let Err(conn_err) = result { -3893 match conn_err { -3894 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason), -3895 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason), -3896 ConnectionError::Reset -3897 | ConnectionError::TransportError(TransportError { -3898 code: TransportErrorCode::AEAD_LIMIT_REACHED, -3899 .. -3900 }) => { -3901 self.state.move_to_drained(Some(conn_err)); -3902 } -3903 ConnectionError::TimedOut => { -3904 unreachable!("timeouts aren't generated by packet processing"); -3905 } -3906 ConnectionError::TransportError(err) => { -3907 debug!("closing connection due to transport error: {}", err); -3908 self.state.move_to_closed(err); -3909 } -3910 ConnectionError::VersionMismatch => { -3911 self.state.move_to_draining(Some(conn_err)); -3912 } -3913 ConnectionError::LocallyClosed => { -3914 unreachable!("LocallyClosed isn't generated by packet processing"); -3915 } -3916 ConnectionError::CidsExhausted => { -3917 unreachable!("CidsExhausted isn't generated by packet processing"); -3918 } -3919 }; -3920 } -3921 -3922 if !was_closed && self.state.is_closed() { -3923 self.close_common(); -3924 if !self.state.is_drained() { -3925 self.set_close_timer(now); -3926 } -3927 } -3928 if !was_drained && self.state.is_drained() { -3929 self.endpoint_events.push_back(EndpointEventInner::Drained); -3930 // Close timer may have been started previously, e.g. if we sent a close and got a -3931 // stateless reset in response -3932 self.timers -3933 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now)); -3934 } -3935 -3936 // Transmit CONNECTION_CLOSE if necessary -3937 if matches!(self.state.as_type(), StateType::Closed) { -3938 // If there is no PathData for this PathId the packet was for a brand new -3939 // path. It was a valid packet however, so the remote is valid and we want to -3940 // send CONNECTION_CLOSE. -3941 let path_remote = self -3942 .paths -3943 .get(&path_id) -3944 .map(|p| p.data.network_path) -3945 .unwrap_or(network_path); -3946 self.close = network_path == path_remote; -3947 } -3948 } -3949 -3950 fn process_decrypted_packet( -3951 &mut self, -3952 now: Instant, -3953 network_path: FourTuple, -3954 path_id: PathId, -3955 number: Option<u64>, -3956 packet: Packet, -3957 qlog: &mut QlogRecvPacket, -3958 ) -> Result<(), ConnectionError> { -3959 if !self.paths.contains_key(&path_id) { -3960 // There is a chance this is a server side, first (for this path) packet, which would -3961 // be a protocol violation. It's more likely, however, that this is a packet of a -3962 // pruned path -3963 trace!(%path_id, ?number, "discarding packet for unknown path"); -3964 return Ok(()); -3965 } -3966 let state = match self.state.as_type() { -3967 StateType::Established => { -3968 match packet.header.space() { -3969 SpaceId::Data => self.process_payload( -3970 now, -3971 network_path, -3972 path_id, -3973 number.unwrap(), -3974 packet, -3975 qlog, -3976 )?, -3977 _ if packet.header.has_frames() => { -3978 self.process_early_payload(now, path_id, packet, qlog)? -3979 } -3980 _ => { -3981 trace!("discarding unexpected pre-handshake packet"); -3982 } -3983 } -3984 return Ok(()); -3985 } -3986 StateType::Closed => { -3987 for result in frame::Iter::new(packet.payload.freeze())? { -3988 let frame = match result { -3989 Ok(frame) => frame, -3990 Err(err) => { -3991 debug!("frame decoding error: {err:?}"); -3992 continue; -3993 } -3994 }; -3995 qlog.frame(&frame); -3996 -3997 if let Frame::Padding = frame { -3998 continue; +3839 } else if self.state.is_handshake() && packet.header.is_short() { +3840 // TODO: SHOULD buffer these to improve reordering tolerance. +3841 trace!("dropping short packet during handshake"); +3842 self.qlog.emit_packet_received(qlog, now); +3843 return; +3844 } else { +3845 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header { +3846 if let Some(hs) = self.state.as_handshake() { +3847 if self.side.is_server() && token != &hs.expected_token { +3848 // Clients must send the same retry token in every Initial. Initial +3849 // packets can be spoofed, so we discard rather than killing the +3850 // connection. +3851 warn!("discarding Initial with invalid retry token"); +3852 self.qlog.emit_packet_received(qlog, now); +3853 return; +3854 } +3855 } +3856 } +3857 +3858 if !self.state.is_closed() { +3859 let spin = match packet.header { +3860 Header::Short { spin, .. } => spin, +3861 _ => false, +3862 }; +3863 +3864 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) { +3865 // Only the client is allowed to open paths +3866 self.ensure_path(path_id, network_path, now, number); +3867 } +3868 if self.paths.contains_key(&path_id) { +3869 self.on_packet_authenticated( +3870 now, +3871 packet.header.space(), +3872 path_id, +3873 ecn, +3874 number, +3875 spin, +3876 packet.header.is_1rtt(), +3877 ); +3878 } +3879 } +3880 +3881 let res = self.process_decrypted_packet( +3882 now, +3883 network_path, +3884 path_id, +3885 number, +3886 packet, +3887 &mut qlog, +3888 ); +3889 +3890 self.qlog.emit_packet_received(qlog, now); +3891 res +3892 } +3893 } +3894 }; +3895 +3896 // State transitions for error cases +3897 if let Err(conn_err) = result { +3898 match conn_err { +3899 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason), +3900 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason), +3901 ConnectionError::Reset +3902 | ConnectionError::TransportError(TransportError { +3903 code: TransportErrorCode::AEAD_LIMIT_REACHED, +3904 .. +3905 }) => { +3906 self.state.move_to_drained(Some(conn_err)); +3907 } +3908 ConnectionError::TimedOut => { +3909 unreachable!("timeouts aren't generated by packet processing"); +3910 } +3911 ConnectionError::TransportError(err) => { +3912 debug!("closing connection due to transport error: {}", err); +3913 self.state.move_to_closed(err); +3914 } +3915 ConnectionError::VersionMismatch => { +3916 self.state.move_to_draining(Some(conn_err)); +3917 } +3918 ConnectionError::LocallyClosed => { +3919 unreachable!("LocallyClosed isn't generated by packet processing"); +3920 } +3921 ConnectionError::CidsExhausted => { +3922 unreachable!("CidsExhausted isn't generated by packet processing"); +3923 } +3924 }; +3925 } +3926 +3927 if !was_closed && self.state.is_closed() { +3928 self.close_common(); +3929 if !self.state.is_drained() { +3930 self.set_close_timer(now); +3931 } +3932 } +3933 if !was_drained && self.state.is_drained() { +3934 self.endpoint_events.push_back(EndpointEventInner::Drained); +3935 // Close timer may have been started previously, e.g. if we sent a close and got a +3936 // stateless reset in response +3937 self.timers +3938 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now)); +3939 } +3940 +3941 // Transmit CONNECTION_CLOSE if necessary +3942 if matches!(self.state.as_type(), StateType::Closed) { +3943 // If there is no PathData for this PathId the packet was for a brand new +3944 // path. It was a valid packet however, so the remote is valid and we want to +3945 // send CONNECTION_CLOSE. +3946 let path_remote = self +3947 .paths +3948 .get(&path_id) +3949 .map(|p| p.data.network_path) +3950 .unwrap_or(network_path); +3951 self.close = network_path == path_remote; +3952 } +3953 } +3954 +3955 fn process_decrypted_packet( +3956 &mut self, +3957 now: Instant, +3958 network_path: FourTuple, +3959 path_id: PathId, +3960 number: Option<u64>, +3961 packet: Packet, +3962 qlog: &mut QlogRecvPacket, +3963 ) -> Result<(), ConnectionError> { +3964 if !self.paths.contains_key(&path_id) { +3965 // There is a chance this is a server side, first (for this path) packet, which would +3966 // be a protocol violation. It's more likely, however, that this is a packet of a +3967 // pruned path +3968 trace!(%path_id, ?number, "discarding packet for unknown path"); +3969 return Ok(()); +3970 } +3971 let state = match self.state.as_type() { +3972 StateType::Established => { +3973 match packet.header.space() { +3974 SpaceId::Data => self.process_payload( +3975 now, +3976 network_path, +3977 path_id, +3978 number.unwrap(), +3979 packet, +3980 qlog, +3981 )?, +3982 _ if packet.header.has_frames() => { +3983 self.process_early_payload(now, path_id, packet, qlog)? +3984 } +3985 _ => { +3986 trace!("discarding unexpected pre-handshake packet"); +3987 } +3988 } +3989 return Ok(()); +3990 } +3991 StateType::Closed => { +3992 for result in frame::Iter::new(packet.payload.freeze())? { +3993 let frame = match result { +3994 Ok(frame) => frame, +3995 Err(err) => { +3996 debug!("frame decoding error: {err:?}"); +3997 continue; +3998 } 3999 }; -4000 -4001 self.stats.frame_rx.record(&frame); -4002 -4003 if let Frame::Close(_error) = frame { -4004 self.state.move_to_draining(None); -4005 break; -4006 } -4007 } -4008 return Ok(()); -4009 } -4010 StateType::Draining | StateType::Drained => return Ok(()), -4011 StateType::Handshake => self.state.as_handshake_mut().expect("checked"), -4012 }; -4013 -4014 match packet.header { -4015 Header::Retry { -4016 src_cid: rem_cid, .. -4017 } => { -4018 debug_assert_eq!(path_id, PathId::ZERO); -4019 if self.side.is_server() { -4020 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into()); -4021 } -4022 -4023 let is_valid_retry = self -4024 .rem_cids -4025 .get(&path_id) -4026 .map(|cids| cids.active()) -4027 .map(|orig_dst_cid| { -4028 self.crypto.is_valid_retry( -4029 orig_dst_cid, -4030 &packet.header_data, -4031 &packet.payload, -4032 ) -4033 }) -4034 .unwrap_or_default(); -4035 if self.total_authed_packets > 1 -4036 || packet.payload.len() <= 16 // token + 16 byte tag -4037 || !is_valid_retry -4038 { -4039 trace!("discarding invalid Retry"); -4040 // - After the client has received and processed an Initial or Retry -4041 // packet from the server, it MUST discard any subsequent Retry -4042 // packets that it receives. -4043 // - A client MUST discard a Retry packet with a zero-length Retry Token -4044 // field. -4045 // - Clients MUST discard Retry packets that have a Retry Integrity Tag -4046 // that cannot be validated -4047 return Ok(()); -4048 } -4049 -4050 trace!("retrying with CID {}", rem_cid); -4051 let client_hello = state.client_hello.take().unwrap(); -4052 self.retry_src_cid = Some(rem_cid); -4053 self.rem_cids -4054 .get_mut(&path_id) -4055 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false") -4056 .update_initial_cid(rem_cid); -4057 self.rem_handshake_cid = rem_cid; -4058 -4059 let space = &mut self.spaces[SpaceId::Initial]; -4060 if let Some(info) = space.for_path(PathId::ZERO).take(0) { -4061 self.on_packet_acked(now, PathId::ZERO, info); -4062 }; +4000 qlog.frame(&frame); +4001 +4002 if let Frame::Padding = frame { +4003 continue; +4004 }; +4005 +4006 self.stats.frame_rx.record(&frame); +4007 +4008 if let Frame::Close(_error) = frame { +4009 self.state.move_to_draining(None); +4010 break; +4011 } +4012 } +4013 return Ok(()); +4014 } +4015 StateType::Draining | StateType::Drained => return Ok(()), +4016 StateType::Handshake => self.state.as_handshake_mut().expect("checked"), +4017 }; +4018 +4019 match packet.header { +4020 Header::Retry { +4021 src_cid: rem_cid, .. +4022 } => { +4023 debug_assert_eq!(path_id, PathId::ZERO); +4024 if self.side.is_server() { +4025 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into()); +4026 } +4027 +4028 let is_valid_retry = self +4029 .rem_cids +4030 .get(&path_id) +4031 .map(|cids| cids.active()) +4032 .map(|orig_dst_cid| { +4033 self.crypto.is_valid_retry( +4034 orig_dst_cid, +4035 &packet.header_data, +4036 &packet.payload, +4037 ) +4038 }) +4039 .unwrap_or_default(); +4040 if self.total_authed_packets > 1 +4041 || packet.payload.len() <= 16 // token + 16 byte tag +4042 || !is_valid_retry +4043 { +4044 trace!("discarding invalid Retry"); +4045 // - After the client has received and processed an Initial or Retry +4046 // packet from the server, it MUST discard any subsequent Retry +4047 // packets that it receives. +4048 // - A client MUST discard a Retry packet with a zero-length Retry Token +4049 // field. +4050 // - Clients MUST discard Retry packets that have a Retry Integrity Tag +4051 // that cannot be validated +4052 return Ok(()); +4053 } +4054 +4055 trace!("retrying with CID {}", rem_cid); +4056 let client_hello = state.client_hello.take().unwrap(); +4057 self.retry_src_cid = Some(rem_cid); +4058 self.rem_cids +4059 .get_mut(&path_id) +4060 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false") +4061 .update_initial_cid(rem_cid); +4062 self.rem_handshake_cid = rem_cid; 4063 -4064 self.discard_space(now, SpaceId::Initial); // Make sure we clean up after -4065 // any retransmitted Initials -4066 self.spaces[SpaceId::Initial] = { -4067 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng); -4068 space.crypto = Some(self.crypto.initial_keys(rem_cid, self.side.side())); -4069 space.crypto_offset = client_hello.len() as u64; -4070 space.for_path(path_id).next_packet_number = self.spaces[SpaceId::Initial] -4071 .for_path(path_id) -4072 .next_packet_number; -4073 space.pending.crypto.push_back(frame::Crypto { -4074 offset: 0, -4075 data: client_hello, -4076 }); -4077 space -4078 }; -4079 -4080 // Retransmit all 0-RTT data -4081 let zero_rtt = mem::take( -4082 &mut self.spaces[SpaceId::Data] -4083 .for_path(PathId::ZERO) -4084 .sent_packets, -4085 ); -4086 for (_, info) in zero_rtt.into_iter() { -4087 self.paths -4088 .get_mut(&PathId::ZERO) -4089 .unwrap() -4090 .remove_in_flight(&info); -4091 self.spaces[SpaceId::Data].pending |= info.retransmits; -4092 } -4093 self.streams.retransmit_all_for_0rtt(); -4094 -4095 let token_len = packet.payload.len() - 16; -4096 let ConnectionSide::Client { ref mut token, .. } = self.side else { -4097 unreachable!("we already short-circuited if we're server"); -4098 }; -4099 *token = packet.payload.freeze().split_to(token_len); -4100 -4101 self.state = State::handshake(state::Handshake { -4102 expected_token: Bytes::new(), -4103 rem_cid_set: false, -4104 client_hello: None, -4105 allow_server_migration: true, -4106 }); -4107 Ok(()) -4108 } -4109 Header::Long { -4110 ty: LongType::Handshake, -4111 src_cid: rem_cid, -4112 dst_cid: loc_cid, -4113 .. -4114 } => { -4115 debug_assert_eq!(path_id, PathId::ZERO); -4116 if rem_cid != self.rem_handshake_cid { -4117 debug!( -4118 "discarding packet with mismatched remote CID: {} != {}", -4119 self.rem_handshake_cid, rem_cid -4120 ); -4121 return Ok(()); -4122 } -4123 self.on_path_validated(path_id); -4124 -4125 self.process_early_payload(now, path_id, packet, qlog)?; -4126 if self.state.is_closed() { -4127 return Ok(()); -4128 } +4064 let space = &mut self.spaces[SpaceId::Initial]; +4065 if let Some(info) = space.for_path(PathId::ZERO).take(0) { +4066 self.on_packet_acked(now, PathId::ZERO, info); +4067 }; +4068 +4069 self.discard_space(now, SpaceId::Initial); // Make sure we clean up after +4070 // any retransmitted Initials +4071 self.spaces[SpaceId::Initial] = { +4072 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng); +4073 space.crypto = Some(self.crypto.initial_keys(rem_cid, self.side.side())); +4074 space.crypto_offset = client_hello.len() as u64; +4075 space.for_path(path_id).next_packet_number = self.spaces[SpaceId::Initial] +4076 .for_path(path_id) +4077 .next_packet_number; +4078 space.pending.crypto.push_back(frame::Crypto { +4079 offset: 0, +4080 data: client_hello, +4081 }); +4082 space +4083 }; +4084 +4085 // Retransmit all 0-RTT data +4086 let zero_rtt = mem::take( +4087 &mut self.spaces[SpaceId::Data] +4088 .for_path(PathId::ZERO) +4089 .sent_packets, +4090 ); +4091 for (_, info) in zero_rtt.into_iter() { +4092 self.paths +4093 .get_mut(&PathId::ZERO) +4094 .unwrap() +4095 .remove_in_flight(&info); +4096 self.spaces[SpaceId::Data].pending |= info.retransmits; +4097 } +4098 self.streams.retransmit_all_for_0rtt(); +4099 +4100 let token_len = packet.payload.len() - 16; +4101 let ConnectionSide::Client { ref mut token, .. } = self.side else { +4102 unreachable!("we already short-circuited if we're server"); +4103 }; +4104 *token = packet.payload.freeze().split_to(token_len); +4105 +4106 self.state = State::handshake(state::Handshake { +4107 expected_token: Bytes::new(), +4108 rem_cid_set: false, +4109 client_hello: None, +4110 allow_server_migration: true, +4111 }); +4112 Ok(()) +4113 } +4114 Header::Long { +4115 ty: LongType::Handshake, +4116 src_cid: rem_cid, +4117 dst_cid: loc_cid, +4118 .. +4119 } => { +4120 debug_assert_eq!(path_id, PathId::ZERO); +4121 if rem_cid != self.rem_handshake_cid { +4122 debug!( +4123 "discarding packet with mismatched remote CID: {} != {}", +4124 self.rem_handshake_cid, rem_cid +4125 ); +4126 return Ok(()); +4127 } +4128 self.on_path_validated(path_id); 4129 -4130 if self.crypto.is_handshaking() { -4131 trace!("handshake ongoing"); +4130 self.process_early_payload(now, path_id, packet, qlog)?; +4131 if self.state.is_closed() { 4132 return Ok(()); 4133 } 4134 -4135 if self.side.is_client() { -4136 // Client-only because server params were set from the client's Initial -4137 let params = self.crypto.transport_parameters()?.ok_or_else(|| { -4138 TransportError::new( -4139 TransportErrorCode::crypto(0x6d), -4140 "transport parameters missing".to_owned(), -4141 ) -4142 })?; -4143 -4144 if self.has_0rtt() { -4145 if !self.crypto.early_data_accepted().unwrap() { -4146 debug_assert!(self.side.is_client()); -4147 debug!("0-RTT rejected"); -4148 self.accepted_0rtt = false; -4149 self.streams.zero_rtt_rejected(); -4150 -4151 // Discard already-queued frames -4152 self.spaces[SpaceId::Data].pending = Retransmits::default(); -4153 -4154 // Discard 0-RTT packets -4155 let sent_packets = mem::take( -4156 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets, -4157 ); -4158 for (_, packet) in sent_packets.into_iter() { -4159 self.paths -4160 .get_mut(&path_id) -4161 .unwrap() -4162 .remove_in_flight(&packet); -4163 } -4164 } else { -4165 self.accepted_0rtt = true; -4166 params.validate_resumption_from(&self.peer_params)?; -4167 } -4168 } -4169 if let Some(token) = params.stateless_reset_token { -4170 // TODO(matheus23): Reset token for a remote, or for a 4-tuple? -4171 let remote = self.path_data(path_id).network_path.remote; -4172 self.endpoint_events -4173 .push_back(EndpointEventInner::ResetToken(path_id, remote, token)); -4174 } -4175 self.handle_peer_params(params, loc_cid, rem_cid, now)?; -4176 self.issue_first_cids(now); -4177 } else { -4178 // Server-only -4179 self.spaces[SpaceId::Data].pending.handshake_done = true; -4180 self.discard_space(now, SpaceId::Handshake); -4181 self.events.push_back(Event::HandshakeConfirmed); -4182 trace!("handshake confirmed"); -4183 } -4184 -4185 self.events.push_back(Event::Connected); -4186 self.state.move_to_established(); -4187 trace!("established"); -4188 -4189 // Multipath can only be enabled after the state has reached Established. -4190 // So this can not happen any earlier. -4191 self.issue_first_path_cids(now); -4192 Ok(()) -4193 } -4194 Header::Initial(InitialHeader { -4195 src_cid: rem_cid, -4196 dst_cid: loc_cid, -4197 .. -4198 }) => { -4199 debug_assert_eq!(path_id, PathId::ZERO); -4200 if !state.rem_cid_set { -4201 trace!("switching remote CID to {}", rem_cid); -4202 let mut state = state.clone(); -4203 self.rem_cids -4204 .get_mut(&path_id) -4205 .expect("PathId::ZERO not yet abandoned") -4206 .update_initial_cid(rem_cid); -4207 self.rem_handshake_cid = rem_cid; -4208 self.orig_rem_cid = rem_cid; -4209 state.rem_cid_set = true; -4210 self.state.move_to_handshake(state); -4211 } else if rem_cid != self.rem_handshake_cid { -4212 debug!( -4213 "discarding packet with mismatched remote CID: {} != {}", -4214 self.rem_handshake_cid, rem_cid -4215 ); -4216 return Ok(()); -4217 } -4218 -4219 let starting_space = self.highest_space; -4220 self.process_early_payload(now, path_id, packet, qlog)?; -4221 -4222 if self.side.is_server() -4223 && starting_space == SpaceId::Initial -4224 && self.highest_space != SpaceId::Initial -4225 { -4226 let params = self.crypto.transport_parameters()?.ok_or_else(|| { -4227 TransportError::new( -4228 TransportErrorCode::crypto(0x6d), -4229 "transport parameters missing".to_owned(), -4230 ) -4231 })?; -4232 self.handle_peer_params(params, loc_cid, rem_cid, now)?; -4233 self.issue_first_cids(now); -4234 self.init_0rtt(now); -4235 } -4236 Ok(()) -4237 } -4238 Header::Long { -4239 ty: LongType::ZeroRtt, -4240 .. -4241 } => { -4242 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?; -4243 Ok(()) -4244 } -4245 Header::VersionNegotiate { .. } => { -4246 if self.total_authed_packets > 1 { -4247 return Ok(()); -4248 } -4249 let supported = packet -4250 .payload -4251 .chunks(4) -4252 .any(|x| match <[u8; 4]>::try_from(x) { -4253 Ok(version) => self.version == u32::from_be_bytes(version), -4254 Err(_) => false, -4255 }); -4256 if supported { -4257 return Ok(()); -4258 } -4259 debug!("remote doesn't support our version"); -4260 Err(ConnectionError::VersionMismatch) -4261 } -4262 Header::Short { .. } => unreachable!( -4263 "short packets received during handshake are discarded in handle_packet" -4264 ), -4265 } -4266 } -4267 -4268 /// Process an Initial or Handshake packet payload -4269 fn process_early_payload( -4270 &mut self, -4271 now: Instant, -4272 path_id: PathId, -4273 packet: Packet, -4274 #[allow(unused)] qlog: &mut QlogRecvPacket, -4275 ) -> Result<(), TransportError> { -4276 debug_assert_ne!(packet.header.space(), SpaceId::Data); -4277 debug_assert_eq!(path_id, PathId::ZERO); -4278 let payload_len = packet.payload.len(); -4279 let mut ack_eliciting = false; -4280 for result in frame::Iter::new(packet.payload.freeze())? { -4281 let frame = result?; -4282 qlog.frame(&frame); -4283 let span = match frame { -4284 Frame::Padding => continue, -4285 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)), -4286 }; -4287 -4288 self.stats.frame_rx.record(&frame); -4289 -4290 let _guard = span.as_ref().map(|x| x.enter()); -4291 ack_eliciting |= frame.is_ack_eliciting(); +4135 if self.crypto.is_handshaking() { +4136 trace!("handshake ongoing"); +4137 return Ok(()); +4138 } +4139 +4140 if self.side.is_client() { +4141 // Client-only because server params were set from the client's Initial +4142 let params = self.crypto.transport_parameters()?.ok_or_else(|| { +4143 TransportError::new( +4144 TransportErrorCode::crypto(0x6d), +4145 "transport parameters missing".to_owned(), +4146 ) +4147 })?; +4148 +4149 if self.has_0rtt() { +4150 if !self.crypto.early_data_accepted().unwrap() { +4151 debug_assert!(self.side.is_client()); +4152 debug!("0-RTT rejected"); +4153 self.accepted_0rtt = false; +4154 self.streams.zero_rtt_rejected(); +4155 +4156 // Discard already-queued frames +4157 self.spaces[SpaceId::Data].pending = Retransmits::default(); +4158 +4159 // Discard 0-RTT packets +4160 let sent_packets = mem::take( +4161 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets, +4162 ); +4163 for (_, packet) in sent_packets.into_iter() { +4164 self.paths +4165 .get_mut(&path_id) +4166 .unwrap() +4167 .remove_in_flight(&packet); +4168 } +4169 } else { +4170 self.accepted_0rtt = true; +4171 params.validate_resumption_from(&self.peer_params)?; +4172 } +4173 } +4174 if let Some(token) = params.stateless_reset_token { +4175 // TODO(matheus23): Reset token for a remote, or for a 4-tuple? +4176 let remote = self.path_data(path_id).network_path.remote; +4177 self.endpoint_events +4178 .push_back(EndpointEventInner::ResetToken(path_id, remote, token)); +4179 } +4180 self.handle_peer_params(params, loc_cid, rem_cid, now)?; +4181 self.issue_first_cids(now); +4182 } else { +4183 // Server-only +4184 self.spaces[SpaceId::Data].pending.handshake_done = true; +4185 self.discard_space(now, SpaceId::Handshake); +4186 self.events.push_back(Event::HandshakeConfirmed); +4187 trace!("handshake confirmed"); +4188 } +4189 +4190 self.events.push_back(Event::Connected); +4191 self.state.move_to_established(); +4192 trace!("established"); +4193 +4194 // Multipath can only be enabled after the state has reached Established. +4195 // So this can not happen any earlier. +4196 self.issue_first_path_cids(now); +4197 Ok(()) +4198 } +4199 Header::Initial(InitialHeader { +4200 src_cid: rem_cid, +4201 dst_cid: loc_cid, +4202 .. +4203 }) => { +4204 debug_assert_eq!(path_id, PathId::ZERO); +4205 if !state.rem_cid_set { +4206 trace!("switching remote CID to {}", rem_cid); +4207 let mut state = state.clone(); +4208 self.rem_cids +4209 .get_mut(&path_id) +4210 .expect("PathId::ZERO not yet abandoned") +4211 .update_initial_cid(rem_cid); +4212 self.rem_handshake_cid = rem_cid; +4213 self.orig_rem_cid = rem_cid; +4214 state.rem_cid_set = true; +4215 self.state.move_to_handshake(state); +4216 } else if rem_cid != self.rem_handshake_cid { +4217 debug!( +4218 "discarding packet with mismatched remote CID: {} != {}", +4219 self.rem_handshake_cid, rem_cid +4220 ); +4221 return Ok(()); +4222 } +4223 +4224 let starting_space = self.highest_space; +4225 self.process_early_payload(now, path_id, packet, qlog)?; +4226 +4227 if self.side.is_server() +4228 && starting_space == SpaceId::Initial +4229 && self.highest_space != SpaceId::Initial +4230 { +4231 let params = self.crypto.transport_parameters()?.ok_or_else(|| { +4232 TransportError::new( +4233 TransportErrorCode::crypto(0x6d), +4234 "transport parameters missing".to_owned(), +4235 ) +4236 })?; +4237 self.handle_peer_params(params, loc_cid, rem_cid, now)?; +4238 self.issue_first_cids(now); +4239 self.init_0rtt(now); +4240 } +4241 Ok(()) +4242 } +4243 Header::Long { +4244 ty: LongType::ZeroRtt, +4245 .. +4246 } => { +4247 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?; +4248 Ok(()) +4249 } +4250 Header::VersionNegotiate { .. } => { +4251 if self.total_authed_packets > 1 { +4252 return Ok(()); +4253 } +4254 let supported = packet +4255 .payload +4256 .chunks(4) +4257 .any(|x| match <[u8; 4]>::try_from(x) { +4258 Ok(version) => self.version == u32::from_be_bytes(version), +4259 Err(_) => false, +4260 }); +4261 if supported { +4262 return Ok(()); +4263 } +4264 debug!("remote doesn't support our version"); +4265 Err(ConnectionError::VersionMismatch) +4266 } +4267 Header::Short { .. } => unreachable!( +4268 "short packets received during handshake are discarded in handle_packet" +4269 ), +4270 } +4271 } +4272 +4273 /// Process an Initial or Handshake packet payload +4274 fn process_early_payload( +4275 &mut self, +4276 now: Instant, +4277 path_id: PathId, +4278 packet: Packet, +4279 #[allow(unused)] qlog: &mut QlogRecvPacket, +4280 ) -> Result<(), TransportError> { +4281 debug_assert_ne!(packet.header.space(), SpaceId::Data); +4282 debug_assert_eq!(path_id, PathId::ZERO); +4283 let payload_len = packet.payload.len(); +4284 let mut ack_eliciting = false; +4285 for result in frame::Iter::new(packet.payload.freeze())? { +4286 let frame = result?; +4287 qlog.frame(&frame); +4288 let span = match frame { +4289 Frame::Padding => continue, +4290 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)), +4291 }; 4292 -4293 // Process frames -4294 if frame.is_1rtt() && packet.header.space() != SpaceId::Data { -4295 return Err(TransportError::PROTOCOL_VIOLATION( -4296 "illegal frame type in handshake", -4297 )); -4298 } -4299 -4300 match frame { -4301 Frame::Padding | Frame::Ping => {} -4302 Frame::Crypto(frame) => { -4303 self.read_crypto(packet.header.space(), &frame, payload_len)?; -4304 } -4305 Frame::Ack(ack) => { -4306 self.on_ack_received(now, packet.header.space(), ack)?; -4307 } -4308 Frame::PathAck(ack) => { -4309 span.as_ref() -4310 .map(|span| span.record("path", tracing::field::debug(&ack.path_id))); -4311 self.on_path_ack_received(now, packet.header.space(), ack)?; +4293 self.stats.frame_rx.record(&frame); +4294 +4295 let _guard = span.as_ref().map(|x| x.enter()); +4296 ack_eliciting |= frame.is_ack_eliciting(); +4297 +4298 // Process frames +4299 if frame.is_1rtt() && packet.header.space() != SpaceId::Data { +4300 return Err(TransportError::PROTOCOL_VIOLATION( +4301 "illegal frame type in handshake", +4302 )); +4303 } +4304 +4305 match frame { +4306 Frame::Padding | Frame::Ping => {} +4307 Frame::Crypto(frame) => { +4308 self.read_crypto(packet.header.space(), &frame, payload_len)?; +4309 } +4310 Frame::Ack(ack) => { +4311 self.on_ack_received(now, packet.header.space(), ack)?; 4312 } -4313 Frame::Close(reason) => { -4314 self.state.move_to_draining(Some(reason.into())); -4315 return Ok(()); -4316 } -4317 _ => { -4318 let mut err = -4319 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake"); -4320 err.frame = frame::MaybeFrame::Known(frame.ty()); -4321 return Err(err); -4322 } -4323 } -4324 } -4325 -4326 if ack_eliciting { -4327 // In the initial and handshake spaces, ACKs must be sent immediately -4328 self.spaces[packet.header.space()] -4329 .for_path(path_id) -4330 .pending_acks -4331 .set_immediate_ack_required(); -4332 } -4333 -4334 self.write_crypto(); -4335 Ok(()) -4336 } -4337 -4338 /// Processes the packet payload, always in the data space. -4339 fn process_payload( -4340 &mut self, -4341 now: Instant, -4342 network_path: FourTuple, -4343 path_id: PathId, -4344 number: u64, -4345 packet: Packet, -4346 #[allow(unused)] qlog: &mut QlogRecvPacket, -4347 ) -> Result<(), TransportError> { -4348 let payload = packet.payload.freeze(); -4349 let mut is_probing_packet = true; -4350 let mut close = None; -4351 let payload_len = payload.len(); -4352 let mut ack_eliciting = false; -4353 // if this packet triggers a path migration and includes a observed address frame, it's -4354 // stored here -4355 let mut migration_observed_addr = None; -4356 for result in frame::Iter::new(payload)? { -4357 let frame = result?; -4358 qlog.frame(&frame); -4359 let span = match frame { -4360 Frame::Padding => continue, -4361 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty), -4362 }; -4363 -4364 self.stats.frame_rx.record(&frame); -4365 // Crypto, Stream and Datagram frames are special cased in order no pollute -4366 // the log with payload data -4367 match &frame { -4368 Frame::Crypto(f) => { -4369 trace!(offset = f.offset, len = f.data.len(), "got crypto frame"); -4370 } -4371 Frame::Stream(f) => { -4372 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got stream frame"); -4373 } -4374 Frame::Datagram(f) => { -4375 trace!(len = f.data.len(), "got datagram frame"); -4376 } -4377 f => { -4378 trace!("got frame {f}"); -4379 } -4380 } -4381 -4382 let _guard = span.enter(); -4383 if packet.header.is_0rtt() { -4384 match frame { -4385 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => { -4386 return Err(TransportError::PROTOCOL_VIOLATION( -4387 "illegal frame type in 0-RTT", -4388 )); -4389 } -4390 _ => { -4391 if frame.is_1rtt() { -4392 return Err(TransportError::PROTOCOL_VIOLATION( -4393 "illegal frame type in 0-RTT", -4394 )); -4395 } -4396 } -4397 } -4398 } -4399 ack_eliciting |= frame.is_ack_eliciting(); -4400 -4401 // Check whether this could be a probing packet -4402 match frame { -4403 Frame::Padding -4404 | Frame::PathChallenge(_) -4405 | Frame::PathResponse(_) -4406 | Frame::NewConnectionId(_) -4407 | Frame::ObservedAddr(_) => {} -4408 _ => { -4409 is_probing_packet = false; -4410 } -4411 } -4412 -4413 match frame { -4414 Frame::Crypto(frame) => { -4415 self.read_crypto(SpaceId::Data, &frame, payload_len)?; -4416 } -4417 Frame::Stream(frame) => { -4418 if self.streams.received(frame, payload_len)?.should_transmit() { -4419 self.spaces[SpaceId::Data].pending.max_data = true; -4420 } +4313 Frame::PathAck(ack) => { +4314 span.as_ref() +4315 .map(|span| span.record("path", tracing::field::debug(&ack.path_id))); +4316 self.on_path_ack_received(now, packet.header.space(), ack)?; +4317 } +4318 Frame::Close(reason) => { +4319 self.state.move_to_draining(Some(reason.into())); +4320 return Ok(()); +4321 } +4322 _ => { +4323 let mut err = +4324 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake"); +4325 err.frame = frame::MaybeFrame::Known(frame.ty()); +4326 return Err(err); +4327 } +4328 } +4329 } +4330 +4331 if ack_eliciting { +4332 // In the initial and handshake spaces, ACKs must be sent immediately +4333 self.spaces[packet.header.space()] +4334 .for_path(path_id) +4335 .pending_acks +4336 .set_immediate_ack_required(); +4337 } +4338 +4339 self.write_crypto(); +4340 Ok(()) +4341 } +4342 +4343 /// Processes the packet payload, always in the data space. +4344 fn process_payload( +4345 &mut self, +4346 now: Instant, +4347 network_path: FourTuple, +4348 path_id: PathId, +4349 number: u64, +4350 packet: Packet, +4351 #[allow(unused)] qlog: &mut QlogRecvPacket, +4352 ) -> Result<(), TransportError> { +4353 let payload = packet.payload.freeze(); +4354 let mut is_probing_packet = true; +4355 let mut close = None; +4356 let payload_len = payload.len(); +4357 let mut ack_eliciting = false; +4358 // if this packet triggers a path migration and includes a observed address frame, it's +4359 // stored here +4360 let mut migration_observed_addr = None; +4361 for result in frame::Iter::new(payload)? { +4362 let frame = result?; +4363 qlog.frame(&frame); +4364 let span = match frame { +4365 Frame::Padding => continue, +4366 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty), +4367 }; +4368 +4369 self.stats.frame_rx.record(&frame); +4370 // Crypto, Stream and Datagram frames are special cased in order no pollute +4371 // the log with payload data +4372 match &frame { +4373 Frame::Crypto(f) => { +4374 trace!(offset = f.offset, len = f.data.len(), "got crypto frame"); +4375 } +4376 Frame::Stream(f) => { +4377 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got stream frame"); +4378 } +4379 Frame::Datagram(f) => { +4380 trace!(len = f.data.len(), "got datagram frame"); +4381 } +4382 f => { +4383 trace!("got frame {f}"); +4384 } +4385 } +4386 +4387 let _guard = span.enter(); +4388 if packet.header.is_0rtt() { +4389 match frame { +4390 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => { +4391 return Err(TransportError::PROTOCOL_VIOLATION( +4392 "illegal frame type in 0-RTT", +4393 )); +4394 } +4395 _ => { +4396 if frame.is_1rtt() { +4397 return Err(TransportError::PROTOCOL_VIOLATION( +4398 "illegal frame type in 0-RTT", +4399 )); +4400 } +4401 } +4402 } +4403 } +4404 ack_eliciting |= frame.is_ack_eliciting(); +4405 +4406 // Check whether this could be a probing packet +4407 match frame { +4408 Frame::Padding +4409 | Frame::PathChallenge(_) +4410 | Frame::PathResponse(_) +4411 | Frame::NewConnectionId(_) +4412 | Frame::ObservedAddr(_) => {} +4413 _ => { +4414 is_probing_packet = false; +4415 } +4416 } +4417 +4418 match frame { +4419 Frame::Crypto(frame) => { +4420 self.read_crypto(SpaceId::Data, &frame, payload_len)?; 4421 } -4422 Frame::Ack(ack) => { -4423 self.on_ack_received(now, SpaceId::Data, ack)?; -4424 } -4425 Frame::PathAck(ack) => { -4426 span.record("path", tracing::field::debug(&ack.path_id)); -4427 self.on_path_ack_received(now, SpaceId::Data, ack)?; -4428 } -4429 Frame::Padding | Frame::Ping => {} -4430 Frame::Close(reason) => { -4431 close = Some(reason); -4432 } -4433 Frame::PathChallenge(challenge) => { -4434 let path = &mut self -4435 .path_mut(path_id) -4436 .expect("payload is processed only after the path becomes known"); -4437 path.path_responses.push(number, challenge.0, network_path); -4438 // At this point, update_network_path_or_discard was already called, so -4439 // we don't need to be lenient about `local_ip` possibly mis-matching. -4440 if network_path == path.network_path { -4441 // PATH_CHALLENGE on active path, possible off-path packet forwarding -4442 // attack. Send a non-probing packet to recover the active path. -4443 // TODO(flub): No longer true! We now path_challege also to validate -4444 // the path if the path is new, without an RFC9000-style -4445 // migration involved. This means we add in an extra -4446 // IMMEDIATE_ACK on some challenges. It isn't really wrong to do -4447 // so, but it still is something untidy. We should instead -4448 // suppress this when we know the remote is still validating the -4449 // path. -4450 match self.peer_supports_ack_frequency() { -4451 true => self.immediate_ack(path_id), -4452 false => { -4453 self.ping_path(path_id).ok(); -4454 } -4455 } -4456 } -4457 } -4458 Frame::PathResponse(response) => { -4459 let path = self -4460 .paths -4461 .get_mut(&path_id) -4462 .expect("payload is processed only after the path becomes known"); -4463 -4464 use PathTimer::*; -4465 use paths::OnPathResponseReceived::*; -4466 match path -4467 .data -4468 .on_path_response_received(now, response.0, network_path) -4469 { -4470 OnPath { was_open } => { -4471 let qlog = self.qlog.with_time(now); -4472 -4473 self.timers -4474 .stop(Timer::PerPath(path_id, PathValidation), qlog.clone()); -4475 self.timers -4476 .stop(Timer::PerPath(path_id, PathOpen), qlog.clone()); +4422 Frame::Stream(frame) => { +4423 if self.streams.received(frame, payload_len)?.should_transmit() { +4424 self.spaces[SpaceId::Data].pending.max_data = true; +4425 } +4426 } +4427 Frame::Ack(ack) => { +4428 self.on_ack_received(now, SpaceId::Data, ack)?; +4429 } +4430 Frame::PathAck(ack) => { +4431 span.record("path", tracing::field::debug(&ack.path_id)); +4432 self.on_path_ack_received(now, SpaceId::Data, ack)?; +4433 } +4434 Frame::Padding | Frame::Ping => {} +4435 Frame::Close(reason) => { +4436 close = Some(reason); +4437 } +4438 Frame::PathChallenge(challenge) => { +4439 let path = &mut self +4440 .path_mut(path_id) +4441 .expect("payload is processed only after the path becomes known"); +4442 path.path_responses.push(number, challenge.0, network_path); +4443 // At this point, update_network_path_or_discard was already called, so +4444 // we don't need to be lenient about `local_ip` possibly mis-matching. +4445 if network_path == path.network_path { +4446 // PATH_CHALLENGE on active path, possible off-path packet forwarding +4447 // attack. Send a non-probing packet to recover the active path. +4448 // TODO(flub): No longer true! We now path_challege also to validate +4449 // the path if the path is new, without an RFC9000-style +4450 // migration involved. This means we add in an extra +4451 // IMMEDIATE_ACK on some challenges. It isn't really wrong to do +4452 // so, but it still is something untidy. We should instead +4453 // suppress this when we know the remote is still validating the +4454 // path. +4455 match self.peer_supports_ack_frequency() { +4456 true => self.immediate_ack(path_id), +4457 false => { +4458 self.ping_path(path_id).ok(); +4459 } +4460 } +4461 } +4462 } +4463 Frame::PathResponse(response) => { +4464 let path = self +4465 .paths +4466 .get_mut(&path_id) +4467 .expect("payload is processed only after the path becomes known"); +4468 +4469 use PathTimer::*; +4470 use paths::OnPathResponseReceived::*; +4471 match path +4472 .data +4473 .on_path_response_received(now, response.0, network_path) +4474 { +4475 OnPath { was_open } => { +4476 let qlog = self.qlog.with_time(now); 4477 -4478 let next_challenge = path -4479 .data -4480 .earliest_expiring_challenge() -4481 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); -4482 self.timers.set_or_stop( -4483 Timer::PerPath(path_id, PathChallengeLost), -4484 next_challenge, -4485 qlog, -4486 ); -4487 -4488 if !was_open { -4489 self.events -4490 .push_back(Event::Path(PathEvent::Opened { id: path_id })); -4491 if let Some(observed) = path.data.last_observed_addr_report.as_ref() -4492 { -4493 self.events.push_back(Event::Path(PathEvent::ObservedAddr { -4494 id: path_id, -4495 addr: observed.socket_addr(), -4496 })); -4497 } -4498 } -4499 if let Some((_, ref mut prev)) = path.prev { -4500 prev.challenges_sent.clear(); -4501 prev.send_new_challenge = false; -4502 } -4503 } -4504 OffPath => { -4505 debug!("Response to off-path PathChallenge!"); -4506 let next_challenge = path -4507 .data -4508 .earliest_expiring_challenge() -4509 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); -4510 self.timers.set_or_stop( -4511 Timer::PerPath(path_id, PathChallengeLost), -4512 next_challenge, -4513 self.qlog.with_time(now), -4514 ); -4515 } -4516 Invalid { expected } => { -4517 debug!(%response, %network_path, %expected, "ignoring invalid PATH_RESPONSE") -4518 } -4519 Unknown => debug!(%response, "ignoring invalid PATH_RESPONSE"), -4520 } -4521 } -4522 Frame::MaxData(bytes) => { -4523 self.streams.received_max_data(bytes); -4524 } -4525 Frame::MaxStreamData { id, offset } => { -4526 self.streams.received_max_stream_data(id, offset)?; -4527 } -4528 Frame::MaxStreams { dir, count } => { -4529 self.streams.received_max_streams(dir, count)?; -4530 } -4531 Frame::ResetStream(frame) => { -4532 if self.streams.received_reset(frame)?.should_transmit() { -4533 self.spaces[SpaceId::Data].pending.max_data = true; -4534 } +4478 self.timers +4479 .stop(Timer::PerPath(path_id, PathValidation), qlog.clone()); +4480 self.timers +4481 .stop(Timer::PerPath(path_id, PathOpen), qlog.clone()); +4482 +4483 let next_challenge = path +4484 .data +4485 .earliest_expiring_challenge() +4486 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); +4487 self.timers.set_or_stop( +4488 Timer::PerPath(path_id, PathChallengeLost), +4489 next_challenge, +4490 qlog, +4491 ); +4492 +4493 if !was_open { +4494 self.events +4495 .push_back(Event::Path(PathEvent::Opened { id: path_id })); +4496 if let Some(observed) = path.data.last_observed_addr_report.as_ref() +4497 { +4498 self.events.push_back(Event::Path(PathEvent::ObservedAddr { +4499 id: path_id, +4500 addr: observed.socket_addr(), +4501 })); +4502 } +4503 } +4504 if let Some((_, ref mut prev)) = path.prev { +4505 prev.challenges_sent.clear(); +4506 prev.send_new_challenge = false; +4507 } +4508 } +4509 OffPath => { +4510 debug!("Response to off-path PathChallenge!"); +4511 let next_challenge = path +4512 .data +4513 .earliest_expiring_challenge() +4514 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto()); +4515 self.timers.set_or_stop( +4516 Timer::PerPath(path_id, PathChallengeLost), +4517 next_challenge, +4518 self.qlog.with_time(now), +4519 ); +4520 } +4521 Invalid { expected } => { +4522 debug!(%response, %network_path, %expected, "ignoring invalid PATH_RESPONSE") +4523 } +4524 Unknown => debug!(%response, "ignoring invalid PATH_RESPONSE"), +4525 } +4526 } +4527 Frame::MaxData(bytes) => { +4528 self.streams.received_max_data(bytes); +4529 } +4530 Frame::MaxStreamData { id, offset } => { +4531 self.streams.received_max_stream_data(id, offset)?; +4532 } +4533 Frame::MaxStreams { dir, count } => { +4534 self.streams.received_max_streams(dir, count)?; 4535 } -4536 Frame::DataBlocked { offset } => { -4537 debug!(offset, "peer claims to be blocked at connection level"); -4538 } -4539 Frame::StreamDataBlocked { id, offset } => { -4540 if id.initiator() == self.side.side() && id.dir() == Dir::Uni { -4541 debug!("got STREAM_DATA_BLOCKED on send-only {}", id); -4542 return Err(TransportError::STREAM_STATE_ERROR( -4543 "STREAM_DATA_BLOCKED on send-only stream", -4544 )); -4545 } -4546 debug!( -4547 stream = %id, -4548 offset, "peer claims to be blocked at stream level" -4549 ); -4550 } -4551 Frame::StreamsBlocked { dir, limit } => { -4552 if limit > MAX_STREAM_COUNT { -4553 return Err(TransportError::FRAME_ENCODING_ERROR( -4554 "unrepresentable stream limit", -4555 )); -4556 } -4557 debug!( -4558 "peer claims to be blocked opening more than {} {} streams", -4559 limit, dir -4560 ); -4561 } -4562 Frame::StopSending(frame::StopSending { id, error_code }) => { -4563 if id.initiator() != self.side.side() { -4564 if id.dir() == Dir::Uni { -4565 debug!("got STOP_SENDING on recv-only {}", id); -4566 return Err(TransportError::STREAM_STATE_ERROR( -4567 "STOP_SENDING on recv-only stream", -4568 )); -4569 } -4570 } else if self.streams.is_local_unopened(id) { -4571 return Err(TransportError::STREAM_STATE_ERROR( -4572 "STOP_SENDING on unopened stream", -4573 )); -4574 } -4575 self.streams.received_stop_sending(id, error_code); -4576 } -4577 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => { -4578 if let Some(ref path_id) = path_id { -4579 span.record("path", tracing::field::debug(&path_id)); -4580 } -4581 let path_id = path_id.unwrap_or_default(); -4582 match self.local_cid_state.get_mut(&path_id) { -4583 None => error!(?path_id, "RETIRE_CONNECTION_ID for unknown path"), -4584 Some(cid_state) => { -4585 let allow_more_cids = cid_state -4586 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?; -4587 -4588 // If the path has closed, we do not issue more CIDs for this path -4589 // For details see https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-3.2.2 -4590 // > an endpoint SHOULD provide new connection IDs for that path, if still open, using PATH_NEW_CONNECTION_ID frames. -4591 let has_path = !self.abandoned_paths.contains(&path_id); -4592 let allow_more_cids = allow_more_cids && has_path; -4593 -4594 self.endpoint_events -4595 .push_back(EndpointEventInner::RetireConnectionId( -4596 now, -4597 path_id, -4598 sequence, -4599 allow_more_cids, -4600 )); -4601 } -4602 } -4603 } -4604 Frame::NewConnectionId(frame) => { -4605 let path_id = if let Some(path_id) = frame.path_id { -4606 if !self.is_multipath_negotiated() { -4607 return Err(TransportError::PROTOCOL_VIOLATION( -4608 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated", -4609 )); -4610 } -4611 if path_id > self.local_max_path_id { +4536 Frame::ResetStream(frame) => { +4537 if self.streams.received_reset(frame)?.should_transmit() { +4538 self.spaces[SpaceId::Data].pending.max_data = true; +4539 } +4540 } +4541 Frame::DataBlocked { offset } => { +4542 debug!(offset, "peer claims to be blocked at connection level"); +4543 } +4544 Frame::StreamDataBlocked { id, offset } => { +4545 if id.initiator() == self.side.side() && id.dir() == Dir::Uni { +4546 debug!("got STREAM_DATA_BLOCKED on send-only {}", id); +4547 return Err(TransportError::STREAM_STATE_ERROR( +4548 "STREAM_DATA_BLOCKED on send-only stream", +4549 )); +4550 } +4551 debug!( +4552 stream = %id, +4553 offset, "peer claims to be blocked at stream level" +4554 ); +4555 } +4556 Frame::StreamsBlocked { dir, limit } => { +4557 if limit > MAX_STREAM_COUNT { +4558 return Err(TransportError::FRAME_ENCODING_ERROR( +4559 "unrepresentable stream limit", +4560 )); +4561 } +4562 debug!( +4563 "peer claims to be blocked opening more than {} {} streams", +4564 limit, dir +4565 ); +4566 } +4567 Frame::StopSending(frame::StopSending { id, error_code }) => { +4568 if id.initiator() != self.side.side() { +4569 if id.dir() == Dir::Uni { +4570 debug!("got STOP_SENDING on recv-only {}", id); +4571 return Err(TransportError::STREAM_STATE_ERROR( +4572 "STOP_SENDING on recv-only stream", +4573 )); +4574 } +4575 } else if self.streams.is_local_unopened(id) { +4576 return Err(TransportError::STREAM_STATE_ERROR( +4577 "STOP_SENDING on unopened stream", +4578 )); +4579 } +4580 self.streams.received_stop_sending(id, error_code); +4581 } +4582 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => { +4583 if let Some(ref path_id) = path_id { +4584 span.record("path", tracing::field::debug(&path_id)); +4585 } +4586 let path_id = path_id.unwrap_or_default(); +4587 match self.local_cid_state.get_mut(&path_id) { +4588 None => error!(?path_id, "RETIRE_CONNECTION_ID for unknown path"), +4589 Some(cid_state) => { +4590 let allow_more_cids = cid_state +4591 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?; +4592 +4593 // If the path has closed, we do not issue more CIDs for this path +4594 // For details see https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-3.2.2 +4595 // > an endpoint SHOULD provide new connection IDs for that path, if still open, using PATH_NEW_CONNECTION_ID frames. +4596 let has_path = !self.abandoned_paths.contains(&path_id); +4597 let allow_more_cids = allow_more_cids && has_path; +4598 +4599 self.endpoint_events +4600 .push_back(EndpointEventInner::RetireConnectionId( +4601 now, +4602 path_id, +4603 sequence, +4604 allow_more_cids, +4605 )); +4606 } +4607 } +4608 } +4609 Frame::NewConnectionId(frame) => { +4610 let path_id = if let Some(path_id) = frame.path_id { +4611 if !self.is_multipath_negotiated() { 4612 return Err(TransportError::PROTOCOL_VIOLATION( -4613 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max", +4613 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated", 4614 )); 4615 } -4616 path_id -4617 } else { -4618 PathId::ZERO -4619 }; -4620 -4621 if self.abandoned_paths.contains(&path_id) { -4622 trace!("ignoring issued CID for abandoned path"); -4623 continue; -4624 } -4625 if let Some(ref path_id) = frame.path_id { -4626 span.record("path", tracing::field::debug(&path_id)); -4627 } -4628 let rem_cids = self -4629 .rem_cids -4630 .entry(path_id) -4631 .or_insert_with(|| CidQueue::new(frame.id)); -4632 if rem_cids.active().is_empty() { -4633 return Err(TransportError::PROTOCOL_VIOLATION( -4634 "NEW_CONNECTION_ID when CIDs aren't in use", -4635 )); -4636 } -4637 if frame.retire_prior_to > frame.sequence { +4616 if path_id > self.local_max_path_id { +4617 return Err(TransportError::PROTOCOL_VIOLATION( +4618 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max", +4619 )); +4620 } +4621 path_id +4622 } else { +4623 PathId::ZERO +4624 }; +4625 +4626 if self.abandoned_paths.contains(&path_id) { +4627 trace!("ignoring issued CID for abandoned path"); +4628 continue; +4629 } +4630 if let Some(ref path_id) = frame.path_id { +4631 span.record("path", tracing::field::debug(&path_id)); +4632 } +4633 let rem_cids = self +4634 .rem_cids +4635 .entry(path_id) +4636 .or_insert_with(|| CidQueue::new(frame.id)); +4637 if rem_cids.active().is_empty() { 4638 return Err(TransportError::PROTOCOL_VIOLATION( -4639 "NEW_CONNECTION_ID retiring unissued CIDs", +4639 "NEW_CONNECTION_ID when CIDs aren't in use", 4640 )); 4641 } -4642 -4643 use crate::cid_queue::InsertError; -4644 match rem_cids.insert(frame) { -4645 Ok(None) if self.path(path_id).is_none() => { -4646 // if this gives us CIDs to open a new path and a nat traversal attempt -4647 // is underway we could try to probe a pending remote -4648 self.continue_nat_traversal_round(now); -4649 } -4650 Ok(None) => {} -4651 Ok(Some((retired, reset_token))) => { -4652 let pending_retired = -4653 &mut self.spaces[SpaceId::Data].pending.retire_cids; -4654 /// Ensure `pending_retired` cannot grow without bound. Limit is -4655 /// somewhat arbitrary but very permissive. -4656 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10; -4657 // We don't bother counting in-flight frames because those are bounded -4658 // by congestion control. -4659 if (pending_retired.len() as u64) -4660 .saturating_add(retired.end.saturating_sub(retired.start)) -4661 > MAX_PENDING_RETIRED_CIDS -4662 { -4663 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR( -4664 "queued too many retired CIDs", -4665 )); -4666 } -4667 pending_retired.extend(retired.map(|seq| (path_id, seq))); -4668 // TODO(matheus23): Reset token for a remote or a full 4-tuple? -4669 self.set_reset_token(path_id, network_path.remote, reset_token); -4670 } -4671 Err(InsertError::ExceedsLimit) => { -4672 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR("")); -4673 } -4674 Err(InsertError::Retired) => { -4675 trace!("discarding already-retired"); -4676 // RETIRE_CONNECTION_ID might not have been previously sent if e.g. a -4677 // range of connection IDs larger than the active connection ID limit -4678 // was retired all at once via retire_prior_to. -4679 self.spaces[SpaceId::Data] -4680 .pending -4681 .retire_cids -4682 .push((path_id, frame.sequence)); -4683 continue; -4684 } -4685 }; -4686 -4687 if self.side.is_server() -4688 && path_id == PathId::ZERO -4689 && self -4690 .rem_cids -4691 .get(&PathId::ZERO) -4692 .map(|cids| cids.active_seq() == 0) -4693 .unwrap_or_default() -4694 { -4695 // We're a server still using the initial remote CID for the client, so -4696 // let's switch immediately to enable clientside stateless resets. -4697 self.update_rem_cid(PathId::ZERO); -4698 } -4699 } -4700 Frame::NewToken(NewToken { token }) => { -4701 let ConnectionSide::Client { -4702 token_store, -4703 server_name, -4704 .. -4705 } = &self.side -4706 else { -4707 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN")); -4708 }; -4709 if token.is_empty() { -4710 return Err(TransportError::FRAME_ENCODING_ERROR("empty token")); -4711 } -4712 trace!("got new token"); -4713 token_store.insert(server_name, token); -4714 } -4715 Frame::Datagram(datagram) => { -4716 if self -4717 .datagrams -4718 .received(datagram, &self.config.datagram_receive_buffer_size)? -4719 { -4720 self.events.push_back(Event::DatagramReceived); -4721 } -4722 } -4723 Frame::AckFrequency(ack_frequency) => { -4724 // This frame can only be sent in the Data space -4725 -4726 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? { -4727 // The AckFrequency frame is stale (we have already received a more -4728 // recent one) -4729 continue; -4730 } -4731 -4732 // Update the params for all of our paths -4733 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() { -4734 space.pending_acks.set_ack_frequency_params(&ack_frequency); -4735 -4736 // Our `max_ack_delay` has been updated, so we may need to adjust -4737 // its associated timeout -4738 if let Some(timeout) = space -4739 .pending_acks -4740 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay) -4741 { -4742 self.timers.set( -4743 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), -4744 timeout, -4745 self.qlog.with_time(now), -4746 ); -4747 } -4748 } -4749 } -4750 Frame::ImmediateAck => { -4751 // This frame can only be sent in the Data space -4752 for pns in self.spaces[SpaceId::Data].iter_paths_mut() { -4753 pns.pending_acks.set_immediate_ack_required(); -4754 } -4755 } -4756 Frame::HandshakeDone => { -4757 if self.side.is_server() { -4758 return Err(TransportError::PROTOCOL_VIOLATION( -4759 "client sent HANDSHAKE_DONE", -4760 )); -4761 } -4762 if self.spaces[SpaceId::Handshake].crypto.is_some() { -4763 self.discard_space(now, SpaceId::Handshake); -4764 } -4765 self.events.push_back(Event::HandshakeConfirmed); -4766 trace!("handshake confirmed"); -4767 } -4768 Frame::ObservedAddr(observed) => { -4769 // check if params allows the peer to send report and this node to receive it -4770 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port); -4771 if !self -4772 .peer_params -4773 .address_discovery_role -4774 .should_report(&self.config.address_discovery_role) -4775 { -4776 return Err(TransportError::PROTOCOL_VIOLATION( -4777 "received OBSERVED_ADDRESS frame when not negotiated", -4778 )); -4779 } -4780 // must only be sent in data space -4781 if packet.header.space() != SpaceId::Data { -4782 return Err(TransportError::PROTOCOL_VIOLATION( -4783 "OBSERVED_ADDRESS frame outside data space", -4784 )); -4785 } -4786 -4787 let path = self.path_data_mut(path_id); -4788 if network_path == path.network_path { -4789 if let Some(updated) = path.update_observed_addr_report(observed) { -4790 if path.open { -4791 self.events.push_back(Event::Path(PathEvent::ObservedAddr { -4792 id: path_id, -4793 addr: updated, -4794 })); -4795 } -4796 // otherwise the event is reported when the path is deemed open -4797 } -4798 } else { -4799 // include in migration -4800 migration_observed_addr = Some(observed) -4801 } -4802 } -4803 Frame::PathAbandon(frame::PathAbandon { -4804 path_id, -4805 error_code, -4806 }) => { -4807 span.record("path", tracing::field::debug(&path_id)); -4808 // TODO(flub): don't really know which error code to use here. -4809 let already_abandoned = match self.close_path(now, path_id, error_code.into()) { -4810 Ok(()) => { -4811 trace!("peer abandoned path"); -4812 false -4813 } -4814 Err(ClosePathError::LastOpenPath) => { -4815 trace!("peer abandoned last path, closing connection"); -4816 // TODO(flub): which error code? -4817 return Err(TransportError::NO_ERROR("last path abandoned by peer")); -4818 } -4819 Err(ClosePathError::ClosedPath) => { -4820 trace!("peer abandoned already closed path"); -4821 true -4822 } -4823 }; -4824 // If we receive a retransmit of PATH_ABANDON then we may already have -4825 // abandoned this path locally. In that case the DiscardPath timer -4826 // may already have fired and we no longer have any state for this path. -4827 // Only set this timer if we still have path state. -4828 if self.path(path_id).is_some() && !already_abandoned { -4829 // TODO(flub): Checking is_some() here followed by a number of calls -4830 // that would panic if it was None is really ugly. If only we -4831 // could do something like PathData::pto(). One day we'll have -4832 // unified SpaceId and PathId and this will be possible. -4833 let delay = self.pto(SpaceId::Data, path_id) * 3; -4834 self.timers.set( -4835 Timer::PerPath(path_id, PathTimer::DiscardPath), -4836 now + delay, -4837 self.qlog.with_time(now), -4838 ); -4839 } -4840 } -4841 Frame::PathStatusAvailable(info) => { -4842 span.record("path", tracing::field::debug(&info.path_id)); -4843 if self.is_multipath_negotiated() { -4844 self.on_path_status( -4845 info.path_id, -4846 PathStatus::Available, -4847 info.status_seq_no, -4848 ); -4849 } else { -4850 return Err(TransportError::PROTOCOL_VIOLATION( -4851 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated", -4852 )); -4853 } -4854 } -4855 Frame::PathStatusBackup(info) => { -4856 span.record("path", tracing::field::debug(&info.path_id)); -4857 if self.is_multipath_negotiated() { -4858 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no); -4859 } else { -4860 return Err(TransportError::PROTOCOL_VIOLATION( -4861 "received PATH_STATUS_BACKUP frame when multipath was not negotiated", -4862 )); -4863 } -4864 } -4865 Frame::MaxPathId(frame::MaxPathId(path_id)) => { -4866 span.record("path", tracing::field::debug(&path_id)); -4867 if !self.is_multipath_negotiated() { -4868 return Err(TransportError::PROTOCOL_VIOLATION( -4869 "received MAX_PATH_ID frame when multipath was not negotiated", -4870 )); -4871 } -4872 // frames that do not increase the path id are ignored -4873 if path_id > self.remote_max_path_id { -4874 self.remote_max_path_id = path_id; -4875 self.issue_first_path_cids(now); -4876 while let Some(true) = self.continue_nat_traversal_round(now) {} -4877 } -4878 } -4879 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => { -4880 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST -4881 // be treated as a connection error of type PROTOCOL_VIOLATION. -4882 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> -4883 if self.is_multipath_negotiated() { -4884 if self.local_max_path_id > max_path_id { -4885 return Err(TransportError::PROTOCOL_VIOLATION( -4886 "PATHS_BLOCKED maximum path identifier was larger than local maximum", -4887 )); -4888 } -4889 debug!("received PATHS_BLOCKED({:?})", max_path_id); -4890 // TODO(@divma): ensure max concurrent paths -4891 } else { -4892 return Err(TransportError::PROTOCOL_VIOLATION( -4893 "received PATHS_BLOCKED frame when not multipath was not negotiated", -4894 )); -4895 } -4896 } -4897 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => { -4898 // Nothing to do. This is recorded in the frame stats, but otherwise we -4899 // always issue all CIDs we're allowed to issue, so either this is an -4900 // impatient peer or a bug on our side. -4901 -4902 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST -4903 // be treated as a connection error of type PROTOCOL_VIOLATION. -4904 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> -4905 if self.is_multipath_negotiated() { -4906 if path_id > self.local_max_path_id { -4907 return Err(TransportError::PROTOCOL_VIOLATION( -4908 "PATH_CIDS_BLOCKED path identifier was larger than local maximum", -4909 )); -4910 } -4911 if next_seq.0 -4912 > self -4913 .local_cid_state -4914 .get(&path_id) -4915 .map(|cid_state| cid_state.active_seq().1 + 1) -4916 .unwrap_or_default() -4917 { -4918 return Err(TransportError::PROTOCOL_VIOLATION( -4919 "PATH_CIDS_BLOCKED next sequence number larger than in local state", -4920 )); -4921 } -4922 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED"); -4923 } else { -4924 return Err(TransportError::PROTOCOL_VIOLATION( -4925 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated", -4926 )); -4927 } -4928 } -4929 Frame::AddAddress(addr) => { -4930 let client_state = match self.iroh_hp.client_side_mut() { -4931 Ok(state) => state, -4932 Err(err) => { -4933 return Err(TransportError::PROTOCOL_VIOLATION(format!( -4934 "Nat traversal(ADD_ADDRESS): {err}" -4935 ))); -4936 } -4937 }; -4938 -4939 if !client_state.check_remote_address(&addr) { -4940 // if the address is not valid we flag it, but update anyway -4941 warn!(?addr, "server sent illegal ADD_ADDRESS frame"); -4942 } +4642 if frame.retire_prior_to > frame.sequence { +4643 return Err(TransportError::PROTOCOL_VIOLATION( +4644 "NEW_CONNECTION_ID retiring unissued CIDs", +4645 )); +4646 } +4647 +4648 use crate::cid_queue::InsertError; +4649 match rem_cids.insert(frame) { +4650 Ok(None) if self.path(path_id).is_none() => { +4651 // if this gives us CIDs to open a new path and a nat traversal attempt +4652 // is underway we could try to probe a pending remote +4653 self.continue_nat_traversal_round(now); +4654 } +4655 Ok(None) => {} +4656 Ok(Some((retired, reset_token))) => { +4657 let pending_retired = +4658 &mut self.spaces[SpaceId::Data].pending.retire_cids; +4659 /// Ensure `pending_retired` cannot grow without bound. Limit is +4660 /// somewhat arbitrary but very permissive. +4661 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10; +4662 // We don't bother counting in-flight frames because those are bounded +4663 // by congestion control. +4664 if (pending_retired.len() as u64) +4665 .saturating_add(retired.end.saturating_sub(retired.start)) +4666 > MAX_PENDING_RETIRED_CIDS +4667 { +4668 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR( +4669 "queued too many retired CIDs", +4670 )); +4671 } +4672 pending_retired.extend(retired.map(|seq| (path_id, seq))); +4673 // TODO(matheus23): Reset token for a remote or a full 4-tuple? +4674 self.set_reset_token(path_id, network_path.remote, reset_token); +4675 } +4676 Err(InsertError::ExceedsLimit) => { +4677 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR("")); +4678 } +4679 Err(InsertError::Retired) => { +4680 trace!("discarding already-retired"); +4681 // RETIRE_CONNECTION_ID might not have been previously sent if e.g. a +4682 // range of connection IDs larger than the active connection ID limit +4683 // was retired all at once via retire_prior_to. +4684 self.spaces[SpaceId::Data] +4685 .pending +4686 .retire_cids +4687 .push((path_id, frame.sequence)); +4688 continue; +4689 } +4690 }; +4691 +4692 if self.side.is_server() +4693 && path_id == PathId::ZERO +4694 && self +4695 .rem_cids +4696 .get(&PathId::ZERO) +4697 .map(|cids| cids.active_seq() == 0) +4698 .unwrap_or_default() +4699 { +4700 // We're a server still using the initial remote CID for the client, so +4701 // let's switch immediately to enable clientside stateless resets. +4702 self.update_rem_cid(PathId::ZERO); +4703 } +4704 } +4705 Frame::NewToken(NewToken { token }) => { +4706 let ConnectionSide::Client { +4707 token_store, +4708 server_name, +4709 .. +4710 } = &self.side +4711 else { +4712 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN")); +4713 }; +4714 if token.is_empty() { +4715 return Err(TransportError::FRAME_ENCODING_ERROR("empty token")); +4716 } +4717 trace!("got new token"); +4718 token_store.insert(server_name, token); +4719 } +4720 Frame::Datagram(datagram) => { +4721 if self +4722 .datagrams +4723 .received(datagram, &self.config.datagram_receive_buffer_size)? +4724 { +4725 self.events.push_back(Event::DatagramReceived); +4726 } +4727 } +4728 Frame::AckFrequency(ack_frequency) => { +4729 // This frame can only be sent in the Data space +4730 +4731 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? { +4732 // The AckFrequency frame is stale (we have already received a more +4733 // recent one) +4734 continue; +4735 } +4736 +4737 // Update the params for all of our paths +4738 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() { +4739 space.pending_acks.set_ack_frequency_params(&ack_frequency); +4740 +4741 // Our `max_ack_delay` has been updated, so we may need to adjust +4742 // its associated timeout +4743 if let Some(timeout) = space +4744 .pending_acks +4745 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay) +4746 { +4747 self.timers.set( +4748 Timer::PerPath(*path_id, PathTimer::MaxAckDelay), +4749 timeout, +4750 self.qlog.with_time(now), +4751 ); +4752 } +4753 } +4754 } +4755 Frame::ImmediateAck => { +4756 // This frame can only be sent in the Data space +4757 for pns in self.spaces[SpaceId::Data].iter_paths_mut() { +4758 pns.pending_acks.set_immediate_ack_required(); +4759 } +4760 } +4761 Frame::HandshakeDone => { +4762 if self.side.is_server() { +4763 return Err(TransportError::PROTOCOL_VIOLATION( +4764 "client sent HANDSHAKE_DONE", +4765 )); +4766 } +4767 if self.spaces[SpaceId::Handshake].crypto.is_some() { +4768 self.discard_space(now, SpaceId::Handshake); +4769 } +4770 self.events.push_back(Event::HandshakeConfirmed); +4771 trace!("handshake confirmed"); +4772 } +4773 Frame::ObservedAddr(observed) => { +4774 // check if params allows the peer to send report and this node to receive it +4775 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port); +4776 if !self +4777 .peer_params +4778 .address_discovery_role +4779 .should_report(&self.config.address_discovery_role) +4780 { +4781 return Err(TransportError::PROTOCOL_VIOLATION( +4782 "received OBSERVED_ADDRESS frame when not negotiated", +4783 )); +4784 } +4785 // must only be sent in data space +4786 if packet.header.space() != SpaceId::Data { +4787 return Err(TransportError::PROTOCOL_VIOLATION( +4788 "OBSERVED_ADDRESS frame outside data space", +4789 )); +4790 } +4791 +4792 let path = self.path_data_mut(path_id); +4793 if network_path == path.network_path { +4794 if let Some(updated) = path.update_observed_addr_report(observed) { +4795 if path.open { +4796 self.events.push_back(Event::Path(PathEvent::ObservedAddr { +4797 id: path_id, +4798 addr: updated, +4799 })); +4800 } +4801 // otherwise the event is reported when the path is deemed open +4802 } +4803 } else { +4804 // include in migration +4805 migration_observed_addr = Some(observed) +4806 } +4807 } +4808 Frame::PathAbandon(frame::PathAbandon { +4809 path_id, +4810 error_code, +4811 }) => { +4812 span.record("path", tracing::field::debug(&path_id)); +4813 // TODO(flub): don't really know which error code to use here. +4814 let already_abandoned = match self.close_path(now, path_id, error_code.into()) { +4815 Ok(()) => { +4816 trace!("peer abandoned path"); +4817 false +4818 } +4819 Err(ClosePathError::LastOpenPath) => { +4820 trace!("peer abandoned last path, closing connection"); +4821 // TODO(flub): which error code? +4822 return Err(TransportError::NO_ERROR("last path abandoned by peer")); +4823 } +4824 Err(ClosePathError::ClosedPath) => { +4825 trace!("peer abandoned already closed path"); +4826 true +4827 } +4828 }; +4829 // If we receive a retransmit of PATH_ABANDON then we may already have +4830 // abandoned this path locally. In that case the DiscardPath timer +4831 // may already have fired and we no longer have any state for this path. +4832 // Only set this timer if we still have path state. +4833 if self.path(path_id).is_some() && !already_abandoned { +4834 // TODO(flub): Checking is_some() here followed by a number of calls +4835 // that would panic if it was None is really ugly. If only we +4836 // could do something like PathData::pto(). One day we'll have +4837 // unified SpaceId and PathId and this will be possible. +4838 let delay = self.pto(SpaceId::Data, path_id) * 3; +4839 self.timers.set( +4840 Timer::PerPath(path_id, PathTimer::DiscardPath), +4841 now + delay, +4842 self.qlog.with_time(now), +4843 ); +4844 } +4845 } +4846 Frame::PathStatusAvailable(info) => { +4847 span.record("path", tracing::field::debug(&info.path_id)); +4848 if self.is_multipath_negotiated() { +4849 self.on_path_status( +4850 info.path_id, +4851 PathStatus::Available, +4852 info.status_seq_no, +4853 ); +4854 } else { +4855 return Err(TransportError::PROTOCOL_VIOLATION( +4856 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated", +4857 )); +4858 } +4859 } +4860 Frame::PathStatusBackup(info) => { +4861 span.record("path", tracing::field::debug(&info.path_id)); +4862 if self.is_multipath_negotiated() { +4863 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no); +4864 } else { +4865 return Err(TransportError::PROTOCOL_VIOLATION( +4866 "received PATH_STATUS_BACKUP frame when multipath was not negotiated", +4867 )); +4868 } +4869 } +4870 Frame::MaxPathId(frame::MaxPathId(path_id)) => { +4871 span.record("path", tracing::field::debug(&path_id)); +4872 if !self.is_multipath_negotiated() { +4873 return Err(TransportError::PROTOCOL_VIOLATION( +4874 "received MAX_PATH_ID frame when multipath was not negotiated", +4875 )); +4876 } +4877 // frames that do not increase the path id are ignored +4878 if path_id > self.remote_max_path_id { +4879 self.remote_max_path_id = path_id; +4880 self.issue_first_path_cids(now); +4881 while let Some(true) = self.continue_nat_traversal_round(now) {} +4882 } +4883 } +4884 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => { +4885 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST +4886 // be treated as a connection error of type PROTOCOL_VIOLATION. +4887 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> +4888 if self.is_multipath_negotiated() { +4889 if max_path_id > self.local_max_path_id { +4890 return Err(TransportError::PROTOCOL_VIOLATION( +4891 "PATHS_BLOCKED maximum path identifier was larger than local maximum", +4892 )); +4893 } +4894 debug!("received PATHS_BLOCKED({:?})", max_path_id); +4895 // TODO(@divma): ensure max concurrent paths +4896 } else { +4897 return Err(TransportError::PROTOCOL_VIOLATION( +4898 "received PATHS_BLOCKED frame when not multipath was not negotiated", +4899 )); +4900 } +4901 } +4902 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => { +4903 // Nothing to do. This is recorded in the frame stats, but otherwise we +4904 // always issue all CIDs we're allowed to issue, so either this is an +4905 // impatient peer or a bug on our side. +4906 +4907 // Receipt of a value of Maximum Path Identifier or Path Identifier that is higher than the local maximum value MUST +4908 // be treated as a connection error of type PROTOCOL_VIOLATION. +4909 // Ref <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-14.html#name-paths_blocked-and-path_cids> +4910 if self.is_multipath_negotiated() { +4911 if path_id > self.local_max_path_id { +4912 return Err(TransportError::PROTOCOL_VIOLATION( +4913 "PATH_CIDS_BLOCKED path identifier was larger than local maximum", +4914 )); +4915 } +4916 if next_seq.0 +4917 > self +4918 .local_cid_state +4919 .get(&path_id) +4920 .map(|cid_state| cid_state.active_seq().1 + 1) +4921 .unwrap_or_default() +4922 { +4923 return Err(TransportError::PROTOCOL_VIOLATION( +4924 "PATH_CIDS_BLOCKED next sequence number larger than in local state", +4925 )); +4926 } +4927 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED"); +4928 } else { +4929 return Err(TransportError::PROTOCOL_VIOLATION( +4930 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated", +4931 )); +4932 } +4933 } +4934 Frame::AddAddress(addr) => { +4935 let client_state = match self.iroh_hp.client_side_mut() { +4936 Ok(state) => state, +4937 Err(err) => { +4938 return Err(TransportError::PROTOCOL_VIOLATION(format!( +4939 "Nat traversal(ADD_ADDRESS): {err}" +4940 ))); +4941 } +4942 }; 4943 -4944 match client_state.add_remote_address(addr) { -4945 Ok(maybe_added) => { -4946 if let Some(added) = maybe_added { -4947 self.events.push_back(Event::NatTraversal( -4948 iroh_hp::Event::AddressAdded(added), -4949 )); -4950 } -4951 } -4952 Err(e) => { -4953 warn!(%e, "failed to add remote address") -4954 } -4955 } -4956 } -4957 Frame::RemoveAddress(addr) => { -4958 let client_state = match self.iroh_hp.client_side_mut() { -4959 Ok(state) => state, -4960 Err(err) => { -4961 return Err(TransportError::PROTOCOL_VIOLATION(format!( -4962 "Nat traversal(REMOVE_ADDRESS): {err}" -4963 ))); -4964 } -4965 }; -4966 if let Some(removed_addr) = client_state.remove_remote_address(addr) { -4967 self.events -4968 .push_back(Event::NatTraversal(iroh_hp::Event::AddressRemoved( -4969 removed_addr, -4970 ))); -4971 } -4972 } -4973 Frame::ReachOut(reach_out) => { -4974 let server_state = match self.iroh_hp.server_side_mut() { -4975 Ok(state) => state, -4976 Err(err) => { -4977 return Err(TransportError::PROTOCOL_VIOLATION(format!( -4978 "Nat traversal(REACH_OUT): {err}" -4979 ))); -4980 } -4981 }; -4982 -4983 if let Err(err) = server_state.handle_reach_out(reach_out) { -4984 return Err(TransportError::PROTOCOL_VIOLATION(format!( -4985 "Nat traversal(REACH_OUT): {err}" -4986 ))); -4987 } -4988 } -4989 } -4990 } -4991 -4992 let space = self.spaces[SpaceId::Data].for_path(path_id); -4993 if space -4994 .pending_acks -4995 .packet_received(now, number, ack_eliciting, &space.dedup) -4996 { -4997 if self.abandoned_paths.contains(&path_id) { -4998 // § 3.4.3 QUIC-MULTIPATH: promptly send ACKs for packets received from -4999 // abandoned paths. -5000 space.pending_acks.set_immediate_ack_required(); -5001 } else { -5002 self.timers.set( -5003 Timer::PerPath(path_id, PathTimer::MaxAckDelay), -5004 now + self.ack_frequency.max_ack_delay, -5005 self.qlog.with_time(now), -5006 ); -5007 } -5008 } -5009 -5010 // Issue stream ID credit due to ACKs of outgoing finish/resets and incoming finish/resets -5011 // on stopped streams. Incoming finishes/resets on open streams are not handled here as they -5012 // are only freed, and hence only issue credit, once the application has been notified -5013 // during a read on the stream. -5014 let pending = &mut self.spaces[SpaceId::Data].pending; -5015 self.streams.queue_max_stream_id(pending); -5016 -5017 if let Some(reason) = close { -5018 self.state.move_to_draining(Some(reason.into())); -5019 self.close = true; -5020 } +4944 if !client_state.check_remote_address(&addr) { +4945 // if the address is not valid we flag it, but update anyway +4946 warn!(?addr, "server sent illegal ADD_ADDRESS frame"); +4947 } +4948 +4949 match client_state.add_remote_address(addr) { +4950 Ok(maybe_added) => { +4951 if let Some(added) = maybe_added { +4952 self.events.push_back(Event::NatTraversal( +4953 iroh_hp::Event::AddressAdded(added), +4954 )); +4955 } +4956 } +4957 Err(e) => { +4958 warn!(%e, "failed to add remote address") +4959 } +4960 } +4961 } +4962 Frame::RemoveAddress(addr) => { +4963 let client_state = match self.iroh_hp.client_side_mut() { +4964 Ok(state) => state, +4965 Err(err) => { +4966 return Err(TransportError::PROTOCOL_VIOLATION(format!( +4967 "Nat traversal(REMOVE_ADDRESS): {err}" +4968 ))); +4969 } +4970 }; +4971 if let Some(removed_addr) = client_state.remove_remote_address(addr) { +4972 self.events +4973 .push_back(Event::NatTraversal(iroh_hp::Event::AddressRemoved( +4974 removed_addr, +4975 ))); +4976 } +4977 } +4978 Frame::ReachOut(reach_out) => { +4979 let server_state = match self.iroh_hp.server_side_mut() { +4980 Ok(state) => state, +4981 Err(err) => { +4982 return Err(TransportError::PROTOCOL_VIOLATION(format!( +4983 "Nat traversal(REACH_OUT): {err}" +4984 ))); +4985 } +4986 }; +4987 +4988 if let Err(err) = server_state.handle_reach_out(reach_out) { +4989 return Err(TransportError::PROTOCOL_VIOLATION(format!( +4990 "Nat traversal(REACH_OUT): {err}" +4991 ))); +4992 } +4993 } +4994 } +4995 } +4996 +4997 let space = self.spaces[SpaceId::Data].for_path(path_id); +4998 if space +4999 .pending_acks +5000 .packet_received(now, number, ack_eliciting, &space.dedup) +5001 { +5002 if self.abandoned_paths.contains(&path_id) { +5003 // § 3.4.3 QUIC-MULTIPATH: promptly send ACKs for packets received from +5004 // abandoned paths. +5005 space.pending_acks.set_immediate_ack_required(); +5006 } else { +5007 self.timers.set( +5008 Timer::PerPath(path_id, PathTimer::MaxAckDelay), +5009 now + self.ack_frequency.max_ack_delay, +5010 self.qlog.with_time(now), +5011 ); +5012 } +5013 } +5014 +5015 // Issue stream ID credit due to ACKs of outgoing finish/resets and incoming finish/resets +5016 // on stopped streams. Incoming finishes/resets on open streams are not handled here as they +5017 // are only freed, and hence only issue credit, once the application has been notified +5018 // during a read on the stream. +5019 let pending = &mut self.spaces[SpaceId::Data].pending; +5020 self.streams.queue_max_stream_id(pending); 5021 -5022 if Some(number) == self.spaces[SpaceId::Data].for_path(path_id).rx_packet -5023 && !is_probing_packet -5024 && network_path != self.path_data(path_id).network_path -5025 { -5026 let ConnectionSide::Server { ref server_config } = self.side else { -5027 panic!("packets from unknown remote should be dropped by clients"); -5028 }; -5029 debug_assert!( -5030 server_config.migration, -5031 "migration-initiating packets should have been dropped immediately" -5032 ); -5033 self.migrate(path_id, now, network_path, migration_observed_addr); -5034 // Break linkability, if possible -5035 self.update_rem_cid(path_id); -5036 self.spin = false; -5037 } -5038 -5039 Ok(()) -5040 } -5041 -5042 fn migrate( -5043 &mut self, -5044 path_id: PathId, -5045 now: Instant, -5046 network_path: FourTuple, -5047 observed_addr: Option<ObservedAddr>, -5048 ) { -5049 trace!(%network_path, %path_id, "migration initiated"); -5050 self.path_counter = self.path_counter.wrapping_add(1); -5051 // TODO(@divma): conditions for path migration in multipath are very specific, check them -5052 // again to prevent path migrations that should actually create a new path -5053 -5054 // Reset rtt/congestion state for new path unless it looks like a NAT rebinding. -5055 // Note that the congestion window will not grow until validation terminates. Helps mitigate -5056 // amplification attacks performed by spoofing source addresses. -5057 let prev_pto = self.pto(SpaceId::Data, path_id); -5058 let known_path = self.paths.get_mut(&path_id).expect("known path"); -5059 let path = &mut known_path.data; -5060 let mut new_path = if network_path.remote.is_ipv4() -5061 && network_path.remote.ip() == path.network_path.remote.ip() -5062 { -5063 PathData::from_previous(network_path, path, self.path_counter, now) -5064 } else { -5065 let peer_max_udp_payload_size = -5066 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()) -5067 .unwrap_or(u16::MAX); -5068 PathData::new( -5069 network_path, -5070 self.allow_mtud, -5071 Some(peer_max_udp_payload_size), -5072 self.path_counter, -5073 now, -5074 &self.config, -5075 ) -5076 }; -5077 new_path.last_observed_addr_report = path.last_observed_addr_report.clone(); -5078 if let Some(report) = observed_addr { -5079 if let Some(updated) = new_path.update_observed_addr_report(report) { -5080 tracing::info!("adding observed addr event from migration"); -5081 self.events.push_back(Event::Path(PathEvent::ObservedAddr { -5082 id: path_id, -5083 addr: updated, -5084 })); -5085 } -5086 } -5087 new_path.send_new_challenge = true; -5088 -5089 let mut prev = mem::replace(path, new_path); -5090 // Don't clobber the original path if the previous one hasn't been validated yet -5091 if !prev.is_validating_path() { -5092 prev.send_new_challenge = true; -5093 // We haven't updated the remote CID yet, this captures the remote CID we were using on -5094 // the previous path. -5095 -5096 known_path.prev = Some((self.rem_cids.get(&path_id).unwrap().active(), prev)); -5097 } -5098 -5099 // We need to re-assign the correct remote to this path in qlog -5100 self.qlog.emit_tuple_assigned(path_id, network_path, now); -5101 -5102 self.timers.set( -5103 Timer::PerPath(path_id, PathTimer::PathValidation), -5104 now + 3 * cmp::max(self.pto(SpaceId::Data, path_id), prev_pto), -5105 self.qlog.with_time(now), -5106 ); -5107 } -5108 -5109 /// Handle a change in the local address, i.e. an active migration -5110 pub fn local_address_changed(&mut self) { -5111 // TODO(flub): if multipath is enabled this needs to create a new path entirely. -5112 self.update_rem_cid(PathId::ZERO); -5113 self.ping(); -5114 } -5115 -5116 /// Switch to a previously unused remote connection ID, if possible -5117 fn update_rem_cid(&mut self, path_id: PathId) { -5118 let Some((reset_token, retired)) = -5119 self.rem_cids.get_mut(&path_id).and_then(|cids| cids.next()) -5120 else { -5121 return; -5122 }; -5123 -5124 // Retire the current remote CID and any CIDs we had to skip. -5125 self.spaces[SpaceId::Data] -5126 .pending -5127 .retire_cids -5128 .extend(retired.map(|seq| (path_id, seq))); -5129 let remote = self.path_data(path_id).network_path.remote; -5130 self.set_reset_token(path_id, remote, reset_token); -5131 } -5132 -5133 /// Sends this reset token to the endpoint -5134 /// -5135 /// The endpoint needs to know the reset tokens issued by the peer, so that if the peer -5136 /// sends a reset token it knows to route it to this connection. See RFC 9000 section -5137 /// 10.3. Stateless Reset. -5138 /// -5139 /// Reset tokens are different for each path, the endpoint identifies paths by peer -5140 /// socket address however, not by path ID. -5141 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) { -5142 self.endpoint_events -5143 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); -5144 -5145 // During the handshake the server sends a reset token in the transport -5146 // parameters. When we are the client and we receive the reset token during the -5147 // handshake we want this to affect our peer transport parameters. -5148 // TODO(flub): Pretty sure this is pointless, the entire params is overwritten -5149 // shortly after this was called. And then the params don't have this anymore. -5150 if path_id == PathId::ZERO { -5151 self.peer_params.stateless_reset_token = Some(reset_token); -5152 } -5153 } -5154 -5155 /// Issue an initial set of connection IDs to the peer upon connection -5156 fn issue_first_cids(&mut self, now: Instant) { -5157 if self -5158 .local_cid_state -5159 .get(&PathId::ZERO) -5160 .expect("PathId::ZERO exists when the connection is created") -5161 .cid_len() -5162 == 0 -5163 { -5164 return; -5165 } -5166 -5167 // Subtract 1 to account for the CID we supplied while handshaking -5168 let mut n = self.peer_params.issue_cids_limit() - 1; -5169 if let ConnectionSide::Server { server_config } = &self.side { -5170 if server_config.has_preferred_address() { -5171 // We also sent a CID in the transport parameters -5172 n -= 1; -5173 } -5174 } -5175 self.endpoint_events -5176 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); -5177 } -5178 -5179 /// Issues an initial set of CIDs for paths that have not yet had any CIDs issued -5180 /// -5181 /// Later CIDs are issued when CIDs expire or are retired by the peer. -5182 fn issue_first_path_cids(&mut self, now: Instant) { -5183 if let Some(max_path_id) = self.max_path_id() { -5184 let mut path_id = self.max_path_id_with_cids.next(); -5185 while path_id <= max_path_id { -5186 self.endpoint_events -5187 .push_back(EndpointEventInner::NeedIdentifiers( -5188 path_id, -5189 now, -5190 self.peer_params.issue_cids_limit(), -5191 )); -5192 path_id = path_id.next(); -5193 } -5194 self.max_path_id_with_cids = max_path_id; -5195 } -5196 } -5197 -5198 /// Populates a packet with frames -5199 /// -5200 /// This tries to fit as many frames as possible into the packet. -5201 /// -5202 /// *path_exclusive_only* means to only build frames which can only be sent on this -5203 /// *path. This is used in multipath for backup paths while there is still an active -5204 /// *path. -5205 fn populate_packet( -5206 &mut self, -5207 now: Instant, -5208 space_id: SpaceId, -5209 path_id: PathId, -5210 path_exclusive_only: bool, -5211 buf: &mut impl BufMut, -5212 pn: u64, -5213 #[allow(unused)] qlog: &mut QlogSentPacket, -5214 ) -> SentFrames { -5215 let mut sent = SentFrames::default(); -5216 let is_multipath_negotiated = self.is_multipath_negotiated(); -5217 let space = &mut self.spaces[space_id]; -5218 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; -5219 let is_0rtt = space_id == SpaceId::Data && space.crypto.is_none(); -5220 space -5221 .for_path(path_id) -5222 .pending_acks -5223 .maybe_ack_non_eliciting(); -5224 -5225 // HANDSHAKE_DONE -5226 if !is_0rtt && mem::replace(&mut space.pending.handshake_done, false) { -5227 trace!("HANDSHAKE_DONE"); -5228 buf.write(frame::FrameType::HandshakeDone); -5229 qlog.frame(&Frame::HandshakeDone); -5230 sent.retransmits.get_or_create().handshake_done = true; -5231 // This is just a u8 counter and the frame is typically just sent once -5232 self.stats.frame_tx.handshake_done = -5233 self.stats.frame_tx.handshake_done.saturating_add(1); -5234 } -5235 -5236 // REACH_OUT -5237 // TODO(@divma): path explusive considerations -5238 if let Some((round, addresses)) = space.pending.reach_out.as_mut() { -5239 while let Some(local_addr) = addresses.pop() { -5240 let reach_out = frame::ReachOut::new(*round, local_addr); -5241 if buf.remaining_mut() > reach_out.size() { -5242 trace!(%round, ?local_addr, "REACH_OUT"); -5243 reach_out.encode(buf); -5244 let sent_reachouts = sent -5245 .retransmits -5246 .get_or_create() -5247 .reach_out -5248 .get_or_insert_with(|| (*round, Default::default())); -5249 sent_reachouts.1.push(local_addr); -5250 self.stats.frame_tx.reach_out = self.stats.frame_tx.reach_out.saturating_add(1); -5251 qlog.frame(&Frame::ReachOut(reach_out)); -5252 } else { -5253 addresses.push(local_addr); -5254 break; -5255 } -5256 } -5257 if addresses.is_empty() { -5258 space.pending.reach_out = None; -5259 } -5260 } -5261 -5262 // OBSERVED_ADDR -5263 if !path_exclusive_only -5264 && space_id == SpaceId::Data -5265 && self -5266 .config -5267 .address_discovery_role -5268 .should_report(&self.peer_params.address_discovery_role) -5269 && (!path.observed_addr_sent || space.pending.observed_addr) -5270 { -5271 let frame = -5272 frame::ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no); -5273 if buf.remaining_mut() > frame.size() { -5274 trace!(seq = %frame.seq_no, ip = %frame.ip, port = frame.port, "OBSERVED_ADDRESS"); -5275 frame.encode(buf); -5276 -5277 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8); -5278 path.observed_addr_sent = true; -5279 -5280 self.stats.frame_tx.observed_addr += 1; -5281 sent.retransmits.get_or_create().observed_addr = true; -5282 space.pending.observed_addr = false; -5283 qlog.frame(&Frame::ObservedAddr(frame)); -5284 } -5285 } -5286 -5287 // PING -5288 if mem::replace(&mut space.for_path(path_id).ping_pending, false) { -5289 trace!("PING"); -5290 buf.write(frame::FrameType::Ping); -5291 sent.non_retransmits = true; -5292 self.stats.frame_tx.ping += 1; -5293 qlog.frame(&Frame::Ping); -5294 } -5295 -5296 // IMMEDIATE_ACK -5297 if mem::replace(&mut space.for_path(path_id).immediate_ack_pending, false) { -5298 debug_assert_eq!( -5299 space_id, -5300 SpaceId::Data, -5301 "immediate acks must be sent in the data space" -5302 ); -5303 trace!("IMMEDIATE_ACK"); -5304 buf.write(frame::FrameType::ImmediateAck); -5305 sent.non_retransmits = true; -5306 self.stats.frame_tx.immediate_ack += 1; -5307 qlog.frame(&Frame::ImmediateAck); -5308 } -5309 -5310 // ACK -5311 // TODO(flub): Should this send acks for this path anyway? -5312 -5313 if !path_exclusive_only { -5314 for path_id in space -5315 .number_spaces -5316 .iter_mut() -5317 .filter(|(_, pns)| pns.pending_acks.can_send()) -5318 .map(|(&path_id, _)| path_id) -5319 .collect::<Vec<_>>() -5320 { -5321 Self::populate_acks( -5322 now, -5323 self.receiving_ecn, -5324 &mut sent, -5325 path_id, -5326 space_id, -5327 space, -5328 is_multipath_negotiated, -5329 buf, -5330 &mut self.stats, -5331 qlog, -5332 ); -5333 } -5334 } -5335 -5336 // ACK_FREQUENCY -5337 if !path_exclusive_only && mem::replace(&mut space.pending.ack_frequency, false) { -5338 let sequence_number = self.ack_frequency.next_sequence_number(); -5339 -5340 // Safe to unwrap because this is always provided when ACK frequency is enabled -5341 let config = self.config.ack_frequency_config.as_ref().unwrap(); -5342 -5343 // Ensure the delay is within bounds to avoid a PROTOCOL_VIOLATION error -5344 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay( -5345 path.rtt.get(), -5346 config, -5347 &self.peer_params, -5348 ); -5349 -5350 trace!(?max_ack_delay, "ACK_FREQUENCY"); -5351 -5352 let frame = frame::AckFrequency { -5353 sequence: sequence_number, -5354 ack_eliciting_threshold: config.ack_eliciting_threshold, -5355 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX), -5356 reordering_threshold: config.reordering_threshold, -5357 }; -5358 frame.encode(buf); -5359 qlog.frame(&Frame::AckFrequency(frame)); -5360 -5361 sent.retransmits.get_or_create().ack_frequency = true; -5362 -5363 self.ack_frequency -5364 .ack_frequency_sent(path_id, pn, max_ack_delay); -5365 self.stats.frame_tx.ack_frequency += 1; -5366 } +5022 if let Some(reason) = close { +5023 self.state.move_to_draining(Some(reason.into())); +5024 self.close = true; +5025 } +5026 +5027 if Some(number) == self.spaces[SpaceId::Data].for_path(path_id).rx_packet +5028 && !is_probing_packet +5029 && network_path != self.path_data(path_id).network_path +5030 { +5031 let ConnectionSide::Server { ref server_config } = self.side else { +5032 panic!("packets from unknown remote should be dropped by clients"); +5033 }; +5034 debug_assert!( +5035 server_config.migration, +5036 "migration-initiating packets should have been dropped immediately" +5037 ); +5038 self.migrate(path_id, now, network_path, migration_observed_addr); +5039 // Break linkability, if possible +5040 self.update_rem_cid(path_id); +5041 self.spin = false; +5042 } +5043 +5044 Ok(()) +5045 } +5046 +5047 fn migrate( +5048 &mut self, +5049 path_id: PathId, +5050 now: Instant, +5051 network_path: FourTuple, +5052 observed_addr: Option<ObservedAddr>, +5053 ) { +5054 trace!(%network_path, %path_id, "migration initiated"); +5055 self.path_generation_counter = self.path_generation_counter.wrapping_add(1); +5056 // TODO(@divma): conditions for path migration in multipath are very specific, check them +5057 // again to prevent path migrations that should actually create a new path +5058 +5059 // Reset rtt/congestion state for new path unless it looks like a NAT rebinding. +5060 // Note that the congestion window will not grow until validation terminates. Helps mitigate +5061 // amplification attacks performed by spoofing source addresses. +5062 let prev_pto = self.pto(SpaceId::Data, path_id); +5063 let known_path = self.paths.get_mut(&path_id).expect("known path"); +5064 let path = &mut known_path.data; +5065 let mut new_path = if network_path.remote.is_ipv4() +5066 && network_path.remote.ip() == path.network_path.remote.ip() +5067 { +5068 PathData::from_previous(network_path, path, self.path_generation_counter, now) +5069 } else { +5070 let peer_max_udp_payload_size = +5071 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()) +5072 .unwrap_or(u16::MAX); +5073 PathData::new( +5074 network_path, +5075 self.allow_mtud, +5076 Some(peer_max_udp_payload_size), +5077 self.path_generation_counter, +5078 now, +5079 &self.config, +5080 ) +5081 }; +5082 new_path.last_observed_addr_report = path.last_observed_addr_report.clone(); +5083 if let Some(report) = observed_addr { +5084 if let Some(updated) = new_path.update_observed_addr_report(report) { +5085 tracing::info!("adding observed addr event from migration"); +5086 self.events.push_back(Event::Path(PathEvent::ObservedAddr { +5087 id: path_id, +5088 addr: updated, +5089 })); +5090 } +5091 } +5092 new_path.send_new_challenge = true; +5093 +5094 let mut prev = mem::replace(path, new_path); +5095 // Don't clobber the original path if the previous one hasn't been validated yet +5096 if !prev.is_validating_path() { +5097 prev.send_new_challenge = true; +5098 // We haven't updated the remote CID yet, this captures the remote CID we were using on +5099 // the previous path. +5100 +5101 known_path.prev = Some((self.rem_cids.get(&path_id).unwrap().active(), prev)); +5102 } +5103 +5104 // We need to re-assign the correct remote to this path in qlog +5105 self.qlog.emit_tuple_assigned(path_id, network_path, now); +5106 +5107 self.timers.set( +5108 Timer::PerPath(path_id, PathTimer::PathValidation), +5109 now + 3 * cmp::max(self.pto(SpaceId::Data, path_id), prev_pto), +5110 self.qlog.with_time(now), +5111 ); +5112 } +5113 +5114 /// Handle a change in the local address, i.e. an active migration +5115 pub fn local_address_changed(&mut self) { +5116 // TODO(flub): if multipath is enabled this needs to create a new path entirely. +5117 self.update_rem_cid(PathId::ZERO); +5118 self.ping(); +5119 } +5120 +5121 /// Switch to a previously unused remote connection ID, if possible +5122 fn update_rem_cid(&mut self, path_id: PathId) { +5123 let Some((reset_token, retired)) = +5124 self.rem_cids.get_mut(&path_id).and_then(|cids| cids.next()) +5125 else { +5126 return; +5127 }; +5128 +5129 // Retire the current remote CID and any CIDs we had to skip. +5130 self.spaces[SpaceId::Data] +5131 .pending +5132 .retire_cids +5133 .extend(retired.map(|seq| (path_id, seq))); +5134 let remote = self.path_data(path_id).network_path.remote; +5135 self.set_reset_token(path_id, remote, reset_token); +5136 } +5137 +5138 /// Sends this reset token to the endpoint +5139 /// +5140 /// The endpoint needs to know the reset tokens issued by the peer, so that if the peer +5141 /// sends a reset token it knows to route it to this connection. See RFC 9000 section +5142 /// 10.3. Stateless Reset. +5143 /// +5144 /// Reset tokens are different for each path, the endpoint identifies paths by peer +5145 /// socket address however, not by path ID. +5146 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) { +5147 self.endpoint_events +5148 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token)); +5149 +5150 // During the handshake the server sends a reset token in the transport +5151 // parameters. When we are the client and we receive the reset token during the +5152 // handshake we want this to affect our peer transport parameters. +5153 // TODO(flub): Pretty sure this is pointless, the entire params is overwritten +5154 // shortly after this was called. And then the params don't have this anymore. +5155 if path_id == PathId::ZERO { +5156 self.peer_params.stateless_reset_token = Some(reset_token); +5157 } +5158 } +5159 +5160 /// Issue an initial set of connection IDs to the peer upon connection +5161 fn issue_first_cids(&mut self, now: Instant) { +5162 if self +5163 .local_cid_state +5164 .get(&PathId::ZERO) +5165 .expect("PathId::ZERO exists when the connection is created") +5166 .cid_len() +5167 == 0 +5168 { +5169 return; +5170 } +5171 +5172 // Subtract 1 to account for the CID we supplied while handshaking +5173 let mut n = self.peer_params.issue_cids_limit() - 1; +5174 if let ConnectionSide::Server { server_config } = &self.side { +5175 if server_config.has_preferred_address() { +5176 // We also sent a CID in the transport parameters +5177 n -= 1; +5178 } +5179 } +5180 self.endpoint_events +5181 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); +5182 } +5183 +5184 /// Issues an initial set of CIDs for paths that have not yet had any CIDs issued +5185 /// +5186 /// Later CIDs are issued when CIDs expire or are retired by the peer. +5187 fn issue_first_path_cids(&mut self, now: Instant) { +5188 if let Some(max_path_id) = self.max_path_id() { +5189 let mut path_id = self.max_path_id_with_cids.next(); +5190 while path_id <= max_path_id { +5191 self.endpoint_events +5192 .push_back(EndpointEventInner::NeedIdentifiers( +5193 path_id, +5194 now, +5195 self.peer_params.issue_cids_limit(), +5196 )); +5197 path_id = path_id.next(); +5198 } +5199 self.max_path_id_with_cids = max_path_id; +5200 } +5201 } +5202 +5203 /// Populates a packet with frames +5204 /// +5205 /// This tries to fit as many frames as possible into the packet. +5206 /// +5207 /// *path_exclusive_only* means to only build frames which can only be sent on this +5208 /// *path. This is used in multipath for backup paths while there is still an active +5209 /// *path. +5210 fn populate_packet( +5211 &mut self, +5212 now: Instant, +5213 space_id: SpaceId, +5214 path_id: PathId, +5215 path_exclusive_only: bool, +5216 buf: &mut impl BufMut, +5217 pn: u64, +5218 #[allow(unused)] qlog: &mut QlogSentPacket, +5219 ) -> SentFrames { +5220 let mut sent = SentFrames::default(); +5221 let is_multipath_negotiated = self.is_multipath_negotiated(); +5222 let space = &mut self.spaces[space_id]; +5223 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; +5224 let is_0rtt = space_id == SpaceId::Data && space.crypto.is_none(); +5225 space +5226 .for_path(path_id) +5227 .pending_acks +5228 .maybe_ack_non_eliciting(); +5229 +5230 // HANDSHAKE_DONE +5231 if !is_0rtt && mem::replace(&mut space.pending.handshake_done, false) { +5232 trace!("HANDSHAKE_DONE"); +5233 buf.write(frame::FrameType::HandshakeDone); +5234 qlog.frame(&Frame::HandshakeDone); +5235 sent.retransmits.get_or_create().handshake_done = true; +5236 // This is just a u8 counter and the frame is typically just sent once +5237 self.stats.frame_tx.handshake_done = +5238 self.stats.frame_tx.handshake_done.saturating_add(1); +5239 } +5240 +5241 // REACH_OUT +5242 // TODO(@divma): path explusive considerations +5243 if let Some((round, addresses)) = space.pending.reach_out.as_mut() { +5244 while let Some(local_addr) = addresses.pop() { +5245 let reach_out = frame::ReachOut::new(*round, local_addr); +5246 if buf.remaining_mut() > reach_out.size() { +5247 trace!(%round, ?local_addr, "REACH_OUT"); +5248 reach_out.encode(buf); +5249 let sent_reachouts = sent +5250 .retransmits +5251 .get_or_create() +5252 .reach_out +5253 .get_or_insert_with(|| (*round, Default::default())); +5254 sent_reachouts.1.push(local_addr); +5255 self.stats.frame_tx.reach_out = self.stats.frame_tx.reach_out.saturating_add(1); +5256 qlog.frame(&Frame::ReachOut(reach_out)); +5257 } else { +5258 addresses.push(local_addr); +5259 break; +5260 } +5261 } +5262 if addresses.is_empty() { +5263 space.pending.reach_out = None; +5264 } +5265 } +5266 +5267 // OBSERVED_ADDR +5268 if !path_exclusive_only +5269 && space_id == SpaceId::Data +5270 && self +5271 .config +5272 .address_discovery_role +5273 .should_report(&self.peer_params.address_discovery_role) +5274 && (!path.observed_addr_sent || space.pending.observed_addr) +5275 { +5276 let frame = +5277 frame::ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no); +5278 if buf.remaining_mut() > frame.size() { +5279 trace!(seq = %frame.seq_no, ip = %frame.ip, port = frame.port, "OBSERVED_ADDRESS"); +5280 frame.encode(buf); +5281 +5282 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8); +5283 path.observed_addr_sent = true; +5284 +5285 self.stats.frame_tx.observed_addr += 1; +5286 sent.retransmits.get_or_create().observed_addr = true; +5287 space.pending.observed_addr = false; +5288 qlog.frame(&Frame::ObservedAddr(frame)); +5289 } +5290 } +5291 +5292 // PING +5293 if mem::replace(&mut space.for_path(path_id).ping_pending, false) { +5294 trace!("PING"); +5295 buf.write(frame::FrameType::Ping); +5296 sent.non_retransmits = true; +5297 self.stats.frame_tx.ping += 1; +5298 qlog.frame(&Frame::Ping); +5299 } +5300 +5301 // IMMEDIATE_ACK +5302 if mem::replace(&mut space.for_path(path_id).immediate_ack_pending, false) { +5303 debug_assert_eq!( +5304 space_id, +5305 SpaceId::Data, +5306 "immediate acks must be sent in the data space" +5307 ); +5308 trace!("IMMEDIATE_ACK"); +5309 buf.write(frame::FrameType::ImmediateAck); +5310 sent.non_retransmits = true; +5311 self.stats.frame_tx.immediate_ack += 1; +5312 qlog.frame(&Frame::ImmediateAck); +5313 } +5314 +5315 // ACK +5316 // TODO(flub): Should this send acks for this path anyway? +5317 +5318 if !path_exclusive_only { +5319 for path_id in space +5320 .number_spaces +5321 .iter_mut() +5322 .filter(|(_, pns)| pns.pending_acks.can_send()) +5323 .map(|(&path_id, _)| path_id) +5324 .collect::<Vec<_>>() +5325 { +5326 Self::populate_acks( +5327 now, +5328 self.receiving_ecn, +5329 &mut sent, +5330 path_id, +5331 space_id, +5332 space, +5333 is_multipath_negotiated, +5334 buf, +5335 &mut self.stats, +5336 qlog, +5337 ); +5338 } +5339 } +5340 +5341 // ACK_FREQUENCY +5342 if !path_exclusive_only && mem::replace(&mut space.pending.ack_frequency, false) { +5343 let sequence_number = self.ack_frequency.next_sequence_number(); +5344 +5345 // Safe to unwrap because this is always provided when ACK frequency is enabled +5346 let config = self.config.ack_frequency_config.as_ref().unwrap(); +5347 +5348 // Ensure the delay is within bounds to avoid a PROTOCOL_VIOLATION error +5349 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay( +5350 path.rtt.get(), +5351 config, +5352 &self.peer_params, +5353 ); +5354 +5355 trace!(?max_ack_delay, "ACK_FREQUENCY"); +5356 +5357 let frame = frame::AckFrequency { +5358 sequence: sequence_number, +5359 ack_eliciting_threshold: config.ack_eliciting_threshold, +5360 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX), +5361 reordering_threshold: config.reordering_threshold, +5362 }; +5363 frame.encode(buf); +5364 qlog.frame(&Frame::AckFrequency(frame)); +5365 +5366 sent.retransmits.get_or_create().ack_frequency = true; 5367 -5368 // PATH_CHALLENGE -5369 if buf.remaining_mut() > frame::PathChallenge::SIZE_BOUND -5370 && space_id == SpaceId::Data -5371 && path.send_new_challenge -5372 && !self.state.is_closed() -5373 // we don't want to send new challenges if we are already closing -5374 { -5375 path.send_new_challenge = false; -5376 -5377 // Generate a new challenge every time we send a new PATH_CHALLENGE -5378 let token = self.rng.random(); -5379 let info = paths::SentChallengeInfo { -5380 sent_instant: now, -5381 network_path: path.network_path, -5382 }; -5383 path.challenges_sent.insert(token, info); -5384 sent.non_retransmits = true; -5385 sent.requires_padding = true; -5386 let challenge = frame::PathChallenge(token); -5387 trace!(frame = %challenge); -5388 buf.write(challenge); -5389 qlog.frame(&Frame::PathChallenge(challenge)); -5390 self.stats.frame_tx.path_challenge += 1; -5391 let pto = self.ack_frequency.max_ack_delay_for_pto() + path.rtt.pto_base(); -5392 self.timers.set( -5393 Timer::PerPath(path_id, PathTimer::PathChallengeLost), -5394 now + pto, -5395 self.qlog.with_time(now), -5396 ); -5397 -5398 if is_multipath_negotiated && !path.validated && path.send_new_challenge { -5399 // queue informing the path status along with the challenge -5400 space.pending.path_status.insert(path_id); -5401 } +5368 self.ack_frequency +5369 .ack_frequency_sent(path_id, pn, max_ack_delay); +5370 self.stats.frame_tx.ack_frequency += 1; +5371 } +5372 +5373 // PATH_CHALLENGE +5374 if buf.remaining_mut() > frame::PathChallenge::SIZE_BOUND +5375 && space_id == SpaceId::Data +5376 && path.send_new_challenge +5377 && !self.state.is_closed() +5378 // we don't want to send new challenges if we are already closing +5379 { +5380 path.send_new_challenge = false; +5381 +5382 // Generate a new challenge every time we send a new PATH_CHALLENGE +5383 let token = self.rng.random(); +5384 let info = paths::SentChallengeInfo { +5385 sent_instant: now, +5386 network_path: path.network_path, +5387 }; +5388 path.challenges_sent.insert(token, info); +5389 sent.non_retransmits = true; +5390 sent.requires_padding = true; +5391 let challenge = frame::PathChallenge(token); +5392 trace!(frame = %challenge); +5393 buf.write(challenge); +5394 qlog.frame(&Frame::PathChallenge(challenge)); +5395 self.stats.frame_tx.path_challenge += 1; +5396 let pto = self.ack_frequency.max_ack_delay_for_pto() + path.rtt.pto_base(); +5397 self.timers.set( +5398 Timer::PerPath(path_id, PathTimer::PathChallengeLost), +5399 now + pto, +5400 self.qlog.with_time(now), +5401 ); 5402 -5403 // Always include an OBSERVED_ADDR frame with a PATH_CHALLENGE, regardless -5404 // of whether one has already been sent on this path. -5405 if space_id == SpaceId::Data -5406 && self -5407 .config -5408 .address_discovery_role -5409 .should_report(&self.peer_params.address_discovery_role) -5410 { -5411 let frame = frame::ObservedAddr::new( -5412 path.network_path.remote, -5413 self.next_observed_addr_seq_no, -5414 ); -5415 if buf.remaining_mut() > frame.size() { -5416 frame.encode(buf); -5417 qlog.frame(&Frame::ObservedAddr(frame)); -5418 -5419 self.next_observed_addr_seq_no = -5420 self.next_observed_addr_seq_no.saturating_add(1u8); -5421 path.observed_addr_sent = true; -5422 -5423 self.stats.frame_tx.observed_addr += 1; -5424 sent.retransmits.get_or_create().observed_addr = true; -5425 space.pending.observed_addr = false; -5426 } -5427 } -5428 } -5429 -5430 // PATH_RESPONSE -5431 if buf.remaining_mut() > frame::PathResponse::SIZE_BOUND && space_id == SpaceId::Data { -5432 if let Some(token) = path.path_responses.pop_on_path(path.network_path) { -5433 sent.non_retransmits = true; -5434 sent.requires_padding = true; -5435 let response = frame::PathResponse(token); -5436 trace!(frame = %response); -5437 buf.write(response); -5438 qlog.frame(&Frame::PathResponse(response)); -5439 self.stats.frame_tx.path_response += 1; -5440 -5441 // NOTE: this is technically not required but might be useful to ride the -5442 // request/response nature of path challenges to refresh an observation -5443 // Since PATH_RESPONSE is a probing frame, this is allowed by the spec. -5444 if space_id == SpaceId::Data -5445 && self -5446 .config -5447 .address_discovery_role -5448 .should_report(&self.peer_params.address_discovery_role) -5449 { -5450 let frame = frame::ObservedAddr::new( -5451 path.network_path.remote, -5452 self.next_observed_addr_seq_no, -5453 ); -5454 if buf.remaining_mut() > frame.size() { -5455 frame.encode(buf); -5456 qlog.frame(&Frame::ObservedAddr(frame)); -5457 -5458 self.next_observed_addr_seq_no = -5459 self.next_observed_addr_seq_no.saturating_add(1u8); -5460 path.observed_addr_sent = true; -5461 -5462 self.stats.frame_tx.observed_addr += 1; -5463 sent.retransmits.get_or_create().observed_addr = true; -5464 space.pending.observed_addr = false; -5465 } -5466 } -5467 } -5468 } -5469 -5470 // CRYPTO -5471 while !path_exclusive_only && buf.remaining_mut() > frame::Crypto::SIZE_BOUND && !is_0rtt { -5472 let mut frame = match space.pending.crypto.pop_front() { -5473 Some(x) => x, -5474 None => break, -5475 }; -5476 -5477 // Calculate the maximum amount of crypto data we can store in the buffer. -5478 // Since the offset is known, we can reserve the exact size required to encode it. -5479 // For length we reserve 2bytes which allows to encode up to 2^14, -5480 // which is more than what fits into normally sized QUIC frames. -5481 let max_crypto_data_size = buf.remaining_mut() -5482 - 1 // Frame Type -5483 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) }) -5484 - 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes -5485 -5486 let len = frame -5487 .data -5488 .len() -5489 .min(2usize.pow(14) - 1) -5490 .min(max_crypto_data_size); -5491 -5492 let data = frame.data.split_to(len); -5493 let truncated = frame::Crypto { -5494 offset: frame.offset, -5495 data, -5496 }; -5497 trace!( -5498 "CRYPTO: off {} len {}", -5499 truncated.offset, -5500 truncated.data.len() -5501 ); -5502 truncated.encode(buf); -5503 self.stats.frame_tx.crypto += 1; -5504 -5505 // The clone is cheap but we still cfg it out if qlog is disabled. -5506 #[cfg(feature = "qlog")] -5507 qlog.frame(&Frame::Crypto(truncated.clone())); -5508 sent.retransmits.get_or_create().crypto.push_back(truncated); -5509 if !frame.data.is_empty() { -5510 frame.offset += len as u64; -5511 space.pending.crypto.push_front(frame); -5512 } -5513 } -5514 -5515 // TODO(flub): maybe this is much higher priority? -5516 // PATH_ABANDON -5517 while !path_exclusive_only -5518 && space_id == SpaceId::Data -5519 && frame::PathAbandon::SIZE_BOUND <= buf.remaining_mut() -5520 { -5521 let Some((path_id, error_code)) = space.pending.path_abandon.pop_first() else { -5522 break; -5523 }; -5524 let frame = frame::PathAbandon { -5525 path_id, -5526 error_code, -5527 }; -5528 frame.encode(buf); -5529 qlog.frame(&Frame::PathAbandon(frame)); -5530 self.stats.frame_tx.path_abandon += 1; -5531 trace!(%path_id, "PATH_ABANDON"); -5532 sent.retransmits -5533 .get_or_create() -5534 .path_abandon -5535 .entry(path_id) -5536 .or_insert(error_code); -5537 } -5538 -5539 // PATH_STATUS_AVAILABLE & PATH_STATUS_BACKUP -5540 while !path_exclusive_only -5541 && space_id == SpaceId::Data -5542 && frame::PathStatusAvailable::SIZE_BOUND <= buf.remaining_mut() -5543 { -5544 let Some(path_id) = space.pending.path_status.pop_first() else { -5545 break; -5546 }; -5547 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else { -5548 trace!(%path_id, "discarding queued path status for unknown path"); -5549 continue; -5550 }; -5551 -5552 let seq = path.status.seq(); -5553 sent.retransmits.get_or_create().path_status.insert(path_id); -5554 match path.local_status() { -5555 PathStatus::Available => { -5556 let frame = frame::PathStatusAvailable { -5557 path_id, -5558 status_seq_no: seq, -5559 }; -5560 frame.encode(buf); -5561 qlog.frame(&Frame::PathStatusAvailable(frame)); -5562 self.stats.frame_tx.path_status_available += 1; -5563 trace!(%path_id, %seq, "PATH_STATUS_AVAILABLE") -5564 } -5565 PathStatus::Backup => { -5566 let frame = frame::PathStatusBackup { -5567 path_id, -5568 status_seq_no: seq, -5569 }; -5570 frame.encode(buf); -5571 qlog.frame(&Frame::PathStatusBackup(frame)); -5572 self.stats.frame_tx.path_status_backup += 1; -5573 trace!(%path_id, %seq, "PATH_STATUS_BACKUP") -5574 } -5575 } -5576 } -5577 -5578 // MAX_PATH_ID -5579 if space_id == SpaceId::Data -5580 && space.pending.max_path_id -5581 && frame::MaxPathId::SIZE_BOUND <= buf.remaining_mut() -5582 { -5583 let frame = frame::MaxPathId(self.local_max_path_id); -5584 frame.encode(buf); -5585 qlog.frame(&Frame::MaxPathId(frame)); -5586 space.pending.max_path_id = false; -5587 sent.retransmits.get_or_create().max_path_id = true; -5588 trace!(val = %self.local_max_path_id, "MAX_PATH_ID"); -5589 self.stats.frame_tx.max_path_id += 1; -5590 } -5591 -5592 // PATHS_BLOCKED -5593 if space_id == SpaceId::Data -5594 && space.pending.paths_blocked -5595 && frame::PathsBlocked::SIZE_BOUND <= buf.remaining_mut() -5596 { -5597 let frame = frame::PathsBlocked(self.remote_max_path_id); -5598 frame.encode(buf); -5599 qlog.frame(&Frame::PathsBlocked(frame)); -5600 space.pending.paths_blocked = false; -5601 sent.retransmits.get_or_create().paths_blocked = true; -5602 trace!(max_path_id = %self.remote_max_path_id, "PATHS_BLOCKED"); -5603 self.stats.frame_tx.paths_blocked += 1; -5604 } -5605 -5606 // PATH_CIDS_BLOCKED -5607 while space_id == SpaceId::Data && frame::PathCidsBlocked::SIZE_BOUND <= buf.remaining_mut() -5608 { -5609 let Some(path_id) = space.pending.path_cids_blocked.pop() else { -5610 break; -5611 }; -5612 let next_seq = match self.rem_cids.get(&path_id) { -5613 Some(cid_queue) => cid_queue.active_seq() + 1, -5614 None => 0, -5615 }; -5616 let frame = frame::PathCidsBlocked { -5617 path_id, -5618 next_seq: VarInt(next_seq), -5619 }; -5620 frame.encode(buf); -5621 qlog.frame(&Frame::PathCidsBlocked(frame)); -5622 sent.retransmits -5623 .get_or_create() -5624 .path_cids_blocked -5625 .push(path_id); -5626 trace!(%path_id, next_seq, "PATH_CIDS_BLOCKED"); -5627 self.stats.frame_tx.path_cids_blocked += 1; -5628 } -5629 -5630 // RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS -5631 if space_id == SpaceId::Data { -5632 self.streams.write_control_frames( -5633 buf, -5634 &mut space.pending, -5635 &mut sent.retransmits, -5636 &mut self.stats.frame_tx, -5637 qlog, -5638 ); -5639 } -5640 -5641 // NEW_CONNECTION_ID -5642 let cid_len = self -5643 .local_cid_state -5644 .values() -5645 .map(|cid_state| cid_state.cid_len()) -5646 .max() -5647 .expect("some local CID state must exist"); -5648 let new_cid_size_bound = -5649 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len); -5650 while !path_exclusive_only && buf.remaining_mut() > new_cid_size_bound { -5651 let issued = match space.pending.new_cids.pop() { -5652 Some(x) => x, -5653 None => break, -5654 }; -5655 let retire_prior_to = self -5656 .local_cid_state -5657 .get(&issued.path_id) -5658 .map(|cid_state| cid_state.retire_prior_to()) -5659 .unwrap_or_else(|| panic!("missing local CID state for path={}", issued.path_id)); -5660 -5661 let cid_path_id = match is_multipath_negotiated { -5662 true => { -5663 trace!( -5664 path_id = ?issued.path_id, -5665 sequence = issued.sequence, -5666 id = %issued.id, -5667 "PATH_NEW_CONNECTION_ID", -5668 ); -5669 self.stats.frame_tx.path_new_connection_id += 1; -5670 Some(issued.path_id) -5671 } -5672 false => { -5673 trace!( -5674 sequence = issued.sequence, -5675 id = %issued.id, -5676 "NEW_CONNECTION_ID" -5677 ); -5678 debug_assert_eq!(issued.path_id, PathId::ZERO); -5679 self.stats.frame_tx.new_connection_id += 1; -5680 None -5681 } -5682 }; -5683 let frame = frame::NewConnectionId { -5684 path_id: cid_path_id, -5685 sequence: issued.sequence, -5686 retire_prior_to, -5687 id: issued.id, -5688 reset_token: issued.reset_token, -5689 }; -5690 frame.encode(buf); -5691 sent.retransmits.get_or_create().new_cids.push(issued); -5692 qlog.frame(&Frame::NewConnectionId(frame)); -5693 } -5694 -5695 // RETIRE_CONNECTION_ID -5696 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated); -5697 while !path_exclusive_only && buf.remaining_mut() > retire_cid_bound { -5698 let (path_id, sequence) = match space.pending.retire_cids.pop() { -5699 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => { -5700 trace!(sequence = seq, "RETIRE_CONNECTION_ID"); -5701 self.stats.frame_tx.retire_connection_id += 1; -5702 (None, seq) -5703 } -5704 Some((path_id, seq)) => { -5705 trace!(%path_id, sequence = seq, "PATH_RETIRE_CONNECTION_ID"); -5706 self.stats.frame_tx.path_retire_connection_id += 1; -5707 (Some(path_id), seq) +5403 if is_multipath_negotiated && !path.validated && path.send_new_challenge { +5404 // queue informing the path status along with the challenge +5405 space.pending.path_status.insert(path_id); +5406 } +5407 +5408 // Always include an OBSERVED_ADDR frame with a PATH_CHALLENGE, regardless +5409 // of whether one has already been sent on this path. +5410 if space_id == SpaceId::Data +5411 && self +5412 .config +5413 .address_discovery_role +5414 .should_report(&self.peer_params.address_discovery_role) +5415 { +5416 let frame = frame::ObservedAddr::new( +5417 path.network_path.remote, +5418 self.next_observed_addr_seq_no, +5419 ); +5420 if buf.remaining_mut() > frame.size() { +5421 frame.encode(buf); +5422 qlog.frame(&Frame::ObservedAddr(frame)); +5423 +5424 self.next_observed_addr_seq_no = +5425 self.next_observed_addr_seq_no.saturating_add(1u8); +5426 path.observed_addr_sent = true; +5427 +5428 self.stats.frame_tx.observed_addr += 1; +5429 sent.retransmits.get_or_create().observed_addr = true; +5430 space.pending.observed_addr = false; +5431 } +5432 } +5433 } +5434 +5435 // PATH_RESPONSE +5436 if buf.remaining_mut() > frame::PathResponse::SIZE_BOUND && space_id == SpaceId::Data { +5437 if let Some(token) = path.path_responses.pop_on_path(path.network_path) { +5438 sent.non_retransmits = true; +5439 sent.requires_padding = true; +5440 let response = frame::PathResponse(token); +5441 trace!(frame = %response); +5442 buf.write(response); +5443 qlog.frame(&Frame::PathResponse(response)); +5444 self.stats.frame_tx.path_response += 1; +5445 +5446 // NOTE: this is technically not required but might be useful to ride the +5447 // request/response nature of path challenges to refresh an observation +5448 // Since PATH_RESPONSE is a probing frame, this is allowed by the spec. +5449 if space_id == SpaceId::Data +5450 && self +5451 .config +5452 .address_discovery_role +5453 .should_report(&self.peer_params.address_discovery_role) +5454 { +5455 let frame = frame::ObservedAddr::new( +5456 path.network_path.remote, +5457 self.next_observed_addr_seq_no, +5458 ); +5459 if buf.remaining_mut() > frame.size() { +5460 frame.encode(buf); +5461 qlog.frame(&Frame::ObservedAddr(frame)); +5462 +5463 self.next_observed_addr_seq_no = +5464 self.next_observed_addr_seq_no.saturating_add(1u8); +5465 path.observed_addr_sent = true; +5466 +5467 self.stats.frame_tx.observed_addr += 1; +5468 sent.retransmits.get_or_create().observed_addr = true; +5469 space.pending.observed_addr = false; +5470 } +5471 } +5472 } +5473 } +5474 +5475 // CRYPTO +5476 while !path_exclusive_only && buf.remaining_mut() > frame::Crypto::SIZE_BOUND && !is_0rtt { +5477 let mut frame = match space.pending.crypto.pop_front() { +5478 Some(x) => x, +5479 None => break, +5480 }; +5481 +5482 // Calculate the maximum amount of crypto data we can store in the buffer. +5483 // Since the offset is known, we can reserve the exact size required to encode it. +5484 // For length we reserve 2bytes which allows to encode up to 2^14, +5485 // which is more than what fits into normally sized QUIC frames. +5486 let max_crypto_data_size = buf.remaining_mut() +5487 - 1 // Frame Type +5488 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) }) +5489 - 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes +5490 +5491 let len = frame +5492 .data +5493 .len() +5494 .min(2usize.pow(14) - 1) +5495 .min(max_crypto_data_size); +5496 +5497 let data = frame.data.split_to(len); +5498 let truncated = frame::Crypto { +5499 offset: frame.offset, +5500 data, +5501 }; +5502 trace!( +5503 "CRYPTO: off {} len {}", +5504 truncated.offset, +5505 truncated.data.len() +5506 ); +5507 truncated.encode(buf); +5508 self.stats.frame_tx.crypto += 1; +5509 +5510 // The clone is cheap but we still cfg it out if qlog is disabled. +5511 #[cfg(feature = "qlog")] +5512 qlog.frame(&Frame::Crypto(truncated.clone())); +5513 sent.retransmits.get_or_create().crypto.push_back(truncated); +5514 if !frame.data.is_empty() { +5515 frame.offset += len as u64; +5516 space.pending.crypto.push_front(frame); +5517 } +5518 } +5519 +5520 // TODO(flub): maybe this is much higher priority? +5521 // PATH_ABANDON +5522 while !path_exclusive_only +5523 && space_id == SpaceId::Data +5524 && frame::PathAbandon::SIZE_BOUND <= buf.remaining_mut() +5525 { +5526 let Some((path_id, error_code)) = space.pending.path_abandon.pop_first() else { +5527 break; +5528 }; +5529 let frame = frame::PathAbandon { +5530 path_id, +5531 error_code, +5532 }; +5533 frame.encode(buf); +5534 qlog.frame(&Frame::PathAbandon(frame)); +5535 self.stats.frame_tx.path_abandon += 1; +5536 trace!(%path_id, "PATH_ABANDON"); +5537 sent.retransmits +5538 .get_or_create() +5539 .path_abandon +5540 .entry(path_id) +5541 .or_insert(error_code); +5542 } +5543 +5544 // PATH_STATUS_AVAILABLE & PATH_STATUS_BACKUP +5545 while !path_exclusive_only +5546 && space_id == SpaceId::Data +5547 && frame::PathStatusAvailable::SIZE_BOUND <= buf.remaining_mut() +5548 { +5549 let Some(path_id) = space.pending.path_status.pop_first() else { +5550 break; +5551 }; +5552 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else { +5553 trace!(%path_id, "discarding queued path status for unknown path"); +5554 continue; +5555 }; +5556 +5557 let seq = path.status.seq(); +5558 sent.retransmits.get_or_create().path_status.insert(path_id); +5559 match path.local_status() { +5560 PathStatus::Available => { +5561 let frame = frame::PathStatusAvailable { +5562 path_id, +5563 status_seq_no: seq, +5564 }; +5565 frame.encode(buf); +5566 qlog.frame(&Frame::PathStatusAvailable(frame)); +5567 self.stats.frame_tx.path_status_available += 1; +5568 trace!(%path_id, %seq, "PATH_STATUS_AVAILABLE") +5569 } +5570 PathStatus::Backup => { +5571 let frame = frame::PathStatusBackup { +5572 path_id, +5573 status_seq_no: seq, +5574 }; +5575 frame.encode(buf); +5576 qlog.frame(&Frame::PathStatusBackup(frame)); +5577 self.stats.frame_tx.path_status_backup += 1; +5578 trace!(%path_id, %seq, "PATH_STATUS_BACKUP") +5579 } +5580 } +5581 } +5582 +5583 // MAX_PATH_ID +5584 if space_id == SpaceId::Data +5585 && space.pending.max_path_id +5586 && frame::MaxPathId::SIZE_BOUND <= buf.remaining_mut() +5587 { +5588 let frame = frame::MaxPathId(self.local_max_path_id); +5589 frame.encode(buf); +5590 qlog.frame(&Frame::MaxPathId(frame)); +5591 space.pending.max_path_id = false; +5592 sent.retransmits.get_or_create().max_path_id = true; +5593 trace!(val = %self.local_max_path_id, "MAX_PATH_ID"); +5594 self.stats.frame_tx.max_path_id += 1; +5595 } +5596 +5597 // PATHS_BLOCKED +5598 if space_id == SpaceId::Data +5599 && space.pending.paths_blocked +5600 && frame::PathsBlocked::SIZE_BOUND <= buf.remaining_mut() +5601 { +5602 let frame = frame::PathsBlocked(self.remote_max_path_id); +5603 frame.encode(buf); +5604 qlog.frame(&Frame::PathsBlocked(frame)); +5605 space.pending.paths_blocked = false; +5606 sent.retransmits.get_or_create().paths_blocked = true; +5607 trace!(max_path_id = %self.remote_max_path_id, "PATHS_BLOCKED"); +5608 self.stats.frame_tx.paths_blocked += 1; +5609 } +5610 +5611 // PATH_CIDS_BLOCKED +5612 while space_id == SpaceId::Data && frame::PathCidsBlocked::SIZE_BOUND <= buf.remaining_mut() +5613 { +5614 let Some(path_id) = space.pending.path_cids_blocked.pop_first() else { +5615 break; +5616 }; +5617 let next_seq = match self.rem_cids.get(&path_id) { +5618 Some(cid_queue) => cid_queue.active_seq() + 1, +5619 None => 0, +5620 }; +5621 let frame = frame::PathCidsBlocked { +5622 path_id, +5623 next_seq: VarInt(next_seq), +5624 }; +5625 frame.encode(buf); +5626 qlog.frame(&Frame::PathCidsBlocked(frame)); +5627 sent.retransmits +5628 .get_or_create() +5629 .path_cids_blocked +5630 .insert(path_id); +5631 trace!(%path_id, next_seq, "PATH_CIDS_BLOCKED"); +5632 self.stats.frame_tx.path_cids_blocked += 1; +5633 } +5634 +5635 // RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS +5636 if space_id == SpaceId::Data { +5637 self.streams.write_control_frames( +5638 buf, +5639 &mut space.pending, +5640 &mut sent.retransmits, +5641 &mut self.stats.frame_tx, +5642 qlog, +5643 ); +5644 } +5645 +5646 // NEW_CONNECTION_ID +5647 let cid_len = self +5648 .local_cid_state +5649 .values() +5650 .map(|cid_state| cid_state.cid_len()) +5651 .max() +5652 .expect("some local CID state must exist"); +5653 let new_cid_size_bound = +5654 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len); +5655 while !path_exclusive_only && buf.remaining_mut() > new_cid_size_bound { +5656 let issued = match space.pending.new_cids.pop() { +5657 Some(x) => x, +5658 None => break, +5659 }; +5660 let retire_prior_to = self +5661 .local_cid_state +5662 .get(&issued.path_id) +5663 .map(|cid_state| cid_state.retire_prior_to()) +5664 .unwrap_or_else(|| panic!("missing local CID state for path={}", issued.path_id)); +5665 +5666 let cid_path_id = match is_multipath_negotiated { +5667 true => { +5668 trace!( +5669 path_id = ?issued.path_id, +5670 sequence = issued.sequence, +5671 id = %issued.id, +5672 "PATH_NEW_CONNECTION_ID", +5673 ); +5674 self.stats.frame_tx.path_new_connection_id += 1; +5675 Some(issued.path_id) +5676 } +5677 false => { +5678 trace!( +5679 sequence = issued.sequence, +5680 id = %issued.id, +5681 "NEW_CONNECTION_ID" +5682 ); +5683 debug_assert_eq!(issued.path_id, PathId::ZERO); +5684 self.stats.frame_tx.new_connection_id += 1; +5685 None +5686 } +5687 }; +5688 let frame = frame::NewConnectionId { +5689 path_id: cid_path_id, +5690 sequence: issued.sequence, +5691 retire_prior_to, +5692 id: issued.id, +5693 reset_token: issued.reset_token, +5694 }; +5695 frame.encode(buf); +5696 sent.retransmits.get_or_create().new_cids.push(issued); +5697 qlog.frame(&Frame::NewConnectionId(frame)); +5698 } +5699 +5700 // RETIRE_CONNECTION_ID +5701 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated); +5702 while !path_exclusive_only && buf.remaining_mut() > retire_cid_bound { +5703 let (path_id, sequence) = match space.pending.retire_cids.pop() { +5704 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => { +5705 trace!(sequence = seq, "RETIRE_CONNECTION_ID"); +5706 self.stats.frame_tx.retire_connection_id += 1; +5707 (None, seq) 5708 } -5709 None => break, -5710 }; -5711 let frame = frame::RetireConnectionId { path_id, sequence }; -5712 frame.encode(buf); -5713 qlog.frame(&Frame::RetireConnectionId(frame)); -5714 sent.retransmits -5715 .get_or_create() -5716 .retire_cids -5717 .push((path_id.unwrap_or_default(), sequence)); -5718 } -5719 -5720 // DATAGRAM -5721 let mut sent_datagrams = false; -5722 while !path_exclusive_only -5723 && buf.remaining_mut() > Datagram::SIZE_BOUND -5724 && space_id == SpaceId::Data -5725 { -5726 let prev_remaining = buf.remaining_mut(); -5727 match self.datagrams.write(buf) { -5728 true => { -5729 sent_datagrams = true; -5730 sent.non_retransmits = true; -5731 self.stats.frame_tx.datagram += 1; -5732 qlog.frame_datagram((prev_remaining - buf.remaining_mut()) as u64); -5733 } -5734 false => break, -5735 } -5736 } -5737 if self.datagrams.send_blocked && sent_datagrams { -5738 self.events.push_back(Event::DatagramsUnblocked); -5739 self.datagrams.send_blocked = false; -5740 } -5741 -5742 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; -5743 -5744 // NEW_TOKEN -5745 while let Some(network_path) = space.pending.new_tokens.pop() { -5746 if path_exclusive_only { -5747 break; -5748 } -5749 debug_assert_eq!(space_id, SpaceId::Data); -5750 let ConnectionSide::Server { server_config } = &self.side else { -5751 panic!("NEW_TOKEN frames should not be enqueued by clients"); -5752 }; -5753 -5754 if !network_path.is_probably_same_path(&path.network_path) { -5755 // NEW_TOKEN frames contain tokens bound to a client's IP address, and are only -5756 // useful if used from the same IP address. Thus, we abandon enqueued NEW_TOKEN -5757 // frames upon an path change. Instead, when the new path becomes validated, -5758 // NEW_TOKEN frames may be enqueued for the new path instead. -5759 continue; -5760 } -5761 -5762 let token = Token::new( -5763 TokenPayload::Validation { -5764 ip: network_path.remote.ip(), -5765 issued: server_config.time_source.now(), -5766 }, -5767 &mut self.rng, -5768 ); -5769 let new_token = NewToken { -5770 token: token.encode(&*server_config.token_key).into(), -5771 }; -5772 -5773 if buf.remaining_mut() < new_token.size() { -5774 space.pending.new_tokens.push(network_path); -5775 break; -5776 } +5709 Some((path_id, seq)) => { +5710 trace!(%path_id, sequence = seq, "PATH_RETIRE_CONNECTION_ID"); +5711 self.stats.frame_tx.path_retire_connection_id += 1; +5712 (Some(path_id), seq) +5713 } +5714 None => break, +5715 }; +5716 let frame = frame::RetireConnectionId { path_id, sequence }; +5717 frame.encode(buf); +5718 qlog.frame(&Frame::RetireConnectionId(frame)); +5719 sent.retransmits +5720 .get_or_create() +5721 .retire_cids +5722 .push((path_id.unwrap_or_default(), sequence)); +5723 } +5724 +5725 // DATAGRAM +5726 let mut sent_datagrams = false; +5727 while !path_exclusive_only +5728 && buf.remaining_mut() > Datagram::SIZE_BOUND +5729 && space_id == SpaceId::Data +5730 { +5731 let prev_remaining = buf.remaining_mut(); +5732 match self.datagrams.write(buf) { +5733 true => { +5734 sent_datagrams = true; +5735 sent.non_retransmits = true; +5736 self.stats.frame_tx.datagram += 1; +5737 qlog.frame_datagram((prev_remaining - buf.remaining_mut()) as u64); +5738 } +5739 false => break, +5740 } +5741 } +5742 if self.datagrams.send_blocked && sent_datagrams { +5743 self.events.push_back(Event::DatagramsUnblocked); +5744 self.datagrams.send_blocked = false; +5745 } +5746 +5747 let path = &mut self.paths.get_mut(&path_id).expect("known path").data; +5748 +5749 // NEW_TOKEN +5750 while let Some(network_path) = space.pending.new_tokens.pop() { +5751 if path_exclusive_only { +5752 break; +5753 } +5754 debug_assert_eq!(space_id, SpaceId::Data); +5755 let ConnectionSide::Server { server_config } = &self.side else { +5756 panic!("NEW_TOKEN frames should not be enqueued by clients"); +5757 }; +5758 +5759 if !network_path.is_probably_same_path(&path.network_path) { +5760 // NEW_TOKEN frames contain tokens bound to a client's IP address, and are only +5761 // useful if used from the same IP address. Thus, we abandon enqueued NEW_TOKEN +5762 // frames upon an path change. Instead, when the new path becomes validated, +5763 // NEW_TOKEN frames may be enqueued for the new path instead. +5764 continue; +5765 } +5766 +5767 let token = Token::new( +5768 TokenPayload::Validation { +5769 ip: network_path.remote.ip(), +5770 issued: server_config.time_source.now(), +5771 }, +5772 &mut self.rng, +5773 ); +5774 let new_token = NewToken { +5775 token: token.encode(&*server_config.token_key).into(), +5776 }; 5777 -5778 trace!("NEW_TOKEN"); -5779 new_token.encode(buf); -5780 qlog.frame(&Frame::NewToken(new_token)); -5781 sent.retransmits -5782 .get_or_create() -5783 .new_tokens -5784 .push(network_path); -5785 self.stats.frame_tx.new_token += 1; -5786 } -5787 -5788 // STREAM -5789 if !path_exclusive_only && space_id == SpaceId::Data { -5790 sent.stream_frames = -5791 self.streams -5792 .write_stream_frames(buf, self.config.send_fairness, qlog); -5793 self.stats.frame_tx.stream += sent.stream_frames.len() as u64; -5794 } -5795 -5796 // ADD_ADDRESS -5797 // TODO(@divma): check if we need to do path exclusive filters -5798 while space_id == SpaceId::Data && frame::AddAddress::SIZE_BOUND <= buf.remaining_mut() { -5799 if let Some(added_address) = space.pending.add_address.pop_last() { -5800 trace!( -5801 seq = %added_address.seq_no, -5802 ip = ?added_address.ip, -5803 port = added_address.port, -5804 "ADD_ADDRESS", -5805 ); -5806 added_address.encode(buf); -5807 sent.retransmits -5808 .get_or_create() -5809 .add_address -5810 .insert(added_address); -5811 self.stats.frame_tx.add_address = self.stats.frame_tx.add_address.saturating_add(1); -5812 qlog.frame(&Frame::AddAddress(added_address)); -5813 } else { -5814 break; -5815 } -5816 } -5817 -5818 // REMOVE_ADDRESS -5819 while space_id == SpaceId::Data && frame::RemoveAddress::SIZE_BOUND <= buf.remaining_mut() { -5820 if let Some(removed_address) = space.pending.remove_address.pop_last() { -5821 trace!(seq = %removed_address.seq_no, "REMOVE_ADDRESS"); -5822 removed_address.encode(buf); -5823 sent.retransmits -5824 .get_or_create() -5825 .remove_address -5826 .insert(removed_address); -5827 self.stats.frame_tx.remove_address = -5828 self.stats.frame_tx.remove_address.saturating_add(1); -5829 qlog.frame(&Frame::RemoveAddress(removed_address)); -5830 } else { -5831 break; -5832 } -5833 } -5834 -5835 sent -5836 } -5837 -5838 /// Write pending ACKs into a buffer -5839 fn populate_acks( -5840 now: Instant, -5841 receiving_ecn: bool, -5842 sent: &mut SentFrames, -5843 path_id: PathId, -5844 space_id: SpaceId, -5845 space: &mut PacketSpace, -5846 is_multipath_negotiated: bool, -5847 buf: &mut impl BufMut, -5848 stats: &mut ConnectionStats, -5849 #[allow(unused)] qlog: &mut QlogSentPacket, -5850 ) { -5851 // 0-RTT packets must never carry acks (which would have to be of handshake packets) -5852 debug_assert!(space.crypto.is_some(), "tried to send ACK in 0-RTT"); -5853 -5854 debug_assert!( -5855 is_multipath_negotiated || path_id == PathId::ZERO, -5856 "Only PathId::ZERO allowed without multipath (have {path_id:?})" -5857 ); -5858 if is_multipath_negotiated { -5859 debug_assert!( -5860 space_id == SpaceId::Data || path_id == PathId::ZERO, -5861 "path acks must be sent in 1RTT space (have {space_id:?})" -5862 ); -5863 } -5864 -5865 let pns = space.for_path(path_id); -5866 let ranges = pns.pending_acks.ranges(); -5867 debug_assert!(!ranges.is_empty(), "can not send empty ACK range"); -5868 let ecn = if receiving_ecn { -5869 Some(&pns.ecn_counters) -5870 } else { -5871 None -5872 }; -5873 if let Some(max) = ranges.max() { -5874 sent.largest_acked.insert(path_id, max); -5875 } -5876 -5877 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64; -5878 // TODO: This should come from `TransportConfig` if that gets configurable. -5879 let ack_delay_exp = TransportParameters::default().ack_delay_exponent; -5880 let delay = delay_micros >> ack_delay_exp.into_inner(); +5778 if buf.remaining_mut() < new_token.size() { +5779 space.pending.new_tokens.push(network_path); +5780 break; +5781 } +5782 +5783 trace!("NEW_TOKEN"); +5784 new_token.encode(buf); +5785 qlog.frame(&Frame::NewToken(new_token)); +5786 sent.retransmits +5787 .get_or_create() +5788 .new_tokens +5789 .push(network_path); +5790 self.stats.frame_tx.new_token += 1; +5791 } +5792 +5793 // STREAM +5794 if !path_exclusive_only && space_id == SpaceId::Data { +5795 sent.stream_frames = +5796 self.streams +5797 .write_stream_frames(buf, self.config.send_fairness, qlog); +5798 self.stats.frame_tx.stream += sent.stream_frames.len() as u64; +5799 } +5800 +5801 // ADD_ADDRESS +5802 // TODO(@divma): check if we need to do path exclusive filters +5803 while space_id == SpaceId::Data && frame::AddAddress::SIZE_BOUND <= buf.remaining_mut() { +5804 if let Some(added_address) = space.pending.add_address.pop_last() { +5805 trace!( +5806 seq = %added_address.seq_no, +5807 ip = ?added_address.ip, +5808 port = added_address.port, +5809 "ADD_ADDRESS", +5810 ); +5811 added_address.encode(buf); +5812 sent.retransmits +5813 .get_or_create() +5814 .add_address +5815 .insert(added_address); +5816 self.stats.frame_tx.add_address = self.stats.frame_tx.add_address.saturating_add(1); +5817 qlog.frame(&Frame::AddAddress(added_address)); +5818 } else { +5819 break; +5820 } +5821 } +5822 +5823 // REMOVE_ADDRESS +5824 while space_id == SpaceId::Data && frame::RemoveAddress::SIZE_BOUND <= buf.remaining_mut() { +5825 if let Some(removed_address) = space.pending.remove_address.pop_last() { +5826 trace!(seq = %removed_address.seq_no, "REMOVE_ADDRESS"); +5827 removed_address.encode(buf); +5828 sent.retransmits +5829 .get_or_create() +5830 .remove_address +5831 .insert(removed_address); +5832 self.stats.frame_tx.remove_address = +5833 self.stats.frame_tx.remove_address.saturating_add(1); +5834 qlog.frame(&Frame::RemoveAddress(removed_address)); +5835 } else { +5836 break; +5837 } +5838 } +5839 +5840 sent +5841 } +5842 +5843 /// Write pending ACKs into a buffer +5844 fn populate_acks( +5845 now: Instant, +5846 receiving_ecn: bool, +5847 sent: &mut SentFrames, +5848 path_id: PathId, +5849 space_id: SpaceId, +5850 space: &mut PacketSpace, +5851 is_multipath_negotiated: bool, +5852 buf: &mut impl BufMut, +5853 stats: &mut ConnectionStats, +5854 #[allow(unused)] qlog: &mut QlogSentPacket, +5855 ) { +5856 // 0-RTT packets must never carry acks (which would have to be of handshake packets) +5857 debug_assert!(space.crypto.is_some(), "tried to send ACK in 0-RTT"); +5858 +5859 debug_assert!( +5860 is_multipath_negotiated || path_id == PathId::ZERO, +5861 "Only PathId::ZERO allowed without multipath (have {path_id:?})" +5862 ); +5863 if is_multipath_negotiated { +5864 debug_assert!( +5865 space_id == SpaceId::Data || path_id == PathId::ZERO, +5866 "path acks must be sent in 1RTT space (have {space_id:?})" +5867 ); +5868 } +5869 +5870 let pns = space.for_path(path_id); +5871 let ranges = pns.pending_acks.ranges(); +5872 debug_assert!(!ranges.is_empty(), "can not send empty ACK range"); +5873 let ecn = if receiving_ecn { +5874 Some(&pns.ecn_counters) +5875 } else { +5876 None +5877 }; +5878 if let Some(max) = ranges.max() { +5879 sent.largest_acked.insert(path_id, max); +5880 } 5881 -5882 if is_multipath_negotiated && space_id == SpaceId::Data { -5883 if !ranges.is_empty() { -5884 trace!("PATH_ACK {path_id:?} {ranges:?}, Delay = {delay_micros}us"); -5885 frame::PathAck::encoder(path_id, delay as _, ranges, ecn).encode(buf); -5886 qlog.frame_path_ack(path_id, delay as _, ranges, ecn); -5887 stats.frame_tx.path_acks += 1; -5888 } -5889 } else { -5890 trace!("ACK {ranges:?}, Delay = {delay_micros}us"); -5891 frame::Ack::encoder(delay as _, ranges, ecn).encode(buf); -5892 stats.frame_tx.acks += 1; -5893 qlog.frame_ack(delay, ranges, ecn); -5894 } -5895 } -5896 -5897 fn close_common(&mut self) { -5898 trace!("connection closed"); -5899 self.timers.reset(); +5882 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64; +5883 // TODO: This should come from `TransportConfig` if that gets configurable. +5884 let ack_delay_exp = TransportParameters::default().ack_delay_exponent; +5885 let delay = delay_micros >> ack_delay_exp.into_inner(); +5886 +5887 if is_multipath_negotiated && space_id == SpaceId::Data { +5888 if !ranges.is_empty() { +5889 trace!("PATH_ACK {path_id:?} {ranges:?}, Delay = {delay_micros}us"); +5890 frame::PathAck::encoder(path_id, delay as _, ranges, ecn).encode(buf); +5891 qlog.frame_path_ack(path_id, delay as _, ranges, ecn); +5892 stats.frame_tx.path_acks += 1; +5893 } +5894 } else { +5895 trace!("ACK {ranges:?}, Delay = {delay_micros}us"); +5896 frame::Ack::encoder(delay as _, ranges, ecn).encode(buf); +5897 stats.frame_tx.acks += 1; +5898 qlog.frame_ack(delay, ranges, ecn); +5899 } 5900 } 5901 -5902 fn set_close_timer(&mut self, now: Instant) { -5903 // QUIC-MULTIPATH § 2.6 Connection Closure: draining for 3*PTO with PTO the max of -5904 // the PTO for all paths. -5905 let pto_max = self.pto_max_path(self.highest_space, true); -5906 self.timers.set( -5907 Timer::Conn(ConnTimer::Close), -5908 now + 3 * pto_max, -5909 self.qlog.with_time(now), -5910 ); -5911 } -5912 -5913 /// Handle transport parameters received from the peer -5914 /// -5915 /// *rem_cid* and *loc_cid* are the source and destination CIDs respectively of the -5916 /// *packet into which the transport parameters arrived. -5917 fn handle_peer_params( -5918 &mut self, -5919 params: TransportParameters, -5920 loc_cid: ConnectionId, -5921 rem_cid: ConnectionId, -5922 now: Instant, -5923 ) -> Result<(), TransportError> { -5924 if Some(self.orig_rem_cid) != params.initial_src_cid -5925 || (self.side.is_client() -5926 && (Some(self.initial_dst_cid) != params.original_dst_cid -5927 || self.retry_src_cid != params.retry_src_cid)) -5928 { -5929 return Err(TransportError::TRANSPORT_PARAMETER_ERROR( -5930 "CID authentication failure", -5931 )); -5932 } -5933 if params.initial_max_path_id.is_some() && (loc_cid.is_empty() || rem_cid.is_empty()) { -5934 return Err(TransportError::PROTOCOL_VIOLATION( -5935 "multipath must not use zero-length CIDs", +5902 fn close_common(&mut self) { +5903 trace!("connection closed"); +5904 self.timers.reset(); +5905 } +5906 +5907 fn set_close_timer(&mut self, now: Instant) { +5908 // QUIC-MULTIPATH § 2.6 Connection Closure: draining for 3*PTO with PTO the max of +5909 // the PTO for all paths. +5910 let pto_max = self.pto_max_path(self.highest_space, true); +5911 self.timers.set( +5912 Timer::Conn(ConnTimer::Close), +5913 now + 3 * pto_max, +5914 self.qlog.with_time(now), +5915 ); +5916 } +5917 +5918 /// Handle transport parameters received from the peer +5919 /// +5920 /// *rem_cid* and *loc_cid* are the source and destination CIDs respectively of the +5921 /// *packet into which the transport parameters arrived. +5922 fn handle_peer_params( +5923 &mut self, +5924 params: TransportParameters, +5925 loc_cid: ConnectionId, +5926 rem_cid: ConnectionId, +5927 now: Instant, +5928 ) -> Result<(), TransportError> { +5929 if Some(self.orig_rem_cid) != params.initial_src_cid +5930 || (self.side.is_client() +5931 && (Some(self.initial_dst_cid) != params.original_dst_cid +5932 || self.retry_src_cid != params.retry_src_cid)) +5933 { +5934 return Err(TransportError::TRANSPORT_PARAMETER_ERROR( +5935 "CID authentication failure", 5936 )); 5937 } -5938 -5939 self.set_peer_params(params); -5940 self.qlog.emit_peer_transport_params_received(self, now); -5941 -5942 Ok(()) -5943 } -5944 -5945 fn set_peer_params(&mut self, params: TransportParameters) { -5946 self.streams.set_params(&params); -5947 self.idle_timeout = -5948 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout)); -5949 trace!("negotiated max idle timeout {:?}", self.idle_timeout); -5950 -5951 if let Some(ref info) = params.preferred_address { -5952 // During the handshake PathId::ZERO exists. -5953 self.rem_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId { -5954 path_id: None, -5955 sequence: 1, -5956 id: info.connection_id, -5957 reset_token: info.stateless_reset_token, -5958 retire_prior_to: 0, -5959 }) -5960 .expect( -5961 "preferred address CID is the first received, and hence is guaranteed to be legal", -5962 ); -5963 let remote = self.path_data(PathId::ZERO).network_path.remote; -5964 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token); -5965 } -5966 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(&params); -5967 -5968 let mut multipath_enabled = None; -5969 if let (Some(local_max_path_id), Some(remote_max_path_id)) = ( -5970 self.config.get_initial_max_path_id(), -5971 params.initial_max_path_id, -5972 ) { -5973 // multipath is enabled, register the local and remote maximums -5974 self.local_max_path_id = local_max_path_id; -5975 self.remote_max_path_id = remote_max_path_id; -5976 let initial_max_path_id = local_max_path_id.min(remote_max_path_id); -5977 debug!(%initial_max_path_id, "multipath negotiated"); -5978 multipath_enabled = Some(initial_max_path_id); -5979 } -5980 -5981 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) = -5982 self.config -5983 .max_remote_nat_traversal_addresses -5984 .zip(params.max_remote_nat_traversal_addresses) -5985 { -5986 if let Some(max_initial_paths) = -5987 multipath_enabled.map(|path_id| path_id.saturating_add(1u8)) -5988 { -5989 let max_local_addresses = max_remotely_allowed_remote_addresses.get(); -5990 let max_remote_addresses = max_locally_allowed_remote_addresses.get(); -5991 self.iroh_hp = -5992 iroh_hp::State::new(max_remote_addresses, max_local_addresses, self.side()); -5993 debug!( -5994 %max_remote_addresses, %max_local_addresses, -5995 "iroh hole punching negotiated" -5996 ); -5997 -5998 match self.side() { -5999 Side::Client => { -6000 if max_initial_paths.as_u32() < max_remote_addresses as u32 + 1 { -6001 // in this case the client might try to open `max_remote_addresses` new -6002 // paths, but the current multipath configuration will not allow it -6003 warn!(%max_initial_paths, %max_remote_addresses, "local client configuration might cause nat traversal issues") -6004 } else if max_local_addresses as u64 -6005 > params.active_connection_id_limit.into_inner() -6006 { -6007 // the server allows us to send at most `params.active_connection_id_limit` -6008 // but they might need at least `max_local_addresses` to effectively send -6009 // `PATH_CHALLENGE` frames to each advertised local address -6010 warn!(%max_local_addresses, remote_cid_limit=%params.active_connection_id_limit.into_inner(), "remote server configuration might cause nat traversal issues") -6011 } -6012 } -6013 Side::Server => { -6014 if (max_initial_paths.as_u32() as u64) < crate::LOC_CID_COUNT { -6015 warn!(%max_initial_paths, local_cid_limit=%crate::LOC_CID_COUNT, "local server configuration might cause nat traversal issues") +5938 if params.initial_max_path_id.is_some() && (loc_cid.is_empty() || rem_cid.is_empty()) { +5939 return Err(TransportError::PROTOCOL_VIOLATION( +5940 "multipath must not use zero-length CIDs", +5941 )); +5942 } +5943 +5944 self.set_peer_params(params); +5945 self.qlog.emit_peer_transport_params_received(self, now); +5946 +5947 Ok(()) +5948 } +5949 +5950 fn set_peer_params(&mut self, params: TransportParameters) { +5951 self.streams.set_params(&params); +5952 self.idle_timeout = +5953 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout)); +5954 trace!("negotiated max idle timeout {:?}", self.idle_timeout); +5955 +5956 if let Some(ref info) = params.preferred_address { +5957 // During the handshake PathId::ZERO exists. +5958 self.rem_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId { +5959 path_id: None, +5960 sequence: 1, +5961 id: info.connection_id, +5962 reset_token: info.stateless_reset_token, +5963 retire_prior_to: 0, +5964 }) +5965 .expect( +5966 "preferred address CID is the first received, and hence is guaranteed to be legal", +5967 ); +5968 let remote = self.path_data(PathId::ZERO).network_path.remote; +5969 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token); +5970 } +5971 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(&params); +5972 +5973 let mut multipath_enabled = None; +5974 if let (Some(local_max_path_id), Some(remote_max_path_id)) = ( +5975 self.config.get_initial_max_path_id(), +5976 params.initial_max_path_id, +5977 ) { +5978 // multipath is enabled, register the local and remote maximums +5979 self.local_max_path_id = local_max_path_id; +5980 self.remote_max_path_id = remote_max_path_id; +5981 let initial_max_path_id = local_max_path_id.min(remote_max_path_id); +5982 debug!(%initial_max_path_id, "multipath negotiated"); +5983 multipath_enabled = Some(initial_max_path_id); +5984 } +5985 +5986 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) = +5987 self.config +5988 .max_remote_nat_traversal_addresses +5989 .zip(params.max_remote_nat_traversal_addresses) +5990 { +5991 if let Some(max_initial_paths) = +5992 multipath_enabled.map(|path_id| path_id.saturating_add(1u8)) +5993 { +5994 let max_local_addresses = max_remotely_allowed_remote_addresses.get(); +5995 let max_remote_addresses = max_locally_allowed_remote_addresses.get(); +5996 self.iroh_hp = +5997 iroh_hp::State::new(max_remote_addresses, max_local_addresses, self.side()); +5998 debug!( +5999 %max_remote_addresses, %max_local_addresses, +6000 "iroh hole punching negotiated" +6001 ); +6002 +6003 match self.side() { +6004 Side::Client => { +6005 if max_initial_paths.as_u32() < max_remote_addresses as u32 + 1 { +6006 // in this case the client might try to open `max_remote_addresses` new +6007 // paths, but the current multipath configuration will not allow it +6008 warn!(%max_initial_paths, %max_remote_addresses, "local client configuration might cause nat traversal issues") +6009 } else if max_local_addresses as u64 +6010 > params.active_connection_id_limit.into_inner() +6011 { +6012 // the server allows us to send at most `params.active_connection_id_limit` +6013 // but they might need at least `max_local_addresses` to effectively send +6014 // `PATH_CHALLENGE` frames to each advertised local address +6015 warn!(%max_local_addresses, remote_cid_limit=%params.active_connection_id_limit.into_inner(), "remote server configuration might cause nat traversal issues") 6016 } 6017 } -6018 } -6019 } else { -6020 debug!("iroh nat traversal enabled for both endpoints, but multipath is missing") -6021 } -6022 } -6023 -6024 self.peer_params = params; -6025 let peer_max_udp_payload_size = -6026 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); -6027 self.path_data_mut(PathId::ZERO) -6028 .mtud -6029 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size); -6030 } -6031 -6032 /// Decrypts a packet, returning the packet number on success -6033 fn decrypt_packet( -6034 &mut self, -6035 now: Instant, -6036 path_id: PathId, -6037 packet: &mut Packet, -6038 ) -> Result<Option<u64>, Option<TransportError>> { -6039 let result = packet_crypto::decrypt_packet_body( -6040 packet, -6041 path_id, -6042 &self.spaces, -6043 self.zero_rtt_crypto.as_ref(), -6044 self.key_phase, -6045 self.prev_crypto.as_ref(), -6046 self.next_crypto.as_ref(), -6047 )?; -6048 -6049 let result = match result { -6050 Some(r) => r, -6051 None => return Ok(None), -6052 }; +6018 Side::Server => { +6019 if (max_initial_paths.as_u32() as u64) < crate::LOC_CID_COUNT { +6020 warn!(%max_initial_paths, local_cid_limit=%crate::LOC_CID_COUNT, "local server configuration might cause nat traversal issues") +6021 } +6022 } +6023 } +6024 } else { +6025 debug!("iroh nat traversal enabled for both endpoints, but multipath is missing") +6026 } +6027 } +6028 +6029 self.peer_params = params; +6030 let peer_max_udp_payload_size = +6031 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX); +6032 self.path_data_mut(PathId::ZERO) +6033 .mtud +6034 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size); +6035 } +6036 +6037 /// Decrypts a packet, returning the packet number on success +6038 fn decrypt_packet( +6039 &mut self, +6040 now: Instant, +6041 path_id: PathId, +6042 packet: &mut Packet, +6043 ) -> Result<Option<u64>, Option<TransportError>> { +6044 let result = packet_crypto::decrypt_packet_body( +6045 packet, +6046 path_id, +6047 &self.spaces, +6048 self.zero_rtt_crypto.as_ref(), +6049 self.key_phase, +6050 self.prev_crypto.as_ref(), +6051 self.next_crypto.as_ref(), +6052 )?; 6053 -6054 if result.outgoing_key_update_acked { -6055 if let Some(prev) = self.prev_crypto.as_mut() { -6056 prev.end_packet = Some((result.number, now)); -6057 self.set_key_discard_timer(now, packet.header.space()); -6058 } -6059 } -6060 -6061 if result.incoming_key_update { -6062 trace!("key update authenticated"); -6063 self.update_keys(Some((result.number, now)), true); -6064 self.set_key_discard_timer(now, packet.header.space()); -6065 } -6066 -6067 Ok(Some(result.number)) -6068 } -6069 -6070 fn update_keys(&mut self, end_packet: Option<(u64, Instant)>, remote: bool) { -6071 trace!("executing key update"); -6072 // Generate keys for the key phase after the one we're switching to, store them in -6073 // `next_crypto`, make the contents of `next_crypto` current, and move the current keys into -6074 // `prev_crypto`. -6075 let new = self -6076 .crypto -6077 .next_1rtt_keys() -6078 .expect("only called for `Data` packets"); -6079 self.key_phase_size = new -6080 .local -6081 .confidentiality_limit() -6082 .saturating_sub(KEY_UPDATE_MARGIN); -6083 let old = mem::replace( -6084 &mut self.spaces[SpaceId::Data] -6085 .crypto -6086 .as_mut() -6087 .unwrap() // safe because update_keys() can only be triggered by short packets -6088 .packet, -6089 mem::replace(self.next_crypto.as_mut().unwrap(), new), -6090 ); -6091 self.spaces[SpaceId::Data] -6092 .iter_paths_mut() -6093 .for_each(|s| s.sent_with_keys = 0); -6094 self.prev_crypto = Some(PrevCrypto { -6095 crypto: old, -6096 end_packet, -6097 update_unacked: remote, -6098 }); -6099 self.key_phase = !self.key_phase; -6100 } -6101 -6102 fn peer_supports_ack_frequency(&self) -> bool { -6103 self.peer_params.min_ack_delay.is_some() -6104 } -6105 -6106 /// Send an IMMEDIATE_ACK frame to the remote endpoint -6107 /// -6108 /// According to the spec, this will result in an error if the remote endpoint does not support -6109 /// the Acknowledgement Frequency extension -6110 pub(crate) fn immediate_ack(&mut self, path_id: PathId) { -6111 debug_assert_eq!( -6112 self.highest_space, -6113 SpaceId::Data, -6114 "immediate ack must be written in the data space" -6115 ); -6116 self.spaces[self.highest_space] -6117 .for_path(path_id) -6118 .immediate_ack_pending = true; -6119 } -6120 -6121 /// Decodes a packet, returning its decrypted payload, so it can be inspected in tests -6122 #[cfg(test)] -6123 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> { -6124 let (path_id, first_decode, remaining) = match &event.0 { -6125 ConnectionEventInner::Datagram(DatagramConnectionEvent { -6126 path_id, -6127 first_decode, -6128 remaining, -6129 .. -6130 }) => (path_id, first_decode, remaining), -6131 _ => return None, -6132 }; -6133 -6134 if remaining.is_some() { -6135 panic!("Packets should never be coalesced in tests"); -6136 } -6137 -6138 let decrypted_header = packet_crypto::unprotect_header( -6139 first_decode.clone(), -6140 &self.spaces, -6141 self.zero_rtt_crypto.as_ref(), -6142 self.peer_params.stateless_reset_token, -6143 )?; -6144 -6145 let mut packet = decrypted_header.packet?; -6146 packet_crypto::decrypt_packet_body( -6147 &mut packet, -6148 *path_id, -6149 &self.spaces, -6150 self.zero_rtt_crypto.as_ref(), -6151 self.key_phase, -6152 self.prev_crypto.as_ref(), -6153 self.next_crypto.as_ref(), -6154 ) -6155 .ok()?; -6156 -6157 Some(packet.payload.to_vec()) -6158 } -6159 -6160 /// The number of bytes of packets containing retransmittable frames that have not been -6161 /// acknowledged or declared lost. -6162 #[cfg(test)] -6163 pub(crate) fn bytes_in_flight(&self) -> u64 { -6164 // TODO(@divma): consider including for multipath? -6165 self.path_data(PathId::ZERO).in_flight.bytes -6166 } -6167 -6168 /// Number of bytes worth of non-ack-only packets that may be sent -6169 #[cfg(test)] -6170 pub(crate) fn congestion_window(&self) -> u64 { -6171 let path = self.path_data(PathId::ZERO); -6172 path.congestion -6173 .window() -6174 .saturating_sub(path.in_flight.bytes) -6175 } -6176 -6177 /// Whether no timers but keepalive, idle, rtt, pushnewcid, and key discard are running -6178 #[cfg(test)] -6179 pub(crate) fn is_idle(&self) -> bool { -6180 let current_timers = self.timers.values(); -6181 current_timers -6182 .into_iter() -6183 .filter(|(timer, _)| { -6184 !matches!( -6185 timer, -6186 Timer::Conn(ConnTimer::KeepAlive) -6187 | Timer::PerPath(_, PathTimer::PathKeepAlive) -6188 | Timer::Conn(ConnTimer::PushNewCid) -6189 | Timer::Conn(ConnTimer::KeyDiscard) -6190 ) -6191 }) -6192 .min_by_key(|(_, time)| *time) -6193 .is_none_or(|(timer, _)| timer == Timer::Conn(ConnTimer::Idle)) -6194 } -6195 -6196 /// Whether explicit congestion notification is in use on outgoing packets. -6197 #[cfg(test)] -6198 pub(crate) fn using_ecn(&self) -> bool { -6199 self.path_data(PathId::ZERO).sending_ecn -6200 } -6201 -6202 /// The number of received bytes in the current path -6203 #[cfg(test)] -6204 pub(crate) fn total_recvd(&self) -> u64 { -6205 self.path_data(PathId::ZERO).total_recvd -6206 } -6207 -6208 #[cfg(test)] -6209 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) { -6210 self.local_cid_state -6211 .get(&PathId::ZERO) -6212 .unwrap() -6213 .active_seq() -6214 } -6215 -6216 #[cfg(test)] -6217 #[track_caller] -6218 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) { -6219 self.local_cid_state -6220 .get(&PathId(path_id)) -6221 .unwrap() -6222 .active_seq() -6223 } -6224 -6225 /// Instruct the peer to replace previously issued CIDs by sending a NEW_CONNECTION_ID frame -6226 /// with updated `retire_prior_to` field set to `v` -6227 #[cfg(test)] -6228 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) { -6229 let n = self -6230 .local_cid_state -6231 .get_mut(&PathId::ZERO) -6232 .unwrap() -6233 .assign_retire_seq(v); -6234 self.endpoint_events -6235 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); -6236 } -6237 -6238 /// Check the current active remote CID sequence for `PathId::ZERO` -6239 #[cfg(test)] -6240 pub(crate) fn active_rem_cid_seq(&self) -> u64 { -6241 self.rem_cids.get(&PathId::ZERO).unwrap().active_seq() -6242 } -6243 -6244 /// Returns the detected maximum udp payload size for the current path -6245 #[cfg(test)] -6246 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 { -6247 self.path_data(path_id).current_mtu() -6248 } -6249 -6250 /// Triggers path validation on all paths -6251 #[cfg(test)] -6252 pub(crate) fn trigger_path_validation(&mut self) { -6253 for path in self.paths.values_mut() { -6254 path.data.send_new_challenge = true; -6255 } -6256 } -6257 -6258 /// Whether we have 1-RTT data to send -6259 /// -6260 /// This checks for frames that can only be sent in the data space (1-RTT): -6261 /// - Pending PATH_CHALLENGE frames on the active and previous path if just migrated. -6262 /// - Pending PATH_RESPONSE frames. -6263 /// - Pending data to send in STREAM frames. -6264 /// - Pending DATAGRAM frames to send. -6265 /// -6266 /// See also [`PacketSpace::can_send`] which keeps track of all other frame types that -6267 /// may need to be sent. -6268 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames { -6269 let path_exclusive = self.paths.get(&path_id).is_some_and(|path| { -6270 path.data.send_new_challenge -6271 || path -6272 .prev -6273 .as_ref() -6274 .is_some_and(|(_, path)| path.send_new_challenge) -6275 || !path.data.path_responses.is_empty() -6276 }); -6277 let other = self.streams.can_send_stream_data() -6278 || self -6279 .datagrams -6280 .outgoing -6281 .front() -6282 .is_some_and(|x| x.size(true) <= max_size); -6283 SendableFrames { -6284 acks: false, -6285 other, -6286 close: false, -6287 path_exclusive, -6288 } -6289 } -6290 -6291 /// Terminate the connection instantly, without sending a close packet -6292 fn kill(&mut self, reason: ConnectionError) { -6293 self.close_common(); -6294 self.state.move_to_drained(Some(reason)); -6295 self.endpoint_events.push_back(EndpointEventInner::Drained); -6296 } -6297 -6298 /// Storage size required for the largest packet that can be transmitted on all currently -6299 /// available paths -6300 /// -6301 /// Buffers passed to [`Connection::poll_transmit`] should be at least this large. -6302 /// -6303 /// When multipath is enabled, this value is the minimum MTU across all available paths. -6304 pub fn current_mtu(&self) -> u16 { -6305 self.paths -6306 .iter() -6307 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id)) -6308 .map(|(_path_id, path_state)| path_state.data.current_mtu()) -6309 .min() -6310 .expect("There is always at least one available path") -6311 } -6312 -6313 /// Size of non-frame data for a 1-RTT packet -6314 /// -6315 /// Quantifies space consumed by the QUIC header and AEAD tag. All other bytes in a packet are -6316 /// frames. Changes if the length of the remote connection ID changes, which is expected to be -6317 /// rare. If `pn` is specified, may additionally change unpredictably due to variations in -6318 /// latency and packet loss. -6319 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize { -6320 let pn_len = PacketNumber::new( -6321 pn, -6322 self.spaces[SpaceId::Data] -6323 .for_path(path) -6324 .largest_acked_packet -6325 .unwrap_or(0), -6326 ) -6327 .len(); -6328 -6329 // 1 byte for flags -6330 1 + self -6331 .rem_cids -6332 .get(&path) -6333 .map(|cids| cids.active().len()) -6334 .unwrap_or(20) // Max CID len in QUIC v1 -6335 + pn_len -6336 + self.tag_len_1rtt() -6337 } -6338 -6339 fn predict_1rtt_overhead_no_pn(&self) -> usize { -6340 let pn_len = 4; -6341 -6342 let cid_len = self -6343 .rem_cids -6344 .values() -6345 .map(|cids| cids.active().len()) -6346 .max() -6347 .unwrap_or(20); // Max CID len in QUIC v1 -6348 -6349 // 1 byte for flags -6350 1 + cid_len + pn_len + self.tag_len_1rtt() -6351 } -6352 -6353 fn tag_len_1rtt(&self) -> usize { -6354 let key = match self.spaces[SpaceId::Data].crypto.as_ref() { -6355 Some(crypto) => Some(&*crypto.packet.local), -6356 None => self.zero_rtt_crypto.as_ref().map(|x| &*x.packet), -6357 }; -6358 // If neither Data nor 0-RTT keys are available, make a reasonable tag length guess. As of -6359 // this writing, all QUIC cipher suites use 16-byte tags. We could return `None` instead, -6360 // but that would needlessly prevent sending datagrams during 0-RTT. -6361 key.map_or(16, |x| x.tag_len()) -6362 } -6363 -6364 /// Mark the path as validated, and enqueue NEW_TOKEN frames to be sent as appropriate -6365 fn on_path_validated(&mut self, path_id: PathId) { -6366 self.path_data_mut(path_id).validated = true; -6367 let ConnectionSide::Server { server_config } = &self.side else { -6368 return; -6369 }; -6370 let network_path = self.path_data(path_id).network_path; -6371 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens; -6372 new_tokens.clear(); -6373 for _ in 0..server_config.validation_token.sent { -6374 new_tokens.push(network_path); -6375 } -6376 } -6377 -6378 /// Handle new path status information: PATH_STATUS_AVAILABLE, PATH_STATUS_BACKUP -6379 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) { -6380 if let Some(path) = self.paths.get_mut(&path_id) { -6381 path.data.status.remote_update(status, status_seq_no); -6382 } else { -6383 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id); -6384 } -6385 self.events.push_back( -6386 PathEvent::RemoteStatus { -6387 id: path_id, -6388 status, -6389 } -6390 .into(), -6391 ); -6392 } -6393 -6394 /// Returns the maximum [`PathId`] to be used for sending in this connection. -6395 /// -6396 /// This is calculated as minimum between the local and remote's maximums when multipath is -6397 /// enabled, or `None` when disabled. -6398 /// -6399 /// For data that's received, we should use [`Self::local_max_path_id`] instead. -6400 /// The reasoning is that the remote might already have updated to its own newer -6401 /// [`Self::max_path_id`] after sending out a `MAX_PATH_ID` frame, but it got re-ordered. -6402 fn max_path_id(&self) -> Option<PathId> { -6403 if self.is_multipath_negotiated() { -6404 Some(self.remote_max_path_id.min(self.local_max_path_id)) -6405 } else { -6406 None -6407 } -6408 } -6409 -6410 /// Add addresses the local endpoint considers are reachable for nat traversal -6411 pub fn add_nat_traversal_address(&mut self, address: SocketAddr) -> Result<(), iroh_hp::Error> { -6412 if let Some(added) = self.iroh_hp.add_local_address(address)? { -6413 self.spaces[SpaceId::Data].pending.add_address.insert(added); -6414 }; -6415 Ok(()) -6416 } -6417 -6418 /// Removes an address the endpoing no longer considers reachable for nat traversal -6419 /// -6420 /// Addresses not present in the set will be silently ignored. -6421 pub fn remove_nat_traversal_address( -6422 &mut self, -6423 address: SocketAddr, -6424 ) -> Result<(), iroh_hp::Error> { -6425 if let Some(removed) = self.iroh_hp.remove_local_address(address)? { -6426 self.spaces[SpaceId::Data] -6427 .pending -6428 .remove_address -6429 .insert(removed); -6430 } -6431 Ok(()) -6432 } -6433 -6434 /// Get the current local nat traversal addresses -6435 pub fn get_local_nat_traversal_addresses(&self) -> Result<Vec<SocketAddr>, iroh_hp::Error> { -6436 self.iroh_hp.get_local_nat_traversal_addresses() +6054 let result = match result { +6055 Some(r) => r, +6056 None => return Ok(None), +6057 }; +6058 +6059 if result.outgoing_key_update_acked { +6060 if let Some(prev) = self.prev_crypto.as_mut() { +6061 prev.end_packet = Some((result.number, now)); +6062 self.set_key_discard_timer(now, packet.header.space()); +6063 } +6064 } +6065 +6066 if result.incoming_key_update { +6067 trace!("key update authenticated"); +6068 self.update_keys(Some((result.number, now)), true); +6069 self.set_key_discard_timer(now, packet.header.space()); +6070 } +6071 +6072 Ok(Some(result.number)) +6073 } +6074 +6075 fn update_keys(&mut self, end_packet: Option<(u64, Instant)>, remote: bool) { +6076 trace!("executing key update"); +6077 // Generate keys for the key phase after the one we're switching to, store them in +6078 // `next_crypto`, make the contents of `next_crypto` current, and move the current keys into +6079 // `prev_crypto`. +6080 let new = self +6081 .crypto +6082 .next_1rtt_keys() +6083 .expect("only called for `Data` packets"); +6084 self.key_phase_size = new +6085 .local +6086 .confidentiality_limit() +6087 .saturating_sub(KEY_UPDATE_MARGIN); +6088 let old = mem::replace( +6089 &mut self.spaces[SpaceId::Data] +6090 .crypto +6091 .as_mut() +6092 .unwrap() // safe because update_keys() can only be triggered by short packets +6093 .packet, +6094 mem::replace(self.next_crypto.as_mut().unwrap(), new), +6095 ); +6096 self.spaces[SpaceId::Data] +6097 .iter_paths_mut() +6098 .for_each(|s| s.sent_with_keys = 0); +6099 self.prev_crypto = Some(PrevCrypto { +6100 crypto: old, +6101 end_packet, +6102 update_unacked: remote, +6103 }); +6104 self.key_phase = !self.key_phase; +6105 } +6106 +6107 fn peer_supports_ack_frequency(&self) -> bool { +6108 self.peer_params.min_ack_delay.is_some() +6109 } +6110 +6111 /// Send an IMMEDIATE_ACK frame to the remote endpoint +6112 /// +6113 /// According to the spec, this will result in an error if the remote endpoint does not support +6114 /// the Acknowledgement Frequency extension +6115 pub(crate) fn immediate_ack(&mut self, path_id: PathId) { +6116 debug_assert_eq!( +6117 self.highest_space, +6118 SpaceId::Data, +6119 "immediate ack must be written in the data space" +6120 ); +6121 self.spaces[self.highest_space] +6122 .for_path(path_id) +6123 .immediate_ack_pending = true; +6124 } +6125 +6126 /// Decodes a packet, returning its decrypted payload, so it can be inspected in tests +6127 #[cfg(test)] +6128 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> { +6129 let (path_id, first_decode, remaining) = match &event.0 { +6130 ConnectionEventInner::Datagram(DatagramConnectionEvent { +6131 path_id, +6132 first_decode, +6133 remaining, +6134 .. +6135 }) => (path_id, first_decode, remaining), +6136 _ => return None, +6137 }; +6138 +6139 if remaining.is_some() { +6140 panic!("Packets should never be coalesced in tests"); +6141 } +6142 +6143 let decrypted_header = packet_crypto::unprotect_header( +6144 first_decode.clone(), +6145 &self.spaces, +6146 self.zero_rtt_crypto.as_ref(), +6147 self.peer_params.stateless_reset_token, +6148 )?; +6149 +6150 let mut packet = decrypted_header.packet?; +6151 packet_crypto::decrypt_packet_body( +6152 &mut packet, +6153 *path_id, +6154 &self.spaces, +6155 self.zero_rtt_crypto.as_ref(), +6156 self.key_phase, +6157 self.prev_crypto.as_ref(), +6158 self.next_crypto.as_ref(), +6159 ) +6160 .ok()?; +6161 +6162 Some(packet.payload.to_vec()) +6163 } +6164 +6165 /// The number of bytes of packets containing retransmittable frames that have not been +6166 /// acknowledged or declared lost. +6167 #[cfg(test)] +6168 pub(crate) fn bytes_in_flight(&self) -> u64 { +6169 // TODO(@divma): consider including for multipath? +6170 self.path_data(PathId::ZERO).in_flight.bytes +6171 } +6172 +6173 /// Number of bytes worth of non-ack-only packets that may be sent +6174 #[cfg(test)] +6175 pub(crate) fn congestion_window(&self) -> u64 { +6176 let path = self.path_data(PathId::ZERO); +6177 path.congestion +6178 .window() +6179 .saturating_sub(path.in_flight.bytes) +6180 } +6181 +6182 /// Whether no timers but keepalive, idle, rtt, pushnewcid, and key discard are running +6183 #[cfg(test)] +6184 pub(crate) fn is_idle(&self) -> bool { +6185 let current_timers = self.timers.values(); +6186 current_timers +6187 .into_iter() +6188 .filter(|(timer, _)| { +6189 !matches!( +6190 timer, +6191 Timer::Conn(ConnTimer::KeepAlive) +6192 | Timer::PerPath(_, PathTimer::PathKeepAlive) +6193 | Timer::Conn(ConnTimer::PushNewCid) +6194 | Timer::Conn(ConnTimer::KeyDiscard) +6195 ) +6196 }) +6197 .min_by_key(|(_, time)| *time) +6198 .is_none_or(|(timer, _)| timer == Timer::Conn(ConnTimer::Idle)) +6199 } +6200 +6201 /// Whether explicit congestion notification is in use on outgoing packets. +6202 #[cfg(test)] +6203 pub(crate) fn using_ecn(&self) -> bool { +6204 self.path_data(PathId::ZERO).sending_ecn +6205 } +6206 +6207 /// The number of received bytes in the current path +6208 #[cfg(test)] +6209 pub(crate) fn total_recvd(&self) -> u64 { +6210 self.path_data(PathId::ZERO).total_recvd +6211 } +6212 +6213 #[cfg(test)] +6214 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) { +6215 self.local_cid_state +6216 .get(&PathId::ZERO) +6217 .unwrap() +6218 .active_seq() +6219 } +6220 +6221 #[cfg(test)] +6222 #[track_caller] +6223 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) { +6224 self.local_cid_state +6225 .get(&PathId(path_id)) +6226 .unwrap() +6227 .active_seq() +6228 } +6229 +6230 /// Instruct the peer to replace previously issued CIDs by sending a NEW_CONNECTION_ID frame +6231 /// with updated `retire_prior_to` field set to `v` +6232 #[cfg(test)] +6233 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) { +6234 let n = self +6235 .local_cid_state +6236 .get_mut(&PathId::ZERO) +6237 .unwrap() +6238 .assign_retire_seq(v); +6239 self.endpoint_events +6240 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n)); +6241 } +6242 +6243 /// Check the current active remote CID sequence for `PathId::ZERO` +6244 #[cfg(test)] +6245 pub(crate) fn active_rem_cid_seq(&self) -> u64 { +6246 self.rem_cids.get(&PathId::ZERO).unwrap().active_seq() +6247 } +6248 +6249 /// Returns the detected maximum udp payload size for the current path +6250 #[cfg(test)] +6251 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 { +6252 self.path_data(path_id).current_mtu() +6253 } +6254 +6255 /// Triggers path validation on all paths +6256 #[cfg(test)] +6257 pub(crate) fn trigger_path_validation(&mut self) { +6258 for path in self.paths.values_mut() { +6259 path.data.send_new_challenge = true; +6260 } +6261 } +6262 +6263 /// Whether we have 1-RTT data to send +6264 /// +6265 /// This checks for frames that can only be sent in the data space (1-RTT): +6266 /// - Pending PATH_CHALLENGE frames on the active and previous path if just migrated. +6267 /// - Pending PATH_RESPONSE frames. +6268 /// - Pending data to send in STREAM frames. +6269 /// - Pending DATAGRAM frames to send. +6270 /// +6271 /// See also [`PacketSpace::can_send`] which keeps track of all other frame types that +6272 /// may need to be sent. +6273 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames { +6274 let path_exclusive = self.paths.get(&path_id).is_some_and(|path| { +6275 path.data.send_new_challenge +6276 || path +6277 .prev +6278 .as_ref() +6279 .is_some_and(|(_, path)| path.send_new_challenge) +6280 || !path.data.path_responses.is_empty() +6281 }); +6282 let other = self.streams.can_send_stream_data() +6283 || self +6284 .datagrams +6285 .outgoing +6286 .front() +6287 .is_some_and(|x| x.size(true) <= max_size); +6288 SendableFrames { +6289 acks: false, +6290 other, +6291 close: false, +6292 path_exclusive, +6293 } +6294 } +6295 +6296 /// Terminate the connection instantly, without sending a close packet +6297 fn kill(&mut self, reason: ConnectionError) { +6298 self.close_common(); +6299 self.state.move_to_drained(Some(reason)); +6300 self.endpoint_events.push_back(EndpointEventInner::Drained); +6301 } +6302 +6303 /// Storage size required for the largest packet that can be transmitted on all currently +6304 /// available paths +6305 /// +6306 /// Buffers passed to [`Connection::poll_transmit`] should be at least this large. +6307 /// +6308 /// When multipath is enabled, this value is the minimum MTU across all available paths. +6309 pub fn current_mtu(&self) -> u16 { +6310 self.paths +6311 .iter() +6312 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id)) +6313 .map(|(_path_id, path_state)| path_state.data.current_mtu()) +6314 .min() +6315 .expect("There is always at least one available path") +6316 } +6317 +6318 /// Size of non-frame data for a 1-RTT packet +6319 /// +6320 /// Quantifies space consumed by the QUIC header and AEAD tag. All other bytes in a packet are +6321 /// frames. Changes if the length of the remote connection ID changes, which is expected to be +6322 /// rare. If `pn` is specified, may additionally change unpredictably due to variations in +6323 /// latency and packet loss. +6324 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize { +6325 let pn_len = PacketNumber::new( +6326 pn, +6327 self.spaces[SpaceId::Data] +6328 .for_path(path) +6329 .largest_acked_packet +6330 .unwrap_or(0), +6331 ) +6332 .len(); +6333 +6334 // 1 byte for flags +6335 1 + self +6336 .rem_cids +6337 .get(&path) +6338 .map(|cids| cids.active().len()) +6339 .unwrap_or(20) // Max CID len in QUIC v1 +6340 + pn_len +6341 + self.tag_len_1rtt() +6342 } +6343 +6344 fn predict_1rtt_overhead_no_pn(&self) -> usize { +6345 let pn_len = 4; +6346 +6347 let cid_len = self +6348 .rem_cids +6349 .values() +6350 .map(|cids| cids.active().len()) +6351 .max() +6352 .unwrap_or(20); // Max CID len in QUIC v1 +6353 +6354 // 1 byte for flags +6355 1 + cid_len + pn_len + self.tag_len_1rtt() +6356 } +6357 +6358 fn tag_len_1rtt(&self) -> usize { +6359 let key = match self.spaces[SpaceId::Data].crypto.as_ref() { +6360 Some(crypto) => Some(&*crypto.packet.local), +6361 None => self.zero_rtt_crypto.as_ref().map(|x| &*x.packet), +6362 }; +6363 // If neither Data nor 0-RTT keys are available, make a reasonable tag length guess. As of +6364 // this writing, all QUIC cipher suites use 16-byte tags. We could return `None` instead, +6365 // but that would needlessly prevent sending datagrams during 0-RTT. +6366 key.map_or(16, |x| x.tag_len()) +6367 } +6368 +6369 /// Mark the path as validated, and enqueue NEW_TOKEN frames to be sent as appropriate +6370 fn on_path_validated(&mut self, path_id: PathId) { +6371 self.path_data_mut(path_id).validated = true; +6372 let ConnectionSide::Server { server_config } = &self.side else { +6373 return; +6374 }; +6375 let network_path = self.path_data(path_id).network_path; +6376 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens; +6377 new_tokens.clear(); +6378 for _ in 0..server_config.validation_token.sent { +6379 new_tokens.push(network_path); +6380 } +6381 } +6382 +6383 /// Handle new path status information: PATH_STATUS_AVAILABLE, PATH_STATUS_BACKUP +6384 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) { +6385 if let Some(path) = self.paths.get_mut(&path_id) { +6386 path.data.status.remote_update(status, status_seq_no); +6387 } else { +6388 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id); +6389 } +6390 self.events.push_back( +6391 PathEvent::RemoteStatus { +6392 id: path_id, +6393 status, +6394 } +6395 .into(), +6396 ); +6397 } +6398 +6399 /// Returns the maximum [`PathId`] to be used for sending in this connection. +6400 /// +6401 /// This is calculated as minimum between the local and remote's maximums when multipath is +6402 /// enabled, or `None` when disabled. +6403 /// +6404 /// For data that's received, we should use [`Self::local_max_path_id`] instead. +6405 /// The reasoning is that the remote might already have updated to its own newer +6406 /// [`Self::max_path_id`] after sending out a `MAX_PATH_ID` frame, but it got re-ordered. +6407 fn max_path_id(&self) -> Option<PathId> { +6408 if self.is_multipath_negotiated() { +6409 Some(self.remote_max_path_id.min(self.local_max_path_id)) +6410 } else { +6411 None +6412 } +6413 } +6414 +6415 /// Add addresses the local endpoint considers are reachable for nat traversal +6416 pub fn add_nat_traversal_address(&mut self, address: SocketAddr) -> Result<(), iroh_hp::Error> { +6417 if let Some(added) = self.iroh_hp.add_local_address(address)? { +6418 self.spaces[SpaceId::Data].pending.add_address.insert(added); +6419 }; +6420 Ok(()) +6421 } +6422 +6423 /// Removes an address the endpoing no longer considers reachable for nat traversal +6424 /// +6425 /// Addresses not present in the set will be silently ignored. +6426 pub fn remove_nat_traversal_address( +6427 &mut self, +6428 address: SocketAddr, +6429 ) -> Result<(), iroh_hp::Error> { +6430 if let Some(removed) = self.iroh_hp.remove_local_address(address)? { +6431 self.spaces[SpaceId::Data] +6432 .pending +6433 .remove_address +6434 .insert(removed); +6435 } +6436 Ok(()) 6437 } 6438 -6439 /// Get the currently advertised nat traversal addresses by the server -6440 pub fn get_remote_nat_traversal_addresses(&self) -> Result<Vec<SocketAddr>, iroh_hp::Error> { -6441 Ok(self -6442 .iroh_hp -6443 .client_side()? -6444 .get_remote_nat_traversal_addresses()) -6445 } -6446 -6447 /// Attempts to open a path for nat traversal. -6448 /// -6449 /// `ipv6` indicates if the path should be opened using an IPV6 remote. If the address is -6450 /// ignored, it will return `None`. -6451 /// -6452 /// On success returns the [`PathId`] and remote address of the path, as well as whether the path -6453 /// existed for the adjusted remote. -6454 fn open_nat_traversal_path( -6455 &mut self, -6456 now: Instant, -6457 (ip, port): (IpAddr, u16), -6458 ipv6: bool, -6459 ) -> Result<Option<(PathId, SocketAddr, bool)>, PathError> { -6460 // If this endpoint is an IPv6 endpoint we use IPv6 addresses for all remotes. -6461 let remote = match ip { -6462 IpAddr::V4(addr) if ipv6 => SocketAddr::new(addr.to_ipv6_mapped().into(), port), -6463 IpAddr::V4(addr) => SocketAddr::new(addr.into(), port), -6464 IpAddr::V6(_) if ipv6 => SocketAddr::new(ip, port), -6465 IpAddr::V6(_) => { -6466 trace!("not using IPv6 nat candidate for IPv4 socket"); -6467 return Ok(None); -6468 } -6469 }; -6470 // TODO(matheus23): Probe the correct 4-tuple, instead of only a remote address? -6471 // By specifying None, we do two things: 1. open_path_ensure won't generate two -6472 // paths to the same remote and 2. we let the OS choose which interface to use for -6473 // sending on that path. -6474 let network_path = FourTuple { -6475 remote, -6476 local_ip: None, -6477 }; -6478 match self.open_path_ensure(network_path, PathStatus::Backup, now) { -6479 Ok((path_id, path_was_known)) => { -6480 if path_was_known { -6481 trace!(%path_id, %remote, "nat traversal: path existed for remote"); -6482 } -6483 Ok(Some((path_id, remote, path_was_known))) -6484 } -6485 Err(e) => { -6486 debug!(%remote, %e, "nat traversal: failed to probe remote"); -6487 Err(e) -6488 } -6489 } -6490 } -6491 -6492 /// Initiates a new nat traversal round -6493 /// -6494 /// A nat traversal round involves advertising the client's local addresses in `REACH_OUT` -6495 /// frames, and initiating probing of the known remote addresses. When a new round is -6496 /// initiated, the previous one is cancelled, and paths that have not been opened are closed. -6497 /// -6498 /// Returns the server addresses that are now being probed. -6499 /// If addresses fail due to spurious errors, these might succeed later and not be returned in -6500 /// this set. -6501 pub fn initiate_nat_traversal_round( -6502 &mut self, -6503 now: Instant, -6504 ) -> Result<Vec<SocketAddr>, iroh_hp::Error> { -6505 if self.state.is_closed() { -6506 return Err(iroh_hp::Error::Closed); -6507 } -6508 -6509 let client_state = self.iroh_hp.client_side_mut()?; -6510 let iroh_hp::NatTraversalRound { -6511 new_round, -6512 reach_out_at, -6513 addresses_to_probe, -6514 prev_round_path_ids, -6515 } = client_state.initiate_nat_traversal_round()?; -6516 -6517 self.spaces[SpaceId::Data].pending.reach_out = Some((new_round, reach_out_at)); -6518 -6519 for path_id in prev_round_path_ids { -6520 // TODO(@divma): this sounds reasonable but we need if this actually works for the -6521 // purposes of the protocol -6522 let validated = self -6523 .path(path_id) -6524 .map(|path| path.validated) -6525 .unwrap_or(false); -6526 -6527 if !validated { -6528 let _ = self.close_path( -6529 now, -6530 path_id, -6531 TransportErrorCode::APPLICATION_ABANDON_PATH.into(), -6532 ); -6533 } -6534 } -6535 -6536 let mut err = None; -6537 -6538 let mut path_ids = Vec::with_capacity(addresses_to_probe.len()); -6539 let mut probed_addresses = Vec::with_capacity(addresses_to_probe.len()); -6540 let ipv6 = self -6541 .paths -6542 .values() -6543 .any(|p| p.data.network_path.remote.is_ipv6()); -6544 -6545 for (id, address) in addresses_to_probe { -6546 match self.open_nat_traversal_path(now, address, ipv6) { -6547 Ok(None) => {} -6548 Ok(Some((path_id, remote, path_was_known))) => { -6549 if !path_was_known { -6550 path_ids.push(path_id); -6551 probed_addresses.push(remote); -6552 } -6553 } -6554 Err(e) => { -6555 self.iroh_hp -6556 .client_side_mut() -6557 .expect("validated") -6558 .report_in_continuation(id, e); -6559 err.get_or_insert(e); -6560 } -6561 } -6562 } -6563 -6564 if let Some(err) = err { -6565 // We failed to probe any addresses, bail out -6566 if probed_addresses.is_empty() { -6567 return Err(iroh_hp::Error::Multipath(err)); -6568 } -6569 } -6570 -6571 self.iroh_hp -6572 .client_side_mut() -6573 .expect("connection side validated") -6574 .set_round_path_ids(path_ids); +6439 /// Get the current local nat traversal addresses +6440 pub fn get_local_nat_traversal_addresses(&self) -> Result<Vec<SocketAddr>, iroh_hp::Error> { +6441 self.iroh_hp.get_local_nat_traversal_addresses() +6442 } +6443 +6444 /// Get the currently advertised nat traversal addresses by the server +6445 pub fn get_remote_nat_traversal_addresses(&self) -> Result<Vec<SocketAddr>, iroh_hp::Error> { +6446 Ok(self +6447 .iroh_hp +6448 .client_side()? +6449 .get_remote_nat_traversal_addresses()) +6450 } +6451 +6452 /// Attempts to open a path for nat traversal. +6453 /// +6454 /// `ipv6` indicates if the path should be opened using an IPV6 remote. If the address is +6455 /// ignored, it will return `None`. +6456 /// +6457 /// On success returns the [`PathId`] and remote address of the path, as well as whether the path +6458 /// existed for the adjusted remote. +6459 fn open_nat_traversal_path( +6460 &mut self, +6461 now: Instant, +6462 (ip, port): (IpAddr, u16), +6463 ipv6: bool, +6464 ) -> Result<Option<(PathId, SocketAddr, bool)>, PathError> { +6465 // If this endpoint is an IPv6 endpoint we use IPv6 addresses for all remotes. +6466 let remote = match ip { +6467 IpAddr::V4(addr) if ipv6 => SocketAddr::new(addr.to_ipv6_mapped().into(), port), +6468 IpAddr::V4(addr) => SocketAddr::new(addr.into(), port), +6469 IpAddr::V6(_) if ipv6 => SocketAddr::new(ip, port), +6470 IpAddr::V6(_) => { +6471 trace!("not using IPv6 nat candidate for IPv4 socket"); +6472 return Ok(None); +6473 } +6474 }; +6475 // TODO(matheus23): Probe the correct 4-tuple, instead of only a remote address? +6476 // By specifying None, we do two things: 1. open_path_ensure won't generate two +6477 // paths to the same remote and 2. we let the OS choose which interface to use for +6478 // sending on that path. +6479 let network_path = FourTuple { +6480 remote, +6481 local_ip: None, +6482 }; +6483 match self.open_path_ensure(network_path, PathStatus::Backup, now) { +6484 Ok((path_id, path_was_known)) => { +6485 if path_was_known { +6486 trace!(%path_id, %remote, "nat traversal: path existed for remote"); +6487 } +6488 Ok(Some((path_id, remote, path_was_known))) +6489 } +6490 Err(e) => { +6491 debug!(%remote, %e, "nat traversal: failed to probe remote"); +6492 Err(e) +6493 } +6494 } +6495 } +6496 +6497 /// Initiates a new nat traversal round +6498 /// +6499 /// A nat traversal round involves advertising the client's local addresses in `REACH_OUT` +6500 /// frames, and initiating probing of the known remote addresses. When a new round is +6501 /// initiated, the previous one is cancelled, and paths that have not been opened are closed. +6502 /// +6503 /// Returns the server addresses that are now being probed. +6504 /// If addresses fail due to spurious errors, these might succeed later and not be returned in +6505 /// this set. +6506 pub fn initiate_nat_traversal_round( +6507 &mut self, +6508 now: Instant, +6509 ) -> Result<Vec<SocketAddr>, iroh_hp::Error> { +6510 if self.state.is_closed() { +6511 return Err(iroh_hp::Error::Closed); +6512 } +6513 +6514 let client_state = self.iroh_hp.client_side_mut()?; +6515 let iroh_hp::NatTraversalRound { +6516 new_round, +6517 reach_out_at, +6518 addresses_to_probe, +6519 prev_round_path_ids, +6520 } = client_state.initiate_nat_traversal_round()?; +6521 +6522 self.spaces[SpaceId::Data].pending.reach_out = Some((new_round, reach_out_at)); +6523 +6524 for path_id in prev_round_path_ids { +6525 // TODO(@divma): this sounds reasonable but we need if this actually works for the +6526 // purposes of the protocol +6527 let validated = self +6528 .path(path_id) +6529 .map(|path| path.validated) +6530 .unwrap_or(false); +6531 +6532 if !validated { +6533 let _ = self.close_path( +6534 now, +6535 path_id, +6536 TransportErrorCode::APPLICATION_ABANDON_PATH.into(), +6537 ); +6538 } +6539 } +6540 +6541 let mut err = None; +6542 +6543 let mut path_ids = Vec::with_capacity(addresses_to_probe.len()); +6544 let mut probed_addresses = Vec::with_capacity(addresses_to_probe.len()); +6545 let ipv6 = self +6546 .paths +6547 .values() +6548 .any(|p| p.data.network_path.remote.is_ipv6()); +6549 +6550 for (id, address) in addresses_to_probe { +6551 match self.open_nat_traversal_path(now, address, ipv6) { +6552 Ok(None) => {} +6553 Ok(Some((path_id, remote, path_was_known))) => { +6554 if !path_was_known { +6555 path_ids.push(path_id); +6556 probed_addresses.push(remote); +6557 } +6558 } +6559 Err(e) => { +6560 self.iroh_hp +6561 .client_side_mut() +6562 .expect("validated") +6563 .report_in_continuation(id, e); +6564 err.get_or_insert(e); +6565 } +6566 } +6567 } +6568 +6569 if let Some(err) = err { +6570 // We failed to probe any addresses, bail out +6571 if probed_addresses.is_empty() { +6572 return Err(iroh_hp::Error::Multipath(err)); +6573 } +6574 } 6575 -6576 Ok(probed_addresses) -6577 } -6578 -6579 /// Attempts to continue a nat traversal round by trying to open paths for pending client probes. -6580 /// -6581 /// If there was nothing to do, it returns `None`. Otherwise it returns whether the path was -6582 /// successfully open. -6583 fn continue_nat_traversal_round(&mut self, now: Instant) -> Option<bool> { -6584 let client_state = self.iroh_hp.client_side_mut().ok()?; -6585 let (id, address) = client_state.continue_nat_traversal_round()?; -6586 let ipv6 = self -6587 .paths -6588 .values() -6589 .any(|p| p.data.network_path.remote.is_ipv6()); -6590 let open_result = self.open_nat_traversal_path(now, address, ipv6); -6591 let client_state = self.iroh_hp.client_side_mut().expect("validated"); -6592 match open_result { -6593 Ok(None) => Some(true), -6594 Ok(Some((path_id, _remote, path_was_known))) => { -6595 if !path_was_known { -6596 client_state.add_round_path_id(path_id); -6597 } -6598 Some(true) -6599 } -6600 Err(e) => { -6601 client_state.report_in_continuation(id, e); -6602 Some(false) -6603 } -6604 } -6605 } -6606} -6607 -6608impl fmt::Debug for Connection { -6609 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -6610 f.debug_struct("Connection") -6611 .field("handshake_cid", &self.handshake_cid) -6612 .finish() -6613 } -6614} -6615 -6616#[derive(Debug, Copy, Clone, PartialEq, Eq)] -6617enum PathBlocked { -6618 No, -6619 AntiAmplification, -6620 Congestion, -6621 Pacing, -6622} -6623 -6624/// Fields of `Connection` specific to it being client-side or server-side -6625enum ConnectionSide { -6626 Client { -6627 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded -6628 token: Bytes, -6629 token_store: Arc<dyn TokenStore>, -6630 server_name: String, -6631 }, -6632 Server { -6633 server_config: Arc<ServerConfig>, -6634 }, -6635} -6636 -6637impl ConnectionSide { -6638 fn remote_may_migrate(&self, state: &State) -> bool { -6639 match self { -6640 Self::Server { server_config } => server_config.migration, -6641 Self::Client { .. } => { -6642 if let Some(hs) = state.as_handshake() { -6643 hs.allow_server_migration -6644 } else { -6645 false -6646 } -6647 } -6648 } -6649 } -6650 -6651 fn is_client(&self) -> bool { -6652 self.side().is_client() -6653 } -6654 -6655 fn is_server(&self) -> bool { -6656 self.side().is_server() -6657 } -6658 -6659 fn side(&self) -> Side { -6660 match *self { -6661 Self::Client { .. } => Side::Client, -6662 Self::Server { .. } => Side::Server, -6663 } -6664 } -6665} -6666 -6667impl From<SideArgs> for ConnectionSide { -6668 fn from(side: SideArgs) -> Self { -6669 match side { -6670 SideArgs::Client { -6671 token_store, -6672 server_name, -6673 } => Self::Client { -6674 token: token_store.take(&server_name).unwrap_or_default(), -6675 token_store, -6676 server_name, -6677 }, -6678 SideArgs::Server { -6679 server_config, -6680 pref_addr_cid: _, -6681 path_validated: _, -6682 } => Self::Server { server_config }, -6683 } -6684 } -6685} -6686 -6687/// Parameters to `Connection::new` specific to it being client-side or server-side -6688pub(crate) enum SideArgs { -6689 Client { -6690 token_store: Arc<dyn TokenStore>, -6691 server_name: String, -6692 }, -6693 Server { -6694 server_config: Arc<ServerConfig>, -6695 pref_addr_cid: Option<ConnectionId>, -6696 path_validated: bool, +6576 self.iroh_hp +6577 .client_side_mut() +6578 .expect("connection side validated") +6579 .set_round_path_ids(path_ids); +6580 +6581 Ok(probed_addresses) +6582 } +6583 +6584 /// Attempts to continue a nat traversal round by trying to open paths for pending client probes. +6585 /// +6586 /// If there was nothing to do, it returns `None`. Otherwise it returns whether the path was +6587 /// successfully open. +6588 fn continue_nat_traversal_round(&mut self, now: Instant) -> Option<bool> { +6589 let client_state = self.iroh_hp.client_side_mut().ok()?; +6590 let (id, address) = client_state.continue_nat_traversal_round()?; +6591 let ipv6 = self +6592 .paths +6593 .values() +6594 .any(|p| p.data.network_path.remote.is_ipv6()); +6595 let open_result = self.open_nat_traversal_path(now, address, ipv6); +6596 let client_state = self.iroh_hp.client_side_mut().expect("validated"); +6597 match open_result { +6598 Ok(None) => Some(true), +6599 Ok(Some((path_id, _remote, path_was_known))) => { +6600 if !path_was_known { +6601 client_state.add_round_path_id(path_id); +6602 } +6603 Some(true) +6604 } +6605 Err(e) => { +6606 client_state.report_in_continuation(id, e); +6607 Some(false) +6608 } +6609 } +6610 } +6611} +6612 +6613impl fmt::Debug for Connection { +6614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +6615 f.debug_struct("Connection") +6616 .field("handshake_cid", &self.handshake_cid) +6617 .finish() +6618 } +6619} +6620 +6621#[derive(Debug, Copy, Clone, PartialEq, Eq)] +6622enum PathBlocked { +6623 No, +6624 AntiAmplification, +6625 Congestion, +6626 Pacing, +6627} +6628 +6629/// Fields of `Connection` specific to it being client-side or server-side +6630enum ConnectionSide { +6631 Client { +6632 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded +6633 token: Bytes, +6634 token_store: Arc<dyn TokenStore>, +6635 server_name: String, +6636 }, +6637 Server { +6638 server_config: Arc<ServerConfig>, +6639 }, +6640} +6641 +6642impl ConnectionSide { +6643 fn remote_may_migrate(&self, state: &State) -> bool { +6644 match self { +6645 Self::Server { server_config } => server_config.migration, +6646 Self::Client { .. } => { +6647 if let Some(hs) = state.as_handshake() { +6648 hs.allow_server_migration +6649 } else { +6650 false +6651 } +6652 } +6653 } +6654 } +6655 +6656 fn is_client(&self) -> bool { +6657 self.side().is_client() +6658 } +6659 +6660 fn is_server(&self) -> bool { +6661 self.side().is_server() +6662 } +6663 +6664 fn side(&self) -> Side { +6665 match *self { +6666 Self::Client { .. } => Side::Client, +6667 Self::Server { .. } => Side::Server, +6668 } +6669 } +6670} +6671 +6672impl From<SideArgs> for ConnectionSide { +6673 fn from(side: SideArgs) -> Self { +6674 match side { +6675 SideArgs::Client { +6676 token_store, +6677 server_name, +6678 } => Self::Client { +6679 token: token_store.take(&server_name).unwrap_or_default(), +6680 token_store, +6681 server_name, +6682 }, +6683 SideArgs::Server { +6684 server_config, +6685 pref_addr_cid: _, +6686 path_validated: _, +6687 } => Self::Server { server_config }, +6688 } +6689 } +6690} +6691 +6692/// Parameters to `Connection::new` specific to it being client-side or server-side +6693pub(crate) enum SideArgs { +6694 Client { +6695 token_store: Arc<dyn TokenStore>, +6696 server_name: String, 6697 }, -6698} -6699 -6700impl SideArgs { -6701 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> { -6702 match *self { -6703 Self::Client { .. } => None, -6704 Self::Server { pref_addr_cid, .. } => pref_addr_cid, -6705 } -6706 } -6707 -6708 pub(crate) fn path_validated(&self) -> bool { -6709 match *self { -6710 Self::Client { .. } => true, -6711 Self::Server { path_validated, .. } => path_validated, -6712 } -6713 } -6714 -6715 pub(crate) fn side(&self) -> Side { -6716 match *self { -6717 Self::Client { .. } => Side::Client, -6718 Self::Server { .. } => Side::Server, -6719 } -6720 } -6721} -6722 -6723/// Reasons why a connection might be lost -6724#[derive(Debug, Error, Clone, PartialEq, Eq)] -6725pub enum ConnectionError { -6726 /// The peer doesn't implement any supported version -6727 #[error("peer doesn't implement any supported version")] -6728 VersionMismatch, -6729 /// The peer violated the QUIC specification as understood by this implementation -6730 #[error(transparent)] -6731 TransportError(#[from] TransportError), -6732 /// The peer's QUIC stack aborted the connection automatically -6733 #[error("aborted by peer: {0}")] -6734 ConnectionClosed(frame::ConnectionClose), -6735 /// The peer closed the connection -6736 #[error("closed by peer: {0}")] -6737 ApplicationClosed(frame::ApplicationClose), -6738 /// The peer is unable to continue processing this connection, usually due to having restarted -6739 #[error("reset by peer")] -6740 Reset, -6741 /// Communication with the peer has lapsed for longer than the negotiated idle timeout -6742 /// -6743 /// If neither side is sending keep-alives, a connection will time out after a long enough idle -6744 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`] -6745 /// and [`TransportConfig::keep_alive_interval()`]. -6746 #[error("timed out")] -6747 TimedOut, -6748 /// The local application closed the connection -6749 #[error("closed")] -6750 LocallyClosed, -6751 /// The connection could not be created because not enough of the CID space is available -6752 /// -6753 /// Try using longer connection IDs. -6754 #[error("CIDs exhausted")] -6755 CidsExhausted, -6756} -6757 -6758impl From<Close> for ConnectionError { -6759 fn from(x: Close) -> Self { -6760 match x { -6761 Close::Connection(reason) => Self::ConnectionClosed(reason), -6762 Close::Application(reason) => Self::ApplicationClosed(reason), -6763 } -6764 } -6765} -6766 -6767// For compatibility with API consumers -6768impl From<ConnectionError> for io::Error { -6769 fn from(x: ConnectionError) -> Self { -6770 use ConnectionError::*; -6771 let kind = match x { -6772 TimedOut => io::ErrorKind::TimedOut, -6773 Reset => io::ErrorKind::ConnectionReset, -6774 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted, -6775 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => { -6776 io::ErrorKind::Other -6777 } -6778 }; -6779 Self::new(kind, x) -6780 } -6781} -6782 -6783/// Errors that might trigger a path being closed -6784// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API -6785#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)] -6786pub enum PathError { -6787 /// The extension was not negotiated with the peer -6788 #[error("multipath extension not negotiated")] -6789 MultipathNotNegotiated, -6790 /// Paths can only be opened client-side -6791 #[error("the server side may not open a path")] -6792 ServerSideNotAllowed, -6793 /// Current limits do not allow us to open more paths -6794 #[error("maximum number of concurrent paths reached")] -6795 MaxPathIdReached, -6796 /// No remote CIDs available to open a new path -6797 #[error("remoted CIDs exhausted")] -6798 RemoteCidsExhausted, -6799 /// Path could not be validated and will be abandoned -6800 #[error("path validation failed")] -6801 ValidationFailed, -6802 /// The remote address for the path is not supported by the endpoint -6803 #[error("invalid remote address")] -6804 InvalidRemoteAddress(SocketAddr), -6805} -6806 -6807/// Errors triggered when abandoning a path -6808#[derive(Debug, Error, Clone, Eq, PartialEq)] -6809pub enum ClosePathError { -6810 /// The path is already closed or was never opened -6811 #[error("closed path")] -6812 ClosedPath, -6813 /// This is the last path, which can not be abandoned -6814 #[error("last open path")] -6815 LastOpenPath, -6816} -6817 -6818#[derive(Debug, Error, Clone, Copy)] -6819#[error("Multipath extension not negotiated")] -6820pub struct MultipathNotNegotiated { -6821 _private: (), -6822} -6823 -6824/// Events of interest to the application -6825#[derive(Debug)] -6826pub enum Event { -6827 /// The connection's handshake data is ready -6828 HandshakeDataReady, -6829 /// The connection was successfully established -6830 Connected, -6831 /// The TLS handshake was confirmed -6832 HandshakeConfirmed, -6833 /// The connection was lost -6834 /// -6835 /// Emitted if the peer closes the connection or an error is encountered. -6836 ConnectionLost { -6837 /// Reason that the connection was closed -6838 reason: ConnectionError, -6839 }, -6840 /// Stream events -6841 Stream(StreamEvent), -6842 /// One or more application datagrams have been received -6843 DatagramReceived, -6844 /// One or more application datagrams have been sent after blocking -6845 DatagramsUnblocked, -6846 /// (Multi)Path events -6847 Path(PathEvent), -6848 /// Iroh's nat traversal events -6849 NatTraversal(iroh_hp::Event), -6850} -6851 -6852impl From<PathEvent> for Event { -6853 fn from(source: PathEvent) -> Self { -6854 Self::Path(source) -6855 } +6698 Server { +6699 server_config: Arc<ServerConfig>, +6700 pref_addr_cid: Option<ConnectionId>, +6701 path_validated: bool, +6702 }, +6703} +6704 +6705impl SideArgs { +6706 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> { +6707 match *self { +6708 Self::Client { .. } => None, +6709 Self::Server { pref_addr_cid, .. } => pref_addr_cid, +6710 } +6711 } +6712 +6713 pub(crate) fn path_validated(&self) -> bool { +6714 match *self { +6715 Self::Client { .. } => true, +6716 Self::Server { path_validated, .. } => path_validated, +6717 } +6718 } +6719 +6720 pub(crate) fn side(&self) -> Side { +6721 match *self { +6722 Self::Client { .. } => Side::Client, +6723 Self::Server { .. } => Side::Server, +6724 } +6725 } +6726} +6727 +6728/// Reasons why a connection might be lost +6729#[derive(Debug, Error, Clone, PartialEq, Eq)] +6730pub enum ConnectionError { +6731 /// The peer doesn't implement any supported version +6732 #[error("peer doesn't implement any supported version")] +6733 VersionMismatch, +6734 /// The peer violated the QUIC specification as understood by this implementation +6735 #[error(transparent)] +6736 TransportError(#[from] TransportError), +6737 /// The peer's QUIC stack aborted the connection automatically +6738 #[error("aborted by peer: {0}")] +6739 ConnectionClosed(frame::ConnectionClose), +6740 /// The peer closed the connection +6741 #[error("closed by peer: {0}")] +6742 ApplicationClosed(frame::ApplicationClose), +6743 /// The peer is unable to continue processing this connection, usually due to having restarted +6744 #[error("reset by peer")] +6745 Reset, +6746 /// Communication with the peer has lapsed for longer than the negotiated idle timeout +6747 /// +6748 /// If neither side is sending keep-alives, a connection will time out after a long enough idle +6749 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`] +6750 /// and [`TransportConfig::keep_alive_interval()`]. +6751 #[error("timed out")] +6752 TimedOut, +6753 /// The local application closed the connection +6754 #[error("closed")] +6755 LocallyClosed, +6756 /// The connection could not be created because not enough of the CID space is available +6757 /// +6758 /// Try using longer connection IDs. +6759 #[error("CIDs exhausted")] +6760 CidsExhausted, +6761} +6762 +6763impl From<Close> for ConnectionError { +6764 fn from(x: Close) -> Self { +6765 match x { +6766 Close::Connection(reason) => Self::ConnectionClosed(reason), +6767 Close::Application(reason) => Self::ApplicationClosed(reason), +6768 } +6769 } +6770} +6771 +6772// For compatibility with API consumers +6773impl From<ConnectionError> for io::Error { +6774 fn from(x: ConnectionError) -> Self { +6775 use ConnectionError::*; +6776 let kind = match x { +6777 TimedOut => io::ErrorKind::TimedOut, +6778 Reset => io::ErrorKind::ConnectionReset, +6779 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted, +6780 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => { +6781 io::ErrorKind::Other +6782 } +6783 }; +6784 Self::new(kind, x) +6785 } +6786} +6787 +6788/// Errors that might trigger a path being closed +6789// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API +6790#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)] +6791pub enum PathError { +6792 /// The extension was not negotiated with the peer +6793 #[error("multipath extension not negotiated")] +6794 MultipathNotNegotiated, +6795 /// Paths can only be opened client-side +6796 #[error("the server side may not open a path")] +6797 ServerSideNotAllowed, +6798 /// Current limits do not allow us to open more paths +6799 #[error("maximum number of concurrent paths reached")] +6800 MaxPathIdReached, +6801 /// No remote CIDs available to open a new path +6802 #[error("remoted CIDs exhausted")] +6803 RemoteCidsExhausted, +6804 /// Path could not be validated and will be abandoned +6805 #[error("path validation failed")] +6806 ValidationFailed, +6807 /// The remote address for the path is not supported by the endpoint +6808 #[error("invalid remote address")] +6809 InvalidRemoteAddress(SocketAddr), +6810} +6811 +6812/// Errors triggered when abandoning a path +6813#[derive(Debug, Error, Clone, Eq, PartialEq)] +6814pub enum ClosePathError { +6815 /// The path is already closed or was never opened +6816 #[error("closed path")] +6817 ClosedPath, +6818 /// This is the last path, which can not be abandoned +6819 #[error("last open path")] +6820 LastOpenPath, +6821} +6822 +6823/// Error when the multipath extension was not negotiated, but attempted to be used. +6824#[derive(Debug, Error, Clone, Copy)] +6825#[error("Multipath extension not negotiated")] +6826pub struct MultipathNotNegotiated { +6827 _private: (), +6828} +6829 +6830/// Events of interest to the application +6831#[derive(Debug)] +6832pub enum Event { +6833 /// The connection's handshake data is ready +6834 HandshakeDataReady, +6835 /// The connection was successfully established +6836 Connected, +6837 /// The TLS handshake was confirmed +6838 HandshakeConfirmed, +6839 /// The connection was lost +6840 /// +6841 /// Emitted if the peer closes the connection or an error is encountered. +6842 ConnectionLost { +6843 /// Reason that the connection was closed +6844 reason: ConnectionError, +6845 }, +6846 /// Stream events +6847 Stream(StreamEvent), +6848 /// One or more application datagrams have been received +6849 DatagramReceived, +6850 /// One or more application datagrams have been sent after blocking +6851 DatagramsUnblocked, +6852 /// (Multi)Path events +6853 Path(PathEvent), +6854 /// Iroh's nat traversal events +6855 NatTraversal(iroh_hp::Event), 6856} 6857 -6858fn get_max_ack_delay(params: &TransportParameters) -> Duration { -6859 Duration::from_micros(params.max_ack_delay.0 * 1000) -6860} -6861 -6862// Prevents overflow and improves behavior in extreme circumstances -6863const MAX_BACKOFF_EXPONENT: u32 = 16; -6864 -6865/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag -6866/// -6867/// This must be at least as large as the header for a well-formed empty packet to be coalesced, -6868/// plus some space for frames. We only care about handshake headers because short header packets -6869/// necessarily have smaller headers, and initial packets are only ever the first packet in a -6870/// datagram (because we coalesce in ascending packet space order and the only reason to split a -6871/// packet is when packet space changes). -6872const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32; -6873 -6874/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header -6875/// -6876/// Excludes packet-type-specific fields such as packet number or Initial token -6877// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid + -6878// scid len + scid + length + pn -6879const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize = -6880 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4; -6881 -6882/// Perform key updates this many packets before the AEAD confidentiality limit. -6883/// -6884/// Chosen arbitrarily, intended to be large enough to prevent spurious connection loss. -6885const KEY_UPDATE_MARGIN: u64 = 10_000; -6886 -6887#[derive(Default)] -6888struct SentFrames { -6889 retransmits: ThinRetransmits, -6890 /// The packet number of the largest acknowledged packet for each path -6891 largest_acked: FxHashMap<PathId, u64>, -6892 stream_frames: StreamMetaVec, -6893 /// Whether the packet contains non-retransmittable frames (like datagrams) -6894 non_retransmits: bool, -6895 /// If the datagram containing these frames should be padded to the min MTU -6896 requires_padding: bool, -6897} -6898 -6899impl SentFrames { -6900 /// Returns whether the packet contains only ACKs -6901 fn is_ack_only(&self, streams: &StreamsState) -> bool { -6902 !self.largest_acked.is_empty() -6903 && !self.non_retransmits -6904 && self.stream_frames.is_empty() -6905 && self.retransmits.is_empty(streams) -6906 } -6907} -6908 -6909/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters. -6910/// -6911/// 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.> -6912/// -6913/// 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.> -6914/// -6915/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout. -6916fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> { -6917 match (x, y) { -6918 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None, -6919 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)), -6920 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)), -6921 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)), -6922 } -6923} -6924 -6925#[cfg(test)] -6926mod tests { -6927 use super::*; -6928 -6929 #[test] -6930 fn negotiate_max_idle_timeout_commutative() { -6931 let test_params = [ -6932 (None, None, None), -6933 (None, Some(VarInt(0)), None), -6934 (None, Some(VarInt(2)), Some(Duration::from_millis(2))), -6935 (Some(VarInt(0)), Some(VarInt(0)), None), -6936 ( -6937 Some(VarInt(2)), -6938 Some(VarInt(0)), -6939 Some(Duration::from_millis(2)), -6940 ), -6941 ( -6942 Some(VarInt(1)), -6943 Some(VarInt(4)), -6944 Some(Duration::from_millis(1)), -6945 ), -6946 ]; -6947 -6948 for (left, right, result) in test_params { -6949 assert_eq!(negotiate_max_idle_timeout(left, right), result); -6950 assert_eq!(negotiate_max_idle_timeout(right, left), result); -6951 } -6952 } -6953} \ No newline at end of file +6858impl From<PathEvent> for Event { +6859 fn from(source: PathEvent) -> Self { +6860 Self::Path(source) +6861 } +6862} +6863 +6864fn get_max_ack_delay(params: &TransportParameters) -> Duration { +6865 Duration::from_micros(params.max_ack_delay.0 * 1000) +6866} +6867 +6868// Prevents overflow and improves behavior in extreme circumstances +6869const MAX_BACKOFF_EXPONENT: u32 = 16; +6870 +6871/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag +6872/// +6873/// This must be at least as large as the header for a well-formed empty packet to be coalesced, +6874/// plus some space for frames. We only care about handshake headers because short header packets +6875/// necessarily have smaller headers, and initial packets are only ever the first packet in a +6876/// datagram (because we coalesce in ascending packet space order and the only reason to split a +6877/// packet is when packet space changes). +6878const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32; +6879 +6880/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header +6881/// +6882/// Excludes packet-type-specific fields such as packet number or Initial token +6883// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid + +6884// scid len + scid + length + pn +6885const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize = +6886 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4; +6887 +6888/// Perform key updates this many packets before the AEAD confidentiality limit. +6889/// +6890/// Chosen arbitrarily, intended to be large enough to prevent spurious connection loss. +6891const KEY_UPDATE_MARGIN: u64 = 10_000; +6892 +6893#[derive(Default)] +6894struct SentFrames { +6895 retransmits: ThinRetransmits, +6896 /// The packet number of the largest acknowledged packet for each path +6897 largest_acked: FxHashMap<PathId, u64>, +6898 stream_frames: StreamMetaVec, +6899 /// Whether the packet contains non-retransmittable frames (like datagrams) +6900 non_retransmits: bool, +6901 /// If the datagram containing these frames should be padded to the min MTU +6902 requires_padding: bool, +6903} +6904 +6905impl SentFrames { +6906 /// Returns whether the packet contains only ACKs +6907 fn is_ack_only(&self, streams: &StreamsState) -> bool { +6908 !self.largest_acked.is_empty() +6909 && !self.non_retransmits +6910 && self.stream_frames.is_empty() +6911 && self.retransmits.is_empty(streams) +6912 } +6913} +6914 +6915/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters. +6916/// +6917/// 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.> +6918/// +6919/// 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.> +6920/// +6921/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout. +6922fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> { +6923 match (x, y) { +6924 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None, +6925 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)), +6926 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)), +6927 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)), +6928 } +6929} +6930 +6931#[cfg(test)] +6932mod tests { +6933 use super::*; +6934 +6935 #[test] +6936 fn negotiate_max_idle_timeout_commutative() { +6937 let test_params = [ +6938 (None, None, None), +6939 (None, Some(VarInt(0)), None), +6940 (None, Some(VarInt(2)), Some(Duration::from_millis(2))), +6941 (Some(VarInt(0)), Some(VarInt(0)), None), +6942 ( +6943 Some(VarInt(2)), +6944 Some(VarInt(0)), +6945 Some(Duration::from_millis(2)), +6946 ), +6947 ( +6948 Some(VarInt(1)), +6949 Some(VarInt(4)), +6950 Some(Duration::from_millis(1)), +6951 ), +6952 ]; +6953 +6954 for (left, right, result) in test_params { +6955 assert_eq!(negotiate_max_idle_timeout(left, right), result); +6956 assert_eq!(negotiate_max_idle_timeout(right, left), result); +6957 } +6958 } +6959} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/paths.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/paths.rs.html index cf2b5c827..9987c1a58 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/paths.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/paths.rs.html @@ -262,8 +262,8 @@ 262 .mtu_discovery_config 263 .as_ref() 264 .filter(|_| allow_mtud) -265 .map_or( -266 MtuDiscovery::disabled(config.get_initial_mtu(), config.min_mtu), +265 .map_or_else( +266 || MtuDiscovery::disabled(config.get_initial_mtu(), config.min_mtu), 267 |mtud_config| { 268 MtuDiscovery::new( 269 config.get_initial_mtu(), diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/spaces.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/spaces.rs.html index f8b6bf212..599eea790 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/spaces.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/spaces.rs.html @@ -534,7 +534,7 @@ 534 /// If a [`frame::PathStatusAvailable`] and [`frame::PathStatusBackup`] need to be sent for a path 535 pub(super) path_status: BTreeSet<PathId>, 536 /// If a PATH_CIDS_BLOCKED frame needs to be sent for a path -537 pub(super) path_cids_blocked: Vec<PathId>, +537 pub(super) path_cids_blocked: BTreeSet<PathId>, 538 539 // Nat traversal data 540 /// Addresses to report in `ADD_ADDRESS` frames @@ -930,7 +930,7 @@ 930 /// Returns the delay since the packet with the largest packet number was received 931 pub(super) fn ack_delay(&self, now: Instant) -> Duration { 932 self.largest_packet -933 .map_or(Duration::default(), |(_, received)| now - received) +933 .map_or_else(Duration::default, |(_, received)| now - received) 934 } 935 936 /// Handle receipt of a new packet diff --git a/pr/255/docs/src/iroh_quinn_proto/crypto/rustls.rs.html b/pr/255/docs/src/iroh_quinn_proto/crypto/rustls.rs.html index 406497d9e..9672d2071 100644 --- a/pr/255/docs/src/iroh_quinn_proto/crypto/rustls.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/crypto/rustls.rs.html @@ -274,7 +274,7 @@ 274/// A QUIC-compatible TLS client configuration 275/// 276/// Quinn implicitly constructs a `QuicClientConfig` with reasonable defaults within -277/// [`ClientConfig::with_root_certificates()`][root_certs] and [`ClientConfig::with_platform_verifier()`][platform]. +277/// [`ClientConfig::with_root_certificates()`][root_certs] and [`ClientConfig::try_with_platform_verifier()`][platform]. 278/// Alternatively, `QuicClientConfig`'s [`TryFrom`] implementation can be used to wrap around a 279/// custom [`rustls::ClientConfig`], in which case care should be taken around certain points: 280/// @@ -288,7 +288,7 @@ 288/// 256 server names. 289/// 290/// [root_certs]: crate::config::ClientConfig::with_root_certificates() -291/// [platform]: crate::config::ClientConfig::with_platform_verifier() +291/// [platform]: crate::config::ClientConfig::try_with_platform_verifier() 292pub struct QuicClientConfig { 293 pub(crate) inner: Arc<rustls::ClientConfig>, 294 initial: Suite, @@ -416,7 +416,7 @@ 416} 417 418impl std::fmt::Display for NoInitialCipherSuite { -419 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 420 f.write_str(match self.specific { 421 true => "invalid cipher suite specified", 422 false => "no initial cipher suite found", diff --git a/pr/255/docs/src/iroh_quinn_proto/endpoint.rs.html b/pr/255/docs/src/iroh_quinn_proto/endpoint.rs.html index db1df6a36..34551ac4e 100644 --- a/pr/255/docs/src/iroh_quinn_proto/endpoint.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/endpoint.rs.html @@ -61,1316 +61,1311 @@ 61 /// `allow_mtud` enables path MTU detection when requested by `Connection` configuration for 62 /// better performance. This requires that outgoing packets are never fragmented, which can be 63 /// achieved via e.g. the `IPV6_DONTFRAG` socket option. -64 /// -65 /// If `rng_seed` is provided, it will be used to initialize the endpoint's rng (having priority -66 /// over the rng seed configured in [`EndpointConfig`]). Note that the `rng_seed` parameter will -67 /// be removed in a future release, so prefer setting it to `None` and configuring rng seeds -68 /// using [`EndpointConfig::rng_seed`]. -69 pub fn new( -70 config: Arc<EndpointConfig>, -71 server_config: Option<Arc<ServerConfig>>, -72 allow_mtud: bool, -73 rng_seed: Option<[u8; 32]>, -74 ) -> Self { -75 let rng_seed = rng_seed.or(config.rng_seed); -76 Self { -77 rng: rng_seed.map_or(StdRng::from_os_rng(), StdRng::from_seed), -78 index: ConnectionIndex::default(), -79 connections: Slab::new(), -80 local_cid_generator: (config.connection_id_generator_factory.as_ref())(), -81 config, -82 server_config, -83 allow_mtud, -84 last_stateless_reset: None, -85 incoming_buffers: Slab::new(), -86 all_incoming_buffers_total_bytes: 0, -87 } +64 pub fn new( +65 config: Arc<EndpointConfig>, +66 server_config: Option<Arc<ServerConfig>>, +67 allow_mtud: bool, +68 ) -> Self { +69 Self { +70 rng: config +71 .rng_seed +72 .map_or_else(StdRng::from_os_rng, StdRng::from_seed), +73 index: ConnectionIndex::default(), +74 connections: Slab::new(), +75 local_cid_generator: (config.connection_id_generator_factory.as_ref())(), +76 config, +77 server_config, +78 allow_mtud, +79 last_stateless_reset: None, +80 incoming_buffers: Slab::new(), +81 all_incoming_buffers_total_bytes: 0, +82 } +83 } +84 +85 /// Replace the server configuration, affecting new incoming connections only +86 pub fn set_server_config(&mut self, server_config: Option<Arc<ServerConfig>>) { +87 self.server_config = server_config; 88 } 89 -90 /// Replace the server configuration, affecting new incoming connections only -91 pub fn set_server_config(&mut self, server_config: Option<Arc<ServerConfig>>) { -92 self.server_config = server_config; -93 } -94 -95 /// Process `EndpointEvent`s emitted from related `Connection`s -96 /// -97 /// In turn, processing this event may return a `ConnectionEvent` for the same `Connection`. -98 pub fn handle_event( -99 &mut self, -100 ch: ConnectionHandle, -101 event: EndpointEvent, -102 ) -> Option<ConnectionEvent> { -103 use EndpointEventInner::*; -104 match event.0 { -105 NeedIdentifiers(path_id, now, n) => { -106 return Some(self.send_new_identifiers(path_id, now, ch, n)); -107 } -108 ResetToken(path_id, remote, token) => { -109 if let Some(old) = self.connections[ch] -110 .reset_token -111 .insert(path_id, (remote, token)) -112 { -113 self.index.connection_reset_tokens.remove(old.0, old.1); -114 } -115 if self.index.connection_reset_tokens.insert(remote, token, ch) { -116 warn!("duplicate reset token"); +90 /// Process `EndpointEvent`s emitted from related `Connection`s +91 /// +92 /// In turn, processing this event may return a `ConnectionEvent` for the same `Connection`. +93 pub fn handle_event( +94 &mut self, +95 ch: ConnectionHandle, +96 event: EndpointEvent, +97 ) -> Option<ConnectionEvent> { +98 use EndpointEventInner::*; +99 match event.0 { +100 NeedIdentifiers(path_id, now, n) => { +101 return Some(self.send_new_identifiers(path_id, now, ch, n)); +102 } +103 ResetToken(path_id, remote, token) => { +104 if let Some(old) = self.connections[ch] +105 .reset_token +106 .insert(path_id, (remote, token)) +107 { +108 self.index.connection_reset_tokens.remove(old.0, old.1); +109 } +110 if self.index.connection_reset_tokens.insert(remote, token, ch) { +111 warn!("duplicate reset token"); +112 } +113 } +114 RetireResetToken(path_id) => { +115 if let Some(old) = self.connections[ch].reset_token.remove(&path_id) { +116 self.index.connection_reset_tokens.remove(old.0, old.1); 117 } 118 } -119 RetireResetToken(path_id) => { -120 if let Some(old) = self.connections[ch].reset_token.remove(&path_id) { -121 self.index.connection_reset_tokens.remove(old.0, old.1); -122 } -123 } -124 RetireConnectionId(now, path_id, seq, allow_more_cids) => { -125 if let Some(cid) = self.connections[ch] -126 .loc_cids -127 .get_mut(&path_id) -128 .and_then(|pcid| pcid.cids.remove(&seq)) -129 { -130 trace!(%path_id, "local CID retired {}: {}", seq, cid); -131 self.index.retire(cid); -132 if allow_more_cids { -133 return Some(self.send_new_identifiers(path_id, now, ch, 1)); -134 } -135 } -136 } -137 Drained => { -138 if let Some(conn) = self.connections.try_remove(ch.0) { -139 self.index.remove(&conn); -140 } else { -141 // This indicates a bug in downstream code, which could cause spurious -142 // connection loss instead of this error if the CID was (re)allocated prior to -143 // the illegal call. -144 error!(id = ch.0, "unknown connection drained"); -145 } -146 } -147 } -148 None -149 } -150 -151 /// Process an incoming UDP datagram -152 pub fn handle( -153 &mut self, -154 now: Instant, -155 network_path: FourTuple, -156 ecn: Option<EcnCodepoint>, -157 data: BytesMut, -158 buf: &mut Vec<u8>, -159 ) -> Option<DatagramEvent> { -160 // Partially decode packet or short-circuit if unable -161 let datagram_len = data.len(); -162 let mut event = match PartialDecode::new( -163 data, -164 &FixedLengthConnectionIdParser::new(self.local_cid_generator.cid_len()), -165 &self.config.supported_versions, -166 self.config.grease_quic_bit, -167 ) { -168 Ok((first_decode, remaining)) => DatagramConnectionEvent { -169 now, -170 network_path, -171 path_id: PathId::ZERO, // Corrected later for existing paths -172 ecn, -173 first_decode, -174 remaining, -175 }, -176 Err(PacketDecodeError::UnsupportedVersion { -177 src_cid, -178 dst_cid, -179 version, -180 }) => { -181 if self.server_config.is_none() { -182 debug!("dropping packet with unsupported version"); -183 return None; -184 } -185 trace!("sending version negotiation"); -186 // Negotiate versions -187 Header::VersionNegotiate { -188 random: self.rng.random::<u8>() | 0x40, -189 src_cid: dst_cid, -190 dst_cid: src_cid, -191 } -192 .encode(buf); -193 // Grease with a reserved version -194 buf.write::<u32>(match version { -195 0x0a1a_2a3a => 0x0a1a_2a4a, -196 _ => 0x0a1a_2a3a, -197 }); -198 for &version in &self.config.supported_versions { -199 buf.write(version); -200 } -201 return Some(DatagramEvent::Response(Transmit { -202 destination: network_path.remote, -203 ecn: None, -204 size: buf.len(), -205 segment_size: None, -206 src_ip: network_path.local_ip, -207 })); -208 } -209 Err(e) => { -210 trace!("malformed header: {}", e); -211 return None; -212 } -213 }; -214 -215 let dst_cid = event.first_decode.dst_cid(); -216 -217 if let Some(route_to) = self.index.get(&network_path, &event.first_decode) { -218 event.path_id = match route_to { -219 RouteDatagramTo::Incoming(_) => PathId::ZERO, -220 RouteDatagramTo::Connection(_, path_id) => path_id, -221 }; -222 match route_to { -223 RouteDatagramTo::Incoming(incoming_idx) => { -224 let incoming_buffer = &mut self.incoming_buffers[incoming_idx]; -225 let config = &self.server_config.as_ref().unwrap(); -226 -227 if incoming_buffer -228 .total_bytes -229 .checked_add(datagram_len as u64) -230 .is_some_and(|n| n <= config.incoming_buffer_size) -231 && self -232 .all_incoming_buffers_total_bytes -233 .checked_add(datagram_len as u64) -234 .is_some_and(|n| n <= config.incoming_buffer_size_total) -235 { -236 incoming_buffer.datagrams.push(event); -237 incoming_buffer.total_bytes += datagram_len as u64; -238 self.all_incoming_buffers_total_bytes += datagram_len as u64; -239 } -240 -241 None -242 } -243 RouteDatagramTo::Connection(ch, _path_id) => Some(DatagramEvent::ConnectionEvent( -244 ch, -245 ConnectionEvent(ConnectionEventInner::Datagram(event)), -246 )), -247 } -248 } else if event.first_decode.initial_header().is_some() { -249 // Potentially create a new connection -250 -251 self.handle_first_packet(datagram_len, event, network_path, buf) -252 } else if event.first_decode.has_long_header() { -253 debug!( -254 "ignoring non-initial packet for unknown connection {}", -255 dst_cid -256 ); +119 RetireConnectionId(now, path_id, seq, allow_more_cids) => { +120 if let Some(cid) = self.connections[ch] +121 .loc_cids +122 .get_mut(&path_id) +123 .and_then(|pcid| pcid.cids.remove(&seq)) +124 { +125 trace!(%path_id, "local CID retired {}: {}", seq, cid); +126 self.index.retire(cid); +127 if allow_more_cids { +128 return Some(self.send_new_identifiers(path_id, now, ch, 1)); +129 } +130 } +131 } +132 Drained => { +133 if let Some(conn) = self.connections.try_remove(ch.0) { +134 self.index.remove(&conn); +135 } else { +136 // This indicates a bug in downstream code, which could cause spurious +137 // connection loss instead of this error if the CID was (re)allocated prior to +138 // the illegal call. +139 error!(id = ch.0, "unknown connection drained"); +140 } +141 } +142 } +143 None +144 } +145 +146 /// Process an incoming UDP datagram +147 pub fn handle( +148 &mut self, +149 now: Instant, +150 network_path: FourTuple, +151 ecn: Option<EcnCodepoint>, +152 data: BytesMut, +153 buf: &mut Vec<u8>, +154 ) -> Option<DatagramEvent> { +155 // Partially decode packet or short-circuit if unable +156 let datagram_len = data.len(); +157 let mut event = match PartialDecode::new( +158 data, +159 &FixedLengthConnectionIdParser::new(self.local_cid_generator.cid_len()), +160 &self.config.supported_versions, +161 self.config.grease_quic_bit, +162 ) { +163 Ok((first_decode, remaining)) => DatagramConnectionEvent { +164 now, +165 network_path, +166 path_id: PathId::ZERO, // Corrected later for existing paths +167 ecn, +168 first_decode, +169 remaining, +170 }, +171 Err(PacketDecodeError::UnsupportedVersion { +172 src_cid, +173 dst_cid, +174 version, +175 }) => { +176 if self.server_config.is_none() { +177 debug!("dropping packet with unsupported version"); +178 return None; +179 } +180 trace!("sending version negotiation"); +181 // Negotiate versions +182 Header::VersionNegotiate { +183 random: self.rng.random::<u8>() | 0x40, +184 src_cid: dst_cid, +185 dst_cid: src_cid, +186 } +187 .encode(buf); +188 // Grease with a reserved version +189 buf.write::<u32>(match version { +190 0x0a1a_2a3a => 0x0a1a_2a4a, +191 _ => 0x0a1a_2a3a, +192 }); +193 for &version in &self.config.supported_versions { +194 buf.write(version); +195 } +196 return Some(DatagramEvent::Response(Transmit { +197 destination: network_path.remote, +198 ecn: None, +199 size: buf.len(), +200 segment_size: None, +201 src_ip: network_path.local_ip, +202 })); +203 } +204 Err(e) => { +205 trace!("malformed header: {}", e); +206 return None; +207 } +208 }; +209 +210 let dst_cid = event.first_decode.dst_cid(); +211 +212 if let Some(route_to) = self.index.get(&network_path, &event.first_decode) { +213 event.path_id = match route_to { +214 RouteDatagramTo::Incoming(_) => PathId::ZERO, +215 RouteDatagramTo::Connection(_, path_id) => path_id, +216 }; +217 match route_to { +218 RouteDatagramTo::Incoming(incoming_idx) => { +219 let incoming_buffer = &mut self.incoming_buffers[incoming_idx]; +220 let config = &self.server_config.as_ref().unwrap(); +221 +222 if incoming_buffer +223 .total_bytes +224 .checked_add(datagram_len as u64) +225 .is_some_and(|n| n <= config.incoming_buffer_size) +226 && self +227 .all_incoming_buffers_total_bytes +228 .checked_add(datagram_len as u64) +229 .is_some_and(|n| n <= config.incoming_buffer_size_total) +230 { +231 incoming_buffer.datagrams.push(event); +232 incoming_buffer.total_bytes += datagram_len as u64; +233 self.all_incoming_buffers_total_bytes += datagram_len as u64; +234 } +235 +236 None +237 } +238 RouteDatagramTo::Connection(ch, _path_id) => Some(DatagramEvent::ConnectionEvent( +239 ch, +240 ConnectionEvent(ConnectionEventInner::Datagram(event)), +241 )), +242 } +243 } else if event.first_decode.initial_header().is_some() { +244 // Potentially create a new connection +245 +246 self.handle_first_packet(datagram_len, event, network_path, buf) +247 } else if event.first_decode.has_long_header() { +248 debug!( +249 "ignoring non-initial packet for unknown connection {}", +250 dst_cid +251 ); +252 None +253 } else if !event.first_decode.is_initial() +254 && self.local_cid_generator.validate(dst_cid).is_err() +255 { +256 debug!("dropping packet with invalid CID"); 257 None -258 } else if !event.first_decode.is_initial() -259 && self.local_cid_generator.validate(dst_cid).is_err() -260 { -261 debug!("dropping packet with invalid CID"); -262 None -263 } else if dst_cid.is_empty() { -264 trace!("dropping unrecognized short packet without ID"); -265 None -266 } else { -267 // If we got this far, we're receiving a seemingly valid packet for an unknown -268 // connection. Send a stateless reset if possible. -269 self.stateless_reset(now, datagram_len, network_path, dst_cid, buf) -270 .map(DatagramEvent::Response) -271 } -272 } -273 -274 /// Builds a stateless reset packet to respond with -275 fn stateless_reset( -276 &mut self, -277 now: Instant, -278 inciting_dgram_len: usize, -279 network_path: FourTuple, -280 dst_cid: ConnectionId, -281 buf: &mut Vec<u8>, -282 ) -> Option<Transmit> { -283 if self -284 .last_stateless_reset -285 .is_some_and(|last| last + self.config.min_reset_interval > now) -286 { -287 debug!("ignoring unexpected packet within minimum stateless reset interval"); -288 return None; -289 } -290 -291 /// Minimum amount of padding for the stateless reset to look like a short-header packet -292 const MIN_PADDING_LEN: usize = 5; -293 -294 // Prevent amplification attacks and reset loops by ensuring we pad to at most 1 byte -295 // smaller than the inciting packet. -296 let max_padding_len = match inciting_dgram_len.checked_sub(RESET_TOKEN_SIZE) { -297 Some(headroom) if headroom > MIN_PADDING_LEN => headroom - 1, -298 _ => { -299 debug!( -300 "ignoring unexpected {} byte packet: not larger than minimum stateless reset size", -301 inciting_dgram_len -302 ); -303 return None; -304 } -305 }; -306 -307 debug!(%dst_cid, %network_path.remote, "sending stateless reset"); -308 self.last_stateless_reset = Some(now); -309 // Resets with at least this much padding can't possibly be distinguished from real packets -310 const IDEAL_MIN_PADDING_LEN: usize = MIN_PADDING_LEN + MAX_CID_SIZE; -311 let padding_len = if max_padding_len <= IDEAL_MIN_PADDING_LEN { -312 max_padding_len -313 } else { -314 self.rng -315 .random_range(IDEAL_MIN_PADDING_LEN..max_padding_len) -316 }; -317 buf.reserve(padding_len + RESET_TOKEN_SIZE); -318 buf.resize(padding_len, 0); -319 self.rng.fill_bytes(&mut buf[0..padding_len]); -320 buf[0] = 0b0100_0000 | (buf[0] >> 2); -321 buf.extend_from_slice(&ResetToken::new(&*self.config.reset_key, dst_cid)); -322 -323 debug_assert!(buf.len() < inciting_dgram_len); -324 -325 Some(Transmit { -326 destination: network_path.remote, -327 ecn: None, -328 size: buf.len(), -329 segment_size: None, -330 src_ip: network_path.local_ip, -331 }) -332 } -333 -334 /// Initiate a connection -335 pub fn connect( -336 &mut self, -337 now: Instant, -338 config: ClientConfig, -339 remote: SocketAddr, -340 server_name: &str, -341 ) -> Result<(ConnectionHandle, Connection), ConnectError> { -342 if self.cids_exhausted() { -343 return Err(ConnectError::CidsExhausted); -344 } -345 if remote.port() == 0 || remote.ip().is_unspecified() { -346 return Err(ConnectError::InvalidRemoteAddress(remote)); -347 } -348 if !self.config.supported_versions.contains(&config.version) { -349 return Err(ConnectError::UnsupportedVersion); -350 } -351 -352 let remote_id = (config.initial_dst_cid_provider)(); -353 trace!(initial_dcid = %remote_id); -354 -355 let ch = ConnectionHandle(self.connections.vacant_key()); -356 let loc_cid = self.new_cid(ch, PathId::ZERO); -357 let params = TransportParameters::new( -358 &config.transport, -359 &self.config, -360 self.local_cid_generator.as_ref(), -361 loc_cid, -362 None, -363 &mut self.rng, -364 ); -365 let tls = config -366 .crypto -367 .start_session(config.version, server_name, &params)?; -368 -369 let conn = self.add_connection( -370 ch, -371 config.version, -372 remote_id, -373 loc_cid, -374 remote_id, -375 FourTuple { -376 remote, -377 local_ip: None, -378 }, -379 now, -380 tls, -381 config.transport, -382 SideArgs::Client { -383 token_store: config.token_store, -384 server_name: server_name.into(), -385 }, -386 &params, -387 ); -388 Ok((ch, conn)) -389 } -390 -391 /// Generates new CIDs and creates message to send to the connection state -392 fn send_new_identifiers( -393 &mut self, -394 path_id: PathId, -395 now: Instant, -396 ch: ConnectionHandle, -397 num: u64, -398 ) -> ConnectionEvent { -399 let mut ids = vec![]; -400 for _ in 0..num { -401 let id = self.new_cid(ch, path_id); -402 let cid_meta = self.connections[ch].loc_cids.entry(path_id).or_default(); -403 let sequence = cid_meta.issued; -404 cid_meta.issued += 1; -405 cid_meta.cids.insert(sequence, id); -406 ids.push(IssuedCid { -407 path_id, -408 sequence, -409 id, -410 reset_token: ResetToken::new(&*self.config.reset_key, id), -411 }); -412 } -413 ConnectionEvent(ConnectionEventInner::NewIdentifiers( -414 ids, -415 now, -416 self.local_cid_generator.cid_len(), -417 self.local_cid_generator.cid_lifetime(), -418 )) -419 } -420 -421 /// Generate a connection ID for `ch` -422 fn new_cid(&mut self, ch: ConnectionHandle, path_id: PathId) -> ConnectionId { -423 loop { -424 let cid = self.local_cid_generator.generate_cid(); -425 if cid.is_empty() { -426 // Zero-length CID; nothing to track -427 debug_assert_eq!(self.local_cid_generator.cid_len(), 0); -428 return cid; -429 } -430 if let hash_map::Entry::Vacant(e) = self.index.connection_ids.entry(cid) { -431 e.insert((ch, path_id)); -432 break cid; -433 } -434 } -435 } -436 -437 fn handle_first_packet( -438 &mut self, -439 datagram_len: usize, -440 event: DatagramConnectionEvent, -441 network_path: FourTuple, -442 buf: &mut Vec<u8>, -443 ) -> Option<DatagramEvent> { -444 let dst_cid = event.first_decode.dst_cid(); -445 let header = event.first_decode.initial_header().unwrap(); -446 -447 let Some(server_config) = &self.server_config else { -448 debug!("packet for unrecognized connection {}", dst_cid); -449 return self -450 .stateless_reset(event.now, datagram_len, network_path, dst_cid, buf) -451 .map(DatagramEvent::Response); -452 }; +258 } else if dst_cid.is_empty() { +259 trace!("dropping unrecognized short packet without ID"); +260 None +261 } else { +262 // If we got this far, we're receiving a seemingly valid packet for an unknown +263 // connection. Send a stateless reset if possible. +264 self.stateless_reset(now, datagram_len, network_path, dst_cid, buf) +265 .map(DatagramEvent::Response) +266 } +267 } +268 +269 /// Builds a stateless reset packet to respond with +270 fn stateless_reset( +271 &mut self, +272 now: Instant, +273 inciting_dgram_len: usize, +274 network_path: FourTuple, +275 dst_cid: ConnectionId, +276 buf: &mut Vec<u8>, +277 ) -> Option<Transmit> { +278 if self +279 .last_stateless_reset +280 .is_some_and(|last| last + self.config.min_reset_interval > now) +281 { +282 debug!("ignoring unexpected packet within minimum stateless reset interval"); +283 return None; +284 } +285 +286 /// Minimum amount of padding for the stateless reset to look like a short-header packet +287 const MIN_PADDING_LEN: usize = 5; +288 +289 // Prevent amplification attacks and reset loops by ensuring we pad to at most 1 byte +290 // smaller than the inciting packet. +291 let max_padding_len = match inciting_dgram_len.checked_sub(RESET_TOKEN_SIZE) { +292 Some(headroom) if headroom > MIN_PADDING_LEN => headroom - 1, +293 _ => { +294 debug!( +295 "ignoring unexpected {} byte packet: not larger than minimum stateless reset size", +296 inciting_dgram_len +297 ); +298 return None; +299 } +300 }; +301 +302 debug!(%dst_cid, %network_path.remote, "sending stateless reset"); +303 self.last_stateless_reset = Some(now); +304 // Resets with at least this much padding can't possibly be distinguished from real packets +305 const IDEAL_MIN_PADDING_LEN: usize = MIN_PADDING_LEN + MAX_CID_SIZE; +306 let padding_len = if max_padding_len <= IDEAL_MIN_PADDING_LEN { +307 max_padding_len +308 } else { +309 self.rng +310 .random_range(IDEAL_MIN_PADDING_LEN..max_padding_len) +311 }; +312 buf.reserve(padding_len + RESET_TOKEN_SIZE); +313 buf.resize(padding_len, 0); +314 self.rng.fill_bytes(&mut buf[0..padding_len]); +315 buf[0] = 0b0100_0000 | (buf[0] >> 2); +316 buf.extend_from_slice(&ResetToken::new(&*self.config.reset_key, dst_cid)); +317 +318 debug_assert!(buf.len() < inciting_dgram_len); +319 +320 Some(Transmit { +321 destination: network_path.remote, +322 ecn: None, +323 size: buf.len(), +324 segment_size: None, +325 src_ip: network_path.local_ip, +326 }) +327 } +328 +329 /// Initiate a connection +330 pub fn connect( +331 &mut self, +332 now: Instant, +333 config: ClientConfig, +334 remote: SocketAddr, +335 server_name: &str, +336 ) -> Result<(ConnectionHandle, Connection), ConnectError> { +337 if self.cids_exhausted() { +338 return Err(ConnectError::CidsExhausted); +339 } +340 if remote.port() == 0 || remote.ip().is_unspecified() { +341 return Err(ConnectError::InvalidRemoteAddress(remote)); +342 } +343 if !self.config.supported_versions.contains(&config.version) { +344 return Err(ConnectError::UnsupportedVersion); +345 } +346 +347 let remote_id = (config.initial_dst_cid_provider)(); +348 trace!(initial_dcid = %remote_id); +349 +350 let ch = ConnectionHandle(self.connections.vacant_key()); +351 let loc_cid = self.new_cid(ch, PathId::ZERO); +352 let params = TransportParameters::new( +353 &config.transport, +354 &self.config, +355 self.local_cid_generator.as_ref(), +356 loc_cid, +357 None, +358 &mut self.rng, +359 ); +360 let tls = config +361 .crypto +362 .start_session(config.version, server_name, &params)?; +363 +364 let conn = self.add_connection( +365 ch, +366 config.version, +367 remote_id, +368 loc_cid, +369 remote_id, +370 FourTuple { +371 remote, +372 local_ip: None, +373 }, +374 now, +375 tls, +376 config.transport, +377 SideArgs::Client { +378 token_store: config.token_store, +379 server_name: server_name.into(), +380 }, +381 &params, +382 ); +383 Ok((ch, conn)) +384 } +385 +386 /// Generates new CIDs and creates message to send to the connection state +387 fn send_new_identifiers( +388 &mut self, +389 path_id: PathId, +390 now: Instant, +391 ch: ConnectionHandle, +392 num: u64, +393 ) -> ConnectionEvent { +394 let mut ids = vec![]; +395 for _ in 0..num { +396 let id = self.new_cid(ch, path_id); +397 let cid_meta = self.connections[ch].loc_cids.entry(path_id).or_default(); +398 let sequence = cid_meta.issued; +399 cid_meta.issued += 1; +400 cid_meta.cids.insert(sequence, id); +401 ids.push(IssuedCid { +402 path_id, +403 sequence, +404 id, +405 reset_token: ResetToken::new(&*self.config.reset_key, id), +406 }); +407 } +408 ConnectionEvent(ConnectionEventInner::NewIdentifiers( +409 ids, +410 now, +411 self.local_cid_generator.cid_len(), +412 self.local_cid_generator.cid_lifetime(), +413 )) +414 } +415 +416 /// Generate a connection ID for `ch` +417 fn new_cid(&mut self, ch: ConnectionHandle, path_id: PathId) -> ConnectionId { +418 loop { +419 let cid = self.local_cid_generator.generate_cid(); +420 if cid.is_empty() { +421 // Zero-length CID; nothing to track +422 debug_assert_eq!(self.local_cid_generator.cid_len(), 0); +423 return cid; +424 } +425 if let hash_map::Entry::Vacant(e) = self.index.connection_ids.entry(cid) { +426 e.insert((ch, path_id)); +427 break cid; +428 } +429 } +430 } +431 +432 fn handle_first_packet( +433 &mut self, +434 datagram_len: usize, +435 event: DatagramConnectionEvent, +436 network_path: FourTuple, +437 buf: &mut Vec<u8>, +438 ) -> Option<DatagramEvent> { +439 let dst_cid = event.first_decode.dst_cid(); +440 let header = event.first_decode.initial_header().unwrap(); +441 +442 let Some(server_config) = &self.server_config else { +443 debug!("packet for unrecognized connection {}", dst_cid); +444 return self +445 .stateless_reset(event.now, datagram_len, network_path, dst_cid, buf) +446 .map(DatagramEvent::Response); +447 }; +448 +449 if datagram_len < MIN_INITIAL_SIZE as usize { +450 debug!("ignoring short initial for connection {}", dst_cid); +451 return None; +452 } 453 -454 if datagram_len < MIN_INITIAL_SIZE as usize { -455 debug!("ignoring short initial for connection {}", dst_cid); -456 return None; -457 } -458 -459 let crypto = match server_config.crypto.initial_keys(header.version, dst_cid) { -460 Ok(keys) => keys, -461 Err(UnsupportedVersion) => { -462 // This probably indicates that the user set supported_versions incorrectly in -463 // `EndpointConfig`. -464 debug!( -465 "ignoring initial packet version {:#x} unsupported by cryptographic layer", -466 header.version -467 ); -468 return None; -469 } -470 }; -471 -472 if let Err(reason) = self.early_validate_first_packet(header) { -473 return Some(DatagramEvent::Response(self.initial_close( -474 header.version, -475 network_path, -476 &crypto, -477 header.src_cid, -478 reason, -479 buf, -480 ))); -481 } -482 -483 let packet = match event.first_decode.finish(Some(&*crypto.header.remote)) { -484 Ok(packet) => packet, -485 Err(e) => { -486 trace!("unable to decode initial packet: {}", e); -487 return None; -488 } -489 }; +454 let crypto = match server_config.crypto.initial_keys(header.version, dst_cid) { +455 Ok(keys) => keys, +456 Err(UnsupportedVersion) => { +457 // This probably indicates that the user set supported_versions incorrectly in +458 // `EndpointConfig`. +459 debug!( +460 "ignoring initial packet version {:#x} unsupported by cryptographic layer", +461 header.version +462 ); +463 return None; +464 } +465 }; +466 +467 if let Err(reason) = self.early_validate_first_packet(header) { +468 return Some(DatagramEvent::Response(self.initial_close( +469 header.version, +470 network_path, +471 &crypto, +472 header.src_cid, +473 reason, +474 buf, +475 ))); +476 } +477 +478 let packet = match event.first_decode.finish(Some(&*crypto.header.remote)) { +479 Ok(packet) => packet, +480 Err(e) => { +481 trace!("unable to decode initial packet: {}", e); +482 return None; +483 } +484 }; +485 +486 if !packet.reserved_bits_valid() { +487 debug!("dropping connection attempt with invalid reserved bits"); +488 return None; +489 } 490 -491 if !packet.reserved_bits_valid() { -492 debug!("dropping connection attempt with invalid reserved bits"); -493 return None; -494 } -495 -496 let Header::Initial(header) = packet.header else { -497 panic!("non-initial packet in handle_first_packet()"); -498 }; -499 -500 let server_config = self.server_config.as_ref().unwrap().clone(); -501 -502 let token = match IncomingToken::from_header(&header, &server_config, network_path.remote) { -503 Ok(token) => token, -504 Err(InvalidRetryTokenError) => { -505 debug!("rejecting invalid retry token"); -506 return Some(DatagramEvent::Response(self.initial_close( -507 header.version, -508 network_path, -509 &crypto, -510 header.src_cid, -511 TransportError::INVALID_TOKEN(""), -512 buf, -513 ))); -514 } -515 }; -516 -517 let incoming_idx = self.incoming_buffers.insert(IncomingBuffer::default()); -518 self.index -519 .insert_initial_incoming(header.dst_cid, incoming_idx); -520 -521 Some(DatagramEvent::NewConnection(Incoming { -522 received_at: event.now, -523 network_path, -524 ecn: event.ecn, -525 packet: InitialPacket { -526 header, -527 header_data: packet.header_data, -528 payload: packet.payload, -529 }, -530 rest: event.remaining, -531 crypto, -532 token, -533 incoming_idx, -534 improper_drop_warner: IncomingImproperDropWarner, -535 })) -536 } -537 -538 /// Attempt to accept this incoming connection (an error may still occur) -539 // box err to avoid clippy::result_large_err -540 pub fn accept( -541 &mut self, -542 mut incoming: Incoming, -543 now: Instant, -544 buf: &mut Vec<u8>, -545 server_config: Option<Arc<ServerConfig>>, -546 ) -> Result<(ConnectionHandle, Connection), Box<AcceptError>> { -547 let remote_address_validated = incoming.remote_address_validated(); -548 incoming.improper_drop_warner.dismiss(); -549 let incoming_buffer = self.incoming_buffers.remove(incoming.incoming_idx); -550 self.all_incoming_buffers_total_bytes -= incoming_buffer.total_bytes; -551 -552 let packet_number = incoming.packet.header.number.expand(0); -553 let InitialHeader { -554 src_cid, -555 dst_cid, -556 version, -557 .. -558 } = incoming.packet.header; -559 let server_config = -560 server_config.unwrap_or_else(|| self.server_config.as_ref().unwrap().clone()); -561 -562 if server_config -563 .transport -564 .max_idle_timeout -565 .is_some_and(|timeout| { -566 incoming.received_at + Duration::from_millis(timeout.into()) <= now -567 }) -568 { -569 debug!("abandoning accept of stale initial"); -570 self.index.remove_initial(dst_cid); -571 return Err(Box::new(AcceptError { -572 cause: ConnectionError::TimedOut, -573 response: None, -574 })); -575 } -576 -577 if self.cids_exhausted() { -578 debug!("refusing connection"); -579 self.index.remove_initial(dst_cid); -580 return Err(Box::new(AcceptError { -581 cause: ConnectionError::CidsExhausted, -582 response: Some(self.initial_close( -583 version, -584 incoming.network_path, -585 &incoming.crypto, -586 src_cid, -587 TransportError::CONNECTION_REFUSED(""), -588 buf, -589 )), -590 })); -591 } -592 -593 if incoming -594 .crypto -595 .packet -596 .remote -597 .decrypt( -598 PathId::ZERO, -599 packet_number, -600 &incoming.packet.header_data, -601 &mut incoming.packet.payload, -602 ) -603 .is_err() -604 { -605 debug!(packet_number, "failed to authenticate initial packet"); -606 self.index.remove_initial(dst_cid); -607 return Err(Box::new(AcceptError { -608 cause: TransportError::PROTOCOL_VIOLATION("authentication failed").into(), -609 response: None, -610 })); -611 }; -612 -613 let ch = ConnectionHandle(self.connections.vacant_key()); -614 let loc_cid = self.new_cid(ch, PathId::ZERO); -615 let mut params = TransportParameters::new( -616 &server_config.transport, -617 &self.config, -618 self.local_cid_generator.as_ref(), -619 loc_cid, -620 Some(&server_config), -621 &mut self.rng, -622 ); -623 params.stateless_reset_token = Some(ResetToken::new(&*self.config.reset_key, loc_cid)); -624 params.original_dst_cid = Some(incoming.token.orig_dst_cid); -625 params.retry_src_cid = incoming.token.retry_src_cid; -626 let mut pref_addr_cid = None; -627 if server_config.has_preferred_address() { -628 let cid = self.new_cid(ch, PathId::ZERO); -629 pref_addr_cid = Some(cid); -630 params.preferred_address = Some(PreferredAddress { -631 address_v4: server_config.preferred_address_v4, -632 address_v6: server_config.preferred_address_v6, -633 connection_id: cid, -634 stateless_reset_token: ResetToken::new(&*self.config.reset_key, cid), -635 }); -636 } -637 -638 let tls = server_config.crypto.clone().start_session(version, &params); -639 let transport_config = server_config.transport.clone(); -640 let mut conn = self.add_connection( -641 ch, -642 version, -643 dst_cid, -644 loc_cid, -645 src_cid, -646 incoming.network_path, -647 incoming.received_at, -648 tls, -649 transport_config, -650 SideArgs::Server { -651 server_config, -652 pref_addr_cid, -653 path_validated: remote_address_validated, -654 }, -655 &params, -656 ); -657 self.index.insert_initial(dst_cid, ch); -658 -659 match conn.handle_first_packet( -660 incoming.received_at, -661 incoming.network_path, -662 incoming.ecn, -663 packet_number, -664 incoming.packet, -665 incoming.rest, -666 ) { -667 Ok(()) => { -668 trace!(id = ch.0, icid = %dst_cid, "new connection"); -669 -670 for event in incoming_buffer.datagrams { -671 conn.handle_event(ConnectionEvent(ConnectionEventInner::Datagram(event))) -672 } -673 -674 Ok((ch, conn)) -675 } -676 Err(e) => { -677 debug!("handshake failed: {}", e); -678 self.handle_event(ch, EndpointEvent(EndpointEventInner::Drained)); -679 let response = match e { -680 ConnectionError::TransportError(ref e) => Some(self.initial_close( -681 version, -682 incoming.network_path, -683 &incoming.crypto, -684 src_cid, -685 e.clone(), -686 buf, -687 )), -688 _ => None, -689 }; -690 Err(Box::new(AcceptError { cause: e, response })) -691 } -692 } -693 } -694 -695 /// Check if we should refuse a connection attempt regardless of the packet's contents -696 fn early_validate_first_packet( -697 &mut self, -698 header: &ProtectedInitialHeader, -699 ) -> Result<(), TransportError> { -700 let config = &self.server_config.as_ref().unwrap(); -701 if self.cids_exhausted() || self.incoming_buffers.len() >= config.max_incoming { -702 return Err(TransportError::CONNECTION_REFUSED("")); -703 } -704 -705 // RFC9000 §7.2 dictates that initial (client-chosen) destination CIDs must be at least 8 -706 // bytes. If this is a Retry packet, then the length must instead match our usual CID -707 // length. If we ever issue non-Retry address validation tokens via `NEW_TOKEN`, then we'll -708 // also need to validate CID length for those after decoding the token. -709 if header.dst_cid.len() < 8 -710 && (header.token_pos.is_empty() -711 || header.dst_cid.len() != self.local_cid_generator.cid_len()) -712 { -713 debug!( -714 "rejecting connection due to invalid DCID length {}", -715 header.dst_cid.len() -716 ); -717 return Err(TransportError::PROTOCOL_VIOLATION( -718 "invalid destination CID length", -719 )); -720 } -721 -722 Ok(()) -723 } +491 let Header::Initial(header) = packet.header else { +492 panic!("non-initial packet in handle_first_packet()"); +493 }; +494 +495 let server_config = self.server_config.as_ref().unwrap().clone(); +496 +497 let token = match IncomingToken::from_header(&header, &server_config, network_path.remote) { +498 Ok(token) => token, +499 Err(InvalidRetryTokenError) => { +500 debug!("rejecting invalid retry token"); +501 return Some(DatagramEvent::Response(self.initial_close( +502 header.version, +503 network_path, +504 &crypto, +505 header.src_cid, +506 TransportError::INVALID_TOKEN(""), +507 buf, +508 ))); +509 } +510 }; +511 +512 let incoming_idx = self.incoming_buffers.insert(IncomingBuffer::default()); +513 self.index +514 .insert_initial_incoming(header.dst_cid, incoming_idx); +515 +516 Some(DatagramEvent::NewConnection(Incoming { +517 received_at: event.now, +518 network_path, +519 ecn: event.ecn, +520 packet: InitialPacket { +521 header, +522 header_data: packet.header_data, +523 payload: packet.payload, +524 }, +525 rest: event.remaining, +526 crypto, +527 token, +528 incoming_idx, +529 improper_drop_warner: IncomingImproperDropWarner, +530 })) +531 } +532 +533 /// Attempt to accept this incoming connection (an error may still occur) +534 // box err to avoid clippy::result_large_err +535 pub fn accept( +536 &mut self, +537 mut incoming: Incoming, +538 now: Instant, +539 buf: &mut Vec<u8>, +540 server_config: Option<Arc<ServerConfig>>, +541 ) -> Result<(ConnectionHandle, Connection), Box<AcceptError>> { +542 let remote_address_validated = incoming.remote_address_validated(); +543 incoming.improper_drop_warner.dismiss(); +544 let incoming_buffer = self.incoming_buffers.remove(incoming.incoming_idx); +545 self.all_incoming_buffers_total_bytes -= incoming_buffer.total_bytes; +546 +547 let packet_number = incoming.packet.header.number.expand(0); +548 let InitialHeader { +549 src_cid, +550 dst_cid, +551 version, +552 .. +553 } = incoming.packet.header; +554 let server_config = +555 server_config.unwrap_or_else(|| self.server_config.as_ref().unwrap().clone()); +556 +557 if server_config +558 .transport +559 .max_idle_timeout +560 .is_some_and(|timeout| { +561 incoming.received_at + Duration::from_millis(timeout.into()) <= now +562 }) +563 { +564 debug!("abandoning accept of stale initial"); +565 self.index.remove_initial(dst_cid); +566 return Err(Box::new(AcceptError { +567 cause: ConnectionError::TimedOut, +568 response: None, +569 })); +570 } +571 +572 if self.cids_exhausted() { +573 debug!("refusing connection"); +574 self.index.remove_initial(dst_cid); +575 return Err(Box::new(AcceptError { +576 cause: ConnectionError::CidsExhausted, +577 response: Some(self.initial_close( +578 version, +579 incoming.network_path, +580 &incoming.crypto, +581 src_cid, +582 TransportError::CONNECTION_REFUSED(""), +583 buf, +584 )), +585 })); +586 } +587 +588 if incoming +589 .crypto +590 .packet +591 .remote +592 .decrypt( +593 PathId::ZERO, +594 packet_number, +595 &incoming.packet.header_data, +596 &mut incoming.packet.payload, +597 ) +598 .is_err() +599 { +600 debug!(packet_number, "failed to authenticate initial packet"); +601 self.index.remove_initial(dst_cid); +602 return Err(Box::new(AcceptError { +603 cause: TransportError::PROTOCOL_VIOLATION("authentication failed").into(), +604 response: None, +605 })); +606 }; +607 +608 let ch = ConnectionHandle(self.connections.vacant_key()); +609 let loc_cid = self.new_cid(ch, PathId::ZERO); +610 let mut params = TransportParameters::new( +611 &server_config.transport, +612 &self.config, +613 self.local_cid_generator.as_ref(), +614 loc_cid, +615 Some(&server_config), +616 &mut self.rng, +617 ); +618 params.stateless_reset_token = Some(ResetToken::new(&*self.config.reset_key, loc_cid)); +619 params.original_dst_cid = Some(incoming.token.orig_dst_cid); +620 params.retry_src_cid = incoming.token.retry_src_cid; +621 let mut pref_addr_cid = None; +622 if server_config.has_preferred_address() { +623 let cid = self.new_cid(ch, PathId::ZERO); +624 pref_addr_cid = Some(cid); +625 params.preferred_address = Some(PreferredAddress { +626 address_v4: server_config.preferred_address_v4, +627 address_v6: server_config.preferred_address_v6, +628 connection_id: cid, +629 stateless_reset_token: ResetToken::new(&*self.config.reset_key, cid), +630 }); +631 } +632 +633 let tls = server_config.crypto.clone().start_session(version, &params); +634 let transport_config = server_config.transport.clone(); +635 let mut conn = self.add_connection( +636 ch, +637 version, +638 dst_cid, +639 loc_cid, +640 src_cid, +641 incoming.network_path, +642 incoming.received_at, +643 tls, +644 transport_config, +645 SideArgs::Server { +646 server_config, +647 pref_addr_cid, +648 path_validated: remote_address_validated, +649 }, +650 &params, +651 ); +652 self.index.insert_initial(dst_cid, ch); +653 +654 match conn.handle_first_packet( +655 incoming.received_at, +656 incoming.network_path, +657 incoming.ecn, +658 packet_number, +659 incoming.packet, +660 incoming.rest, +661 ) { +662 Ok(()) => { +663 trace!(id = ch.0, icid = %dst_cid, "new connection"); +664 +665 for event in incoming_buffer.datagrams { +666 conn.handle_event(ConnectionEvent(ConnectionEventInner::Datagram(event))) +667 } +668 +669 Ok((ch, conn)) +670 } +671 Err(e) => { +672 debug!("handshake failed: {}", e); +673 self.handle_event(ch, EndpointEvent(EndpointEventInner::Drained)); +674 let response = match e { +675 ConnectionError::TransportError(ref e) => Some(self.initial_close( +676 version, +677 incoming.network_path, +678 &incoming.crypto, +679 src_cid, +680 e.clone(), +681 buf, +682 )), +683 _ => None, +684 }; +685 Err(Box::new(AcceptError { cause: e, response })) +686 } +687 } +688 } +689 +690 /// Check if we should refuse a connection attempt regardless of the packet's contents +691 fn early_validate_first_packet( +692 &mut self, +693 header: &ProtectedInitialHeader, +694 ) -> Result<(), TransportError> { +695 let config = &self.server_config.as_ref().unwrap(); +696 if self.cids_exhausted() || self.incoming_buffers.len() >= config.max_incoming { +697 return Err(TransportError::CONNECTION_REFUSED("")); +698 } +699 +700 // RFC9000 §7.2 dictates that initial (client-chosen) destination CIDs must be at least 8 +701 // bytes. If this is a Retry packet, then the length must instead match our usual CID +702 // length. If we ever issue non-Retry address validation tokens via `NEW_TOKEN`, then we'll +703 // also need to validate CID length for those after decoding the token. +704 if header.dst_cid.len() < 8 +705 && (header.token_pos.is_empty() +706 || header.dst_cid.len() != self.local_cid_generator.cid_len()) +707 { +708 debug!( +709 "rejecting connection due to invalid DCID length {}", +710 header.dst_cid.len() +711 ); +712 return Err(TransportError::PROTOCOL_VIOLATION( +713 "invalid destination CID length", +714 )); +715 } +716 +717 Ok(()) +718 } +719 +720 /// Reject this incoming connection attempt +721 pub fn refuse(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Transmit { +722 self.clean_up_incoming(&incoming); +723 incoming.improper_drop_warner.dismiss(); 724 -725 /// Reject this incoming connection attempt -726 pub fn refuse(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Transmit { -727 self.clean_up_incoming(&incoming); -728 incoming.improper_drop_warner.dismiss(); -729 -730 self.initial_close( -731 incoming.packet.header.version, -732 incoming.network_path, -733 &incoming.crypto, -734 incoming.packet.header.src_cid, -735 TransportError::CONNECTION_REFUSED(""), -736 buf, -737 ) -738 } -739 -740 /// Respond with a retry packet, requiring the client to retry with address validation -741 /// -742 /// Errors if `incoming.may_retry()` is false. -743 pub fn retry(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Result<Transmit, RetryError> { -744 if !incoming.may_retry() { -745 return Err(RetryError(Box::new(incoming))); -746 } +725 self.initial_close( +726 incoming.packet.header.version, +727 incoming.network_path, +728 &incoming.crypto, +729 incoming.packet.header.src_cid, +730 TransportError::CONNECTION_REFUSED(""), +731 buf, +732 ) +733 } +734 +735 /// Respond with a retry packet, requiring the client to retry with address validation +736 /// +737 /// Errors if `incoming.may_retry()` is false. +738 pub fn retry(&mut self, incoming: Incoming, buf: &mut Vec<u8>) -> Result<Transmit, RetryError> { +739 if !incoming.may_retry() { +740 return Err(RetryError(Box::new(incoming))); +741 } +742 +743 self.clean_up_incoming(&incoming); +744 incoming.improper_drop_warner.dismiss(); +745 +746 let server_config = self.server_config.as_ref().unwrap(); 747 -748 self.clean_up_incoming(&incoming); -749 incoming.improper_drop_warner.dismiss(); -750 -751 let server_config = self.server_config.as_ref().unwrap(); -752 -753 // First Initial -754 // The peer will use this as the DCID of its following Initials. Initial DCIDs are -755 // looked up separately from Handshake/Data DCIDs, so there is no risk of collision -756 // with established connections. In the unlikely event that a collision occurs -757 // between two connections in the initial phase, both will fail fast and may be -758 // retried by the application layer. -759 let loc_cid = self.local_cid_generator.generate_cid(); -760 -761 let payload = TokenPayload::Retry { -762 address: incoming.network_path.remote, -763 orig_dst_cid: incoming.packet.header.dst_cid, -764 issued: server_config.time_source.now(), -765 }; -766 let token = Token::new(payload, &mut self.rng).encode(&*server_config.token_key); -767 -768 let header = Header::Retry { -769 src_cid: loc_cid, -770 dst_cid: incoming.packet.header.src_cid, -771 version: incoming.packet.header.version, -772 }; -773 -774 let encode = header.encode(buf); -775 buf.put_slice(&token); -776 buf.extend_from_slice(&server_config.crypto.retry_tag( -777 incoming.packet.header.version, -778 incoming.packet.header.dst_cid, -779 buf, -780 )); -781 encode.finish(buf, &*incoming.crypto.header.local, None); -782 -783 Ok(Transmit { -784 destination: incoming.network_path.remote, -785 ecn: None, -786 size: buf.len(), -787 segment_size: None, -788 src_ip: incoming.network_path.local_ip, -789 }) -790 } -791 -792 /// Ignore this incoming connection attempt, not sending any packet in response -793 /// -794 /// Doing this actively, rather than merely dropping the [`Incoming`], is necessary to prevent -795 /// memory leaks due to state within [`Endpoint`] tracking the incoming connection. -796 pub fn ignore(&mut self, incoming: Incoming) { -797 self.clean_up_incoming(&incoming); -798 incoming.improper_drop_warner.dismiss(); -799 } -800 -801 /// Clean up endpoint data structures associated with an `Incoming`. -802 fn clean_up_incoming(&mut self, incoming: &Incoming) { -803 self.index.remove_initial(incoming.packet.header.dst_cid); -804 let incoming_buffer = self.incoming_buffers.remove(incoming.incoming_idx); -805 self.all_incoming_buffers_total_bytes -= incoming_buffer.total_bytes; -806 } -807 -808 fn add_connection( -809 &mut self, -810 ch: ConnectionHandle, -811 version: u32, -812 init_cid: ConnectionId, -813 loc_cid: ConnectionId, -814 rem_cid: ConnectionId, -815 network_path: FourTuple, -816 now: Instant, -817 tls: Box<dyn crypto::Session>, -818 transport_config: Arc<TransportConfig>, -819 side_args: SideArgs, -820 // Only used for qlog. -821 params: &TransportParameters, -822 ) -> Connection { -823 let mut rng_seed = [0; 32]; -824 self.rng.fill_bytes(&mut rng_seed); -825 let side = side_args.side(); -826 let pref_addr_cid = side_args.pref_addr_cid(); -827 -828 let qlog = -829 transport_config.create_qlog_sink(side_args.side(), network_path.remote, init_cid, now); -830 -831 qlog.emit_connection_started( -832 now, -833 loc_cid, -834 rem_cid, -835 network_path.remote, -836 network_path.local_ip, -837 params, -838 ); -839 -840 let conn = Connection::new( -841 self.config.clone(), -842 transport_config, -843 init_cid, -844 loc_cid, -845 rem_cid, -846 network_path, -847 tls, -848 self.local_cid_generator.as_ref(), -849 now, -850 version, -851 self.allow_mtud, -852 rng_seed, -853 side_args, -854 qlog, -855 ); -856 -857 let mut path_cids = PathLocalCids::default(); -858 path_cids.cids.insert(path_cids.issued, loc_cid); -859 path_cids.issued += 1; -860 -861 if let Some(cid) = pref_addr_cid { -862 debug_assert_eq!(path_cids.issued, 1, "preferred address cid seq must be 1"); -863 path_cids.cids.insert(path_cids.issued, cid); -864 path_cids.issued += 1; -865 } -866 -867 let id = self.connections.insert(ConnectionMeta { -868 init_cid, -869 loc_cids: FxHashMap::from_iter([(PathId::ZERO, path_cids)]), -870 network_path, -871 side, -872 reset_token: Default::default(), -873 }); -874 debug_assert_eq!(id, ch.0, "connection handle allocation out of sync"); +748 // First Initial +749 // The peer will use this as the DCID of its following Initials. Initial DCIDs are +750 // looked up separately from Handshake/Data DCIDs, so there is no risk of collision +751 // with established connections. In the unlikely event that a collision occurs +752 // between two connections in the initial phase, both will fail fast and may be +753 // retried by the application layer. +754 let loc_cid = self.local_cid_generator.generate_cid(); +755 +756 let payload = TokenPayload::Retry { +757 address: incoming.network_path.remote, +758 orig_dst_cid: incoming.packet.header.dst_cid, +759 issued: server_config.time_source.now(), +760 }; +761 let token = Token::new(payload, &mut self.rng).encode(&*server_config.token_key); +762 +763 let header = Header::Retry { +764 src_cid: loc_cid, +765 dst_cid: incoming.packet.header.src_cid, +766 version: incoming.packet.header.version, +767 }; +768 +769 let encode = header.encode(buf); +770 buf.put_slice(&token); +771 buf.extend_from_slice(&server_config.crypto.retry_tag( +772 incoming.packet.header.version, +773 incoming.packet.header.dst_cid, +774 buf, +775 )); +776 encode.finish(buf, &*incoming.crypto.header.local, None); +777 +778 Ok(Transmit { +779 destination: incoming.network_path.remote, +780 ecn: None, +781 size: buf.len(), +782 segment_size: None, +783 src_ip: incoming.network_path.local_ip, +784 }) +785 } +786 +787 /// Ignore this incoming connection attempt, not sending any packet in response +788 /// +789 /// Doing this actively, rather than merely dropping the [`Incoming`], is necessary to prevent +790 /// memory leaks due to state within [`Endpoint`] tracking the incoming connection. +791 pub fn ignore(&mut self, incoming: Incoming) { +792 self.clean_up_incoming(&incoming); +793 incoming.improper_drop_warner.dismiss(); +794 } +795 +796 /// Clean up endpoint data structures associated with an `Incoming`. +797 fn clean_up_incoming(&mut self, incoming: &Incoming) { +798 self.index.remove_initial(incoming.packet.header.dst_cid); +799 let incoming_buffer = self.incoming_buffers.remove(incoming.incoming_idx); +800 self.all_incoming_buffers_total_bytes -= incoming_buffer.total_bytes; +801 } +802 +803 fn add_connection( +804 &mut self, +805 ch: ConnectionHandle, +806 version: u32, +807 init_cid: ConnectionId, +808 loc_cid: ConnectionId, +809 rem_cid: ConnectionId, +810 network_path: FourTuple, +811 now: Instant, +812 tls: Box<dyn crypto::Session>, +813 transport_config: Arc<TransportConfig>, +814 side_args: SideArgs, +815 // Only used for qlog. +816 params: &TransportParameters, +817 ) -> Connection { +818 let mut rng_seed = [0; 32]; +819 self.rng.fill_bytes(&mut rng_seed); +820 let side = side_args.side(); +821 let pref_addr_cid = side_args.pref_addr_cid(); +822 +823 let qlog = +824 transport_config.create_qlog_sink(side_args.side(), network_path.remote, init_cid, now); +825 +826 qlog.emit_connection_started( +827 now, +828 loc_cid, +829 rem_cid, +830 network_path.remote, +831 network_path.local_ip, +832 params, +833 ); +834 +835 let conn = Connection::new( +836 self.config.clone(), +837 transport_config, +838 init_cid, +839 loc_cid, +840 rem_cid, +841 network_path, +842 tls, +843 self.local_cid_generator.as_ref(), +844 now, +845 version, +846 self.allow_mtud, +847 rng_seed, +848 side_args, +849 qlog, +850 ); +851 +852 let mut path_cids = PathLocalCids::default(); +853 path_cids.cids.insert(path_cids.issued, loc_cid); +854 path_cids.issued += 1; +855 +856 if let Some(cid) = pref_addr_cid { +857 debug_assert_eq!(path_cids.issued, 1, "preferred address cid seq must be 1"); +858 path_cids.cids.insert(path_cids.issued, cid); +859 path_cids.issued += 1; +860 } +861 +862 let id = self.connections.insert(ConnectionMeta { +863 init_cid, +864 loc_cids: FxHashMap::from_iter([(PathId::ZERO, path_cids)]), +865 network_path, +866 side, +867 reset_token: Default::default(), +868 }); +869 debug_assert_eq!(id, ch.0, "connection handle allocation out of sync"); +870 +871 self.index.insert_conn(network_path, loc_cid, ch, side); +872 +873 conn +874 } 875 -876 self.index.insert_conn(network_path, loc_cid, ch, side); -877 -878 conn -879 } -880 -881 fn initial_close( -882 &mut self, -883 version: u32, -884 network_path: FourTuple, -885 crypto: &Keys, -886 remote_id: ConnectionId, -887 reason: TransportError, -888 buf: &mut Vec<u8>, -889 ) -> Transmit { -890 // We don't need to worry about CID collisions in initial closes because the peer -891 // shouldn't respond, and if it does, and the CID collides, we'll just drop the -892 // unexpected response. -893 let local_id = self.local_cid_generator.generate_cid(); -894 let number = PacketNumber::U8(0); -895 let header = Header::Initial(InitialHeader { -896 dst_cid: remote_id, -897 src_cid: local_id, -898 number, -899 token: Bytes::new(), -900 version, -901 }); -902 -903 let partial_encode = header.encode(buf); -904 let max_len = -905 INITIAL_MTU as usize - partial_encode.header_len - crypto.packet.local.tag_len(); -906 frame::Close::from(reason).encoder(max_len).encode(buf); -907 buf.resize(buf.len() + crypto.packet.local.tag_len(), 0); -908 partial_encode.finish( -909 buf, -910 &*crypto.header.local, -911 Some((0, Default::default(), &*crypto.packet.local)), -912 ); -913 Transmit { -914 destination: network_path.remote, -915 ecn: None, -916 size: buf.len(), -917 segment_size: None, -918 src_ip: network_path.local_ip, -919 } +876 fn initial_close( +877 &mut self, +878 version: u32, +879 network_path: FourTuple, +880 crypto: &Keys, +881 remote_id: ConnectionId, +882 reason: TransportError, +883 buf: &mut Vec<u8>, +884 ) -> Transmit { +885 // We don't need to worry about CID collisions in initial closes because the peer +886 // shouldn't respond, and if it does, and the CID collides, we'll just drop the +887 // unexpected response. +888 let local_id = self.local_cid_generator.generate_cid(); +889 let number = PacketNumber::U8(0); +890 let header = Header::Initial(InitialHeader { +891 dst_cid: remote_id, +892 src_cid: local_id, +893 number, +894 token: Bytes::new(), +895 version, +896 }); +897 +898 let partial_encode = header.encode(buf); +899 let max_len = +900 INITIAL_MTU as usize - partial_encode.header_len - crypto.packet.local.tag_len(); +901 frame::Close::from(reason).encoder(max_len).encode(buf); +902 buf.resize(buf.len() + crypto.packet.local.tag_len(), 0); +903 partial_encode.finish( +904 buf, +905 &*crypto.header.local, +906 Some((0, Default::default(), &*crypto.packet.local)), +907 ); +908 Transmit { +909 destination: network_path.remote, +910 ecn: None, +911 size: buf.len(), +912 segment_size: None, +913 src_ip: network_path.local_ip, +914 } +915 } +916 +917 /// Access the configuration used by this endpoint +918 pub fn config(&self) -> &EndpointConfig { +919 &self.config 920 } 921 -922 /// Access the configuration used by this endpoint -923 pub fn config(&self) -> &EndpointConfig { -924 &self.config +922 /// Number of connections that are currently open +923 pub fn open_connections(&self) -> usize { +924 self.connections.len() 925 } 926 -927 /// Number of connections that are currently open -928 pub fn open_connections(&self) -> usize { -929 self.connections.len() -930 } -931 -932 /// Counter for the number of bytes currently used -933 /// in the buffers for Initial and 0-RTT messages for pending incoming connections -934 pub fn incoming_buffer_bytes(&self) -> u64 { -935 self.all_incoming_buffers_total_bytes -936 } -937 -938 #[cfg(test)] -939 pub(crate) fn known_connections(&self) -> usize { -940 let x = self.connections.len(); -941 debug_assert_eq!(x, self.index.connection_ids_initial.len()); -942 // Not all connections have known reset tokens -943 debug_assert!(x >= self.index.connection_reset_tokens.0.len()); -944 // Not all connections have unique remotes, and 0-length CIDs might not be in use. -945 debug_assert!(x >= self.index.incoming_connection_remotes.len()); -946 debug_assert!(x >= self.index.outgoing_connection_remotes.len()); -947 x +927 /// Counter for the number of bytes currently used +928 /// in the buffers for Initial and 0-RTT messages for pending incoming connections +929 pub fn incoming_buffer_bytes(&self) -> u64 { +930 self.all_incoming_buffers_total_bytes +931 } +932 +933 #[cfg(test)] +934 pub(crate) fn known_connections(&self) -> usize { +935 let x = self.connections.len(); +936 debug_assert_eq!(x, self.index.connection_ids_initial.len()); +937 // Not all connections have known reset tokens +938 debug_assert!(x >= self.index.connection_reset_tokens.0.len()); +939 // Not all connections have unique remotes, and 0-length CIDs might not be in use. +940 debug_assert!(x >= self.index.incoming_connection_remotes.len()); +941 debug_assert!(x >= self.index.outgoing_connection_remotes.len()); +942 x +943 } +944 +945 #[cfg(test)] +946 pub(crate) fn known_cids(&self) -> usize { +947 self.index.connection_ids.len() 948 } 949 -950 #[cfg(test)] -951 pub(crate) fn known_cids(&self) -> usize { -952 self.index.connection_ids.len() -953 } -954 -955 /// Whether we've used up 3/4 of the available CID space -956 /// -957 /// We leave some space unused so that `new_cid` can be relied upon to finish quickly. We don't -958 /// bother to check when CID longer than 4 bytes are used because 2^40 connections is a lot. -959 fn cids_exhausted(&self) -> bool { -960 self.local_cid_generator.cid_len() <= 4 -961 && self.local_cid_generator.cid_len() != 0 -962 && (2usize.pow(self.local_cid_generator.cid_len() as u32 * 8) -963 - self.index.connection_ids.len()) -964 < 2usize.pow(self.local_cid_generator.cid_len() as u32 * 8 - 2) -965 } -966} -967 -968impl fmt::Debug for Endpoint { -969 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { -970 fmt.debug_struct("Endpoint") -971 .field("rng", &self.rng) -972 .field("index", &self.index) -973 .field("connections", &self.connections) -974 .field("config", &self.config) -975 .field("server_config", &self.server_config) -976 // incoming_buffers too large -977 .field("incoming_buffers.len", &self.incoming_buffers.len()) -978 .field( -979 "all_incoming_buffers_total_bytes", -980 &self.all_incoming_buffers_total_bytes, -981 ) -982 .finish() -983 } -984} -985 -986/// Buffered Initial and 0-RTT messages for a pending incoming connection -987#[derive(Default)] -988struct IncomingBuffer { -989 datagrams: Vec<DatagramConnectionEvent>, -990 total_bytes: u64, -991} -992 -993/// Part of protocol state incoming datagrams can be routed to -994#[derive(Copy, Clone, Debug)] -995enum RouteDatagramTo { -996 Incoming(usize), -997 Connection(ConnectionHandle, PathId), -998} -999 -1000/// Maps packets to existing connections -1001#[derive(Default, Debug)] -1002struct ConnectionIndex { -1003 /// Identifies connections based on the initial DCID the peer utilized -1004 /// -1005 /// Uses a standard `HashMap` to protect against hash collision attacks. -1006 /// -1007 /// Used by the server, not the client. -1008 connection_ids_initial: HashMap<ConnectionId, RouteDatagramTo>, -1009 /// Identifies connections based on locally created CIDs -1010 /// -1011 /// Uses a cheaper hash function since keys are locally created -1012 connection_ids: FxHashMap<ConnectionId, (ConnectionHandle, PathId)>, -1013 /// Identifies incoming connections with zero-length CIDs -1014 /// -1015 /// Uses a standard `HashMap` to protect against hash collision attacks. -1016 incoming_connection_remotes: HashMap<FourTuple, ConnectionHandle>, -1017 /// Identifies outgoing connections with zero-length CIDs +950 /// Whether we've used up 3/4 of the available CID space +951 /// +952 /// We leave some space unused so that `new_cid` can be relied upon to finish quickly. We don't +953 /// bother to check when CID longer than 4 bytes are used because 2^40 connections is a lot. +954 fn cids_exhausted(&self) -> bool { +955 self.local_cid_generator.cid_len() <= 4 +956 && self.local_cid_generator.cid_len() != 0 +957 && (2usize.pow(self.local_cid_generator.cid_len() as u32 * 8) +958 - self.index.connection_ids.len()) +959 < 2usize.pow(self.local_cid_generator.cid_len() as u32 * 8 - 2) +960 } +961} +962 +963impl fmt::Debug for Endpoint { +964 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +965 fmt.debug_struct("Endpoint") +966 .field("rng", &self.rng) +967 .field("index", &self.index) +968 .field("connections", &self.connections) +969 .field("config", &self.config) +970 .field("server_config", &self.server_config) +971 // incoming_buffers too large +972 .field("incoming_buffers.len", &self.incoming_buffers.len()) +973 .field( +974 "all_incoming_buffers_total_bytes", +975 &self.all_incoming_buffers_total_bytes, +976 ) +977 .finish() +978 } +979} +980 +981/// Buffered Initial and 0-RTT messages for a pending incoming connection +982#[derive(Default)] +983struct IncomingBuffer { +984 datagrams: Vec<DatagramConnectionEvent>, +985 total_bytes: u64, +986} +987 +988/// Part of protocol state incoming datagrams can be routed to +989#[derive(Copy, Clone, Debug)] +990enum RouteDatagramTo { +991 Incoming(usize), +992 Connection(ConnectionHandle, PathId), +993} +994 +995/// Maps packets to existing connections +996#[derive(Default, Debug)] +997struct ConnectionIndex { +998 /// Identifies connections based on the initial DCID the peer utilized +999 /// +1000 /// Uses a standard `HashMap` to protect against hash collision attacks. +1001 /// +1002 /// Used by the server, not the client. +1003 connection_ids_initial: HashMap<ConnectionId, RouteDatagramTo>, +1004 /// Identifies connections based on locally created CIDs +1005 /// +1006 /// Uses a cheaper hash function since keys are locally created +1007 connection_ids: FxHashMap<ConnectionId, (ConnectionHandle, PathId)>, +1008 /// Identifies incoming connections with zero-length CIDs +1009 /// +1010 /// Uses a standard `HashMap` to protect against hash collision attacks. +1011 incoming_connection_remotes: HashMap<FourTuple, ConnectionHandle>, +1012 /// Identifies outgoing connections with zero-length CIDs +1013 /// +1014 /// We don't yet support explicit source addresses for client connections, and zero-length CIDs +1015 /// require a unique 4-tuple, so at most one client connection with zero-length local CIDs +1016 /// may be established per remote. We must omit the local address from the key because we don't +1017 /// necessarily know what address we're sending from, and hence receiving at. 1018 /// -1019 /// We don't yet support explicit source addresses for client connections, and zero-length CIDs -1020 /// require a unique 4-tuple, so at most one client connection with zero-length local CIDs -1021 /// may be established per remote. We must omit the local address from the key because we don't -1022 /// necessarily know what address we're sending from, and hence receiving at. +1019 /// Uses a standard `HashMap` to protect against hash collision attacks. +1020 // TODO(matheus23): It's possible this could be changed now that we track the full 4-tuple on the client side, too. +1021 outgoing_connection_remotes: HashMap<SocketAddr, ConnectionHandle>, +1022 /// Reset tokens provided by the peer for the CID each connection is currently sending to 1023 /// -1024 /// Uses a standard `HashMap` to protect against hash collision attacks. -1025 // TODO(matheus23): It's possible this could be changed now that we track the full 4-tuple on the client side, too. -1026 outgoing_connection_remotes: HashMap<SocketAddr, ConnectionHandle>, -1027 /// Reset tokens provided by the peer for the CID each connection is currently sending to -1028 /// -1029 /// Incoming stateless resets do not have correct CIDs, so we need this to identify the correct -1030 /// recipient, if any. -1031 connection_reset_tokens: ResetTokenTable, -1032} -1033 -1034impl ConnectionIndex { -1035 /// Associate an incoming connection with its initial destination CID -1036 fn insert_initial_incoming(&mut self, dst_cid: ConnectionId, incoming_key: usize) { -1037 if dst_cid.is_empty() { -1038 return; -1039 } -1040 self.connection_ids_initial -1041 .insert(dst_cid, RouteDatagramTo::Incoming(incoming_key)); -1042 } -1043 -1044 /// Remove an association with an initial destination CID -1045 fn remove_initial(&mut self, dst_cid: ConnectionId) { -1046 if dst_cid.is_empty() { -1047 return; -1048 } -1049 let removed = self.connection_ids_initial.remove(&dst_cid); -1050 debug_assert!(removed.is_some()); -1051 } -1052 -1053 /// Associate a connection with its initial destination CID -1054 fn insert_initial(&mut self, dst_cid: ConnectionId, connection: ConnectionHandle) { -1055 if dst_cid.is_empty() { -1056 return; -1057 } -1058 self.connection_ids_initial.insert( -1059 dst_cid, -1060 RouteDatagramTo::Connection(connection, PathId::ZERO), -1061 ); -1062 } -1063 -1064 /// Associate a connection with its first locally-chosen destination CID if used, or otherwise -1065 /// its current 4-tuple -1066 fn insert_conn( -1067 &mut self, -1068 network_path: FourTuple, -1069 dst_cid: ConnectionId, -1070 connection: ConnectionHandle, -1071 side: Side, -1072 ) { -1073 match dst_cid.len() { -1074 0 => match side { -1075 Side::Server => { -1076 self.incoming_connection_remotes -1077 .insert(network_path, connection); -1078 } -1079 Side::Client => { -1080 self.outgoing_connection_remotes -1081 .insert(network_path.remote, connection); -1082 } -1083 }, -1084 _ => { -1085 self.connection_ids -1086 .insert(dst_cid, (connection, PathId::ZERO)); -1087 } -1088 } +1024 /// Incoming stateless resets do not have correct CIDs, so we need this to identify the correct +1025 /// recipient, if any. +1026 connection_reset_tokens: ResetTokenTable, +1027} +1028 +1029impl ConnectionIndex { +1030 /// Associate an incoming connection with its initial destination CID +1031 fn insert_initial_incoming(&mut self, dst_cid: ConnectionId, incoming_key: usize) { +1032 if dst_cid.is_empty() { +1033 return; +1034 } +1035 self.connection_ids_initial +1036 .insert(dst_cid, RouteDatagramTo::Incoming(incoming_key)); +1037 } +1038 +1039 /// Remove an association with an initial destination CID +1040 fn remove_initial(&mut self, dst_cid: ConnectionId) { +1041 if dst_cid.is_empty() { +1042 return; +1043 } +1044 let removed = self.connection_ids_initial.remove(&dst_cid); +1045 debug_assert!(removed.is_some()); +1046 } +1047 +1048 /// Associate a connection with its initial destination CID +1049 fn insert_initial(&mut self, dst_cid: ConnectionId, connection: ConnectionHandle) { +1050 if dst_cid.is_empty() { +1051 return; +1052 } +1053 self.connection_ids_initial.insert( +1054 dst_cid, +1055 RouteDatagramTo::Connection(connection, PathId::ZERO), +1056 ); +1057 } +1058 +1059 /// Associate a connection with its first locally-chosen destination CID if used, or otherwise +1060 /// its current 4-tuple +1061 fn insert_conn( +1062 &mut self, +1063 network_path: FourTuple, +1064 dst_cid: ConnectionId, +1065 connection: ConnectionHandle, +1066 side: Side, +1067 ) { +1068 match dst_cid.len() { +1069 0 => match side { +1070 Side::Server => { +1071 self.incoming_connection_remotes +1072 .insert(network_path, connection); +1073 } +1074 Side::Client => { +1075 self.outgoing_connection_remotes +1076 .insert(network_path.remote, connection); +1077 } +1078 }, +1079 _ => { +1080 self.connection_ids +1081 .insert(dst_cid, (connection, PathId::ZERO)); +1082 } +1083 } +1084 } +1085 +1086 /// Discard a connection ID +1087 fn retire(&mut self, dst_cid: ConnectionId) { +1088 self.connection_ids.remove(&dst_cid); 1089 } 1090 -1091 /// Discard a connection ID -1092 fn retire(&mut self, dst_cid: ConnectionId) { -1093 self.connection_ids.remove(&dst_cid); -1094 } -1095 -1096 /// Remove all references to a connection -1097 fn remove(&mut self, conn: &ConnectionMeta) { -1098 if conn.side.is_server() { -1099 self.remove_initial(conn.init_cid); -1100 } -1101 for cid in conn.loc_cids.values().flat_map(|pcids| pcids.cids.values()) { -1102 self.connection_ids.remove(cid); -1103 } -1104 self.incoming_connection_remotes.remove(&conn.network_path); -1105 self.outgoing_connection_remotes -1106 .remove(&conn.network_path.remote); -1107 for (remote, token) in conn.reset_token.values() { -1108 self.connection_reset_tokens.remove(*remote, *token); -1109 } -1110 } -1111 -1112 /// Find the existing connection that `datagram` should be routed to, if any -1113 fn get(&self, network_path: &FourTuple, datagram: &PartialDecode) -> Option<RouteDatagramTo> { -1114 if !datagram.dst_cid().is_empty() { -1115 if let Some(&(ch, path_id)) = self.connection_ids.get(&datagram.dst_cid()) { -1116 return Some(RouteDatagramTo::Connection(ch, path_id)); +1091 /// Remove all references to a connection +1092 fn remove(&mut self, conn: &ConnectionMeta) { +1093 if conn.side.is_server() { +1094 self.remove_initial(conn.init_cid); +1095 } +1096 for cid in conn.loc_cids.values().flat_map(|pcids| pcids.cids.values()) { +1097 self.connection_ids.remove(cid); +1098 } +1099 self.incoming_connection_remotes.remove(&conn.network_path); +1100 self.outgoing_connection_remotes +1101 .remove(&conn.network_path.remote); +1102 for (remote, token) in conn.reset_token.values() { +1103 self.connection_reset_tokens.remove(*remote, *token); +1104 } +1105 } +1106 +1107 /// Find the existing connection that `datagram` should be routed to, if any +1108 fn get(&self, network_path: &FourTuple, datagram: &PartialDecode) -> Option<RouteDatagramTo> { +1109 if !datagram.dst_cid().is_empty() { +1110 if let Some(&(ch, path_id)) = self.connection_ids.get(&datagram.dst_cid()) { +1111 return Some(RouteDatagramTo::Connection(ch, path_id)); +1112 } +1113 } +1114 if datagram.is_initial() || datagram.is_0rtt() { +1115 if let Some(&ch) = self.connection_ids_initial.get(&datagram.dst_cid()) { +1116 return Some(ch); 1117 } 1118 } -1119 if datagram.is_initial() || datagram.is_0rtt() { -1120 if let Some(&ch) = self.connection_ids_initial.get(&datagram.dst_cid()) { -1121 return Some(ch); -1122 } -1123 } -1124 if datagram.dst_cid().is_empty() { -1125 if let Some(&ch) = self.incoming_connection_remotes.get(network_path) { -1126 // Never multipath because QUIC-MULTIPATH 1.1 mandates the use of non-zero -1127 // length CIDs. So this is always PathId::ZERO. -1128 return Some(RouteDatagramTo::Connection(ch, PathId::ZERO)); -1129 } -1130 if let Some(&ch) = self.outgoing_connection_remotes.get(&network_path.remote) { -1131 // Like above, QUIC-MULTIPATH 1.1 mandates the use of non-zero length CIDs. -1132 return Some(RouteDatagramTo::Connection(ch, PathId::ZERO)); -1133 } -1134 } -1135 let data = datagram.data(); -1136 if data.len() < RESET_TOKEN_SIZE { -1137 return None; -1138 } -1139 // For stateless resets the PathId is meaningless since it closes the entire -1140 // connection regardless of path. So use PathId::ZERO. -1141 self.connection_reset_tokens -1142 .get(network_path.remote, &data[data.len() - RESET_TOKEN_SIZE..]) -1143 .cloned() -1144 .map(|ch| RouteDatagramTo::Connection(ch, PathId::ZERO)) -1145 } -1146} -1147 -1148#[derive(Debug)] -1149pub(crate) struct ConnectionMeta { -1150 init_cid: ConnectionId, -1151 /// Locally issues CIDs for each path -1152 loc_cids: FxHashMap<PathId, PathLocalCids>, -1153 /// Remote/local addresses the connection began with -1154 /// -1155 /// Only needed to support connections with zero-length CIDs, which cannot migrate, so we don't -1156 /// bother keeping it up to date. -1157 network_path: FourTuple, -1158 side: Side, -1159 /// Reset tokens provided by the peer for CIDs we're currently sending to -1160 /// -1161 /// Since each reset token is for a CID, it is also for a fixed remote address which is -1162 /// also stored. This allows us to look up which reset tokens we might expect from a -1163 /// given remote address, see [`ResetTokenTable`]. -1164 /// -1165 /// Each path has its own active CID. We use the [`PathId`] as a unique index, allowing -1166 /// us to retire the reset token when a path is abandoned. -1167 // TODO(matheus23): Should be migrated to make reset tokens per 4-tuple instead of per remote addr -1168 reset_token: FxHashMap<PathId, (SocketAddr, ResetToken)>, -1169} -1170 -1171/// Local connection IDs for a single path -1172#[derive(Debug, Default)] -1173struct PathLocalCids { -1174 /// Number of connection IDs that have been issued in (PATH_)NEW_CONNECTION_ID frames -1175 /// -1176 /// Another way of saying this is that this is the next sequence number to be issued. -1177 issued: u64, -1178 /// Issues CIDs indexed by their sequence number. -1179 cids: FxHashMap<u64, ConnectionId>, -1180} -1181 -1182/// Internal identifier for a `Connection` currently associated with an endpoint -1183#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] -1184pub struct ConnectionHandle(pub usize); -1185 -1186impl From<ConnectionHandle> for usize { -1187 fn from(x: ConnectionHandle) -> Self { -1188 x.0 -1189 } -1190} -1191 -1192impl Index<ConnectionHandle> for Slab<ConnectionMeta> { -1193 type Output = ConnectionMeta; -1194 fn index(&self, ch: ConnectionHandle) -> &ConnectionMeta { -1195 &self[ch.0] -1196 } -1197} -1198 -1199impl IndexMut<ConnectionHandle> for Slab<ConnectionMeta> { -1200 fn index_mut(&mut self, ch: ConnectionHandle) -> &mut ConnectionMeta { -1201 &mut self[ch.0] -1202 } -1203} -1204 -1205/// Event resulting from processing a single datagram -1206pub enum DatagramEvent { -1207 /// The datagram is redirected to its `Connection` -1208 ConnectionEvent(ConnectionHandle, ConnectionEvent), -1209 /// The datagram may result in starting a new `Connection` -1210 NewConnection(Incoming), -1211 /// Response generated directly by the endpoint -1212 Response(Transmit), -1213} -1214 -1215/// An incoming connection for which the server has not yet begun its part of the handshake. -1216#[derive(derive_more::Debug)] -1217pub struct Incoming { -1218 #[debug(skip)] -1219 received_at: Instant, -1220 network_path: FourTuple, -1221 ecn: Option<EcnCodepoint>, -1222 #[debug(skip)] -1223 packet: InitialPacket, -1224 #[debug(skip)] -1225 rest: Option<BytesMut>, -1226 #[debug(skip)] -1227 crypto: Keys, -1228 token: IncomingToken, -1229 incoming_idx: usize, -1230 #[debug(skip)] -1231 improper_drop_warner: IncomingImproperDropWarner, -1232} -1233 -1234impl Incoming { -1235 /// The local IP address which was used when the peer established the connection -1236 /// -1237 /// This has the same behavior as [`Connection::local_ip`]. -1238 pub fn local_ip(&self) -> Option<IpAddr> { -1239 self.network_path.local_ip +1119 if datagram.dst_cid().is_empty() { +1120 if let Some(&ch) = self.incoming_connection_remotes.get(network_path) { +1121 // Never multipath because QUIC-MULTIPATH 1.1 mandates the use of non-zero +1122 // length CIDs. So this is always PathId::ZERO. +1123 return Some(RouteDatagramTo::Connection(ch, PathId::ZERO)); +1124 } +1125 if let Some(&ch) = self.outgoing_connection_remotes.get(&network_path.remote) { +1126 // Like above, QUIC-MULTIPATH 1.1 mandates the use of non-zero length CIDs. +1127 return Some(RouteDatagramTo::Connection(ch, PathId::ZERO)); +1128 } +1129 } +1130 let data = datagram.data(); +1131 if data.len() < RESET_TOKEN_SIZE { +1132 return None; +1133 } +1134 // For stateless resets the PathId is meaningless since it closes the entire +1135 // connection regardless of path. So use PathId::ZERO. +1136 self.connection_reset_tokens +1137 .get(network_path.remote, &data[data.len() - RESET_TOKEN_SIZE..]) +1138 .cloned() +1139 .map(|ch| RouteDatagramTo::Connection(ch, PathId::ZERO)) +1140 } +1141} +1142 +1143#[derive(Debug)] +1144pub(crate) struct ConnectionMeta { +1145 init_cid: ConnectionId, +1146 /// Locally issues CIDs for each path +1147 loc_cids: FxHashMap<PathId, PathLocalCids>, +1148 /// Remote/local addresses the connection began with +1149 /// +1150 /// Only needed to support connections with zero-length CIDs, which cannot migrate, so we don't +1151 /// bother keeping it up to date. +1152 network_path: FourTuple, +1153 side: Side, +1154 /// Reset tokens provided by the peer for CIDs we're currently sending to +1155 /// +1156 /// Since each reset token is for a CID, it is also for a fixed remote address which is +1157 /// also stored. This allows us to look up which reset tokens we might expect from a +1158 /// given remote address, see [`ResetTokenTable`]. +1159 /// +1160 /// Each path has its own active CID. We use the [`PathId`] as a unique index, allowing +1161 /// us to retire the reset token when a path is abandoned. +1162 // TODO(matheus23): Should be migrated to make reset tokens per 4-tuple instead of per remote addr +1163 reset_token: FxHashMap<PathId, (SocketAddr, ResetToken)>, +1164} +1165 +1166/// Local connection IDs for a single path +1167#[derive(Debug, Default)] +1168struct PathLocalCids { +1169 /// Number of connection IDs that have been issued in (PATH_)NEW_CONNECTION_ID frames +1170 /// +1171 /// Another way of saying this is that this is the next sequence number to be issued. +1172 issued: u64, +1173 /// Issues CIDs indexed by their sequence number. +1174 cids: FxHashMap<u64, ConnectionId>, +1175} +1176 +1177/// Internal identifier for a `Connection` currently associated with an endpoint +1178#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +1179pub struct ConnectionHandle(pub usize); +1180 +1181impl From<ConnectionHandle> for usize { +1182 fn from(x: ConnectionHandle) -> Self { +1183 x.0 +1184 } +1185} +1186 +1187impl Index<ConnectionHandle> for Slab<ConnectionMeta> { +1188 type Output = ConnectionMeta; +1189 fn index(&self, ch: ConnectionHandle) -> &ConnectionMeta { +1190 &self[ch.0] +1191 } +1192} +1193 +1194impl IndexMut<ConnectionHandle> for Slab<ConnectionMeta> { +1195 fn index_mut(&mut self, ch: ConnectionHandle) -> &mut ConnectionMeta { +1196 &mut self[ch.0] +1197 } +1198} +1199 +1200/// Event resulting from processing a single datagram +1201pub enum DatagramEvent { +1202 /// The datagram is redirected to its `Connection` +1203 ConnectionEvent(ConnectionHandle, ConnectionEvent), +1204 /// The datagram may result in starting a new `Connection` +1205 NewConnection(Incoming), +1206 /// Response generated directly by the endpoint +1207 Response(Transmit), +1208} +1209 +1210/// An incoming connection for which the server has not yet begun its part of the handshake. +1211#[derive(derive_more::Debug)] +1212pub struct Incoming { +1213 #[debug(skip)] +1214 received_at: Instant, +1215 network_path: FourTuple, +1216 ecn: Option<EcnCodepoint>, +1217 #[debug(skip)] +1218 packet: InitialPacket, +1219 #[debug(skip)] +1220 rest: Option<BytesMut>, +1221 #[debug(skip)] +1222 crypto: Keys, +1223 token: IncomingToken, +1224 incoming_idx: usize, +1225 #[debug(skip)] +1226 improper_drop_warner: IncomingImproperDropWarner, +1227} +1228 +1229impl Incoming { +1230 /// The local IP address which was used when the peer established the connection +1231 /// +1232 /// This has the same behavior as [`Connection::local_ip`]. +1233 pub fn local_ip(&self) -> Option<IpAddr> { +1234 self.network_path.local_ip +1235 } +1236 +1237 /// The peer's UDP address +1238 pub fn remote_address(&self) -> SocketAddr { +1239 self.network_path.remote 1240 } 1241 -1242 /// The peer's UDP address -1243 pub fn remote_address(&self) -> SocketAddr { -1244 self.network_path.remote -1245 } -1246 -1247 /// Whether the socket address that is initiating this connection has been validated -1248 /// -1249 /// This means that the sender of the initial packet has proved that they can receive traffic -1250 /// sent to `self.remote_address()`. -1251 /// -1252 /// If `self.remote_address_validated()` is false, `self.may_retry()` is guaranteed to be true. -1253 /// The inverse is not guaranteed. -1254 pub fn remote_address_validated(&self) -> bool { -1255 self.token.validated -1256 } -1257 -1258 /// Whether it is legal to respond with a retry packet -1259 /// -1260 /// If `self.remote_address_validated()` is false, `self.may_retry()` is guaranteed to be true. -1261 /// The inverse is not guaranteed. -1262 pub fn may_retry(&self) -> bool { -1263 self.token.retry_src_cid.is_none() +1242 /// Whether the socket address that is initiating this connection has been validated +1243 /// +1244 /// This means that the sender of the initial packet has proved that they can receive traffic +1245 /// sent to `self.remote_address()`. +1246 /// +1247 /// If `self.remote_address_validated()` is false, `self.may_retry()` is guaranteed to be true. +1248 /// The inverse is not guaranteed. +1249 pub fn remote_address_validated(&self) -> bool { +1250 self.token.validated +1251 } +1252 +1253 /// Whether it is legal to respond with a retry packet +1254 /// +1255 /// If `self.remote_address_validated()` is false, `self.may_retry()` is guaranteed to be true. +1256 /// The inverse is not guaranteed. +1257 pub fn may_retry(&self) -> bool { +1258 self.token.retry_src_cid.is_none() +1259 } +1260 +1261 /// The original destination connection ID sent by the client +1262 pub fn orig_dst_cid(&self) -> ConnectionId { +1263 self.token.orig_dst_cid 1264 } -1265 -1266 /// The original destination connection ID sent by the client -1267 pub fn orig_dst_cid(&self) -> ConnectionId { -1268 self.token.orig_dst_cid -1269 } -1270} -1271 -1272struct IncomingImproperDropWarner; -1273 -1274impl IncomingImproperDropWarner { -1275 fn dismiss(self) { -1276 mem::forget(self); -1277 } -1278} -1279 -1280impl Drop for IncomingImproperDropWarner { -1281 fn drop(&mut self) { -1282 warn!( -1283 "quinn_proto::Incoming dropped without passing to Endpoint::accept/refuse/retry/ignore \ -1284 (may cause memory leak and eventual inability to accept new connections)" -1285 ); -1286 } -1287} -1288 -1289/// Errors in the parameters being used to create a new connection -1290/// -1291/// These arise before any I/O has been performed. -1292#[derive(Debug, Error, Clone, PartialEq, Eq)] -1293pub enum ConnectError { -1294 /// The endpoint can no longer create new connections +1265} +1266 +1267struct IncomingImproperDropWarner; +1268 +1269impl IncomingImproperDropWarner { +1270 fn dismiss(self) { +1271 mem::forget(self); +1272 } +1273} +1274 +1275impl Drop for IncomingImproperDropWarner { +1276 fn drop(&mut self) { +1277 warn!( +1278 "quinn_proto::Incoming dropped without passing to Endpoint::accept/refuse/retry/ignore \ +1279 (may cause memory leak and eventual inability to accept new connections)" +1280 ); +1281 } +1282} +1283 +1284/// Errors in the parameters being used to create a new connection +1285/// +1286/// These arise before any I/O has been performed. +1287#[derive(Debug, Error, Clone, PartialEq, Eq)] +1288pub enum ConnectError { +1289 /// The endpoint can no longer create new connections +1290 /// +1291 /// Indicates that a necessary component of the endpoint has been dropped or otherwise disabled. +1292 #[error("endpoint stopping")] +1293 EndpointStopping, +1294 /// The connection could not be created because not enough of the CID space is available 1295 /// -1296 /// Indicates that a necessary component of the endpoint has been dropped or otherwise disabled. -1297 #[error("endpoint stopping")] -1298 EndpointStopping, -1299 /// The connection could not be created because not enough of the CID space is available -1300 /// -1301 /// Try using longer connection IDs -1302 #[error("CIDs exhausted")] -1303 CidsExhausted, -1304 /// The given server name was malformed -1305 #[error("invalid server name: {0}")] -1306 InvalidServerName(String), -1307 /// The remote [`SocketAddr`] supplied was malformed +1296 /// Try using longer connection IDs +1297 #[error("CIDs exhausted")] +1298 CidsExhausted, +1299 /// The given server name was malformed +1300 #[error("invalid server name: {0}")] +1301 InvalidServerName(String), +1302 /// The remote [`SocketAddr`] supplied was malformed +1303 /// +1304 /// Examples include attempting to connect to port 0, or using an inappropriate address family. +1305 #[error("invalid remote address: {0}")] +1306 InvalidRemoteAddress(SocketAddr), +1307 /// No default client configuration was set up 1308 /// -1309 /// Examples include attempting to connect to port 0, or using an inappropriate address family. -1310 #[error("invalid remote address: {0}")] -1311 InvalidRemoteAddress(SocketAddr), -1312 /// No default client configuration was set up -1313 /// -1314 /// Use `Endpoint::connect_with` to specify a client configuration. -1315 #[error("no default client config")] -1316 NoDefaultClientConfig, -1317 /// The local endpoint does not support the QUIC version specified in the client configuration -1318 #[error("unsupported QUIC version")] -1319 UnsupportedVersion, -1320} -1321 -1322/// Error type for attempting to accept an [`Incoming`] -1323#[derive(Debug)] -1324pub struct AcceptError { -1325 /// Underlying error describing reason for failure -1326 pub cause: ConnectionError, -1327 /// Optional response to transmit back -1328 pub response: Option<Transmit>, -1329} +1309 /// Use `Endpoint::connect_with` to specify a client configuration. +1310 #[error("no default client config")] +1311 NoDefaultClientConfig, +1312 /// The local endpoint does not support the QUIC version specified in the client configuration +1313 #[error("unsupported QUIC version")] +1314 UnsupportedVersion, +1315} +1316 +1317/// Error type for attempting to accept an [`Incoming`] +1318#[derive(Debug)] +1319pub struct AcceptError { +1320 /// Underlying error describing reason for failure +1321 pub cause: ConnectionError, +1322 /// Optional response to transmit back +1323 pub response: Option<Transmit>, +1324} +1325 +1326/// Error for attempting to retry an [`Incoming`] which already bears a token from a previous retry +1327#[derive(Debug, Error)] +1328#[error("retry() with validated Incoming")] +1329pub struct RetryError(Box<Incoming>); 1330 -1331/// Error for attempting to retry an [`Incoming`] which already bears a token from a previous retry -1332#[derive(Debug, Error)] -1333#[error("retry() with validated Incoming")] -1334pub struct RetryError(Box<Incoming>); -1335 -1336impl RetryError { -1337 /// Get the [`Incoming`] -1338 pub fn into_incoming(self) -> Incoming { -1339 *self.0 -1340 } -1341} -1342 -1343/// Reset Tokens which are associated with peer socket addresses -1344/// -1345/// The standard `HashMap` is used since both `SocketAddr` and `ResetToken` are -1346/// peer generated and might be usable for hash collision attacks. -1347#[derive(Default, Debug)] -1348struct ResetTokenTable(HashMap<SocketAddr, HashMap<ResetToken, ConnectionHandle>>); -1349 -1350impl ResetTokenTable { -1351 fn insert(&mut self, remote: SocketAddr, token: ResetToken, ch: ConnectionHandle) -> bool { -1352 self.0 -1353 .entry(remote) -1354 .or_default() -1355 .insert(token, ch) -1356 .is_some() -1357 } -1358 -1359 fn remove(&mut self, remote: SocketAddr, token: ResetToken) { -1360 use std::collections::hash_map::Entry; -1361 match self.0.entry(remote) { -1362 Entry::Vacant(_) => {} -1363 Entry::Occupied(mut e) => { -1364 e.get_mut().remove(&token); -1365 if e.get().is_empty() { -1366 e.remove_entry(); -1367 } -1368 } -1369 } +1331impl RetryError { +1332 /// Get the [`Incoming`] +1333 pub fn into_incoming(self) -> Incoming { +1334 *self.0 +1335 } +1336} +1337 +1338/// Reset Tokens which are associated with peer socket addresses +1339/// +1340/// The standard `HashMap` is used since both `SocketAddr` and `ResetToken` are +1341/// peer generated and might be usable for hash collision attacks. +1342#[derive(Default, Debug)] +1343struct ResetTokenTable(HashMap<SocketAddr, HashMap<ResetToken, ConnectionHandle>>); +1344 +1345impl ResetTokenTable { +1346 fn insert(&mut self, remote: SocketAddr, token: ResetToken, ch: ConnectionHandle) -> bool { +1347 self.0 +1348 .entry(remote) +1349 .or_default() +1350 .insert(token, ch) +1351 .is_some() +1352 } +1353 +1354 fn remove(&mut self, remote: SocketAddr, token: ResetToken) { +1355 use std::collections::hash_map::Entry; +1356 match self.0.entry(remote) { +1357 Entry::Vacant(_) => {} +1358 Entry::Occupied(mut e) => { +1359 e.get_mut().remove(&token); +1360 if e.get().is_empty() { +1361 e.remove_entry(); +1362 } +1363 } +1364 } +1365 } +1366 +1367 fn get(&self, remote: SocketAddr, token: &[u8]) -> Option<&ConnectionHandle> { +1368 let token = ResetToken::from(<[u8; RESET_TOKEN_SIZE]>::try_from(token).ok()?); +1369 self.0.get(&remote)?.get(&token) 1370 } -1371 -1372 fn get(&self, remote: SocketAddr, token: &[u8]) -> Option<&ConnectionHandle> { -1373 let token = ResetToken::from(<[u8; RESET_TOKEN_SIZE]>::try_from(token).ok()?); -1374 self.0.get(&remote)?.get(&token) -1375 } -1376} \ No newline at end of file +1371} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/frame.rs.html b/pr/255/docs/src/iroh_quinn_proto/frame.rs.html index 1b521222d..bb19305c3 100644 --- a/pr/255/docs/src/iroh_quinn_proto/frame.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/frame.rs.html @@ -93,25 +93,25 @@ 93 #[assoc(to_u64 = 0x9f81a7)] 94 ObservedIpv6Addr, 95 // Multipath -96 #[assoc(to_u64 = 0x15228c00)] +96 #[assoc(to_u64 = 0x3e)] 97 PathAck, -98 #[assoc(to_u64 = 0x15228c01)] +98 #[assoc(to_u64 = 0x3f)] 99 PathAckEcn, -100 #[assoc(to_u64 = 0x15228c05)] +100 #[assoc(to_u64 = 0x3e75)] 101 PathAbandon, -102 #[assoc(to_u64 = 0x15228c07)] +102 #[assoc(to_u64 = 0x3e76)] 103 PathStatusBackup, -104 #[assoc(to_u64 = 0x15228c08)] +104 #[assoc(to_u64 = 0x3e77)] 105 PathStatusAvailable, -106 #[assoc(to_u64 = 0x15228c09)] +106 #[assoc(to_u64 = 0x3e78)] 107 PathNewConnectionId, -108 #[assoc(to_u64 = 0x15228c0a)] +108 #[assoc(to_u64 = 0x3e79)] 109 PathRetireConnectionId, -110 #[assoc(to_u64 = 0x15228c0c)] +110 #[assoc(to_u64 = 0x3e7a)] 111 MaxPathId, -112 #[assoc(to_u64 = 0x15228c0d)] +112 #[assoc(to_u64 = 0x3e7b)] 113 PathsBlocked, -114 #[assoc(to_u64 = 0x15228c0e)] +114 #[assoc(to_u64 = 0x3e7c)] 115 PathCidsBlocked, 116 // IROH'S NAT TRAVERSAL 117 #[assoc(to_u64 = 0x3d7f90)] @@ -126,2166 +126,2171 @@ 126 RemoveAddress, 127} 128 -129#[derive(Debug, PartialEq, Eq)] -130pub struct InvalidFrameId(u64); -131 -132impl TryFrom<u64> for FrameType { -133 type Error = InvalidFrameId; -134 fn try_from(value: u64) -> Result<Self, Self::Error> { -135 match Self::from_u64(value) { -136 Some(t) => Ok(t), -137 None => { -138 if DatagramInfo::VALUES.contains(&value) { -139 return Ok(Self::Datagram(DatagramInfo(value as u8))); -140 } -141 if StreamInfo::VALUES.contains(&value) { -142 return Ok(Self::Stream(StreamInfo(value as u8))); -143 } -144 Err(InvalidFrameId(value)) -145 } -146 } -147 } -148} -149 -150impl FrameType { -151 /// The encoded size of this [`FrameType`]. -152 const fn size(&self) -> usize { -153 VarInt(self.to_u64()).size() -154 } -155} -156 -157impl Decodable for FrameType { -158 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -159 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd) -160 } -161} -162 -163impl Encodable for FrameType { -164 fn encode<B: BufMut>(&self, buf: &mut B) { -165 buf.write_var(self.to_u64()); -166 } -167} -168 -169pub(crate) trait FrameStruct { -170 /// Smallest number of bytes this type of frame is guaranteed to fit within. -171 const SIZE_BOUND: usize; -172} -173 -174/// The type used to refer to [`FrameType`]s in closing and transport errors. -175#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)] -176pub enum MaybeFrame { -177 /// Not attributed to any particular [`FrameType`]. -178 None, -179 /// Attributed to some frame type this implementation does not recognize. -180 #[display("UNKNOWN{:02x}", _0)] -181 #[debug("Unknown{:02x}", _0)] -182 Unknown(u64), -183 /// Attributed to a specific [`FrameType`], never [`FrameType::Padding`]. -184 Known(FrameType), -185} -186 -187impl MaybeFrame { -188 /// Encoded size of this [`MaybeFrame`]. -189 const fn size(&self) -> usize { -190 match self { -191 Self::None => VarInt(0).size(), -192 Self::Unknown(other) => VarInt(*other).size(), -193 Self::Known(frame_type) => frame_type.size(), -194 } -195 } -196} -197 -198impl Decodable for MaybeFrame { -199 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -200 match FrameType::try_from(buf.get_var()?) { -201 Ok(FrameType::Padding) => Ok(Self::None), -202 Ok(other_frame) => Ok(Self::Known(other_frame)), -203 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)), -204 } -205 } -206} -207 -208impl Encodable for MaybeFrame { -209 fn encode<B: BufMut>(&self, buf: &mut B) { -210 match self { -211 Self::None => buf.write(0u64), -212 Self::Unknown(frame_id) => buf.write(*frame_id), -213 Self::Known(frame_type) => buf.write(*frame_type), -214 } -215 } -216} -217 -218#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] -219#[display("STREAM")] -220pub struct StreamInfo(u8); -221 -222impl StreamInfo { -223 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f); -224 fn fin(self) -> bool { -225 self.0 & 0x01 != 0 -226 } -227 fn len(self) -> bool { -228 self.0 & 0x02 != 0 -229 } -230 fn off(self) -> bool { -231 self.0 & 0x04 != 0 -232 } -233 -234 const fn to_u64(self) -> u64 { -235 self.0 as u64 -236 } -237} -238 -239#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] -240#[display("DATAGRAM")] -241pub struct DatagramInfo(u8); -242 -243impl DatagramInfo { -244 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31); +129/// Encounter a frame ID that was not valid. +130#[derive(Debug, PartialEq, Eq)] +131pub struct InvalidFrameId(u64); +132 +133impl TryFrom<u64> for FrameType { +134 type Error = InvalidFrameId; +135 fn try_from(value: u64) -> Result<Self, Self::Error> { +136 match Self::from_u64(value) { +137 Some(t) => Ok(t), +138 None => { +139 if DatagramInfo::VALUES.contains(&value) { +140 return Ok(Self::Datagram(DatagramInfo(value as u8))); +141 } +142 if StreamInfo::VALUES.contains(&value) { +143 return Ok(Self::Stream(StreamInfo(value as u8))); +144 } +145 Err(InvalidFrameId(value)) +146 } +147 } +148 } +149} +150 +151impl FrameType { +152 /// The encoded size of this [`FrameType`]. +153 const fn size(&self) -> usize { +154 VarInt(self.to_u64()).size() +155 } +156} +157 +158impl Decodable for FrameType { +159 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +160 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd) +161 } +162} +163 +164impl Encodable for FrameType { +165 fn encode<B: BufMut>(&self, buf: &mut B) { +166 buf.write_var(self.to_u64()); +167 } +168} +169 +170pub(crate) trait FrameStruct { +171 /// Smallest number of bytes this type of frame is guaranteed to fit within. +172 const SIZE_BOUND: usize; +173} +174 +175/// The type used to refer to [`FrameType`]s in closing and transport errors. +176#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)] +177pub enum MaybeFrame { +178 /// Not attributed to any particular [`FrameType`]. +179 None, +180 /// Attributed to some frame type this implementation does not recognize. +181 #[display("UNKNOWN{:02x}", _0)] +182 #[debug("Unknown{:02x}", _0)] +183 Unknown(u64), +184 /// Attributed to a specific [`FrameType`], never [`FrameType::Padding`]. +185 Known(FrameType), +186} +187 +188impl MaybeFrame { +189 /// Encoded size of this [`MaybeFrame`]. +190 const fn size(&self) -> usize { +191 match self { +192 Self::None => VarInt(0).size(), +193 Self::Unknown(other) => VarInt(*other).size(), +194 Self::Known(frame_type) => frame_type.size(), +195 } +196 } +197} +198 +199impl Decodable for MaybeFrame { +200 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +201 match FrameType::try_from(buf.get_var()?) { +202 Ok(FrameType::Padding) => Ok(Self::None), +203 Ok(other_frame) => Ok(Self::Known(other_frame)), +204 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)), +205 } +206 } +207} +208 +209impl Encodable for MaybeFrame { +210 fn encode<B: BufMut>(&self, buf: &mut B) { +211 match self { +212 Self::None => buf.write_var(0u64), +213 Self::Unknown(frame_id) => buf.write_var(*frame_id), +214 Self::Known(frame_type) => buf.write(*frame_type), +215 } +216 } +217} +218 +219#[allow(missing_docs)] +220#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] +221#[display("STREAM")] +222pub struct StreamInfo(u8); +223 +224impl StreamInfo { +225 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f); +226 fn fin(self) -> bool { +227 self.0 & 0x01 != 0 +228 } +229 fn len(self) -> bool { +230 self.0 & 0x02 != 0 +231 } +232 fn off(self) -> bool { +233 self.0 & 0x04 != 0 +234 } +235 +236 const fn to_u64(self) -> u64 { +237 self.0 as u64 +238 } +239} +240 +241#[allow(missing_docs)] +242#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] +243#[display("DATAGRAM")] +244pub struct DatagramInfo(u8); 245 -246 fn len(self) -> bool { -247 self.0 & 0x01 != 0 -248 } -249 -250 const fn to_u64(self) -> u64 { -251 self.0 as u64 -252 } -253} -254 -255#[derive(Debug)] -256pub(crate) enum Frame { -257 Padding, -258 Ping, -259 Ack(Ack), -260 PathAck(PathAck), -261 ResetStream(ResetStream), -262 StopSending(StopSending), -263 Crypto(Crypto), -264 NewToken(NewToken), -265 Stream(Stream), -266 MaxData(VarInt), -267 MaxStreamData { id: StreamId, offset: u64 }, -268 MaxStreams { dir: Dir, count: u64 }, -269 DataBlocked { offset: u64 }, -270 StreamDataBlocked { id: StreamId, offset: u64 }, -271 StreamsBlocked { dir: Dir, limit: u64 }, -272 NewConnectionId(NewConnectionId), -273 RetireConnectionId(RetireConnectionId), -274 PathChallenge(PathChallenge), -275 PathResponse(PathResponse), -276 Close(Close), -277 Datagram(Datagram), -278 AckFrequency(AckFrequency), -279 ImmediateAck, -280 HandshakeDone, -281 ObservedAddr(ObservedAddr), -282 PathAbandon(PathAbandon), -283 PathStatusAvailable(PathStatusAvailable), -284 PathStatusBackup(PathStatusBackup), -285 MaxPathId(MaxPathId), -286 PathsBlocked(PathsBlocked), -287 PathCidsBlocked(PathCidsBlocked), -288 AddAddress(AddAddress), -289 ReachOut(ReachOut), -290 RemoveAddress(RemoveAddress), -291} -292 -293impl fmt::Display for Frame { -294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -295 // Eventually all our frames will support fmt::Display and be able to be used to log -296 // consistently. For now we fall back to fmt::Debug. -297 match self { -298 Self::Padding => write!(f, "PADDING"), -299 Self::Ping => write!(f, "PING"), -300 Self::PathChallenge(frame) => write!(f, "{frame}"), -301 Self::PathResponse(frame) => write!(f, "{frame}"), -302 Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"), -303 Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"), -304 _ => write!(f, "{self:?}"), -305 } -306 } -307} -308 -309impl Frame { -310 pub(crate) fn ty(&self) -> FrameType { -311 use Frame::*; -312 match *self { -313 Padding => FrameType::Padding, -314 ResetStream(_) => FrameType::ResetStream, -315 Close(self::Close::Connection(_)) => FrameType::ConnectionClose, -316 Close(self::Close::Application(_)) => FrameType::ConnectionClose, -317 MaxData(_) => FrameType::MaxData, -318 MaxStreamData { .. } => FrameType::MaxStreamData, -319 MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi, -320 MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni, -321 Ping => FrameType::Ping, -322 DataBlocked { .. } => FrameType::DataBlocked, -323 StreamDataBlocked { .. } => FrameType::StreamDataBlocked, -324 StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi, -325 StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni, -326 StopSending { .. } => FrameType::StopSending, -327 RetireConnectionId { .. } => FrameType::RetireConnectionId, -328 Ack(_) => FrameType::Ack, -329 PathAck(_) => FrameType::PathAck, -330 Stream(ref x) => { -331 let mut ty = *StreamInfo::VALUES.start() as u8; -332 if x.fin { -333 ty |= 0x01; -334 } -335 if x.offset != 0 { -336 ty |= 0x04; +246impl DatagramInfo { +247 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31); +248 +249 fn len(self) -> bool { +250 self.0 & 0x01 != 0 +251 } +252 +253 const fn to_u64(self) -> u64 { +254 self.0 as u64 +255 } +256} +257 +258#[derive(Debug)] +259pub(crate) enum Frame { +260 Padding, +261 Ping, +262 Ack(Ack), +263 PathAck(PathAck), +264 ResetStream(ResetStream), +265 StopSending(StopSending), +266 Crypto(Crypto), +267 NewToken(NewToken), +268 Stream(Stream), +269 MaxData(VarInt), +270 MaxStreamData { id: StreamId, offset: u64 }, +271 MaxStreams { dir: Dir, count: u64 }, +272 DataBlocked { offset: u64 }, +273 StreamDataBlocked { id: StreamId, offset: u64 }, +274 StreamsBlocked { dir: Dir, limit: u64 }, +275 NewConnectionId(NewConnectionId), +276 RetireConnectionId(RetireConnectionId), +277 PathChallenge(PathChallenge), +278 PathResponse(PathResponse), +279 Close(Close), +280 Datagram(Datagram), +281 AckFrequency(AckFrequency), +282 ImmediateAck, +283 HandshakeDone, +284 ObservedAddr(ObservedAddr), +285 PathAbandon(PathAbandon), +286 PathStatusAvailable(PathStatusAvailable), +287 PathStatusBackup(PathStatusBackup), +288 MaxPathId(MaxPathId), +289 PathsBlocked(PathsBlocked), +290 PathCidsBlocked(PathCidsBlocked), +291 AddAddress(AddAddress), +292 ReachOut(ReachOut), +293 RemoveAddress(RemoveAddress), +294} +295 +296impl fmt::Display for Frame { +297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +298 // Eventually all our frames will support fmt::Display and be able to be used to log +299 // consistently. For now we fall back to fmt::Debug. +300 match self { +301 Self::Padding => write!(f, "PADDING"), +302 Self::Ping => write!(f, "PING"), +303 Self::PathChallenge(frame) => write!(f, "{frame}"), +304 Self::PathResponse(frame) => write!(f, "{frame}"), +305 Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"), +306 Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"), +307 _ => write!(f, "{self:?}"), +308 } +309 } +310} +311 +312impl Frame { +313 pub(crate) fn ty(&self) -> FrameType { +314 use Frame::*; +315 match *self { +316 Padding => FrameType::Padding, +317 ResetStream(_) => FrameType::ResetStream, +318 Close(self::Close::Connection(_)) => FrameType::ConnectionClose, +319 Close(self::Close::Application(_)) => FrameType::ConnectionClose, +320 MaxData(_) => FrameType::MaxData, +321 MaxStreamData { .. } => FrameType::MaxStreamData, +322 MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi, +323 MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni, +324 Ping => FrameType::Ping, +325 DataBlocked { .. } => FrameType::DataBlocked, +326 StreamDataBlocked { .. } => FrameType::StreamDataBlocked, +327 StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi, +328 StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni, +329 StopSending { .. } => FrameType::StopSending, +330 RetireConnectionId { .. } => FrameType::RetireConnectionId, +331 Ack(_) => FrameType::Ack, +332 PathAck(_) => FrameType::PathAck, +333 Stream(ref x) => { +334 let mut ty = *StreamInfo::VALUES.start() as u8; +335 if x.fin { +336 ty |= 0x01; 337 } -338 // TODO(@divma): move all this to getframetype for Stream -339 FrameType::Stream(StreamInfo(ty)) -340 } -341 PathChallenge(_) => FrameType::PathChallenge, -342 PathResponse(_) => FrameType::PathResponse, -343 NewConnectionId(cid) => cid.get_type(), -344 Crypto(_) => FrameType::Crypto, -345 NewToken(_) => FrameType::NewToken, -346 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)), -347 AckFrequency(_) => FrameType::AckFrequency, -348 ImmediateAck => FrameType::ImmediateAck, -349 HandshakeDone => FrameType::HandshakeDone, -350 ObservedAddr(ref observed) => observed.get_type(), -351 PathAbandon(_) => FrameType::PathAbandon, -352 PathStatusAvailable(_) => FrameType::PathStatusAvailable, -353 PathStatusBackup(_) => FrameType::PathStatusBackup, -354 MaxPathId(_) => FrameType::MaxPathId, -355 PathsBlocked(_) => FrameType::PathsBlocked, -356 PathCidsBlocked(_) => FrameType::PathCidsBlocked, -357 AddAddress(ref frame) => frame.get_type(), -358 ReachOut(ref frame) => frame.get_type(), -359 RemoveAddress(_) => self::RemoveAddress::TYPE, -360 } -361 } -362 -363 pub(crate) fn is_ack_eliciting(&self) -> bool { -364 !matches!( -365 *self, -366 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_) -367 ) -368 } -369 -370 /// Returns `true` if this frame MUST be sent in 1-RTT space -371 pub(crate) fn is_1rtt(&self) -> bool { -372 // See also https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-4-1: -373 // > All frames defined in this document MUST only be sent in 1-RTT packets. -374 // > If an endpoint receives a multipath-specific frame in a different packet type, it MUST close the -375 // > connection with an error of type PROTOCOL_VIOLATION. -376 -377 self.is_multipath_frame() || self.is_qad_frame() -378 } +338 if x.offset != 0 { +339 ty |= 0x04; +340 } +341 // TODO(@divma): move all this to getframetype for Stream +342 FrameType::Stream(StreamInfo(ty)) +343 } +344 PathChallenge(_) => FrameType::PathChallenge, +345 PathResponse(_) => FrameType::PathResponse, +346 NewConnectionId(cid) => cid.get_type(), +347 Crypto(_) => FrameType::Crypto, +348 NewToken(_) => FrameType::NewToken, +349 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)), +350 AckFrequency(_) => FrameType::AckFrequency, +351 ImmediateAck => FrameType::ImmediateAck, +352 HandshakeDone => FrameType::HandshakeDone, +353 ObservedAddr(ref observed) => observed.get_type(), +354 PathAbandon(_) => FrameType::PathAbandon, +355 PathStatusAvailable(_) => FrameType::PathStatusAvailable, +356 PathStatusBackup(_) => FrameType::PathStatusBackup, +357 MaxPathId(_) => FrameType::MaxPathId, +358 PathsBlocked(_) => FrameType::PathsBlocked, +359 PathCidsBlocked(_) => FrameType::PathCidsBlocked, +360 AddAddress(ref frame) => frame.get_type(), +361 ReachOut(ref frame) => frame.get_type(), +362 RemoveAddress(_) => self::RemoveAddress::TYPE, +363 } +364 } +365 +366 pub(crate) fn is_ack_eliciting(&self) -> bool { +367 !matches!( +368 *self, +369 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_) +370 ) +371 } +372 +373 /// Returns `true` if this frame MUST be sent in 1-RTT space +374 pub(crate) fn is_1rtt(&self) -> bool { +375 // See also https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-4-1: +376 // > All frames defined in this document MUST only be sent in 1-RTT packets. +377 // > If an endpoint receives a multipath-specific frame in a different packet type, it MUST close the +378 // > connection with an error of type PROTOCOL_VIOLATION. 379 -380 fn is_qad_frame(&self) -> bool { -381 matches!(*self, Self::ObservedAddr(_)) -382 } -383 -384 fn is_multipath_frame(&self) -> bool { -385 matches!( -386 *self, -387 Self::PathAck(_) -388 | Self::PathAbandon(_) -389 | Self::PathStatusBackup(_) -390 | Self::PathStatusAvailable(_) -391 | Self::MaxPathId(_) -392 | Self::PathsBlocked(_) -393 | Self::PathCidsBlocked(_) -394 | Self::NewConnectionId(NewConnectionId { -395 path_id: Some(_), -396 .. -397 }) -398 | Self::RetireConnectionId(RetireConnectionId { -399 path_id: Some(_), -400 .. -401 }) -402 ) -403 } -404} -405 -406#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)] -407#[display("PATH_CHALLENGE({_0:08x})")] -408pub(crate) struct PathChallenge(pub(crate) u64); -409 -410impl PathChallenge { -411 pub(crate) const SIZE_BOUND: usize = 9; -412} -413impl Decodable for PathChallenge { -414 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -415 Ok(Self(buf.get()?)) -416 } -417} -418impl Encodable for PathChallenge { -419 fn encode<B: BufMut>(&self, buf: &mut B) { -420 buf.write(FrameType::PathChallenge); -421 buf.write(self.0); -422 } -423} -424 -425#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)] -426#[display("PATH_RESPONSE({_0:08x})")] -427pub(crate) struct PathResponse(pub(crate) u64); -428 -429impl PathResponse { -430 pub(crate) const SIZE_BOUND: usize = 9; -431} -432 -433impl Decodable for PathResponse { -434 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -435 Ok(Self(buf.get()?)) -436 } -437} -438impl Encodable for PathResponse { -439 fn encode<B: BufMut>(&self, buf: &mut B) { -440 buf.write(FrameType::PathResponse); -441 buf.write(self.0); -442 } -443} -444 -445#[derive(Debug, PartialEq, Eq)] -446pub(crate) struct RetireConnectionId { -447 pub(crate) path_id: Option<PathId>, -448 pub(crate) sequence: u64, -449} -450 -451impl RetireConnectionId { -452 /// Maximum size of this frame when the frame type is [`FrameType::RetireConnectionId`] -453 pub(crate) const SIZE_BOUND: usize = { -454 let type_len = FrameType::RetireConnectionId.size(); -455 let seq_max_len = 8usize; -456 type_len + seq_max_len -457 }; -458 -459 /// Maximum size of this frame when the frame type is [`FrameType::PathRetireConnectionId`] -460 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { -461 let type_len = FrameType::PathRetireConnectionId.size(); -462 let path_id_len = VarInt::from_u32(u32::MAX).size(); -463 let seq_max_len = 8usize; -464 type_len + path_id_len + seq_max_len -465 }; -466 -467 /// Decode [`Self`] from the buffer, provided that the frame type has been verified (either -468 /// [`FrameType::PathRetireConnectionId`], or [`FrameType::RetireConnectionId`]) -469 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> { -470 Ok(Self { -471 path_id: if read_path { Some(bytes.get()?) } else { None }, -472 sequence: bytes.get_var()?, -473 }) -474 } -475 -476 /// Get the [`FrameType`] for this [`RetireConnectionId`] -477 pub(crate) fn get_type(&self) -> FrameType { -478 if self.path_id.is_some() { -479 FrameType::PathRetireConnectionId -480 } else { -481 FrameType::RetireConnectionId -482 } -483 } -484 -485 /// Returns the maximum encoded size on the wire -486 /// -487 /// `path_retire_cid` determines whether this frame is a multipath frame. This is a rough upper -488 /// estimate, does not squeeze every last byte out. -489 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize { -490 match path_retire_cid { -491 true => Self::SIZE_BOUND_MULTIPATH, -492 false => Self::SIZE_BOUND, -493 } -494 } -495} -496 -497impl Encodable for RetireConnectionId { -498 fn encode<W: BufMut>(&self, buf: &mut W) { -499 buf.write(self.get_type()); -500 if let Some(id) = self.path_id { -501 buf.write(id); -502 } -503 buf.write_var(self.sequence); -504 } -505} -506 -507#[derive(Clone, Debug)] -508pub enum Close { -509 Connection(ConnectionClose), -510 Application(ApplicationClose), -511} -512 -513impl Close { -514 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> { -515 CloseEncoder { -516 close: self, -517 max_len, -518 } -519 } -520 -521 pub(crate) fn is_transport_layer(&self) -> bool { -522 matches!(*self, Self::Connection(_)) -523 } -524} -525 -526pub(crate) struct CloseEncoder<'a> { -527 close: &'a Close, -528 max_len: usize, -529} -530 -531impl<'a> Encodable for CloseEncoder<'a> { -532 fn encode<W: BufMut>(&self, out: &mut W) { -533 match self.close { -534 Close::Connection(x) => x.encode(out, self.max_len), -535 Close::Application(x) => x.encode(out, self.max_len), -536 } -537 } -538} -539 -540impl From<TransportError> for Close { -541 fn from(x: TransportError) -> Self { -542 Self::Connection(x.into()) -543 } -544} -545impl From<ConnectionClose> for Close { -546 fn from(x: ConnectionClose) -> Self { -547 Self::Connection(x) -548 } -549} -550impl From<ApplicationClose> for Close { -551 fn from(x: ApplicationClose) -> Self { -552 Self::Application(x) -553 } -554} -555 -556/// Reason given by the transport for closing the connection -557#[derive(Debug, Clone, PartialEq, Eq)] -558pub struct ConnectionClose { -559 /// Class of error as encoded in the specification -560 pub error_code: TransportErrorCode, -561 /// Type of frame that caused the close -562 pub frame_type: MaybeFrame, -563 /// Human-readable reason for the close -564 pub reason: Bytes, -565} -566 -567impl fmt::Display for ConnectionClose { -568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -569 self.error_code.fmt(f)?; -570 if !self.reason.as_ref().is_empty() { -571 f.write_str(": ")?; -572 f.write_str(&String::from_utf8_lossy(&self.reason))?; -573 } -574 Ok(()) -575 } -576} -577 -578impl From<TransportError> for ConnectionClose { -579 fn from(x: TransportError) -> Self { -580 Self { -581 error_code: x.code, -582 frame_type: x.frame, -583 reason: x.reason.into(), -584 } -585 } -586} -587 -588impl FrameStruct for ConnectionClose { -589 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -590} -591 -592impl ConnectionClose { -593 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { -594 out.write(FrameType::ConnectionClose); // 1 byte -595 out.write(self.error_code); // <= 8 bytes -596 out.write(self.frame_type); // <= 8 bytes -597 let max_len = max_len -598 - 3 -599 - self.frame_type.size() -600 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); -601 let actual_len = self.reason.len().min(max_len); -602 out.write_var(actual_len as u64); // <= 8 bytes -603 out.put_slice(&self.reason[0..actual_len]); // whatever's left -604 } -605} -606 -607/// Reason given by an application for closing the connection -608#[derive(Debug, Clone, PartialEq, Eq)] -609pub struct ApplicationClose { -610 /// Application-specific reason code -611 pub error_code: VarInt, -612 /// Human-readable reason for the close -613 pub reason: Bytes, -614} -615 -616impl fmt::Display for ApplicationClose { -617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -618 if !self.reason.as_ref().is_empty() { -619 f.write_str(&String::from_utf8_lossy(&self.reason))?; -620 f.write_str(" (code ")?; -621 self.error_code.fmt(f)?; -622 f.write_str(")")?; -623 } else { +380 self.is_multipath_frame() || self.is_qad_frame() +381 } +382 +383 fn is_qad_frame(&self) -> bool { +384 matches!(*self, Self::ObservedAddr(_)) +385 } +386 +387 fn is_multipath_frame(&self) -> bool { +388 matches!( +389 *self, +390 Self::PathAck(_) +391 | Self::PathAbandon(_) +392 | Self::PathStatusBackup(_) +393 | Self::PathStatusAvailable(_) +394 | Self::MaxPathId(_) +395 | Self::PathsBlocked(_) +396 | Self::PathCidsBlocked(_) +397 | Self::NewConnectionId(NewConnectionId { +398 path_id: Some(_), +399 .. +400 }) +401 | Self::RetireConnectionId(RetireConnectionId { +402 path_id: Some(_), +403 .. +404 }) +405 ) +406 } +407} +408 +409#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)] +410#[display("PATH_CHALLENGE({_0:08x})")] +411pub(crate) struct PathChallenge(pub(crate) u64); +412 +413impl PathChallenge { +414 pub(crate) const SIZE_BOUND: usize = 9; +415} +416impl Decodable for PathChallenge { +417 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +418 Ok(Self(buf.get()?)) +419 } +420} +421impl Encodable for PathChallenge { +422 fn encode<B: BufMut>(&self, buf: &mut B) { +423 buf.write(FrameType::PathChallenge); +424 buf.write(self.0); +425 } +426} +427 +428#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)] +429#[display("PATH_RESPONSE({_0:08x})")] +430pub(crate) struct PathResponse(pub(crate) u64); +431 +432impl PathResponse { +433 pub(crate) const SIZE_BOUND: usize = 9; +434} +435 +436impl Decodable for PathResponse { +437 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +438 Ok(Self(buf.get()?)) +439 } +440} +441impl Encodable for PathResponse { +442 fn encode<B: BufMut>(&self, buf: &mut B) { +443 buf.write(FrameType::PathResponse); +444 buf.write(self.0); +445 } +446} +447 +448#[derive(Debug, PartialEq, Eq)] +449pub(crate) struct RetireConnectionId { +450 pub(crate) path_id: Option<PathId>, +451 pub(crate) sequence: u64, +452} +453 +454impl RetireConnectionId { +455 /// Maximum size of this frame when the frame type is [`FrameType::RetireConnectionId`] +456 pub(crate) const SIZE_BOUND: usize = { +457 let type_len = FrameType::RetireConnectionId.size(); +458 let seq_max_len = 8usize; +459 type_len + seq_max_len +460 }; +461 +462 /// Maximum size of this frame when the frame type is [`FrameType::PathRetireConnectionId`] +463 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { +464 let type_len = FrameType::PathRetireConnectionId.size(); +465 let path_id_len = VarInt::from_u32(u32::MAX).size(); +466 let seq_max_len = 8usize; +467 type_len + path_id_len + seq_max_len +468 }; +469 +470 /// Decode [`Self`] from the buffer, provided that the frame type has been verified (either +471 /// [`FrameType::PathRetireConnectionId`], or [`FrameType::RetireConnectionId`]) +472 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> { +473 Ok(Self { +474 path_id: if read_path { Some(bytes.get()?) } else { None }, +475 sequence: bytes.get_var()?, +476 }) +477 } +478 +479 /// Get the [`FrameType`] for this [`RetireConnectionId`] +480 pub(crate) fn get_type(&self) -> FrameType { +481 if self.path_id.is_some() { +482 FrameType::PathRetireConnectionId +483 } else { +484 FrameType::RetireConnectionId +485 } +486 } +487 +488 /// Returns the maximum encoded size on the wire +489 /// +490 /// `path_retire_cid` determines whether this frame is a multipath frame. This is a rough upper +491 /// estimate, does not squeeze every last byte out. +492 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize { +493 match path_retire_cid { +494 true => Self::SIZE_BOUND_MULTIPATH, +495 false => Self::SIZE_BOUND, +496 } +497 } +498} +499 +500impl Encodable for RetireConnectionId { +501 fn encode<W: BufMut>(&self, buf: &mut W) { +502 buf.write(self.get_type()); +503 if let Some(id) = self.path_id { +504 buf.write(id); +505 } +506 buf.write_var(self.sequence); +507 } +508} +509 +510#[derive(Clone, Debug)] +511pub(crate) enum Close { +512 Connection(ConnectionClose), +513 Application(ApplicationClose), +514} +515 +516impl Close { +517 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> { +518 CloseEncoder { +519 close: self, +520 max_len, +521 } +522 } +523 +524 pub(crate) fn is_transport_layer(&self) -> bool { +525 matches!(*self, Self::Connection(_)) +526 } +527} +528 +529pub(crate) struct CloseEncoder<'a> { +530 close: &'a Close, +531 max_len: usize, +532} +533 +534impl<'a> Encodable for CloseEncoder<'a> { +535 fn encode<W: BufMut>(&self, out: &mut W) { +536 match self.close { +537 Close::Connection(x) => x.encode(out, self.max_len), +538 Close::Application(x) => x.encode(out, self.max_len), +539 } +540 } +541} +542 +543impl From<TransportError> for Close { +544 fn from(x: TransportError) -> Self { +545 Self::Connection(x.into()) +546 } +547} +548impl From<ConnectionClose> for Close { +549 fn from(x: ConnectionClose) -> Self { +550 Self::Connection(x) +551 } +552} +553impl From<ApplicationClose> for Close { +554 fn from(x: ApplicationClose) -> Self { +555 Self::Application(x) +556 } +557} +558 +559/// Reason given by the transport for closing the connection +560#[derive(Debug, Clone, PartialEq, Eq)] +561pub struct ConnectionClose { +562 /// Class of error as encoded in the specification +563 pub error_code: TransportErrorCode, +564 /// Type of frame that caused the close +565 pub frame_type: MaybeFrame, +566 /// Human-readable reason for the close +567 pub reason: Bytes, +568} +569 +570impl fmt::Display for ConnectionClose { +571 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +572 self.error_code.fmt(f)?; +573 if !self.reason.as_ref().is_empty() { +574 f.write_str(": ")?; +575 f.write_str(&String::from_utf8_lossy(&self.reason))?; +576 } +577 Ok(()) +578 } +579} +580 +581impl From<TransportError> for ConnectionClose { +582 fn from(x: TransportError) -> Self { +583 Self { +584 error_code: x.code, +585 frame_type: x.frame, +586 reason: x.reason.into(), +587 } +588 } +589} +590 +591impl FrameStruct for ConnectionClose { +592 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +593} +594 +595impl ConnectionClose { +596 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { +597 out.write(FrameType::ConnectionClose); // 1 byte +598 out.write(self.error_code); // <= 8 bytes +599 out.write(self.frame_type); // <= 8 bytes +600 let max_len = max_len +601 - 3 +602 - self.frame_type.size() +603 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); +604 let actual_len = self.reason.len().min(max_len); +605 out.write_var(actual_len as u64); // <= 8 bytes +606 out.put_slice(&self.reason[0..actual_len]); // whatever's left +607 } +608} +609 +610/// Reason given by an application for closing the connection +611#[derive(Debug, Clone, PartialEq, Eq)] +612pub struct ApplicationClose { +613 /// Application-specific reason code +614 pub error_code: VarInt, +615 /// Human-readable reason for the close +616 pub reason: Bytes, +617} +618 +619impl fmt::Display for ApplicationClose { +620 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +621 if !self.reason.as_ref().is_empty() { +622 f.write_str(&String::from_utf8_lossy(&self.reason))?; +623 f.write_str(" (code ")?; 624 self.error_code.fmt(f)?; -625 } -626 Ok(()) -627 } -628} -629 -630impl FrameStruct for ApplicationClose { -631 const SIZE_BOUND: usize = 1 + 8 + 8; -632} -633 -634impl ApplicationClose { -635 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { -636 out.write(FrameType::ApplicationClose); // 1 byte -637 out.write(self.error_code); // <= 8 bytes -638 let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); -639 let actual_len = self.reason.len().min(max_len); -640 out.write_var(actual_len as u64); // <= 8 bytes -641 out.put_slice(&self.reason[0..actual_len]); // whatever's left -642 } -643} -644 -645#[derive(Clone, Eq, PartialEq)] -646pub struct PathAck { -647 pub path_id: PathId, -648 pub largest: u64, -649 pub delay: u64, -650 pub additional: Bytes, -651 pub ecn: Option<EcnCounts>, -652} -653 -654impl fmt::Debug for PathAck { -655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -656 let mut ranges = "[".to_string(); -657 let mut first = true; -658 for range in self.into_iter() { -659 if !first { -660 ranges.push(','); -661 } -662 write!(ranges, "{range:?}")?; -663 first = false; -664 } -665 ranges.push(']'); -666 -667 f.debug_struct("PathAck") -668 .field("path_id", &self.path_id) -669 .field("largest", &self.largest) -670 .field("delay", &self.delay) -671 .field("ecn", &self.ecn) -672 .field("ranges", &ranges) -673 .finish() -674 } -675} -676 -677impl<'a> IntoIterator for &'a PathAck { -678 type Item = RangeInclusive<u64>; -679 type IntoIter = AckIter<'a>; -680 -681 fn into_iter(self) -> AckIter<'a> { -682 AckIter::new(self.largest, &self.additional[..]) -683 } -684} -685 -686impl PathAck { -687 pub fn into_ack(self) -> (Ack, PathId) { -688 let ack = Ack { -689 largest: self.largest, -690 delay: self.delay, -691 additional: self.additional, -692 ecn: self.ecn, -693 }; -694 -695 (ack, self.path_id) -696 } -697 -698 pub(crate) fn encoder<'a>( -699 path_id: PathId, -700 delay: u64, -701 ranges: &'a ArrayRangeSet, -702 ecn: Option<&'a EcnCounts>, -703 ) -> PathAckEncoder<'a> { -704 PathAckEncoder { -705 path_id, -706 delay, -707 ranges, -708 ecn, -709 } -710 } -711} -712 -713pub(crate) struct PathAckEncoder<'a> { -714 path_id: PathId, -715 delay: u64, -716 ranges: &'a ArrayRangeSet, -717 ecn: Option<&'a EcnCounts>, -718} -719 -720impl<'a> Encodable for PathAckEncoder<'a> { -721 /// Encode [`Self`] into the given buffer -722 /// -723 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] -724 /// depending on whether [`EcnCounts`] are provided. -725 /// -726 /// PANICS: if `ranges` is empty. -727 fn encode<W: BufMut>(&self, buf: &mut W) { -728 let PathAckEncoder { -729 path_id, -730 delay, -731 ranges, -732 ecn, -733 } = self; -734 let mut rest = ranges.iter().rev(); -735 let first = rest -736 .next() -737 .expect("Caller has verified ranges is non empty"); -738 let largest = first.end - 1; -739 let first_size = first.end - first.start; -740 let kind = match ecn.is_some() { -741 true => FrameType::PathAckEcn, -742 false => FrameType::PathAck, -743 }; -744 buf.write(kind); -745 buf.write(*path_id); -746 buf.write_var(largest); -747 buf.write_var(*delay); -748 buf.write_var(ranges.len() as u64 - 1); -749 buf.write_var(first_size - 1); -750 let mut prev = first.start; -751 for block in rest { -752 let size = block.end - block.start; -753 buf.write_var(prev - block.end - 1); -754 buf.write_var(size - 1); -755 prev = block.start; -756 } -757 if let Some(x) = ecn { -758 x.encode(buf) -759 } -760 } -761} -762 -763#[derive(Clone, Eq, PartialEq)] -764pub struct Ack { -765 pub largest: u64, -766 pub delay: u64, -767 pub additional: Bytes, -768 pub ecn: Option<EcnCounts>, -769} -770 -771impl fmt::Debug for Ack { -772 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -773 let mut ranges = "[".to_string(); -774 let mut first = true; -775 for range in self.iter() { -776 if !first { -777 ranges.push(','); -778 } -779 write!(ranges, "{range:?}").unwrap(); -780 first = false; -781 } -782 ranges.push(']'); -783 -784 f.debug_struct("Ack") -785 .field("largest", &self.largest) -786 .field("delay", &self.delay) -787 .field("ecn", &self.ecn) -788 .field("ranges", &ranges) -789 .finish() -790 } -791} -792 -793impl<'a> IntoIterator for &'a Ack { -794 type Item = RangeInclusive<u64>; -795 type IntoIter = AckIter<'a>; +625 f.write_str(")")?; +626 } else { +627 self.error_code.fmt(f)?; +628 } +629 Ok(()) +630 } +631} +632 +633impl FrameStruct for ApplicationClose { +634 const SIZE_BOUND: usize = 1 + 8 + 8; +635} +636 +637impl ApplicationClose { +638 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { +639 out.write(FrameType::ApplicationClose); // 1 byte +640 out.write(self.error_code); // <= 8 bytes +641 let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); +642 let actual_len = self.reason.len().min(max_len); +643 out.write_var(actual_len as u64); // <= 8 bytes +644 out.put_slice(&self.reason[0..actual_len]); // whatever's left +645 } +646} +647 +648#[derive(Clone, Eq, PartialEq)] +649pub(crate) struct PathAck { +650 pub path_id: PathId, +651 pub largest: u64, +652 pub delay: u64, +653 pub additional: Bytes, +654 pub ecn: Option<EcnCounts>, +655} +656 +657impl fmt::Debug for PathAck { +658 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +659 let mut ranges = "[".to_string(); +660 let mut first = true; +661 for range in self.into_iter() { +662 if !first { +663 ranges.push(','); +664 } +665 write!(ranges, "{range:?}")?; +666 first = false; +667 } +668 ranges.push(']'); +669 +670 f.debug_struct("PathAck") +671 .field("path_id", &self.path_id) +672 .field("largest", &self.largest) +673 .field("delay", &self.delay) +674 .field("ecn", &self.ecn) +675 .field("ranges", &ranges) +676 .finish() +677 } +678} +679 +680impl<'a> IntoIterator for &'a PathAck { +681 type Item = RangeInclusive<u64>; +682 #[allow(unnameable_types)] +683 type IntoIter = AckIter<'a>; +684 +685 fn into_iter(self) -> Self::IntoIter { +686 AckIter::new(self.largest, &self.additional[..]) +687 } +688} +689 +690impl PathAck { +691 pub(crate) fn into_ack(self) -> (Ack, PathId) { +692 let ack = Ack { +693 largest: self.largest, +694 delay: self.delay, +695 additional: self.additional, +696 ecn: self.ecn, +697 }; +698 +699 (ack, self.path_id) +700 } +701 +702 pub(crate) fn encoder<'a>( +703 path_id: PathId, +704 delay: u64, +705 ranges: &'a ArrayRangeSet, +706 ecn: Option<&'a EcnCounts>, +707 ) -> PathAckEncoder<'a> { +708 PathAckEncoder { +709 path_id, +710 delay, +711 ranges, +712 ecn, +713 } +714 } +715} +716 +717pub(crate) struct PathAckEncoder<'a> { +718 path_id: PathId, +719 delay: u64, +720 ranges: &'a ArrayRangeSet, +721 ecn: Option<&'a EcnCounts>, +722} +723 +724impl<'a> Encodable for PathAckEncoder<'a> { +725 /// Encode [`Self`] into the given buffer +726 /// +727 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] +728 /// depending on whether [`EcnCounts`] are provided. +729 /// +730 /// PANICS: if `ranges` is empty. +731 fn encode<W: BufMut>(&self, buf: &mut W) { +732 let PathAckEncoder { +733 path_id, +734 delay, +735 ranges, +736 ecn, +737 } = self; +738 let mut rest = ranges.iter().rev(); +739 let first = rest +740 .next() +741 .expect("Caller has verified ranges is non empty"); +742 let largest = first.end - 1; +743 let first_size = first.end - first.start; +744 let kind = match ecn.is_some() { +745 true => FrameType::PathAckEcn, +746 false => FrameType::PathAck, +747 }; +748 buf.write(kind); +749 buf.write(*path_id); +750 buf.write_var(largest); +751 buf.write_var(*delay); +752 buf.write_var(ranges.len() as u64 - 1); +753 buf.write_var(first_size - 1); +754 let mut prev = first.start; +755 for block in rest { +756 let size = block.end - block.start; +757 buf.write_var(prev - block.end - 1); +758 buf.write_var(size - 1); +759 prev = block.start; +760 } +761 if let Some(x) = ecn { +762 x.encode(buf) +763 } +764 } +765} +766 +767#[derive(Clone, Eq, PartialEq)] +768pub(crate) struct Ack { +769 pub largest: u64, +770 pub delay: u64, +771 pub additional: Bytes, +772 pub ecn: Option<EcnCounts>, +773} +774 +775impl fmt::Debug for Ack { +776 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +777 let mut ranges = "[".to_string(); +778 let mut first = true; +779 for range in self.iter() { +780 if !first { +781 ranges.push(','); +782 } +783 write!(ranges, "{range:?}").unwrap(); +784 first = false; +785 } +786 ranges.push(']'); +787 +788 f.debug_struct("Ack") +789 .field("largest", &self.largest) +790 .field("delay", &self.delay) +791 .field("ecn", &self.ecn) +792 .field("ranges", &ranges) +793 .finish() +794 } +795} 796 -797 fn into_iter(self) -> AckIter<'a> { -798 AckIter::new(self.largest, &self.additional[..]) -799 } -800} +797#[allow(unnameable_types)] +798impl<'a> IntoIterator for &'a Ack { +799 type Item = RangeInclusive<u64>; +800 type IntoIter = AckIter<'a>; 801 -802impl Ack { -803 pub(crate) fn encoder<'a>( -804 delay: u64, -805 ranges: &'a ArrayRangeSet, -806 ecn: Option<&'a EcnCounts>, -807 ) -> AckEncoder<'a> { -808 AckEncoder { delay, ranges, ecn } -809 } -810 -811 pub fn iter(&self) -> AckIter<'_> { -812 self.into_iter() -813 } -814} +802 fn into_iter(self) -> AckIter<'a> { +803 AckIter::new(self.largest, &self.additional[..]) +804 } +805} +806 +807impl Ack { +808 pub(crate) fn encoder<'a>( +809 delay: u64, +810 ranges: &'a ArrayRangeSet, +811 ecn: Option<&'a EcnCounts>, +812 ) -> AckEncoder<'a> { +813 AckEncoder { delay, ranges, ecn } +814 } 815 -816pub(crate) struct AckEncoder<'a> { -817 delay: u64, -818 ranges: &'a ArrayRangeSet, -819 ecn: Option<&'a EcnCounts>, -820} -821 -822impl<'a> Encodable for AckEncoder<'a> { -823 fn encode<W: BufMut>(&self, buf: &mut W) { -824 let AckEncoder { delay, ranges, ecn } = self; -825 let mut rest = ranges.iter().rev(); -826 let first = rest.next().unwrap(); -827 let largest = first.end - 1; -828 let first_size = first.end - first.start; -829 let kind = match ecn.is_some() { -830 true => FrameType::AckEcn, -831 false => FrameType::Ack, -832 }; -833 buf.write(kind); -834 buf.write_var(largest); -835 buf.write_var(*delay); -836 buf.write_var(ranges.len() as u64 - 1); -837 buf.write_var(first_size - 1); -838 let mut prev = first.start; -839 for block in rest { -840 let size = block.end - block.start; -841 buf.write_var(prev - block.end - 1); -842 buf.write_var(size - 1); -843 prev = block.start; -844 } -845 if let Some(x) = ecn { -846 x.encode(buf) -847 } -848 } -849} -850 -851#[derive(Debug, Copy, Clone, Eq, PartialEq)] -852pub struct EcnCounts { -853 pub ect0: u64, -854 pub ect1: u64, -855 pub ce: u64, -856} -857 -858impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { -859 fn add_assign(&mut self, rhs: EcnCodepoint) { -860 match rhs { -861 EcnCodepoint::Ect0 => { -862 self.ect0 += 1; -863 } -864 EcnCodepoint::Ect1 => { -865 self.ect1 += 1; -866 } -867 EcnCodepoint::Ce => { -868 self.ce += 1; -869 } -870 } -871 } -872} -873 -874impl EcnCounts { -875 pub const ZERO: Self = Self { -876 ect0: 0, -877 ect1: 0, -878 ce: 0, -879 }; -880} -881 -882impl Encodable for EcnCounts { -883 fn encode<W: BufMut>(&self, out: &mut W) { -884 out.write_var(self.ect0); -885 out.write_var(self.ect1); -886 out.write_var(self.ce); -887 } -888} -889 -890#[derive(Debug, Clone)] -891pub(crate) struct Stream { -892 pub(crate) id: StreamId, -893 pub(crate) offset: u64, -894 pub(crate) fin: bool, -895 pub(crate) data: Bytes, -896} -897 -898impl FrameStruct for Stream { -899 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -900} -901 -902/// Metadata from a stream frame -903#[derive(Debug, Clone)] -904pub(crate) struct StreamMeta { -905 pub(crate) id: StreamId, -906 pub(crate) offsets: Range<u64>, -907 pub(crate) fin: bool, -908} -909 -910// This manual implementation exists because `Default` is not implemented for `StreamId` -911impl Default for StreamMeta { -912 fn default() -> Self { -913 Self { -914 id: StreamId(0), -915 offsets: 0..0, -916 fin: false, -917 } -918 } -919} -920 -921impl StreamMeta { -922 pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> { -923 StreamMetaEncoder { -924 meta: self, -925 encode_length, -926 } -927 } -928} -929 -930pub(crate) struct StreamMetaEncoder<'a> { -931 meta: &'a StreamMeta, -932 encode_length: bool, +816 pub(crate) fn iter(&self) -> AckIter<'_> { +817 self.into_iter() +818 } +819} +820 +821pub(crate) struct AckEncoder<'a> { +822 delay: u64, +823 ranges: &'a ArrayRangeSet, +824 ecn: Option<&'a EcnCounts>, +825} +826 +827impl<'a> Encodable for AckEncoder<'a> { +828 fn encode<W: BufMut>(&self, buf: &mut W) { +829 let AckEncoder { delay, ranges, ecn } = self; +830 let mut rest = ranges.iter().rev(); +831 let first = rest.next().unwrap(); +832 let largest = first.end - 1; +833 let first_size = first.end - first.start; +834 let kind = match ecn.is_some() { +835 true => FrameType::AckEcn, +836 false => FrameType::Ack, +837 }; +838 buf.write(kind); +839 buf.write_var(largest); +840 buf.write_var(*delay); +841 buf.write_var(ranges.len() as u64 - 1); +842 buf.write_var(first_size - 1); +843 let mut prev = first.start; +844 for block in rest { +845 let size = block.end - block.start; +846 buf.write_var(prev - block.end - 1); +847 buf.write_var(size - 1); +848 prev = block.start; +849 } +850 if let Some(x) = ecn { +851 x.encode(buf) +852 } +853 } +854} +855 +856#[derive(Debug, Copy, Clone, Eq, PartialEq)] +857pub(crate) struct EcnCounts { +858 pub ect0: u64, +859 pub ect1: u64, +860 pub ce: u64, +861} +862 +863impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { +864 fn add_assign(&mut self, rhs: EcnCodepoint) { +865 match rhs { +866 EcnCodepoint::Ect0 => { +867 self.ect0 += 1; +868 } +869 EcnCodepoint::Ect1 => { +870 self.ect1 += 1; +871 } +872 EcnCodepoint::Ce => { +873 self.ce += 1; +874 } +875 } +876 } +877} +878 +879impl EcnCounts { +880 pub(crate) const ZERO: Self = Self { +881 ect0: 0, +882 ect1: 0, +883 ce: 0, +884 }; +885} +886 +887impl Encodable for EcnCounts { +888 fn encode<W: BufMut>(&self, out: &mut W) { +889 out.write_var(self.ect0); +890 out.write_var(self.ect1); +891 out.write_var(self.ce); +892 } +893} +894 +895#[derive(Debug, Clone)] +896pub(crate) struct Stream { +897 pub(crate) id: StreamId, +898 pub(crate) offset: u64, +899 pub(crate) fin: bool, +900 pub(crate) data: Bytes, +901} +902 +903impl FrameStruct for Stream { +904 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +905} +906 +907/// Metadata from a stream frame +908#[derive(Debug, Clone)] +909pub(crate) struct StreamMeta { +910 pub(crate) id: StreamId, +911 pub(crate) offsets: Range<u64>, +912 pub(crate) fin: bool, +913} +914 +915// This manual implementation exists because `Default` is not implemented for `StreamId` +916impl Default for StreamMeta { +917 fn default() -> Self { +918 Self { +919 id: StreamId(0), +920 offsets: 0..0, +921 fin: false, +922 } +923 } +924} +925 +926impl StreamMeta { +927 pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> { +928 StreamMetaEncoder { +929 meta: self, +930 encode_length, +931 } +932 } 933} 934 -935impl<'a> Encodable for StreamMetaEncoder<'a> { -936 fn encode<W: BufMut>(&self, out: &mut W) { -937 let StreamMetaEncoder { -938 meta, -939 encode_length: length, -940 } = self; -941 let mut ty = *StreamInfo::VALUES.start(); -942 if meta.offsets.start != 0 { -943 ty |= 0x04; -944 } -945 if *length { -946 ty |= 0x02; -947 } -948 if meta.fin { -949 ty |= 0x01; -950 } -951 out.write_var(ty); // 1 byte -952 out.write(meta.id); // <=8 bytes -953 if meta.offsets.start != 0 { -954 out.write_var(meta.offsets.start); // <=8 bytes -955 } -956 if *length { -957 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes -958 } -959 } -960} -961 -962/// A vector of [`StreamMeta`] with optimization for the single element case -963pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; -964 -965#[derive(Debug, Clone)] -966pub(crate) struct Crypto { -967 pub(crate) offset: u64, -968 pub(crate) data: Bytes, -969} -970 -971impl Crypto { -972 pub(crate) const SIZE_BOUND: usize = 17; -973} -974 -975impl Encodable for Crypto { -976 fn encode<W: BufMut>(&self, out: &mut W) { -977 out.write(FrameType::Crypto); -978 out.write_var(self.offset); -979 out.write_var(self.data.len() as u64); -980 out.put_slice(&self.data); -981 } -982} -983 -984#[derive(Debug, Clone)] -985pub(crate) struct NewToken { -986 pub(crate) token: Bytes, +935pub(crate) struct StreamMetaEncoder<'a> { +936 meta: &'a StreamMeta, +937 encode_length: bool, +938} +939 +940impl<'a> Encodable for StreamMetaEncoder<'a> { +941 fn encode<W: BufMut>(&self, out: &mut W) { +942 let StreamMetaEncoder { +943 meta, +944 encode_length: length, +945 } = self; +946 let mut ty = *StreamInfo::VALUES.start(); +947 if meta.offsets.start != 0 { +948 ty |= 0x04; +949 } +950 if *length { +951 ty |= 0x02; +952 } +953 if meta.fin { +954 ty |= 0x01; +955 } +956 out.write_var(ty); // 1 byte +957 out.write(meta.id); // <=8 bytes +958 if meta.offsets.start != 0 { +959 out.write_var(meta.offsets.start); // <=8 bytes +960 } +961 if *length { +962 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes +963 } +964 } +965} +966 +967/// A vector of [`StreamMeta`] with optimization for the single element case +968pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; +969 +970#[derive(Debug, Clone)] +971pub(crate) struct Crypto { +972 pub(crate) offset: u64, +973 pub(crate) data: Bytes, +974} +975 +976impl Crypto { +977 pub(crate) const SIZE_BOUND: usize = 17; +978} +979 +980impl Encodable for Crypto { +981 fn encode<W: BufMut>(&self, out: &mut W) { +982 out.write(FrameType::Crypto); +983 out.write_var(self.offset); +984 out.write_var(self.data.len() as u64); +985 out.put_slice(&self.data); +986 } 987} 988 -989impl Encodable for NewToken { -990 fn encode<W: BufMut>(&self, out: &mut W) { -991 out.write(FrameType::NewToken); -992 out.write_var(self.token.len() as u64); -993 out.put_slice(&self.token); -994 } -995} -996 -997impl NewToken { -998 pub(crate) fn size(&self) -> usize { -999 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() -1000 } -1001} -1002 -1003#[derive(Debug, Clone)] -1004pub(crate) struct MaxPathId(pub(crate) PathId); -1005 -1006impl MaxPathId { -1007 pub(crate) const SIZE_BOUND: usize = -1008 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); -1009} +989#[derive(Debug, Clone)] +990pub(crate) struct NewToken { +991 pub(crate) token: Bytes, +992} +993 +994impl Encodable for NewToken { +995 fn encode<W: BufMut>(&self, out: &mut W) { +996 out.write(FrameType::NewToken); +997 out.write_var(self.token.len() as u64); +998 out.put_slice(&self.token); +999 } +1000} +1001 +1002impl NewToken { +1003 pub(crate) fn size(&self) -> usize { +1004 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() +1005 } +1006} +1007 +1008#[derive(Debug, Clone)] +1009pub(crate) struct MaxPathId(pub(crate) PathId); 1010 -1011impl Decodable for MaxPathId { -1012 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -1013 Ok(Self(buf.get()?)) -1014 } -1015} -1016 -1017impl Encodable for MaxPathId { -1018 fn encode<B: BufMut>(&self, buf: &mut B) { -1019 buf.write(FrameType::MaxPathId); -1020 buf.write(self.0); -1021 } -1022} -1023 -1024#[derive(Debug, Clone, PartialEq, Eq)] -1025pub(crate) struct PathsBlocked(pub(crate) PathId); -1026 -1027impl PathsBlocked { -1028 pub(crate) const SIZE_BOUND: usize = -1029 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); -1030} +1011impl MaxPathId { +1012 pub(crate) const SIZE_BOUND: usize = +1013 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); +1014} +1015 +1016impl Decodable for MaxPathId { +1017 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1018 Ok(Self(buf.get()?)) +1019 } +1020} +1021 +1022impl Encodable for MaxPathId { +1023 fn encode<B: BufMut>(&self, buf: &mut B) { +1024 buf.write(FrameType::MaxPathId); +1025 buf.write(self.0); +1026 } +1027} +1028 +1029#[derive(Debug, Clone, PartialEq, Eq)] +1030pub(crate) struct PathsBlocked(pub(crate) PathId); 1031 -1032impl Encodable for PathsBlocked { -1033 fn encode<B: BufMut>(&self, buf: &mut B) { -1034 buf.write(FrameType::PathsBlocked); -1035 buf.write(self.0); -1036 } -1037} -1038 -1039impl Decodable for PathsBlocked { -1040 /// Decode [`Self`] from the buffer, provided that the frame type has been verified -1041 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -1042 Ok(Self(buf.get()?)) -1043 } -1044} -1045 -1046#[derive(Debug, Clone, PartialEq, Eq)] -1047pub(crate) struct PathCidsBlocked { -1048 pub(crate) path_id: PathId, -1049 pub(crate) next_seq: VarInt, -1050} -1051 -1052impl PathCidsBlocked { -1053 pub(crate) const SIZE_BOUND: usize = -1054 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); +1032impl PathsBlocked { +1033 pub(crate) const SIZE_BOUND: usize = +1034 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); +1035} +1036 +1037impl Encodable for PathsBlocked { +1038 fn encode<B: BufMut>(&self, buf: &mut B) { +1039 buf.write(FrameType::PathsBlocked); +1040 buf.write(self.0); +1041 } +1042} +1043 +1044impl Decodable for PathsBlocked { +1045 /// Decode [`Self`] from the buffer, provided that the frame type has been verified +1046 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1047 Ok(Self(buf.get()?)) +1048 } +1049} +1050 +1051#[derive(Debug, Clone, PartialEq, Eq)] +1052pub(crate) struct PathCidsBlocked { +1053 pub(crate) path_id: PathId, +1054 pub(crate) next_seq: VarInt, 1055} 1056 -1057impl Decodable for PathCidsBlocked { -1058 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { -1059 Ok(Self { -1060 path_id: buf.get()?, -1061 next_seq: buf.get()?, -1062 }) -1063 } -1064} -1065 -1066impl Encodable for PathCidsBlocked { -1067 fn encode<W: BufMut>(&self, buf: &mut W) { -1068 buf.write(FrameType::PathCidsBlocked); -1069 buf.write(self.path_id); -1070 buf.write(self.next_seq); -1071 } -1072} -1073 -1074pub(crate) struct Iter { -1075 bytes: Bytes, -1076 last_ty: MaybeFrame, +1057impl PathCidsBlocked { +1058 pub(crate) const SIZE_BOUND: usize = +1059 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); +1060} +1061 +1062impl Decodable for PathCidsBlocked { +1063 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { +1064 Ok(Self { +1065 path_id: buf.get()?, +1066 next_seq: buf.get()?, +1067 }) +1068 } +1069} +1070 +1071impl Encodable for PathCidsBlocked { +1072 fn encode<W: BufMut>(&self, buf: &mut W) { +1073 buf.write(FrameType::PathCidsBlocked); +1074 buf.write(self.path_id); +1075 buf.write(self.next_seq); +1076 } 1077} 1078 -1079impl Iter { -1080 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { -1081 if payload.is_empty() { -1082 // "An endpoint MUST treat receipt of a packet containing no frames as a -1083 // connection error of type PROTOCOL_VIOLATION." -1084 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types -1085 return Err(TransportError::PROTOCOL_VIOLATION( -1086 "packet payload is empty", -1087 )); -1088 } -1089 -1090 Ok(Self { -1091 bytes: payload, -1092 last_ty: MaybeFrame::None, -1093 }) -1094 } -1095 -1096 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { -1097 let len = self.bytes.get_var()?; -1098 if len > self.bytes.remaining() as u64 { -1099 return Err(UnexpectedEnd); -1100 } -1101 Ok(self.bytes.split_to(len as usize)) -1102 } -1103 -1104 #[track_caller] -1105 fn try_next(&mut self) -> Result<Frame, IterErr> { -1106 self.last_ty = self.bytes.get()?; -1107 -1108 let ty = match self.last_ty { -1109 MaybeFrame::None => FrameType::Padding, -1110 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), -1111 MaybeFrame::Known(frame_type) => frame_type, -1112 }; -1113 Ok(match ty { -1114 FrameType::Padding => Frame::Padding, -1115 FrameType::ResetStream => Frame::ResetStream(ResetStream { -1116 id: self.bytes.get()?, -1117 error_code: self.bytes.get()?, -1118 final_offset: self.bytes.get()?, -1119 }), -1120 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { -1121 error_code: self.bytes.get()?, -1122 frame_type: self.bytes.get()?, -1123 reason: self.take_len()?, -1124 })), -1125 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { +1079pub(crate) struct Iter { +1080 bytes: Bytes, +1081 last_ty: MaybeFrame, +1082} +1083 +1084impl Iter { +1085 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { +1086 if payload.is_empty() { +1087 // "An endpoint MUST treat receipt of a packet containing no frames as a +1088 // connection error of type PROTOCOL_VIOLATION." +1089 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types +1090 return Err(TransportError::PROTOCOL_VIOLATION( +1091 "packet payload is empty", +1092 )); +1093 } +1094 +1095 Ok(Self { +1096 bytes: payload, +1097 last_ty: MaybeFrame::None, +1098 }) +1099 } +1100 +1101 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { +1102 let len = self.bytes.get_var()?; +1103 if len > self.bytes.remaining() as u64 { +1104 return Err(UnexpectedEnd); +1105 } +1106 Ok(self.bytes.split_to(len as usize)) +1107 } +1108 +1109 #[track_caller] +1110 fn try_next(&mut self) -> Result<Frame, IterErr> { +1111 self.last_ty = self.bytes.get()?; +1112 +1113 let ty = match self.last_ty { +1114 MaybeFrame::None => FrameType::Padding, +1115 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), +1116 MaybeFrame::Known(frame_type) => frame_type, +1117 }; +1118 Ok(match ty { +1119 FrameType::Padding => Frame::Padding, +1120 FrameType::ResetStream => Frame::ResetStream(ResetStream { +1121 id: self.bytes.get()?, +1122 error_code: self.bytes.get()?, +1123 final_offset: self.bytes.get()?, +1124 }), +1125 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { 1126 error_code: self.bytes.get()?, -1127 reason: self.take_len()?, -1128 })), -1129 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), -1130 FrameType::MaxStreamData => Frame::MaxStreamData { -1131 id: self.bytes.get()?, -1132 offset: self.bytes.get_var()?, -1133 }, -1134 FrameType::MaxStreamsBidi => Frame::MaxStreams { -1135 dir: Dir::Bi, -1136 count: self.bytes.get_var()?, -1137 }, -1138 FrameType::MaxStreamsUni => Frame::MaxStreams { -1139 dir: Dir::Uni, -1140 count: self.bytes.get_var()?, -1141 }, -1142 FrameType::Ping => Frame::Ping, -1143 FrameType::DataBlocked => Frame::DataBlocked { -1144 offset: self.bytes.get_var()?, -1145 }, -1146 FrameType::StreamDataBlocked => Frame::StreamDataBlocked { -1147 id: self.bytes.get()?, -1148 offset: self.bytes.get_var()?, -1149 }, -1150 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked { -1151 dir: Dir::Bi, -1152 limit: self.bytes.get_var()?, -1153 }, -1154 FrameType::StreamsBlockedUni => Frame::StreamsBlocked { -1155 dir: Dir::Uni, -1156 limit: self.bytes.get_var()?, -1157 }, -1158 FrameType::StopSending => Frame::StopSending(StopSending { -1159 id: self.bytes.get()?, -1160 error_code: self.bytes.get()?, -1161 }), -1162 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { -1163 Frame::RetireConnectionId(RetireConnectionId::decode( -1164 &mut self.bytes, -1165 ty == FrameType::PathRetireConnectionId, -1166 )?) -1167 } -1168 FrameType::Ack | FrameType::AckEcn => { -1169 let largest = self.bytes.get_var()?; -1170 let delay = self.bytes.get_var()?; -1171 let extra_blocks = self.bytes.get_var()? as usize; -1172 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; -1173 Frame::Ack(Ack { -1174 delay, -1175 largest, -1176 additional: self.bytes.split_to(n), -1177 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { -1178 None -1179 } else { -1180 Some(EcnCounts { -1181 ect0: self.bytes.get_var()?, -1182 ect1: self.bytes.get_var()?, -1183 ce: self.bytes.get_var()?, -1184 }) -1185 }, -1186 }) -1187 } -1188 FrameType::PathAck | FrameType::PathAckEcn => { -1189 let path_id = self.bytes.get()?; -1190 let largest = self.bytes.get_var()?; -1191 let delay = self.bytes.get_var()?; -1192 let extra_blocks = self.bytes.get_var()? as usize; -1193 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; -1194 Frame::PathAck(PathAck { -1195 path_id, -1196 delay, -1197 largest, -1198 additional: self.bytes.split_to(n), -1199 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { -1200 None -1201 } else { -1202 Some(EcnCounts { -1203 ect0: self.bytes.get_var()?, -1204 ect1: self.bytes.get_var()?, -1205 ce: self.bytes.get_var()?, -1206 }) -1207 }, -1208 }) -1209 } -1210 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), -1211 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), -1212 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { -1213 let read_path = ty == FrameType::PathNewConnectionId; -1214 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) -1215 } -1216 FrameType::Crypto => Frame::Crypto(Crypto { -1217 offset: self.bytes.get_var()?, -1218 data: self.take_len()?, -1219 }), -1220 FrameType::NewToken => Frame::NewToken(NewToken { -1221 token: self.take_len()?, -1222 }), -1223 FrameType::HandshakeDone => Frame::HandshakeDone, -1224 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { -1225 sequence: self.bytes.get()?, -1226 ack_eliciting_threshold: self.bytes.get()?, -1227 request_max_ack_delay: self.bytes.get()?, -1228 reordering_threshold: self.bytes.get()?, -1229 }), -1230 FrameType::ImmediateAck => Frame::ImmediateAck, -1231 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { -1232 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; -1233 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; -1234 Frame::ObservedAddr(observed) -1235 } -1236 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), -1237 FrameType::PathStatusAvailable => { -1238 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) -1239 } -1240 FrameType::PathStatusBackup => { -1241 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) -1242 } -1243 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), -1244 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), -1245 FrameType::PathCidsBlocked => { -1246 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) +1127 frame_type: self.bytes.get()?, +1128 reason: self.take_len()?, +1129 })), +1130 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { +1131 error_code: self.bytes.get()?, +1132 reason: self.take_len()?, +1133 })), +1134 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), +1135 FrameType::MaxStreamData => Frame::MaxStreamData { +1136 id: self.bytes.get()?, +1137 offset: self.bytes.get_var()?, +1138 }, +1139 FrameType::MaxStreamsBidi => Frame::MaxStreams { +1140 dir: Dir::Bi, +1141 count: self.bytes.get_var()?, +1142 }, +1143 FrameType::MaxStreamsUni => Frame::MaxStreams { +1144 dir: Dir::Uni, +1145 count: self.bytes.get_var()?, +1146 }, +1147 FrameType::Ping => Frame::Ping, +1148 FrameType::DataBlocked => Frame::DataBlocked { +1149 offset: self.bytes.get_var()?, +1150 }, +1151 FrameType::StreamDataBlocked => Frame::StreamDataBlocked { +1152 id: self.bytes.get()?, +1153 offset: self.bytes.get_var()?, +1154 }, +1155 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked { +1156 dir: Dir::Bi, +1157 limit: self.bytes.get_var()?, +1158 }, +1159 FrameType::StreamsBlockedUni => Frame::StreamsBlocked { +1160 dir: Dir::Uni, +1161 limit: self.bytes.get_var()?, +1162 }, +1163 FrameType::StopSending => Frame::StopSending(StopSending { +1164 id: self.bytes.get()?, +1165 error_code: self.bytes.get()?, +1166 }), +1167 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { +1168 Frame::RetireConnectionId(RetireConnectionId::decode( +1169 &mut self.bytes, +1170 ty == FrameType::PathRetireConnectionId, +1171 )?) +1172 } +1173 FrameType::Ack | FrameType::AckEcn => { +1174 let largest = self.bytes.get_var()?; +1175 let delay = self.bytes.get_var()?; +1176 let extra_blocks = self.bytes.get_var()? as usize; +1177 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; +1178 Frame::Ack(Ack { +1179 delay, +1180 largest, +1181 additional: self.bytes.split_to(n), +1182 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { +1183 None +1184 } else { +1185 Some(EcnCounts { +1186 ect0: self.bytes.get_var()?, +1187 ect1: self.bytes.get_var()?, +1188 ce: self.bytes.get_var()?, +1189 }) +1190 }, +1191 }) +1192 } +1193 FrameType::PathAck | FrameType::PathAckEcn => { +1194 let path_id = self.bytes.get()?; +1195 let largest = self.bytes.get_var()?; +1196 let delay = self.bytes.get_var()?; +1197 let extra_blocks = self.bytes.get_var()? as usize; +1198 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; +1199 Frame::PathAck(PathAck { +1200 path_id, +1201 delay, +1202 largest, +1203 additional: self.bytes.split_to(n), +1204 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { +1205 None +1206 } else { +1207 Some(EcnCounts { +1208 ect0: self.bytes.get_var()?, +1209 ect1: self.bytes.get_var()?, +1210 ce: self.bytes.get_var()?, +1211 }) +1212 }, +1213 }) +1214 } +1215 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), +1216 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), +1217 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { +1218 let read_path = ty == FrameType::PathNewConnectionId; +1219 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) +1220 } +1221 FrameType::Crypto => Frame::Crypto(Crypto { +1222 offset: self.bytes.get_var()?, +1223 data: self.take_len()?, +1224 }), +1225 FrameType::NewToken => Frame::NewToken(NewToken { +1226 token: self.take_len()?, +1227 }), +1228 FrameType::HandshakeDone => Frame::HandshakeDone, +1229 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { +1230 sequence: self.bytes.get()?, +1231 ack_eliciting_threshold: self.bytes.get()?, +1232 request_max_ack_delay: self.bytes.get()?, +1233 reordering_threshold: self.bytes.get()?, +1234 }), +1235 FrameType::ImmediateAck => Frame::ImmediateAck, +1236 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { +1237 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; +1238 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; +1239 Frame::ObservedAddr(observed) +1240 } +1241 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), +1242 FrameType::PathStatusAvailable => { +1243 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) +1244 } +1245 FrameType::PathStatusBackup => { +1246 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) 1247 } -1248 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { -1249 let is_ipv6 = ty == FrameType::AddIpv6Address; -1250 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; -1251 Frame::AddAddress(add_address) +1248 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), +1249 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), +1250 FrameType::PathCidsBlocked => { +1251 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) 1252 } -1253 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { -1254 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; -1255 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; -1256 Frame::ReachOut(reach_out) +1253 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { +1254 let is_ipv6 = ty == FrameType::AddIpv6Address; +1255 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; +1256 Frame::AddAddress(add_address) 1257 } -1258 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), -1259 FrameType::Stream(s) => Frame::Stream(Stream { -1260 id: self.bytes.get()?, -1261 offset: if s.off() { self.bytes.get_var()? } else { 0 }, -1262 fin: s.fin(), -1263 data: if s.len() { -1264 self.take_len()? -1265 } else { -1266 self.take_remaining() -1267 }, -1268 }), -1269 FrameType::Datagram(d) => Frame::Datagram(Datagram { -1270 data: if d.len() { -1271 self.take_len()? -1272 } else { -1273 self.take_remaining() -1274 }, -1275 }), -1276 }) -1277 } -1278 -1279 fn take_remaining(&mut self) -> Bytes { -1280 mem::take(&mut self.bytes) -1281 } -1282} +1258 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { +1259 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; +1260 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; +1261 Frame::ReachOut(reach_out) +1262 } +1263 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), +1264 FrameType::Stream(s) => Frame::Stream(Stream { +1265 id: self.bytes.get()?, +1266 offset: if s.off() { self.bytes.get_var()? } else { 0 }, +1267 fin: s.fin(), +1268 data: if s.len() { +1269 self.take_len()? +1270 } else { +1271 self.take_remaining() +1272 }, +1273 }), +1274 FrameType::Datagram(d) => Frame::Datagram(Datagram { +1275 data: if d.len() { +1276 self.take_len()? +1277 } else { +1278 self.take_remaining() +1279 }, +1280 }), +1281 }) +1282 } 1283 -1284impl Iterator for Iter { -1285 type Item = Result<Frame, InvalidFrame>; -1286 fn next(&mut self) -> Option<Self::Item> { -1287 if !self.bytes.has_remaining() { -1288 return None; -1289 } -1290 match self.try_next() { -1291 Ok(x) => Some(Ok(x)), -1292 Err(e) => { -1293 // Corrupt frame, skip it and everything that follows -1294 self.bytes.clear(); -1295 Some(Err(InvalidFrame { -1296 ty: self.last_ty, -1297 reason: e.reason(), -1298 })) -1299 } -1300 } -1301 } -1302} -1303 -1304#[derive(Debug)] -1305pub(crate) struct InvalidFrame { -1306 pub(crate) ty: MaybeFrame, -1307 pub(crate) reason: &'static str, -1308} -1309 -1310impl From<InvalidFrame> for TransportError { -1311 fn from(err: InvalidFrame) -> Self { -1312 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); -1313 te.frame = err.ty; -1314 te -1315 } -1316} -1317 -1318/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover -1319fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> { -1320 let total_len = buf.remaining(); -1321 let first_block = buf.get_var()?; -1322 let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?; -1323 for _ in 0..n { -1324 let gap = buf.get_var()?; -1325 smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?; -1326 let block = buf.get_var()?; -1327 smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?; -1328 } -1329 Ok(total_len - buf.remaining()) -1330} -1331 -1332#[derive(Debug)] -1333enum IterErr { -1334 UnexpectedEnd, -1335 InvalidFrameId, -1336 Malformed, -1337} -1338 -1339impl IterErr { -1340 fn reason(&self) -> &'static str { -1341 use IterErr::*; -1342 match *self { -1343 UnexpectedEnd => "unexpected end", -1344 InvalidFrameId => "invalid frame ID", -1345 Malformed => "malformed", -1346 } -1347 } -1348} -1349 -1350impl From<UnexpectedEnd> for IterErr { -1351 fn from(_: UnexpectedEnd) -> Self { -1352 Self::UnexpectedEnd -1353 } -1354} -1355 -1356#[derive(Debug, Clone)] -1357pub struct AckIter<'a> { -1358 largest: u64, -1359 data: &'a [u8], -1360} -1361 -1362impl<'a> AckIter<'a> { -1363 fn new(largest: u64, data: &'a [u8]) -> Self { -1364 Self { largest, data } -1365 } -1366} -1367 -1368impl Iterator for AckIter<'_> { -1369 type Item = RangeInclusive<u64>; -1370 fn next(&mut self) -> Option<RangeInclusive<u64>> { -1371 if !self.data.has_remaining() { -1372 return None; -1373 } -1374 let block = self.data.get_var().unwrap(); -1375 let largest = self.largest; -1376 if let Ok(gap) = self.data.get_var() { -1377 self.largest -= block + gap + 2; +1284 fn take_remaining(&mut self) -> Bytes { +1285 mem::take(&mut self.bytes) +1286 } +1287} +1288 +1289impl Iterator for Iter { +1290 type Item = Result<Frame, InvalidFrame>; +1291 fn next(&mut self) -> Option<Self::Item> { +1292 if !self.bytes.has_remaining() { +1293 return None; +1294 } +1295 match self.try_next() { +1296 Ok(x) => Some(Ok(x)), +1297 Err(e) => { +1298 // Corrupt frame, skip it and everything that follows +1299 self.bytes.clear(); +1300 Some(Err(InvalidFrame { +1301 ty: self.last_ty, +1302 reason: e.reason(), +1303 })) +1304 } +1305 } +1306 } +1307} +1308 +1309#[derive(Debug)] +1310pub(crate) struct InvalidFrame { +1311 pub(crate) ty: MaybeFrame, +1312 pub(crate) reason: &'static str, +1313} +1314 +1315impl From<InvalidFrame> for TransportError { +1316 fn from(err: InvalidFrame) -> Self { +1317 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); +1318 te.frame = err.ty; +1319 te +1320 } +1321} +1322 +1323/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover +1324fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> { +1325 let total_len = buf.remaining(); +1326 let first_block = buf.get_var()?; +1327 let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?; +1328 for _ in 0..n { +1329 let gap = buf.get_var()?; +1330 smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?; +1331 let block = buf.get_var()?; +1332 smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?; +1333 } +1334 Ok(total_len - buf.remaining()) +1335} +1336 +1337#[derive(Debug)] +1338enum IterErr { +1339 UnexpectedEnd, +1340 InvalidFrameId, +1341 Malformed, +1342} +1343 +1344impl IterErr { +1345 fn reason(&self) -> &'static str { +1346 use IterErr::*; +1347 match *self { +1348 UnexpectedEnd => "unexpected end", +1349 InvalidFrameId => "invalid frame ID", +1350 Malformed => "malformed", +1351 } +1352 } +1353} +1354 +1355impl From<UnexpectedEnd> for IterErr { +1356 fn from(_: UnexpectedEnd) -> Self { +1357 Self::UnexpectedEnd +1358 } +1359} +1360 +1361#[derive(Debug, Clone)] +1362pub(crate) struct AckIter<'a> { +1363 largest: u64, +1364 data: &'a [u8], +1365} +1366 +1367impl<'a> AckIter<'a> { +1368 fn new(largest: u64, data: &'a [u8]) -> Self { +1369 Self { largest, data } +1370 } +1371} +1372 +1373impl Iterator for AckIter<'_> { +1374 type Item = RangeInclusive<u64>; +1375 fn next(&mut self) -> Option<RangeInclusive<u64>> { +1376 if !self.data.has_remaining() { +1377 return None; 1378 } -1379 Some(largest - block..=largest) -1380 } -1381} -1382 -1383#[allow(unreachable_pub)] // fuzzing only -1384#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] -1385#[derive(Debug, Copy, Clone)] -1386pub struct ResetStream { -1387 pub(crate) id: StreamId, -1388 pub(crate) error_code: VarInt, -1389 pub(crate) final_offset: VarInt, -1390} -1391 -1392impl FrameStruct for ResetStream { -1393 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -1394} -1395 -1396impl Encodable for ResetStream { -1397 fn encode<W: BufMut>(&self, out: &mut W) { -1398 out.write(FrameType::ResetStream); // 1 byte -1399 out.write(self.id); // <= 8 bytes -1400 out.write(self.error_code); // <= 8 bytes -1401 out.write(self.final_offset); // <= 8 bytes -1402 } -1403} -1404 -1405#[derive(Debug, Copy, Clone)] -1406pub(crate) struct StopSending { -1407 pub(crate) id: StreamId, -1408 pub(crate) error_code: VarInt, -1409} -1410 -1411impl FrameStruct for StopSending { -1412 const SIZE_BOUND: usize = 1 + 8 + 8; -1413} -1414 -1415impl Encodable for StopSending { -1416 fn encode<W: BufMut>(&self, out: &mut W) { -1417 out.write(FrameType::StopSending); // 1 byte -1418 out.write(self.id); // <= 8 bytes -1419 out.write(self.error_code) // <= 8 bytes -1420 } -1421} -1422 -1423#[derive(Debug, Copy, Clone, PartialEq, Eq)] -1424pub(crate) struct NewConnectionId { -1425 pub(crate) path_id: Option<PathId>, -1426 pub(crate) sequence: u64, -1427 pub(crate) retire_prior_to: u64, -1428 pub(crate) id: ConnectionId, -1429 pub(crate) reset_token: ResetToken, -1430} -1431 -1432impl NewConnectionId { -1433 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], -1434 pub(crate) const SIZE_BOUND: usize = { -1435 let type_len = FrameType::NewConnectionId.size(); -1436 let seq_max_len = 8usize; -1437 let retire_prior_to_max_len = 8usize; -1438 let cid_len_len = 1; -1439 let cid_len = 160; -1440 let reset_token_len = 16; -1441 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len -1442 }; -1443 -1444 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], -1445 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { -1446 let type_len = FrameType::PathNewConnectionId.size(); -1447 let path_id_len = VarInt::from_u32(u32::MAX).size(); -1448 let seq_max_len = 8usize; -1449 let retire_prior_to_max_len = 8usize; -1450 let cid_len_len = 1; -1451 let cid_len = 160; -1452 let reset_token_len = 16; -1453 type_len -1454 + path_id_len -1455 + seq_max_len -1456 + retire_prior_to_max_len -1457 + cid_len_len -1458 + cid_len -1459 + reset_token_len -1460 }; -1461 -1462 pub(crate) fn get_type(&self) -> FrameType { -1463 if self.path_id.is_some() { -1464 FrameType::PathNewConnectionId -1465 } else { -1466 FrameType::NewConnectionId -1467 } -1468 } -1469 -1470 /// Returns the maximum encoded size on the wire. -1471 /// -1472 /// This is a rough upper estimate, does not squeeze every last byte out. -1473 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { -1474 let upper_bound = match path_new_cid { -1475 true => Self::SIZE_BOUND_MULTIPATH, -1476 false => Self::SIZE_BOUND, -1477 }; -1478 // instead of using the maximum cid len, use the provided one -1479 upper_bound - 160 + cid_len -1480 } -1481 -1482 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { -1483 let path_id = if read_path { Some(bytes.get()?) } else { None }; -1484 let sequence = bytes.get_var()?; -1485 let retire_prior_to = bytes.get_var()?; -1486 if retire_prior_to > sequence { -1487 return Err(IterErr::Malformed); -1488 } -1489 let length = bytes.get::<u8>()? as usize; -1490 if length > MAX_CID_SIZE || length == 0 { -1491 return Err(IterErr::Malformed); -1492 } -1493 if length > bytes.remaining() { -1494 return Err(IterErr::UnexpectedEnd); -1495 } -1496 let mut stage = [0; MAX_CID_SIZE]; -1497 bytes.copy_to_slice(&mut stage[0..length]); -1498 let id = ConnectionId::new(&stage[..length]); -1499 if bytes.remaining() < 16 { -1500 return Err(IterErr::UnexpectedEnd); -1501 } -1502 let mut reset_token = [0; RESET_TOKEN_SIZE]; -1503 bytes.copy_to_slice(&mut reset_token); -1504 Ok(Self { -1505 path_id, -1506 sequence, -1507 retire_prior_to, -1508 id, -1509 reset_token: reset_token.into(), -1510 }) -1511 } -1512} -1513 -1514impl Encodable for NewConnectionId { -1515 fn encode<W: BufMut>(&self, out: &mut W) { -1516 out.write(self.get_type()); -1517 if let Some(id) = self.path_id { -1518 out.write(id); -1519 } -1520 out.write_var(self.sequence); -1521 out.write_var(self.retire_prior_to); -1522 out.write(self.id.len() as u8); -1523 out.put_slice(&self.id); -1524 out.put_slice(&self.reset_token); -1525 } -1526} -1527 -1528impl FrameStruct for NewConnectionId { -1529 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; -1530} -1531 -1532/// An unreliable datagram -1533#[derive(Debug, Clone)] -1534pub struct Datagram { -1535 /// Payload -1536 pub data: Bytes, -1537} -1538 -1539impl FrameStruct for Datagram { -1540 const SIZE_BOUND: usize = 1 + 8; -1541} -1542 -1543impl Datagram { -1544 pub(crate) fn size(&self, length: bool) -> usize { -1545 1 + if length { -1546 VarInt::from_u64(self.data.len() as u64).unwrap().size() -1547 } else { -1548 0 -1549 } + self.data.len() -1550 } -1551} -1552 -1553impl Encodable for Datagram { -1554 fn encode<B: BufMut>(&self, out: &mut B) { -1555 // A datagram is encoded only after this is verified. -1556 const ENCODE_LEN: bool = true; -1557 out.write(FrameType::Datagram(DatagramInfo( -1558 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), -1559 ))); // 1 byte -1560 // Safe to unwrap because we check length sanity before queueing datagrams -1561 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes -1562 out.put_slice(&self.data); -1563 } -1564} -1565 -1566#[derive(Debug, Copy, Clone, PartialEq, Eq)] -1567pub(crate) struct AckFrequency { -1568 pub(crate) sequence: VarInt, -1569 pub(crate) ack_eliciting_threshold: VarInt, -1570 pub(crate) request_max_ack_delay: VarInt, -1571 pub(crate) reordering_threshold: VarInt, -1572} -1573 -1574impl Encodable for AckFrequency { -1575 fn encode<W: BufMut>(&self, buf: &mut W) { -1576 buf.write(FrameType::AckFrequency); -1577 buf.write(self.sequence); -1578 buf.write(self.ack_eliciting_threshold); -1579 buf.write(self.request_max_ack_delay); -1580 buf.write(self.reordering_threshold); -1581 } -1582} -1583 -1584/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ -1585 -1586/// Conjunction of the information contained in the address discovery frames -1587/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). -1588#[derive(Debug, PartialEq, Eq, Clone)] -1589pub(crate) struct ObservedAddr { -1590 /// Monotonically increasing integer within the same connection. -1591 pub(crate) seq_no: VarInt, -1592 /// Reported observed address. -1593 pub(crate) ip: IpAddr, -1594 /// Reported observed port. -1595 pub(crate) port: u16, -1596} -1597 -1598impl ObservedAddr { -1599 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { -1600 Self { -1601 ip: remote.ip(), -1602 port: remote.port(), -1603 seq_no: seq_no.into(), -1604 } -1605 } -1606 -1607 /// Get the [`FrameType`] for this frame. -1608 pub(crate) fn get_type(&self) -> FrameType { -1609 if self.ip.is_ipv6() { -1610 FrameType::ObservedIpv6Addr -1611 } else { -1612 FrameType::ObservedIpv4Addr -1613 } -1614 } -1615 -1616 /// Compute the number of bytes needed to encode the frame. -1617 pub(crate) fn size(&self) -> usize { -1618 let type_size = self.get_type().size(); -1619 let req_id_bytes = self.seq_no.size(); -1620 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1621 let port_bytes = 2; -1622 type_size + req_id_bytes + ip_bytes + port_bytes -1623 } -1624 -1625 /// Reads the frame contents from the buffer. -1626 /// -1627 /// Should only be called when the frame type has been identified as -1628 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. -1629 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1630 let seq_no = bytes.get()?; -1631 let ip = if is_ipv6 { -1632 IpAddr::V6(bytes.get()?) -1633 } else { -1634 IpAddr::V4(bytes.get()?) -1635 }; -1636 let port = bytes.get()?; -1637 Ok(Self { seq_no, ip, port }) -1638 } -1639 -1640 /// Gives the [`SocketAddr`] reported in the frame. -1641 pub(crate) fn socket_addr(&self) -> SocketAddr { -1642 (self.ip, self.port).into() +1379 let block = self.data.get_var().unwrap(); +1380 let largest = self.largest; +1381 if let Ok(gap) = self.data.get_var() { +1382 self.largest -= block + gap + 2; +1383 } +1384 Some(largest - block..=largest) +1385 } +1386} +1387 +1388#[allow(unreachable_pub)] // fuzzing only +1389#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +1390#[derive(Debug, Copy, Clone)] +1391pub struct ResetStream { +1392 pub(crate) id: StreamId, +1393 pub(crate) error_code: VarInt, +1394 pub(crate) final_offset: VarInt, +1395} +1396 +1397impl FrameStruct for ResetStream { +1398 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +1399} +1400 +1401impl Encodable for ResetStream { +1402 fn encode<W: BufMut>(&self, out: &mut W) { +1403 out.write(FrameType::ResetStream); // 1 byte +1404 out.write(self.id); // <= 8 bytes +1405 out.write(self.error_code); // <= 8 bytes +1406 out.write(self.final_offset); // <= 8 bytes +1407 } +1408} +1409 +1410#[derive(Debug, Copy, Clone)] +1411pub(crate) struct StopSending { +1412 pub(crate) id: StreamId, +1413 pub(crate) error_code: VarInt, +1414} +1415 +1416impl FrameStruct for StopSending { +1417 const SIZE_BOUND: usize = 1 + 8 + 8; +1418} +1419 +1420impl Encodable for StopSending { +1421 fn encode<W: BufMut>(&self, out: &mut W) { +1422 out.write(FrameType::StopSending); // 1 byte +1423 out.write(self.id); // <= 8 bytes +1424 out.write(self.error_code) // <= 8 bytes +1425 } +1426} +1427 +1428#[derive(Debug, Copy, Clone, PartialEq, Eq)] +1429pub(crate) struct NewConnectionId { +1430 pub(crate) path_id: Option<PathId>, +1431 pub(crate) sequence: u64, +1432 pub(crate) retire_prior_to: u64, +1433 pub(crate) id: ConnectionId, +1434 pub(crate) reset_token: ResetToken, +1435} +1436 +1437impl NewConnectionId { +1438 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], +1439 pub(crate) const SIZE_BOUND: usize = { +1440 let type_len = FrameType::NewConnectionId.size(); +1441 let seq_max_len = 8usize; +1442 let retire_prior_to_max_len = 8usize; +1443 let cid_len_len = 1; +1444 let cid_len = 160; +1445 let reset_token_len = 16; +1446 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len +1447 }; +1448 +1449 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], +1450 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { +1451 let type_len = FrameType::PathNewConnectionId.size(); +1452 let path_id_len = VarInt::from_u32(u32::MAX).size(); +1453 let seq_max_len = 8usize; +1454 let retire_prior_to_max_len = 8usize; +1455 let cid_len_len = 1; +1456 let cid_len = 160; +1457 let reset_token_len = 16; +1458 type_len +1459 + path_id_len +1460 + seq_max_len +1461 + retire_prior_to_max_len +1462 + cid_len_len +1463 + cid_len +1464 + reset_token_len +1465 }; +1466 +1467 pub(crate) fn get_type(&self) -> FrameType { +1468 if self.path_id.is_some() { +1469 FrameType::PathNewConnectionId +1470 } else { +1471 FrameType::NewConnectionId +1472 } +1473 } +1474 +1475 /// Returns the maximum encoded size on the wire. +1476 /// +1477 /// This is a rough upper estimate, does not squeeze every last byte out. +1478 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { +1479 let upper_bound = match path_new_cid { +1480 true => Self::SIZE_BOUND_MULTIPATH, +1481 false => Self::SIZE_BOUND, +1482 }; +1483 // instead of using the maximum cid len, use the provided one +1484 upper_bound - 160 + cid_len +1485 } +1486 +1487 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { +1488 let path_id = if read_path { Some(bytes.get()?) } else { None }; +1489 let sequence = bytes.get_var()?; +1490 let retire_prior_to = bytes.get_var()?; +1491 if retire_prior_to > sequence { +1492 return Err(IterErr::Malformed); +1493 } +1494 let length = bytes.get::<u8>()? as usize; +1495 if length > MAX_CID_SIZE || length == 0 { +1496 return Err(IterErr::Malformed); +1497 } +1498 if length > bytes.remaining() { +1499 return Err(IterErr::UnexpectedEnd); +1500 } +1501 let mut stage = [0; MAX_CID_SIZE]; +1502 bytes.copy_to_slice(&mut stage[0..length]); +1503 let id = ConnectionId::new(&stage[..length]); +1504 if bytes.remaining() < 16 { +1505 return Err(IterErr::UnexpectedEnd); +1506 } +1507 let mut reset_token = [0; RESET_TOKEN_SIZE]; +1508 bytes.copy_to_slice(&mut reset_token); +1509 Ok(Self { +1510 path_id, +1511 sequence, +1512 retire_prior_to, +1513 id, +1514 reset_token: reset_token.into(), +1515 }) +1516 } +1517} +1518 +1519impl Encodable for NewConnectionId { +1520 fn encode<W: BufMut>(&self, out: &mut W) { +1521 out.write(self.get_type()); +1522 if let Some(id) = self.path_id { +1523 out.write(id); +1524 } +1525 out.write_var(self.sequence); +1526 out.write_var(self.retire_prior_to); +1527 out.write(self.id.len() as u8); +1528 out.put_slice(&self.id); +1529 out.put_slice(&self.reset_token); +1530 } +1531} +1532 +1533impl FrameStruct for NewConnectionId { +1534 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; +1535} +1536 +1537/// An unreliable datagram +1538#[derive(Debug, Clone)] +1539pub struct Datagram { +1540 /// Payload +1541 pub data: Bytes, +1542} +1543 +1544impl FrameStruct for Datagram { +1545 const SIZE_BOUND: usize = 1 + 8; +1546} +1547 +1548impl Datagram { +1549 pub(crate) fn size(&self, length: bool) -> usize { +1550 1 + if length { +1551 VarInt::from_u64(self.data.len() as u64).unwrap().size() +1552 } else { +1553 0 +1554 } + self.data.len() +1555 } +1556} +1557 +1558impl Encodable for Datagram { +1559 fn encode<B: BufMut>(&self, out: &mut B) { +1560 // A datagram is encoded only after this is verified. +1561 const ENCODE_LEN: bool = true; +1562 out.write(FrameType::Datagram(DatagramInfo( +1563 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), +1564 ))); // 1 byte +1565 // Safe to unwrap because we check length sanity before queueing datagrams +1566 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes +1567 out.put_slice(&self.data); +1568 } +1569} +1570 +1571#[derive(Debug, Copy, Clone, PartialEq, Eq)] +1572pub(crate) struct AckFrequency { +1573 pub(crate) sequence: VarInt, +1574 pub(crate) ack_eliciting_threshold: VarInt, +1575 pub(crate) request_max_ack_delay: VarInt, +1576 pub(crate) reordering_threshold: VarInt, +1577} +1578 +1579impl Encodable for AckFrequency { +1580 fn encode<W: BufMut>(&self, buf: &mut W) { +1581 buf.write(FrameType::AckFrequency); +1582 buf.write(self.sequence); +1583 buf.write(self.ack_eliciting_threshold); +1584 buf.write(self.request_max_ack_delay); +1585 buf.write(self.reordering_threshold); +1586 } +1587} +1588 +1589/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ +1590 +1591/// Conjunction of the information contained in the address discovery frames +1592/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). +1593#[derive(Debug, PartialEq, Eq, Clone)] +1594pub(crate) struct ObservedAddr { +1595 /// Monotonically increasing integer within the same connection. +1596 pub(crate) seq_no: VarInt, +1597 /// Reported observed address. +1598 pub(crate) ip: IpAddr, +1599 /// Reported observed port. +1600 pub(crate) port: u16, +1601} +1602 +1603impl ObservedAddr { +1604 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { +1605 Self { +1606 ip: remote.ip(), +1607 port: remote.port(), +1608 seq_no: seq_no.into(), +1609 } +1610 } +1611 +1612 /// Get the [`FrameType`] for this frame. +1613 pub(crate) fn get_type(&self) -> FrameType { +1614 if self.ip.is_ipv6() { +1615 FrameType::ObservedIpv6Addr +1616 } else { +1617 FrameType::ObservedIpv4Addr +1618 } +1619 } +1620 +1621 /// Compute the number of bytes needed to encode the frame. +1622 pub(crate) fn size(&self) -> usize { +1623 let type_size = self.get_type().size(); +1624 let req_id_bytes = self.seq_no.size(); +1625 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1626 let port_bytes = 2; +1627 type_size + req_id_bytes + ip_bytes + port_bytes +1628 } +1629 +1630 /// Reads the frame contents from the buffer. +1631 /// +1632 /// Should only be called when the frame type has been identified as +1633 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. +1634 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1635 let seq_no = bytes.get()?; +1636 let ip = if is_ipv6 { +1637 IpAddr::V6(bytes.get()?) +1638 } else { +1639 IpAddr::V4(bytes.get()?) +1640 }; +1641 let port = bytes.get()?; +1642 Ok(Self { seq_no, ip, port }) 1643 } -1644} -1645 -1646impl Encodable for ObservedAddr { -1647 fn encode<W: BufMut>(&self, buf: &mut W) { -1648 buf.write(self.get_type()); -1649 buf.write(self.seq_no); -1650 match self.ip { -1651 IpAddr::V4(ipv4_addr) => { -1652 buf.write(ipv4_addr); -1653 } -1654 IpAddr::V6(ipv6_addr) => { -1655 buf.write(ipv6_addr); -1656 } -1657 } -1658 buf.write::<u16>(self.port); -1659 } -1660} -1661 -1662/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ -1663 -1664#[derive(Debug, PartialEq, Eq)] -1665pub(crate) struct PathAbandon { -1666 pub(crate) path_id: PathId, -1667 pub(crate) error_code: TransportErrorCode, -1668} -1669 -1670impl PathAbandon { -1671 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; -1672} -1673 -1674impl Encodable for PathAbandon { -1675 fn encode<W: BufMut>(&self, buf: &mut W) { -1676 buf.write(FrameType::PathAbandon); -1677 buf.write(self.path_id); -1678 buf.write(self.error_code); -1679 } -1680} -1681 -1682impl Decodable for PathAbandon { -1683 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1684 Ok(Self { -1685 path_id: bytes.get()?, -1686 error_code: bytes.get()?, -1687 }) -1688 } -1689} -1690 -1691#[derive(Debug, PartialEq, Eq)] -1692pub(crate) struct PathStatusAvailable { -1693 pub(crate) path_id: PathId, -1694 pub(crate) status_seq_no: VarInt, -1695} -1696 -1697impl PathStatusAvailable { -1698 const TYPE: FrameType = FrameType::PathStatusAvailable; -1699 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; +1644 +1645 /// Gives the [`SocketAddr`] reported in the frame. +1646 pub(crate) fn socket_addr(&self) -> SocketAddr { +1647 (self.ip, self.port).into() +1648 } +1649} +1650 +1651impl Encodable for ObservedAddr { +1652 fn encode<W: BufMut>(&self, buf: &mut W) { +1653 buf.write(self.get_type()); +1654 buf.write(self.seq_no); +1655 match self.ip { +1656 IpAddr::V4(ipv4_addr) => { +1657 buf.write(ipv4_addr); +1658 } +1659 IpAddr::V6(ipv6_addr) => { +1660 buf.write(ipv6_addr); +1661 } +1662 } +1663 buf.write::<u16>(self.port); +1664 } +1665} +1666 +1667/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ +1668 +1669#[derive(Debug, PartialEq, Eq)] +1670pub(crate) struct PathAbandon { +1671 pub(crate) path_id: PathId, +1672 pub(crate) error_code: TransportErrorCode, +1673} +1674 +1675impl PathAbandon { +1676 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; +1677} +1678 +1679impl Encodable for PathAbandon { +1680 fn encode<W: BufMut>(&self, buf: &mut W) { +1681 buf.write(FrameType::PathAbandon); +1682 buf.write(self.path_id); +1683 buf.write(self.error_code); +1684 } +1685} +1686 +1687impl Decodable for PathAbandon { +1688 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1689 Ok(Self { +1690 path_id: bytes.get()?, +1691 error_code: bytes.get()?, +1692 }) +1693 } +1694} +1695 +1696#[derive(Debug, PartialEq, Eq)] +1697pub(crate) struct PathStatusAvailable { +1698 pub(crate) path_id: PathId, +1699 pub(crate) status_seq_no: VarInt, 1700} 1701 -1702impl Encodable for PathStatusAvailable { -1703 fn encode<W: BufMut>(&self, buf: &mut W) { -1704 buf.write(Self::TYPE); -1705 buf.write(self.path_id); -1706 buf.write(self.status_seq_no); -1707 } -1708} -1709 -1710impl Decodable for PathStatusAvailable { -1711 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1712 Ok(Self { -1713 path_id: bytes.get()?, -1714 status_seq_no: bytes.get()?, -1715 }) -1716 } -1717} -1718 -1719#[derive(Debug, PartialEq, Eq)] -1720pub(crate) struct PathStatusBackup { -1721 pub(crate) path_id: PathId, -1722 pub(crate) status_seq_no: VarInt, -1723} -1724 -1725impl PathStatusBackup { -1726 const TYPE: FrameType = FrameType::PathStatusBackup; -1727} -1728 -1729impl Encodable for PathStatusBackup { -1730 fn encode<W: BufMut>(&self, buf: &mut W) { -1731 buf.write(Self::TYPE); -1732 buf.write(self.path_id); -1733 buf.write(self.status_seq_no); -1734 } -1735} -1736 -1737impl Decodable for PathStatusBackup { -1738 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1739 Ok(Self { -1740 path_id: bytes.get()?, -1741 status_seq_no: bytes.get()?, -1742 }) -1743 } -1744} -1745 -1746/* Nat traversal frames */ -1747 -1748/// Conjunction of the information contained in the add address frames -1749/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). -1750#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] -1751// TODO(@divma): remove -1752#[allow(dead_code)] -1753pub(crate) struct AddAddress { -1754 /// Monotonically increasing integer within the same connection -1755 // TODO(@divma): both assumed, the draft has no mention of this but it's standard -1756 pub(crate) seq_no: VarInt, -1757 /// Address to include in the known set -1758 pub(crate) ip: IpAddr, -1759 /// Port to use with this address -1760 pub(crate) port: u16, -1761} -1762 -1763// TODO(@divma): remove -1764#[allow(dead_code)] -1765impl AddAddress { -1766 /// Smallest number of bytes this type of frame is guaranteed to fit within. -1767 pub(crate) const SIZE_BOUND: usize = Self { -1768 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -1769 port: u16::MAX, -1770 seq_no: VarInt::MAX, -1771 } -1772 .size(); -1773 -1774 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { -1775 Self { ip, port, seq_no } +1702impl PathStatusAvailable { +1703 const TYPE: FrameType = FrameType::PathStatusAvailable; +1704 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; +1705} +1706 +1707impl Encodable for PathStatusAvailable { +1708 fn encode<W: BufMut>(&self, buf: &mut W) { +1709 buf.write(Self::TYPE); +1710 buf.write(self.path_id); +1711 buf.write(self.status_seq_no); +1712 } +1713} +1714 +1715impl Decodable for PathStatusAvailable { +1716 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1717 Ok(Self { +1718 path_id: bytes.get()?, +1719 status_seq_no: bytes.get()?, +1720 }) +1721 } +1722} +1723 +1724#[derive(Debug, PartialEq, Eq)] +1725pub(crate) struct PathStatusBackup { +1726 pub(crate) path_id: PathId, +1727 pub(crate) status_seq_no: VarInt, +1728} +1729 +1730impl PathStatusBackup { +1731 const TYPE: FrameType = FrameType::PathStatusBackup; +1732} +1733 +1734impl Encodable for PathStatusBackup { +1735 fn encode<W: BufMut>(&self, buf: &mut W) { +1736 buf.write(Self::TYPE); +1737 buf.write(self.path_id); +1738 buf.write(self.status_seq_no); +1739 } +1740} +1741 +1742impl Decodable for PathStatusBackup { +1743 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1744 Ok(Self { +1745 path_id: bytes.get()?, +1746 status_seq_no: bytes.get()?, +1747 }) +1748 } +1749} +1750 +1751/* Nat traversal frames */ +1752 +1753/// Conjunction of the information contained in the add address frames +1754/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). +1755#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] +1756// TODO(@divma): remove +1757#[allow(dead_code)] +1758pub(crate) struct AddAddress { +1759 /// Monotonically increasing integer within the same connection +1760 // TODO(@divma): both assumed, the draft has no mention of this but it's standard +1761 pub(crate) seq_no: VarInt, +1762 /// Address to include in the known set +1763 pub(crate) ip: IpAddr, +1764 /// Port to use with this address +1765 pub(crate) port: u16, +1766} +1767 +1768// TODO(@divma): remove +1769#[allow(dead_code)] +1770impl AddAddress { +1771 /// Smallest number of bytes this type of frame is guaranteed to fit within. +1772 pub(crate) const SIZE_BOUND: usize = Self { +1773 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +1774 port: u16::MAX, +1775 seq_no: VarInt::MAX, 1776 } -1777 -1778 /// Get the [`FrameType`] for this frame. -1779 pub(crate) const fn get_type(&self) -> FrameType { -1780 if self.ip.is_ipv6() { -1781 FrameType::AddIpv6Address -1782 } else { -1783 FrameType::AddIpv4Address -1784 } -1785 } -1786 -1787 /// Compute the number of bytes needed to encode the frame -1788 pub(crate) const fn size(&self) -> usize { -1789 let type_size = self.get_type().size(); -1790 let seq_no_bytes = self.seq_no.size(); -1791 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1792 let port_bytes = 2; -1793 type_size + seq_no_bytes + ip_bytes + port_bytes -1794 } -1795 -1796 /// Read the frame contents from the buffer -1797 /// -1798 /// Should only be called when the frame type has been identified as -1799 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. -1800 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1801 let seq_no = bytes.get()?; -1802 let ip = if is_ipv6 { -1803 IpAddr::V6(bytes.get()?) -1804 } else { -1805 IpAddr::V4(bytes.get()?) -1806 }; -1807 let port = bytes.get()?; -1808 Ok(Self { seq_no, ip, port }) -1809 } -1810 -1811 /// Give the [`SocketAddr`] encoded in the frame -1812 pub(crate) fn socket_addr(&self) -> SocketAddr { -1813 self.ip_port().into() +1777 .size(); +1778 +1779 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { +1780 Self { ip, port, seq_no } +1781 } +1782 +1783 /// Get the [`FrameType`] for this frame. +1784 pub(crate) const fn get_type(&self) -> FrameType { +1785 if self.ip.is_ipv6() { +1786 FrameType::AddIpv6Address +1787 } else { +1788 FrameType::AddIpv4Address +1789 } +1790 } +1791 +1792 /// Compute the number of bytes needed to encode the frame +1793 pub(crate) const fn size(&self) -> usize { +1794 let type_size = self.get_type().size(); +1795 let seq_no_bytes = self.seq_no.size(); +1796 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1797 let port_bytes = 2; +1798 type_size + seq_no_bytes + ip_bytes + port_bytes +1799 } +1800 +1801 /// Read the frame contents from the buffer +1802 /// +1803 /// Should only be called when the frame type has been identified as +1804 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. +1805 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1806 let seq_no = bytes.get()?; +1807 let ip = if is_ipv6 { +1808 IpAddr::V6(bytes.get()?) +1809 } else { +1810 IpAddr::V4(bytes.get()?) +1811 }; +1812 let port = bytes.get()?; +1813 Ok(Self { seq_no, ip, port }) 1814 } 1815 -1816 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { -1817 (self.ip, self.port) -1818 } -1819} +1816 /// Give the [`SocketAddr`] encoded in the frame +1817 pub(crate) fn socket_addr(&self) -> SocketAddr { +1818 self.ip_port().into() +1819 } 1820 -1821impl Encodable for AddAddress { -1822 fn encode<W: BufMut>(&self, buf: &mut W) { -1823 buf.write(self.get_type()); -1824 buf.write(self.seq_no); -1825 match self.ip { -1826 IpAddr::V4(ipv4_addr) => { -1827 buf.write(ipv4_addr); -1828 } -1829 IpAddr::V6(ipv6_addr) => { -1830 buf.write(ipv6_addr); -1831 } -1832 } -1833 buf.write::<u16>(self.port); -1834 } -1835} -1836 -1837/// Conjunction of the information contained in the reach out frames -1838/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) -1839#[derive(Debug, PartialEq, Eq, Clone)] -1840// TODO(@divma): remove -1841#[allow(dead_code)] -1842pub(crate) struct ReachOut { -1843 /// The sequence number of the NAT Traversal attempts -1844 pub(crate) round: VarInt, -1845 /// Address to use -1846 pub(crate) ip: IpAddr, -1847 /// Port to use with this address -1848 pub(crate) port: u16, -1849} -1850 -1851// TODO(@divma): remove -1852#[allow(dead_code)] -1853impl ReachOut { -1854 /// Smallest number of bytes this type of frame is guaranteed to fit within -1855 pub(crate) const SIZE_BOUND: usize = Self { -1856 round: VarInt::MAX, -1857 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -1858 port: u16::MAX, -1859 } -1860 .size(); -1861 -1862 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { -1863 Self { round, ip, port } +1821 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { +1822 (self.ip, self.port) +1823 } +1824} +1825 +1826impl Encodable for AddAddress { +1827 fn encode<W: BufMut>(&self, buf: &mut W) { +1828 buf.write(self.get_type()); +1829 buf.write(self.seq_no); +1830 match self.ip { +1831 IpAddr::V4(ipv4_addr) => { +1832 buf.write(ipv4_addr); +1833 } +1834 IpAddr::V6(ipv6_addr) => { +1835 buf.write(ipv6_addr); +1836 } +1837 } +1838 buf.write::<u16>(self.port); +1839 } +1840} +1841 +1842/// Conjunction of the information contained in the reach out frames +1843/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) +1844#[derive(Debug, PartialEq, Eq, Clone)] +1845// TODO(@divma): remove +1846#[allow(dead_code)] +1847pub(crate) struct ReachOut { +1848 /// The sequence number of the NAT Traversal attempts +1849 pub(crate) round: VarInt, +1850 /// Address to use +1851 pub(crate) ip: IpAddr, +1852 /// Port to use with this address +1853 pub(crate) port: u16, +1854} +1855 +1856// TODO(@divma): remove +1857#[allow(dead_code)] +1858impl ReachOut { +1859 /// Smallest number of bytes this type of frame is guaranteed to fit within +1860 pub(crate) const SIZE_BOUND: usize = Self { +1861 round: VarInt::MAX, +1862 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +1863 port: u16::MAX, 1864 } -1865 -1866 /// Get the [`FrameType`] for this frame -1867 pub(crate) const fn get_type(&self) -> FrameType { -1868 if self.ip.is_ipv6() { -1869 FrameType::ReachOutAtIpv6 -1870 } else { -1871 FrameType::ReachOutAtIpv4 -1872 } -1873 } -1874 -1875 /// Compute the number of bytes needed to encode the frame -1876 pub(crate) const fn size(&self) -> usize { -1877 let type_size = self.get_type().size(); -1878 let round_bytes = self.round.size(); -1879 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1880 let port_bytes = 2; -1881 type_size + round_bytes + ip_bytes + port_bytes -1882 } -1883 -1884 /// Read the frame contents from the buffer -1885 /// -1886 /// Should only be called when the frame type has been identified as -1887 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. -1888 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1889 let round = bytes.get()?; -1890 let ip = if is_ipv6 { -1891 IpAddr::V6(bytes.get()?) -1892 } else { -1893 IpAddr::V4(bytes.get()?) -1894 }; -1895 let port = bytes.get()?; -1896 Ok(Self { round, ip, port }) -1897 } -1898 -1899 /// Give the [`SocketAddr`] encoded in the frame -1900 pub(crate) fn socket_addr(&self) -> SocketAddr { -1901 (self.ip, self.port).into() +1865 .size(); +1866 +1867 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { +1868 Self { round, ip, port } +1869 } +1870 +1871 /// Get the [`FrameType`] for this frame +1872 pub(crate) const fn get_type(&self) -> FrameType { +1873 if self.ip.is_ipv6() { +1874 FrameType::ReachOutAtIpv6 +1875 } else { +1876 FrameType::ReachOutAtIpv4 +1877 } +1878 } +1879 +1880 /// Compute the number of bytes needed to encode the frame +1881 pub(crate) const fn size(&self) -> usize { +1882 let type_size = self.get_type().size(); +1883 let round_bytes = self.round.size(); +1884 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1885 let port_bytes = 2; +1886 type_size + round_bytes + ip_bytes + port_bytes +1887 } +1888 +1889 /// Read the frame contents from the buffer +1890 /// +1891 /// Should only be called when the frame type has been identified as +1892 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. +1893 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1894 let round = bytes.get()?; +1895 let ip = if is_ipv6 { +1896 IpAddr::V6(bytes.get()?) +1897 } else { +1898 IpAddr::V4(bytes.get()?) +1899 }; +1900 let port = bytes.get()?; +1901 Ok(Self { round, ip, port }) 1902 } -1903} -1904 -1905impl Encodable for ReachOut { -1906 fn encode<W: BufMut>(&self, buf: &mut W) { -1907 buf.write(self.get_type()); -1908 buf.write(self.round); -1909 match self.ip { -1910 IpAddr::V4(ipv4_addr) => { -1911 buf.write(ipv4_addr); -1912 } -1913 IpAddr::V6(ipv6_addr) => { -1914 buf.write(ipv6_addr); -1915 } -1916 } -1917 buf.write::<u16>(self.port); -1918 } -1919} -1920 -1921/// Frame signaling an address is no longer being advertised -1922#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] -1923// TODO(@divma): remove -1924#[allow(dead_code)] -1925pub(crate) struct RemoveAddress { -1926 /// The sequence number of the address advertisement to be removed -1927 pub(crate) seq_no: VarInt, -1928} -1929 -1930// TODO(@divma): remove -1931#[allow(dead_code)] -1932impl RemoveAddress { -1933 /// [`FrameType`] of this frame -1934 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; -1935 -1936 /// Smallest number of bytes this type of frame is guaranteed to fit within -1937 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); -1938 -1939 pub(crate) const fn new(seq_no: VarInt) -> Self { -1940 Self { seq_no } -1941 } -1942 -1943 /// Compute the number of bytes needed to encode the frame -1944 pub(crate) const fn size(&self) -> usize { -1945 let type_size = Self::TYPE.size(); -1946 let seq_no_bytes = self.seq_no.size(); -1947 type_size + seq_no_bytes -1948 } -1949 -1950 /// Read the frame contents from the buffer -1951 /// -1952 /// Should only be called when the frame type has been identified as -1953 /// [`FrameType::RemoveAddress`]. -1954 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1955 Ok(Self { -1956 seq_no: bytes.get()?, -1957 }) -1958 } -1959} -1960 -1961impl Encodable for RemoveAddress { -1962 fn encode<W: BufMut>(&self, buf: &mut W) { -1963 buf.write(Self::TYPE); -1964 buf.write(self.seq_no); -1965 } -1966} -1967 -1968#[cfg(test)] -1969mod test { -1970 use super::*; -1971 use crate::coding::Encodable; -1972 use assert_matches::assert_matches; -1973 -1974 #[test] -1975 fn frame_type() { -1976 assert_eq!( -1977 FrameType::try_from(FrameType::Padding.to_u64()), -1978 Ok(FrameType::Padding), -1979 ); -1980 +1903 +1904 /// Give the [`SocketAddr`] encoded in the frame +1905 pub(crate) fn socket_addr(&self) -> SocketAddr { +1906 (self.ip, self.port).into() +1907 } +1908} +1909 +1910impl Encodable for ReachOut { +1911 fn encode<W: BufMut>(&self, buf: &mut W) { +1912 buf.write(self.get_type()); +1913 buf.write(self.round); +1914 match self.ip { +1915 IpAddr::V4(ipv4_addr) => { +1916 buf.write(ipv4_addr); +1917 } +1918 IpAddr::V6(ipv6_addr) => { +1919 buf.write(ipv6_addr); +1920 } +1921 } +1922 buf.write::<u16>(self.port); +1923 } +1924} +1925 +1926/// Frame signaling an address is no longer being advertised +1927#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] +1928// TODO(@divma): remove +1929#[allow(dead_code)] +1930pub(crate) struct RemoveAddress { +1931 /// The sequence number of the address advertisement to be removed +1932 pub(crate) seq_no: VarInt, +1933} +1934 +1935// TODO(@divma): remove +1936#[allow(dead_code)] +1937impl RemoveAddress { +1938 /// [`FrameType`] of this frame +1939 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; +1940 +1941 /// Smallest number of bytes this type of frame is guaranteed to fit within +1942 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); +1943 +1944 pub(crate) const fn new(seq_no: VarInt) -> Self { +1945 Self { seq_no } +1946 } +1947 +1948 /// Compute the number of bytes needed to encode the frame +1949 pub(crate) const fn size(&self) -> usize { +1950 let type_size = Self::TYPE.size(); +1951 let seq_no_bytes = self.seq_no.size(); +1952 type_size + seq_no_bytes +1953 } +1954 +1955 /// Read the frame contents from the buffer +1956 /// +1957 /// Should only be called when the frame type has been identified as +1958 /// [`FrameType::RemoveAddress`]. +1959 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1960 Ok(Self { +1961 seq_no: bytes.get()?, +1962 }) +1963 } +1964} +1965 +1966impl Encodable for RemoveAddress { +1967 fn encode<W: BufMut>(&self, buf: &mut W) { +1968 buf.write(Self::TYPE); +1969 buf.write(self.seq_no); +1970 } +1971} +1972 +1973#[cfg(test)] +1974mod test { +1975 use super::*; +1976 use crate::coding::Encodable; +1977 use assert_matches::assert_matches; +1978 +1979 #[test] +1980 fn frame_type() { 1981 assert_eq!( -1982 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()), -1983 Ok(FrameType::Datagram(DatagramInfo(0x30))), +1982 FrameType::try_from(FrameType::Padding.to_u64()), +1983 Ok(FrameType::Padding), 1984 ); 1985 1986 assert_eq!( -1987 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()), -1988 Ok(FrameType::Stream(StreamInfo(0x08))), +1987 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()), +1988 Ok(FrameType::Datagram(DatagramInfo(0x30))), 1989 ); -1990 } -1991 -1992 #[track_caller] -1993 fn frames(buf: Vec<u8>) -> Vec<Frame> { -1994 Iter::new(Bytes::from(buf)) -1995 .unwrap() -1996 .collect::<Result<Vec<_>, _>>() -1997 .unwrap() -1998 } -1999 -2000 #[test] -2001 fn ack_coding() { -2002 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -2003 let mut ranges = ArrayRangeSet::new(); -2004 for &packet in PACKETS { -2005 ranges.insert(packet..packet + 1); -2006 } -2007 let mut buf = Vec::new(); -2008 const ECN: EcnCounts = EcnCounts { -2009 ect0: 42, -2010 ect1: 24, -2011 ce: 12, -2012 }; -2013 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); -2014 let frames = frames(buf); -2015 assert_eq!(frames.len(), 1); -2016 match frames[0] { -2017 Frame::Ack(ref ack) => { -2018 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); -2019 packets.sort_unstable(); -2020 assert_eq!(&packets[..], PACKETS); -2021 assert_eq!(ack.ecn, Some(ECN)); -2022 } -2023 ref x => panic!("incorrect frame {x:?}"), -2024 } -2025 } -2026 -2027 #[test] -2028 #[allow(clippy::range_plus_one)] -2029 fn path_ack_coding() { -2030 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -2031 let mut ranges = ArrayRangeSet::new(); -2032 for &packet in PACKETS { -2033 ranges.insert(packet..packet + 1); -2034 } -2035 let mut buf = Vec::new(); -2036 const ECN: EcnCounts = EcnCounts { -2037 ect0: 42, -2038 ect1: 24, -2039 ce: 12, -2040 }; -2041 const PATH_ID: PathId = PathId::MAX; -2042 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); -2043 let frames = frames(buf); -2044 assert_eq!(frames.len(), 1); -2045 match frames[0] { -2046 Frame::PathAck(ref ack) => { -2047 assert_eq!(ack.path_id, PATH_ID); -2048 let mut packets = ack.into_iter().flatten().collect::<Vec<_>>(); -2049 packets.sort_unstable(); -2050 assert_eq!(&packets[..], PACKETS); -2051 assert_eq!(ack.ecn, Some(ECN)); -2052 } -2053 ref x => panic!("incorrect frame {x:?}"), -2054 } -2055 } -2056 -2057 #[test] -2058 fn ack_frequency_coding() { -2059 let mut buf = Vec::new(); -2060 let original = AckFrequency { -2061 sequence: VarInt(42), -2062 ack_eliciting_threshold: VarInt(20), -2063 request_max_ack_delay: VarInt(50_000), -2064 reordering_threshold: VarInt(1), -2065 }; -2066 original.encode(&mut buf); -2067 let frames = frames(buf); -2068 assert_eq!(frames.len(), 1); -2069 match &frames[0] { -2070 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), -2071 x => panic!("incorrect frame {x:?}"), -2072 } -2073 } -2074 -2075 #[test] -2076 fn immediate_ack_coding() { -2077 let mut buf = Vec::new(); -2078 FrameType::ImmediateAck.encode(&mut buf); -2079 let frames = frames(buf); -2080 assert_eq!(frames.len(), 1); -2081 assert_matches!(&frames[0], Frame::ImmediateAck); -2082 } -2083 -2084 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. -2085 #[test] -2086 fn test_observed_addr_roundrip() { -2087 let observed_addr = ObservedAddr { -2088 seq_no: VarInt(42), -2089 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2090 port: 4242, -2091 }; -2092 let mut buf = Vec::with_capacity(observed_addr.size()); -2093 observed_addr.encode(&mut buf); -2094 -2095 assert_eq!( -2096 observed_addr.size(), -2097 buf.len(), -2098 "expected written bytes and actual size differ" -2099 ); -2100 -2101 let mut decoded = frames(buf); -2102 assert_eq!(decoded.len(), 1); -2103 match decoded.pop().expect("non empty") { -2104 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), -2105 x => panic!("incorrect frame {x:?}"), -2106 } -2107 } -2108 -2109 #[test] -2110 fn test_path_abandon_roundtrip() { -2111 let abandon = PathAbandon { -2112 path_id: PathId(42), -2113 error_code: TransportErrorCode::NO_ERROR, -2114 }; -2115 let mut buf = Vec::new(); -2116 abandon.encode(&mut buf); -2117 -2118 let mut decoded = frames(buf); -2119 assert_eq!(decoded.len(), 1); -2120 match decoded.pop().expect("non empty") { -2121 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), -2122 x => panic!("incorrect frame {x:?}"), -2123 } -2124 } -2125 -2126 #[test] -2127 fn test_path_status_available_roundtrip() { -2128 let path_status_available = PathStatusAvailable { -2129 path_id: PathId(42), -2130 status_seq_no: VarInt(73), -2131 }; -2132 let mut buf = Vec::new(); -2133 path_status_available.encode(&mut buf); -2134 -2135 let mut decoded = frames(buf); -2136 assert_eq!(decoded.len(), 1); -2137 match decoded.pop().expect("non empty") { -2138 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), -2139 x => panic!("incorrect frame {x:?}"), -2140 } -2141 } -2142 -2143 #[test] -2144 fn test_path_status_backup_roundtrip() { -2145 let path_status_backup = PathStatusBackup { -2146 path_id: PathId(42), -2147 status_seq_no: VarInt(73), -2148 }; -2149 let mut buf = Vec::new(); -2150 path_status_backup.encode(&mut buf); -2151 -2152 let mut decoded = frames(buf); -2153 assert_eq!(decoded.len(), 1); -2154 match decoded.pop().expect("non empty") { -2155 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), -2156 x => panic!("incorrect frame {x:?}"), -2157 } -2158 } -2159 -2160 #[test] -2161 fn test_path_new_connection_id_roundtrip() { -2162 let cid = NewConnectionId { -2163 path_id: Some(PathId(22)), -2164 sequence: 31, -2165 retire_prior_to: 13, -2166 id: ConnectionId::new(&[0xAB; 8]), -2167 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), -2168 }; -2169 let mut buf = Vec::new(); -2170 cid.encode(&mut buf); -2171 -2172 let mut decoded = frames(buf); -2173 assert_eq!(decoded.len(), 1); -2174 match decoded.pop().expect("non empty") { -2175 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), -2176 x => panic!("incorrect frame {x:?}"), -2177 } -2178 } -2179 -2180 #[test] -2181 fn test_path_retire_connection_id_roundtrip() { -2182 let retire_cid = RetireConnectionId { -2183 path_id: Some(PathId(22)), -2184 sequence: 31, -2185 }; -2186 let mut buf = Vec::new(); -2187 retire_cid.encode(&mut buf); -2188 -2189 let mut decoded = frames(buf); -2190 assert_eq!(decoded.len(), 1); -2191 match decoded.pop().expect("non empty") { -2192 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), -2193 x => panic!("incorrect frame {x:?}"), -2194 } -2195 } -2196 -2197 #[test] -2198 fn test_paths_blocked_path_cids_blocked_roundtrip() { -2199 let mut buf = Vec::new(); -2200 -2201 let frame0 = PathsBlocked(PathId(22)); -2202 frame0.encode(&mut buf); -2203 let frame1 = PathCidsBlocked { -2204 path_id: PathId(23), -2205 next_seq: VarInt(32), -2206 }; -2207 frame1.encode(&mut buf); -2208 -2209 let mut decoded = frames(buf); -2210 assert_eq!(decoded.len(), 2); -2211 match decoded.pop().expect("non empty") { -2212 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), -2213 x => panic!("incorrect frame {x:?}"), -2214 } -2215 match decoded.pop().expect("non empty") { -2216 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), -2217 x => panic!("incorrect frame {x:?}"), -2218 } -2219 } -2220 -2221 /// Test that encoding and decoding [`AddAddress`] produces the same result -2222 #[test] -2223 fn test_add_address_roundrip() { -2224 let add_address = AddAddress { -2225 seq_no: VarInt(42), -2226 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2227 port: 4242, -2228 }; -2229 let mut buf = Vec::with_capacity(add_address.size()); -2230 add_address.encode(&mut buf); -2231 -2232 assert_eq!( -2233 add_address.size(), -2234 buf.len(), -2235 "expected written bytes and actual size differ" -2236 ); -2237 -2238 let mut decoded = frames(buf); -2239 assert_eq!(decoded.len(), 1); -2240 match decoded.pop().expect("non empty") { -2241 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), -2242 x => panic!("incorrect frame {x:?}"), -2243 } -2244 } -2245 -2246 /// Test that encoding and decoding [`AddAddress`] produces the same result -2247 #[test] -2248 fn test_reach_out_roundrip() { -2249 let reach_out = ReachOut { -2250 round: VarInt(42), -2251 ip: std::net::Ipv6Addr::LOCALHOST.into(), -2252 port: 4242, -2253 }; -2254 let mut buf = Vec::with_capacity(reach_out.size()); -2255 reach_out.encode(&mut buf); -2256 -2257 assert_eq!( -2258 reach_out.size(), -2259 buf.len(), -2260 "expected written bytes and actual size differ" -2261 ); -2262 -2263 let mut decoded = frames(buf); -2264 assert_eq!(decoded.len(), 1); -2265 match decoded.pop().expect("non empty") { -2266 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), -2267 x => panic!("incorrect frame {x:?}"), -2268 } -2269 } -2270 -2271 /// Test that encoding and decoding [`RemoveAddress`] produces the same result -2272 #[test] -2273 fn test_remove_address_roundrip() { -2274 let remove_addr = RemoveAddress::new(VarInt(10)); -2275 let mut buf = Vec::with_capacity(remove_addr.size()); -2276 remove_addr.encode(&mut buf); -2277 -2278 assert_eq!( -2279 remove_addr.size(), -2280 buf.len(), -2281 "expected written bytes and actual size differ" -2282 ); -2283 -2284 let mut decoded = frames(buf); -2285 assert_eq!(decoded.len(), 1); -2286 match decoded.pop().expect("non empty") { -2287 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), -2288 x => panic!("incorrect frame {x:?}"), -2289 } -2290 } -2291} \ No newline at end of file +1990 +1991 assert_eq!( +1992 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()), +1993 Ok(FrameType::Stream(StreamInfo(0x08))), +1994 ); +1995 } +1996 +1997 #[track_caller] +1998 fn frames(buf: Vec<u8>) -> Vec<Frame> { +1999 Iter::new(Bytes::from(buf)) +2000 .unwrap() +2001 .collect::<Result<Vec<_>, _>>() +2002 .unwrap() +2003 } +2004 +2005 #[test] +2006 fn ack_coding() { +2007 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2008 let mut ranges = ArrayRangeSet::new(); +2009 for &packet in PACKETS { +2010 ranges.insert(packet..packet + 1); +2011 } +2012 let mut buf = Vec::new(); +2013 const ECN: EcnCounts = EcnCounts { +2014 ect0: 42, +2015 ect1: 24, +2016 ce: 12, +2017 }; +2018 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); +2019 let frames = frames(buf); +2020 assert_eq!(frames.len(), 1); +2021 match frames[0] { +2022 Frame::Ack(ref ack) => { +2023 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); +2024 packets.sort_unstable(); +2025 assert_eq!(&packets[..], PACKETS); +2026 assert_eq!(ack.ecn, Some(ECN)); +2027 } +2028 ref x => panic!("incorrect frame {x:?}"), +2029 } +2030 } +2031 +2032 #[test] +2033 #[allow(clippy::range_plus_one)] +2034 fn path_ack_coding() { +2035 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2036 let mut ranges = ArrayRangeSet::new(); +2037 for &packet in PACKETS { +2038 ranges.insert(packet..packet + 1); +2039 } +2040 let mut buf = Vec::new(); +2041 const ECN: EcnCounts = EcnCounts { +2042 ect0: 42, +2043 ect1: 24, +2044 ce: 12, +2045 }; +2046 const PATH_ID: PathId = PathId::MAX; +2047 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); +2048 let frames = frames(buf); +2049 assert_eq!(frames.len(), 1); +2050 match frames[0] { +2051 Frame::PathAck(ref ack) => { +2052 assert_eq!(ack.path_id, PATH_ID); +2053 let mut packets = ack.into_iter().flatten().collect::<Vec<_>>(); +2054 packets.sort_unstable(); +2055 assert_eq!(&packets[..], PACKETS); +2056 assert_eq!(ack.ecn, Some(ECN)); +2057 } +2058 ref x => panic!("incorrect frame {x:?}"), +2059 } +2060 } +2061 +2062 #[test] +2063 fn ack_frequency_coding() { +2064 let mut buf = Vec::new(); +2065 let original = AckFrequency { +2066 sequence: VarInt(42), +2067 ack_eliciting_threshold: VarInt(20), +2068 request_max_ack_delay: VarInt(50_000), +2069 reordering_threshold: VarInt(1), +2070 }; +2071 original.encode(&mut buf); +2072 let frames = frames(buf); +2073 assert_eq!(frames.len(), 1); +2074 match &frames[0] { +2075 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), +2076 x => panic!("incorrect frame {x:?}"), +2077 } +2078 } +2079 +2080 #[test] +2081 fn immediate_ack_coding() { +2082 let mut buf = Vec::new(); +2083 FrameType::ImmediateAck.encode(&mut buf); +2084 let frames = frames(buf); +2085 assert_eq!(frames.len(), 1); +2086 assert_matches!(&frames[0], Frame::ImmediateAck); +2087 } +2088 +2089 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. +2090 #[test] +2091 fn test_observed_addr_roundrip() { +2092 let observed_addr = ObservedAddr { +2093 seq_no: VarInt(42), +2094 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2095 port: 4242, +2096 }; +2097 let mut buf = Vec::with_capacity(observed_addr.size()); +2098 observed_addr.encode(&mut buf); +2099 +2100 assert_eq!( +2101 observed_addr.size(), +2102 buf.len(), +2103 "expected written bytes and actual size differ" +2104 ); +2105 +2106 let mut decoded = frames(buf); +2107 assert_eq!(decoded.len(), 1); +2108 match decoded.pop().expect("non empty") { +2109 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), +2110 x => panic!("incorrect frame {x:?}"), +2111 } +2112 } +2113 +2114 #[test] +2115 fn test_path_abandon_roundtrip() { +2116 let abandon = PathAbandon { +2117 path_id: PathId(42), +2118 error_code: TransportErrorCode::NO_ERROR, +2119 }; +2120 let mut buf = Vec::new(); +2121 abandon.encode(&mut buf); +2122 +2123 let mut decoded = frames(buf); +2124 assert_eq!(decoded.len(), 1); +2125 match decoded.pop().expect("non empty") { +2126 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), +2127 x => panic!("incorrect frame {x:?}"), +2128 } +2129 } +2130 +2131 #[test] +2132 fn test_path_status_available_roundtrip() { +2133 let path_status_available = PathStatusAvailable { +2134 path_id: PathId(42), +2135 status_seq_no: VarInt(73), +2136 }; +2137 let mut buf = Vec::new(); +2138 path_status_available.encode(&mut buf); +2139 +2140 let mut decoded = frames(buf); +2141 assert_eq!(decoded.len(), 1); +2142 match decoded.pop().expect("non empty") { +2143 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), +2144 x => panic!("incorrect frame {x:?}"), +2145 } +2146 } +2147 +2148 #[test] +2149 fn test_path_status_backup_roundtrip() { +2150 let path_status_backup = PathStatusBackup { +2151 path_id: PathId(42), +2152 status_seq_no: VarInt(73), +2153 }; +2154 let mut buf = Vec::new(); +2155 path_status_backup.encode(&mut buf); +2156 +2157 let mut decoded = frames(buf); +2158 assert_eq!(decoded.len(), 1); +2159 match decoded.pop().expect("non empty") { +2160 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), +2161 x => panic!("incorrect frame {x:?}"), +2162 } +2163 } +2164 +2165 #[test] +2166 fn test_path_new_connection_id_roundtrip() { +2167 let cid = NewConnectionId { +2168 path_id: Some(PathId(22)), +2169 sequence: 31, +2170 retire_prior_to: 13, +2171 id: ConnectionId::new(&[0xAB; 8]), +2172 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), +2173 }; +2174 let mut buf = Vec::new(); +2175 cid.encode(&mut buf); +2176 +2177 let mut decoded = frames(buf); +2178 assert_eq!(decoded.len(), 1); +2179 match decoded.pop().expect("non empty") { +2180 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), +2181 x => panic!("incorrect frame {x:?}"), +2182 } +2183 } +2184 +2185 #[test] +2186 fn test_path_retire_connection_id_roundtrip() { +2187 let retire_cid = RetireConnectionId { +2188 path_id: Some(PathId(22)), +2189 sequence: 31, +2190 }; +2191 let mut buf = Vec::new(); +2192 retire_cid.encode(&mut buf); +2193 +2194 let mut decoded = frames(buf); +2195 assert_eq!(decoded.len(), 1); +2196 match decoded.pop().expect("non empty") { +2197 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), +2198 x => panic!("incorrect frame {x:?}"), +2199 } +2200 } +2201 +2202 #[test] +2203 fn test_paths_blocked_path_cids_blocked_roundtrip() { +2204 let mut buf = Vec::new(); +2205 +2206 let frame0 = PathsBlocked(PathId(22)); +2207 frame0.encode(&mut buf); +2208 let frame1 = PathCidsBlocked { +2209 path_id: PathId(23), +2210 next_seq: VarInt(32), +2211 }; +2212 frame1.encode(&mut buf); +2213 +2214 let mut decoded = frames(buf); +2215 assert_eq!(decoded.len(), 2); +2216 match decoded.pop().expect("non empty") { +2217 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), +2218 x => panic!("incorrect frame {x:?}"), +2219 } +2220 match decoded.pop().expect("non empty") { +2221 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), +2222 x => panic!("incorrect frame {x:?}"), +2223 } +2224 } +2225 +2226 /// Test that encoding and decoding [`AddAddress`] produces the same result +2227 #[test] +2228 fn test_add_address_roundrip() { +2229 let add_address = AddAddress { +2230 seq_no: VarInt(42), +2231 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2232 port: 4242, +2233 }; +2234 let mut buf = Vec::with_capacity(add_address.size()); +2235 add_address.encode(&mut buf); +2236 +2237 assert_eq!( +2238 add_address.size(), +2239 buf.len(), +2240 "expected written bytes and actual size differ" +2241 ); +2242 +2243 let mut decoded = frames(buf); +2244 assert_eq!(decoded.len(), 1); +2245 match decoded.pop().expect("non empty") { +2246 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), +2247 x => panic!("incorrect frame {x:?}"), +2248 } +2249 } +2250 +2251 /// Test that encoding and decoding [`AddAddress`] produces the same result +2252 #[test] +2253 fn test_reach_out_roundrip() { +2254 let reach_out = ReachOut { +2255 round: VarInt(42), +2256 ip: std::net::Ipv6Addr::LOCALHOST.into(), +2257 port: 4242, +2258 }; +2259 let mut buf = Vec::with_capacity(reach_out.size()); +2260 reach_out.encode(&mut buf); +2261 +2262 assert_eq!( +2263 reach_out.size(), +2264 buf.len(), +2265 "expected written bytes and actual size differ" +2266 ); +2267 +2268 let mut decoded = frames(buf); +2269 assert_eq!(decoded.len(), 1); +2270 match decoded.pop().expect("non empty") { +2271 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), +2272 x => panic!("incorrect frame {x:?}"), +2273 } +2274 } +2275 +2276 /// Test that encoding and decoding [`RemoveAddress`] produces the same result +2277 #[test] +2278 fn test_remove_address_roundrip() { +2279 let remove_addr = RemoveAddress::new(VarInt(10)); +2280 let mut buf = Vec::with_capacity(remove_addr.size()); +2281 remove_addr.encode(&mut buf); +2282 +2283 assert_eq!( +2284 remove_addr.size(), +2285 buf.len(), +2286 "expected written bytes and actual size differ" +2287 ); +2288 +2289 let mut decoded = frames(buf); +2290 assert_eq!(decoded.len(), 1); +2291 match decoded.pop().expect("non empty") { +2292 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), +2293 x => panic!("incorrect frame {x:?}"), +2294 } +2295 } +2296} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/lib.rs.html b/pr/255/docs/src/iroh_quinn_proto/lib.rs.html index 9adce6ac7..f195cf65c 100644 --- a/pr/255/docs/src/iroh_quinn_proto/lib.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/lib.rs.html @@ -44,10 +44,10 @@ 44pub(crate) mod connection; 45pub use crate::connection::{ 46 Chunk, Chunks, ClosePathError, ClosedPath, ClosedStream, Connection, ConnectionError, -47 ConnectionStats, Datagrams, Event, FinishError, FrameStats, PathError, PathEvent, PathId, -48 PathStats, PathStatus, ReadError, ReadableError, RecvStream, RttEstimator, SendDatagramError, -49 SendStream, SetPathStatusError, ShouldTransmit, StreamEvent, Streams, UdpStats, WriteError, -50 Written, +47 ConnectionStats, Datagrams, Event, FinishError, FrameStats, MultipathNotNegotiated, PathError, +48 PathEvent, PathId, PathStats, PathStatus, ReadError, ReadableError, RecvStream, RttEstimator, +49 SendDatagramError, SendStream, SetPathStatusError, ShouldTransmit, StreamEvent, Streams, +50 UdpStats, WriteError, Written, 51}; 52 53#[cfg(feature = "rustls")] @@ -66,352 +66,355 @@ 66pub mod crypto; 67 68mod frame; -69pub use crate::frame::{ApplicationClose, ConnectionClose, Datagram, FrameType}; -70use crate::{ -71 coding::{Decodable, Encodable}, -72 frame::Frame, -73}; -74 -75mod endpoint; -76pub use crate::endpoint::{ -77 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint, Incoming, RetryError, -78}; -79 -80mod packet; -81pub use packet::{ -82 ConnectionIdParser, FixedLengthConnectionIdParser, LongType, PacketDecodeError, PartialDecode, -83 ProtectedHeader, ProtectedInitialHeader, -84}; -85 -86mod shared; -87pub use crate::shared::{ConnectionEvent, ConnectionId, EcnCodepoint, EndpointEvent}; +69pub use crate::frame::{ +70 ApplicationClose, ConnectionClose, Datagram, DatagramInfo, FrameType, InvalidFrameId, +71 MaybeFrame, StreamInfo, +72}; +73use crate::{ +74 coding::{Decodable, Encodable}, +75 frame::Frame, +76}; +77 +78mod endpoint; +79pub use crate::endpoint::{ +80 AcceptError, ConnectError, ConnectionHandle, DatagramEvent, Endpoint, Incoming, RetryError, +81}; +82 +83mod packet; +84pub use packet::{ +85 ConnectionIdParser, FixedLengthConnectionIdParser, LongType, PacketDecodeError, PartialDecode, +86 ProtectedHeader, ProtectedInitialHeader, +87}; 88 -89mod transport_error; -90pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError}; +89mod shared; +90pub use crate::shared::{ConnectionEvent, ConnectionId, EcnCodepoint, EndpointEvent}; 91 -92pub mod congestion; -93 -94mod cid_generator; -95pub use crate::cid_generator::{ -96 ConnectionIdGenerator, HashedConnectionIdGenerator, InvalidCid, RandomConnectionIdGenerator, -97}; -98 -99mod token; -100use token::ResetToken; -101pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore}; -102 -103mod address_discovery; -104 -105mod token_memory_cache; -106pub use token_memory_cache::TokenMemoryCache; +92mod transport_error; +93pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError}; +94 +95pub mod congestion; +96 +97mod cid_generator; +98pub use crate::cid_generator::{ +99 ConnectionIdGenerator, HashedConnectionIdGenerator, InvalidCid, RandomConnectionIdGenerator, +100}; +101 +102mod token; +103use token::ResetToken; +104pub use token::{NoneTokenLog, NoneTokenStore, TokenLog, TokenReuseError, TokenStore}; +105 +106mod address_discovery; 107 -108pub mod iroh_hp; -109 -110#[cfg(feature = "arbitrary")] -111use arbitrary::Arbitrary; +108mod token_memory_cache; +109pub use token_memory_cache::TokenMemoryCache; +110 +111pub mod iroh_hp; 112 -113// Deal with time -114#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] -115pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -116#[cfg(all(target_family = "wasm", target_os = "unknown"))] -117pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -118 -119#[cfg(feature = "bench")] -120pub mod bench_exports { -121 //! Exports for benchmarks -122 pub use crate::connection::send_buffer::send_buffer_benches; -123} -124 -125#[cfg(fuzzing)] -126pub mod fuzzing { -127 pub use crate::connection::{Retransmits, State as ConnectionState, StreamsState}; -128 pub use crate::frame::ResetStream; -129 pub use crate::packet::PartialDecode; -130 pub use crate::transport_parameters::TransportParameters; -131 pub use bytes::{BufMut, BytesMut}; -132 -133 #[cfg(feature = "arbitrary")] -134 use arbitrary::{Arbitrary, Result, Unstructured}; +113#[cfg(feature = "arbitrary")] +114use arbitrary::Arbitrary; +115 +116// Deal with time +117#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +118pub(crate) use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +119#[cfg(all(target_family = "wasm", target_os = "unknown"))] +120pub(crate) use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +121 +122#[cfg(feature = "bench")] +123pub mod bench_exports { +124 //! Exports for benchmarks +125 pub use crate::connection::send_buffer::send_buffer_benches; +126} +127 +128#[cfg(fuzzing)] +129pub mod fuzzing { +130 pub use crate::connection::{Retransmits, State as ConnectionState, StreamsState}; +131 pub use crate::frame::ResetStream; +132 pub use crate::packet::PartialDecode; +133 pub use crate::transport_parameters::TransportParameters; +134 pub use bytes::{BufMut, BytesMut}; 135 136 #[cfg(feature = "arbitrary")] -137 impl<'arbitrary> Arbitrary<'arbitrary> for TransportParameters { -138 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> { -139 Ok(Self { -140 initial_max_streams_bidi: u.arbitrary()?, -141 initial_max_streams_uni: u.arbitrary()?, -142 ack_delay_exponent: u.arbitrary()?, -143 max_udp_payload_size: u.arbitrary()?, -144 ..Self::default() -145 }) -146 } -147 } -148 -149 #[derive(Debug)] -150 pub struct PacketParams { -151 pub local_cid_len: usize, -152 pub buf: BytesMut, -153 pub grease_quic_bit: bool, -154 } -155 -156 #[cfg(feature = "arbitrary")] -157 impl<'arbitrary> Arbitrary<'arbitrary> for PacketParams { -158 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> { -159 let local_cid_len: usize = u.int_in_range(0..=crate::MAX_CID_SIZE)?; -160 let bytes: Vec<u8> = Vec::arbitrary(u)?; -161 let mut buf = BytesMut::new(); -162 buf.put_slice(&bytes[..]); -163 Ok(Self { -164 local_cid_len, -165 buf, -166 grease_quic_bit: bool::arbitrary(u)?, -167 }) -168 } -169 } -170} -171 -172/// The QUIC protocol version implemented. -173pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[ -174 0x00000001, -175 0xff00_001d, -176 0xff00_001e, -177 0xff00_001f, -178 0xff00_0020, -179 0xff00_0021, -180 0xff00_0022, -181]; -182 -183/// Whether an endpoint was the initiator of a connection -184#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] -185#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -186pub enum Side { -187 /// The initiator of a connection -188 Client = 0, -189 /// The acceptor of a connection -190 Server = 1, -191} -192 -193impl Side { -194 #[inline] -195 /// Shorthand for `self == Side::Client` -196 pub fn is_client(self) -> bool { -197 self == Self::Client -198 } -199 -200 #[inline] -201 /// Shorthand for `self == Side::Server` -202 pub fn is_server(self) -> bool { -203 self == Self::Server -204 } -205} -206 -207impl ops::Not for Side { -208 type Output = Self; -209 fn not(self) -> Self { -210 match self { -211 Self::Client => Self::Server, -212 Self::Server => Self::Client, -213 } -214 } -215} -216 -217/// Whether a stream communicates data in both directions or only from the initiator -218#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] -219#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -220pub enum Dir { -221 /// Data flows in both directions -222 Bi = 0, -223 /// Data flows only from the stream's initiator -224 Uni = 1, -225} -226 -227impl Dir { -228 fn iter() -> impl Iterator<Item = Self> { -229 [Self::Bi, Self::Uni].iter().cloned() -230 } -231} -232 -233impl fmt::Display for Dir { -234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -235 use Dir::*; -236 f.pad(match *self { -237 Bi => "bidirectional", -238 Uni => "unidirectional", -239 }) -240 } -241} -242 -243/// Identifier for a stream within a particular connection -244#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] -245#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -246pub struct StreamId(u64); -247 -248impl fmt::Display for StreamId { -249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -250 let initiator = match self.initiator() { -251 Side::Client => "client", -252 Side::Server => "server", -253 }; -254 let dir = match self.dir() { -255 Dir::Uni => "uni", -256 Dir::Bi => "bi", -257 }; -258 write!( -259 f, -260 "{} {}directional stream {}", -261 initiator, -262 dir, -263 self.index() -264 ) -265 } -266} -267 -268impl StreamId { -269 /// Create a new StreamId -270 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self { -271 Self((index << 2) | ((dir as u64) << 1) | initiator as u64) -272 } -273 /// Which side of a connection initiated the stream -274 pub fn initiator(self) -> Side { -275 if self.0 & 0x1 == 0 { -276 Side::Client -277 } else { -278 Side::Server -279 } -280 } -281 /// Which directions data flows in -282 pub fn dir(self) -> Dir { -283 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni } -284 } -285 /// Distinguishes streams of the same initiator and directionality -286 pub fn index(self) -> u64 { -287 self.0 >> 2 -288 } -289} -290 -291impl From<StreamId> for VarInt { -292 fn from(x: StreamId) -> Self { -293 unsafe { Self::from_u64_unchecked(x.0) } -294 } -295} -296 -297impl From<VarInt> for StreamId { -298 fn from(v: VarInt) -> Self { -299 Self(v.0) -300 } -301} -302 -303impl From<StreamId> for u64 { -304 fn from(x: StreamId) -> Self { -305 x.0 -306 } -307} -308 -309impl Decodable for StreamId { -310 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> { -311 VarInt::decode(buf).map(|x| Self(x.into_inner())) -312 } -313} -314impl Encodable for StreamId { -315 fn encode<B: bytes::BufMut>(&self, buf: &mut B) { -316 VarInt::from_u64(self.0).unwrap().encode(buf); -317 } -318} -319 -320/// An outgoing packet -321#[derive(Debug)] -322#[must_use] -323pub struct Transmit { -324 /// The socket this datagram should be sent to -325 pub destination: SocketAddr, -326 /// Explicit congestion notification bits to set on the packet -327 pub ecn: Option<EcnCodepoint>, -328 /// Amount of data written to the caller-supplied buffer -329 pub size: usize, -330 /// The segment size if this transmission contains multiple datagrams. -331 /// This is `None` if the transmit only contains a single datagram -332 pub segment_size: Option<usize>, -333 /// Optional source IP address for the datagram -334 pub src_ip: Option<IpAddr>, -335} -336 -337// -338// Useful internal constants -339// -340 -341/// The maximum number of CIDs we bother to issue per path -342const LOC_CID_COUNT: u64 = 12; -343const RESET_TOKEN_SIZE: usize = 16; -344const MAX_CID_SIZE: usize = 20; -345const MIN_INITIAL_SIZE: u16 = 1200; -346/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size> -347const INITIAL_MTU: u16 = 1200; -348const MAX_UDP_PAYLOAD: u16 = 65527; -349const TIMER_GRANULARITY: Duration = Duration::from_millis(1); -350/// Maximum number of streams that can be uniquely identified by a stream ID -351const MAX_STREAM_COUNT: u64 = 1 << 60; -352 -353/// Identifies a network path by the combination of remote and local addresses -354/// -355/// Including the local ensures good behavior when the host has multiple IP addresses on the same -356/// subnet and zero-length connection IDs are in use or when multipath is enabled and multiple -357/// paths exist with the same remote, but different local IP interfaces. -358#[derive(Hash, Eq, PartialEq, Copy, Clone)] -359pub struct FourTuple { -360 /// The remote side of this tuple -361 pub remote: SocketAddr, -362 /// The local side of this tuple. -363 /// -364 /// The socket is irrelevant for our intents and purposes: -365 /// When we send, we can only specify the `src_ip`, not the source port. -366 /// So even if we track the port, we won't be able to make use of it. -367 pub local_ip: Option<IpAddr>, -368} -369 -370impl FourTuple { -371 /// Returns whether we think the other address probably represents the same path -372 /// as ours. -373 /// -374 /// If we have a local IP set, then we're exact and only match if the 4-tuples are -375 /// exactly equal. -376 /// If we don't have a local IP set, then we only check the remote addresses for equality. -377 pub fn is_probably_same_path(&self, other: &Self) -> bool { -378 self.remote == other.remote && (self.local_ip.is_none() || self.local_ip == other.local_ip) -379 } -380 -381 /// Updates this tuple's local address iff -382 /// - it was unset before, -383 /// - the other tuple has the same remote, and -384 /// - the other tuple has a local address set. -385 /// -386 /// Returns whether this and the other remote are now fully equal. -387 pub fn update_local_if_same_remote(&mut self, other: &Self) -> bool { -388 if self.remote != other.remote { -389 return false; -390 } -391 if self.local_ip.is_some() && self.local_ip != other.local_ip { +137 use arbitrary::{Arbitrary, Result, Unstructured}; +138 +139 #[cfg(feature = "arbitrary")] +140 impl<'arbitrary> Arbitrary<'arbitrary> for TransportParameters { +141 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> { +142 Ok(Self { +143 initial_max_streams_bidi: u.arbitrary()?, +144 initial_max_streams_uni: u.arbitrary()?, +145 ack_delay_exponent: u.arbitrary()?, +146 max_udp_payload_size: u.arbitrary()?, +147 ..Self::default() +148 }) +149 } +150 } +151 +152 #[derive(Debug)] +153 pub struct PacketParams { +154 pub local_cid_len: usize, +155 pub buf: BytesMut, +156 pub grease_quic_bit: bool, +157 } +158 +159 #[cfg(feature = "arbitrary")] +160 impl<'arbitrary> Arbitrary<'arbitrary> for PacketParams { +161 fn arbitrary(u: &mut Unstructured<'arbitrary>) -> Result<Self> { +162 let local_cid_len: usize = u.int_in_range(0..=crate::MAX_CID_SIZE)?; +163 let bytes: Vec<u8> = Vec::arbitrary(u)?; +164 let mut buf = BytesMut::new(); +165 buf.put_slice(&bytes[..]); +166 Ok(Self { +167 local_cid_len, +168 buf, +169 grease_quic_bit: bool::arbitrary(u)?, +170 }) +171 } +172 } +173} +174 +175/// The QUIC protocol version implemented. +176pub const DEFAULT_SUPPORTED_VERSIONS: &[u32] = &[ +177 0x00000001, +178 0xff00_001d, +179 0xff00_001e, +180 0xff00_001f, +181 0xff00_0020, +182 0xff00_0021, +183 0xff00_0022, +184]; +185 +186/// Whether an endpoint was the initiator of a connection +187#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +188#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +189pub enum Side { +190 /// The initiator of a connection +191 Client = 0, +192 /// The acceptor of a connection +193 Server = 1, +194} +195 +196impl Side { +197 #[inline] +198 /// Shorthand for `self == Side::Client` +199 pub fn is_client(self) -> bool { +200 self == Self::Client +201 } +202 +203 #[inline] +204 /// Shorthand for `self == Side::Server` +205 pub fn is_server(self) -> bool { +206 self == Self::Server +207 } +208} +209 +210impl ops::Not for Side { +211 type Output = Self; +212 fn not(self) -> Self { +213 match self { +214 Self::Client => Self::Server, +215 Self::Server => Self::Client, +216 } +217 } +218} +219 +220/// Whether a stream communicates data in both directions or only from the initiator +221#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +222#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +223pub enum Dir { +224 /// Data flows in both directions +225 Bi = 0, +226 /// Data flows only from the stream's initiator +227 Uni = 1, +228} +229 +230impl Dir { +231 fn iter() -> impl Iterator<Item = Self> { +232 [Self::Bi, Self::Uni].iter().cloned() +233 } +234} +235 +236impl fmt::Display for Dir { +237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +238 use Dir::*; +239 f.pad(match *self { +240 Bi => "bidirectional", +241 Uni => "unidirectional", +242 }) +243 } +244} +245 +246/// Identifier for a stream within a particular connection +247#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +248#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +249pub struct StreamId(u64); +250 +251impl fmt::Display for StreamId { +252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +253 let initiator = match self.initiator() { +254 Side::Client => "client", +255 Side::Server => "server", +256 }; +257 let dir = match self.dir() { +258 Dir::Uni => "uni", +259 Dir::Bi => "bi", +260 }; +261 write!( +262 f, +263 "{} {}directional stream {}", +264 initiator, +265 dir, +266 self.index() +267 ) +268 } +269} +270 +271impl StreamId { +272 /// Create a new StreamId +273 pub fn new(initiator: Side, dir: Dir, index: u64) -> Self { +274 Self((index << 2) | ((dir as u64) << 1) | initiator as u64) +275 } +276 /// Which side of a connection initiated the stream +277 pub fn initiator(self) -> Side { +278 if self.0 & 0x1 == 0 { +279 Side::Client +280 } else { +281 Side::Server +282 } +283 } +284 /// Which directions data flows in +285 pub fn dir(self) -> Dir { +286 if self.0 & 0x2 == 0 { Dir::Bi } else { Dir::Uni } +287 } +288 /// Distinguishes streams of the same initiator and directionality +289 pub fn index(self) -> u64 { +290 self.0 >> 2 +291 } +292} +293 +294impl From<StreamId> for VarInt { +295 fn from(x: StreamId) -> Self { +296 unsafe { Self::from_u64_unchecked(x.0) } +297 } +298} +299 +300impl From<VarInt> for StreamId { +301 fn from(v: VarInt) -> Self { +302 Self(v.0) +303 } +304} +305 +306impl From<StreamId> for u64 { +307 fn from(x: StreamId) -> Self { +308 x.0 +309 } +310} +311 +312impl Decodable for StreamId { +313 fn decode<B: bytes::Buf>(buf: &mut B) -> coding::Result<Self> { +314 VarInt::decode(buf).map(|x| Self(x.into_inner())) +315 } +316} +317impl Encodable for StreamId { +318 fn encode<B: bytes::BufMut>(&self, buf: &mut B) { +319 VarInt::from_u64(self.0).unwrap().encode(buf); +320 } +321} +322 +323/// An outgoing packet +324#[derive(Debug)] +325#[must_use] +326pub struct Transmit { +327 /// The socket this datagram should be sent to +328 pub destination: SocketAddr, +329 /// Explicit congestion notification bits to set on the packet +330 pub ecn: Option<EcnCodepoint>, +331 /// Amount of data written to the caller-supplied buffer +332 pub size: usize, +333 /// The segment size if this transmission contains multiple datagrams. +334 /// This is `None` if the transmit only contains a single datagram +335 pub segment_size: Option<usize>, +336 /// Optional source IP address for the datagram +337 pub src_ip: Option<IpAddr>, +338} +339 +340// +341// Useful internal constants +342// +343 +344/// The maximum number of CIDs we bother to issue per path +345const LOC_CID_COUNT: u64 = 12; +346const RESET_TOKEN_SIZE: usize = 16; +347const MAX_CID_SIZE: usize = 20; +348const MIN_INITIAL_SIZE: u16 = 1200; +349/// <https://www.rfc-editor.org/rfc/rfc9000.html#name-datagram-size> +350const INITIAL_MTU: u16 = 1200; +351const MAX_UDP_PAYLOAD: u16 = 65527; +352const TIMER_GRANULARITY: Duration = Duration::from_millis(1); +353/// Maximum number of streams that can be uniquely identified by a stream ID +354const MAX_STREAM_COUNT: u64 = 1 << 60; +355 +356/// Identifies a network path by the combination of remote and local addresses +357/// +358/// Including the local ensures good behavior when the host has multiple IP addresses on the same +359/// subnet and zero-length connection IDs are in use or when multipath is enabled and multiple +360/// paths exist with the same remote, but different local IP interfaces. +361#[derive(Hash, Eq, PartialEq, Copy, Clone)] +362pub struct FourTuple { +363 /// The remote side of this tuple +364 pub remote: SocketAddr, +365 /// The local side of this tuple. +366 /// +367 /// The socket is irrelevant for our intents and purposes: +368 /// When we send, we can only specify the `src_ip`, not the source port. +369 /// So even if we track the port, we won't be able to make use of it. +370 pub local_ip: Option<IpAddr>, +371} +372 +373impl FourTuple { +374 /// Returns whether we think the other address probably represents the same path +375 /// as ours. +376 /// +377 /// If we have a local IP set, then we're exact and only match if the 4-tuples are +378 /// exactly equal. +379 /// If we don't have a local IP set, then we only check the remote addresses for equality. +380 pub fn is_probably_same_path(&self, other: &Self) -> bool { +381 self.remote == other.remote && (self.local_ip.is_none() || self.local_ip == other.local_ip) +382 } +383 +384 /// Updates this tuple's local address iff +385 /// - it was unset before, +386 /// - the other tuple has the same remote, and +387 /// - the other tuple has a local address set. +388 /// +389 /// Returns whether this and the other remote are now fully equal. +390 pub fn update_local_if_same_remote(&mut self, other: &Self) -> bool { +391 if self.remote != other.remote { 392 return false; 393 } -394 self.local_ip = other.local_ip; -395 true -396 } -397} -398 -399impl fmt::Display for FourTuple { -400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -401 f.write_str("(")?; -402 if let Some(local_ip) = &self.local_ip { -403 local_ip.fmt(f)?; -404 f.write_str(", ")?; -405 } else { -406 f.write_str("<unknown>, ")?; -407 } -408 self.remote.fmt(f)?; -409 f.write_str(")") -410 } -411} -412 -413impl fmt::Debug for FourTuple { -414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -415 fmt::Display::fmt(&self, f) -416 } -417} \ No newline at end of file +394 if self.local_ip.is_some() && self.local_ip != other.local_ip { +395 return false; +396 } +397 self.local_ip = other.local_ip; +398 true +399 } +400} +401 +402impl fmt::Display for FourTuple { +403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +404 f.write_str("(")?; +405 if let Some(local_ip) = &self.local_ip { +406 local_ip.fmt(f)?; +407 f.write_str(", ")?; +408 } else { +409 f.write_str("<unknown>, ")?; +410 } +411 self.remote.fmt(f)?; +412 f.write_str(")") +413 } +414} +415 +416impl fmt::Debug for FourTuple { +417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +418 fmt::Display::fmt(&self, f) +419 } +420} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/packet.rs.html b/pr/255/docs/src/iroh_quinn_proto/packet.rs.html index 8f84c5925..9955a44e4 100644 --- a/pr/255/docs/src/iroh_quinn_proto/packet.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/packet.rs.html @@ -910,7 +910,7 @@ 910 911/// Packet number space identifiers 912#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -913pub enum SpaceId { +913pub(crate) enum SpaceId { 914 /// Unprotected packets, used to bootstrap the handshake 915 Initial = 0, 916 Handshake = 1, @@ -919,13 +919,13 @@ 919} 920 921impl SpaceId { -922 pub fn iter() -> impl Iterator<Item = Self> { +922 pub(crate) fn iter() -> impl Iterator<Item = Self> { 923 [Self::Initial, Self::Handshake, Self::Data].iter().cloned() 924 } 925 926 /// Returns the next higher packet space. 927 /// -928 /// Returns `None` if at `Data`. +928 /// Returns `None` if at [`SpaceId::Data`]. 929 pub fn next(&self) -> Option<Self> { 930 match self { 931 Self::Initial => Some(Self::Handshake), diff --git a/pr/255/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html b/pr/255/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html index 4afd5976c..bb409d1d1 100644 --- a/pr/255/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/range_set/array_range_set.rs.html @@ -56,157 +56,156 @@ 56 self.0.len() 57 } 58 -59 // TODO(@divma): consider removing -60 #[allow(unused)] -61 pub(crate) fn contains(&self, x: u64) -> bool { -62 for range in self.0.iter() { -63 if range.start > x { -64 // We only get here if there was no prior range that contained x -65 return false; -66 } else if range.contains(&x) { -67 return true; -68 } -69 } -70 false -71 } -72 -73 pub(crate) fn iter_range(&self, range: Range<u64>) -> impl Iterator<Item = Range<u64>> + '_ { -74 self.iter().filter_map(move |r| { -75 if r.end > range.start && r.start < range.end { -76 Some(r.start.max(range.start)..r.end.min(range.end)) -77 } else { -78 None -79 } -80 }) -81 } -82 -83 pub(crate) fn insert_one(&mut self, x: u64) -> bool { -84 self.insert(x..x + 1) -85 } -86 -87 pub(crate) fn insert(&mut self, x: Range<u64>) -> bool { -88 let mut result = false; -89 -90 if x.is_empty() { -91 // Don't try to deal with ranges where x.end <= x.start -92 return false; -93 } -94 -95 let mut idx = 0; -96 while idx != self.0.len() { -97 let range = &mut self.0[idx]; -98 -99 if range.start > x.end { -100 // The range is fully before this range and therefore not extensible. -101 // Add a new range to the left -102 self.0.insert(idx, x); -103 return true; -104 } else if range.start > x.start { -105 // The new range starts before this range but overlaps. -106 // Extend the current range to the left -107 // Note that we don't have to merge a potential left range, since -108 // this case would have been captured by merging the right range -109 // in the previous loop iteration -110 result = true; -111 range.start = x.start; -112 } -113 -114 // At this point we have handled all parts of the new range which -115 // are in front of the current range. Now we handle everything from -116 // the start of the current range -117 -118 if x.end <= range.end { -119 // Fully contained -120 return result; -121 } else if x.start <= range.end { -122 // Extend the current range to the end of the new range. -123 // Since it's not contained it must be bigger -124 range.end = x.end; -125 -126 // Merge all follow-up ranges which overlap -127 while idx != self.0.len() - 1 { -128 let curr = self.0[idx].clone(); -129 let next = self.0[idx + 1].clone(); -130 if curr.end >= next.start { -131 self.0[idx].end = next.end.max(curr.end); -132 self.0.remove(idx + 1); -133 } else { -134 break; -135 } -136 } -137 -138 return true; -139 } -140 -141 idx += 1; -142 } -143 -144 // Insert a range at the end -145 self.0.push(x); -146 true -147 } -148 -149 pub(crate) fn remove(&mut self, x: Range<u64>) -> bool { -150 let mut result = false; -151 -152 if x.is_empty() { -153 // Don't try to deal with ranges where x.end <= x.start -154 return false; -155 } -156 -157 let mut idx = 0; -158 while idx != self.0.len() && x.start != x.end { -159 let range = self.0[idx].clone(); -160 -161 if x.end <= range.start { -162 // The range is fully before this range -163 return result; -164 } else if x.start >= range.end { -165 // The range is fully after this range -166 idx += 1; -167 continue; -168 } -169 -170 // The range overlaps with this range -171 result = true; -172 -173 let left = range.start..x.start; -174 let right = x.end..range.end; -175 if left.is_empty() && right.is_empty() { -176 self.0.remove(idx); -177 } else if left.is_empty() { -178 self.0[idx] = right; -179 idx += 1; -180 } else if right.is_empty() { -181 self.0[idx] = left; -182 idx += 1; -183 } else { -184 self.0[idx] = right; -185 self.0.insert(idx, left); -186 idx += 2; -187 } -188 } -189 -190 result -191 } -192 -193 pub(crate) fn is_empty(&self) -> bool { -194 self.0.is_empty() -195 } -196 -197 pub(crate) fn pop_min(&mut self) -> Option<Range<u64>> { -198 if !self.0.is_empty() { -199 Some(self.0.remove(0)) -200 } else { -201 None -202 } -203 } -204 -205 pub(crate) fn min(&self) -> Option<u64> { -206 self.iter().next().map(|x| x.start) -207 } -208 -209 pub(crate) fn max(&self) -> Option<u64> { -210 self.iter().next_back().map(|x| x.end - 1) -211 } -212} \ No newline at end of file +59 #[cfg(test)] +60 pub(crate) fn contains(&self, x: u64) -> bool { +61 for range in self.0.iter() { +62 if range.start > x { +63 // We only get here if there was no prior range that contained x +64 return false; +65 } else if range.contains(&x) { +66 return true; +67 } +68 } +69 false +70 } +71 +72 pub(crate) fn iter_range(&self, range: Range<u64>) -> impl Iterator<Item = Range<u64>> + '_ { +73 self.iter().filter_map(move |r| { +74 if r.end > range.start && r.start < range.end { +75 Some(r.start.max(range.start)..r.end.min(range.end)) +76 } else { +77 None +78 } +79 }) +80 } +81 +82 pub(crate) fn insert_one(&mut self, x: u64) -> bool { +83 self.insert(x..x + 1) +84 } +85 +86 pub(crate) fn insert(&mut self, x: Range<u64>) -> bool { +87 let mut result = false; +88 +89 if x.is_empty() { +90 // Don't try to deal with ranges where x.end <= x.start +91 return false; +92 } +93 +94 let mut idx = 0; +95 while idx != self.0.len() { +96 let range = &mut self.0[idx]; +97 +98 if range.start > x.end { +99 // The range is fully before this range and therefore not extensible. +100 // Add a new range to the left +101 self.0.insert(idx, x); +102 return true; +103 } else if range.start > x.start { +104 // The new range starts before this range but overlaps. +105 // Extend the current range to the left +106 // Note that we don't have to merge a potential left range, since +107 // this case would have been captured by merging the right range +108 // in the previous loop iteration +109 result = true; +110 range.start = x.start; +111 } +112 +113 // At this point we have handled all parts of the new range which +114 // are in front of the current range. Now we handle everything from +115 // the start of the current range +116 +117 if x.end <= range.end { +118 // Fully contained +119 return result; +120 } else if x.start <= range.end { +121 // Extend the current range to the end of the new range. +122 // Since it's not contained it must be bigger +123 range.end = x.end; +124 +125 // Merge all follow-up ranges which overlap +126 while idx != self.0.len() - 1 { +127 let curr = self.0[idx].clone(); +128 let next = self.0[idx + 1].clone(); +129 if curr.end >= next.start { +130 self.0[idx].end = next.end.max(curr.end); +131 self.0.remove(idx + 1); +132 } else { +133 break; +134 } +135 } +136 +137 return true; +138 } +139 +140 idx += 1; +141 } +142 +143 // Insert a range at the end +144 self.0.push(x); +145 true +146 } +147 +148 pub(crate) fn remove(&mut self, x: Range<u64>) -> bool { +149 let mut result = false; +150 +151 if x.is_empty() { +152 // Don't try to deal with ranges where x.end <= x.start +153 return false; +154 } +155 +156 let mut idx = 0; +157 while idx != self.0.len() && x.start != x.end { +158 let range = self.0[idx].clone(); +159 +160 if x.end <= range.start { +161 // The range is fully before this range +162 return result; +163 } else if x.start >= range.end { +164 // The range is fully after this range +165 idx += 1; +166 continue; +167 } +168 +169 // The range overlaps with this range +170 result = true; +171 +172 let left = range.start..x.start; +173 let right = x.end..range.end; +174 if left.is_empty() && right.is_empty() { +175 self.0.remove(idx); +176 } else if left.is_empty() { +177 self.0[idx] = right; +178 idx += 1; +179 } else if right.is_empty() { +180 self.0[idx] = left; +181 idx += 1; +182 } else { +183 self.0[idx] = right; +184 self.0.insert(idx, left); +185 idx += 2; +186 } +187 } +188 +189 result +190 } +191 +192 pub(crate) fn is_empty(&self) -> bool { +193 self.0.is_empty() +194 } +195 +196 pub(crate) fn pop_min(&mut self) -> Option<Range<u64>> { +197 if !self.0.is_empty() { +198 Some(self.0.remove(0)) +199 } else { +200 None +201 } +202 } +203 +204 pub(crate) fn min(&self) -> Option<u64> { +205 self.iter().next().map(|x| x.start) +206 } +207 +208 pub(crate) fn max(&self) -> Option<u64> { +209 self.iter().next_back().map(|x| x.end - 1) +210 } +211} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/transport_error.rs.html b/pr/255/docs/src/iroh_quinn_proto/transport_error.rs.html index 068d92426..1fe018217 100644 --- a/pr/255/docs/src/iroh_quinn_proto/transport_error.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/transport_error.rs.html @@ -158,8 +158,8 @@ 158 KEY_UPDATE_ERROR(0xE) "key update error"; 159 AEAD_LIMIT_REACHED(0xF) "the endpoint has reached the confidentiality or integrity limit for the AEAD algorithm"; 160 NO_VIABLE_PATH(0x10) "no viable network path exists"; -161 APPLICATION_ABANDON_PATH(0x004150504142414e) "Path abandoned at the application's request"; -162 PATH_RESOURCE_LIMIT_REACHED(0x0052534c494d4954) "Path abandoned due to resource limitations in the transport"; -163 PATH_UNSTABLE_OR_POOR(0x00554e5f494e5446) "Path abandoned due to unstable interfaces"; -164 NO_CID_AVAILABLE_FOR_PATH(0x004e4f5f4349445f) "Path abandoned due to no available connection IDs for the path"; +161 APPLICATION_ABANDON_PATH(0x3e) "Path abandoned at the application's request"; +162 PATH_RESOURCE_LIMIT_REACHED(0x3e75) "Path abandoned due to resource limitations in the transport"; +163 PATH_UNSTABLE_OR_POOR(0x3e76) "Path abandoned due to unstable interfaces"; +164 NO_CID_AVAILABLE_FOR_PATH(0x3e77) "Path abandoned due to no available connection IDs for the path"; 165} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/transport_parameters.rs.html b/pr/255/docs/src/iroh_quinn_proto/transport_parameters.rs.html index ec1947c1f..61258e94e 100644 --- a/pr/255/docs/src/iroh_quinn_proto/transport_parameters.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/transport_parameters.rs.html @@ -327,652 +327,653 @@ 327impl TransportParameters { 328 /// Encode `TransportParameters` into buffer 329 pub fn write<W: BufMut>(&self, w: &mut W) { -330 for idx in self -331 .write_order -332 .as_ref() -333 .unwrap_or(&std::array::from_fn(|i| i as u8)) -334 { -335 let id = TransportParameterId::SUPPORTED[*idx as usize]; -336 match id { -337 TransportParameterId::ReservedTransportParameter => { -338 if let Some(param) = self.grease_transport_parameter { -339 param.write(w); -340 } -341 } -342 TransportParameterId::StatelessResetToken => { -343 if let Some(ref x) = self.stateless_reset_token { -344 w.write_var(id as u64); -345 w.write_var(16); -346 w.put_slice(x); -347 } -348 } -349 TransportParameterId::DisableActiveMigration => { -350 if self.disable_active_migration { -351 w.write_var(id as u64); -352 w.write_var(0); -353 } -354 } -355 TransportParameterId::MaxDatagramFrameSize => { -356 if let Some(x) = self.max_datagram_frame_size { -357 w.write_var(id as u64); -358 w.write_var(x.size() as u64); -359 w.write(x); -360 } -361 } -362 TransportParameterId::PreferredAddress => { -363 if let Some(ref x) = self.preferred_address { -364 w.write_var(id as u64); -365 w.write_var(x.wire_size() as u64); -366 x.write(w); -367 } -368 } -369 TransportParameterId::OriginalDestinationConnectionId => { -370 if let Some(ref cid) = self.original_dst_cid { -371 w.write_var(id as u64); -372 w.write_var(cid.len() as u64); -373 w.put_slice(cid); -374 } -375 } -376 TransportParameterId::InitialSourceConnectionId => { -377 if let Some(ref cid) = self.initial_src_cid { -378 w.write_var(id as u64); -379 w.write_var(cid.len() as u64); -380 w.put_slice(cid); -381 } -382 } -383 TransportParameterId::RetrySourceConnectionId => { -384 if let Some(ref cid) = self.retry_src_cid { -385 w.write_var(id as u64); -386 w.write_var(cid.len() as u64); -387 w.put_slice(cid); -388 } -389 } -390 TransportParameterId::GreaseQuicBit => { -391 if self.grease_quic_bit { -392 w.write_var(id as u64); -393 w.write_var(0); -394 } -395 } -396 TransportParameterId::MinAckDelayDraft07 => { -397 if let Some(x) = self.min_ack_delay { -398 w.write_var(id as u64); -399 w.write_var(x.size() as u64); -400 w.write(x); -401 } -402 } -403 TransportParameterId::ObservedAddr => { -404 if let Some(varint_role) = self.address_discovery_role.as_transport_parameter() -405 { -406 w.write_var(id as u64); -407 w.write_var(varint_role.size() as u64); -408 w.write(varint_role); -409 } -410 } -411 TransportParameterId::InitialMaxPathId => { -412 if let Some(val) = self.initial_max_path_id { -413 w.write_var(id as u64); -414 w.write_var(val.size() as u64); -415 w.write(val); -416 } -417 } -418 TransportParameterId::IrohNatTraversal => { -419 if let Some(val) = self.max_remote_nat_traversal_addresses { -420 w.write_var(id as u64); -421 w.write(VarInt(1)); -422 w.write(val.get()); -423 } -424 } -425 id => { -426 macro_rules! write_params { -427 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => { -428 match id { -429 $(TransportParameterId::$id => { -430 if self.$name.0 != $default { -431 w.write_var(id as u64); -432 w.write(VarInt::try_from(self.$name.size()).unwrap()); -433 w.write(self.$name); -434 } -435 })*, -436 _ => { -437 unimplemented!("Missing implementation of write for transport parameter with code {id:?}"); -438 } -439 } -440 } -441 } -442 apply_params!(write_params); -443 } -444 } -445 } -446 } -447 -448 /// Decode `TransportParameters` from buffer -449 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> { -450 // Initialize to protocol-specified defaults -451 let mut params = Self::default(); -452 -453 // State to check for duplicate transport parameters. -454 macro_rules! param_state { -455 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {{ -456 struct ParamState { -457 $($name: bool,)* -458 } -459 -460 ParamState { -461 $($name: false,)* -462 } -463 }} -464 } -465 let mut got = apply_params!(param_state); -466 -467 while r.has_remaining() { -468 let id = r.get_var()?; -469 let len = r.get_var()?; -470 if (r.remaining() as u64) < len { -471 return Err(Error::Malformed); -472 } -473 let len = len as usize; -474 let Ok(id) = TransportParameterId::try_from(id) else { -475 // unknown transport parameters are ignored -476 r.advance(len); -477 continue; -478 }; -479 -480 match id { -481 TransportParameterId::OriginalDestinationConnectionId => { -482 decode_cid(len, &mut params.original_dst_cid, r)? -483 } -484 TransportParameterId::StatelessResetToken => { -485 if len != 16 || params.stateless_reset_token.is_some() { -486 return Err(Error::Malformed); -487 } -488 let mut tok = [0; RESET_TOKEN_SIZE]; -489 r.copy_to_slice(&mut tok); -490 params.stateless_reset_token = Some(tok.into()); -491 } -492 TransportParameterId::DisableActiveMigration => { -493 if len != 0 || params.disable_active_migration { -494 return Err(Error::Malformed); -495 } -496 params.disable_active_migration = true; -497 } -498 TransportParameterId::PreferredAddress => { -499 if params.preferred_address.is_some() { -500 return Err(Error::Malformed); -501 } -502 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?); -503 } -504 TransportParameterId::InitialSourceConnectionId => { -505 decode_cid(len, &mut params.initial_src_cid, r)? -506 } -507 TransportParameterId::RetrySourceConnectionId => { -508 decode_cid(len, &mut params.retry_src_cid, r)? -509 } -510 TransportParameterId::MaxDatagramFrameSize => { -511 if len > 8 || params.max_datagram_frame_size.is_some() { -512 return Err(Error::Malformed); -513 } -514 params.max_datagram_frame_size = Some(r.get().unwrap()); -515 } -516 TransportParameterId::GreaseQuicBit => match len { -517 0 => params.grease_quic_bit = true, -518 _ => return Err(Error::Malformed), -519 }, -520 TransportParameterId::MinAckDelayDraft07 => { -521 params.min_ack_delay = Some(r.get().unwrap()) -522 } -523 TransportParameterId::ObservedAddr => { -524 if !params.address_discovery_role.is_disabled() { -525 // duplicate parameter -526 return Err(Error::Malformed); -527 } -528 let value: VarInt = r.get()?; -529 if len != value.size() { -530 return Err(Error::Malformed); -531 } -532 params.address_discovery_role = value.try_into()?; -533 tracing::debug!( -534 role = ?params.address_discovery_role, -535 "address discovery enabled for peer" -536 ); -537 } -538 TransportParameterId::InitialMaxPathId => { -539 if params.initial_max_path_id.is_some() { -540 return Err(Error::Malformed); -541 } -542 -543 let value: PathId = r.get()?; -544 if len != value.size() { -545 return Err(Error::Malformed); -546 } -547 -548 params.initial_max_path_id = Some(value); -549 } -550 TransportParameterId::IrohNatTraversal => { -551 if params.max_remote_nat_traversal_addresses.is_some() { -552 return Err(Error::Malformed); -553 } -554 if len != 1 { -555 return Err(Error::Malformed); -556 } -557 -558 let value: u8 = r.get()?; -559 let value = NonZeroU8::new(value).ok_or(Error::IllegalValue)?; -560 -561 params.max_remote_nat_traversal_addresses = Some(value); -562 } -563 _ => { -564 macro_rules! parse { -565 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => { -566 match id { -567 $(TransportParameterId::$id => { -568 let value = r.get::<VarInt>()?; -569 if len != value.size() || got.$name { return Err(Error::Malformed); } -570 params.$name = value.into(); -571 got.$name = true; -572 })* -573 _ => r.advance(len), -574 } -575 } -576 } -577 apply_params!(parse); -578 } -579 } -580 } -581 -582 // Semantic validation -583 -584 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.26.1 -585 if params.ack_delay_exponent.0 > 20 -586 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.28.1 -587 || params.max_ack_delay.0 >= 1 << 14 -588 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-6.2.1 -589 || params.active_connection_id_limit.0 < 2 -590 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.10.1 -591 || params.max_udp_payload_size.0 < 1200 -592 // https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2 -593 || params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT -594 || params.initial_max_streams_uni.0 > MAX_STREAM_COUNT -595 // https://www.ietf.org/archive/id/draft-ietf-quic-ack-frequency-08.html#section-3-4 -596 || params.min_ack_delay.is_some_and(|min_ack_delay| { -597 // min_ack_delay uses microseconds, whereas max_ack_delay uses milliseconds -598 min_ack_delay.0 > params.max_ack_delay.0 * 1_000 -599 }) -600 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-8 -601 || (side.is_server() -602 && (params.original_dst_cid.is_some() -603 || params.preferred_address.is_some() -604 || params.retry_src_cid.is_some() -605 || params.stateless_reset_token.is_some())) -606 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.38.1 -607 || params -608 .preferred_address.is_some_and(|x| x.connection_id.is_empty()) -609 { -610 return Err(Error::IllegalValue); -611 } -612 -613 Ok(params) -614 } -615} -616 -617/// A reserved transport parameter. -618/// -619/// It has an identifier of the form 31 * N + 27 for the integer value of N. -620/// Such identifiers are reserved to exercise the requirement that unknown transport parameters be ignored. -621/// The reserved transport parameter has no semantics and can carry arbitrary values. -622/// It may be included in transport parameters sent to the peer, and should be ignored when received. -623/// -624/// See spec: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> -625#[derive(Debug, Copy, Clone, Eq, PartialEq)] -626pub(crate) struct ReservedTransportParameter { -627 /// The reserved identifier of the transport parameter -628 id: VarInt, -629 -630 /// Buffer to store the parameter payload -631 payload: [u8; Self::MAX_PAYLOAD_LEN], -632 -633 /// The number of bytes to include in the wire format from the `payload` buffer -634 payload_len: usize, -635} -636 -637impl ReservedTransportParameter { -638 /// Generates a transport parameter with a random payload and a reserved ID. -639 /// -640 /// The implementation is inspired by quic-go and quiche: -641 /// 1. <https://github.com/quic-go/quic-go/blob/3e0a67b2476e1819752f04d75968de042b197b56/internal/wire/transport_parameters.go#L338-L344> -642 /// 2. <https://github.com/google/quiche/blob/cb1090b20c40e2f0815107857324e99acf6ec567/quiche/quic/core/crypto/transport_parameters.cc#L843-L860> -643 fn random(rng: &mut impl RngCore) -> Self { -644 let id = Self::generate_reserved_id(rng); -645 -646 let payload_len = rng.random_range(0..Self::MAX_PAYLOAD_LEN); -647 -648 let payload = { -649 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN]; -650 rng.fill_bytes(&mut slice[..payload_len]); -651 slice -652 }; -653 -654 Self { -655 id, -656 payload, -657 payload_len, -658 } -659 } -660 -661 fn write(&self, w: &mut impl BufMut) { -662 w.write_var(self.id.0); -663 w.write_var(self.payload_len as u64); -664 w.put_slice(&self.payload[..self.payload_len]); -665 } -666 -667 /// Generates a random reserved identifier of the form `31 * N + 27`, as required by RFC 9000. -668 /// Reserved transport parameter identifiers are used to test compliance with the requirement -669 /// that unknown transport parameters must be ignored by peers. -670 /// See: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> and <https://www.rfc-editor.org/rfc/rfc9000.html#section-22.3> -671 fn generate_reserved_id(rng: &mut impl RngCore) -> VarInt { -672 let id = { -673 let rand = rng.random_range(0u64..(1 << 62) - 27); -674 let n = rand / 31; -675 31 * n + 27 -676 }; -677 debug_assert!( -678 id % 31 == 27, -679 "generated id does not have the form of 31 * N + 27" -680 ); -681 VarInt::from_u64(id).expect( -682 "generated id does fit into range of allowed transport parameter IDs: [0; 2^62)", -683 ) -684 } -685 -686 /// The maximum length of the payload to include as the parameter payload. -687 /// This value is not a specification-imposed limit but is chosen to match -688 /// the limit used by other implementations of QUIC, e.g., quic-go and quiche. -689 const MAX_PAYLOAD_LEN: usize = 16; -690} -691 -692#[repr(u64)] -693#[derive(Debug, Clone, Copy, PartialEq, Eq)] -694pub(crate) enum TransportParameterId { -695 // https://www.rfc-editor.org/rfc/rfc9000.html#iana-tp-table -696 OriginalDestinationConnectionId = 0x00, -697 MaxIdleTimeout = 0x01, -698 StatelessResetToken = 0x02, -699 MaxUdpPayloadSize = 0x03, -700 InitialMaxData = 0x04, -701 InitialMaxStreamDataBidiLocal = 0x05, -702 InitialMaxStreamDataBidiRemote = 0x06, -703 InitialMaxStreamDataUni = 0x07, -704 InitialMaxStreamsBidi = 0x08, -705 InitialMaxStreamsUni = 0x09, -706 AckDelayExponent = 0x0A, -707 MaxAckDelay = 0x0B, -708 DisableActiveMigration = 0x0C, -709 PreferredAddress = 0x0D, -710 ActiveConnectionIdLimit = 0x0E, -711 InitialSourceConnectionId = 0x0F, -712 RetrySourceConnectionId = 0x10, -713 -714 // Smallest possible ID of reserved transport parameter https://datatracker.ietf.org/doc/html/rfc9000#section-22.3 -715 ReservedTransportParameter = 0x1B, -716 -717 // https://www.rfc-editor.org/rfc/rfc9221.html#section-3 -718 MaxDatagramFrameSize = 0x20, -719 -720 // https://www.rfc-editor.org/rfc/rfc9287.html#section-3 -721 GreaseQuicBit = 0x2AB2, -722 -723 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency#section-10.1 -724 MinAckDelayDraft07 = 0xFF04DE1B, -725 -726 // <https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/> -727 ObservedAddr = 0x9f81a176, -728 -729 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-multipath -730 InitialMaxPathId = 0x0f739bbc1b666d0c, -731 -732 // inspired by https://www.ietf.org/archive/id/draft-seemann-quic-nat-traversal-02.html, -733 // simplified to iroh's needs -734 IrohNatTraversal = 0x3d7f91120401, -735} -736 -737impl TransportParameterId { -738 /// Array with all supported transport parameter IDs -739 const SUPPORTED: [Self; 24] = [ -740 Self::MaxIdleTimeout, -741 Self::MaxUdpPayloadSize, -742 Self::InitialMaxData, -743 Self::InitialMaxStreamDataBidiLocal, -744 Self::InitialMaxStreamDataBidiRemote, -745 Self::InitialMaxStreamDataUni, -746 Self::InitialMaxStreamsBidi, -747 Self::InitialMaxStreamsUni, -748 Self::AckDelayExponent, -749 Self::MaxAckDelay, -750 Self::ActiveConnectionIdLimit, -751 Self::ReservedTransportParameter, -752 Self::StatelessResetToken, -753 Self::DisableActiveMigration, -754 Self::MaxDatagramFrameSize, -755 Self::PreferredAddress, -756 Self::OriginalDestinationConnectionId, -757 Self::InitialSourceConnectionId, -758 Self::RetrySourceConnectionId, -759 Self::GreaseQuicBit, -760 Self::MinAckDelayDraft07, -761 Self::ObservedAddr, -762 Self::InitialMaxPathId, -763 Self::IrohNatTraversal, -764 ]; -765} -766 -767impl std::cmp::PartialEq<u64> for TransportParameterId { -768 fn eq(&self, other: &u64) -> bool { -769 *other == (*self as u64) -770 } -771} -772 -773impl TryFrom<u64> for TransportParameterId { -774 type Error = (); -775 -776 fn try_from(value: u64) -> Result<Self, Self::Error> { -777 let param = match value { -778 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout, -779 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize, -780 id if Self::InitialMaxData == id => Self::InitialMaxData, -781 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal, -782 id if Self::InitialMaxStreamDataBidiRemote == id => { -783 Self::InitialMaxStreamDataBidiRemote -784 } -785 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni, -786 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi, -787 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni, -788 id if Self::AckDelayExponent == id => Self::AckDelayExponent, -789 id if Self::MaxAckDelay == id => Self::MaxAckDelay, -790 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit, -791 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter, -792 id if Self::StatelessResetToken == id => Self::StatelessResetToken, -793 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration, -794 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize, -795 id if Self::PreferredAddress == id => Self::PreferredAddress, -796 id if Self::OriginalDestinationConnectionId == id => { -797 Self::OriginalDestinationConnectionId -798 } -799 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId, -800 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId, -801 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit, -802 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07, -803 id if Self::ObservedAddr == id => Self::ObservedAddr, -804 id if Self::InitialMaxPathId == id => Self::InitialMaxPathId, -805 id if Self::IrohNatTraversal == id => Self::IrohNatTraversal, -806 _ => return Err(()), -807 }; -808 Ok(param) -809 } -810} -811 -812fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> { -813 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len { -814 return Err(Error::Malformed); -815 } -816 -817 *value = Some(ConnectionId::from_buf(r, len)); -818 Ok(()) -819} -820 -821#[cfg(test)] -822mod test { -823 -824 use super::*; -825 -826 #[test] -827 fn coding() { -828 let mut buf = Vec::new(); -829 let params = TransportParameters { -830 initial_src_cid: Some(ConnectionId::new(&[])), -831 original_dst_cid: Some(ConnectionId::new(&[])), -832 initial_max_streams_bidi: 16u32.into(), -833 initial_max_streams_uni: 16u32.into(), -834 ack_delay_exponent: 2u32.into(), -835 max_udp_payload_size: 1200u32.into(), -836 preferred_address: Some(PreferredAddress { -837 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)), -838 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)), -839 connection_id: ConnectionId::new(&[0x42]), -840 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(), -841 }), -842 grease_quic_bit: true, -843 min_ack_delay: Some(2_000u32.into()), -844 address_discovery_role: address_discovery::Role::SendOnly, -845 initial_max_path_id: Some(PathId::MAX), -846 max_remote_nat_traversal_addresses: Some(5u8.try_into().unwrap()), -847 ..TransportParameters::default() -848 }; -849 params.write(&mut buf); -850 assert_eq!( -851 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(), -852 params -853 ); -854 } -855 -856 #[test] -857 fn reserved_transport_parameter_generate_reserved_id() { -858 let mut rngs = [ -859 StepRng(0), -860 StepRng(1), -861 StepRng(27), -862 StepRng(31), -863 StepRng(u32::MAX as u64), -864 StepRng(u32::MAX as u64 - 1), -865 StepRng(u32::MAX as u64 + 1), -866 StepRng(u32::MAX as u64 - 27), -867 StepRng(u32::MAX as u64 + 27), -868 StepRng(u32::MAX as u64 - 31), -869 StepRng(u32::MAX as u64 + 31), -870 StepRng(u64::MAX), -871 StepRng(u64::MAX - 1), -872 StepRng(u64::MAX - 27), -873 StepRng(u64::MAX - 31), -874 StepRng(1 << 62), -875 StepRng((1 << 62) - 1), -876 StepRng((1 << 62) + 1), -877 StepRng((1 << 62) - 27), -878 StepRng((1 << 62) + 27), -879 StepRng((1 << 62) - 31), -880 StepRng((1 << 62) + 31), -881 ]; -882 for rng in &mut rngs { -883 let id = ReservedTransportParameter::generate_reserved_id(rng); -884 assert!(id.0 % 31 == 27) -885 } -886 } -887 -888 struct StepRng(u64); -889 -890 impl RngCore for StepRng { -891 #[inline] -892 fn next_u32(&mut self) -> u32 { -893 self.next_u64() as u32 -894 } -895 -896 #[inline] -897 fn next_u64(&mut self) -> u64 { -898 let res = self.0; -899 self.0 = self.0.wrapping_add(1); -900 res -901 } -902 -903 #[inline] -904 fn fill_bytes(&mut self, dst: &mut [u8]) { -905 let mut left = dst; -906 while left.len() >= 8 { -907 let (l, r) = left.split_at_mut(8); -908 left = r; -909 l.copy_from_slice(&self.next_u64().to_le_bytes()); -910 } -911 let n = left.len(); -912 if n > 0 { -913 left.copy_from_slice(&self.next_u32().to_le_bytes()[..n]); -914 } -915 } -916 } -917 -918 #[test] -919 fn reserved_transport_parameter_ignored_when_read() { -920 let mut buf = Vec::new(); -921 let reserved_parameter = ReservedTransportParameter::random(&mut rand::rng()); -922 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN); -923 assert!(reserved_parameter.id.0 % 31 == 27); -924 -925 reserved_parameter.write(&mut buf); -926 assert!(!buf.is_empty()); -927 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap(); -928 assert_eq!(read_params, TransportParameters::default()); -929 } -930 -931 #[test] -932 fn read_semantic_validation() { -933 #[allow(clippy::type_complexity)] -934 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![ -935 Box::new(|t| { -936 // This min_ack_delay is bigger than max_ack_delay! -937 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1; -938 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap()) -939 }), -940 Box::new(|t| { -941 // Preferred address can only be sent by senders (and we are reading the transport -942 // params as a client) -943 t.preferred_address = Some(PreferredAddress { -944 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)), -945 address_v6: None, -946 connection_id: ConnectionId::new(&[]), -947 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(), -948 }) -949 }), -950 ]; -951 -952 for mut builder in illegal_params_builders { -953 let mut buf = Vec::new(); -954 let mut params = TransportParameters::default(); -955 builder(&mut params); -956 params.write(&mut buf); -957 -958 assert_eq!( -959 TransportParameters::read(Side::Server, &mut buf.as_slice()), -960 Err(Error::IllegalValue) -961 ); -962 } -963 } -964 -965 #[test] -966 fn resumption_params_validation() { -967 let high_limit = TransportParameters { -968 initial_max_streams_uni: 32u32.into(), -969 ..TransportParameters::default() -970 }; -971 let low_limit = TransportParameters { -972 initial_max_streams_uni: 16u32.into(), -973 ..TransportParameters::default() -974 }; -975 high_limit.validate_resumption_from(&low_limit).unwrap(); -976 low_limit.validate_resumption_from(&high_limit).unwrap_err(); -977 } -978} \ No newline at end of file +330 let ids = match &self.write_order { +331 Some(order) => order, +332 None => &std::array::from_fn(|i| i as u8), +333 }; +334 +335 for idx in ids { +336 let id = TransportParameterId::SUPPORTED[*idx as usize]; +337 match id { +338 TransportParameterId::ReservedTransportParameter => { +339 if let Some(param) = self.grease_transport_parameter { +340 param.write(w); +341 } +342 } +343 TransportParameterId::StatelessResetToken => { +344 if let Some(ref x) = self.stateless_reset_token { +345 w.write_var(id as u64); +346 w.write_var(16); +347 w.put_slice(x); +348 } +349 } +350 TransportParameterId::DisableActiveMigration => { +351 if self.disable_active_migration { +352 w.write_var(id as u64); +353 w.write_var(0); +354 } +355 } +356 TransportParameterId::MaxDatagramFrameSize => { +357 if let Some(x) = self.max_datagram_frame_size { +358 w.write_var(id as u64); +359 w.write_var(x.size() as u64); +360 w.write(x); +361 } +362 } +363 TransportParameterId::PreferredAddress => { +364 if let Some(ref x) = self.preferred_address { +365 w.write_var(id as u64); +366 w.write_var(x.wire_size() as u64); +367 x.write(w); +368 } +369 } +370 TransportParameterId::OriginalDestinationConnectionId => { +371 if let Some(ref cid) = self.original_dst_cid { +372 w.write_var(id as u64); +373 w.write_var(cid.len() as u64); +374 w.put_slice(cid); +375 } +376 } +377 TransportParameterId::InitialSourceConnectionId => { +378 if let Some(ref cid) = self.initial_src_cid { +379 w.write_var(id as u64); +380 w.write_var(cid.len() as u64); +381 w.put_slice(cid); +382 } +383 } +384 TransportParameterId::RetrySourceConnectionId => { +385 if let Some(ref cid) = self.retry_src_cid { +386 w.write_var(id as u64); +387 w.write_var(cid.len() as u64); +388 w.put_slice(cid); +389 } +390 } +391 TransportParameterId::GreaseQuicBit => { +392 if self.grease_quic_bit { +393 w.write_var(id as u64); +394 w.write_var(0); +395 } +396 } +397 TransportParameterId::MinAckDelayDraft07 => { +398 if let Some(x) = self.min_ack_delay { +399 w.write_var(id as u64); +400 w.write_var(x.size() as u64); +401 w.write(x); +402 } +403 } +404 TransportParameterId::ObservedAddr => { +405 if let Some(varint_role) = self.address_discovery_role.as_transport_parameter() +406 { +407 w.write_var(id as u64); +408 w.write_var(varint_role.size() as u64); +409 w.write(varint_role); +410 } +411 } +412 TransportParameterId::InitialMaxPathId => { +413 if let Some(val) = self.initial_max_path_id { +414 w.write_var(id as u64); +415 w.write_var(val.size() as u64); +416 w.write(val); +417 } +418 } +419 TransportParameterId::IrohNatTraversal => { +420 if let Some(val) = self.max_remote_nat_traversal_addresses { +421 w.write_var(id as u64); +422 w.write(VarInt(1)); +423 w.write(val.get()); +424 } +425 } +426 id => { +427 macro_rules! write_params { +428 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => { +429 match id { +430 $(TransportParameterId::$id => { +431 if self.$name.0 != $default { +432 w.write_var(id as u64); +433 w.write(VarInt::try_from(self.$name.size()).unwrap()); +434 w.write(self.$name); +435 } +436 })*, +437 _ => { +438 unimplemented!("Missing implementation of write for transport parameter with code {id:?}"); +439 } +440 } +441 } +442 } +443 apply_params!(write_params); +444 } +445 } +446 } +447 } +448 +449 /// Decode `TransportParameters` from buffer +450 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> { +451 // Initialize to protocol-specified defaults +452 let mut params = Self::default(); +453 +454 // State to check for duplicate transport parameters. +455 macro_rules! param_state { +456 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {{ +457 struct ParamState { +458 $($name: bool,)* +459 } +460 +461 ParamState { +462 $($name: false,)* +463 } +464 }} +465 } +466 let mut got = apply_params!(param_state); +467 +468 while r.has_remaining() { +469 let id = r.get_var()?; +470 let len = r.get_var()?; +471 if (r.remaining() as u64) < len { +472 return Err(Error::Malformed); +473 } +474 let len = len as usize; +475 let Ok(id) = TransportParameterId::try_from(id) else { +476 // unknown transport parameters are ignored +477 r.advance(len); +478 continue; +479 }; +480 +481 match id { +482 TransportParameterId::OriginalDestinationConnectionId => { +483 decode_cid(len, &mut params.original_dst_cid, r)? +484 } +485 TransportParameterId::StatelessResetToken => { +486 if len != 16 || params.stateless_reset_token.is_some() { +487 return Err(Error::Malformed); +488 } +489 let mut tok = [0; RESET_TOKEN_SIZE]; +490 r.copy_to_slice(&mut tok); +491 params.stateless_reset_token = Some(tok.into()); +492 } +493 TransportParameterId::DisableActiveMigration => { +494 if len != 0 || params.disable_active_migration { +495 return Err(Error::Malformed); +496 } +497 params.disable_active_migration = true; +498 } +499 TransportParameterId::PreferredAddress => { +500 if params.preferred_address.is_some() { +501 return Err(Error::Malformed); +502 } +503 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?); +504 } +505 TransportParameterId::InitialSourceConnectionId => { +506 decode_cid(len, &mut params.initial_src_cid, r)? +507 } +508 TransportParameterId::RetrySourceConnectionId => { +509 decode_cid(len, &mut params.retry_src_cid, r)? +510 } +511 TransportParameterId::MaxDatagramFrameSize => { +512 if len > 8 || params.max_datagram_frame_size.is_some() { +513 return Err(Error::Malformed); +514 } +515 params.max_datagram_frame_size = Some(r.get().unwrap()); +516 } +517 TransportParameterId::GreaseQuicBit => match len { +518 0 => params.grease_quic_bit = true, +519 _ => return Err(Error::Malformed), +520 }, +521 TransportParameterId::MinAckDelayDraft07 => { +522 params.min_ack_delay = Some(r.get().unwrap()) +523 } +524 TransportParameterId::ObservedAddr => { +525 if !params.address_discovery_role.is_disabled() { +526 // duplicate parameter +527 return Err(Error::Malformed); +528 } +529 let value: VarInt = r.get()?; +530 if len != value.size() { +531 return Err(Error::Malformed); +532 } +533 params.address_discovery_role = value.try_into()?; +534 tracing::debug!( +535 role = ?params.address_discovery_role, +536 "address discovery enabled for peer" +537 ); +538 } +539 TransportParameterId::InitialMaxPathId => { +540 if params.initial_max_path_id.is_some() { +541 return Err(Error::Malformed); +542 } +543 +544 let value: PathId = r.get()?; +545 if len != value.size() { +546 return Err(Error::Malformed); +547 } +548 +549 params.initial_max_path_id = Some(value); +550 } +551 TransportParameterId::IrohNatTraversal => { +552 if params.max_remote_nat_traversal_addresses.is_some() { +553 return Err(Error::Malformed); +554 } +555 if len != 1 { +556 return Err(Error::Malformed); +557 } +558 +559 let value: u8 = r.get()?; +560 let value = NonZeroU8::new(value).ok_or(Error::IllegalValue)?; +561 +562 params.max_remote_nat_traversal_addresses = Some(value); +563 } +564 _ => { +565 macro_rules! parse { +566 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => { +567 match id { +568 $(TransportParameterId::$id => { +569 let value = r.get::<VarInt>()?; +570 if len != value.size() || got.$name { return Err(Error::Malformed); } +571 params.$name = value.into(); +572 got.$name = true; +573 })* +574 _ => r.advance(len), +575 } +576 } +577 } +578 apply_params!(parse); +579 } +580 } +581 } +582 +583 // Semantic validation +584 +585 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.26.1 +586 if params.ack_delay_exponent.0 > 20 +587 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.28.1 +588 || params.max_ack_delay.0 >= 1 << 14 +589 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-6.2.1 +590 || params.active_connection_id_limit.0 < 2 +591 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.10.1 +592 || params.max_udp_payload_size.0 < 1200 +593 // https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2 +594 || params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT +595 || params.initial_max_streams_uni.0 > MAX_STREAM_COUNT +596 // https://www.ietf.org/archive/id/draft-ietf-quic-ack-frequency-08.html#section-3-4 +597 || params.min_ack_delay.is_some_and(|min_ack_delay| { +598 // min_ack_delay uses microseconds, whereas max_ack_delay uses milliseconds +599 min_ack_delay.0 > params.max_ack_delay.0 * 1_000 +600 }) +601 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-8 +602 || (side.is_server() +603 && (params.original_dst_cid.is_some() +604 || params.preferred_address.is_some() +605 || params.retry_src_cid.is_some() +606 || params.stateless_reset_token.is_some())) +607 // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.38.1 +608 || params +609 .preferred_address.is_some_and(|x| x.connection_id.is_empty()) +610 { +611 return Err(Error::IllegalValue); +612 } +613 +614 Ok(params) +615 } +616} +617 +618/// A reserved transport parameter. +619/// +620/// It has an identifier of the form 31 * N + 27 for the integer value of N. +621/// Such identifiers are reserved to exercise the requirement that unknown transport parameters be ignored. +622/// The reserved transport parameter has no semantics and can carry arbitrary values. +623/// It may be included in transport parameters sent to the peer, and should be ignored when received. +624/// +625/// See spec: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> +626#[derive(Debug, Copy, Clone, Eq, PartialEq)] +627pub(crate) struct ReservedTransportParameter { +628 /// The reserved identifier of the transport parameter +629 id: VarInt, +630 +631 /// Buffer to store the parameter payload +632 payload: [u8; Self::MAX_PAYLOAD_LEN], +633 +634 /// The number of bytes to include in the wire format from the `payload` buffer +635 payload_len: usize, +636} +637 +638impl ReservedTransportParameter { +639 /// Generates a transport parameter with a random payload and a reserved ID. +640 /// +641 /// The implementation is inspired by quic-go and quiche: +642 /// 1. <https://github.com/quic-go/quic-go/blob/3e0a67b2476e1819752f04d75968de042b197b56/internal/wire/transport_parameters.go#L338-L344> +643 /// 2. <https://github.com/google/quiche/blob/cb1090b20c40e2f0815107857324e99acf6ec567/quiche/quic/core/crypto/transport_parameters.cc#L843-L860> +644 fn random(rng: &mut impl RngCore) -> Self { +645 let id = Self::generate_reserved_id(rng); +646 +647 let payload_len = rng.random_range(0..Self::MAX_PAYLOAD_LEN); +648 +649 let payload = { +650 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN]; +651 rng.fill_bytes(&mut slice[..payload_len]); +652 slice +653 }; +654 +655 Self { +656 id, +657 payload, +658 payload_len, +659 } +660 } +661 +662 fn write(&self, w: &mut impl BufMut) { +663 w.write_var(self.id.0); +664 w.write_var(self.payload_len as u64); +665 w.put_slice(&self.payload[..self.payload_len]); +666 } +667 +668 /// Generates a random reserved identifier of the form `31 * N + 27`, as required by RFC 9000. +669 /// Reserved transport parameter identifiers are used to test compliance with the requirement +670 /// that unknown transport parameters must be ignored by peers. +671 /// See: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> and <https://www.rfc-editor.org/rfc/rfc9000.html#section-22.3> +672 fn generate_reserved_id(rng: &mut impl RngCore) -> VarInt { +673 let id = { +674 let rand = rng.random_range(0u64..(1 << 62) - 27); +675 let n = rand / 31; +676 31 * n + 27 +677 }; +678 debug_assert!( +679 id % 31 == 27, +680 "generated id does not have the form of 31 * N + 27" +681 ); +682 VarInt::from_u64(id).expect( +683 "generated id does fit into range of allowed transport parameter IDs: [0; 2^62)", +684 ) +685 } +686 +687 /// The maximum length of the payload to include as the parameter payload. +688 /// This value is not a specification-imposed limit but is chosen to match +689 /// the limit used by other implementations of QUIC, e.g., quic-go and quiche. +690 const MAX_PAYLOAD_LEN: usize = 16; +691} +692 +693#[repr(u64)] +694#[derive(Debug, Clone, Copy, PartialEq, Eq)] +695pub(crate) enum TransportParameterId { +696 // https://www.rfc-editor.org/rfc/rfc9000.html#iana-tp-table +697 OriginalDestinationConnectionId = 0x00, +698 MaxIdleTimeout = 0x01, +699 StatelessResetToken = 0x02, +700 MaxUdpPayloadSize = 0x03, +701 InitialMaxData = 0x04, +702 InitialMaxStreamDataBidiLocal = 0x05, +703 InitialMaxStreamDataBidiRemote = 0x06, +704 InitialMaxStreamDataUni = 0x07, +705 InitialMaxStreamsBidi = 0x08, +706 InitialMaxStreamsUni = 0x09, +707 AckDelayExponent = 0x0A, +708 MaxAckDelay = 0x0B, +709 DisableActiveMigration = 0x0C, +710 PreferredAddress = 0x0D, +711 ActiveConnectionIdLimit = 0x0E, +712 InitialSourceConnectionId = 0x0F, +713 RetrySourceConnectionId = 0x10, +714 +715 // Smallest possible ID of reserved transport parameter https://datatracker.ietf.org/doc/html/rfc9000#section-22.3 +716 ReservedTransportParameter = 0x1B, +717 +718 // https://www.rfc-editor.org/rfc/rfc9221.html#section-3 +719 MaxDatagramFrameSize = 0x20, +720 +721 // https://www.rfc-editor.org/rfc/rfc9287.html#section-3 +722 GreaseQuicBit = 0x2AB2, +723 +724 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency#section-10.1 +725 MinAckDelayDraft07 = 0xFF04DE1B, +726 +727 // <https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/> +728 ObservedAddr = 0x9f81a176, +729 +730 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-multipath +731 InitialMaxPathId = 0x3e, +732 +733 // inspired by https://www.ietf.org/archive/id/draft-seemann-quic-nat-traversal-02.html, +734 // simplified to iroh's needs +735 IrohNatTraversal = 0x3d7f91120401, +736} +737 +738impl TransportParameterId { +739 /// Array with all supported transport parameter IDs +740 const SUPPORTED: [Self; 24] = [ +741 Self::MaxIdleTimeout, +742 Self::MaxUdpPayloadSize, +743 Self::InitialMaxData, +744 Self::InitialMaxStreamDataBidiLocal, +745 Self::InitialMaxStreamDataBidiRemote, +746 Self::InitialMaxStreamDataUni, +747 Self::InitialMaxStreamsBidi, +748 Self::InitialMaxStreamsUni, +749 Self::AckDelayExponent, +750 Self::MaxAckDelay, +751 Self::ActiveConnectionIdLimit, +752 Self::ReservedTransportParameter, +753 Self::StatelessResetToken, +754 Self::DisableActiveMigration, +755 Self::MaxDatagramFrameSize, +756 Self::PreferredAddress, +757 Self::OriginalDestinationConnectionId, +758 Self::InitialSourceConnectionId, +759 Self::RetrySourceConnectionId, +760 Self::GreaseQuicBit, +761 Self::MinAckDelayDraft07, +762 Self::ObservedAddr, +763 Self::InitialMaxPathId, +764 Self::IrohNatTraversal, +765 ]; +766} +767 +768impl std::cmp::PartialEq<u64> for TransportParameterId { +769 fn eq(&self, other: &u64) -> bool { +770 *other == (*self as u64) +771 } +772} +773 +774impl TryFrom<u64> for TransportParameterId { +775 type Error = (); +776 +777 fn try_from(value: u64) -> Result<Self, Self::Error> { +778 let param = match value { +779 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout, +780 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize, +781 id if Self::InitialMaxData == id => Self::InitialMaxData, +782 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal, +783 id if Self::InitialMaxStreamDataBidiRemote == id => { +784 Self::InitialMaxStreamDataBidiRemote +785 } +786 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni, +787 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi, +788 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni, +789 id if Self::AckDelayExponent == id => Self::AckDelayExponent, +790 id if Self::MaxAckDelay == id => Self::MaxAckDelay, +791 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit, +792 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter, +793 id if Self::StatelessResetToken == id => Self::StatelessResetToken, +794 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration, +795 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize, +796 id if Self::PreferredAddress == id => Self::PreferredAddress, +797 id if Self::OriginalDestinationConnectionId == id => { +798 Self::OriginalDestinationConnectionId +799 } +800 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId, +801 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId, +802 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit, +803 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07, +804 id if Self::ObservedAddr == id => Self::ObservedAddr, +805 id if Self::InitialMaxPathId == id => Self::InitialMaxPathId, +806 id if Self::IrohNatTraversal == id => Self::IrohNatTraversal, +807 _ => return Err(()), +808 }; +809 Ok(param) +810 } +811} +812 +813fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> { +814 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len { +815 return Err(Error::Malformed); +816 } +817 +818 *value = Some(ConnectionId::from_buf(r, len)); +819 Ok(()) +820} +821 +822#[cfg(test)] +823mod test { +824 +825 use super::*; +826 +827 #[test] +828 fn coding() { +829 let mut buf = Vec::new(); +830 let params = TransportParameters { +831 initial_src_cid: Some(ConnectionId::new(&[])), +832 original_dst_cid: Some(ConnectionId::new(&[])), +833 initial_max_streams_bidi: 16u32.into(), +834 initial_max_streams_uni: 16u32.into(), +835 ack_delay_exponent: 2u32.into(), +836 max_udp_payload_size: 1200u32.into(), +837 preferred_address: Some(PreferredAddress { +838 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)), +839 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)), +840 connection_id: ConnectionId::new(&[0x42]), +841 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(), +842 }), +843 grease_quic_bit: true, +844 min_ack_delay: Some(2_000u32.into()), +845 address_discovery_role: address_discovery::Role::SendOnly, +846 initial_max_path_id: Some(PathId::MAX), +847 max_remote_nat_traversal_addresses: Some(5u8.try_into().unwrap()), +848 ..TransportParameters::default() +849 }; +850 params.write(&mut buf); +851 assert_eq!( +852 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(), +853 params +854 ); +855 } +856 +857 #[test] +858 fn reserved_transport_parameter_generate_reserved_id() { +859 let mut rngs = [ +860 StepRng(0), +861 StepRng(1), +862 StepRng(27), +863 StepRng(31), +864 StepRng(u32::MAX as u64), +865 StepRng(u32::MAX as u64 - 1), +866 StepRng(u32::MAX as u64 + 1), +867 StepRng(u32::MAX as u64 - 27), +868 StepRng(u32::MAX as u64 + 27), +869 StepRng(u32::MAX as u64 - 31), +870 StepRng(u32::MAX as u64 + 31), +871 StepRng(u64::MAX), +872 StepRng(u64::MAX - 1), +873 StepRng(u64::MAX - 27), +874 StepRng(u64::MAX - 31), +875 StepRng(1 << 62), +876 StepRng((1 << 62) - 1), +877 StepRng((1 << 62) + 1), +878 StepRng((1 << 62) - 27), +879 StepRng((1 << 62) + 27), +880 StepRng((1 << 62) - 31), +881 StepRng((1 << 62) + 31), +882 ]; +883 for rng in &mut rngs { +884 let id = ReservedTransportParameter::generate_reserved_id(rng); +885 assert!(id.0 % 31 == 27) +886 } +887 } +888 +889 struct StepRng(u64); +890 +891 impl RngCore for StepRng { +892 #[inline] +893 fn next_u32(&mut self) -> u32 { +894 self.next_u64() as u32 +895 } +896 +897 #[inline] +898 fn next_u64(&mut self) -> u64 { +899 let res = self.0; +900 self.0 = self.0.wrapping_add(1); +901 res +902 } +903 +904 #[inline] +905 fn fill_bytes(&mut self, dst: &mut [u8]) { +906 let mut left = dst; +907 while left.len() >= 8 { +908 let (l, r) = left.split_at_mut(8); +909 left = r; +910 l.copy_from_slice(&self.next_u64().to_le_bytes()); +911 } +912 let n = left.len(); +913 if n > 0 { +914 left.copy_from_slice(&self.next_u32().to_le_bytes()[..n]); +915 } +916 } +917 } +918 +919 #[test] +920 fn reserved_transport_parameter_ignored_when_read() { +921 let mut buf = Vec::new(); +922 let reserved_parameter = ReservedTransportParameter::random(&mut rand::rng()); +923 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN); +924 assert!(reserved_parameter.id.0 % 31 == 27); +925 +926 reserved_parameter.write(&mut buf); +927 assert!(!buf.is_empty()); +928 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap(); +929 assert_eq!(read_params, TransportParameters::default()); +930 } +931 +932 #[test] +933 fn read_semantic_validation() { +934 #[allow(clippy::type_complexity)] +935 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![ +936 Box::new(|t| { +937 // This min_ack_delay is bigger than max_ack_delay! +938 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1; +939 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap()) +940 }), +941 Box::new(|t| { +942 // Preferred address can only be sent by senders (and we are reading the transport +943 // params as a client) +944 t.preferred_address = Some(PreferredAddress { +945 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)), +946 address_v6: None, +947 connection_id: ConnectionId::new(&[]), +948 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(), +949 }) +950 }), +951 ]; +952 +953 for mut builder in illegal_params_builders { +954 let mut buf = Vec::new(); +955 let mut params = TransportParameters::default(); +956 builder(&mut params); +957 params.write(&mut buf); +958 +959 assert_eq!( +960 TransportParameters::read(Side::Server, &mut buf.as_slice()), +961 Err(Error::IllegalValue) +962 ); +963 } +964 } +965 +966 #[test] +967 fn resumption_params_validation() { +968 let high_limit = TransportParameters { +969 initial_max_streams_uni: 32u32.into(), +970 ..TransportParameters::default() +971 }; +972 let low_limit = TransportParameters { +973 initial_max_streams_uni: 16u32.into(), +974 ..TransportParameters::default() +975 }; +976 high_limit.validate_resumption_from(&low_limit).unwrap(); +977 low_limit.validate_resumption_from(&high_limit).unwrap_err(); +978 } +979} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_udp/lib.rs.html b/pr/255/docs/src/iroh_quinn_udp/lib.rs.html index d2fe73949..22c12ab98 100644 --- a/pr/255/docs/src/iroh_quinn_udp/lib.rs.html +++ b/pr/255/docs/src/iroh_quinn_udp/lib.rs.html @@ -150,91 +150,151 @@ 150 pub src_ip: Option<IpAddr>, 151} 152 -153/// Log at most 1 IO error per minute -154#[cfg(not(wasm_browser))] -155const IO_ERROR_LOG_INTERVAL: Duration = std::time::Duration::from_secs(60); -156 -157/// Logs a warning message when sendmsg fails -158/// -159/// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`] -160/// has elapsed since the last error was logged. -161#[cfg(all(not(wasm_browser), any(feature = "tracing-log", feature = "log")))] -162fn log_sendmsg_error( -163 last_send_error: &Mutex<Instant>, -164 err: impl core::fmt::Debug, -165 transmit: &Transmit, -166) { -167 let now = Instant::now(); -168 let last_send_error = &mut *last_send_error.lock().expect("poisend lock"); -169 if now.saturating_duration_since(*last_send_error) > IO_ERROR_LOG_INTERVAL { -170 *last_send_error = now; -171 log::warn!( -172 "sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}", -173 err, -174 transmit.destination, -175 transmit.src_ip, -176 transmit.ecn, -177 transmit.contents.len(), -178 transmit.segment_size -179 ); -180 } -181} -182 -183// No-op -184#[cfg(not(any(wasm_browser, feature = "tracing-log", feature = "log")))] -185fn log_sendmsg_error(_: &Mutex<Instant>, _: impl core::fmt::Debug, _: &Transmit) {} -186 -187/// A borrowed UDP socket -188/// -189/// On Unix, constructible via `From<T: AsFd>`. On Windows, constructible via `From<T: -190/// AsSocket>`. -191// Wrapper around socket2 to avoid making it a public dependency and incurring stability risk -192#[cfg(not(wasm_browser))] -193pub struct UdpSockRef<'a>(socket2::SockRef<'a>); -194 -195#[cfg(unix)] -196impl<'s, S> From<&'s S> for UdpSockRef<'s> -197where -198 S: AsFd, -199{ -200 fn from(socket: &'s S) -> Self { -201 Self(socket.into()) -202 } -203} -204 -205#[cfg(windows)] -206impl<'s, S> From<&'s S> for UdpSockRef<'s> -207where -208 S: AsSocket, -209{ -210 fn from(socket: &'s S) -> Self { -211 Self(socket.into()) -212 } -213} -214 -215/// Explicit congestion notification codepoint -216#[repr(u8)] -217#[derive(Debug, Copy, Clone, Eq, PartialEq)] -218pub enum EcnCodepoint { -219 /// The ECT(0) codepoint, indicating that an endpoint is ECN-capable -220 Ect0 = 0b10, -221 /// The ECT(1) codepoint, indicating that an endpoint is ECN-capable -222 Ect1 = 0b01, -223 /// The CE codepoint, signalling that congestion was experienced -224 Ce = 0b11, -225} -226 -227impl EcnCodepoint { -228 /// Create new object from the given bits -229 pub fn from_bits(x: u8) -> Option<Self> { -230 use EcnCodepoint::*; -231 Some(match x & 0b11 { -232 0b10 => Ect0, -233 0b01 => Ect1, -234 0b11 => Ce, -235 _ => { -236 return None; -237 } -238 }) -239 } -240} \ No newline at end of file +153impl Transmit<'_> { +154 /// Computes the effective segment-size of the packet. +155 /// +156 /// Some (older) network drivers don't like being told to do GSO even if +157 /// there is effectively only a single segment. +158 /// (i.e. `segment_size == contents.len()`) +159 /// Additionally, a `segment_size` that is greater than the content also +160 /// means there is effectively only a single segment. +161 /// This case is actually quite common when splitting up a prepared GSO batch +162 /// again after GSO has been disabled because the last datagram in a GSO +163 /// batch is allowed to be smaller than the segment size. +164 fn effective_segment_size(&self) -> Option<usize> { +165 match self.segment_size? { +166 size if size >= self.contents.len() => None, +167 size => Some(size), +168 } +169 } +170} +171 +172/// Log at most 1 IO error per minute +173#[cfg(not(wasm_browser))] +174const IO_ERROR_LOG_INTERVAL: Duration = std::time::Duration::from_secs(60); +175 +176/// Logs a warning message when sendmsg fails +177/// +178/// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`] +179/// has elapsed since the last error was logged. +180#[cfg(all(not(wasm_browser), any(feature = "tracing-log", feature = "log")))] +181fn log_sendmsg_error( +182 last_send_error: &Mutex<Instant>, +183 err: impl core::fmt::Debug, +184 transmit: &Transmit<'_>, +185) { +186 let now = Instant::now(); +187 let last_send_error = &mut *last_send_error.lock().expect("poisend lock"); +188 if now.saturating_duration_since(*last_send_error) > IO_ERROR_LOG_INTERVAL { +189 *last_send_error = now; +190 log::warn!( +191 "sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}", +192 err, +193 transmit.destination, +194 transmit.src_ip, +195 transmit.ecn, +196 transmit.contents.len(), +197 transmit.segment_size +198 ); +199 } +200} +201 +202// No-op +203#[cfg(not(any(wasm_browser, feature = "tracing-log", feature = "log")))] +204fn log_sendmsg_error(_: &Mutex<Instant>, _: impl core::fmt::Debug, _: &Transmit<'_>) {} +205 +206/// A borrowed UDP socket +207/// +208/// On Unix, constructible via `From<T: AsFd>`. On Windows, constructible via `From<T: +209/// AsSocket>`. +210// Wrapper around socket2 to avoid making it a public dependency and incurring stability risk +211#[cfg(not(wasm_browser))] +212pub struct UdpSockRef<'a>(socket2::SockRef<'a>); +213 +214#[cfg(unix)] +215impl<'s, S> From<&'s S> for UdpSockRef<'s> +216where +217 S: AsFd, +218{ +219 fn from(socket: &'s S) -> Self { +220 Self(socket.into()) +221 } +222} +223 +224#[cfg(windows)] +225impl<'s, S> From<&'s S> for UdpSockRef<'s> +226where +227 S: AsSocket, +228{ +229 fn from(socket: &'s S) -> Self { +230 Self(socket.into()) +231 } +232} +233 +234/// Explicit congestion notification codepoint +235#[repr(u8)] +236#[derive(Debug, Copy, Clone, Eq, PartialEq)] +237pub enum EcnCodepoint { +238 /// The ECT(0) codepoint, indicating that an endpoint is ECN-capable +239 Ect0 = 0b10, +240 /// The ECT(1) codepoint, indicating that an endpoint is ECN-capable +241 Ect1 = 0b01, +242 /// The CE codepoint, signalling that congestion was experienced +243 Ce = 0b11, +244} +245 +246impl EcnCodepoint { +247 /// Create new object from the given bits +248 pub fn from_bits(x: u8) -> Option<Self> { +249 use EcnCodepoint::*; +250 Some(match x & 0b11 { +251 0b10 => Ect0, +252 0b01 => Ect1, +253 0b11 => Ce, +254 _ => { +255 return None; +256 } +257 }) +258 } +259} +260 +261#[cfg(test)] +262mod tests { +263 use std::net::Ipv4Addr; +264 +265 use super::*; +266 +267 #[test] +268 fn effective_segment_size() { +269 assert_eq!( +270 make_transmit(&[0u8; 10], Some(15)).effective_segment_size(), +271 None, +272 "segment_size > content_len should yield no effective segment_size" +273 ); +274 assert_eq!( +275 make_transmit(&[0u8; 10], Some(10)).effective_segment_size(), +276 None, +277 "segment_size == content_len should yield no effective segment_size" +278 ); +279 assert_eq!( +280 make_transmit(&[0u8; 10], None).effective_segment_size(), +281 None, +282 "no segment_size should yield no effective segment_size" +283 ); +284 assert_eq!( +285 make_transmit(&[0u8; 10], Some(5)).effective_segment_size(), +286 Some(5), +287 "segment_size < content_len should yield effective segment_size" +288 ); +289 } +290 +291 fn make_transmit(contents: &[u8], segment_size: Option<usize>) -> Transmit<'_> { +292 Transmit { +293 destination: SocketAddr::from((Ipv4Addr::UNSPECIFIED, 1)), +294 ecn: None, +295 contents, +296 segment_size, +297 src_ip: None, +298 } +299 } +300} \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_udp/unix.rs.html b/pr/255/docs/src/iroh_quinn_udp/unix.rs.html index 81b5fcdcf..1701fa30a 100644 --- a/pr/255/docs/src/iroh_quinn_udp/unix.rs.html +++ b/pr/255/docs/src/iroh_quinn_udp/unix.rs.html @@ -51,1051 +51,1030 @@ 51 ) -> isize; 52} 53 -54// Defined in netinet6/in6.h on OpenBSD, this is not yet exported by the libc crate -55// directly. See https://github.com/rust-lang/libc/issues/3704 for when we might be able to -56// rely on this from the libc crate. -57#[cfg(any(target_os = "openbsd", target_os = "netbsd"))] -58const IPV6_DONTFRAG: libc::c_int = 62; -59#[cfg(not(any(target_os = "openbsd", target_os = "netbsd")))] -60const IPV6_DONTFRAG: libc::c_int = libc::IPV6_DONTFRAG; -61 -62#[cfg(target_os = "freebsd")] -63type IpTosTy = libc::c_uchar; -64#[cfg(not(any(target_os = "freebsd", target_os = "netbsd")))] -65type IpTosTy = libc::c_int; -66 -67/// Tokio-compatible UDP socket with some useful specializations. -68/// -69/// Unlike a standard tokio UDP socket, this allows ECN bits to be read and written on some -70/// platforms. -71#[derive(Debug)] -72pub struct UdpSocketState { -73 last_send_error: Mutex<Instant>, -74 max_gso_segments: AtomicUsize, -75 gro_segments: NonZeroUsize, -76 may_fragment: bool, +54#[cfg(target_os = "freebsd")] +55type IpTosTy = libc::c_uchar; +56#[cfg(not(any(target_os = "freebsd", target_os = "netbsd")))] +57type IpTosTy = libc::c_int; +58 +59/// Tokio-compatible UDP socket with some useful specializations. +60/// +61/// Unlike a standard tokio UDP socket, this allows ECN bits to be read and written on some +62/// platforms. +63#[derive(Debug)] +64pub struct UdpSocketState { +65 last_send_error: Mutex<Instant>, +66 max_gso_segments: AtomicUsize, +67 gro_segments: NonZeroUsize, +68 may_fragment: bool, +69 +70 /// True if we have received EINVAL error from `sendmsg` system call at least once. +71 /// +72 /// If enabled, we assume that old kernel is used and switch to fallback mode. +73 /// In particular, we do not use IP_TOS cmsg_type in this case, +74 /// which is not supported on Linux <3.13 and results in not sending the UDP packet at all. +75 sendmsg_einval: AtomicBool, +76} 77 -78 /// True if we have received EINVAL error from `sendmsg` system call at least once. -79 /// -80 /// If enabled, we assume that old kernel is used and switch to fallback mode. -81 /// In particular, we do not use IP_TOS cmsg_type in this case, -82 /// which is not supported on Linux <3.13 and results in not sending the UDP packet at all. -83 sendmsg_einval: AtomicBool, -84} -85 -86impl UdpSocketState { -87 pub fn new(sock: UdpSockRef<'_>) -> io::Result<Self> { -88 let io = sock.0; -89 let mut cmsg_platform_space = 0; -90 if cfg!(target_os = "linux") -91 || cfg!(bsd) -92 || cfg!(apple) -93 || cfg!(target_os = "android") -94 || cfg!(solarish) -95 { -96 cmsg_platform_space += -97 unsafe { libc::CMSG_SPACE(mem::size_of::<libc::in6_pktinfo>() as _) as usize }; -98 } -99 -100 assert!( -101 CMSG_LEN -102 >= unsafe { libc::CMSG_SPACE(mem::size_of::<libc::c_int>() as _) as usize } -103 + cmsg_platform_space -104 ); -105 assert!( -106 mem::align_of::<libc::cmsghdr>() <= mem::align_of::<cmsg::Aligned<[u8; 0]>>(), -107 "control message buffers will be misaligned" -108 ); -109 -110 io.set_nonblocking(true)?; -111 -112 let addr = io.local_addr()?; -113 let is_ipv4 = addr.family() == libc::AF_INET as libc::sa_family_t; -114 -115 // mac and ios do not support IP_RECVTOS on dual-stack sockets :( -116 // older macos versions also don't have the flag and will error out if we don't ignore it -117 #[cfg(not(any( -118 target_os = "openbsd", -119 target_os = "netbsd", -120 target_os = "dragonfly", -121 solarish -122 )))] -123 if is_ipv4 || !io.only_v6()? { -124 if let Err(_err) = -125 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_RECVTOS, OPTION_ON) -126 { -127 crate::log::debug!("Ignoring error setting IP_RECVTOS on socket: {_err:?}"); -128 } -129 } -130 -131 let mut may_fragment = false; -132 #[cfg(any(target_os = "linux", target_os = "android"))] -133 { -134 // opportunistically try to enable GRO. See gro::gro_segments(). -135 let _ = set_socket_option(&*io, libc::SOL_UDP, gro::UDP_GRO, OPTION_ON); -136 -137 // Forbid IPv4 fragmentation. Set even for IPv6 to account for IPv6 mapped IPv4 addresses. -138 // Set `may_fragment` to `true` if this option is not supported on the platform. -139 may_fragment |= !set_socket_option_supported( -140 &*io, -141 libc::IPPROTO_IP, -142 libc::IP_MTU_DISCOVER, -143 libc::IP_PMTUDISC_PROBE, -144 )?; -145 -146 if is_ipv4 { -147 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_PKTINFO, OPTION_ON)?; -148 } else { -149 // Set `may_fragment` to `true` if this option is not supported on the platform. -150 may_fragment |= !set_socket_option_supported( -151 &*io, -152 libc::IPPROTO_IPV6, -153 libc::IPV6_MTU_DISCOVER, -154 libc::IPV6_PMTUDISC_PROBE, -155 )?; -156 } -157 } -158 #[cfg(any(target_os = "freebsd", apple))] -159 { -160 if is_ipv4 { -161 // Set `may_fragment` to `true` if this option is not supported on the platform. -162 may_fragment |= !set_socket_option_supported( -163 &*io, -164 libc::IPPROTO_IP, -165 libc::IP_DONTFRAG, -166 OPTION_ON, -167 )?; -168 } -169 } -170 #[cfg(any(bsd, apple, solarish))] -171 // IP_RECVDSTADDR == IP_SENDSRCADDR on FreeBSD -172 // macOS uses only IP_RECVDSTADDR, no IP_SENDSRCADDR on macOS (the same on Solaris) -173 // macOS also supports IP_PKTINFO -174 { -175 if is_ipv4 { -176 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, OPTION_ON)?; -177 } -178 } -179 -180 // Options standardized in RFC 3542 -181 if !is_ipv4 { -182 set_socket_option(&*io, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, OPTION_ON)?; -183 set_socket_option(&*io, libc::IPPROTO_IPV6, libc::IPV6_RECVTCLASS, OPTION_ON)?; -184 // Linux's IP_PMTUDISC_PROBE allows us to operate under interface MTU rather than the -185 // kernel's path MTU guess, but actually disabling fragmentation requires this too. See -186 // __ip6_append_data in ip6_output.c. -187 // Set `may_fragment` to `true` if this option is not supported on the platform. -188 may_fragment |= -189 !set_socket_option_supported(&*io, libc::IPPROTO_IPV6, IPV6_DONTFRAG, OPTION_ON)?; -190 } -191 -192 let now = Instant::now(); -193 Ok(Self { -194 last_send_error: Mutex::new(now.checked_sub(2 * IO_ERROR_LOG_INTERVAL).unwrap_or(now)), -195 max_gso_segments: AtomicUsize::new(gso::max_gso_segments()), -196 gro_segments: gro::gro_segments(), -197 may_fragment, -198 sendmsg_einval: AtomicBool::new(false), -199 }) -200 } -201 -202 /// Sends a [`Transmit`] on the given socket. -203 /// -204 /// This function will only ever return errors of kind [`io::ErrorKind::WouldBlock`]. -205 /// All other errors will be logged and converted to `Ok`. +78impl UdpSocketState { +79 pub fn new(sock: UdpSockRef<'_>) -> io::Result<Self> { +80 let io = sock.0; +81 let mut cmsg_platform_space = 0; +82 if cfg!(target_os = "linux") +83 || cfg!(bsd) +84 || cfg!(apple) +85 || cfg!(target_os = "android") +86 || cfg!(solarish) +87 { +88 cmsg_platform_space += +89 unsafe { libc::CMSG_SPACE(mem::size_of::<libc::in6_pktinfo>() as _) as usize }; +90 } +91 +92 assert!( +93 CMSG_LEN +94 >= unsafe { libc::CMSG_SPACE(mem::size_of::<libc::c_int>() as _) as usize } +95 + cmsg_platform_space +96 ); +97 assert!( +98 mem::align_of::<libc::cmsghdr>() <= mem::align_of::<cmsg::Aligned<[u8; 0]>>(), +99 "control message buffers will be misaligned" +100 ); +101 +102 io.set_nonblocking(true)?; +103 +104 let addr = io.local_addr()?; +105 let is_ipv4 = addr.family() == libc::AF_INET as libc::sa_family_t; +106 +107 // mac and ios do not support IP_RECVTOS on dual-stack sockets :( +108 // older macos versions also don't have the flag and will error out if we don't ignore it +109 #[cfg(not(any( +110 target_os = "openbsd", +111 target_os = "netbsd", +112 target_os = "dragonfly", +113 solarish +114 )))] +115 if is_ipv4 || !io.only_v6()? { +116 if let Err(_err) = +117 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_RECVTOS, OPTION_ON) +118 { +119 crate::log::debug!("Ignoring error setting IP_RECVTOS on socket: {_err:?}"); +120 } +121 } +122 +123 let mut may_fragment = false; +124 #[cfg(any(target_os = "linux", target_os = "android"))] +125 { +126 // opportunistically try to enable GRO. See gro::gro_segments(). +127 let _ = set_socket_option(&*io, libc::SOL_UDP, libc::UDP_GRO, OPTION_ON); +128 +129 // Forbid IPv4 fragmentation. Set even for IPv6 to account for IPv6 mapped IPv4 addresses. +130 // Set `may_fragment` to `true` if this option is not supported on the platform. +131 may_fragment |= !set_socket_option_supported( +132 &*io, +133 libc::IPPROTO_IP, +134 libc::IP_MTU_DISCOVER, +135 libc::IP_PMTUDISC_PROBE, +136 )?; +137 +138 if is_ipv4 { +139 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_PKTINFO, OPTION_ON)?; +140 } else { +141 // Set `may_fragment` to `true` if this option is not supported on the platform. +142 may_fragment |= !set_socket_option_supported( +143 &*io, +144 libc::IPPROTO_IPV6, +145 libc::IPV6_MTU_DISCOVER, +146 libc::IPV6_PMTUDISC_PROBE, +147 )?; +148 } +149 } +150 #[cfg(any(target_os = "freebsd", apple))] +151 { +152 if is_ipv4 { +153 // Set `may_fragment` to `true` if this option is not supported on the platform. +154 may_fragment |= !set_socket_option_supported( +155 &*io, +156 libc::IPPROTO_IP, +157 libc::IP_DONTFRAG, +158 OPTION_ON, +159 )?; +160 } +161 } +162 #[cfg(any(bsd, apple, solarish))] +163 // IP_RECVDSTADDR == IP_SENDSRCADDR on FreeBSD +164 // macOS uses only IP_RECVDSTADDR, no IP_SENDSRCADDR on macOS (the same on Solaris) +165 // macOS also supports IP_PKTINFO +166 { +167 if is_ipv4 { +168 set_socket_option(&*io, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, OPTION_ON)?; +169 } +170 } +171 +172 // Options standardized in RFC 3542 +173 if !is_ipv4 { +174 set_socket_option(&*io, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, OPTION_ON)?; +175 set_socket_option(&*io, libc::IPPROTO_IPV6, libc::IPV6_RECVTCLASS, OPTION_ON)?; +176 // Linux's IP_PMTUDISC_PROBE allows us to operate under interface MTU rather than the +177 // kernel's path MTU guess, but actually disabling fragmentation requires this too. See +178 // __ip6_append_data in ip6_output.c. +179 // Set `may_fragment` to `true` if this option is not supported on the platform. +180 may_fragment |= !set_socket_option_supported( +181 &*io, +182 libc::IPPROTO_IPV6, +183 libc::IPV6_DONTFRAG, +184 OPTION_ON, +185 )?; +186 } +187 +188 let now = Instant::now(); +189 Ok(Self { +190 last_send_error: Mutex::new(now.checked_sub(2 * IO_ERROR_LOG_INTERVAL).unwrap_or(now)), +191 max_gso_segments: AtomicUsize::new(gso::max_gso_segments()), +192 gro_segments: gro::gro_segments(), +193 may_fragment, +194 sendmsg_einval: AtomicBool::new(false), +195 }) +196 } +197 +198 /// Sends a [`Transmit`] on the given socket. +199 /// +200 /// This function will only ever return errors of kind [`io::ErrorKind::WouldBlock`]. +201 /// All other errors will be logged and converted to `Ok`. +202 /// +203 /// UDP transmission errors are considered non-fatal because higher-level protocols must +204 /// employ retransmits and timeouts anyway in order to deal with UDP's unreliable nature. +205 /// Thus, logging is most likely the only thing you can do with these errors. 206 /// -207 /// UDP transmission errors are considered non-fatal because higher-level protocols must -208 /// employ retransmits and timeouts anyway in order to deal with UDP's unreliable nature. -209 /// Thus, logging is most likely the only thing you can do with these errors. -210 /// -211 /// If you would like to handle these errors yourself, use [`UdpSocketState::try_send`] -212 /// instead. -213 pub fn send(&self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { -214 match send(self, socket.0, transmit) { -215 Ok(()) => Ok(()), -216 Err(e) if e.kind() == io::ErrorKind::WouldBlock => Err(e), -217 // - EMSGSIZE is expected for MTU probes. Future work might be able to avoid -218 // these by automatically clamping the MTUD upper bound to the interface MTU. -219 Err(e) if e.raw_os_error() == Some(libc::EMSGSIZE) => Ok(()), -220 Err(e) => { -221 log_sendmsg_error(&self.last_send_error, e, transmit); -222 -223 Ok(()) -224 } -225 } -226 } -227 -228 /// Sends a [`Transmit`] on the given socket without any additional error handling. -229 pub fn try_send(&self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { -230 send(self, socket.0, transmit) -231 } -232 -233 pub fn recv( -234 &self, -235 socket: UdpSockRef<'_>, -236 bufs: &mut [IoSliceMut<'_>], -237 meta: &mut [RecvMeta], -238 ) -> io::Result<usize> { -239 recv(socket.0, bufs, meta) -240 } -241 -242 /// The maximum amount of segments which can be transmitted if a platform -243 /// supports Generic Send Offload (GSO). -244 /// -245 /// This is 1 if the platform doesn't support GSO. Subject to change if errors are detected -246 /// while using GSO. -247 #[inline] -248 pub fn max_gso_segments(&self) -> NonZeroUsize { -249 self.max_gso_segments -250 .load(Ordering::Relaxed) -251 .try_into() -252 .expect("must have non zero GSO segments") -253 } -254 -255 /// The number of segments to read when GRO is enabled. Used as a factor to -256 /// compute the receive buffer size. -257 /// -258 /// Returns 1 if the platform doesn't support GRO. -259 #[inline] -260 pub fn gro_segments(&self) -> NonZeroUsize { -261 self.gro_segments -262 } -263 -264 /// Resize the send buffer of `socket` to `bytes` -265 #[inline] -266 pub fn set_send_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> { -267 socket.0.set_send_buffer_size(bytes) -268 } -269 -270 /// Resize the receive buffer of `socket` to `bytes` -271 #[inline] -272 pub fn set_recv_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> { -273 socket.0.set_recv_buffer_size(bytes) -274 } -275 -276 /// Get the size of the `socket` send buffer -277 #[inline] -278 pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> { -279 socket.0.send_buffer_size() -280 } -281 -282 /// Get the size of the `socket` receive buffer -283 #[inline] -284 pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> { -285 socket.0.recv_buffer_size() -286 } -287 -288 /// Whether transmitted datagrams might get fragmented by the IP layer -289 /// -290 /// Returns `false` on targets which employ e.g. the `IPV6_DONTFRAG` socket option. -291 #[inline] -292 pub fn may_fragment(&self) -> bool { -293 self.may_fragment -294 } -295 -296 /// Returns true if we previously got an EINVAL error from `sendmsg` syscall. -297 fn sendmsg_einval(&self) -> bool { -298 self.sendmsg_einval.load(Ordering::Relaxed) -299 } -300 -301 /// Sets the flag indicating we got EINVAL error from `sendmsg` syscall. -302 #[cfg(not(any(apple, target_os = "openbsd", target_os = "netbsd")))] -303 fn set_sendmsg_einval(&self) { -304 self.sendmsg_einval.store(true, Ordering::Relaxed) -305 } -306} -307 -308#[cfg(not(any(apple, target_os = "openbsd", target_os = "netbsd")))] -309fn send( -310 #[allow(unused_variables)] // only used on Linux -311 state: &UdpSocketState, -312 io: SockRef<'_>, -313 transmit: &Transmit<'_>, -314) -> io::Result<()> { -315 #[allow(unused_mut)] // only mutable on FreeBSD -316 let mut encode_src_ip = true; -317 #[cfg(target_os = "freebsd")] -318 { -319 let addr = io.local_addr()?; -320 let is_ipv4 = addr.family() == libc::AF_INET as libc::sa_family_t; -321 if is_ipv4 { -322 if let Some(socket) = addr.as_socket_ipv4() { -323 encode_src_ip = socket.ip() == &Ipv4Addr::UNSPECIFIED; -324 } -325 } -326 } -327 let mut msg_hdr: libc::msghdr = unsafe { mem::zeroed() }; -328 let mut iovec: libc::iovec = unsafe { mem::zeroed() }; -329 let mut cmsgs = cmsg::Aligned([0u8; CMSG_LEN]); -330 let dst_addr = socket2::SockAddr::from(transmit.destination); -331 prepare_msg( -332 transmit, -333 &dst_addr, -334 &mut msg_hdr, -335 &mut iovec, -336 &mut cmsgs, -337 encode_src_ip, -338 state.sendmsg_einval(), -339 ); -340 -341 loop { -342 let n = unsafe { libc::sendmsg(io.as_raw_fd(), &msg_hdr, 0) }; +207 /// If you would like to handle these errors yourself, use [`UdpSocketState::try_send`] +208 /// instead. +209 pub fn send(&self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { +210 match send(self, socket.0, transmit) { +211 Ok(()) => Ok(()), +212 Err(e) if e.kind() == io::ErrorKind::WouldBlock => Err(e), +213 // - EMSGSIZE is expected for MTU probes. Future work might be able to avoid +214 // these by automatically clamping the MTUD upper bound to the interface MTU. +215 Err(e) if e.raw_os_error() == Some(libc::EMSGSIZE) => Ok(()), +216 Err(e) => { +217 log_sendmsg_error(&self.last_send_error, e, transmit); +218 +219 Ok(()) +220 } +221 } +222 } +223 +224 /// Sends a [`Transmit`] on the given socket without any additional error handling. +225 pub fn try_send(&self, socket: UdpSockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { +226 send(self, socket.0, transmit) +227 } +228 +229 pub fn recv( +230 &self, +231 socket: UdpSockRef<'_>, +232 bufs: &mut [IoSliceMut<'_>], +233 meta: &mut [RecvMeta], +234 ) -> io::Result<usize> { +235 recv(socket.0, bufs, meta) +236 } +237 +238 /// The maximum amount of segments which can be transmitted if a platform +239 /// supports Generic Send Offload (GSO). +240 /// +241 /// This is 1 if the platform doesn't support GSO. Subject to change if errors are detected +242 /// while using GSO. +243 #[inline] +244 pub fn max_gso_segments(&self) -> NonZeroUsize { +245 self.max_gso_segments +246 .load(Ordering::Relaxed) +247 .try_into() +248 .expect("must have non zero GSO segments") +249 } +250 +251 /// The number of segments to read when GRO is enabled. Used as a factor to +252 /// compute the receive buffer size. +253 /// +254 /// Returns 1 if the platform doesn't support GRO. +255 #[inline] +256 pub fn gro_segments(&self) -> NonZeroUsize { +257 self.gro_segments +258 } +259 +260 /// Resize the send buffer of `socket` to `bytes` +261 #[inline] +262 pub fn set_send_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> { +263 socket.0.set_send_buffer_size(bytes) +264 } +265 +266 /// Resize the receive buffer of `socket` to `bytes` +267 #[inline] +268 pub fn set_recv_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> { +269 socket.0.set_recv_buffer_size(bytes) +270 } +271 +272 /// Get the size of the `socket` send buffer +273 #[inline] +274 pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> { +275 socket.0.send_buffer_size() +276 } +277 +278 /// Get the size of the `socket` receive buffer +279 #[inline] +280 pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> { +281 socket.0.recv_buffer_size() +282 } +283 +284 /// Whether transmitted datagrams might get fragmented by the IP layer +285 /// +286 /// Returns `false` on targets which employ e.g. the `IPV6_DONTFRAG` socket option. +287 #[inline] +288 pub fn may_fragment(&self) -> bool { +289 self.may_fragment +290 } +291 +292 /// Returns true if we previously got an EINVAL error from `sendmsg` syscall. +293 fn sendmsg_einval(&self) -> bool { +294 self.sendmsg_einval.load(Ordering::Relaxed) +295 } +296 +297 /// Sets the flag indicating we got EINVAL error from `sendmsg` syscall. +298 #[cfg(not(any(apple, target_os = "openbsd", target_os = "netbsd")))] +299 fn set_sendmsg_einval(&self) { +300 self.sendmsg_einval.store(true, Ordering::Relaxed) +301 } +302} +303 +304#[cfg(not(any(apple, target_os = "openbsd", target_os = "netbsd")))] +305fn send( +306 #[allow(unused_variables)] // only used on Linux +307 state: &UdpSocketState, +308 io: SockRef<'_>, +309 transmit: &Transmit<'_>, +310) -> io::Result<()> { +311 #[allow(unused_mut)] // only mutable on FreeBSD +312 let mut encode_src_ip = true; +313 #[cfg(target_os = "freebsd")] +314 { +315 let addr = io.local_addr()?; +316 let is_ipv4 = addr.family() == libc::AF_INET as libc::sa_family_t; +317 if is_ipv4 { +318 if let Some(socket) = addr.as_socket_ipv4() { +319 encode_src_ip = socket.ip() == &Ipv4Addr::UNSPECIFIED; +320 } +321 } +322 } +323 let mut msg_hdr: libc::msghdr = unsafe { mem::zeroed() }; +324 let mut iovec: libc::iovec = unsafe { mem::zeroed() }; +325 let mut cmsgs = cmsg::Aligned([0u8; CMSG_LEN]); +326 let dst_addr = socket2::SockAddr::from(transmit.destination); +327 prepare_msg( +328 transmit, +329 &dst_addr, +330 &mut msg_hdr, +331 &mut iovec, +332 &mut cmsgs, +333 encode_src_ip, +334 state.sendmsg_einval(), +335 ); +336 +337 loop { +338 let n = unsafe { libc::sendmsg(io.as_raw_fd(), &msg_hdr, 0) }; +339 +340 if n >= 0 { +341 return Ok(()); +342 } 343 -344 if n >= 0 { -345 return Ok(()); -346 } -347 -348 let e = io::Error::last_os_error(); -349 match e.kind() { -350 // Retry the transmission -351 io::ErrorKind::Interrupted => continue, -352 io::ErrorKind::WouldBlock => return Err(e), -353 _ => { -354 // Some network adapters and drivers do not support GSO. Unfortunately, Linux -355 // offers no easy way for us to detect this short of an EIO or sometimes EINVAL -356 // when we try to actually send datagrams using it. -357 #[cfg(any(target_os = "linux", target_os = "android"))] -358 if let Some(libc::EIO) | Some(libc::EINVAL) = e.raw_os_error() { -359 // Prevent new transmits from being scheduled using GSO. Existing GSO transmits -360 // may already be in the pipeline, so we need to tolerate additional failures. -361 if state.max_gso_segments().get() > 1 { -362 crate::log::info!( -363 "`libc::sendmsg` failed with {e}; halting segmentation offload" -364 ); -365 state -366 .max_gso_segments -367 .store(1, std::sync::atomic::Ordering::Relaxed); -368 } -369 } -370 -371 // Some arguments to `sendmsg` are not supported. Switch to -372 // fallback mode and retry if we haven't already. -373 if e.raw_os_error() == Some(libc::EINVAL) && !state.sendmsg_einval() { -374 state.set_sendmsg_einval(); -375 prepare_msg( -376 transmit, -377 &dst_addr, -378 &mut msg_hdr, -379 &mut iovec, -380 &mut cmsgs, -381 encode_src_ip, -382 state.sendmsg_einval(), -383 ); -384 continue; -385 } -386 -387 return Err(e); -388 } -389 } -390 } -391} -392 -393#[cfg(apple_fast)] -394fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { -395 let mut hdrs = unsafe { mem::zeroed::<[msghdr_x; BATCH_SIZE]>() }; -396 let mut iovs = unsafe { mem::zeroed::<[libc::iovec; BATCH_SIZE]>() }; -397 let mut ctrls = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE]; -398 let addr = socket2::SockAddr::from(transmit.destination); -399 let segment_size = transmit.segment_size.unwrap_or(transmit.contents.len()); -400 let mut cnt = 0; -401 debug_assert!(transmit.contents.len().div_ceil(segment_size) <= BATCH_SIZE); -402 for (i, chunk) in transmit -403 .contents -404 .chunks(segment_size) -405 .enumerate() -406 .take(BATCH_SIZE) -407 { -408 prepare_msg( -409 &Transmit { -410 destination: transmit.destination, -411 ecn: transmit.ecn, -412 contents: chunk, -413 segment_size: Some(chunk.len()), -414 src_ip: transmit.src_ip, -415 }, -416 &addr, -417 &mut hdrs[i], -418 &mut iovs[i], -419 &mut ctrls[i], -420 true, -421 state.sendmsg_einval(), -422 ); -423 hdrs[i].msg_datalen = chunk.len(); -424 cnt += 1; -425 } -426 loop { -427 let n = unsafe { sendmsg_x(io.as_raw_fd(), hdrs.as_ptr(), cnt as u32, 0) }; +344 let e = io::Error::last_os_error(); +345 match e.kind() { +346 // Retry the transmission +347 io::ErrorKind::Interrupted => continue, +348 io::ErrorKind::WouldBlock => return Err(e), +349 _ => { +350 // Some network adapters and drivers do not support GSO. Unfortunately, Linux +351 // offers no easy way for us to detect this short of an EIO or sometimes EINVAL +352 // when we try to actually send datagrams using it. +353 #[cfg(any(target_os = "linux", target_os = "android"))] +354 if let Some(libc::EIO) | Some(libc::EINVAL) = e.raw_os_error() { +355 // Prevent new transmits from being scheduled using GSO. Existing GSO transmits +356 // may already be in the pipeline, so we need to tolerate additional failures. +357 if state.max_gso_segments().get() > 1 { +358 crate::log::info!( +359 "`libc::sendmsg` failed with {e}; halting segmentation offload" +360 ); +361 state +362 .max_gso_segments +363 .store(1, std::sync::atomic::Ordering::Relaxed); +364 } +365 } +366 +367 // Some arguments to `sendmsg` are not supported. Switch to +368 // fallback mode and retry if we haven't already. +369 if e.raw_os_error() == Some(libc::EINVAL) && !state.sendmsg_einval() { +370 state.set_sendmsg_einval(); +371 prepare_msg( +372 transmit, +373 &dst_addr, +374 &mut msg_hdr, +375 &mut iovec, +376 &mut cmsgs, +377 encode_src_ip, +378 state.sendmsg_einval(), +379 ); +380 continue; +381 } +382 +383 return Err(e); +384 } +385 } +386 } +387} +388 +389#[cfg(apple_fast)] +390fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { +391 let mut hdrs = unsafe { mem::zeroed::<[msghdr_x; BATCH_SIZE]>() }; +392 let mut iovs = unsafe { mem::zeroed::<[libc::iovec; BATCH_SIZE]>() }; +393 let mut ctrls = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE]; +394 let addr = socket2::SockAddr::from(transmit.destination); +395 let segment_size = transmit.segment_size.unwrap_or(transmit.contents.len()); +396 let mut cnt = 0; +397 debug_assert!(transmit.contents.len().div_ceil(segment_size) <= BATCH_SIZE); +398 for (i, chunk) in transmit +399 .contents +400 .chunks(segment_size) +401 .enumerate() +402 .take(BATCH_SIZE) +403 { +404 prepare_msg( +405 &Transmit { +406 destination: transmit.destination, +407 ecn: transmit.ecn, +408 contents: chunk, +409 segment_size: Some(chunk.len()), +410 src_ip: transmit.src_ip, +411 }, +412 &addr, +413 &mut hdrs[i], +414 &mut iovs[i], +415 &mut ctrls[i], +416 true, +417 state.sendmsg_einval(), +418 ); +419 hdrs[i].msg_datalen = chunk.len(); +420 cnt += 1; +421 } +422 loop { +423 let n = unsafe { sendmsg_x(io.as_raw_fd(), hdrs.as_ptr(), cnt as u32, 0) }; +424 +425 if n >= 0 { +426 return Ok(()); +427 } 428 -429 if n >= 0 { -430 return Ok(()); -431 } -432 -433 let e = io::Error::last_os_error(); -434 match e.kind() { -435 // Retry the transmission -436 io::ErrorKind::Interrupted => continue, -437 _ => return Err(e), -438 } -439 } -440} -441 -442#[cfg(any(target_os = "openbsd", target_os = "netbsd", apple_slow))] -443fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { -444 let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; -445 let mut iov: libc::iovec = unsafe { mem::zeroed() }; -446 let mut ctrl = cmsg::Aligned([0u8; CMSG_LEN]); -447 let addr = socket2::SockAddr::from(transmit.destination); -448 prepare_msg( -449 transmit, -450 &addr, -451 &mut hdr, -452 &mut iov, -453 &mut ctrl, -454 cfg!(apple) || cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd"), -455 state.sendmsg_einval(), -456 ); -457 loop { -458 let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) }; +429 let e = io::Error::last_os_error(); +430 match e.kind() { +431 // Retry the transmission +432 io::ErrorKind::Interrupted => continue, +433 _ => return Err(e), +434 } +435 } +436} +437 +438#[cfg(any(target_os = "openbsd", target_os = "netbsd", apple_slow))] +439fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io::Result<()> { +440 let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; +441 let mut iov: libc::iovec = unsafe { mem::zeroed() }; +442 let mut ctrl = cmsg::Aligned([0u8; CMSG_LEN]); +443 let addr = socket2::SockAddr::from(transmit.destination); +444 prepare_msg( +445 transmit, +446 &addr, +447 &mut hdr, +448 &mut iov, +449 &mut ctrl, +450 cfg!(apple) || cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd"), +451 state.sendmsg_einval(), +452 ); +453 loop { +454 let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) }; +455 +456 if n >= 0 { +457 return Ok(()); +458 } 459 -460 if n >= 0 { -461 return Ok(()); -462 } -463 -464 let e = io::Error::last_os_error(); -465 match e.kind() { -466 // Retry the transmission -467 io::ErrorKind::Interrupted => continue, -468 _ => return Err(e), -469 } -470 } -471} -472 -473#[cfg(not(any( -474 apple, -475 target_os = "openbsd", -476 target_os = "netbsd", -477 target_os = "dragonfly", -478 solarish -479)))] -480fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { -481 let mut names = [MaybeUninit::<libc::sockaddr_storage>::uninit(); BATCH_SIZE]; -482 let mut ctrls = [cmsg::Aligned(MaybeUninit::<[u8; CMSG_LEN]>::uninit()); BATCH_SIZE]; -483 let mut hdrs = unsafe { mem::zeroed::<[libc::mmsghdr; BATCH_SIZE]>() }; -484 let max_msg_count = bufs.len().min(BATCH_SIZE); -485 for i in 0..max_msg_count { -486 prepare_recv( -487 &mut bufs[i], -488 &mut names[i], -489 &mut ctrls[i], -490 &mut hdrs[i].msg_hdr, -491 ); -492 } -493 let msg_count = loop { -494 let n = unsafe { -495 libc::recvmmsg( -496 io.as_raw_fd(), -497 hdrs.as_mut_ptr(), -498 bufs.len().min(BATCH_SIZE) as _, -499 0, -500 ptr::null_mut::<libc::timespec>(), -501 ) -502 }; +460 let e = io::Error::last_os_error(); +461 match e.kind() { +462 // Retry the transmission +463 io::ErrorKind::Interrupted => continue, +464 _ => return Err(e), +465 } +466 } +467} +468 +469#[cfg(not(any( +470 apple, +471 target_os = "openbsd", +472 target_os = "netbsd", +473 target_os = "dragonfly", +474 solarish +475)))] +476fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { +477 let mut names = [MaybeUninit::<libc::sockaddr_storage>::uninit(); BATCH_SIZE]; +478 let mut ctrls = [cmsg::Aligned(MaybeUninit::<[u8; CMSG_LEN]>::uninit()); BATCH_SIZE]; +479 let mut hdrs = unsafe { mem::zeroed::<[libc::mmsghdr; BATCH_SIZE]>() }; +480 let max_msg_count = bufs.len().min(BATCH_SIZE); +481 for i in 0..max_msg_count { +482 prepare_recv( +483 &mut bufs[i], +484 &mut names[i], +485 &mut ctrls[i], +486 &mut hdrs[i].msg_hdr, +487 ); +488 } +489 let msg_count = loop { +490 let n = unsafe { +491 libc::recvmmsg( +492 io.as_raw_fd(), +493 hdrs.as_mut_ptr(), +494 bufs.len().min(BATCH_SIZE) as _, +495 0, +496 ptr::null_mut::<libc::timespec>(), +497 ) +498 }; +499 +500 if n >= 0 { +501 break n; +502 } 503 -504 if n >= 0 { -505 break n; -506 } -507 -508 let e = io::Error::last_os_error(); -509 match e.kind() { -510 // Retry receiving -511 io::ErrorKind::Interrupted => continue, -512 _ => return Err(e), -513 } -514 }; -515 for i in 0..(msg_count as usize) { -516 meta[i] = decode_recv(&names[i], &hdrs[i].msg_hdr, hdrs[i].msg_len as usize)?; -517 } -518 Ok(msg_count as usize) -519} -520 -521#[cfg(apple_fast)] -522fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { -523 let mut names = [MaybeUninit::<libc::sockaddr_storage>::uninit(); BATCH_SIZE]; -524 // MacOS 10.15 `recvmsg_x` does not override the `msghdr_x` -525 // `msg_controllen`. Thus, after the call to `recvmsg_x`, one does not know -526 // which control messages have been written to. To prevent reading -527 // uninitialized memory, do not use `MaybeUninit` for `ctrls`, instead -528 // initialize `ctrls` with `0`s. A control message of all `0`s is -529 // automatically skipped by `libc::CMSG_NXTHDR`. -530 let mut ctrls = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE]; -531 let mut hdrs = unsafe { mem::zeroed::<[msghdr_x; BATCH_SIZE]>() }; -532 let max_msg_count = bufs.len().min(BATCH_SIZE); -533 for i in 0..max_msg_count { -534 prepare_recv(&mut bufs[i], &mut names[i], &mut ctrls[i], &mut hdrs[i]); -535 } -536 let msg_count = loop { -537 let n = unsafe { recvmsg_x(io.as_raw_fd(), hdrs.as_mut_ptr(), max_msg_count as _, 0) }; +504 let e = io::Error::last_os_error(); +505 match e.kind() { +506 // Retry receiving +507 io::ErrorKind::Interrupted => continue, +508 _ => return Err(e), +509 } +510 }; +511 for i in 0..(msg_count as usize) { +512 meta[i] = decode_recv(&names[i], &hdrs[i].msg_hdr, hdrs[i].msg_len as usize)?; +513 } +514 Ok(msg_count as usize) +515} +516 +517#[cfg(apple_fast)] +518fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { +519 let mut names = [MaybeUninit::<libc::sockaddr_storage>::uninit(); BATCH_SIZE]; +520 // MacOS 10.15 `recvmsg_x` does not override the `msghdr_x` +521 // `msg_controllen`. Thus, after the call to `recvmsg_x`, one does not know +522 // which control messages have been written to. To prevent reading +523 // uninitialized memory, do not use `MaybeUninit` for `ctrls`, instead +524 // initialize `ctrls` with `0`s. A control message of all `0`s is +525 // automatically skipped by `libc::CMSG_NXTHDR`. +526 let mut ctrls = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE]; +527 let mut hdrs = unsafe { mem::zeroed::<[msghdr_x; BATCH_SIZE]>() }; +528 let max_msg_count = bufs.len().min(BATCH_SIZE); +529 for i in 0..max_msg_count { +530 prepare_recv(&mut bufs[i], &mut names[i], &mut ctrls[i], &mut hdrs[i]); +531 } +532 let msg_count = loop { +533 let n = unsafe { recvmsg_x(io.as_raw_fd(), hdrs.as_mut_ptr(), max_msg_count as _, 0) }; +534 +535 if n >= 0 { +536 break n; +537 } 538 -539 if n >= 0 { -540 break n; -541 } -542 -543 let e = io::Error::last_os_error(); -544 match e.kind() { -545 // Retry receiving -546 io::ErrorKind::Interrupted => continue, -547 _ => return Err(e), -548 } -549 }; -550 for i in 0..(msg_count as usize) { -551 meta[i] = decode_recv(&names[i], &hdrs[i], hdrs[i].msg_datalen as usize)?; -552 } -553 Ok(msg_count as usize) -554} -555 -556#[cfg(any( -557 target_os = "openbsd", -558 target_os = "netbsd", -559 target_os = "dragonfly", -560 solarish, -561 apple_slow -562))] -563fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { -564 let mut name = MaybeUninit::<libc::sockaddr_storage>::uninit(); -565 let mut ctrl = cmsg::Aligned(MaybeUninit::<[u8; CMSG_LEN]>::uninit()); -566 let mut hdr = unsafe { mem::zeroed::<libc::msghdr>() }; -567 prepare_recv(&mut bufs[0], &mut name, &mut ctrl, &mut hdr); -568 let n = loop { -569 let n = unsafe { libc::recvmsg(io.as_raw_fd(), &mut hdr, 0) }; +539 let e = io::Error::last_os_error(); +540 match e.kind() { +541 // Retry receiving +542 io::ErrorKind::Interrupted => continue, +543 _ => return Err(e), +544 } +545 }; +546 for i in 0..(msg_count as usize) { +547 meta[i] = decode_recv(&names[i], &hdrs[i], hdrs[i].msg_datalen as usize)?; +548 } +549 Ok(msg_count as usize) +550} +551 +552#[cfg(any( +553 target_os = "openbsd", +554 target_os = "netbsd", +555 target_os = "dragonfly", +556 solarish, +557 apple_slow +558))] +559fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> io::Result<usize> { +560 let mut name = MaybeUninit::<libc::sockaddr_storage>::uninit(); +561 let mut ctrl = cmsg::Aligned(MaybeUninit::<[u8; CMSG_LEN]>::uninit()); +562 let mut hdr = unsafe { mem::zeroed::<libc::msghdr>() }; +563 prepare_recv(&mut bufs[0], &mut name, &mut ctrl, &mut hdr); +564 let n = loop { +565 let n = unsafe { libc::recvmsg(io.as_raw_fd(), &mut hdr, 0) }; +566 +567 if hdr.msg_flags & libc::MSG_TRUNC != 0 { +568 continue; +569 } 570 -571 if hdr.msg_flags & libc::MSG_TRUNC != 0 { -572 continue; +571 if n >= 0 { +572 break n; 573 } 574 -575 if n >= 0 { -576 break n; -577 } -578 -579 let e = io::Error::last_os_error(); -580 match e.kind() { -581 // Retry receiving -582 io::ErrorKind::Interrupted => continue, -583 _ => return Err(e), -584 } -585 }; -586 meta[0] = decode_recv(&name, &hdr, n as usize)?; -587 Ok(1) -588} -589 -590const CMSG_LEN: usize = 88; -591 -592fn prepare_msg( -593 transmit: &Transmit<'_>, -594 dst_addr: &socket2::SockAddr, -595 #[cfg(not(apple_fast))] hdr: &mut libc::msghdr, -596 #[cfg(apple_fast)] hdr: &mut msghdr_x, -597 iov: &mut libc::iovec, -598 ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>, -599 #[allow(unused_variables)] // only used on FreeBSD & macOS -600 encode_src_ip: bool, -601 sendmsg_einval: bool, -602) { -603 iov.iov_base = transmit.contents.as_ptr() as *const _ as *mut _; -604 iov.iov_len = transmit.contents.len(); -605 -606 // SAFETY: Casting the pointer to a mutable one is legal, -607 // as sendmsg is guaranteed to not alter the mutable pointer -608 // as per the POSIX spec. See the section on the sys/socket.h -609 // header for details. The type is only mutable in the first -610 // place because it is reused by recvmsg as well. -611 let name = dst_addr.as_ptr() as *mut libc::c_void; -612 let namelen = dst_addr.len(); -613 hdr.msg_name = name as *mut _; -614 hdr.msg_namelen = namelen; -615 hdr.msg_iov = iov; -616 hdr.msg_iovlen = 1; -617 -618 hdr.msg_control = ctrl.0.as_mut_ptr() as _; -619 hdr.msg_controllen = CMSG_LEN as _; -620 let mut encoder = unsafe { cmsg::Encoder::new(hdr) }; -621 let ecn = transmit.ecn.map_or(0, |x| x as libc::c_int); -622 // True for IPv4 or IPv4-Mapped IPv6 -623 let is_ipv4 = transmit.destination.is_ipv4() -624 || matches!(transmit.destination.ip(), IpAddr::V6(addr) if addr.to_ipv4_mapped().is_some()); -625 if is_ipv4 { -626 if !sendmsg_einval { -627 #[cfg(not(target_os = "netbsd"))] -628 { -629 encoder.push(libc::IPPROTO_IP, libc::IP_TOS, ecn as IpTosTy); -630 } -631 } -632 } else { -633 encoder.push(libc::IPPROTO_IPV6, libc::IPV6_TCLASS, ecn); +575 let e = io::Error::last_os_error(); +576 match e.kind() { +577 // Retry receiving +578 io::ErrorKind::Interrupted => continue, +579 _ => return Err(e), +580 } +581 }; +582 meta[0] = decode_recv(&name, &hdr, n as usize)?; +583 Ok(1) +584} +585 +586const CMSG_LEN: usize = 88; +587 +588fn prepare_msg( +589 transmit: &Transmit<'_>, +590 dst_addr: &socket2::SockAddr, +591 #[cfg(not(apple_fast))] hdr: &mut libc::msghdr, +592 #[cfg(apple_fast)] hdr: &mut msghdr_x, +593 iov: &mut libc::iovec, +594 ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>, +595 #[allow(unused_variables)] // only used on FreeBSD & macOS +596 encode_src_ip: bool, +597 sendmsg_einval: bool, +598) { +599 iov.iov_base = transmit.contents.as_ptr() as *const _ as *mut _; +600 iov.iov_len = transmit.contents.len(); +601 +602 // SAFETY: Casting the pointer to a mutable one is legal, +603 // as sendmsg is guaranteed to not alter the mutable pointer +604 // as per the POSIX spec. See the section on the sys/socket.h +605 // header for details. The type is only mutable in the first +606 // place because it is reused by recvmsg as well. +607 let name = dst_addr.as_ptr() as *mut libc::c_void; +608 let namelen = dst_addr.len(); +609 hdr.msg_name = name as *mut _; +610 hdr.msg_namelen = namelen; +611 hdr.msg_iov = iov; +612 hdr.msg_iovlen = 1; +613 +614 hdr.msg_control = ctrl.0.as_mut_ptr() as _; +615 hdr.msg_controllen = CMSG_LEN as _; +616 let mut encoder = unsafe { cmsg::Encoder::new(hdr) }; +617 let ecn = transmit.ecn.map_or(0, |x| x as libc::c_int); +618 // True for IPv4 or IPv4-Mapped IPv6 +619 let is_ipv4 = transmit.destination.is_ipv4() +620 || matches!(transmit.destination.ip(), IpAddr::V6(addr) if addr.to_ipv4_mapped().is_some()); +621 if is_ipv4 { +622 if !sendmsg_einval { +623 #[cfg(not(target_os = "netbsd"))] +624 { +625 encoder.push(libc::IPPROTO_IP, libc::IP_TOS, ecn as IpTosTy); +626 } +627 } +628 } else { +629 encoder.push(libc::IPPROTO_IPV6, libc::IPV6_TCLASS, ecn); +630 } +631 +632 if let Some(segment_size) = transmit.effective_segment_size() { +633 gso::set_segment_size(&mut encoder, segment_size as u16); 634 } 635 -636 // Only set the segment size if it is less than the size of the contents. -637 // Some network drivers don't like being told to do GSO even if there is effectively only a single segment (i.e. `segment_size == transmit.contents.len()`) -638 // Additionally, a `segment_size` that is greater than the content also means there is effectively only a single segment. -639 // This case is actually quite common when splitting up a prepared GSO batch again after GSO has been disabled because the last datagram in a GSO batch is allowed to be smaller than the segment size. -640 if let Some(segment_size) = transmit -641 .segment_size -642 .filter(|segment_size| *segment_size < transmit.contents.len()) -643 { -644 gso::set_segment_size(&mut encoder, segment_size as u16); -645 } -646 -647 if let Some(ip) = &transmit.src_ip { -648 match ip { -649 IpAddr::V4(v4) => { -650 #[cfg(any(target_os = "linux", target_os = "android"))] +636 if let Some(ip) = &transmit.src_ip { +637 match ip { +638 IpAddr::V4(v4) => { +639 #[cfg(any(target_os = "linux", target_os = "android"))] +640 { +641 let pktinfo = libc::in_pktinfo { +642 ipi_ifindex: 0, +643 ipi_spec_dst: libc::in_addr { +644 s_addr: u32::from_ne_bytes(v4.octets()), +645 }, +646 ipi_addr: libc::in_addr { s_addr: 0 }, +647 }; +648 encoder.push(libc::IPPROTO_IP, libc::IP_PKTINFO, pktinfo); +649 } +650 #[cfg(any(bsd, apple, solarish))] 651 { -652 let pktinfo = libc::in_pktinfo { -653 ipi_ifindex: 0, -654 ipi_spec_dst: libc::in_addr { -655 s_addr: u32::from_ne_bytes(v4.octets()), -656 }, -657 ipi_addr: libc::in_addr { s_addr: 0 }, -658 }; -659 encoder.push(libc::IPPROTO_IP, libc::IP_PKTINFO, pktinfo); -660 } -661 #[cfg(any(bsd, apple, solarish))] -662 { -663 if encode_src_ip { -664 let addr = libc::in_addr { -665 s_addr: u32::from_ne_bytes(v4.octets()), -666 }; -667 encoder.push(libc::IPPROTO_IP, libc::IP_RECVDSTADDR, addr); -668 } -669 } -670 } -671 IpAddr::V6(v6) => { -672 let pktinfo = libc::in6_pktinfo { -673 ipi6_ifindex: 0, -674 ipi6_addr: libc::in6_addr { -675 s6_addr: v6.octets(), -676 }, -677 }; -678 encoder.push(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO, pktinfo); -679 } -680 } -681 } -682 -683 encoder.finish(); -684} -685 -686#[cfg(not(apple_fast))] -687fn prepare_recv( -688 buf: &mut IoSliceMut, -689 name: &mut MaybeUninit<libc::sockaddr_storage>, -690 ctrl: &mut cmsg::Aligned<MaybeUninit<[u8; CMSG_LEN]>>, -691 hdr: &mut libc::msghdr, -692) { -693 hdr.msg_name = name.as_mut_ptr() as _; -694 hdr.msg_namelen = mem::size_of::<libc::sockaddr_storage>() as _; -695 hdr.msg_iov = buf as *mut IoSliceMut as *mut libc::iovec; -696 hdr.msg_iovlen = 1; -697 hdr.msg_control = ctrl.0.as_mut_ptr() as _; -698 hdr.msg_controllen = CMSG_LEN as _; -699 hdr.msg_flags = 0; -700} -701 -702#[cfg(apple_fast)] -703fn prepare_recv( -704 buf: &mut IoSliceMut, -705 name: &mut MaybeUninit<libc::sockaddr_storage>, -706 ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>, -707 hdr: &mut msghdr_x, -708) { -709 hdr.msg_name = name.as_mut_ptr() as _; -710 hdr.msg_namelen = mem::size_of::<libc::sockaddr_storage>() as _; -711 hdr.msg_iov = buf as *mut IoSliceMut as *mut libc::iovec; -712 hdr.msg_iovlen = 1; -713 hdr.msg_control = ctrl.0.as_mut_ptr() as _; -714 hdr.msg_controllen = CMSG_LEN as _; -715 hdr.msg_flags = 0; -716 hdr.msg_datalen = buf.len(); -717} -718 -719fn decode_recv( -720 name: &MaybeUninit<libc::sockaddr_storage>, -721 #[cfg(not(apple_fast))] hdr: &libc::msghdr, -722 #[cfg(apple_fast)] hdr: &msghdr_x, -723 len: usize, -724) -> io::Result<RecvMeta> { -725 let name = unsafe { name.assume_init() }; -726 let mut ecn_bits = 0; -727 let mut dst_ip = None; -728 let mut interface_index = None; -729 #[allow(unused_mut)] // only mutable on Linux -730 let mut stride = len; -731 -732 let cmsg_iter = unsafe { cmsg::Iter::new(hdr) }; -733 for cmsg in cmsg_iter { -734 match (cmsg.cmsg_level, cmsg.cmsg_type) { -735 (libc::IPPROTO_IP, libc::IP_TOS) => unsafe { -736 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); -737 }, -738 // FreeBSD uses IP_RECVTOS here, and we can be liberal because cmsgs are opt-in. -739 #[cfg(not(any( -740 target_os = "openbsd", -741 target_os = "netbsd", -742 target_os = "dragonfly", -743 solarish -744 )))] -745 (libc::IPPROTO_IP, libc::IP_RECVTOS) => unsafe { -746 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); +652 if encode_src_ip { +653 let addr = libc::in_addr { +654 s_addr: u32::from_ne_bytes(v4.octets()), +655 }; +656 encoder.push(libc::IPPROTO_IP, libc::IP_RECVDSTADDR, addr); +657 } +658 } +659 } +660 IpAddr::V6(v6) => { +661 let pktinfo = libc::in6_pktinfo { +662 ipi6_ifindex: 0, +663 ipi6_addr: libc::in6_addr { +664 s6_addr: v6.octets(), +665 }, +666 }; +667 encoder.push(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO, pktinfo); +668 } +669 } +670 } +671 +672 encoder.finish(); +673} +674 +675#[cfg(not(apple_fast))] +676fn prepare_recv( +677 buf: &mut IoSliceMut<'_>, +678 name: &mut MaybeUninit<libc::sockaddr_storage>, +679 ctrl: &mut cmsg::Aligned<MaybeUninit<[u8; CMSG_LEN]>>, +680 hdr: &mut libc::msghdr, +681) { +682 hdr.msg_name = name.as_mut_ptr() as _; +683 hdr.msg_namelen = mem::size_of::<libc::sockaddr_storage>() as _; +684 hdr.msg_iov = buf as *mut IoSliceMut<'_> as *mut libc::iovec; +685 hdr.msg_iovlen = 1; +686 hdr.msg_control = ctrl.0.as_mut_ptr() as _; +687 hdr.msg_controllen = CMSG_LEN as _; +688 hdr.msg_flags = 0; +689} +690 +691#[cfg(apple_fast)] +692fn prepare_recv( +693 buf: &mut IoSliceMut<'_>, +694 name: &mut MaybeUninit<libc::sockaddr_storage>, +695 ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>, +696 hdr: &mut msghdr_x, +697) { +698 hdr.msg_name = name.as_mut_ptr() as _; +699 hdr.msg_namelen = mem::size_of::<libc::sockaddr_storage>() as _; +700 hdr.msg_iov = buf as *mut IoSliceMut<'_> as *mut libc::iovec; +701 hdr.msg_iovlen = 1; +702 hdr.msg_control = ctrl.0.as_mut_ptr() as _; +703 hdr.msg_controllen = CMSG_LEN as _; +704 hdr.msg_flags = 0; +705 hdr.msg_datalen = buf.len(); +706} +707 +708fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>( +709 name: &MaybeUninit<libc::sockaddr_storage>, +710 hdr: &M, +711 len: usize, +712) -> io::Result<RecvMeta> { +713 let name = unsafe { name.assume_init() }; +714 let mut ecn_bits = 0; +715 let mut dst_ip = None; +716 let mut interface_index = None; +717 #[allow(unused_mut)] // only mutable on Linux +718 let mut stride = len; +719 +720 let cmsg_iter = unsafe { cmsg::Iter::new(hdr) }; +721 for cmsg in cmsg_iter { +722 match (cmsg.cmsg_level, cmsg.cmsg_type) { +723 (libc::IPPROTO_IP, libc::IP_TOS) => unsafe { +724 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); +725 }, +726 // FreeBSD uses IP_RECVTOS here, and we can be liberal because cmsgs are opt-in. +727 #[cfg(not(any( +728 target_os = "openbsd", +729 target_os = "netbsd", +730 target_os = "dragonfly", +731 solarish +732 )))] +733 (libc::IPPROTO_IP, libc::IP_RECVTOS) => unsafe { +734 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); +735 }, +736 (libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => unsafe { +737 // Temporary hack around broken macos ABI. Remove once upstream fixes it. +738 // https://bugreport.apple.com/web/?problemID=48761855 +739 #[allow(clippy::unnecessary_cast)] // cmsg.cmsg_len defined as size_t +740 if cfg!(apple) +741 && cmsg.cmsg_len as usize == libc::CMSG_LEN(mem::size_of::<u8>() as _) as usize +742 { +743 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); +744 } else { +745 ecn_bits = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as u8; +746 } 747 }, -748 (libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => unsafe { -749 // Temporary hack around broken macos ABI. Remove once upstream fixes it. -750 // https://bugreport.apple.com/web/?problemID=48761855 -751 #[allow(clippy::unnecessary_cast)] // cmsg.cmsg_len defined as size_t -752 if cfg!(apple) -753 && cmsg.cmsg_len as usize == libc::CMSG_LEN(mem::size_of::<u8>() as _) as usize -754 { -755 ecn_bits = cmsg::decode::<u8, libc::cmsghdr>(cmsg); -756 } else { -757 ecn_bits = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as u8; -758 } -759 }, -760 #[cfg(any(target_os = "linux", target_os = "android"))] -761 (libc::IPPROTO_IP, libc::IP_PKTINFO) => { -762 let pktinfo = unsafe { cmsg::decode::<libc::in_pktinfo, libc::cmsghdr>(cmsg) }; -763 dst_ip = Some(IpAddr::V4(Ipv4Addr::from( -764 pktinfo.ipi_addr.s_addr.to_ne_bytes(), -765 ))); -766 interface_index = Some(pktinfo.ipi_ifindex as u32); -767 } -768 #[cfg(any(bsd, apple))] -769 (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => { -770 let in_addr = unsafe { cmsg::decode::<libc::in_addr, libc::cmsghdr>(cmsg) }; -771 dst_ip = Some(IpAddr::V4(Ipv4Addr::from(in_addr.s_addr.to_ne_bytes()))); -772 } -773 (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { -774 let pktinfo = unsafe { cmsg::decode::<libc::in6_pktinfo, libc::cmsghdr>(cmsg) }; -775 dst_ip = Some(IpAddr::V6(Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr))); -776 interface_index = Some(pktinfo.ipi6_ifindex as u32); -777 } -778 #[cfg(any(target_os = "linux", target_os = "android"))] -779 (libc::SOL_UDP, gro::UDP_GRO) => unsafe { -780 stride = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as usize; -781 }, -782 _ => {} +748 #[cfg(any(target_os = "linux", target_os = "android"))] +749 (libc::IPPROTO_IP, libc::IP_PKTINFO) => { +750 let pktinfo = unsafe { cmsg::decode::<libc::in_pktinfo, libc::cmsghdr>(cmsg) }; +751 dst_ip = Some(IpAddr::V4(Ipv4Addr::from( +752 pktinfo.ipi_addr.s_addr.to_ne_bytes(), +753 ))); +754 interface_index = Some(pktinfo.ipi_ifindex as u32); +755 } +756 #[cfg(any(bsd, apple))] +757 (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => { +758 let in_addr = unsafe { cmsg::decode::<libc::in_addr, libc::cmsghdr>(cmsg) }; +759 dst_ip = Some(IpAddr::V4(Ipv4Addr::from(in_addr.s_addr.to_ne_bytes()))); +760 } +761 (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { +762 let pktinfo = unsafe { cmsg::decode::<libc::in6_pktinfo, libc::cmsghdr>(cmsg) }; +763 dst_ip = Some(IpAddr::V6(Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr))); +764 interface_index = Some(pktinfo.ipi6_ifindex as u32); +765 } +766 #[cfg(any(target_os = "linux", target_os = "android"))] +767 (libc::SOL_UDP, libc::UDP_GRO) => unsafe { +768 stride = cmsg::decode::<libc::c_int, libc::cmsghdr>(cmsg) as usize; +769 }, +770 _ => {} +771 } +772 } +773 +774 let addr = match libc::c_int::from(name.ss_family) { +775 libc::AF_INET => { +776 // Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in. +777 let addr: &libc::sockaddr_in = +778 unsafe { &*(&name as *const _ as *const libc::sockaddr_in) }; +779 SocketAddr::V4(SocketAddrV4::new( +780 Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes()), +781 u16::from_be(addr.sin_port), +782 )) 783 } -784 } -785 -786 let addr = match libc::c_int::from(name.ss_family) { -787 libc::AF_INET => { -788 // Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in. -789 let addr: &libc::sockaddr_in = -790 unsafe { &*(&name as *const _ as *const libc::sockaddr_in) }; -791 SocketAddr::V4(SocketAddrV4::new( -792 Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes()), -793 u16::from_be(addr.sin_port), -794 )) -795 } -796 libc::AF_INET6 => { -797 // Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6. -798 let addr: &libc::sockaddr_in6 = -799 unsafe { &*(&name as *const _ as *const libc::sockaddr_in6) }; -800 SocketAddr::V6(SocketAddrV6::new( -801 Ipv6Addr::from(addr.sin6_addr.s6_addr), -802 u16::from_be(addr.sin6_port), -803 addr.sin6_flowinfo, -804 addr.sin6_scope_id, -805 )) -806 } -807 f => { -808 return Err(io::Error::other(format!( -809 "expected AF_INET or AF_INET6, got {f} in decode_recv" -810 ))); -811 } -812 }; -813 -814 Ok(RecvMeta { -815 len, -816 stride, -817 addr, -818 ecn: EcnCodepoint::from_bits(ecn_bits), -819 dst_ip, -820 interface_index, -821 }) -822} +784 libc::AF_INET6 => { +785 // Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6. +786 let addr: &libc::sockaddr_in6 = +787 unsafe { &*(&name as *const _ as *const libc::sockaddr_in6) }; +788 SocketAddr::V6(SocketAddrV6::new( +789 Ipv6Addr::from(addr.sin6_addr.s6_addr), +790 u16::from_be(addr.sin6_port), +791 addr.sin6_flowinfo, +792 addr.sin6_scope_id, +793 )) +794 } +795 f => { +796 return Err(io::Error::other(format!( +797 "expected AF_INET or AF_INET6, got {f} in decode_recv" +798 ))); +799 } +800 }; +801 +802 Ok(RecvMeta { +803 len, +804 stride, +805 addr, +806 ecn: EcnCodepoint::from_bits(ecn_bits), +807 dst_ip, +808 interface_index, +809 }) +810} +811 +812#[cfg(not(apple_slow))] +813// Chosen somewhat arbitrarily; might benefit from additional tuning. +814pub(crate) const BATCH_SIZE: usize = 32; +815 +816#[cfg(apple_slow)] +817pub(crate) const BATCH_SIZE: usize = 1; +818 +819#[cfg(any(target_os = "linux", target_os = "android"))] +820mod gso { +821 use super::*; +822 use std::{ffi::CStr, mem, str::FromStr, sync::OnceLock}; 823 -824#[cfg(not(apple_slow))] -825// Chosen somewhat arbitrarily; might benefit from additional tuning. -826pub(crate) const BATCH_SIZE: usize = 32; -827 -828#[cfg(apple_slow)] -829pub(crate) const BATCH_SIZE: usize = 1; +824 // Support for UDP GSO has been added to linux kernel in version 4.18 +825 // https://github.com/torvalds/linux/commit/cb586c63e3fc5b227c51fd8c4cb40b34d3750645 +826 const SUPPORTED_SINCE: KernelVersion = KernelVersion { +827 version: 4, +828 major_revision: 18, +829 }; 830 -831#[cfg(any(target_os = "linux", target_os = "android"))] -832mod gso { -833 use super::*; -834 use std::{ffi::CStr, mem, str::FromStr, sync::OnceLock}; +831 /// Checks whether GSO support is available by checking the kernel version followed by setting +832 /// the UDP_SEGMENT option on a socket +833 pub(crate) fn max_gso_segments() -> usize { +834 const GSO_SIZE: libc::c_int = 1500; 835 -836 #[cfg(not(target_os = "android"))] -837 const UDP_SEGMENT: libc::c_int = libc::UDP_SEGMENT; -838 #[cfg(target_os = "android")] -839 // TODO: Add this to libc -840 const UDP_SEGMENT: libc::c_int = 103; -841 -842 // Support for UDP GSO has been added to linux kernel in version 4.18 -843 // https://github.com/torvalds/linux/commit/cb586c63e3fc5b227c51fd8c4cb40b34d3750645 -844 const SUPPORTED_SINCE: KernelVersion = KernelVersion { -845 version: 4, -846 major_revision: 18, -847 }; -848 -849 /// Checks whether GSO support is available by checking the kernel version followed by setting -850 /// the UDP_SEGMENT option on a socket -851 pub(crate) fn max_gso_segments() -> usize { -852 const GSO_SIZE: libc::c_int = 1500; -853 -854 if !SUPPORTED_BY_CURRENT_KERNEL.get_or_init(supported_by_current_kernel) { -855 return 1; -856 } -857 -858 let socket = match std::net::UdpSocket::bind("[::]:0") -859 .or_else(|_| std::net::UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))) -860 { -861 Ok(socket) => socket, -862 Err(_) => return 1, -863 }; -864 -865 // As defined in linux/udp.h -866 // #define UDP_MAX_SEGMENTS (1 << 6UL) -867 match set_socket_option(&socket, libc::SOL_UDP, UDP_SEGMENT, GSO_SIZE) { -868 Ok(()) => 64, -869 Err(_e) => { -870 crate::log::debug!( -871 "failed to set `UDP_SEGMENT` socket option ({_e}); setting `max_gso_segments = 1`" -872 ); -873 -874 1 -875 } -876 } -877 } -878 -879 pub(crate) fn set_segment_size(encoder: &mut cmsg::Encoder<libc::msghdr>, segment_size: u16) { -880 encoder.push(libc::SOL_UDP, UDP_SEGMENT, segment_size); -881 } -882 -883 // Avoid calling `supported_by_current_kernel` for each socket by using `OnceLock`. -884 static SUPPORTED_BY_CURRENT_KERNEL: OnceLock<bool> = OnceLock::new(); -885 -886 fn supported_by_current_kernel() -> bool { -887 let kernel_version_string = match kernel_version_string() { -888 Ok(kernel_version_string) => kernel_version_string, -889 Err(_e) => { -890 crate::log::warn!("GSO disabled: uname returned {_e}"); -891 return false; -892 } -893 }; +836 if !SUPPORTED_BY_CURRENT_KERNEL.get_or_init(supported_by_current_kernel) { +837 return 1; +838 } +839 +840 let socket = match std::net::UdpSocket::bind("[::]:0") +841 .or_else(|_| std::net::UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))) +842 { +843 Ok(socket) => socket, +844 Err(_) => return 1, +845 }; +846 +847 // As defined in linux/udp.h +848 // #define UDP_MAX_SEGMENTS (1 << 6UL) +849 match set_socket_option(&socket, libc::SOL_UDP, libc::UDP_SEGMENT, GSO_SIZE) { +850 Ok(()) => 64, +851 Err(_e) => { +852 crate::log::debug!( +853 "failed to set `UDP_SEGMENT` socket option ({_e}); setting `max_gso_segments = 1`" +854 ); +855 +856 1 +857 } +858 } +859 } +860 +861 pub(crate) fn set_segment_size( +862 encoder: &mut cmsg::Encoder<'_, libc::msghdr>, +863 segment_size: u16, +864 ) { +865 encoder.push(libc::SOL_UDP, libc::UDP_SEGMENT, segment_size); +866 } +867 +868 // Avoid calling `supported_by_current_kernel` for each socket by using `OnceLock`. +869 static SUPPORTED_BY_CURRENT_KERNEL: OnceLock<bool> = OnceLock::new(); +870 +871 fn supported_by_current_kernel() -> bool { +872 let kernel_version_string = match kernel_version_string() { +873 Ok(kernel_version_string) => kernel_version_string, +874 Err(_e) => { +875 crate::log::warn!("GSO disabled: uname returned {_e}"); +876 return false; +877 } +878 }; +879 +880 let Some(kernel_version) = KernelVersion::from_str(&kernel_version_string) else { +881 crate::log::warn!( +882 "GSO disabled: failed to parse kernel version ({kernel_version_string})" +883 ); +884 return false; +885 }; +886 +887 if kernel_version < SUPPORTED_SINCE { +888 crate::log::info!("GSO disabled: kernel too old ({kernel_version_string}); need 4.18+",); +889 return false; +890 } +891 +892 true +893 } 894 -895 let Some(kernel_version) = KernelVersion::from_str(&kernel_version_string) else { -896 crate::log::warn!( -897 "GSO disabled: failed to parse kernel version ({kernel_version_string})" -898 ); -899 return false; -900 }; -901 -902 if kernel_version < SUPPORTED_SINCE { -903 crate::log::info!("GSO disabled: kernel too old ({kernel_version_string}); need 4.18+",); -904 return false; -905 } -906 -907 true -908 } -909 -910 fn kernel_version_string() -> io::Result<String> { -911 let mut n = unsafe { mem::zeroed() }; -912 let r = unsafe { libc::uname(&mut n) }; -913 if r != 0 { -914 return Err(io::Error::last_os_error()); -915 } -916 Ok(unsafe { -917 CStr::from_ptr(n.release[..].as_ptr()) -918 .to_string_lossy() -919 .into_owned() -920 }) -921 } +895 fn kernel_version_string() -> io::Result<String> { +896 let mut n = unsafe { mem::zeroed() }; +897 let r = unsafe { libc::uname(&mut n) }; +898 if r != 0 { +899 return Err(io::Error::last_os_error()); +900 } +901 Ok(unsafe { +902 CStr::from_ptr(n.release[..].as_ptr()) +903 .to_string_lossy() +904 .into_owned() +905 }) +906 } +907 +908 // https://www.linfo.org/kernel_version_numbering.html +909 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug)] +910 struct KernelVersion { +911 version: u8, +912 major_revision: u8, +913 } +914 +915 impl KernelVersion { +916 fn from_str(release: &str) -> Option<Self> { +917 let mut split = release +918 .split_once('-') +919 .map(|pair| pair.0) +920 .unwrap_or(release) +921 .split('.'); 922 -923 // https://www.linfo.org/kernel_version_numbering.html -924 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug)] -925 struct KernelVersion { -926 version: u8, -927 major_revision: u8, -928 } -929 -930 impl KernelVersion { -931 fn from_str(release: &str) -> Option<Self> { -932 let mut split = release -933 .split_once('-') -934 .map(|pair| pair.0) -935 .unwrap_or(release) -936 .split('.'); -937 -938 let version = u8::from_str(split.next()?).ok()?; -939 let major_revision = u8::from_str(split.next()?).ok()?; -940 -941 Some(Self { -942 version, -943 major_revision, -944 }) -945 } -946 } -947 -948 #[cfg(test)] -949 mod test { -950 use super::*; -951 -952 #[test] -953 fn parse_current_kernel_version_release_string() { -954 let release = kernel_version_string().unwrap(); -955 KernelVersion::from_str(&release).unwrap(); -956 } -957 -958 #[test] -959 fn parse_kernel_version_release_string() { -960 // These are made up for the test +923 let version = u8::from_str(split.next()?).ok()?; +924 let major_revision = u8::from_str(split.next()?).ok()?; +925 +926 Some(Self { +927 version, +928 major_revision, +929 }) +930 } +931 } +932 +933 #[cfg(test)] +934 mod test { +935 use super::*; +936 +937 #[test] +938 fn parse_current_kernel_version_release_string() { +939 let release = kernel_version_string().unwrap(); +940 KernelVersion::from_str(&release).unwrap(); +941 } +942 +943 #[test] +944 fn parse_kernel_version_release_string() { +945 // These are made up for the test +946 assert_eq!( +947 KernelVersion::from_str("4.14"), +948 Some(KernelVersion { +949 version: 4, +950 major_revision: 14 +951 }) +952 ); +953 assert_eq!( +954 KernelVersion::from_str("4.18"), +955 Some(KernelVersion { +956 version: 4, +957 major_revision: 18 +958 }) +959 ); +960 // These were seen in the wild 961 assert_eq!( -962 KernelVersion::from_str("4.14"), +962 KernelVersion::from_str("4.14.186-27095505"), 963 Some(KernelVersion { 964 version: 4, 965 major_revision: 14 966 }) 967 ); 968 assert_eq!( -969 KernelVersion::from_str("4.18"), +969 KernelVersion::from_str("6.8.0-59-generic"), 970 Some(KernelVersion { -971 version: 4, -972 major_revision: 18 +971 version: 6, +972 major_revision: 8 973 }) 974 ); -975 // These were seen in the wild -976 assert_eq!( -977 KernelVersion::from_str("4.14.186-27095505"), -978 Some(KernelVersion { -979 version: 4, -980 major_revision: 14 -981 }) -982 ); -983 assert_eq!( -984 KernelVersion::from_str("6.8.0-59-generic"), -985 Some(KernelVersion { -986 version: 6, -987 major_revision: 8 -988 }) -989 ); +975 } +976 } +977} +978 +979// On Apple platforms using the `sendmsg_x` call, UDP datagram segmentation is not +980// offloaded to the NIC or even the kernel, but instead done here in user space in +981// [`send`]) and then passed to the OS as individual `iovec`s (up to `BATCH_SIZE`). +982#[cfg(not(any(target_os = "linux", target_os = "android")))] +983mod gso { +984 use super::*; +985 +986 pub(super) fn max_gso_segments() -> usize { +987 #[cfg(apple_fast)] +988 { +989 BATCH_SIZE 990 } -991 } -992} -993 -994// On Apple platforms using the `sendmsg_x` call, UDP datagram segmentation is not -995// offloaded to the NIC or even the kernel, but instead done here in user space in -996// [`send`]) and then passed to the OS as individual `iovec`s (up to `BATCH_SIZE`). -997#[cfg(not(any(target_os = "linux", target_os = "android")))] -998mod gso { -999 use super::*; -1000 -1001 pub(super) fn max_gso_segments() -> usize { -1002 #[cfg(apple_fast)] -1003 { -1004 BATCH_SIZE -1005 } -1006 #[cfg(not(apple_fast))] -1007 { -1008 1 -1009 } -1010 } -1011 -1012 pub(super) fn set_segment_size( -1013 #[cfg(not(apple_fast))] _encoder: &mut cmsg::Encoder<libc::msghdr>, -1014 #[cfg(apple_fast)] _encoder: &mut cmsg::Encoder<msghdr_x>, -1015 _segment_size: u16, -1016 ) { -1017 } -1018} -1019 -1020#[cfg(any(target_os = "linux", target_os = "android"))] -1021mod gro { -1022 use super::*; -1023 -1024 #[cfg(not(target_os = "android"))] -1025 pub(crate) const UDP_GRO: libc::c_int = libc::UDP_GRO; -1026 #[cfg(target_os = "android")] -1027 // TODO: Add this to libc -1028 pub(crate) const UDP_GRO: libc::c_int = 104; -1029 -1030 pub(crate) fn gro_segments() -> NonZeroUsize { -1031 let socket = match std::net::UdpSocket::bind("[::]:0") -1032 .or_else(|_| std::net::UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))) -1033 { -1034 Ok(socket) => socket, -1035 Err(_) => return NonZeroUsize::MIN, -1036 }; -1037 -1038 // As defined in net/ipv4/udp_offload.c -1039 // #define UDP_GRO_CNT_MAX 64 -1040 // -1041 // NOTE: this MUST be set to UDP_GRO_CNT_MAX to ensure that the receive buffer size -1042 // (get_max_udp_payload_size() * gro_segments()) is large enough to hold the largest GRO -1043 // list the kernel might potentially produce. See -1044 // https://github.com/quinn-rs/quinn/pull/1354. -1045 match set_socket_option(&socket, libc::SOL_UDP, UDP_GRO, OPTION_ON) { -1046 Ok(()) => NonZeroUsize::new(64).expect("known"), -1047 Err(_) => NonZeroUsize::MIN, -1048 } -1049 } -1050} -1051 -1052/// Returns whether the given socket option is supported on the current platform -1053/// -1054/// Yields `Ok(true)` if the option was set successfully, `Ok(false)` if setting -1055/// the option raised an `ENOPROTOOPT` or `EOPNOTSUPP` error, and `Err` for any other error. -1056fn set_socket_option_supported( -1057 socket: &impl AsRawFd, -1058 level: libc::c_int, -1059 name: libc::c_int, -1060 value: libc::c_int, -1061) -> io::Result<bool> { -1062 match set_socket_option(socket, level, name, value) { -1063 Ok(()) => Ok(true), -1064 Err(err) if err.raw_os_error() == Some(libc::ENOPROTOOPT) => Ok(false), -1065 Err(err) if err.raw_os_error() == Some(libc::EOPNOTSUPP) => Ok(false), -1066 Err(err) => Err(err), -1067 } -1068} -1069 -1070fn set_socket_option( -1071 socket: &impl AsRawFd, -1072 level: libc::c_int, -1073 name: libc::c_int, -1074 value: libc::c_int, -1075) -> io::Result<()> { -1076 let rc = unsafe { -1077 libc::setsockopt( -1078 socket.as_raw_fd(), -1079 level, -1080 name, -1081 &value as *const _ as _, -1082 mem::size_of_val(&value) as _, -1083 ) -1084 }; -1085 -1086 match rc == 0 { -1087 true => Ok(()), -1088 false => Err(io::Error::last_os_error()), -1089 } -1090} -1091 -1092const OPTION_ON: libc::c_int = 1; -1093 -1094#[cfg(not(any(target_os = "linux", target_os = "android")))] -1095mod gro { -1096 use std::num::NonZeroUsize; -1097 -1098 pub(super) fn gro_segments() -> NonZeroUsize { -1099 NonZeroUsize::MIN -1100 } -1101} \ No newline at end of file +991 #[cfg(not(apple_fast))] +992 { +993 1 +994 } +995 } +996 +997 pub(super) fn set_segment_size( +998 #[cfg(not(apple_fast))] _encoder: &mut cmsg::Encoder<'_, libc::msghdr>, +999 #[cfg(apple_fast)] _encoder: &mut cmsg::Encoder<'_, msghdr_x>, +1000 _segment_size: u16, +1001 ) { +1002 } +1003} +1004 +1005#[cfg(any(target_os = "linux", target_os = "android"))] +1006mod gro { +1007 use super::*; +1008 +1009 pub(crate) fn gro_segments() -> NonZeroUsize { +1010 let socket = match std::net::UdpSocket::bind("[::]:0") +1011 .or_else(|_| std::net::UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))) +1012 { +1013 Ok(socket) => socket, +1014 Err(_) => return NonZeroUsize::MIN, +1015 }; +1016 +1017 // As defined in net/ipv4/udp_offload.c +1018 // #define UDP_GRO_CNT_MAX 64 +1019 // +1020 // NOTE: this MUST be set to UDP_GRO_CNT_MAX to ensure that the receive buffer size +1021 // (get_max_udp_payload_size() * gro_segments()) is large enough to hold the largest GRO +1022 // list the kernel might potentially produce. See +1023 // https://github.com/quinn-rs/quinn/pull/1354. +1024 match set_socket_option(&socket, libc::SOL_UDP, libc::UDP_GRO, OPTION_ON) { +1025 Ok(()) => NonZeroUsize::new(64).expect("known"), +1026 Err(_) => NonZeroUsize::MIN, +1027 } +1028 } +1029} +1030 +1031/// Returns whether the given socket option is supported on the current platform +1032/// +1033/// Yields `Ok(true)` if the option was set successfully, `Ok(false)` if setting +1034/// the option raised an `ENOPROTOOPT` or `EOPNOTSUPP` error, and `Err` for any other error. +1035fn set_socket_option_supported( +1036 socket: &impl AsRawFd, +1037 level: libc::c_int, +1038 name: libc::c_int, +1039 value: libc::c_int, +1040) -> io::Result<bool> { +1041 match set_socket_option(socket, level, name, value) { +1042 Ok(()) => Ok(true), +1043 Err(err) if err.raw_os_error() == Some(libc::ENOPROTOOPT) => Ok(false), +1044 Err(err) if err.raw_os_error() == Some(libc::EOPNOTSUPP) => Ok(false), +1045 Err(err) => Err(err), +1046 } +1047} +1048 +1049fn set_socket_option( +1050 socket: &impl AsRawFd, +1051 level: libc::c_int, +1052 name: libc::c_int, +1053 value: libc::c_int, +1054) -> io::Result<()> { +1055 let rc = unsafe { +1056 libc::setsockopt( +1057 socket.as_raw_fd(), +1058 level, +1059 name, +1060 &value as *const _ as _, +1061 mem::size_of_val(&value) as _, +1062 ) +1063 }; +1064 +1065 match rc == 0 { +1066 true => Ok(()), +1067 false => Err(io::Error::last_os_error()), +1068 } +1069} +1070 +1071const OPTION_ON: libc::c_int = 1; +1072 +1073#[cfg(not(any(target_os = "linux", target_os = "android")))] +1074mod gro { +1075 use std::num::NonZeroUsize; +1076 +1077 pub(super) fn gro_segments() -> NonZeroUsize { +1078 NonZeroUsize::MIN +1079 } +1080} \ No newline at end of file diff --git a/pr/255/docs/src/perf/lib.rs.html b/pr/255/docs/src/perf/lib.rs.html index 4c2c22ac8..59df4814f 100644 --- a/pr/255/docs/src/perf/lib.rs.html +++ b/pr/255/docs/src/perf/lib.rs.html @@ -205,9 +205,9 @@ 205impl CongestionAlgorithm { 206 pub fn build(self) -> Arc<dyn ControllerFactory + Send + Sync + 'static> { 207 match self { -208 CongestionAlgorithm::Cubic => Arc::new(congestion::CubicConfig::default()), -209 CongestionAlgorithm::Bbr => Arc::new(congestion::BbrConfig::default()), -210 CongestionAlgorithm::NewReno => Arc::new(congestion::NewRenoConfig::default()), +208 Self::Cubic => Arc::new(congestion::CubicConfig::default()), +209 Self::Bbr => Arc::new(congestion::BbrConfig::default()), +210 Self::NewReno => Arc::new(congestion::NewRenoConfig::default()), 211 } 212 } 213} diff --git a/pr/255/docs/trait.impl/core/clone/trait.Clone.js b/pr/255/docs/trait.impl/core/clone/trait.Clone.js index f78999e6a..6966d52bc 100644 --- a/pr/255/docs/trait.impl/core/clone/trait.Clone.js +++ b/pr/255/docs/trait.impl/core/clone/trait.Clone.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Clone for CipherSuite"],["impl Clone for Opt"]]],["iroh_quinn",[["impl Clone for ReadError"],["impl Clone for ReadExactError"],["impl Clone for ReadToEndError"],["impl Clone for ResetError"],["impl Clone for SendDatagramError"],["impl Clone for StoppedError"],["impl Clone for WriteError"],["impl Clone for Connection"],["impl Clone for Endpoint"],["impl Clone for EndpointStats"],["impl Clone for WeakConnectionHandle"]]],["iroh_quinn_proto",[["impl Clone for ClosePathError"],["impl Clone for ConfigError"],["impl Clone for ConnectError"],["impl Clone for ConnectionError"],["impl Clone for Dir"],["impl Clone for EcnCodepoint"],["impl Clone for FinishError"],["impl Clone for FrameType"],["impl Clone for LongType"],["impl Clone for PacketDecodeError"],["impl Clone for PathError"],["impl Clone for PathEvent"],["impl Clone for PathStatus"],["impl Clone for ProtectedHeader"],["impl Clone for ReadError"],["impl Clone for ReadableError"],["impl Clone for SendDatagramError"],["impl Clone for SetPathStatusError"],["impl Clone for Side"],["impl Clone for WriteError"],["impl Clone for Event"],["impl Clone for Error"],["impl Clone for UnexpectedEnd"],["impl Clone for Bbr"],["impl Clone for BbrConfig"],["impl Clone for Cubic"],["impl Clone for CubicConfig"],["impl Clone for NewReno"],["impl Clone for NewRenoConfig"],["impl Clone for NoInitialCipherSuite"],["impl Clone for AckFrequencyConfig"],["impl Clone for ApplicationClose"],["impl Clone for ClientConfig"],["impl Clone for ClosedPath"],["impl Clone for ClosedStream"],["impl Clone for ConnectionClose"],["impl Clone for ConnectionHandle"],["impl Clone for ConnectionId"],["impl Clone for ConnectionStats"],["impl Clone for Datagram"],["impl Clone for EndpointConfig"],["impl Clone for FourTuple"],["impl Clone for FrameStats"],["impl Clone for IdleTimeout"],["impl Clone for InvalidCid"],["impl Clone for MtuDiscoveryConfig"],["impl Clone for PathId"],["impl Clone for PathStats"],["impl Clone for ProtectedInitialHeader"],["impl Clone for RandomConnectionIdGenerator"],["impl Clone for RttEstimator"],["impl Clone for ServerConfig"],["impl Clone for ShouldTransmit"],["impl Clone for StreamId"],["impl Clone for TransportConfig"],["impl Clone for Error"],["impl Clone for Code"],["impl Clone for UdpStats"],["impl Clone for ValidationTokenConfig"],["impl Clone for VarInt"],["impl Clone for VarIntBoundsExceeded"],["impl Clone for Written"],["impl Clone for TransportParameters"]]],["iroh_quinn_udp",[["impl Clone for EcnCodepoint"],["impl Clone for RecvMeta"],["impl<'a> Clone for Transmit<'a>"]]],["perf",[["impl Clone for CongestionAlgorithm"],["impl Clone for OpenStreamStats"]]]]); + var implementors = Object.fromEntries([["bench",[["impl Clone for CipherSuite"],["impl Clone for Opt"]]],["iroh_quinn",[["impl Clone for ReadError"],["impl Clone for ReadExactError"],["impl Clone for ReadToEndError"],["impl Clone for ResetError"],["impl Clone for SendDatagramError"],["impl Clone for StoppedError"],["impl Clone for WriteError"],["impl Clone for Connection"],["impl Clone for Endpoint"],["impl Clone for EndpointStats"],["impl Clone for WeakConnectionHandle"]]],["iroh_quinn_proto",[["impl Clone for ClosePathError"],["impl Clone for ConfigError"],["impl Clone for ConnectError"],["impl Clone for ConnectionError"],["impl Clone for Dir"],["impl Clone for EcnCodepoint"],["impl Clone for FinishError"],["impl Clone for FrameType"],["impl Clone for LongType"],["impl Clone for MaybeFrame"],["impl Clone for PacketDecodeError"],["impl Clone for PathError"],["impl Clone for PathEvent"],["impl Clone for PathStatus"],["impl Clone for ProtectedHeader"],["impl Clone for ReadError"],["impl Clone for ReadableError"],["impl Clone for SendDatagramError"],["impl Clone for SetPathStatusError"],["impl Clone for Side"],["impl Clone for WriteError"],["impl Clone for Event"],["impl Clone for Error"],["impl Clone for UnexpectedEnd"],["impl Clone for Bbr"],["impl Clone for BbrConfig"],["impl Clone for Cubic"],["impl Clone for CubicConfig"],["impl Clone for NewReno"],["impl Clone for NewRenoConfig"],["impl Clone for NoInitialCipherSuite"],["impl Clone for AckFrequencyConfig"],["impl Clone for ApplicationClose"],["impl Clone for ClientConfig"],["impl Clone for ClosedPath"],["impl Clone for ClosedStream"],["impl Clone for ConnectionClose"],["impl Clone for ConnectionHandle"],["impl Clone for ConnectionId"],["impl Clone for ConnectionStats"],["impl Clone for Datagram"],["impl Clone for DatagramInfo"],["impl Clone for EndpointConfig"],["impl Clone for FourTuple"],["impl Clone for FrameStats"],["impl Clone for IdleTimeout"],["impl Clone for InvalidCid"],["impl Clone for MtuDiscoveryConfig"],["impl Clone for MultipathNotNegotiated"],["impl Clone for PathId"],["impl Clone for PathStats"],["impl Clone for ProtectedInitialHeader"],["impl Clone for RandomConnectionIdGenerator"],["impl Clone for RttEstimator"],["impl Clone for ServerConfig"],["impl Clone for ShouldTransmit"],["impl Clone for StreamId"],["impl Clone for StreamInfo"],["impl Clone for TransportConfig"],["impl Clone for Error"],["impl Clone for Code"],["impl Clone for UdpStats"],["impl Clone for ValidationTokenConfig"],["impl Clone for VarInt"],["impl Clone for VarIntBoundsExceeded"],["impl Clone for Written"],["impl Clone for TransportParameters"]]],["iroh_quinn_udp",[["impl Clone for EcnCodepoint"],["impl Clone for RecvMeta"],["impl<'a> Clone for Transmit<'a>"]]],["perf",[["impl Clone for CongestionAlgorithm"],["impl Clone for OpenStreamStats"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[499,2982,18061,851,568]} \ No newline at end of file +//{"start":57,"fragment_lengths":[499,2982,19209,851,568]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/cmp/trait.Eq.js b/pr/255/docs/trait.impl/core/cmp/trait.Eq.js index 48b25c8fb..df733bcb7 100644 --- a/pr/255/docs/trait.impl/core/cmp/trait.Eq.js +++ b/pr/255/docs/trait.impl/core/cmp/trait.Eq.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Eq for CipherSuite"]]],["iroh_quinn",[["impl Eq for ReadError"],["impl Eq for ReadExactError"],["impl Eq for ReadToEndError"],["impl Eq for ResetError"],["impl Eq for SendDatagramError"],["impl Eq for StoppedError"],["impl Eq for WriteError"]]],["iroh_quinn_proto",[["impl Eq for ClosePathError"],["impl Eq for ConfigError"],["impl Eq for ConnectError"],["impl Eq for ConnectionError"],["impl Eq for Dir"],["impl Eq for EcnCodepoint"],["impl Eq for FinishError"],["impl Eq for FrameType"],["impl Eq for LongType"],["impl Eq for PacketDecodeError"],["impl Eq for PathError"],["impl Eq for PathEvent"],["impl Eq for PathStatus"],["impl Eq for ReadError"],["impl Eq for ReadableError"],["impl Eq for SendDatagramError"],["impl Eq for SetPathStatusError"],["impl Eq for Side"],["impl Eq for StreamEvent"],["impl Eq for WriteError"],["impl Eq for Error"],["impl Eq for UnexpectedEnd"],["impl Eq for ExportKeyingMaterialError"],["impl Eq for ApplicationClose"],["impl Eq for Chunk"],["impl Eq for ClosedPath"],["impl Eq for ClosedStream"],["impl Eq for ConnectionClose"],["impl Eq for ConnectionHandle"],["impl Eq for ConnectionId"],["impl Eq for FourTuple"],["impl Eq for IdleTimeout"],["impl Eq for PathId"],["impl Eq for PathStats"],["impl Eq for ShouldTransmit"],["impl Eq for StreamId"],["impl Eq for Error"],["impl Eq for Code"],["impl Eq for VarInt"],["impl Eq for VarIntBoundsExceeded"],["impl Eq for Written"],["impl Eq for TransportParameters"]]],["iroh_quinn_udp",[["impl Eq for EcnCodepoint"]]]]); + var implementors = Object.fromEntries([["bench",[["impl Eq for CipherSuite"]]],["iroh_quinn",[["impl Eq for ReadError"],["impl Eq for ReadExactError"],["impl Eq for ReadToEndError"],["impl Eq for ResetError"],["impl Eq for SendDatagramError"],["impl Eq for StoppedError"],["impl Eq for WriteError"]]],["iroh_quinn_proto",[["impl Eq for ClosePathError"],["impl Eq for ConfigError"],["impl Eq for ConnectError"],["impl Eq for ConnectionError"],["impl Eq for Dir"],["impl Eq for EcnCodepoint"],["impl Eq for FinishError"],["impl Eq for FrameType"],["impl Eq for LongType"],["impl Eq for MaybeFrame"],["impl Eq for PacketDecodeError"],["impl Eq for PathError"],["impl Eq for PathEvent"],["impl Eq for PathStatus"],["impl Eq for ReadError"],["impl Eq for ReadableError"],["impl Eq for SendDatagramError"],["impl Eq for SetPathStatusError"],["impl Eq for Side"],["impl Eq for StreamEvent"],["impl Eq for WriteError"],["impl Eq for Error"],["impl Eq for UnexpectedEnd"],["impl Eq for ExportKeyingMaterialError"],["impl Eq for ApplicationClose"],["impl Eq for Chunk"],["impl Eq for ClosedPath"],["impl Eq for ClosedStream"],["impl Eq for ConnectionClose"],["impl Eq for ConnectionHandle"],["impl Eq for ConnectionId"],["impl Eq for DatagramInfo"],["impl Eq for FourTuple"],["impl Eq for IdleTimeout"],["impl Eq for InvalidFrameId"],["impl Eq for PathId"],["impl Eq for PathStats"],["impl Eq for ShouldTransmit"],["impl Eq for StreamId"],["impl Eq for StreamInfo"],["impl Eq for Error"],["impl Eq for Code"],["impl Eq for VarInt"],["impl Eq for VarIntBoundsExceeded"],["impl Eq for Written"],["impl Eq for TransportParameters"]]],["iroh_quinn_udp",[["impl Eq for EcnCodepoint"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[251,1794,11336,282]} \ No newline at end of file +//{"start":57,"fragment_lengths":[251,1794,12408,282]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/cmp/trait.PartialEq.js b/pr/255/docs/trait.impl/core/cmp/trait.PartialEq.js index 324658711..67b64acaf 100644 --- a/pr/255/docs/trait.impl/core/cmp/trait.PartialEq.js +++ b/pr/255/docs/trait.impl/core/cmp/trait.PartialEq.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl PartialEq for CipherSuite"]]],["iroh_quinn",[["impl PartialEq for ReadError"],["impl PartialEq for ReadExactError"],["impl PartialEq for ReadToEndError"],["impl PartialEq for ResetError"],["impl PartialEq for SendDatagramError"],["impl PartialEq for StoppedError"],["impl PartialEq for WriteError"]]],["iroh_quinn_proto",[["impl PartialEq for ClosePathError"],["impl PartialEq for ConfigError"],["impl PartialEq for ConnectError"],["impl PartialEq for ConnectionError"],["impl PartialEq for Dir"],["impl PartialEq for EcnCodepoint"],["impl PartialEq for FinishError"],["impl PartialEq for FrameType"],["impl PartialEq for LongType"],["impl PartialEq for PacketDecodeError"],["impl PartialEq for PathError"],["impl PartialEq for PathEvent"],["impl PartialEq for PathStatus"],["impl PartialEq for ReadError"],["impl PartialEq for ReadableError"],["impl PartialEq for SendDatagramError"],["impl PartialEq for SetPathStatusError"],["impl PartialEq for Side"],["impl PartialEq for StreamEvent"],["impl PartialEq for WriteError"],["impl PartialEq for Error"],["impl PartialEq for UnexpectedEnd"],["impl PartialEq for ExportKeyingMaterialError"],["impl PartialEq for ApplicationClose"],["impl PartialEq for Chunk"],["impl PartialEq for ClosedPath"],["impl PartialEq for ClosedStream"],["impl PartialEq for ConnectionClose"],["impl PartialEq for ConnectionHandle"],["impl PartialEq for ConnectionId"],["impl PartialEq for FourTuple"],["impl PartialEq for IdleTimeout"],["impl PartialEq for PathId"],["impl PartialEq for PathStats"],["impl PartialEq for ShouldTransmit"],["impl PartialEq for StreamId"],["impl PartialEq for Error"],["impl PartialEq for Code"],["impl PartialEq for VarInt"],["impl PartialEq for VarIntBoundsExceeded"],["impl PartialEq for Written"],["impl PartialEq for TransportParameters"]]],["iroh_quinn_udp",[["impl PartialEq for EcnCodepoint"]]]]); + var implementors = Object.fromEntries([["bench",[["impl PartialEq for CipherSuite"]]],["iroh_quinn",[["impl PartialEq for ReadError"],["impl PartialEq for ReadExactError"],["impl PartialEq for ReadToEndError"],["impl PartialEq for ResetError"],["impl PartialEq for SendDatagramError"],["impl PartialEq for StoppedError"],["impl PartialEq for WriteError"]]],["iroh_quinn_proto",[["impl PartialEq for ClosePathError"],["impl PartialEq for ConfigError"],["impl PartialEq for ConnectError"],["impl PartialEq for ConnectionError"],["impl PartialEq for Dir"],["impl PartialEq for EcnCodepoint"],["impl PartialEq for FinishError"],["impl PartialEq for FrameType"],["impl PartialEq for LongType"],["impl PartialEq for MaybeFrame"],["impl PartialEq for PacketDecodeError"],["impl PartialEq for PathError"],["impl PartialEq for PathEvent"],["impl PartialEq for PathStatus"],["impl PartialEq for ReadError"],["impl PartialEq for ReadableError"],["impl PartialEq for SendDatagramError"],["impl PartialEq for SetPathStatusError"],["impl PartialEq for Side"],["impl PartialEq for StreamEvent"],["impl PartialEq for WriteError"],["impl PartialEq for Error"],["impl PartialEq for UnexpectedEnd"],["impl PartialEq for ExportKeyingMaterialError"],["impl PartialEq for ApplicationClose"],["impl PartialEq for Chunk"],["impl PartialEq for ClosedPath"],["impl PartialEq for ClosedStream"],["impl PartialEq for ConnectionClose"],["impl PartialEq for ConnectionHandle"],["impl PartialEq for ConnectionId"],["impl PartialEq for DatagramInfo"],["impl PartialEq for FourTuple"],["impl PartialEq for IdleTimeout"],["impl PartialEq for InvalidFrameId"],["impl PartialEq for PathId"],["impl PartialEq for PathStats"],["impl PartialEq for ShouldTransmit"],["impl PartialEq for StreamId"],["impl PartialEq for StreamInfo"],["impl PartialEq for Error"],["impl PartialEq for Code"],["impl PartialEq for VarInt"],["impl PartialEq for VarIntBoundsExceeded"],["impl PartialEq for Written"],["impl PartialEq for TransportParameters"]]],["iroh_quinn_udp",[["impl PartialEq for EcnCodepoint"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[272,1941,12218,303]} \ No newline at end of file +//{"start":57,"fragment_lengths":[272,1941,13374,303]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/error/trait.Error.js b/pr/255/docs/trait.impl/core/error/trait.Error.js index 212b4f6df..3ac1c7c07 100644 --- a/pr/255/docs/trait.impl/core/error/trait.Error.js +++ b/pr/255/docs/trait.impl/core/error/trait.Error.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["iroh_quinn",[["impl Error for ReadError"],["impl Error for ReadExactError"],["impl Error for ReadToEndError"],["impl Error for ResetError"],["impl Error for SendDatagramError"],["impl Error for StoppedError"],["impl Error for WriteError"],["impl Error for RetryError"]]],["iroh_quinn_proto",[["impl Error for ClosePathError"],["impl Error for ConfigError"],["impl Error for ConnectError"],["impl Error for ConnectionError"],["impl Error for FinishError"],["impl Error for PacketDecodeError"],["impl Error for PathError"],["impl Error for ReadError"],["impl Error for ReadableError"],["impl Error for SendDatagramError"],["impl Error for SetPathStatusError"],["impl Error for WriteError"],["impl Error for Error"],["impl Error for Error"],["impl Error for UnexpectedEnd"],["impl Error for NoInitialCipherSuite"],["impl Error for ClosedPath"],["impl Error for ClosedStream"],["impl Error for RetryError"],["impl Error for Error"],["impl Error for VarIntBoundsExceeded"]]]]); + var implementors = Object.fromEntries([["iroh_quinn",[["impl Error for ReadError"],["impl Error for ReadExactError"],["impl Error for ReadToEndError"],["impl Error for ResetError"],["impl Error for SendDatagramError"],["impl Error for StoppedError"],["impl Error for WriteError"],["impl Error for RetryError"]]],["iroh_quinn_proto",[["impl Error for ClosePathError"],["impl Error for ConfigError"],["impl Error for ConnectError"],["impl Error for ConnectionError"],["impl Error for FinishError"],["impl Error for PacketDecodeError"],["impl Error for PathError"],["impl Error for ReadError"],["impl Error for ReadableError"],["impl Error for SendDatagramError"],["impl Error for SetPathStatusError"],["impl Error for WriteError"],["impl Error for Error"],["impl Error for Error"],["impl Error for UnexpectedEnd"],["impl Error for NoInitialCipherSuite"],["impl Error for ClosedPath"],["impl Error for ClosedStream"],["impl Error for MultipathNotNegotiated"],["impl Error for RetryError"],["impl Error for Error"],["impl Error for VarIntBoundsExceeded"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[2150,6038]} \ No newline at end of file +//{"start":57,"fragment_lengths":[2150,6352]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/fmt/trait.Debug.js b/pr/255/docs/trait.impl/core/fmt/trait.Debug.js index 51de3dba4..551bbe323 100644 --- a/pr/255/docs/trait.impl/core/fmt/trait.Debug.js +++ b/pr/255/docs/trait.impl/core/fmt/trait.Debug.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Debug for CipherSuite"],["impl Debug for TransferResult"],["impl Debug for Opt"]]],["certificate",[["impl Debug for SkipServerVerification"]]],["iroh_quinn",[["impl Debug for ReadError"],["impl Debug for ReadExactError"],["impl Debug for ReadToEndError"],["impl Debug for ResetError"],["impl Debug for SendDatagramError"],["impl Debug for StoppedError"],["impl Debug for WriteError"],["impl Debug for Connecting"],["impl Debug for Connection"],["impl Debug for Endpoint"],["impl Debug for EndpointStats"],["impl Debug for Incoming"],["impl Debug for IncomingFuture"],["impl Debug for Path"],["impl Debug for RecvStream"],["impl Debug for RetryError"],["impl Debug for SendStream"],["impl Debug for SmolRuntime"],["impl Debug for TokioRuntime"],["impl Debug for UnorderedRecvStream"],["impl Debug for WeakConnectionHandle"]]],["iroh_quinn_proto",[["impl Debug for ClosePathError"],["impl Debug for ConfigError"],["impl Debug for ConnectError"],["impl Debug for ConnectionError"],["impl Debug for Dir"],["impl Debug for EcnCodepoint"],["impl Debug for Event"],["impl Debug for FinishError"],["impl Debug for FrameType"],["impl Debug for LongType"],["impl Debug for PacketDecodeError"],["impl Debug for PathError"],["impl Debug for PathEvent"],["impl Debug for PathStatus"],["impl Debug for ProtectedHeader"],["impl Debug for ReadError"],["impl Debug for ReadableError"],["impl Debug for SendDatagramError"],["impl Debug for SetPathStatusError"],["impl Debug for Side"],["impl Debug for StreamEvent"],["impl Debug for WriteError"],["impl Debug for Error"],["impl Debug for Event"],["impl Debug for Error"],["impl Debug for UnexpectedEnd"],["impl Debug for Bbr"],["impl Debug for BbrConfig"],["impl Debug for ControllerMetrics"],["impl Debug for Cubic"],["impl Debug for CubicConfig"],["impl Debug for NewReno"],["impl Debug for NewRenoConfig"],["impl Debug for NoInitialCipherSuite"],["impl Debug for CryptoError"],["impl Debug for ExportKeyingMaterialError"],["impl Debug for UnsupportedVersion"],["impl Debug for AcceptError"],["impl Debug for AckFrequencyConfig"],["impl Debug for ApplicationClose"],["impl Debug for Chunk"],["impl Debug for ClientConfig"],["impl Debug for ClosedPath"],["impl Debug for ClosedStream"],["impl Debug for Connection"],["impl Debug for ConnectionClose"],["impl Debug for ConnectionEvent"],["impl Debug for ConnectionHandle"],["impl Debug for ConnectionId"],["impl Debug for ConnectionStats"],["impl Debug for Datagram"],["impl Debug for Endpoint"],["impl Debug for EndpointConfig"],["impl Debug for EndpointEvent"],["impl Debug for FourTuple"],["impl Debug for FrameStats"],["impl Debug for IdleTimeout"],["impl Debug for Incoming"],["impl Debug for InvalidCid"],["impl Debug for MtuDiscoveryConfig"],["impl Debug for PartialDecode"],["impl Debug for PathId"],["impl Debug for PathStats"],["impl Debug for ProtectedInitialHeader"],["impl Debug for QlogFileFactory"],["impl Debug for RandomConnectionIdGenerator"],["impl Debug for RetryError"],["impl Debug for RttEstimator"],["impl Debug for ServerConfig"],["impl Debug for ShouldTransmit"],["impl Debug for StreamId"],["impl Debug for TokenMemoryCache"],["impl Debug for Transmit"],["impl Debug for TransportConfig"],["impl Debug for Error"],["impl Debug for Code"],["impl Debug for UdpStats"],["impl Debug for ValidationTokenConfig"],["impl Debug for VarInt"],["impl Debug for VarIntBoundsExceeded"],["impl Debug for Written"],["impl Debug for TransportParameters"]]],["iroh_quinn_udp",[["impl Debug for EcnCodepoint"],["impl Debug for RecvMeta"],["impl Debug for UdpSocketState"],["impl<'a> Debug for Transmit<'a>"]]]]); + var implementors = Object.fromEntries([["bench",[["impl Debug for CipherSuite"],["impl Debug for TransferResult"],["impl Debug for Opt"]]],["certificate",[["impl Debug for SkipServerVerification"]]],["iroh_quinn",[["impl Debug for ReadError"],["impl Debug for ReadExactError"],["impl Debug for ReadToEndError"],["impl Debug for ResetError"],["impl Debug for SendDatagramError"],["impl Debug for StoppedError"],["impl Debug for WriteError"],["impl Debug for Connecting"],["impl Debug for Connection"],["impl Debug for Endpoint"],["impl Debug for EndpointStats"],["impl Debug for Incoming"],["impl Debug for IncomingFuture"],["impl Debug for Path"],["impl Debug for RecvStream"],["impl Debug for RetryError"],["impl Debug for SendStream"],["impl Debug for SmolRuntime"],["impl Debug for TokioRuntime"],["impl Debug for UnorderedRecvStream"],["impl Debug for WeakConnectionHandle"]]],["iroh_quinn_proto",[["impl Debug for ClosePathError"],["impl Debug for ConfigError"],["impl Debug for ConnectError"],["impl Debug for ConnectionError"],["impl Debug for Dir"],["impl Debug for EcnCodepoint"],["impl Debug for Event"],["impl Debug for FinishError"],["impl Debug for FrameType"],["impl Debug for LongType"],["impl Debug for MaybeFrame"],["impl Debug for PacketDecodeError"],["impl Debug for PathError"],["impl Debug for PathEvent"],["impl Debug for PathStatus"],["impl Debug for ProtectedHeader"],["impl Debug for ReadError"],["impl Debug for ReadableError"],["impl Debug for SendDatagramError"],["impl Debug for SetPathStatusError"],["impl Debug for Side"],["impl Debug for StreamEvent"],["impl Debug for WriteError"],["impl Debug for Error"],["impl Debug for Event"],["impl Debug for Error"],["impl Debug for UnexpectedEnd"],["impl Debug for Bbr"],["impl Debug for BbrConfig"],["impl Debug for ControllerMetrics"],["impl Debug for Cubic"],["impl Debug for CubicConfig"],["impl Debug for NewReno"],["impl Debug for NewRenoConfig"],["impl Debug for NoInitialCipherSuite"],["impl Debug for CryptoError"],["impl Debug for ExportKeyingMaterialError"],["impl Debug for UnsupportedVersion"],["impl Debug for AcceptError"],["impl Debug for AckFrequencyConfig"],["impl Debug for ApplicationClose"],["impl Debug for Chunk"],["impl Debug for ClientConfig"],["impl Debug for ClosedPath"],["impl Debug for ClosedStream"],["impl Debug for Connection"],["impl Debug for ConnectionClose"],["impl Debug for ConnectionEvent"],["impl Debug for ConnectionHandle"],["impl Debug for ConnectionId"],["impl Debug for ConnectionStats"],["impl Debug for Datagram"],["impl Debug for DatagramInfo"],["impl Debug for Endpoint"],["impl Debug for EndpointConfig"],["impl Debug for EndpointEvent"],["impl Debug for FourTuple"],["impl Debug for FrameStats"],["impl Debug for IdleTimeout"],["impl Debug for Incoming"],["impl Debug for InvalidCid"],["impl Debug for InvalidFrameId"],["impl Debug for MtuDiscoveryConfig"],["impl Debug for MultipathNotNegotiated"],["impl Debug for PartialDecode"],["impl Debug for PathId"],["impl Debug for PathStats"],["impl Debug for ProtectedInitialHeader"],["impl Debug for QlogFileFactory"],["impl Debug for RandomConnectionIdGenerator"],["impl Debug for RetryError"],["impl Debug for RttEstimator"],["impl Debug for ServerConfig"],["impl Debug for ShouldTransmit"],["impl Debug for StreamId"],["impl Debug for StreamInfo"],["impl Debug for TokenMemoryCache"],["impl Debug for Transmit"],["impl Debug for TransportConfig"],["impl Debug for Error"],["impl Debug for Code"],["impl Debug for UdpStats"],["impl Debug for ValidationTokenConfig"],["impl Debug for VarInt"],["impl Debug for VarIntBoundsExceeded"],["impl Debug for Written"],["impl Debug for TransportParameters"]]],["iroh_quinn_udp",[["impl Debug for EcnCodepoint"],["impl Debug for RecvMeta"],["impl Debug for UdpSocketState"],["impl<'a> Debug for Transmit<'a>"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[768,318,5582,23184,1121]} \ No newline at end of file +//{"start":57,"fragment_lengths":[768,318,5582,24602,1121]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/fmt/trait.Display.js b/pr/255/docs/trait.impl/core/fmt/trait.Display.js index 2d939c9aa..93a331159 100644 --- a/pr/255/docs/trait.impl/core/fmt/trait.Display.js +++ b/pr/255/docs/trait.impl/core/fmt/trait.Display.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["iroh_quinn",[["impl Display for ReadError"],["impl Display for ReadExactError"],["impl Display for ReadToEndError"],["impl Display for ResetError"],["impl Display for SendDatagramError"],["impl Display for StoppedError"],["impl Display for WriteError"],["impl Display for RetryError"]]],["iroh_quinn_proto",[["impl Display for ClosePathError"],["impl Display for ConfigError"],["impl Display for ConnectError"],["impl Display for ConnectionError"],["impl Display for Dir"],["impl Display for FinishError"],["impl Display for FrameType"],["impl Display for PacketDecodeError"],["impl Display for PathError"],["impl Display for ReadError"],["impl Display for ReadableError"],["impl Display for SendDatagramError"],["impl Display for SetPathStatusError"],["impl Display for WriteError"],["impl Display for Error"],["impl Display for Error"],["impl Display for UnexpectedEnd"],["impl Display for NoInitialCipherSuite"],["impl Display for ApplicationClose"],["impl Display for ClosedPath"],["impl Display for ClosedStream"],["impl Display for ConnectionClose"],["impl Display for ConnectionId"],["impl Display for FourTuple"],["impl Display for PathId"],["impl Display for RetryError"],["impl Display for StreamId"],["impl Display for Error"],["impl Display for Code"],["impl Display for VarInt"],["impl Display for VarIntBoundsExceeded"]]]]); + var implementors = Object.fromEntries([["iroh_quinn",[["impl Display for ReadError"],["impl Display for ReadExactError"],["impl Display for ReadToEndError"],["impl Display for ResetError"],["impl Display for SendDatagramError"],["impl Display for StoppedError"],["impl Display for WriteError"],["impl Display for RetryError"]]],["iroh_quinn_proto",[["impl Display for ClosePathError"],["impl Display for ConfigError"],["impl Display for ConnectError"],["impl Display for ConnectionError"],["impl Display for Dir"],["impl Display for FinishError"],["impl Display for FrameType"],["impl Display for MaybeFrame"],["impl Display for PacketDecodeError"],["impl Display for PathError"],["impl Display for ReadError"],["impl Display for ReadableError"],["impl Display for SendDatagramError"],["impl Display for SetPathStatusError"],["impl Display for WriteError"],["impl Display for Error"],["impl Display for Error"],["impl Display for UnexpectedEnd"],["impl Display for NoInitialCipherSuite"],["impl Display for ApplicationClose"],["impl Display for ClosedPath"],["impl Display for ClosedStream"],["impl Display for ConnectionClose"],["impl Display for ConnectionId"],["impl Display for DatagramInfo"],["impl Display for FourTuple"],["impl Display for MultipathNotNegotiated"],["impl Display for PathId"],["impl Display for RetryError"],["impl Display for StreamId"],["impl Display for StreamInfo"],["impl Display for Error"],["impl Display for Code"],["impl Display for VarInt"],["impl Display for VarIntBoundsExceeded"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[2166,8860]} \ No newline at end of file +//{"start":57,"fragment_lengths":[2166,10016]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/future/future/trait.Future.js b/pr/255/docs/trait.impl/core/future/future/trait.Future.js index 3c2fb2ac9..8c8628b9c 100644 --- a/pr/255/docs/trait.impl/core/future/future/trait.Future.js +++ b/pr/255/docs/trait.impl/core/future/future/trait.Future.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["iroh_quinn",[["impl Future for Accept<'_>"],["impl Future for AcceptBi<'_>"],["impl Future for AcceptUni<'_>"],["impl Future for Connecting"],["impl Future for IncomingFuture"],["impl Future for OnClosed"],["impl Future for OpenBi<'_>"],["impl Future for OpenPath"],["impl Future for OpenUni<'_>"],["impl Future for ReadDatagram<'_>"],["impl Future for SendDatagram<'_>"],["impl Future for ZeroRttAccepted"]]]]); + var implementors = Object.fromEntries([["iroh_quinn",[["impl Future for Accept<'_>"],["impl Future for AcceptBi<'_>"],["impl Future for AcceptUni<'_>"],["impl Future for ClosePath"],["impl Future for Connecting"],["impl Future for IncomingFuture"],["impl Future for OnClosed"],["impl Future for OpenBi<'_>"],["impl Future for OpenPath"],["impl Future for OpenUni<'_>"],["impl Future for ReadDatagram<'_>"],["impl Future for SendDatagram<'_>"],["impl Future for ZeroRttAccepted"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[3503]} \ No newline at end of file +//{"start":57,"fragment_lengths":[3786]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.Copy.js b/pr/255/docs/trait.impl/core/marker/trait.Copy.js index 15b8d4fe0..3073465ce 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.Copy.js +++ b/pr/255/docs/trait.impl/core/marker/trait.Copy.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Copy for CipherSuite"],["impl Copy for Opt"]]],["iroh_quinn",[["impl Copy for EndpointStats"]]],["iroh_quinn_proto",[["impl Copy for Dir"],["impl Copy for EcnCodepoint"],["impl Copy for FrameType"],["impl Copy for LongType"],["impl Copy for PathError"],["impl Copy for PathStatus"],["impl Copy for Side"],["impl Copy for Error"],["impl Copy for UnexpectedEnd"],["impl Copy for ConnectionHandle"],["impl Copy for ConnectionId"],["impl Copy for FourTuple"],["impl Copy for FrameStats"],["impl Copy for IdleTimeout"],["impl Copy for InvalidCid"],["impl Copy for PathId"],["impl Copy for PathStats"],["impl Copy for RandomConnectionIdGenerator"],["impl Copy for RttEstimator"],["impl Copy for ShouldTransmit"],["impl Copy for StreamId"],["impl Copy for Code"],["impl Copy for UdpStats"],["impl Copy for VarInt"],["impl Copy for VarIntBoundsExceeded"],["impl Copy for Written"],["impl Copy for TransportParameters"]]],["iroh_quinn_udp",[["impl Copy for EcnCodepoint"],["impl Copy for RecvMeta"]]],["perf",[["impl Copy for CongestionAlgorithm"]]]]); + var implementors = Object.fromEntries([["bench",[["impl Copy for CipherSuite"],["impl Copy for Opt"]]],["iroh_quinn",[["impl Copy for EndpointStats"]]],["iroh_quinn_proto",[["impl Copy for Dir"],["impl Copy for EcnCodepoint"],["impl Copy for FrameType"],["impl Copy for LongType"],["impl Copy for MaybeFrame"],["impl Copy for PathError"],["impl Copy for PathStatus"],["impl Copy for Side"],["impl Copy for Error"],["impl Copy for UnexpectedEnd"],["impl Copy for ConnectionHandle"],["impl Copy for ConnectionId"],["impl Copy for DatagramInfo"],["impl Copy for FourTuple"],["impl Copy for FrameStats"],["impl Copy for IdleTimeout"],["impl Copy for InvalidCid"],["impl Copy for MultipathNotNegotiated"],["impl Copy for PathId"],["impl Copy for PathStats"],["impl Copy for RandomConnectionIdGenerator"],["impl Copy for RttEstimator"],["impl Copy for ShouldTransmit"],["impl Copy for StreamId"],["impl Copy for StreamInfo"],["impl Copy for Code"],["impl Copy for UdpStats"],["impl Copy for VarInt"],["impl Copy for VarIntBoundsExceeded"],["impl Copy for Written"],["impl Copy for TransportParameters"]]],["iroh_quinn_udp",[["impl Copy for EcnCodepoint"],["impl Copy for RecvMeta"]]],["perf",[["impl Copy for CongestionAlgorithm"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[497,291,7616,561,285]} \ No newline at end of file +//{"start":57,"fragment_lengths":[497,291,8760,561,285]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.Freeze.js b/pr/255/docs/trait.impl/core/marker/trait.Freeze.js index a17d6cc70..787fedeeb 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.Freeze.js +++ b/pr/255/docs/trait.impl/core/marker/trait.Freeze.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Freeze for CipherSuite",1,["bench::CipherSuite"]],["impl Freeze for Stats",1,["bench::stats::Stats"]],["impl Freeze for StreamStats",1,["bench::stats::StreamStats"]],["impl Freeze for TransferResult",1,["bench::stats::TransferResult"]],["impl Freeze for Opt",1,["bench::Opt"]]]],["bulk",[["impl Freeze for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Freeze for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !Freeze for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !Freeze for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !Freeze for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !Freeze for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !Freeze for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !Freeze for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !Freeze for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !Freeze for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !Freeze for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Freeze for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Freeze for Connection",1,["iroh_quinn::connection::Connection"]],["impl Freeze for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Freeze for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Freeze for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Freeze for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Freeze for Path",1,["iroh_quinn::path::Path"]],["impl Freeze for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Freeze for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Freeze for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Freeze for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Freeze for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Freeze for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Freeze for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Freeze for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> !Freeze for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !Freeze for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !Freeze for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !Freeze for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !Freeze for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !Freeze for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !Freeze for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !Freeze for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !Freeze for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !Freeze for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !Freeze for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl !Freeze for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !Freeze for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl !Freeze for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl !Freeze for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl !Freeze for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !Freeze for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl !Freeze for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl !Freeze for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !Freeze for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Freeze for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Freeze for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Freeze for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Freeze for Dir",1,["iroh_quinn_proto::Dir"]],["impl Freeze for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Freeze for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Freeze for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Freeze for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Freeze for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Freeze for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Freeze for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Freeze for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Freeze for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Freeze for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Freeze for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Freeze for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Freeze for Side",1,["iroh_quinn_proto::Side"]],["impl Freeze for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Freeze for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Freeze for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Freeze for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Freeze for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Freeze for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Freeze for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Freeze for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Freeze for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Freeze for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Freeze for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Freeze for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Freeze for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Freeze for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Freeze for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Freeze for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Freeze for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Freeze for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Freeze for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Freeze for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Freeze for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Freeze for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Freeze for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Freeze for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Freeze for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Freeze for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Freeze for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Freeze for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Freeze for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Freeze for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Freeze for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Freeze for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Freeze for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Freeze for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Freeze for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Freeze for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Freeze for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Freeze for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Freeze for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Freeze for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Freeze for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Freeze for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Freeze for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Freeze for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Freeze for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Freeze for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Freeze for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Freeze for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Freeze for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Freeze for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Freeze for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Freeze for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Freeze for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Freeze for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Freeze for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Freeze for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Freeze for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Freeze for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Freeze for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Freeze for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Freeze for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Freeze for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Freeze for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Freeze for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Freeze for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Freeze for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Freeze for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Freeze for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Freeze for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Freeze for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Freeze for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Freeze for KeyPair<T>
where\n T: Freeze,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl !Freeze for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl Freeze for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Freeze for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl<'a> Freeze for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Freeze for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !Freeze for StreamStats",1,["perf::stats::StreamStats"]],["impl Freeze for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Freeze for Opt",1,["perf::client::Opt"]],["impl Freeze for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Freeze for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Freeze for Opt",1,["perf::server::Opt"]],["impl Freeze for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Freeze for Stats",1,["perf::stats::Stats"]],["impl Freeze for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Freeze for Commands",1,["quinn_perf::Commands"]],["impl Freeze for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl Freeze for CipherSuite",1,["bench::CipherSuite"]],["impl Freeze for Stats",1,["bench::stats::Stats"]],["impl Freeze for StreamStats",1,["bench::stats::StreamStats"]],["impl Freeze for TransferResult",1,["bench::stats::TransferResult"]],["impl Freeze for Opt",1,["bench::Opt"]]]],["bulk",[["impl Freeze for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Freeze for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !Freeze for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !Freeze for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !Freeze for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !Freeze for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !Freeze for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !Freeze for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !Freeze for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !Freeze for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !Freeze for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Freeze for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl Freeze for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl Freeze for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Freeze for Connection",1,["iroh_quinn::connection::Connection"]],["impl Freeze for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Freeze for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Freeze for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Freeze for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Freeze for Path",1,["iroh_quinn::path::Path"]],["impl Freeze for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Freeze for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Freeze for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Freeze for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Freeze for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Freeze for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Freeze for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Freeze for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> !Freeze for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !Freeze for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !Freeze for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !Freeze for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !Freeze for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !Freeze for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !Freeze for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !Freeze for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !Freeze for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !Freeze for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !Freeze for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl !Freeze for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !Freeze for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl !Freeze for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl !Freeze for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl !Freeze for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !Freeze for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl !Freeze for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl !Freeze for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !Freeze for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Freeze for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Freeze for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Freeze for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Freeze for Dir",1,["iroh_quinn_proto::Dir"]],["impl Freeze for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Freeze for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Freeze for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Freeze for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Freeze for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl Freeze for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Freeze for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Freeze for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Freeze for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Freeze for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Freeze for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Freeze for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Freeze for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Freeze for Side",1,["iroh_quinn_proto::Side"]],["impl Freeze for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Freeze for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Freeze for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Freeze for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Freeze for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Freeze for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Freeze for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Freeze for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Freeze for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Freeze for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Freeze for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Freeze for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Freeze for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Freeze for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Freeze for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Freeze for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Freeze for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Freeze for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Freeze for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Freeze for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Freeze for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Freeze for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Freeze for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Freeze for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Freeze for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Freeze for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Freeze for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Freeze for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Freeze for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Freeze for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Freeze for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl Freeze for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Freeze for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Freeze for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Freeze for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Freeze for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Freeze for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Freeze for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Freeze for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Freeze for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Freeze for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl Freeze for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Freeze for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl Freeze for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Freeze for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Freeze for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Freeze for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Freeze for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Freeze for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Freeze for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Freeze for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Freeze for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Freeze for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Freeze for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Freeze for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Freeze for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Freeze for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Freeze for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Freeze for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl Freeze for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Freeze for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Freeze for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Freeze for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Freeze for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Freeze for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Freeze for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Freeze for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Freeze for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Freeze for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Freeze for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Freeze for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Freeze for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Freeze for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Freeze for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Freeze for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Freeze for KeyPair<T>
where\n T: Freeze,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl !Freeze for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl Freeze for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Freeze for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl<'a> Freeze for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Freeze for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !Freeze for StreamStats",1,["perf::stats::StreamStats"]],["impl Freeze for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Freeze for Opt",1,["perf::client::Opt"]],["impl Freeze for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Freeze for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Freeze for Opt",1,["perf::server::Opt"]],["impl Freeze for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Freeze for Stats",1,["perf::stats::Stats"]],["impl Freeze for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Freeze for Commands",1,["quinn_perf::Commands"]],["impl Freeze for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1466,297,369,9899,35374,1629,2824,575]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1466,297,369,10531,37070,1629,2824,575]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.Send.js b/pr/255/docs/trait.impl/core/marker/trait.Send.js index 6ed39071c..e5e68cd3d 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.Send.js +++ b/pr/255/docs/trait.impl/core/marker/trait.Send.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Send for CipherSuite",1,["bench::CipherSuite"]],["impl Send for Stats",1,["bench::stats::Stats"]],["impl Send for StreamStats",1,["bench::stats::StreamStats"]],["impl Send for TransferResult",1,["bench::stats::TransferResult"]],["impl Send for Opt",1,["bench::Opt"]]]],["bulk",[["impl Send for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Send for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Send for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Send for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Send for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Send for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Send for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Send for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Send for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Send for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Send for Connection",1,["iroh_quinn::connection::Connection"]],["impl Send for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Send for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Send for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Send for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Send for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Send for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Send for Path",1,["iroh_quinn::path::Path"]],["impl Send for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Send for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Send for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Send for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Send for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Send for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Send for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Send for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> Send for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> Send for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> Send for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> Send for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> Send for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> Send for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> Send for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl Send for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Send for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Send for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Send for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Send for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Send for Dir",1,["iroh_quinn_proto::Dir"]],["impl Send for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Send for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Send for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Send for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Send for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Send for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Send for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Send for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Send for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Send for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Send for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Send for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Send for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Send for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Send for Side",1,["iroh_quinn_proto::Side"]],["impl Send for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Send for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Send for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Send for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Send for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Send for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Send for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Send for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Send for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Send for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Send for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Send for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Send for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Send for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Send for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Send for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Send for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Send for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Send for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Send for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Send for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Send for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Send for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Send for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Send for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Send for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Send for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Send for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Send for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Send for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Send for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Send for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Send for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Send for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Send for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Send for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Send for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Send for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Send for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Send for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Send for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Send for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Send for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Send for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Send for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Send for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Send for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Send for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Send for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Send for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Send for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Send for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Send for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Send for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Send for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Send for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Send for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Send for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Send for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Send for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Send for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Send for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Send for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Send for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Send for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Send for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Send for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Send for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Send for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Send for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Send for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Send for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Send for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Send for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Send for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Send for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Send for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Send for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Send for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Send for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Send for KeyPair<T>
where\n T: Send,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Send for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Send for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Send for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Send for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Send for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Send for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Send for Opt",1,["perf::client::Opt"]],["impl Send for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Send for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Send for Opt",1,["perf::server::Opt"]],["impl Send for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Send for Stats",1,["perf::stats::Stats"]],["impl Send for StreamStats",1,["perf::stats::StreamStats"]],["impl Send for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Send for Commands",1,["quinn_perf::Commands"]],["impl Send for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl Send for CipherSuite",1,["bench::CipherSuite"]],["impl Send for Stats",1,["bench::stats::Stats"]],["impl Send for StreamStats",1,["bench::stats::StreamStats"]],["impl Send for TransferResult",1,["bench::stats::TransferResult"]],["impl Send for Opt",1,["bench::Opt"]]]],["bulk",[["impl Send for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Send for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Send for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Send for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Send for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Send for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Send for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Send for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Send for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Send for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl Send for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl Send for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Send for Connection",1,["iroh_quinn::connection::Connection"]],["impl Send for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Send for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Send for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Send for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Send for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Send for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Send for Path",1,["iroh_quinn::path::Path"]],["impl Send for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Send for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Send for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Send for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Send for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Send for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Send for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Send for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> Send for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> Send for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> Send for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> Send for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> Send for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> Send for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> Send for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl Send for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Send for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Send for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Send for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Send for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Send for Dir",1,["iroh_quinn_proto::Dir"]],["impl Send for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Send for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Send for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Send for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Send for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Send for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl Send for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Send for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Send for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Send for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Send for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Send for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Send for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Send for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Send for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Send for Side",1,["iroh_quinn_proto::Side"]],["impl Send for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Send for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Send for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Send for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Send for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Send for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Send for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Send for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Send for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Send for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Send for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Send for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Send for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Send for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Send for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Send for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Send for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Send for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Send for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Send for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Send for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Send for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Send for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Send for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Send for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Send for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Send for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Send for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Send for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Send for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Send for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Send for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Send for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Send for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Send for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Send for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Send for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Send for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl Send for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Send for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Send for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Send for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Send for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Send for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Send for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Send for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Send for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Send for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Send for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl Send for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Send for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl Send for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Send for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Send for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Send for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Send for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Send for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Send for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Send for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Send for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Send for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Send for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Send for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Send for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Send for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Send for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Send for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl Send for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Send for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Send for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Send for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Send for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Send for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Send for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Send for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Send for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Send for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Send for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Send for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Send for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Send for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Send for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Send for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Send for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Send for KeyPair<T>
where\n T: Send,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Send for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Send for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Send for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Send for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Send for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Send for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Send for Opt",1,["perf::client::Opt"]],["impl Send for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Send for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Send for Opt",1,["perf::server::Opt"]],["impl Send for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Send for Stats",1,["perf::stats::Stats"]],["impl Send for StreamStats",1,["perf::stats::StreamStats"]],["impl Send for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Send for Commands",1,["quinn_perf::Commands"]],["impl Send for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1436,291,363,9697,34743,1598,2769,563]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1436,291,363,10317,36409,1598,2769,563]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.StructuralPartialEq.js b/pr/255/docs/trait.impl/core/marker/trait.StructuralPartialEq.js index b17420186..79acabebf 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.StructuralPartialEq.js +++ b/pr/255/docs/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl StructuralPartialEq for CipherSuite"]]],["iroh_quinn",[["impl StructuralPartialEq for ReadError"],["impl StructuralPartialEq for ReadExactError"],["impl StructuralPartialEq for ReadToEndError"],["impl StructuralPartialEq for ResetError"],["impl StructuralPartialEq for SendDatagramError"],["impl StructuralPartialEq for StoppedError"],["impl StructuralPartialEq for WriteError"]]],["iroh_quinn_proto",[["impl StructuralPartialEq for ClosePathError"],["impl StructuralPartialEq for ConfigError"],["impl StructuralPartialEq for ConnectError"],["impl StructuralPartialEq for ConnectionError"],["impl StructuralPartialEq for Dir"],["impl StructuralPartialEq for EcnCodepoint"],["impl StructuralPartialEq for FinishError"],["impl StructuralPartialEq for FrameType"],["impl StructuralPartialEq for LongType"],["impl StructuralPartialEq for PacketDecodeError"],["impl StructuralPartialEq for PathError"],["impl StructuralPartialEq for PathEvent"],["impl StructuralPartialEq for PathStatus"],["impl StructuralPartialEq for ReadError"],["impl StructuralPartialEq for ReadableError"],["impl StructuralPartialEq for SendDatagramError"],["impl StructuralPartialEq for SetPathStatusError"],["impl StructuralPartialEq for Side"],["impl StructuralPartialEq for StreamEvent"],["impl StructuralPartialEq for WriteError"],["impl StructuralPartialEq for Error"],["impl StructuralPartialEq for UnexpectedEnd"],["impl StructuralPartialEq for ExportKeyingMaterialError"],["impl StructuralPartialEq for ApplicationClose"],["impl StructuralPartialEq for Chunk"],["impl StructuralPartialEq for ClosedPath"],["impl StructuralPartialEq for ClosedStream"],["impl StructuralPartialEq for ConnectionClose"],["impl StructuralPartialEq for ConnectionHandle"],["impl StructuralPartialEq for ConnectionId"],["impl StructuralPartialEq for FourTuple"],["impl StructuralPartialEq for IdleTimeout"],["impl StructuralPartialEq for PathId"],["impl StructuralPartialEq for PathStats"],["impl StructuralPartialEq for ShouldTransmit"],["impl StructuralPartialEq for StreamId"],["impl StructuralPartialEq for Code"],["impl StructuralPartialEq for VarInt"],["impl StructuralPartialEq for VarIntBoundsExceeded"],["impl StructuralPartialEq for Written"],["impl StructuralPartialEq for TransportParameters"]]],["iroh_quinn_udp",[["impl StructuralPartialEq for EcnCodepoint"]]]]); + var implementors = Object.fromEntries([["bench",[["impl StructuralPartialEq for CipherSuite"]]],["iroh_quinn",[["impl StructuralPartialEq for ReadError"],["impl StructuralPartialEq for ReadExactError"],["impl StructuralPartialEq for ReadToEndError"],["impl StructuralPartialEq for ResetError"],["impl StructuralPartialEq for SendDatagramError"],["impl StructuralPartialEq for StoppedError"],["impl StructuralPartialEq for WriteError"]]],["iroh_quinn_proto",[["impl StructuralPartialEq for ClosePathError"],["impl StructuralPartialEq for ConfigError"],["impl StructuralPartialEq for ConnectError"],["impl StructuralPartialEq for ConnectionError"],["impl StructuralPartialEq for Dir"],["impl StructuralPartialEq for EcnCodepoint"],["impl StructuralPartialEq for FinishError"],["impl StructuralPartialEq for FrameType"],["impl StructuralPartialEq for LongType"],["impl StructuralPartialEq for MaybeFrame"],["impl StructuralPartialEq for PacketDecodeError"],["impl StructuralPartialEq for PathError"],["impl StructuralPartialEq for PathEvent"],["impl StructuralPartialEq for PathStatus"],["impl StructuralPartialEq for ReadError"],["impl StructuralPartialEq for ReadableError"],["impl StructuralPartialEq for SendDatagramError"],["impl StructuralPartialEq for SetPathStatusError"],["impl StructuralPartialEq for Side"],["impl StructuralPartialEq for StreamEvent"],["impl StructuralPartialEq for WriteError"],["impl StructuralPartialEq for Error"],["impl StructuralPartialEq for UnexpectedEnd"],["impl StructuralPartialEq for ExportKeyingMaterialError"],["impl StructuralPartialEq for ApplicationClose"],["impl StructuralPartialEq for Chunk"],["impl StructuralPartialEq for ClosedPath"],["impl StructuralPartialEq for ClosedStream"],["impl StructuralPartialEq for ConnectionClose"],["impl StructuralPartialEq for ConnectionHandle"],["impl StructuralPartialEq for ConnectionId"],["impl StructuralPartialEq for DatagramInfo"],["impl StructuralPartialEq for FourTuple"],["impl StructuralPartialEq for IdleTimeout"],["impl StructuralPartialEq for InvalidFrameId"],["impl StructuralPartialEq for PathId"],["impl StructuralPartialEq for PathStats"],["impl StructuralPartialEq for ShouldTransmit"],["impl StructuralPartialEq for StreamId"],["impl StructuralPartialEq for StreamInfo"],["impl StructuralPartialEq for Code"],["impl StructuralPartialEq for VarInt"],["impl StructuralPartialEq for VarIntBoundsExceeded"],["impl StructuralPartialEq for Written"],["impl StructuralPartialEq for TransportParameters"]]],["iroh_quinn_udp",[["impl StructuralPartialEq for EcnCodepoint"]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[308,2193,13405,339]} \ No newline at end of file +//{"start":57,"fragment_lengths":[308,2193,14705,339]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.Sync.js b/pr/255/docs/trait.impl/core/marker/trait.Sync.js index d56b83334..774bebcb5 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.Sync.js +++ b/pr/255/docs/trait.impl/core/marker/trait.Sync.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Sync for CipherSuite",1,["bench::CipherSuite"]],["impl Sync for Stats",1,["bench::stats::Stats"]],["impl Sync for StreamStats",1,["bench::stats::StreamStats"]],["impl Sync for TransferResult",1,["bench::stats::TransferResult"]],["impl Sync for Opt",1,["bench::Opt"]]]],["bulk",[["impl Sync for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Sync for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Sync for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Sync for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Sync for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Sync for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Sync for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Sync for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Sync for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Sync for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Sync for Connection",1,["iroh_quinn::connection::Connection"]],["impl Sync for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Sync for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Sync for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Sync for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Sync for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Sync for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Sync for Path",1,["iroh_quinn::path::Path"]],["impl Sync for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Sync for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Sync for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Sync for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Sync for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Sync for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Sync for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Sync for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> Sync for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> Sync for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> Sync for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> Sync for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> Sync for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> Sync for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> Sync for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl Sync for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Sync for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Sync for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Sync for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Sync for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Sync for Dir",1,["iroh_quinn_proto::Dir"]],["impl Sync for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Sync for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Sync for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Sync for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Sync for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Sync for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Sync for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Sync for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Sync for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Sync for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Sync for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Sync for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Sync for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Sync for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Sync for Side",1,["iroh_quinn_proto::Side"]],["impl Sync for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Sync for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Sync for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Sync for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Sync for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Sync for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Sync for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Sync for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Sync for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Sync for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Sync for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Sync for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Sync for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Sync for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Sync for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Sync for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Sync for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Sync for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Sync for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Sync for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Sync for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Sync for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Sync for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Sync for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Sync for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Sync for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Sync for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Sync for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Sync for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Sync for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Sync for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Sync for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Sync for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Sync for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Sync for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Sync for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Sync for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Sync for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Sync for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Sync for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Sync for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Sync for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Sync for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Sync for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Sync for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Sync for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Sync for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Sync for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Sync for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Sync for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Sync for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Sync for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Sync for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Sync for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Sync for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Sync for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Sync for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Sync for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Sync for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Sync for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Sync for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Sync for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Sync for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Sync for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Sync for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Sync for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Sync for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Sync for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Sync for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Sync for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Sync for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Sync for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Sync for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Sync for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Sync for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Sync for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Sync for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Sync for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Sync for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Sync for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Sync for KeyPair<T>
where\n T: Sync,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Sync for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Sync for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Sync for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Sync for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Sync for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Sync for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Sync for Opt",1,["perf::client::Opt"]],["impl Sync for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Sync for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Sync for Opt",1,["perf::server::Opt"]],["impl Sync for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Sync for Stats",1,["perf::stats::Stats"]],["impl Sync for StreamStats",1,["perf::stats::StreamStats"]],["impl Sync for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Sync for Commands",1,["quinn_perf::Commands"]],["impl Sync for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl Sync for CipherSuite",1,["bench::CipherSuite"]],["impl Sync for Stats",1,["bench::stats::Stats"]],["impl Sync for StreamStats",1,["bench::stats::StreamStats"]],["impl Sync for TransferResult",1,["bench::stats::TransferResult"]],["impl Sync for Opt",1,["bench::Opt"]]]],["bulk",[["impl Sync for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Sync for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Sync for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Sync for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Sync for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Sync for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Sync for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Sync for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Sync for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Sync for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl Sync for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl Sync for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Sync for Connection",1,["iroh_quinn::connection::Connection"]],["impl Sync for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Sync for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Sync for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Sync for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Sync for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Sync for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Sync for Path",1,["iroh_quinn::path::Path"]],["impl Sync for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Sync for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Sync for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Sync for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Sync for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Sync for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Sync for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Sync for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> Sync for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> Sync for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> Sync for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> Sync for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> Sync for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> Sync for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> Sync for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl Sync for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Sync for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Sync for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Sync for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Sync for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Sync for Dir",1,["iroh_quinn_proto::Dir"]],["impl Sync for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Sync for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Sync for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Sync for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Sync for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Sync for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl Sync for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Sync for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Sync for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Sync for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Sync for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Sync for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Sync for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Sync for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Sync for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Sync for Side",1,["iroh_quinn_proto::Side"]],["impl Sync for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Sync for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Sync for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Sync for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Sync for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Sync for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Sync for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Sync for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Sync for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Sync for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Sync for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Sync for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Sync for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Sync for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Sync for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Sync for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Sync for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Sync for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Sync for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Sync for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Sync for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Sync for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Sync for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Sync for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Sync for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Sync for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Sync for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Sync for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Sync for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Sync for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Sync for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Sync for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Sync for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Sync for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Sync for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Sync for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Sync for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Sync for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl Sync for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Sync for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Sync for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Sync for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Sync for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Sync for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Sync for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Sync for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Sync for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Sync for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Sync for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl Sync for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Sync for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl Sync for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Sync for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Sync for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Sync for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Sync for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Sync for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Sync for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Sync for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Sync for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Sync for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Sync for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Sync for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Sync for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Sync for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Sync for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Sync for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl Sync for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Sync for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Sync for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Sync for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Sync for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Sync for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Sync for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Sync for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Sync for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Sync for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Sync for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Sync for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Sync for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Sync for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Sync for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Sync for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Sync for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Sync for KeyPair<T>
where\n T: Sync,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Sync for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Sync for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Sync for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Sync for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Sync for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Sync for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Sync for Opt",1,["perf::client::Opt"]],["impl Sync for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Sync for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Sync for Opt",1,["perf::server::Opt"]],["impl Sync for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Sync for Stats",1,["perf::stats::Stats"]],["impl Sync for StreamStats",1,["perf::stats::StreamStats"]],["impl Sync for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Sync for Commands",1,["quinn_perf::Commands"]],["impl Sync for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1436,291,363,9697,34743,1598,2769,563]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1436,291,363,10317,36409,1598,2769,563]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.Unpin.js b/pr/255/docs/trait.impl/core/marker/trait.Unpin.js index 0a4f95744..4133aabed 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.Unpin.js +++ b/pr/255/docs/trait.impl/core/marker/trait.Unpin.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl Unpin for CipherSuite",1,["bench::CipherSuite"]],["impl Unpin for Stats",1,["bench::stats::Stats"]],["impl Unpin for StreamStats",1,["bench::stats::StreamStats"]],["impl Unpin for TransferResult",1,["bench::stats::TransferResult"]],["impl Unpin for Opt",1,["bench::Opt"]]]],["bulk",[["impl Unpin for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Unpin for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Unpin for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Unpin for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Unpin for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Unpin for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Unpin for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Unpin for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Unpin for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Unpin for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Unpin for Connection",1,["iroh_quinn::connection::Connection"]],["impl Unpin for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Unpin for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Unpin for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Unpin for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Unpin for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Unpin for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Unpin for Path",1,["iroh_quinn::path::Path"]],["impl Unpin for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Unpin for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Unpin for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Unpin for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Unpin for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Unpin for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Unpin for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Unpin for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'__pin, 'a> Unpin for Accept<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for AcceptBi<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for AcceptUni<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for OpenBi<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for OpenUni<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for ReadDatagram<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for SendDatagram<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"]]],["iroh_quinn_proto",[["impl Unpin for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Unpin for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Unpin for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Unpin for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Unpin for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Unpin for Dir",1,["iroh_quinn_proto::Dir"]],["impl Unpin for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Unpin for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Unpin for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Unpin for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Unpin for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Unpin for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Unpin for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Unpin for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Unpin for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Unpin for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Unpin for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Unpin for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Unpin for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Unpin for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Unpin for Side",1,["iroh_quinn_proto::Side"]],["impl Unpin for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Unpin for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Unpin for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Unpin for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Unpin for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Unpin for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Unpin for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Unpin for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Unpin for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Unpin for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Unpin for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Unpin for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Unpin for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Unpin for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Unpin for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Unpin for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Unpin for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Unpin for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Unpin for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Unpin for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Unpin for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Unpin for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Unpin for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Unpin for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Unpin for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Unpin for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Unpin for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Unpin for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Unpin for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Unpin for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Unpin for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Unpin for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Unpin for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Unpin for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Unpin for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Unpin for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Unpin for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Unpin for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Unpin for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Unpin for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Unpin for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Unpin for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Unpin for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Unpin for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Unpin for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Unpin for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Unpin for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Unpin for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Unpin for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Unpin for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Unpin for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Unpin for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Unpin for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Unpin for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Unpin for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Unpin for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Unpin for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Unpin for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Unpin for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Unpin for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Unpin for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Unpin for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Unpin for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Unpin for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Unpin for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Unpin for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Unpin for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Unpin for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Unpin for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Unpin for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Unpin for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Unpin for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Unpin for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Unpin for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Unpin for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Unpin for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Unpin for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Unpin for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Unpin for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Unpin for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Unpin for KeyPair<T>
where\n T: Unpin,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Unpin for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Unpin for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Unpin for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Unpin for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Unpin for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Unpin for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Unpin for Opt",1,["perf::client::Opt"]],["impl Unpin for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Unpin for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Unpin for Opt",1,["perf::server::Opt"]],["impl Unpin for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Unpin for Stats",1,["perf::stats::Stats"]],["impl Unpin for StreamStats",1,["perf::stats::StreamStats"]],["impl Unpin for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Unpin for Commands",1,["quinn_perf::Commands"]],["impl Unpin for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl Unpin for CipherSuite",1,["bench::CipherSuite"]],["impl Unpin for Stats",1,["bench::stats::Stats"]],["impl Unpin for StreamStats",1,["bench::stats::StreamStats"]],["impl Unpin for TransferResult",1,["bench::stats::TransferResult"]],["impl Unpin for Opt",1,["bench::Opt"]]]],["bulk",[["impl Unpin for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl Unpin for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl Unpin for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl Unpin for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl Unpin for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl Unpin for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl Unpin for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl Unpin for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl Unpin for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl Unpin for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl Unpin for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl Unpin for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl Unpin for Connection",1,["iroh_quinn::connection::Connection"]],["impl Unpin for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl Unpin for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl Unpin for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl Unpin for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl Unpin for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl Unpin for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl Unpin for Path",1,["iroh_quinn::path::Path"]],["impl Unpin for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl Unpin for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl Unpin for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl Unpin for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl Unpin for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl Unpin for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl Unpin for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl Unpin for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'__pin, 'a> Unpin for Accept<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for AcceptBi<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for AcceptUni<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for OpenBi<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for OpenUni<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for ReadDatagram<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"],["impl<'__pin, 'a> Unpin for SendDatagram<'a>
where\n PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,
"]]],["iroh_quinn_proto",[["impl Unpin for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl Unpin for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl Unpin for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl Unpin for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl Unpin for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl Unpin for Dir",1,["iroh_quinn_proto::Dir"]],["impl Unpin for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl Unpin for Event",1,["iroh_quinn_proto::connection::Event"]],["impl Unpin for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl Unpin for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl Unpin for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl Unpin for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl Unpin for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl Unpin for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl Unpin for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl Unpin for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl Unpin for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl Unpin for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl Unpin for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl Unpin for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl Unpin for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl Unpin for Side",1,["iroh_quinn_proto::Side"]],["impl Unpin for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl Unpin for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl Unpin for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl Unpin for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl Unpin for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl Unpin for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl Unpin for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl Unpin for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl Unpin for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl Unpin for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl Unpin for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl Unpin for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl Unpin for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl Unpin for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl Unpin for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl Unpin for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl Unpin for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl Unpin for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl Unpin for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl Unpin for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl Unpin for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl Unpin for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl Unpin for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl Unpin for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl Unpin for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl Unpin for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl Unpin for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl Unpin for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl Unpin for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl Unpin for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl Unpin for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl Unpin for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl Unpin for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl Unpin for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl Unpin for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl Unpin for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl Unpin for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl Unpin for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl Unpin for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl Unpin for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl Unpin for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl Unpin for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl Unpin for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl Unpin for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl Unpin for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl Unpin for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl Unpin for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl Unpin for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl Unpin for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl Unpin for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl Unpin for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl Unpin for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl Unpin for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl Unpin for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl Unpin for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl Unpin for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl Unpin for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl Unpin for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl Unpin for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl Unpin for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl Unpin for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl Unpin for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl Unpin for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl Unpin for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl Unpin for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl Unpin for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl Unpin for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl Unpin for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl Unpin for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl Unpin for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl Unpin for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl Unpin for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl Unpin for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl Unpin for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl Unpin for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl Unpin for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl Unpin for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl Unpin for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl Unpin for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> Unpin for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> Unpin for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> Unpin for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> Unpin for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> Unpin for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> Unpin for KeyPair<T>
where\n T: Unpin,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl Unpin for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl Unpin for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl Unpin for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> Unpin for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> Unpin for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl Unpin for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl Unpin for Opt",1,["perf::client::Opt"]],["impl Unpin for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl Unpin for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl Unpin for Opt",1,["perf::server::Opt"]],["impl Unpin for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl Unpin for Stats",1,["perf::stats::Stats"]],["impl Unpin for StreamStats",1,["perf::stats::StreamStats"]],["impl Unpin for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl Unpin for Commands",1,["quinn_perf::Commands"]],["impl Unpin for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1451,294,366,11146,35052,1613,2796,569]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1451,294,366,11772,36733,1613,2796,569]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/marker/trait.UnsafeUnpin.js b/pr/255/docs/trait.impl/core/marker/trait.UnsafeUnpin.js index d0e3af770..070ffdd04 100644 --- a/pr/255/docs/trait.impl/core/marker/trait.UnsafeUnpin.js +++ b/pr/255/docs/trait.impl/core/marker/trait.UnsafeUnpin.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl UnsafeUnpin for CipherSuite",1,["bench::CipherSuite"]],["impl UnsafeUnpin for Stats",1,["bench::stats::Stats"]],["impl UnsafeUnpin for StreamStats",1,["bench::stats::StreamStats"]],["impl UnsafeUnpin for TransferResult",1,["bench::stats::TransferResult"]],["impl UnsafeUnpin for Opt",1,["bench::Opt"]]]],["bulk",[["impl UnsafeUnpin for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl UnsafeUnpin for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl UnsafeUnpin for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl UnsafeUnpin for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl UnsafeUnpin for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl UnsafeUnpin for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl UnsafeUnpin for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl UnsafeUnpin for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl UnsafeUnpin for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl UnsafeUnpin for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl UnsafeUnpin for Connection",1,["iroh_quinn::connection::Connection"]],["impl UnsafeUnpin for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl UnsafeUnpin for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl UnsafeUnpin for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl UnsafeUnpin for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl UnsafeUnpin for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl UnsafeUnpin for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl UnsafeUnpin for Path",1,["iroh_quinn::path::Path"]],["impl UnsafeUnpin for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl UnsafeUnpin for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl UnsafeUnpin for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl UnsafeUnpin for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl UnsafeUnpin for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl UnsafeUnpin for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl UnsafeUnpin for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl UnsafeUnpin for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> !UnsafeUnpin for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !UnsafeUnpin for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !UnsafeUnpin for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !UnsafeUnpin for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !UnsafeUnpin for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !UnsafeUnpin for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !UnsafeUnpin for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl UnsafeUnpin for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl UnsafeUnpin for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl UnsafeUnpin for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl UnsafeUnpin for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl UnsafeUnpin for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl UnsafeUnpin for Dir",1,["iroh_quinn_proto::Dir"]],["impl UnsafeUnpin for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl UnsafeUnpin for Event",1,["iroh_quinn_proto::connection::Event"]],["impl UnsafeUnpin for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl UnsafeUnpin for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl UnsafeUnpin for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl UnsafeUnpin for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl UnsafeUnpin for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl UnsafeUnpin for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl UnsafeUnpin for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl UnsafeUnpin for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl UnsafeUnpin for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl UnsafeUnpin for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl UnsafeUnpin for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl UnsafeUnpin for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl UnsafeUnpin for Side",1,["iroh_quinn_proto::Side"]],["impl UnsafeUnpin for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl UnsafeUnpin for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl UnsafeUnpin for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl UnsafeUnpin for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl UnsafeUnpin for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl UnsafeUnpin for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl UnsafeUnpin for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl UnsafeUnpin for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl UnsafeUnpin for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl UnsafeUnpin for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl UnsafeUnpin for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl UnsafeUnpin for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl UnsafeUnpin for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl UnsafeUnpin for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl UnsafeUnpin for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl UnsafeUnpin for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl UnsafeUnpin for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl UnsafeUnpin for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl UnsafeUnpin for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl UnsafeUnpin for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl UnsafeUnpin for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl UnsafeUnpin for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl UnsafeUnpin for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl UnsafeUnpin for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl UnsafeUnpin for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl UnsafeUnpin for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl UnsafeUnpin for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl UnsafeUnpin for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl UnsafeUnpin for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl UnsafeUnpin for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl UnsafeUnpin for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl UnsafeUnpin for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl UnsafeUnpin for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl UnsafeUnpin for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl UnsafeUnpin for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl UnsafeUnpin for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl UnsafeUnpin for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl UnsafeUnpin for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl UnsafeUnpin for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl UnsafeUnpin for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl UnsafeUnpin for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl UnsafeUnpin for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl UnsafeUnpin for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl UnsafeUnpin for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl UnsafeUnpin for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl UnsafeUnpin for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl UnsafeUnpin for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl UnsafeUnpin for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl UnsafeUnpin for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl UnsafeUnpin for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl UnsafeUnpin for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl UnsafeUnpin for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl UnsafeUnpin for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl UnsafeUnpin for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl UnsafeUnpin for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl UnsafeUnpin for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl UnsafeUnpin for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl UnsafeUnpin for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl UnsafeUnpin for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl UnsafeUnpin for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl UnsafeUnpin for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl UnsafeUnpin for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl UnsafeUnpin for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl UnsafeUnpin for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl UnsafeUnpin for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl UnsafeUnpin for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl UnsafeUnpin for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl UnsafeUnpin for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl UnsafeUnpin for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl UnsafeUnpin for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl UnsafeUnpin for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl UnsafeUnpin for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> UnsafeUnpin for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> UnsafeUnpin for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> UnsafeUnpin for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> UnsafeUnpin for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> UnsafeUnpin for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> UnsafeUnpin for KeyPair<T>
where\n T: UnsafeUnpin,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl UnsafeUnpin for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl UnsafeUnpin for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl UnsafeUnpin for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> UnsafeUnpin for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> UnsafeUnpin for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl UnsafeUnpin for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl UnsafeUnpin for Opt",1,["perf::client::Opt"]],["impl UnsafeUnpin for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl UnsafeUnpin for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl UnsafeUnpin for Opt",1,["perf::server::Opt"]],["impl UnsafeUnpin for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl UnsafeUnpin for Stats",1,["perf::stats::Stats"]],["impl UnsafeUnpin for StreamStats",1,["perf::stats::StreamStats"]],["impl UnsafeUnpin for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl UnsafeUnpin for Commands",1,["quinn_perf::Commands"]],["impl UnsafeUnpin for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl UnsafeUnpin for CipherSuite",1,["bench::CipherSuite"]],["impl UnsafeUnpin for Stats",1,["bench::stats::Stats"]],["impl UnsafeUnpin for StreamStats",1,["bench::stats::StreamStats"]],["impl UnsafeUnpin for TransferResult",1,["bench::stats::TransferResult"]],["impl UnsafeUnpin for Opt",1,["bench::Opt"]]]],["bulk",[["impl UnsafeUnpin for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl UnsafeUnpin for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl UnsafeUnpin for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl UnsafeUnpin for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl UnsafeUnpin for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl UnsafeUnpin for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl UnsafeUnpin for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl UnsafeUnpin for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl UnsafeUnpin for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl UnsafeUnpin for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl UnsafeUnpin for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl UnsafeUnpin for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl UnsafeUnpin for Connection",1,["iroh_quinn::connection::Connection"]],["impl UnsafeUnpin for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl UnsafeUnpin for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl UnsafeUnpin for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl UnsafeUnpin for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl UnsafeUnpin for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl UnsafeUnpin for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl UnsafeUnpin for Path",1,["iroh_quinn::path::Path"]],["impl UnsafeUnpin for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl UnsafeUnpin for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl UnsafeUnpin for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl UnsafeUnpin for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl UnsafeUnpin for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl UnsafeUnpin for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl UnsafeUnpin for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl UnsafeUnpin for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl<'a> !UnsafeUnpin for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !UnsafeUnpin for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !UnsafeUnpin for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !UnsafeUnpin for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !UnsafeUnpin for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !UnsafeUnpin for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !UnsafeUnpin for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl UnsafeUnpin for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl UnsafeUnpin for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl UnsafeUnpin for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl UnsafeUnpin for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl UnsafeUnpin for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl UnsafeUnpin for Dir",1,["iroh_quinn_proto::Dir"]],["impl UnsafeUnpin for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl UnsafeUnpin for Event",1,["iroh_quinn_proto::connection::Event"]],["impl UnsafeUnpin for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl UnsafeUnpin for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl UnsafeUnpin for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl UnsafeUnpin for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl UnsafeUnpin for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl UnsafeUnpin for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl UnsafeUnpin for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl UnsafeUnpin for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl UnsafeUnpin for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl UnsafeUnpin for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl UnsafeUnpin for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl UnsafeUnpin for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl UnsafeUnpin for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl UnsafeUnpin for Side",1,["iroh_quinn_proto::Side"]],["impl UnsafeUnpin for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl UnsafeUnpin for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl UnsafeUnpin for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl UnsafeUnpin for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl UnsafeUnpin for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl UnsafeUnpin for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl UnsafeUnpin for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl UnsafeUnpin for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl UnsafeUnpin for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl UnsafeUnpin for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl UnsafeUnpin for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl UnsafeUnpin for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl UnsafeUnpin for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl UnsafeUnpin for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl UnsafeUnpin for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl UnsafeUnpin for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl UnsafeUnpin for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl UnsafeUnpin for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl UnsafeUnpin for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl UnsafeUnpin for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl UnsafeUnpin for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl UnsafeUnpin for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl UnsafeUnpin for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl UnsafeUnpin for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl UnsafeUnpin for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl UnsafeUnpin for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl UnsafeUnpin for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl UnsafeUnpin for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl UnsafeUnpin for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl UnsafeUnpin for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl UnsafeUnpin for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl UnsafeUnpin for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl UnsafeUnpin for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl UnsafeUnpin for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl UnsafeUnpin for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl UnsafeUnpin for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl UnsafeUnpin for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl UnsafeUnpin for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl UnsafeUnpin for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl UnsafeUnpin for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl UnsafeUnpin for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl UnsafeUnpin for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl UnsafeUnpin for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl UnsafeUnpin for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl UnsafeUnpin for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl UnsafeUnpin for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl UnsafeUnpin for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl UnsafeUnpin for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl UnsafeUnpin for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl UnsafeUnpin for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl UnsafeUnpin for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl UnsafeUnpin for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl UnsafeUnpin for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl UnsafeUnpin for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl UnsafeUnpin for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl UnsafeUnpin for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl UnsafeUnpin for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl UnsafeUnpin for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl UnsafeUnpin for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl UnsafeUnpin for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl UnsafeUnpin for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl UnsafeUnpin for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl UnsafeUnpin for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl UnsafeUnpin for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl UnsafeUnpin for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl UnsafeUnpin for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl UnsafeUnpin for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl UnsafeUnpin for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl UnsafeUnpin for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl UnsafeUnpin for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl UnsafeUnpin for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl UnsafeUnpin for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl UnsafeUnpin for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl UnsafeUnpin for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl UnsafeUnpin for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl UnsafeUnpin for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl UnsafeUnpin for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> UnsafeUnpin for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> UnsafeUnpin for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> UnsafeUnpin for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> UnsafeUnpin for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> UnsafeUnpin for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> UnsafeUnpin for KeyPair<T>
where\n T: UnsafeUnpin,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl UnsafeUnpin for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl UnsafeUnpin for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl UnsafeUnpin for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> UnsafeUnpin for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> UnsafeUnpin for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl UnsafeUnpin for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl UnsafeUnpin for Opt",1,["perf::client::Opt"]],["impl UnsafeUnpin for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl UnsafeUnpin for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl UnsafeUnpin for Opt",1,["perf::server::Opt"]],["impl UnsafeUnpin for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl UnsafeUnpin for Stats",1,["perf::stats::Stats"]],["impl UnsafeUnpin for StreamStats",1,["perf::stats::StreamStats"]],["impl UnsafeUnpin for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl UnsafeUnpin for Commands",1,["quinn_perf::Commands"]],["impl UnsafeUnpin for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[826,312,384,5922,22177,988,1671,605]} \ No newline at end of file +//{"start":57,"fragment_lengths":[826,312,384,6298,23233,988,1671,605]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js index 4c88463df..705386914 100644 --- a/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ b/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl RefUnwindSafe for CipherSuite",1,["bench::CipherSuite"]],["impl RefUnwindSafe for Stats",1,["bench::stats::Stats"]],["impl RefUnwindSafe for StreamStats",1,["bench::stats::StreamStats"]],["impl RefUnwindSafe for TransferResult",1,["bench::stats::TransferResult"]],["impl RefUnwindSafe for Opt",1,["bench::Opt"]]]],["bulk",[["impl RefUnwindSafe for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl !RefUnwindSafe for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !RefUnwindSafe for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !RefUnwindSafe for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !RefUnwindSafe for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !RefUnwindSafe for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !RefUnwindSafe for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !RefUnwindSafe for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !RefUnwindSafe for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !RefUnwindSafe for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl !RefUnwindSafe for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl !RefUnwindSafe for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !RefUnwindSafe for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl !RefUnwindSafe for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl !RefUnwindSafe for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl !RefUnwindSafe for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl !RefUnwindSafe for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl RefUnwindSafe for Connection",1,["iroh_quinn::connection::Connection"]],["impl RefUnwindSafe for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl RefUnwindSafe for Path",1,["iroh_quinn::path::Path"]],["impl RefUnwindSafe for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl RefUnwindSafe for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl RefUnwindSafe for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl RefUnwindSafe for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl RefUnwindSafe for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl RefUnwindSafe for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl<'a> !RefUnwindSafe for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !RefUnwindSafe for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !RefUnwindSafe for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !RefUnwindSafe for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !RefUnwindSafe for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !RefUnwindSafe for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !RefUnwindSafe for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !RefUnwindSafe for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !RefUnwindSafe for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !RefUnwindSafe for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !RefUnwindSafe for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl !RefUnwindSafe for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl !RefUnwindSafe for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl !RefUnwindSafe for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl !RefUnwindSafe for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !RefUnwindSafe for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl !RefUnwindSafe for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !RefUnwindSafe for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl !RefUnwindSafe for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl !RefUnwindSafe for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !RefUnwindSafe for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl !RefUnwindSafe for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl !RefUnwindSafe for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl !RefUnwindSafe for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl !RefUnwindSafe for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl !RefUnwindSafe for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl RefUnwindSafe for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl RefUnwindSafe for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl RefUnwindSafe for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl RefUnwindSafe for Dir",1,["iroh_quinn_proto::Dir"]],["impl RefUnwindSafe for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl RefUnwindSafe for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl RefUnwindSafe for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl RefUnwindSafe for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl RefUnwindSafe for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl RefUnwindSafe for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl RefUnwindSafe for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl RefUnwindSafe for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl RefUnwindSafe for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl RefUnwindSafe for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl RefUnwindSafe for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl RefUnwindSafe for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl RefUnwindSafe for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl RefUnwindSafe for Side",1,["iroh_quinn_proto::Side"]],["impl RefUnwindSafe for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl RefUnwindSafe for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl RefUnwindSafe for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl RefUnwindSafe for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl RefUnwindSafe for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl RefUnwindSafe for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl RefUnwindSafe for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl RefUnwindSafe for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl RefUnwindSafe for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl RefUnwindSafe for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl RefUnwindSafe for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl RefUnwindSafe for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl RefUnwindSafe for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl RefUnwindSafe for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl RefUnwindSafe for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl RefUnwindSafe for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl RefUnwindSafe for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl RefUnwindSafe for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl RefUnwindSafe for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl RefUnwindSafe for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl RefUnwindSafe for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl RefUnwindSafe for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl RefUnwindSafe for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl RefUnwindSafe for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl RefUnwindSafe for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl RefUnwindSafe for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl RefUnwindSafe for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl RefUnwindSafe for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl RefUnwindSafe for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl RefUnwindSafe for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl RefUnwindSafe for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl RefUnwindSafe for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl RefUnwindSafe for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl RefUnwindSafe for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl RefUnwindSafe for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl RefUnwindSafe for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl RefUnwindSafe for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl RefUnwindSafe for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl RefUnwindSafe for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl RefUnwindSafe for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl RefUnwindSafe for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl RefUnwindSafe for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl RefUnwindSafe for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl RefUnwindSafe for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl RefUnwindSafe for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl RefUnwindSafe for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl RefUnwindSafe for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl RefUnwindSafe for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl RefUnwindSafe for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl RefUnwindSafe for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl RefUnwindSafe for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl RefUnwindSafe for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl RefUnwindSafe for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl RefUnwindSafe for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl RefUnwindSafe for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl RefUnwindSafe for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl RefUnwindSafe for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl RefUnwindSafe for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl RefUnwindSafe for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> !RefUnwindSafe for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> !RefUnwindSafe for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> !RefUnwindSafe for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<'a> RefUnwindSafe for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> RefUnwindSafe for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<T> RefUnwindSafe for KeyPair<T>
where\n T: RefUnwindSafe,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl RefUnwindSafe for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl RefUnwindSafe for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl RefUnwindSafe for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> RefUnwindSafe for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> RefUnwindSafe for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !RefUnwindSafe for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl !RefUnwindSafe for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl RefUnwindSafe for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl RefUnwindSafe for Opt",1,["perf::client::Opt"]],["impl RefUnwindSafe for Opt",1,["perf::server::Opt"]],["impl RefUnwindSafe for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl RefUnwindSafe for Stats",1,["perf::stats::Stats"]],["impl RefUnwindSafe for StreamStats",1,["perf::stats::StreamStats"]],["impl RefUnwindSafe for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl RefUnwindSafe for Commands",1,["quinn_perf::Commands"]],["impl RefUnwindSafe for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl RefUnwindSafe for CipherSuite",1,["bench::CipherSuite"]],["impl RefUnwindSafe for Stats",1,["bench::stats::Stats"]],["impl RefUnwindSafe for StreamStats",1,["bench::stats::StreamStats"]],["impl RefUnwindSafe for TransferResult",1,["bench::stats::TransferResult"]],["impl RefUnwindSafe for Opt",1,["bench::Opt"]]]],["bulk",[["impl RefUnwindSafe for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl !RefUnwindSafe for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !RefUnwindSafe for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !RefUnwindSafe for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !RefUnwindSafe for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !RefUnwindSafe for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !RefUnwindSafe for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !RefUnwindSafe for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !RefUnwindSafe for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !RefUnwindSafe for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl !RefUnwindSafe for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl !RefUnwindSafe for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl !RefUnwindSafe for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl !RefUnwindSafe for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !RefUnwindSafe for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl !RefUnwindSafe for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl !RefUnwindSafe for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl !RefUnwindSafe for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl !RefUnwindSafe for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl RefUnwindSafe for Connection",1,["iroh_quinn::connection::Connection"]],["impl RefUnwindSafe for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl RefUnwindSafe for Path",1,["iroh_quinn::path::Path"]],["impl RefUnwindSafe for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl RefUnwindSafe for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl RefUnwindSafe for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl RefUnwindSafe for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl RefUnwindSafe for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl RefUnwindSafe for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl<'a> !RefUnwindSafe for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !RefUnwindSafe for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !RefUnwindSafe for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !RefUnwindSafe for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !RefUnwindSafe for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !RefUnwindSafe for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !RefUnwindSafe for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !RefUnwindSafe for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !RefUnwindSafe for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !RefUnwindSafe for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !RefUnwindSafe for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl !RefUnwindSafe for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl !RefUnwindSafe for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl !RefUnwindSafe for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl !RefUnwindSafe for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !RefUnwindSafe for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl !RefUnwindSafe for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !RefUnwindSafe for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl !RefUnwindSafe for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl !RefUnwindSafe for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !RefUnwindSafe for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl !RefUnwindSafe for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl !RefUnwindSafe for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl !RefUnwindSafe for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl !RefUnwindSafe for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl !RefUnwindSafe for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl RefUnwindSafe for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl RefUnwindSafe for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl RefUnwindSafe for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl RefUnwindSafe for Dir",1,["iroh_quinn_proto::Dir"]],["impl RefUnwindSafe for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl RefUnwindSafe for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl RefUnwindSafe for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl RefUnwindSafe for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl RefUnwindSafe for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl RefUnwindSafe for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl RefUnwindSafe for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl RefUnwindSafe for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl RefUnwindSafe for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl RefUnwindSafe for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl RefUnwindSafe for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl RefUnwindSafe for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl RefUnwindSafe for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl RefUnwindSafe for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl RefUnwindSafe for Side",1,["iroh_quinn_proto::Side"]],["impl RefUnwindSafe for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl RefUnwindSafe for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl RefUnwindSafe for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl RefUnwindSafe for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl RefUnwindSafe for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl RefUnwindSafe for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl RefUnwindSafe for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl RefUnwindSafe for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl RefUnwindSafe for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl RefUnwindSafe for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl RefUnwindSafe for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl RefUnwindSafe for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl RefUnwindSafe for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl RefUnwindSafe for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl RefUnwindSafe for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl RefUnwindSafe for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl RefUnwindSafe for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl RefUnwindSafe for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl RefUnwindSafe for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl RefUnwindSafe for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl RefUnwindSafe for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl RefUnwindSafe for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl RefUnwindSafe for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl RefUnwindSafe for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl RefUnwindSafe for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl RefUnwindSafe for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl RefUnwindSafe for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl RefUnwindSafe for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl RefUnwindSafe for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl RefUnwindSafe for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl RefUnwindSafe for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl RefUnwindSafe for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl RefUnwindSafe for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl RefUnwindSafe for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl RefUnwindSafe for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl RefUnwindSafe for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl RefUnwindSafe for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl RefUnwindSafe for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl RefUnwindSafe for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl RefUnwindSafe for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl RefUnwindSafe for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl RefUnwindSafe for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl RefUnwindSafe for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl RefUnwindSafe for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl RefUnwindSafe for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl RefUnwindSafe for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl RefUnwindSafe for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl RefUnwindSafe for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl RefUnwindSafe for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl RefUnwindSafe for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl RefUnwindSafe for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl RefUnwindSafe for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl RefUnwindSafe for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl RefUnwindSafe for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl RefUnwindSafe for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl RefUnwindSafe for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl RefUnwindSafe for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl RefUnwindSafe for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl RefUnwindSafe for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl RefUnwindSafe for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl RefUnwindSafe for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl RefUnwindSafe for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl RefUnwindSafe for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> !RefUnwindSafe for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> !RefUnwindSafe for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> !RefUnwindSafe for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<'a> RefUnwindSafe for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> RefUnwindSafe for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<T> RefUnwindSafe for KeyPair<T>
where\n T: RefUnwindSafe,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl RefUnwindSafe for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl RefUnwindSafe for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl RefUnwindSafe for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> RefUnwindSafe for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> RefUnwindSafe for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !RefUnwindSafe for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl !RefUnwindSafe for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl RefUnwindSafe for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl RefUnwindSafe for Opt",1,["perf::client::Opt"]],["impl RefUnwindSafe for Opt",1,["perf::server::Opt"]],["impl RefUnwindSafe for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl RefUnwindSafe for Stats",1,["perf::stats::Stats"]],["impl RefUnwindSafe for StreamStats",1,["perf::stats::StreamStats"]],["impl RefUnwindSafe for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl RefUnwindSafe for Commands",1,["quinn_perf::Commands"]],["impl RefUnwindSafe for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1686,341,414,11269,39915,1848,3221,663]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1686,341,414,11991,41831,1848,3221,663]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js index 19c211d09..bbc497ab7 100644 --- a/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js +++ b/pr/255/docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -1,9 +1,9 @@ (function() { - var implementors = Object.fromEntries([["bench",[["impl UnwindSafe for CipherSuite",1,["bench::CipherSuite"]],["impl UnwindSafe for Stats",1,["bench::stats::Stats"]],["impl UnwindSafe for StreamStats",1,["bench::stats::StreamStats"]],["impl UnwindSafe for TransferResult",1,["bench::stats::TransferResult"]],["impl UnwindSafe for Opt",1,["bench::Opt"]]]],["bulk",[["impl UnwindSafe for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl !UnwindSafe for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !UnwindSafe for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !UnwindSafe for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !UnwindSafe for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !UnwindSafe for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !UnwindSafe for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !UnwindSafe for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !UnwindSafe for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !UnwindSafe for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl !UnwindSafe for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl !UnwindSafe for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !UnwindSafe for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl !UnwindSafe for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl !UnwindSafe for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl !UnwindSafe for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl !UnwindSafe for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl UnwindSafe for Connection",1,["iroh_quinn::connection::Connection"]],["impl UnwindSafe for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl UnwindSafe for Path",1,["iroh_quinn::path::Path"]],["impl UnwindSafe for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl UnwindSafe for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl UnwindSafe for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl UnwindSafe for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl UnwindSafe for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl UnwindSafe for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl<'a> !UnwindSafe for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !UnwindSafe for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !UnwindSafe for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !UnwindSafe for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !UnwindSafe for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !UnwindSafe for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !UnwindSafe for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !UnwindSafe for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !UnwindSafe for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !UnwindSafe for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !UnwindSafe for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl !UnwindSafe for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl !UnwindSafe for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl !UnwindSafe for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl !UnwindSafe for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !UnwindSafe for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl !UnwindSafe for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !UnwindSafe for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl !UnwindSafe for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl !UnwindSafe for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !UnwindSafe for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl !UnwindSafe for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl !UnwindSafe for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl !UnwindSafe for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl !UnwindSafe for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl !UnwindSafe for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl UnwindSafe for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl UnwindSafe for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl UnwindSafe for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl UnwindSafe for Dir",1,["iroh_quinn_proto::Dir"]],["impl UnwindSafe for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl UnwindSafe for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl UnwindSafe for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl UnwindSafe for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl UnwindSafe for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl UnwindSafe for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl UnwindSafe for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl UnwindSafe for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl UnwindSafe for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl UnwindSafe for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl UnwindSafe for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl UnwindSafe for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl UnwindSafe for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl UnwindSafe for Side",1,["iroh_quinn_proto::Side"]],["impl UnwindSafe for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl UnwindSafe for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl UnwindSafe for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl UnwindSafe for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl UnwindSafe for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl UnwindSafe for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl UnwindSafe for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl UnwindSafe for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl UnwindSafe for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl UnwindSafe for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl UnwindSafe for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl UnwindSafe for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl UnwindSafe for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl UnwindSafe for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl UnwindSafe for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl UnwindSafe for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl UnwindSafe for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl UnwindSafe for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl UnwindSafe for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl UnwindSafe for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl UnwindSafe for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl UnwindSafe for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl UnwindSafe for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl UnwindSafe for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl UnwindSafe for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl UnwindSafe for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl UnwindSafe for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl UnwindSafe for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl UnwindSafe for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl UnwindSafe for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl UnwindSafe for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl UnwindSafe for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl UnwindSafe for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl UnwindSafe for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl UnwindSafe for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl UnwindSafe for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl UnwindSafe for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl UnwindSafe for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl UnwindSafe for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl UnwindSafe for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl UnwindSafe for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl UnwindSafe for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl UnwindSafe for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl UnwindSafe for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl UnwindSafe for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl UnwindSafe for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl UnwindSafe for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl UnwindSafe for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl UnwindSafe for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl UnwindSafe for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl UnwindSafe for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl UnwindSafe for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl UnwindSafe for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl UnwindSafe for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl UnwindSafe for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl UnwindSafe for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl UnwindSafe for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl UnwindSafe for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl UnwindSafe for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> !UnwindSafe for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> !UnwindSafe for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> !UnwindSafe for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> !UnwindSafe for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> !UnwindSafe for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> UnwindSafe for KeyPair<T>
where\n T: UnwindSafe,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl UnwindSafe for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl UnwindSafe for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl UnwindSafe for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> UnwindSafe for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> UnwindSafe for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !UnwindSafe for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl !UnwindSafe for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl UnwindSafe for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl UnwindSafe for Opt",1,["perf::client::Opt"]],["impl UnwindSafe for Opt",1,["perf::server::Opt"]],["impl UnwindSafe for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl UnwindSafe for Stats",1,["perf::stats::Stats"]],["impl UnwindSafe for StreamStats",1,["perf::stats::StreamStats"]],["impl UnwindSafe for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl UnwindSafe for Commands",1,["quinn_perf::Commands"]],["impl UnwindSafe for Cli",1,["quinn_perf::Cli"]]]]]); + var implementors = Object.fromEntries([["bench",[["impl UnwindSafe for CipherSuite",1,["bench::CipherSuite"]],["impl UnwindSafe for Stats",1,["bench::stats::Stats"]],["impl UnwindSafe for StreamStats",1,["bench::stats::StreamStats"]],["impl UnwindSafe for TransferResult",1,["bench::stats::TransferResult"]],["impl UnwindSafe for Opt",1,["bench::Opt"]]]],["bulk",[["impl UnwindSafe for ClientStats",1,["bulk::ClientStats"]]]],["certificate",[["impl !UnwindSafe for SkipServerVerification",1,["certificate::SkipServerVerification"]]]],["iroh_quinn",[["impl !UnwindSafe for ReadError",1,["iroh_quinn::recv_stream::ReadError"]],["impl !UnwindSafe for ReadExactError",1,["iroh_quinn::recv_stream::ReadExactError"]],["impl !UnwindSafe for ReadToEndError",1,["iroh_quinn::recv_stream::ReadToEndError"]],["impl !UnwindSafe for ResetError",1,["iroh_quinn::recv_stream::ResetError"]],["impl !UnwindSafe for SendDatagramError",1,["iroh_quinn::connection::SendDatagramError"]],["impl !UnwindSafe for StoppedError",1,["iroh_quinn::send_stream::StoppedError"]],["impl !UnwindSafe for WriteError",1,["iroh_quinn::send_stream::WriteError"]],["impl !UnwindSafe for AddressDiscovery",1,["iroh_quinn::path::AddressDiscovery"]],["impl !UnwindSafe for ClosePath",1,["iroh_quinn::path::ClosePath"]],["impl !UnwindSafe for Connecting",1,["iroh_quinn::connection::Connecting"]],["impl !UnwindSafe for Endpoint",1,["iroh_quinn::endpoint::Endpoint"]],["impl !UnwindSafe for Incoming",1,["iroh_quinn::incoming::Incoming"]],["impl !UnwindSafe for IncomingFuture",1,["iroh_quinn::incoming::IncomingFuture"]],["impl !UnwindSafe for OnClosed",1,["iroh_quinn::connection::OnClosed"]],["impl !UnwindSafe for OpenPath",1,["iroh_quinn::path::OpenPath"]],["impl !UnwindSafe for RetryError",1,["iroh_quinn::incoming::RetryError"]],["impl !UnwindSafe for ZeroRttAccepted",1,["iroh_quinn::connection::ZeroRttAccepted"]],["impl UnwindSafe for Connection",1,["iroh_quinn::connection::Connection"]],["impl UnwindSafe for EndpointStats",1,["iroh_quinn::endpoint::EndpointStats"]],["impl UnwindSafe for Path",1,["iroh_quinn::path::Path"]],["impl UnwindSafe for RecvStream",1,["iroh_quinn::recv_stream::RecvStream"]],["impl UnwindSafe for SendStream",1,["iroh_quinn::send_stream::SendStream"]],["impl UnwindSafe for SmolRuntime",1,["iroh_quinn::runtime::smol::SmolRuntime"]],["impl UnwindSafe for TokioRuntime",1,["iroh_quinn::runtime::tokio::TokioRuntime"]],["impl UnwindSafe for UnorderedRecvStream",1,["iroh_quinn::recv_stream::UnorderedRecvStream"]],["impl UnwindSafe for WeakConnectionHandle",1,["iroh_quinn::connection::WeakConnectionHandle"]],["impl<'a> !UnwindSafe for Accept<'a>",1,["iroh_quinn::endpoint::Accept"]],["impl<'a> !UnwindSafe for AcceptBi<'a>",1,["iroh_quinn::connection::AcceptBi"]],["impl<'a> !UnwindSafe for AcceptUni<'a>",1,["iroh_quinn::connection::AcceptUni"]],["impl<'a> !UnwindSafe for OpenBi<'a>",1,["iroh_quinn::connection::OpenBi"]],["impl<'a> !UnwindSafe for OpenUni<'a>",1,["iroh_quinn::connection::OpenUni"]],["impl<'a> !UnwindSafe for ReadDatagram<'a>",1,["iroh_quinn::connection::ReadDatagram"]],["impl<'a> !UnwindSafe for SendDatagram<'a>",1,["iroh_quinn::connection::SendDatagram"]]]],["iroh_quinn_proto",[["impl !UnwindSafe for ConnectionError",1,["iroh_quinn_proto::connection::ConnectionError"]],["impl !UnwindSafe for DatagramEvent",1,["iroh_quinn_proto::endpoint::DatagramEvent"]],["impl !UnwindSafe for Event",1,["iroh_quinn_proto::connection::Event"]],["impl !UnwindSafe for QuicClientConfig",1,["iroh_quinn_proto::crypto::rustls::QuicClientConfig"]],["impl !UnwindSafe for QuicServerConfig",1,["iroh_quinn_proto::crypto::rustls::QuicServerConfig"]],["impl !UnwindSafe for TlsSession",1,["iroh_quinn_proto::crypto::rustls::TlsSession"]],["impl !UnwindSafe for Keys",1,["iroh_quinn_proto::crypto::Keys"]],["impl !UnwindSafe for AcceptError",1,["iroh_quinn_proto::endpoint::AcceptError"]],["impl !UnwindSafe for ClientConfig",1,["iroh_quinn_proto::config::ClientConfig"]],["impl !UnwindSafe for Connection",1,["iroh_quinn_proto::connection::Connection"]],["impl !UnwindSafe for Endpoint",1,["iroh_quinn_proto::endpoint::Endpoint"]],["impl !UnwindSafe for EndpointConfig",1,["iroh_quinn_proto::config::EndpointConfig"]],["impl !UnwindSafe for Incoming",1,["iroh_quinn_proto::endpoint::Incoming"]],["impl !UnwindSafe for QlogConfig",1,["iroh_quinn_proto::config::qlog::QlogConfig"]],["impl !UnwindSafe for RetryError",1,["iroh_quinn_proto::endpoint::RetryError"]],["impl !UnwindSafe for ServerConfig",1,["iroh_quinn_proto::config::ServerConfig"]],["impl !UnwindSafe for TransportConfig",1,["iroh_quinn_proto::config::transport::TransportConfig"]],["impl !UnwindSafe for Error",1,["iroh_quinn_proto::transport_error::Error"]],["impl !UnwindSafe for ValidationTokenConfig",1,["iroh_quinn_proto::config::ValidationTokenConfig"]],["impl UnwindSafe for ClosePathError",1,["iroh_quinn_proto::connection::ClosePathError"]],["impl UnwindSafe for ConfigError",1,["iroh_quinn_proto::config::ConfigError"]],["impl UnwindSafe for ConnectError",1,["iroh_quinn_proto::endpoint::ConnectError"]],["impl UnwindSafe for Dir",1,["iroh_quinn_proto::Dir"]],["impl UnwindSafe for EcnCodepoint",1,["iroh_quinn_proto::shared::EcnCodepoint"]],["impl UnwindSafe for FinishError",1,["iroh_quinn_proto::connection::streams::send::FinishError"]],["impl UnwindSafe for FrameType",1,["iroh_quinn_proto::frame::FrameType"]],["impl UnwindSafe for LongType",1,["iroh_quinn_proto::packet::LongType"]],["impl UnwindSafe for MaybeFrame",1,["iroh_quinn_proto::frame::MaybeFrame"]],["impl UnwindSafe for PacketDecodeError",1,["iroh_quinn_proto::packet::PacketDecodeError"]],["impl UnwindSafe for PathError",1,["iroh_quinn_proto::connection::PathError"]],["impl UnwindSafe for PathEvent",1,["iroh_quinn_proto::connection::paths::PathEvent"]],["impl UnwindSafe for PathStatus",1,["iroh_quinn_proto::connection::paths::PathStatus"]],["impl UnwindSafe for ProtectedHeader",1,["iroh_quinn_proto::packet::ProtectedHeader"]],["impl UnwindSafe for ReadError",1,["iroh_quinn_proto::connection::streams::recv::ReadError"]],["impl UnwindSafe for ReadableError",1,["iroh_quinn_proto::connection::streams::recv::ReadableError"]],["impl UnwindSafe for SendDatagramError",1,["iroh_quinn_proto::connection::datagrams::SendDatagramError"]],["impl UnwindSafe for SetPathStatusError",1,["iroh_quinn_proto::connection::paths::SetPathStatusError"]],["impl UnwindSafe for Side",1,["iroh_quinn_proto::Side"]],["impl UnwindSafe for StreamEvent",1,["iroh_quinn_proto::connection::streams::StreamEvent"]],["impl UnwindSafe for WriteError",1,["iroh_quinn_proto::connection::streams::send::WriteError"]],["impl UnwindSafe for Error",1,["iroh_quinn_proto::iroh_hp::Error"]],["impl UnwindSafe for Event",1,["iroh_quinn_proto::iroh_hp::Event"]],["impl UnwindSafe for Error",1,["iroh_quinn_proto::transport_parameters::Error"]],["impl UnwindSafe for UnexpectedEnd",1,["iroh_quinn_proto::coding::UnexpectedEnd"]],["impl UnwindSafe for Bbr",1,["iroh_quinn_proto::congestion::bbr::Bbr"]],["impl UnwindSafe for BbrConfig",1,["iroh_quinn_proto::congestion::bbr::BbrConfig"]],["impl UnwindSafe for ControllerMetrics",1,["iroh_quinn_proto::congestion::ControllerMetrics"]],["impl UnwindSafe for Cubic",1,["iroh_quinn_proto::congestion::cubic::Cubic"]],["impl UnwindSafe for CubicConfig",1,["iroh_quinn_proto::congestion::cubic::CubicConfig"]],["impl UnwindSafe for NewReno",1,["iroh_quinn_proto::congestion::new_reno::NewReno"]],["impl UnwindSafe for NewRenoConfig",1,["iroh_quinn_proto::congestion::new_reno::NewRenoConfig"]],["impl UnwindSafe for HandshakeData",1,["iroh_quinn_proto::crypto::rustls::HandshakeData"]],["impl UnwindSafe for NoInitialCipherSuite",1,["iroh_quinn_proto::crypto::rustls::NoInitialCipherSuite"]],["impl UnwindSafe for CryptoError",1,["iroh_quinn_proto::crypto::CryptoError"]],["impl UnwindSafe for ExportKeyingMaterialError",1,["iroh_quinn_proto::crypto::ExportKeyingMaterialError"]],["impl UnwindSafe for UnsupportedVersion",1,["iroh_quinn_proto::crypto::UnsupportedVersion"]],["impl UnwindSafe for AckFrequencyConfig",1,["iroh_quinn_proto::config::transport::AckFrequencyConfig"]],["impl UnwindSafe for ApplicationClose",1,["iroh_quinn_proto::frame::ApplicationClose"]],["impl UnwindSafe for BloomTokenLog",1,["iroh_quinn_proto::bloom_token_log::BloomTokenLog"]],["impl UnwindSafe for Chunk",1,["iroh_quinn_proto::connection::assembler::Chunk"]],["impl UnwindSafe for ClosedPath",1,["iroh_quinn_proto::connection::paths::ClosedPath"]],["impl UnwindSafe for ClosedStream",1,["iroh_quinn_proto::connection::streams::ClosedStream"]],["impl UnwindSafe for ConnectionClose",1,["iroh_quinn_proto::frame::ConnectionClose"]],["impl UnwindSafe for ConnectionEvent",1,["iroh_quinn_proto::shared::ConnectionEvent"]],["impl UnwindSafe for ConnectionHandle",1,["iroh_quinn_proto::endpoint::ConnectionHandle"]],["impl UnwindSafe for ConnectionId",1,["iroh_quinn_proto::shared::ConnectionId"]],["impl UnwindSafe for ConnectionStats",1,["iroh_quinn_proto::connection::stats::ConnectionStats"]],["impl UnwindSafe for Datagram",1,["iroh_quinn_proto::frame::Datagram"]],["impl UnwindSafe for DatagramInfo",1,["iroh_quinn_proto::frame::DatagramInfo"]],["impl UnwindSafe for EndpointEvent",1,["iroh_quinn_proto::shared::EndpointEvent"]],["impl UnwindSafe for FixedLengthConnectionIdParser",1,["iroh_quinn_proto::packet::FixedLengthConnectionIdParser"]],["impl UnwindSafe for FourTuple",1,["iroh_quinn_proto::FourTuple"]],["impl UnwindSafe for FrameStats",1,["iroh_quinn_proto::connection::stats::FrameStats"]],["impl UnwindSafe for HashedConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::HashedConnectionIdGenerator"]],["impl UnwindSafe for IdleTimeout",1,["iroh_quinn_proto::config::transport::IdleTimeout"]],["impl UnwindSafe for InvalidCid",1,["iroh_quinn_proto::cid_generator::InvalidCid"]],["impl UnwindSafe for InvalidFrameId",1,["iroh_quinn_proto::frame::InvalidFrameId"]],["impl UnwindSafe for MtuDiscoveryConfig",1,["iroh_quinn_proto::config::transport::MtuDiscoveryConfig"]],["impl UnwindSafe for MultipathNotNegotiated",1,["iroh_quinn_proto::connection::MultipathNotNegotiated"]],["impl UnwindSafe for NoneTokenLog",1,["iroh_quinn_proto::token::NoneTokenLog"]],["impl UnwindSafe for NoneTokenStore",1,["iroh_quinn_proto::token::NoneTokenStore"]],["impl UnwindSafe for PartialDecode",1,["iroh_quinn_proto::packet::PartialDecode"]],["impl UnwindSafe for PathId",1,["iroh_quinn_proto::connection::paths::PathId"]],["impl UnwindSafe for PathStats",1,["iroh_quinn_proto::connection::stats::PathStats"]],["impl UnwindSafe for ProtectedInitialHeader",1,["iroh_quinn_proto::packet::ProtectedInitialHeader"]],["impl UnwindSafe for QlogFileFactory",1,["iroh_quinn_proto::config::qlog::QlogFileFactory"]],["impl UnwindSafe for RandomConnectionIdGenerator",1,["iroh_quinn_proto::cid_generator::RandomConnectionIdGenerator"]],["impl UnwindSafe for RttEstimator",1,["iroh_quinn_proto::connection::paths::RttEstimator"]],["impl UnwindSafe for ShouldTransmit",1,["iroh_quinn_proto::connection::streams::ShouldTransmit"]],["impl UnwindSafe for StdSystemTime",1,["iroh_quinn_proto::config::StdSystemTime"]],["impl UnwindSafe for StreamId",1,["iroh_quinn_proto::StreamId"]],["impl UnwindSafe for StreamInfo",1,["iroh_quinn_proto::frame::StreamInfo"]],["impl UnwindSafe for TokenMemoryCache",1,["iroh_quinn_proto::token_memory_cache::TokenMemoryCache"]],["impl UnwindSafe for TokenReuseError",1,["iroh_quinn_proto::token::TokenReuseError"]],["impl UnwindSafe for Transmit",1,["iroh_quinn_proto::Transmit"]],["impl UnwindSafe for Code",1,["iroh_quinn_proto::transport_error::Code"]],["impl UnwindSafe for UdpStats",1,["iroh_quinn_proto::connection::stats::UdpStats"]],["impl UnwindSafe for VarInt",1,["iroh_quinn_proto::varint::VarInt"]],["impl UnwindSafe for VarIntBoundsExceeded",1,["iroh_quinn_proto::varint::VarIntBoundsExceeded"]],["impl UnwindSafe for Written",1,["iroh_quinn_proto::connection::streams::send::Written"]],["impl UnwindSafe for TransportParameters",1,["iroh_quinn_proto::transport_parameters::TransportParameters"]],["impl<'a> !UnwindSafe for Chunks<'a>",1,["iroh_quinn_proto::connection::streams::recv::Chunks"]],["impl<'a> !UnwindSafe for Datagrams<'a>",1,["iroh_quinn_proto::connection::datagrams::Datagrams"]],["impl<'a> !UnwindSafe for RecvStream<'a>",1,["iroh_quinn_proto::connection::streams::RecvStream"]],["impl<'a> !UnwindSafe for SendStream<'a>",1,["iroh_quinn_proto::connection::streams::SendStream"]],["impl<'a> !UnwindSafe for Streams<'a>",1,["iroh_quinn_proto::connection::streams::Streams"]],["impl<T> UnwindSafe for KeyPair<T>
where\n T: UnwindSafe,
",1,["iroh_quinn_proto::crypto::KeyPair"]]]],["iroh_quinn_udp",[["impl UnwindSafe for EcnCodepoint",1,["iroh_quinn_udp::EcnCodepoint"]],["impl UnwindSafe for RecvMeta",1,["iroh_quinn_udp::RecvMeta"]],["impl UnwindSafe for UdpSocketState",1,["iroh_quinn_udp::imp::UdpSocketState"]],["impl<'a> UnwindSafe for Transmit<'a>",1,["iroh_quinn_udp::Transmit"]],["impl<'a> UnwindSafe for UdpSockRef<'a>",1,["iroh_quinn_udp::UdpSockRef"]]]],["perf",[["impl !UnwindSafe for NoProtectionClientConfig",1,["perf::noprotection::NoProtectionClientConfig"]],["impl !UnwindSafe for NoProtectionServerConfig",1,["perf::noprotection::NoProtectionServerConfig"]],["impl UnwindSafe for CongestionAlgorithm",1,["perf::CongestionAlgorithm"]],["impl UnwindSafe for Opt",1,["perf::client::Opt"]],["impl UnwindSafe for Opt",1,["perf::server::Opt"]],["impl UnwindSafe for OpenStreamStats",1,["perf::stats::OpenStreamStats"]],["impl UnwindSafe for Stats",1,["perf::stats::Stats"]],["impl UnwindSafe for StreamStats",1,["perf::stats::StreamStats"]],["impl UnwindSafe for CommonOpt",1,["perf::CommonOpt"]]]],["quinn_perf",[["impl UnwindSafe for Commands",1,["quinn_perf::Commands"]],["impl UnwindSafe for Cli",1,["quinn_perf::Cli"]]]]]); if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } })() -//{"start":57,"fragment_lengths":[1641,332,405,10990,38990,1803,3140,645]} \ No newline at end of file +//{"start":57,"fragment_lengths":[1641,332,405,11694,40861,1803,3140,645]} \ No newline at end of file diff --git a/pr/255/docs/trait.impl/futures_core/stream/trait.Stream.js b/pr/255/docs/trait.impl/futures_core/stream/trait.Stream.js new file mode 100644 index 000000000..907146828 --- /dev/null +++ b/pr/255/docs/trait.impl/futures_core/stream/trait.Stream.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["iroh_quinn",[["impl Stream for AddressDiscovery"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[172]} \ No newline at end of file