Skip to content

Commit

Permalink
Merge pull request #399 from Tencent/release/v1.3.0
Browse files Browse the repository at this point in the history
Release/v1.3.0
  • Loading branch information
iyangsj authored Oct 10, 2024
2 parents 50ed3c5 + 3d87c37 commit 875c94c
Show file tree
Hide file tree
Showing 18 changed files with 256 additions and 34 deletions.
7 changes: 7 additions & 0 deletions .cargo/aarch64-unknown-linux-ohos-clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

exec ${OHOS_NDK_HOME}/native/llvm/bin/clang \
-target aarch64-linux-ohos \
--sysroot=${OHOS_NDK_HOME}/native/sysroot \
-D__MUSL__ \
"$@"
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[target.aarch64-unknown-linux-ohos]
ar = "${OHOS_NDK_HOME}/native/llvm/bin/llvm-ar"
linker = ".cargo/aarch64-unknown-linux-ohos-clang.sh"
24 changes: 24 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,30 @@ jobs:
env:
ANDROID_NDK_HOME: ${{ github.workspace }}/android-ndk-r${{ env.NDK_LTS_VER }}

build_harmony:
name: Build for Harmony
runs-on: ubuntu-latest
env:
TARGET: "aarch64-unknown-linux-ohos"
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Install rust toolchain
run: rustup target add ${{ env.TARGET }}
- name: Download OHOS NDK
run: |
wget https://repo.huaweicloud.com/openharmony/os/4.0-Release/ohos-sdk-windows_linux-public.tar.gz
tar -xvzf ohos-sdk-windows_linux-public.tar.gz
cd ohos-sdk/linux/
unzip -q native-linux-x64-4.0.10.13-Release.zip
- name: Run cargo build
run: |
OHOS_NDK_HOME=${{ github.workspace }}/ohos-sdk/linux/ \
CC_aarch64_unknown_linux_ohos=${OHOS_NDK_HOME}/native/llvm/bin/clang \
AR_aarch64_unknown_linux_ohos=${OHOS_NDK_HOME}/native/llvm/bin/llvm-ar \
cargo build --target ${{ env.TARGET }} --verbose --features ffi --release

static_analysis:
name: Static analysis
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/tquic-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ jobs:
run: |
cd tools/tests/
bash ./tquic_tools_test.sh -b ../../target/release/ -t multipath_redundant,multipath_minrtt,multipath_roundrobin -f 1000M -p 5
- name: Run integration tests for disable_1rtt_encryption
run: |
cd tools/tests/
bash ./tquic_tools_test.sh -b ../../target/debug/ -t multipath_roundrobin -c '~~disable-encryption' -s '~~disable-encryption'

10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [v1.3.0] - 2024-10-10

### Added
- Support building for HarmonyOS
- Support disable_1rtt_encryption transport parameter
- Support sending 1-RTT packets on the server before handshake completion
- Resolve new issues found by cargo clippy


## [v1.2.0] - 2024-09-26

### Added
Expand Down Expand Up @@ -310,6 +319,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Provide example clients and servers.


