Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0-rtt support #213

Open
Tracked by #2422
ktprime opened this issue Oct 23, 2023 · 10 comments
Open
Tracked by #2422

0-rtt support #213

ktprime opened this issue Oct 23, 2023 · 10 comments

Comments

@ktprime
Copy link

ktprime commented Oct 23, 2023

can server/client save the cfg/session file to use 0-rtt ?

@martenrichter
Copy link
Member

Can you give some additional information? May be a pointer to the spec....

@ktprime
Copy link
Author

ktprime commented Oct 23, 2023

I know how to set/reuse 0-rtt session only google-quic version(Q043-Q050), but I have no any ideal to ietf quic version.

void QuicSessionEntry::OnCryptoHandshakeComplete()
{
    if (conn_state_ == QuicSessionState::QuicSessionState_Connected)
        return;

    //TODO:if tls serssion.
    if (statics_.use_text >= 0 || config_.quic_version > quic::QUIC_VERSION_50)
    {
        const auto head_protect = config_.quic_version >= quic::QUIC_VERSION_50 ? 12 : 0;
        auto level = ENCRYPTION_FORWARD_SECURE;
        auto* qconnection = qsession_->connection();
        //DebugPrint(dbg_event, " ====== set text %d ===== ", statics_.use_text);

        qconnection->SetEncrypter(level,
                std::make_unique<quic_sdk::TextEncrypter>(qconnection->perspective(), true, head_protect));
        qconnection->SetAlternativeDecrypter(level,
                std::make_unique<quic_sdk::TextDecrypter>(qconnection->perspective(), true, head_protect), false);
    }

    conn_state_ = QuicSessionState::QuicSessionState_Connected;
    has_connected_ = true;

    statics_.hands_time = int(CLOCK_NOWCMS - last_contime_);
    auto num_sent_client_hellos = statics_.hands_rtts;
    auto* ep = packet_transport_->GetPoller();

    if (IsServer()) {
#if HYB_QUIC_SERVER
#ifndef DELAY_NOTIFY_SERVERCON
        ep->NotifyListeren(Fd(), udp_socket_);
#endif
        if (config_.use_0rtt && gserver_cfg_.empty()) {
            gserver_cfg_ = session_factory_->getCryptoServerConfig()->serialized_crypto_config;
            if (QuicHasOption(cfg_file_session_key) == 0)
               WriteString2File("server_config.cfg", gserver_cfg_); //save server 0-rtt session
        }
#endif
    } else {
        ConnectionManager().UpdateTimeOut(Fd(), connection_id());
        if (num_sent_client_hellos > 1 && config_.use_0rtt) {
           ((quic::QuartcClientSession*)qsession_)->get_server_config(server_cfg_);
            WriteString2File("client_config.cfg", server_cfg_); // //save client 0-rtt session
        }
        ep->AddPollEvent(QPOLLOUT, this);
        early_data_.clear();
    }

    server_cfg_.clear(); //never used again.
    LogPrint("%d-RTT hands_time:%d ms, text = %d", num_sent_client_hellos, statics_.hands_time, statics_.use_text);
}


@martenrichter
Copy link
Member

Ok, what is the use case for Webtransport. Probably mainly for the server, if it is for the client, where is it in the spec for the WebTransport web javascript interface.

Is it just to save the crypto config of the server or client for later?
I currently have no clue about the use case and what change of interface would be needed.

@ktprime
Copy link
Author

ktprime commented Oct 23, 2023

the crypto config can also be saved in memory for web server/client?
it's seem the Http3SessionCache need to be inited by 0-rtt use (from memory crypto cache or file ?)

  void Insert(const QuicServerId& server_id,
              bssl::UniquePtr<SSL_SESSION> session,
              const TransportParameters& params,
              const ApplicationState* application_state) override;

@martenrichter
Copy link
Member

Yes, but what will be the use case? That I need to understand how to draft an API for this feature (and also for deciding, if I want to support it).

@achingbrain
Copy link
Contributor

I've just come across this problem as well.

