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

refactor: enable mozilla-central http3server to use neqo-bin #1878

Merged
merged 8 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion neqo-bin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use neqo_transport::{

pub mod client;
pub mod server;
mod udp;
pub mod udp;

#[derive(Debug, Parser)]
pub struct SharedArgs {
Expand Down
102 changes: 45 additions & 57 deletions neqo-bin/src/server/old_https.rs → neqo-bin/src/server/http09.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,67 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{
cell::RefCell, collections::HashMap, fmt::Display, path::PathBuf, rc::Rc, time::Instant,
};
use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc, time::Instant};

use neqo_common::{event::Provider, hex, qdebug, qerror, qinfo, qwarn, Datagram};
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay, Cipher};
use neqo_crypto::{generate_ech_keys, random, AllowZeroRtt, AntiReplay};
use neqo_http3::Error;
use neqo_transport::{
server::{ActiveConnectionRef, Server, ValidateAddress},
ConnectionEvent, ConnectionIdGenerator, ConnectionParameters, Output, State, StreamId,
ConnectionEvent, ConnectionIdGenerator, Output, State, StreamId,
};
use regex::Regex;

use super::{qns_read_response, Args, HttpServer};
use super::{qns_read_response, Args};

#[derive(Default)]
struct Http09StreamState {
struct HttpStreamState {
writable: bool,
data_to_send: Option<(Vec<u8>, usize)>,
}

pub struct Http09Server {
pub struct HttpServer {
server: Server,
write_state: HashMap<StreamId, Http09StreamState>,
write_state: HashMap<StreamId, HttpStreamState>,
read_state: HashMap<StreamId, Vec<u8>>,
is_qns_test: bool,
}

impl Http09Server {
impl HttpServer {
pub fn new(
now: Instant,
certs: &[impl AsRef<str>],
protocols: &[impl AsRef<str>],
args: &Args,
anti_replay: AntiReplay,
cid_manager: Rc<RefCell<dyn ConnectionIdGenerator>>,
conn_params: ConnectionParameters,
) -> Result<Self, Error> {
let mut server = Server::new(
args.now(),
&[args.key.clone()],
&[args.shared.alpn.clone()],
anti_replay,
Box::new(AllowZeroRtt {}),
cid_manager,
args.shared.quic_parameters.get(&args.shared.alpn),
)?;

server.set_ciphers(&args.get_ciphers());
server.set_qlog_dir(args.shared.qlog_dir.clone());
if args.retry {
server.set_validation(ValidateAddress::Always);
}
if args.ech {
let (sk, pk) = generate_ech_keys().expect("generate ECH keys");
server
.enable_ech(random::<1>()[0], "public.example", &sk, &pk)
.expect("enable ECH");
let cfg = server.ech_config();
qinfo!("ECHConfigList: {}", hex(cfg));
}
larseggert marked this conversation as resolved.
Show resolved Hide resolved

Ok(Self {
server: Server::new(
now,
certs,
protocols,
anti_replay,
Box::new(AllowZeroRtt {}),
cid_manager,
conn_params,
)?,
server,
write_state: HashMap::new(),
read_state: HashMap::new(),
is_qns_test: args.shared.qns_test.is_some(),
})
}

Expand Down Expand Up @@ -92,20 +105,15 @@ impl Http09Server {
} else {
self.write_state.insert(
stream_id,
Http09StreamState {
HttpStreamState {
writable: false,
data_to_send: Some((resp, 0)),
},
);
}
}

fn stream_readable(
&mut self,
stream_id: StreamId,
conn: &mut ActiveConnectionRef,
args: &Args,
) {
fn stream_readable(&mut self, stream_id: StreamId, conn: &mut ActiveConnectionRef) {
if !stream_id.is_client_initiated() || !stream_id.is_bidi() {
qdebug!("Stream {} not client-initiated bidi, ignoring", stream_id);
return;
Expand Down Expand Up @@ -136,7 +144,7 @@ impl Http09Server {
return;
};

let re = if args.shared.qns_test.is_some() {
let re = if self.is_qns_test {
Regex::new(r"GET +/(\S+)(?:\r)?\n").unwrap()
} else {
Regex::new(r"GET +/(\d+)(?:\r)?\n").unwrap()
Expand All @@ -150,7 +158,7 @@ impl Http09Server {
let resp = {
let path = path.as_str();
qdebug!("Path = '{path}'");
if args.shared.qns_test.is_some() {
if self.is_qns_test {
match qns_read_response(path) {
Ok(data) => Some(data),
Err(e) => {
Expand Down Expand Up @@ -194,12 +202,12 @@ impl Http09Server {
}
}

impl HttpServer for Http09Server {
impl super::HttpServer for HttpServer {
fn process(&mut self, dgram: Option<&Datagram>, now: Instant) -> Output {
self.server.process(dgram, now)
}

fn process_events(&mut self, args: &Args, now: Instant) {
fn process_events(&mut self, now: Instant) {
let active_conns = self.server.active_connections();
for mut acr in active_conns {
loop {
Expand All @@ -210,10 +218,10 @@ impl HttpServer for Http09Server {
match event {
ConnectionEvent::NewStream { stream_id } => {
self.write_state
.insert(stream_id, Http09StreamState::default());
.insert(stream_id, HttpStreamState::default());
}
ConnectionEvent::RecvStreamReadable { stream_id } => {
self.stream_readable(stream_id, &mut acr, args);
self.stream_readable(stream_id, &mut acr);
}
ConnectionEvent::SendStreamWritable { stream_id } => {
self.stream_writable(stream_id, &mut acr);
Expand All @@ -233,32 +241,12 @@ impl HttpServer for Http09Server {
}
}

fn set_qlog_dir(&mut self, dir: Option<PathBuf>) {
self.server.set_qlog_dir(dir);
}

fn validate_address(&mut self, v: ValidateAddress) {
self.server.set_validation(v);
}

fn set_ciphers(&mut self, ciphers: &[Cipher]) {
self.server.set_ciphers(ciphers);
}

fn enable_ech(&mut self) -> &[u8] {
let (sk, pk) = generate_ech_keys().expect("generate ECH keys");
self.server
.enable_ech(random::<1>()[0], "public.example", &sk, &pk)
.expect("enable ECH");
self.server.ech_config()
}

fn has_events(&self) -> bool {
self.server.has_active_connections()
}
}

impl Display for Http09Server {
impl Display for HttpServer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Http 0.9 server ")
}
Expand Down
Loading
Loading