Skip to content

Commit 3fcbb3e

Browse files
ivilaDemesneGH
authored andcommitted
examples: update tcp_client-rs and udp_socket-rs to support no_std
- add ipv6 call in tcp_client-rs and udp_socket-rs - enable no_std run of tcp_client-rs and udp_socket-rs in ci Signed-off-by: ivila <390810839@qq.com> Reviewed-by: Yuan Zhuang <yuanz@apache.org> Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
1 parent a709820 commit 3fcbb3e

18 files changed

Lines changed: 230 additions & 102 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ branch (`main`), please refer to the
8181
- **Common**: See
8282
[Overview of OP-TEE Rust Examples](https://teaclave.apache.org/trustzone-sdk-docs/overview-of-optee-rust-examples/).
8383

84-
- **`no-std`**: Excludes `test_serde`, `test_tcp_client`, `test_udp_socket`,
85-
`test_message_passing_interface`, `test_tls_client`, `test_tls_server`.
84+
- **`no-std`**: Excludes `test_serde`, `test_message_passing_interface`,
85+
`test_tls_client`, `test_tls_server`.
8686

8787

8888
## Quick Start with the OP-TEE Repo for QEMUv8

ci/ci.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ pushd ../tests
3535
./test_signature_verification.sh
3636
./test_supp_plugin.sh
3737
./test_error_handling.sh
38+
./test_tcp_client.sh
39+
./test_udp_socket.sh
3840

3941
# Run std only tests
4042
if [ "$STD" ]; then
4143
./test_serde.sh
4244
./test_message_passing_interface.sh
43-
./test_tcp_client.sh
44-
./test_udp_socket.sh
4545
./test_tls_client.sh
4646
./test_tls_server.sh
4747
./test_eth_wallet.sh

examples/tcp_client-rs/host/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ edition = "2018"
2828
libc = "0.2.48"
2929
proto = { path = "../proto" }
3030
optee-teec = { path = "../../../optee-teec" }
31+
tiny_http = "0.12.0"
3132

3233
[profile.release]
3334
lto = true

examples/tcp_client-rs/host/Makefile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,7 @@ LINKER_CFG := target.$(TARGET).linker=\"$(CROSS_COMPILE)gcc\"
2424

2525
OUT_DIR := $(CURDIR)/target/$(TARGET)/release
2626

27-
ifeq ($(STD),)
28-
all:
29-
@echo "Please \`export STD=y\` then rerun \`source environment\` to build the STD version"
30-
else
3127
all: host strip
32-
endif
3328

3429
host:
3530
@cargo build --target $(TARGET_HOST) --release --config $(LINKER_CFG)

examples/tcp_client-rs/host/src/main.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,33 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use optee_teec::ParamNone;
19-
use optee_teec::{Context, Operation, Session, Uuid};
20-
use proto::{Command, UUID};
18+
use std::net::{Ipv6Addr, SocketAddr, SocketAddrV6};
19+
use std::thread;
2120

22-
fn tcp_client(session: &mut Session) -> optee_teec::Result<()> {
23-
let mut operation = Operation::new(0, ParamNone, ParamNone, ParamNone, ParamNone);
21+
use optee_teec::{Context, Operation, ParamType, Session, Uuid};
22+
use optee_teec::{ParamNone, ParamTmpRef, ParamValue};
23+
use proto::{Command, IpVersion, UUID};
24+
25+
fn tcp_client(
26+
session: &mut Session,
27+
address: &str,
28+
port: u16,
29+
ip_version: IpVersion,
30+
host_name: &str,
31+
) -> optee_teec::Result<()> {
32+
println!("Test on: {}", address);
33+
34+
let http_data = format!("GET / HTTP/1.0\r\nHost: {}\r\n\r\n", host_name);
35+
let mut operation = Operation::new(
36+
0,
37+
ParamTmpRef::new_input(address.as_bytes()),
38+
ParamValue::new(port as u32, ip_version as u32, ParamType::ValueInput),
39+
ParamTmpRef::new_input(http_data.as_bytes()),
40+
ParamNone,
41+
);
2442
session.invoke_command(Command::Start as u32, &mut operation)?;
43+
44+
println!("Success");
2545
Ok(())
2646
}
2747

@@ -30,8 +50,36 @@ fn main() -> optee_teec::Result<()> {
3050
let uuid = Uuid::parse_str(UUID).unwrap();
3151
let mut session = ctx.open_session(uuid)?;
3252

33-
tcp_client(&mut session)?;
53+
// test ipv4
54+
const IPV4_HOST: &str = "teaclave.apache.org";
55+
// Use the host directly to also check its domain name resolving capability.
56+
tcp_client(&mut session, IPV4_HOST, 80, IpVersion::V4, IPV4_HOST)?;
57+
58+
// test ipv6
59+
let addr = SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 0, 0, 0));
60+
let server = tiny_http::Server::http(addr).unwrap();
61+
let listen_addr = server.server_addr().to_ip().unwrap();
62+
let ip = listen_addr.ip().to_string();
63+
let port = listen_addr.port();
64+
65+
let child = thread::spawn(move || {
66+
for request in server.incoming_requests() {
67+
println!(
68+
"received request! method: {:?}, url: {:?}, headers: {:?}",
69+
request.method(),
70+
request.url(),
71+
request.headers()
72+
);
73+
74+
let response = tiny_http::Response::from_string("hello world");
75+
request.respond(response).unwrap();
76+
break;
77+
}
78+
});
79+
// Use the IP address directly to ensure we're actually trying an IPv6
80+
// address.
81+
tcp_client(&mut session, &ip, port, IpVersion::V6, &ip)?;
82+
let _ = child.join();
3483

35-
println!("Success");
3684
Ok(())
3785
}

examples/tcp_client-rs/proto/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ description = "Data structures and functions shared by host and TA."
2525
edition = "2018"
2626

2727
[dependencies]
28+
num_enum = { version = "0.7.3", default-features = false }
2829

2930
[build-dependencies]
3031
uuid = { version = "1.8", default-features = false }

examples/tcp_client-rs/proto/src/lib.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@
1414
// KIND, either express or implied. See the License for the
1515
// specific language governing permissions and limitations
1616
// under the License.
17+
#![no_std]
18+
use num_enum::{FromPrimitive, TryFromPrimitive, IntoPrimitive};
1719

20+
#[derive(FromPrimitive, IntoPrimitive)]
21+
#[repr(u32)]
1822
pub enum Command {
1923
Start,
24+
#[default]
2025
Unknown,
2126
}
2227

23-
impl From<u32> for Command {
24-
#[inline]
25-
fn from(value: u32) -> Command {
26-
match value {
27-
0 => Command::Start,
28-
_ => Command::Unknown,
29-
}
30-
}
28+
#[derive(TryFromPrimitive, IntoPrimitive)]
29+
#[repr(u32)]
30+
pub enum IpVersion {
31+
V4 = 1,
32+
V6 = 2,
3133
}
3234

3335
pub const UUID: &str = &include_str!(concat!(env!("OUT_DIR"), "/uuid.txt"));

examples/tcp_client-rs/ta/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ edition = "2018"
2828
proto = { path = "../proto" }
2929
optee-utee-sys = { path = "../../../optee-utee/optee-utee-sys" }
3030
optee-utee = { path = "../../../optee-utee" }
31+
cfg_block = "0.2.0"
3132

3233
[build-dependencies]
3334
proto = { path = "../proto" }
3435
optee-utee-build = { path = "../../../optee-utee-build" }
3536

3637
[profile.release]
3738
panic = "abort"
38-
lto = false
39+
lto = true
3940
opt-level = 1

examples/tcp_client-rs/ta/Makefile

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,12 @@ TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem
2929
SIGN := $(TA_DEV_KIT_DIR)/scripts/sign_encrypt.py
3030
OUT_DIR := $(CURDIR)/target/$(TARGET)/release
3131

32-
ifeq ($(STD),)
33-
all:
34-
@echo "Please \`export STD=y\` then rerun \`source environment\` to build the STD version"
35-
else
32+
BUILDER = $(if $(STD),xargo,cargo)
33+
3634
all: ta strip sign
37-
endif
3835

3936
ta:
40-
@xargo build --target $(TARGET) --release --config $(LINKER_CFG)
37+
@$(BUILDER) build --target $(TARGET) --release --config $(LINKER_CFG)
4138

4239
strip: ta
4340
@$(OBJCOPY) --strip-unneeded $(OUT_DIR)/ta $(OUT_DIR)/stripped_ta

examples/tcp_client-rs/ta/src/main.rs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,28 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
#![cfg_attr(not(target_os = "optee"), no_std)]
1819
#![no_main]
1920

21+
cfg_block::cfg_block! {
22+
// In Teaclave, if target_os = "optee", the codes is compiled with std.
23+
// Otherwise, no-std
24+
if #[cfg(target_os = "optee")] {
25+
use std::io::{Read, Write};
26+
} else {
27+
extern crate alloc;
28+
use optee_utee::net::{StdCompatConnect, StdCompatWrite, StdCompatRead};
29+
use alloc::vec::Vec;
30+
use alloc::string::String;
31+
}
32+
}
33+
2034
use optee_utee::net::TcpStream;
2135
use optee_utee::{
2236
ta_close_session, ta_create, ta_destroy, ta_invoke_command, ta_open_session, trace_println,
2337
};
2438
use optee_utee::{Error, ErrorKind, Parameters, Result};
25-
use proto::Command;
26-
use std::io::Read;
27-
use std::io::Write;
39+
use proto::{Command, IpVersion};
2840

