forked from arceos-org/arceos
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net: add TcpListener & TcpStream APIs
- Loading branch information
1 parent
2702ffa
commit 4d834f8
Showing
18 changed files
with
700 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,6 @@ authors = ["Yuekai Jia <[email protected]>"] | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
axruntime = { path = "../../modules/axruntime", features = ["paging", "net"] } | ||
axnet = { path = "../../../modules/axnet" } | ||
axerror = { path = "../../../modules/axerror" } | ||
axruntime = { path = "../../../modules/axruntime", features = ["paging", "net"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[macro_use] | ||
extern crate axruntime; | ||
extern crate alloc; | ||
|
||
use alloc::vec::Vec; | ||
use core::str::FromStr; | ||
|
||
use axerror::AxResult; | ||
use axnet::io::{Read, Write}; | ||
use axnet::{IpAddr, TcpListener, TcpStream}; | ||
|
||
fn reverse(buf: &[u8]) -> Vec<u8> { | ||
let mut lines = buf | ||
.split(|&b| b == b'\n') | ||
.map(Vec::from) | ||
.collect::<Vec<_>>(); | ||
for line in lines.iter_mut() { | ||
line.reverse(); | ||
} | ||
lines.join(&b'\n') | ||
} | ||
|
||
fn echo_server(mut stream: TcpStream) -> AxResult { | ||
let mut buf = [0u8; 1024]; | ||
loop { | ||
let n = stream.read(&mut buf)?; | ||
if n == 0 { | ||
return Ok(()); | ||
} | ||
stream.write_all(reverse(&buf[..n]).as_slice())?; | ||
} | ||
} | ||
|
||
fn accept_loop() -> AxResult { | ||
let (addr, port) = (IpAddr::from_str("10.0.2.15").unwrap(), 5555); | ||
let mut listener = TcpListener::bind((addr, port).into())?; | ||
println!("listen on: {}", listener.local_addr().unwrap()); | ||
|
||
loop { | ||
match listener.accept() { | ||
Ok((stream, addr)) => { | ||
println!("new client: {}", addr); | ||
echo_server(stream)?; | ||
println!("client closed"); | ||
} | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
fn main() { | ||
println!("Hello, echo server!"); | ||
accept_loop().expect("test echo server failed"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "arceos-httpclient" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Yuekai Jia <[email protected]>"] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
axnet = { path = "../../../modules/axnet" } | ||
axerror = { path = "../../../modules/axerror" } | ||
axruntime = { path = "../../../modules/axruntime", features = ["paging", "net"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
#[macro_use] | ||
extern crate axruntime; | ||
|
||
use core::str::FromStr; | ||
|
||
use axerror::AxResult; | ||
use axnet::io::{Read, Write}; | ||
use axnet::{IpAddr, TcpStream}; | ||
|
||
const DEST_IP: &str = "49.12.234.183"; // ident.me | ||
const REQUEST: &str = "\ | ||
GET / HTTP/1.1\r\n\ | ||
Host: ident.me\r\n\ | ||
Accept: */*\r\n\ | ||
\r\n"; | ||
|
||
fn client() -> AxResult { | ||
let (addr, port) = (IpAddr::from_str(DEST_IP).unwrap(), 80); | ||
let mut stream = TcpStream::connect((addr, port).into())?; | ||
stream.write(REQUEST.as_bytes())?; | ||
|
||
let mut buf = [0; 1024]; | ||
let n = stream.read(&mut buf)?; | ||
let response = core::str::from_utf8(&buf[..n]).unwrap(); | ||
println!("{}", response); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[no_mangle] | ||
fn main() { | ||
println!("Hello, simple http client!"); | ||
client().expect("test http client failed"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,20 +7,22 @@ authors = ["Yuekai Jia <[email protected]>"] | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[features] | ||
smoltcp = ["dep:smoltcp"] | ||
smoltcp = [] | ||
default = ["axdriver/virtio-net", "smoltcp"] | ||
|
||
[dependencies] | ||
log = "0.4" | ||
spin = "0.9" | ||
cfg-if = "1.0" | ||
driver_common = { path = "../../crates/driver_common" } | ||
driver_net = { path = "../../crates/driver_net" } | ||
lazy_init = { path = "../../crates/lazy_init" } | ||
axhal = { path = "../axhal" } | ||
axdriver = { path = "../axdriver" } | ||
axerror = { path = "../axerror" } | ||
|
||
[dependencies.smoltcp] | ||
version = "0.9.1" | ||
optional = true | ||
default-features = false | ||
features = [ | ||
"alloc", "log", # no std | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use alloc::{string::String, vec::Vec}; | ||
|
||
use axerror::{ax_err, AxResult}; | ||
|
||
pub trait Read { | ||
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize>; | ||
|
||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> AxResult<usize> { | ||
let start_len = buf.len(); | ||
let mut probe = [0u8; 32]; | ||
loop { | ||
match self.read(&mut probe) { | ||
Ok(0) => return Ok(buf.len() - start_len), | ||
Ok(n) => buf.extend_from_slice(&probe[..n]), | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
} | ||
|
||
fn read_to_string(&mut self, buf: &mut String) -> AxResult<usize> { | ||
let old_len = buf.len(); | ||
let buf = unsafe { buf.as_mut_vec() }; | ||
let ret = self.read_to_end(buf)?; | ||
if core::str::from_utf8(&buf[old_len..]).is_err() { | ||
ax_err!(Io, "stream did not contain valid UTF-8") | ||
} else { | ||
Ok(ret) | ||
} | ||
} | ||
|
||
fn read_exact(&mut self, mut buf: &mut [u8]) -> AxResult { | ||
while !buf.is_empty() { | ||
match self.read(buf) { | ||
Ok(0) => break, | ||
Ok(n) => { | ||
let tmp = buf; | ||
buf = &mut tmp[n..]; | ||
} | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
if !buf.is_empty() { | ||
ax_err!(Io, "failed to fill whole buffer") | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
} | ||
|
||
pub trait Write { | ||
fn write(&mut self, buf: &[u8]) -> AxResult<usize>; | ||
fn flush(&mut self) -> AxResult; | ||
|
||
fn write_all(&mut self, mut buf: &[u8]) -> AxResult { | ||
while !buf.is_empty() { | ||
match self.write(buf) { | ||
Ok(0) => return ax_err!(Io, "failed to write whole buffer"), | ||
Ok(n) => buf = &buf[n..], | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.