I'm trying to accept connections from webtransport-go clients that use quic-go's EarlyConnection feature, eg:

https://github.com/libp2p/go-libp2p/blob/0385ec924bad172f74a74db09939e97c079b1420/p2p/transport/webtransport/transport.go#L205-L219

I'm trying to create a simple reproduction, it's something like:

package main

import (
	"context"
	"crypto/tls"
	_ "embed"
	"fmt"
	"log"

	"github.com/quic-go/quic-go"
	"github.com/quic-go/webtransport-go"
)

func main() {
	addr := "127.0.0.1:35909"
	url := "https://127.0.0.1:35909"
	ctx := context.Background()

    // n.b. need to load the server cert here if it's self-signed
	tlsConf := &tls.Config{}
	quicConf := &quic.Config{}

	earlyConn, err := quic.DialAddrEarly(ctx, addr, tlsConf, quicConf)
	if err != nil {
		log.Fatal(err)
	}

	dialer := webtransport.Dialer{
		DialAddr: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
			return earlyConn.(quic.EarlyConnection), nil
		},
		QUICConfig: quicConf.Clone(),
	}
	rsp, sess, err := dialer.Dial(ctx, url, nil)
	if err != nil {
		log.Fatal(err)
	}
	if rsp.StatusCode < 200 || rsp.StatusCode > 299 {
		err := fmt.Errorf("invalid response status code from %s : %d", url, rsp.StatusCode)
		log.Fatal(err)
	}

	//...do something with sess
}

The client always gets a 404 from a @fails-components/webtransport-transport-http3-quiche server.

From what I can see the request gets to this line but there's no WebTransport session yet so it continues to this line and a 404 is returned.

@achingbrain
Copy link
Contributor

The use case is transferring small amounts of data - connection establishment ends up adding significant overhead when the expected data payload is small so 0-RTT makes this much more viable.

@martenrichter
Copy link
Member

I am not sure if it is the same thing.
The issue was regarding reusing the stored data for 0-rtt between different server starts.
You seem to want to reuse a WebTransport session from a previous connection.
Can you point me to the part of the WebTransport protocol spec where it says this should be possible?
I would think that a new WebTransport Session stream has to be established in the 0-rtt case, or should old streams be reused?
Currently, I have no idea, how I should it implement it, following the spec.

@martenrichter
Copy link
Member

I have read a little more in the specs you find in [https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3-07:

Clients cannot initiate WebTransport in 0-RTT packets, as the CONNECT method is not considered safe; see Section 10.9 of [HTTP3]. However, WebTransport-related SETTINGS parameters may be retained from the previous session as described in Section 7.2.4.2 of [HTTP3]. If the server accepts 0-RTT, the server MUST NOT reduce the limit of maximum open WebTransport sessions from the one negotiated during the previous session; such change would be deemed incompatible, and MUST result in a H3_SETTINGS_ERROR connection error.

Older revisions state that it is impossible to use 0-rtt at all.
It still sounds like WebTransport may not be possible or is limited in 0-rtt connections.
Anyway, I still have no clue how to act in this case, as the specification does not spell out this case. The second thing is that I rely on the support of this feature in the underlying libquiche, and I also have no clue if it supports this case. So without more information, I can not do anything, and it might not be inside the spec or unsafe.

@martenrichter
Copy link
Member

You can look at:
https://github.com/google/quiche/blob/065baa708f81459a4c86712945df629edd056ab6/quiche/quic/core/http/quic_spdy_stream.cc#L1342
This is the code, that determines, if it is a web_transport() is set. So basically, if you get a 404, it means, that you do not fulfill the requirements in this piece of code or that it is not executed. (It basically checks the headers of the connect message, if it has protocol and method set right).
Furthermore this call https://github.com/google/quiche/blob/065baa708f81459a4c86712945df629edd056ab6/quiche/quic/core/http/quic_spdy_stream.cc#L1343 checks, the conditions here:
https://github.com/google/quiche/blob/065baa708f81459a4c86712945df629edd056ab6/quiche/quic/core/http/quic_spdy_session.cc#L1774

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants