Subject: Re: QUIC API (was: Re: Small size of core QUIC library to replace TCP for embedded system)

From: Martin Duke <[email-masked]>
Date: Thu, 6 Aug 2020 15:57:18 -0700

On this subject, (speaking as individual) I think it would be useful to
define a QUIC application API. SCTP did one (
https://datatracker.ietf.org/doc/rfc6458/) and the idea that an application
would have to be written separately for each quic implementation is silly.

On Tue, Jul 21, 2020 at 11:18 PM Lars Eggert <[email-masked]> wrote:

> Hi,
>
> On 2020-7-21, at 20:02, Paul Vixie <[email-masked]> wrote:
> > my question is, has any QUIC implementor been thinking along these
> lines? i
> > believe that the parameters to a QUIC "connect" syscall would be larger
> and
> > more numerous than for a TCP or SCTP or UDP "connect" syscall, for
> example.
>
> most QUIC implementations have an API that is at a high level pretty
> similar to the socket API, but different in all the details. And they are
> all different from each other.
>
> Since you asked about a "connect" equivalent, here is what some of the C
> stacks offer:
>
> quant:
> https://github.com/NTAP/quant/blob/master/lib/include/quant/quant.h#L110-L118
>
> msquic:
> https://github.com/microsoft/msquic/blob/master/src/inc/msquic.h#L745-L757
>
> quicly:
> https://github.com/h2o/quicly/blob/master/include/quicly.h#L892-L900
>
> Pretty different.
>
> Lars
>

---

From: Paul Vixie <[email-masked]>
Date: Thu, 6 Aug 2020 16:11:42 -0700

Martin Duke wrote on 2020-08-06 15:57:
> On this subject, (speaking as individual) I think it would be useful 
> to define a QUIC application API. SCTP did one 
> (https://datatracker.ietf.org/doc/rfc6458/) and the idea that an 
> application would have to be written separately for each quic 
> implementation is silly.

i agree, in two ways. first, something like getdns (see 
https://getdnsapi.net/) to describe the core functions and standard 
language-specific bindings would be good. as with dns, there may be more 
than one instance of this kind of thing, but it would be good to see 
shared libraries generally available so that a quic app (and perhaps 
also HoQ, DoQ, and other layerings) could be normal dependencies of 
packages we install. RFC 6458 assumes that the the sockets API will be 
involved, which does not facilitate the kind of user-mode transport that 
QUIC anticipates.

second, something like RFC 2292 (see https://tools.ietf.org/html/rfc3542 
<https://tools.ietf.org/html/rfc3542>) or RFC 6458 [ibid] that explains 
how to access quic through the socket interface if some of us want to 
use the system call interface as a monitoring point (so, like dtrace) or 
a control point (so, like anti-malware), and where UDP sockets might be 
restricted to privileged processes and the kernel, but not generally 
available to apps who want to avoid the kernel operator's monitoring 
and/or controls. as a kernel operator i don't plan to trust my apps to 
do things that are not transparent to me.

if anybody decides to work on either one, i promise to review, 
comment/discuss, test where possible, and perhaps implement/prototype.

vixie

-- 
Sent from Postbox 
<https://www.postbox-inc.com/?utm_source=email&utm_medium=siglink&utm_campaign=reach>

---

From: Nick Banks <[email-masked]>
Date: Thu, 6 Aug 2020 23:25:35 +0000

MsQuic has a fairly generic (msquic.h<https://github.com/microsoft/msquic/blob/master/src/inc/msquic.h#L992>) API that is used in Windows by two completely different production protocols (HTTP & SMB), a number of tools/tests and several prototypes. It’s also a WIP to be exposed in .NET core. It has some documentation (start here<https://github.com/microsoft/msquic/blob/master/docs/API.md>). It’s still a work in progress, but probably about 90% complete. I’d like to think that our API exposes pretty much the entire QUIC spec’s worth of functionality in a general purpose way. It uses all async IO (which I know quite a few aren’t a fan of) and it’s completely separate from sockets. I’d be happy to work with any group that wishes to try to outline a general API for QUIC. Also, if you have any questions or comments on our API, feel free to file issues on our GitHub repo: https://github.com/microsoft/msquic.

Thanks,
- Nick

From: QUIC <[email-masked]> On Behalf Of Paul Vixie
Sent: Thursday, August 6, 2020 4:12 PM
To: Martin Duke <[email-masked]>
Cc: Lars Eggert <[email-masked]>; quic <[email-masked]>
Subject: Re: QUIC API

On this subject, (speaking as individual) I think it would be useful to define a QUIC application API. SCTP did one (https://datatracker.ietf.org/doc/rfc6458/<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdatatracker.ietf.org%2Fdoc%2Frfc6458%2F&data=02%7C01%7Cnibanks%40microsoft.com%7C42ecbc69fb5744fd4c4808d83a5e2e0a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637323524361871926&sdata=4Y9dkOYeSsWkZMPYWGWwCA%2Br7Bw2BpLx6ws1ErWPOFo%3D&reserved=0>) and the idea that an application would have to be written separately for each quic implementation is silly.

i agree, in two ways. first, something like getdns (see https://getdnsapi.net/<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgetdnsapi.net%2F&data=02%7C01%7Cnibanks%40microsoft.com%7C42ecbc69fb5744fd4c4808d83a5e2e0a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637323524361871926&sdata=Amdt0pV4oLxGtZvF%2FEpuMoZMp9WRKUth3iCul%2FEa%2Bg4%3D&reserved=0>) to describe the core functions and standard language-specific bindings would be good. as with dns, there may be more than one instance of this kind of thing, but it would be good to see shared libraries generally available so that a quic app (and perhaps also HoQ, DoQ, and other layerings) could be normal dependencies of packages we install. RFC 6458 assumes that the the sockets API will be involved, which does not facilitate the kind of user-mode transport that QUIC anticipates.

second, something like RFC 2292 (see https://tools.ietf.org/html/rfc3542<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc3542&data=02%7C01%7Cnibanks%40microsoft.com%7C42ecbc69fb5744fd4c4808d83a5e2e0a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637323524361881882&sdata=9ygGCiFbsP9phEF78igkzrUWP%2FBaX0aPyw0kfeckhqA%3D&reserved=0>) or RFC 6458 [ibid] that explains how to access quic through the socket interface if some of us want to use the system call interface as a monitoring point (so, like dtrace) or a control point (so, like anti-malware), and where UDP sockets might be restricted to privileged processes and the kernel, but not generally available to apps who want to avoid the kernel operator's monitoring and/or controls. as a kernel operator i don't plan to trust my apps to do things that are not transparent to me.

if anybody decides to work on either one, i promise to review, comment/discuss, test where possible, and perhaps implement/prototype.

vixie
--
Sent from Postbox<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.postbox-inc.com%2F%3Futm_source%3Demail%26utm_medium%3Dsiglink%26utm_campaign%3Dreach&data=02%7C01%7Cnibanks%40microsoft.com%7C42ecbc69fb5744fd4c4808d83a5e2e0a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637323524361881882&sdata=LSRr0XnJj65RuVVXzwwdKbA7kverhGC5nzMugqrcLQ0%3D&reserved=0>

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 7 Aug 2020 00:27:20 +0100

Would TAPS fit your bill?

https://tools.ietf.org/html/draft-ietf-taps-interface-09

On Thu, 6 Aug 2020, 23:57 Martin Duke, <[email-masked]> wrote:

> https://datatracker.ietf.org/doc/rfc6458/) and the idea that an
>> <https://github.com/h2o/quicly/blob/master/include/quicly..h#L892-L900>
>>
>> Pretty different.
>>
>> Lars
>>
>

---

From: Martin Duke <[email-masked]>
Date: Thu, 6 Aug 2020 16:37:01 -0700

I am all for using TAPS concepts wherever possible, but I am not sure we
should put all of our eggs in that basket.

On Thu, Aug 6, 2020 at 4:27 PM Lucas Pardue <[email-masked]>
wrote:

>>> > believe that the parameters to a QUIC "connect" syscall would be
>>> larger and

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 7 Aug 2020 01:16:09 +0100

> should put all of our eggs in that basket.

I'm no TAPS or SCTP aficionado so take my view with a pinch of salt.

It's just that looking at RFC 6458 and seeing a 100 page document makes me
wonder what would be required to do something for QUIC, who would implement
that, and who would pick up the pen.

It seems like a possible divergent effort from other API work, which seems
like a fragmented outcome.

How successful is RFC 6458?

Also, I think it help would me to understand the incentives. The
supposition was about an application wanting to use different QUIC stacks?
Curl is already doing this and it doesn't seem too onerous. I'm sure there
are other incentives though.

Lucas

>>>> Since you asked about a "connect" equivalent, here is what some of the
>>>> C stacks offer:
>>>>
>>>> quant:

---

From: David Schinazi <[email-masked]>
Date: Thu, 6 Aug 2020 17:58:26 -0700

What would be the purpose of defining a QUIC API?

In theory, it could mean that one could write an application
in such a way that it could swap QUIC implementations.
I don't see that happening in practice. The application
developer would have to periodically test against these
implementations for them to work reliably, so the idea
of a drop-in replacement sounds unreal to me.

Additionally, in 2020, networking APIs are asynchronous.
That means that a QUIC API would need to be tied to
a specific asynchronous IO model, and those are tied
to programming language and library choices. So any
API would only work for applications that pick the same
language and standard libraries.

David

On Thu, Aug 6, 2020 at 5:16 PM Lucas Pardue <[email-masked]>
wrote:

>>>>> <https://github.com/h2o/quicly/blob/master/include/quicly...h#L892-L900>
>>>>>
>>>>> Pretty different.
>>>>>
>>>>> Lars
>>>>>
>>>>

---

From: Christian Huitema <[email-masked]>
Date: Thu, 6 Aug 2020 23:36:51 -0700

> of a drop-in replacement sounds unreal to me.

Yes. We had an example of that when testers wanted to plug their tools
to different QUIC stacks. Not impossible, but there was a lot of glue
required.

> language and standard libraries.

People today are experimenting with a variety of application--stack
interactions. I think that's a good thing at this point. Take the
example of out-of-order delivery: really cool potential, but we have
very little experience. It might require tight integration with the
application, dealing with the intricacies of video codecs. I think that
in the next year or two we will gain some experience and maybe see a
small number of API models emerge. But attempting standardization before
that seems very premature.

-- Christian Huitema

---

From: Robin MARX <[email-masked]>
Date: Fri, 7 Aug 2020 10:17:33 +0200

Personally, I would agree that creating a general purpose API just for QUIC
would be difficult.
I'm mainly thinking about what the interface for steering stream
multiplexing/prioritization would look like, seeing as the specs are very
light on details for these.
Speccing something out for HTTP/3 should be do-able (and is being
contemplated by some, e.g., https://github.com/hyperium/h3/pull/1), though
potentially not as useful.

I would echo Lucas' reference in thinking that abstracting from QUIC to a
more high-level view of transport features with something like TAPS is more
logical in the long run.
Rather than putting all eggs in one basket, it would be good to get at
least this one egg into that particular basket imo.

Like Lucas and David, I'm also not sure how common/realistic of a use case
the "I want to switch ad-hoc between QUIC implementations" argument will
be.
To me, a common API would be mostly interesting in writing re-usable
high-level coding tutorials and teaching materials to help new devs use the
protocol more quickly.
>From that perspective, you can make an even stronger argument for TAPS imo.

With best regards,
Robin

-- 

Robin Marx
PhD researcher - web performance
Expertise centre for Digital Media

T +32(0)11 26 84 79 - GSM +32(0)497 72 86 94

www.uhasselt.be
Universiteit Hasselt - Campus Diepenbeek
Agoralaan Gebouw D - B-3590 Diepenbeek
Kantoor EDM-2.05

---

From: Michael Welzl <[email-masked]>
Date: Fri, 7 Aug 2020 10:49:20 +0200

> On Aug 7, 2020, at 10:17 AM, Robin MARX <[email-masked]> wrote:
> 
> Personally, I would agree that creating a general purpose API just for QUIC would be difficult. 
> I'm mainly thinking about what the interface for steering stream multiplexing/prioritization would look like, seeing as the specs are very light on details for these. 
> Speccing something out for HTTP/3 should be do-able (and is being contemplated by some, e.g., https://github.com/hyperium/h3/pull/1 <https://github.com/hyperium/h3/pull/1>), though potentially not as useful. 
> 
> I would echo Lucas' reference in thinking that abstracting from QUIC to a more high-level view of transport features with something like TAPS is more logical in the long run. 
> Rather than putting all eggs in one basket, it would be good to get at least this one egg into that particular basket imo. 

+1

Lucas mentioned RFC 6458. I regularly used this particular RFC as an example to motivate TAPS prior to its “birth”, as the whole point was to make the job easier for application programmers (while enabling protocol evolution below the API).

We did this by identifying what really must be exposed (vs. what can be automated below an API), as opposed to offering absolutely everything a protocol can do (which is what RFC 6458 does). This led to an analysis of the API-relevant bits of TCP, MPTCP, UDP(-Lite), LEDBAT and SCTP (yes, RFC 6458), in RFCs 8303 and 8304, followed by a systematic approach to throw out things that may be automatable (draft-ietf-taps-minset-11, in the RFC Editor queue). This “minimum set” now forms the core of the current TAPS drafts (the API being in draft-ietf-taps-interface). You may notice that QUIC is missing in the list above, because it was still very much in flux at the time these RFCs were done. However, we’re doing our best to support QUIC in a similar way with TAPS.

Some programmers will want fine grain control of everything - the kind of control that RFC 6458 offers. Indeed, for this, I’d also ask whether defining it all in an RFC is worth the effort. Either way, it’s a different egg.

Cheers,
Michael

> Like Lucas and David, I'm also not sure how common/realistic of a use case the "I want to switch ad-hoc between QUIC implementations" argument will be. 
> To me, a common API would be mostly interesting in writing re-usable high-level coding tutorials and teaching materials to help new devs use the protocol more quickly. 
> On Fri, 7 Aug 2020 at 08:39, Christian Huitema <[email-masked] <mailto:[email-masked]>> wrote:
> 
> www.uhasselt.be <http://www.uhasselt.be/>

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 7 Aug 2020 18:17:36 +0900

+1 to others pointing out that it is difficult to define a common API.

In fact, I would point out that the APIs provided by existing QUIC stacks
are very different. Some QUIC stacks are designed like a layer. Others are
designed like a codec that takes inputs (of bytes) and returns an output
(of bytes). Some QUIC stacks are designed under the assumption that
applications "push" data, whereas other QUIC stacks are designed under the
assumption that the QUIC stacks would "pull" the data from application when
there's room to send something.

There are pros and cons in these approaches, and I do not think it would
be productive to agree on one particular approach through discussion.

At the same time, I would point out sometimes it is inevitable to define a
standard API, and I had assumed that that is happening in WebTransport (on
the W3C side). So maybe people looking for an API can contribute there?

2020年8月7日(金) 17:18 Robin MARX <[email-masked]>:

> contemplated by some, e.g., https://github.com/hyperium/h3/pull/1),
> though potentially not as useful.
>

-- 
Kazuho Oku

---

From: Michael Tuexen <[email-masked]>
Date: Fri, 7 Aug 2020 11:20:09 +0200

> On 7. Aug 2020, at 02:16, Lucas Pardue <[email-masked]> wrote:
> 
> 
> 
> I am all for using TAPS concepts wherever possible, but I am not sure we should put all of our eggs in that basket.
> 
> It's just that looking at RFC 6458 and seeing a 100 page document makes me wonder what would be required to do something for QUIC, who would implement that, and who would pick up the pen.
> 
> It seems like a possible divergent effort from other API work, which seems like a fragmented outcome.
> 
Not sure what the criteria for success is. However, the implementers of SCTP for the
FreeBSD, Linux, and Solaris kernel used this document to come up with an API, which
is supported by the three SCTP kernel implementations. As an implementer, you had a spec
to know the application programmer expects.
You can now write a program and it should compile and run on all three platforms.
After the implementation phase, the document has been used by application program
developers to figure out how they can do what they want. When questions come up,
I regularly point application programmers to the relevant section.

Best regards
Michael
> 
> Also, I think it help would me to understand the incentives. The supposition was about an application wanting to use different QUIC stacks? Curl is already doing this and it doesn't seem too onerous. I'm sure there are other incentives though.
> 
> Lucas 
> 
> 
> 
> 
> 
> On Thu, Aug 6, 2020 at 4:27 PM Lucas Pardue <[email-masked]> wrote:
> On this subject, (speaking as individual) I think it would be useful to define a QUIC application API. SCTP did one (https://datatracker.ietf.org/doc/rfc6458/) and the idea that an application would have to be written separately for each quic implementation is silly.
> 
> > my question is, has any QUIC implementor been thinking along these lines? i
> > believe that the parameters to a QUIC "connect" syscall would be larger and
> > more numerous than for a TCP or SCTP or UDP "connect" syscall, for example.
> 
> most QUIC implementations have an API that is at a high level pretty similar to the socket API, but different in all the details. And they are all different from each other.
> 
> Since you asked about a "connect" equivalent, here is what some of the C stacks offer:
> 
> quant: https://github.com/NTAP/quant/blob/master/lib/include/quant/quant.h#L110-L118
> 
> msquic: https://github.com/microsoft/msquic/blob/master/src/inc/msquic.h#L745-L757
> 
> quicly: https://github.com/h2o/quicly/blob/master/include/quicly.h#L892-L900
> 
> Pretty different.
> 
> Lars

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 7 Aug 2020 13:49:59 +0100

Thanks for the additional context on TAPS and SCTP.

The interesting thing for me in this context is the diversity of current
QUIC implementations in terms of programming language (and language
bindings), operating system support, and design paradigms. Which were
mentioned up thread by others.

Using Cloudflare quiche as an example, it is written in Rust and provides C
bindings. It is independent of UDP socket and operates a bit like Kazuho's
description of a push encoder; the application sets up a QUIC context
(connection), feeds in application-layer data, and is presented a QUIC
packet to be sent. This happens in the application's event loop of choice.

Quiche provides a transport API layer and an HTTP/3 API layer the
integrates on the top. Rust applications that use quiche can use Rust's
network layer and benefit from it's cross platform support; we have example
applications that work across Linux, Windows, MacOS, iOS, Android.
Applications that use the C bindings have more work to do, mainly due to
the difference between UDP socket programming.

There are a already a large collection of QUIC implementations in different
languages and using different paradigms. I think that diversity has
benefits. I struggle to see how defining a common QUIC layer API would
actually work out in practice but maybe I just lack vision.

To give an example, an HTTP application is unlikely to write its own HTTP/3
mapping on top of QUIC. They'll rely on a mapping layer and chances are
that it has a preferred integration with a QUIC layer. It would be
interesting to poll the maintainers of such libraries to see if they
perceive value in substitution, because chances are they are the ones that
would have to rewrite both sides of the API boundary to make this a reality.

Lucas

---

From: "Bajpai, Vaibhav" <[email-masked]>
Date: Fri, 7 Aug 2020 13:15:14 +0000

Hi,

Recent work shows that different implementations behave quite differently:
https://doi.org/10.1145/3405796.3405828

Takeaways of related academic work on QUIC is increasingly becoming a 
function of which implementation(s) was(were) used to perform the study.

It is tricky to study QUIC behaviour for application workload(s) at the 
moment since implementations are so divergent that rewriting the application
using X-different implementations and then repeating the experiments to 
converge to a conclusion is the only choice left. However, QUIC is also a
moving target where snapshot views quicly ;) loose value with time, 
demanding a longitudinal view which makes it even harder.

-- Vaibhav

> On 7. Aug 2020, at 00:57, Martin Duke <[email-masked]> wrote:
> 

------------------------------
Vaibhav Bajpai, www.vaibhavbajpai.com

---

From: Roberto Peon <[email-masked]>
Date: Fri, 7 Aug 2020 16:53:33 +0000

I also believe it is too early to attempt the work of making a common API.

-=R

On 8/7/20, 6:15 AM, "QUIC on behalf of Bajpai, Vaibhav" <[email-masked] on behalf of [email-masked]> wrote:

    Hi,

    Recent work shows that different implementations behave quite differently:
    https://urldefense.proofpoint.com/v2/url?u=https-3A__doi.org_10.1145_3405796.3405828&d=DwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=C0sUo-LFNBaYfyoaCsf6TA&m=J-cKq53K_uZRmp7yK197soYnAI5fVyG0TT-hNubky1Q&s=eHCgEpYrCyhx-s1DW979BYYTi65WBltnE1BAfaO0hak&e= 

    -- Vaibhav

    > On this subject, (speaking as individual) I think it would be useful to define a QUIC application API. SCTP did one (https://urldefense.proofpoint.com/v2/url?u=https-3A__datatracker.ietf.org_doc_rfc6458_&d=DwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=C0sUo-LFNBaYfyoaCsf6TA&m=J-cKq53K_uZRmp7yK197soYnAI5fVyG0TT-hNubky1Q&s=Wcsq-ZFefQPAHDXM4fiBwRjRHGTv8kLCDXZ7_jioJPM&e= ) and the idea that an application would have to be written separately for each quic implementation is silly.

    ------------------------------
    Vaibhav Bajpai, https://urldefense.proofpoint.com/v2/url?u=http-3A__www.vaibhavbajpai.com&d=DwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=C0sUo-LFNBaYfyoaCsf6TA&m=J-cKq53K_uZRmp7yK197soYnAI5fVyG0TT-hNubky1Q&s=boejRSu5kklhMu3KuhXe8w29VXCed6tIMnZMGG40JKA&e=

---

From: Dirkjan Ochtman <[email-masked]>
Date: Mon, 10 Aug 2020 22:34:25 +0200

> On this subject, (speaking as individual) I think it would be useful to define a QUIC application API. SCTP did one (https://datatracker.ietf.org/doc/rfc6458/) and the idea that an application woul…

For what it's worth, for the hyper library (the most popular HTTP
library in the Rust ecosystem) we're trying to define a set of Rust
traits (abstract interfaces) that cover the basic QUIC API insofar as
H3 support needs it.

https://github.com/hyperium/h3/blob/master/design/PROPOSAL.md#4-public-api

Kind regards,

Dirkjan

---

From: Ian Swett <[email-masked]>
Date: Mon, 10 Aug 2020 17:40:35 -0400

+1.  I also believe it's too early.

If analysis and deployment experience show that certain APIs consistently
perform better, then we should gravitate towards them.  I think it's more
likely that each API will have pros and cons depending upon the application
and environment, so there won't be a clear winner.

On Fri, Aug 7, 2020 at 12:55 PM Roberto Peon <fenix=[email-masked]>
wrote:

> On 8/7/20, 6:15 AM, "QUIC on behalf of Bajpai, Vaibhav" <
> [email-masked] on behalf of [email-masked]> wrote:
>
>     Hi,
>
> to define a QUIC application API. SCTP did one (
> https://urldefense.proofpoint.com/v2/url?u=https-3A__datatracker.ietf.org_doc_rfc6458_&d=DwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=C0sUo-LFNBaYfyoaCsf6TA&m=J-cKq53K_uZRmp7yK197soYnAI5fVyG0TT-hNubky1Q&s=Wcsq-ZFefQPAHDXM4fiBwRjRHGTv8kLCDXZ7_jioJPM&e=
> ) and the idea that an application would have to be written separately for
> each quic implementation is silly.
>
>
>     Vaibhav Bajpai,
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.vaibhavbajpai.com&d=DwIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=C0sUo-LFNBaYfyoaCsf6TA&m=J-cKq53K_uZRmp7yK197soYnAI5fVyG0TT-hNubky1Q&s=boejRSu5kklhMu3KuhXe8w29VXCed6tIMnZMGG40JKA&e=
>
>
>