2941
#[ta_create]
3042
fn create() -> Result<()> {
@@ -49,35 +61,59 @@ fn destroy() {
4961
}
5062

5163
#[ta_invoke_command]
52-
fn invoke_command(cmd_id: u32, _params: &mut Parameters) -> Result<()> {
64+
fn invoke_command(cmd_id: u32, params: &mut Parameters) -> Result<()> {
5365
trace_println!("[+] TA invoke command");
5466
match Command::from(cmd_id) {
5567
Command::Start => {
56-
tcp_client();
57-
Ok(())
68+
use core::convert::TryFrom;
69+
70+
let mut param0 = unsafe { params.0.as_memref()? };
71+
let param1 = unsafe { params.1.as_value()? };
72+
let mut param2 = unsafe { params.2.as_memref()? };
73+
74+
let address = core::str::from_utf8(param0.buffer()).unwrap();
75+
let port = param1.a() as u16;
76+
let ip_version =
77+
IpVersion::try_from(param1.b()).map_err(|_| ErrorKind::BadParameters)?;
78+
let http_data = param2.buffer();
79+
80+
tcp_client(address, port, ip_version, http_data)
5881
}
5982
_ => Err(Error::new(ErrorKind::BadParameters)),
6083
}
6184
}
6285

63-
fn tcp_client() {
64-
let mut stream = TcpStream::connect("teaclave.apache.org", 80).unwrap();
65-
stream
66-
.write_all(b"GET / HTTP/1.0\r\nHost: teaclave.apache.org\r\n\r\n")
67-
.unwrap();
86+
fn tcp_client(address: &str, port: u16, ip_version: IpVersion, http_data: &[u8]) -> Result<()> {
87+
let mut stream = match ip_version {
88+
IpVersion::V4 => TcpStream::connect_v4(address, port),
89+
IpVersion::V6 => TcpStream::connect_v6(address, port),
90+
}
91+
.map_err(|err| {
92+
trace_println!("failed to connect to {}:{} due to {:?}", address, port, err);
93+
ErrorKind::Generic
94+
})?;
95+
96+
stream.set_send_timeout_in_milli(60 * 1000);
97+
stream.set_recv_timeout_in_milli(60 * 1000);
98+
99+
stream.write_all(http_data).map_err(|err| {
100+
trace_println!("failed to write_all due to {:?}", err);
101+
ErrorKind::Generic
102+
})?;
68103
let mut response = Vec::new();
69104
let mut chunk = [0u8; 1024];
70105
loop {
71106
match stream.read(&mut chunk) {
72107
Ok(0) => break,
73108
Ok(n) => response.extend_from_slice(&chunk[..n]),
74-
Err(_) => {
75-
trace_println!("Error");
76-
panic!();
109+
Err(err) => {
110+
trace_println!("failed to read due to {:?}", err);
111+
return Err(ErrorKind::Generic.into());
77112
}
78113
}
79114
}
80115
trace_println!("{}", String::from_utf8_lossy(&response));
116+
Ok(())
81117
}
82118

83119
include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs"));

0 commit comments

Comments
 (0)