[v1.3.0]: https://github.com/tencent/tquic/compare/v1.2.0...v1.3.0
[v1.2.0]: https://github.com/tencent/tquic/compare/v1.1.0...v1.2.0
[v1.1.0]: https://github.com/tencent/tquic/compare/v1.0.0...v1.1.0
[v1.0.0]: https://github.com/tencent/tquic/compare/v0.15.0...v1.0.0
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tquic"
version = "1.2.0"
version = "1.3.0"
edition = "2021"
rust-version = "1.70.0"
license = "Apache-2.0"
Expand Down
8 changes: 8 additions & 0 deletions include/tquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,14 @@ void quic_config_set_zerortt_buffer_size(struct quic_config_t *config, uint16_t
*/
void quic_config_set_max_undecryptable_packets(struct quic_config_t *config, uint16_t v);

/**
* Enable or disable encryption on 1-RTT packets. (Experimental)
* The default value is true.
* WARN: The The disable_1rtt_encryption extension is not meant to be used
* for any practical application protocol on the open internet.
*/
void quic_config_enable_encryption(struct quic_config_t *config, bool v);

/**
* Create a new TlsConfig.
* The caller is responsible for the memory of the TlsConfig and should properly
Expand Down
24 changes: 24 additions & 0 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const CMAKE_PARAMS_IOS: &[(&str, &[(&str, &str)])] = &[
),
];

/// Additional parameters for Ohos
const CMAKE_PARAMS_OHOS_NDK: &[(&str, &[(&str, &str)])] =
&[("aarch64", &[("OHOS_ARCH", "arm64-v8a")])];

/// Create a cmake::Config for building BoringSSL.
fn new_boringssl_cmake_config() -> cmake::Config {
let target = std::env::var("TARGET").unwrap();
Expand Down Expand Up @@ -101,6 +105,26 @@ fn new_boringssl_cmake_config() -> cmake::Config {
}
}

"linux" => {
if target.ends_with("ohos") {
for (ohos_arch, params) in CMAKE_PARAMS_OHOS_NDK {
if *ohos_arch == arch {
for (name, value) in *params {
boringssl_cmake.define(name, value);
}
break;
}
}

let ohos_ndk_home = std::env::var("OHOS_NDK_HOME")
.expect("Please set OHOS_NDK_HOME for Harmony build");
let ohos_ndk_home = std::path::Path::new(&ohos_ndk_home);
let toolchain_file = ohos_ndk_home.join("native/build/cmake/ohos.toolchain.cmake");
let toolchain_file = toolchain_file.to_str().unwrap();
boringssl_cmake.define("CMAKE_TOOLCHAIN_FILE", toolchain_file);
}
}

_ => (),
};

Expand Down
87 changes: 73 additions & 14 deletions src/connection/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,9 @@ impl Connection {
return Ok(read + length);
}
};
packet::decrypt_header(buf, pkt_num_offset, &mut hdr, key).map_err(|_| Error::Done)?;
let is_encryption_disabled = self.is_encryption_disabled(hdr.pkt_type);
packet::decrypt_header(buf, pkt_num_offset, &mut hdr, key, is_encryption_disabled)
.map_err(|_| Error::Done)?;

// Decode packet sequence number
let handshake_confirmed = self.is_confirmed();
Expand Down Expand Up @@ -564,9 +566,12 @@ impl Connection {
&hdr,
space,
)?;
let mut payload =
let mut payload = if !is_encryption_disabled {
packet::decrypt_payload(buf, payload_offset, payload_len, cid_seq, pkt_num, key)
.map_err(|_| Error::Done)?;
.map_err(|_| Error::Done)?
} else {
bytes::Bytes::copy_from_slice(&buf[payload_offset..payload_offset + payload_len])
};
if payload.is_empty() {
// An endpoint MUST treat receipt of a packet containing no frames as a connection error
// of type PROTOCOL_VIOLATION.
Expand Down Expand Up @@ -1187,6 +1192,15 @@ impl Connection {
self.events.add(Event::ResetTokenAdvertised(reset_token));
}

// The connection enters disable_1rtt_encryption mode
if peer_params.disable_encryption && self.local_transport_params.disable_encryption {
self.flags.insert(DisableEncryption);
debug!(
"{} encryption on 1-RTT packets has been negotiated to be disabled",
self.trace_id
);
}

self.set_peer_trans_params(peer_params)?;
self.flags.insert(AppliedPeerTransportParams);

Expand Down Expand Up @@ -1729,16 +1743,20 @@ impl Connection {
cid_seq = Some(dcid_seq as u32);
}

let written = packet::encrypt_packet(
out,
cid_seq,
pkt_num,
pkt_num_len,
payload_len,
payload_offset,
None,
key,
)?;
let written = if !self.is_encryption_disabled(hdr.pkt_type) {
packet::encrypt_packet(
out,
cid_seq,
pkt_num,
pkt_num_len,
payload_len,
payload_offset,
None,
key,
)?
} else {
payload_offset + payload_len
};

let sent_pkt = space::SentPacket {
pkt_type,
Expand Down Expand Up @@ -3022,7 +3040,13 @@ impl Connection {
// If there are sendable, reset, stopped, almost full, blocked streams,
// or need to update concurrency limits, use the 0RTT/1RTT packet.
let path = self.paths.get(pid)?;
if (self.is_established() || self.tls_session.is_in_early_data())
if (self.is_established()
// Note: The server's use of 1-RTT keys before the handshake is
// complete is limited to sending data. BoringSSL will provide 1-RTT
// write secret until the handshake is complete.
// See RFC 9001 Section 5.7
|| self.tls_session.get_keys(Level::OneRTT).seal.is_some()
|| self.tls_session.is_in_early_data())
&& (self.need_send_handshake_done_frame()
|| self.need_send_new_token_frame()
|| self.local_error.as_ref().map_or(false, |e| e.is_app)
Expand Down Expand Up @@ -3299,6 +3323,11 @@ impl Connection {
Some(idle_timeout)
}

/// Whether encryption on the specified packet type should be disabled
fn is_encryption_disabled(&self, pkt_type: PacketType) -> bool {
pkt_type == PacketType::OneRTT && self.flags.contains(DisableEncryption)
}

/// Check whether the connection is a server connection.
pub fn is_server(&self) -> bool {
self.is_server
Expand Down Expand Up @@ -4366,6 +4395,9 @@ enum ConnectionFlags {

/// The multipath extension is successfully negotiated.
EnableMultipath = 1 << 20,

/// The disable_1rtt_encryption is successfully negotiated.
DisableEncryption = 1 << 21,
}

/// Statistics about a QUIC connection.
Expand Down Expand Up @@ -5668,6 +5700,33 @@ pub(crate) mod tests {
Ok(())
}

#[test]
fn handshake_with_disable_encryption_negotiated() -> Result<()> {
let cases = [
// The items in each case are as following:
// - client disable_encryption
// - server disable_encryption
// - disable_encryption negotiation result
//(true, false, false),
//(false,false, false),
//(false, true, false),
(true, true, true),
];
for case in cases {
let mut client_config = TestPair::new_test_config(false)?;
client_config.enable_encryption(!case.0);
let mut server_config = TestPair::new_test_config(true)?;
server_config.enable_encryption(!case.1);

let mut test_pair = TestPair::new(&mut client_config, &mut server_config)?;
assert_eq!(test_pair.handshake(), Ok(()));
assert_eq!(test_pair.client.flags.contains(DisableEncryption), case.2);
assert_eq!(test_pair.server.flags.contains(DisableEncryption), case.2);
}

Ok(())
}

#[test]
fn max_datagram_size() -> Result<()> {
let mut client_config = TestPair::new_test_config(false)?;
Expand Down
20 changes: 20 additions & 0 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2719,6 +2719,26 @@ mod tests {
Ok(())
}

#[test]
fn transfer_single_stream_disable_encryption() -> Result<()> {
let mut t = TestPair::new();

let mut cli_conf = TestPair::new_test_config(false)?;
cli_conf.enable_encryption(false);
let mut srv_conf = TestPair::new_test_config(true)?;
srv_conf.enable_encryption(false);

let mut case_conf = CaseConf::default();
case_conf.session = Some(TestPair::new_test_session_state());
case_conf.client_0rtt_expected = true;
case_conf.resumption_expected = true;
case_conf.request_num = 1;
case_conf.request_size = 1024 * 16;

t.run(cli_conf, srv_conf, case_conf)?;
Ok(())
}

#[test]
fn transfer_multi_stream_normal() -> Result<()> {
let mut t = TestPair::new();
Expand Down
11 changes: 10 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,15 @@ pub extern "C" fn quic_config_set_max_undecryptable_packets(config: &mut Config,
config.set_max_undecryptable_packets(v as usize);
}

/// Enable or disable encryption on 1-RTT packets. (Experimental)
/// The default value is true.
/// WARN: The The disable_1rtt_encryption extension is not meant to be used
/// for any practical application protocol on the open internet.
#[no_mangle]
pub extern "C" fn quic_config_enable_encryption(config: &mut Config, v: bool) {
config.enable_encryption(v);
}

/// Create a new TlsConfig.
/// The caller is responsible for the memory of the TlsConfig and should properly
/// destroy it by calling `quic_tls_config_free`.
Expand Down Expand Up @@ -823,7 +832,7 @@ pub extern "C" fn quic_endpoint_new(
context: sender_ctx,
});
let e = Endpoint::new(config.clone(), is_server, handler, sender);
Box::into_raw(config);
let _ = Box::into_raw(config);
Box::into_raw(Box::new(e))
}

Expand Down
10 changes: 9 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const RESET_TOKEN_LEN: usize = 16;

/// For the Stateless Reset to appear as a valid QUIC packet, the Unpredictable
/// Bits field needs to include at least 38 bits of data. The minimum length of
/// a Statless Reset Packet is 21 bytes.
/// a Stateless Reset Packet is 21 bytes.
const MIN_RESET_PACKET_LEN: usize = 21;

/// Assuming the maximum possible connection ID and packet number size, the 1RTT
Expand Down Expand Up @@ -735,6 +735,14 @@ impl Config {
}
}

/// Enable or disable encryption on 1-RTT packets. (Experimental)
/// The default value is true.
/// WARN: The The disable_1rtt_encryption extension is not meant to be used
/// for any practical application protocol on the open internet.
pub fn enable_encryption(&mut self, v: bool) {
self.local_transport_params.disable_encryption = !v;
}

/// Set TLS config.
pub fn set_tls_config(&mut self, tls_config: tls::TlsConfig) {
self.set_tls_config_selector(Arc::new(tls::DefaultTlsConfigSelector {
Expand Down
Loading

0 comments on commit 875c94c

Please sign in to comment.