add tcp support and tcp_simplehttp app

This commit is contained in:
yufeng 2023-03-03 16:58:07 +08:00 committed by Yifan Wu
parent 9832bafb44
commit 5a63d8e1fe
19 changed files with 666 additions and 83 deletions

View file

@ -0,0 +1,189 @@
#![no_std]
#![no_main]
use alloc::string::{String, ToString};
#[macro_use]
extern crate user_lib;
#[macro_use]
extern crate alloc;
// use http://localhost:6201/ to access the http server
use user_lib::{read, write, listen, accept};
// get url from the tcp request list.
fn get_url_from_tcp_request(req: &[u8]) -> String {
let mut index = 0;
for i in 4..req.len() {
if req[i] == 0x20 {
index = i;
break;
}
}
String::from_utf8_lossy(&req[4..index]).to_string()
}
// just receive GET requests
fn handle_tcp_client(client_fd: usize) -> bool {
// a buf to receive the data from the server
let mut buf = vec![0u8; 1024];
let len = read(client_fd as usize, &mut buf);
println!("receive {} bytes", len);
hexdump(&buf[..len as usize]);
// verify whether it is a valid HTTP request simply, [0x47,0x45,0x54, 0x20] is GET
if len < 4 || buf[..4] != [0x47,0x45,0x54, 0x20] {
println!("it's not a valid http request");
return false;
}
let url = get_url_from_tcp_request(&buf);
if url == "/close" {
let content = r#"<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container-fluid p-5 bg-danger text-white text-center">
<h1>server closed</h1>
</div>
</body>
</html>"#;
let response = format!("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnecion: Close\r\n\r\n{}", content.len(),content);
write(client_fd, response.as_bytes());
// terminate the connection immediately.
return true;
}
let content = r#"<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container-fluid p-5 bg-primary text-white text-center">
<h1>lose-net-stack</h1>
<p>rcore-tutorial RISC-V Unix .</p>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-sm-4">
<h3>Rust</h3>
<p>Rust</p>
<p>Rust是一门系统编程语言</p>
</div>
<div class="col-sm-4">
<h3></h3>
<p>repo url</p>
<p>https://github.com/yfblock/lose-net-stack</p>
</div>
<div class="col-sm-4">
<h3>QQ </h3>
<p>Official QQ group number</p>
<p>735045051</p>
</div>
</div>
</div>
<div class="container p-5 text-black text-center d-grid col-sm-4">
<p></p>
<button type="button" class="btn btn-warning btn-block p-3" onclick="close_server()"> server</button>
</div>
<script>
function close_server() {
location.href = "/close";
}
</script>
</body>
</html>"#;
let response = format!("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnecion: Close\r\n\r\n{}", content.len(),content);
// write a response
write(client_fd, response.as_bytes());
false
}
#[no_mangle]
pub fn main() -> i32 {
println!("This is a very simple http server");
let tcp_fd = listen(80);
if tcp_fd < 0 {
println!("Failed to listen on port 80");
return -1;
}
loop {
let client = accept(tcp_fd as usize);
println!("client connected: {}", client);
if client < 1 {
println!("Failed to accept a client on port 80");
return -1;
}
if handle_tcp_client(client as usize) {
break;
}
}
println!("finish tcp test");
// String::from_utf8_lossy(&buf[..len as usize])
0
}
#[allow(unused)]
pub fn hexdump(data: &[u8]) {
const PRELAND_WIDTH: usize = 70;
println!("[kernel] {:-^1$}", " hexdump ", PRELAND_WIDTH);
for offset in (0..data.len()).step_by(16) {
print!("[kernel] ");
for i in 0..16 {
if offset + i < data.len() {
print!("{:02x} ", data[offset + i]);
} else {
print!("{:02} ", "");
}
}
print!("{:>6}", ' ');
for i in 0..16 {
if offset + i < data.len() {
let c = data[offset + i];
if c >= 0x20 && c <= 0x7e {
print!("{}", c as char);
} else {
print!(".");
}
} else {
print!("{:02} ", "");
}
}
println!("");
}
println!("[kernel] {:-^1$}", " hexdump end ", PRELAND_WIDTH);
}

View file

@ -8,12 +8,12 @@ extern crate user_lib;
#[macro_use]
extern crate alloc;
use user_lib::{connect, write, read};
use user_lib::{connect, read, write};
#[no_mangle]
pub fn main() -> i32 {
println!("udp test open!");
let udp_fd = connect(10 << 24 | 0 << 16 | 2 << 8 | 2, 2001, 26099);
if udp_fd < 0 {
@ -43,4 +43,4 @@ pub fn main() -> i32 {
println!("receive reply <{}>", recv_str);
0
}
}

View file

@ -27,4 +27,4 @@ pub fn read(fd: usize, buf: &mut [u8]) -> isize {
}
pub fn write(fd: usize, buf: &[u8]) -> isize {
sys_write(fd, buf)
}
}

View file

@ -6,13 +6,13 @@
#[macro_use]
pub mod console;
mod lang_items;
mod syscall;
mod file;
mod task;
mod sync;
mod io;
mod lang_items;
mod net;
mod sync;
mod syscall;
mod task;
extern crate alloc;
#[macro_use]
@ -20,12 +20,12 @@ extern crate bitflags;
use alloc::vec::Vec;
use buddy_system_allocator::LockedHeap;
use syscall::*;
pub use file::*;
pub use task::*;
pub use sync::*;
pub use io::*;
pub use net::*;
pub use sync::*;
use syscall::*;
pub use task::*;
const USER_HEAP_SIZE: usize = 32768;

View file

@ -2,4 +2,12 @@ use super::*;
pub fn connect(ip: u32, sport: u16, dport: u16) -> isize {
sys_connect(ip, sport, dport)
}
}
pub fn listen(sport: u16) -> isize {
sys_listen(sport)
}
pub fn accept(socket_fd: usize) -> isize {
sys_accept(socket_fd)
}

View file

@ -29,4 +29,4 @@ pub fn condvar_signal(condvar_id: usize) {
}
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
sys_condvar_wait(condvar_id, mutex_id);
}
}

View file

@ -1,5 +1,7 @@
const SYSCALL_DUP: usize = 24;
const SYSCALL_CONNECT: usize = 29;
const SYSCALL_LISTEN: usize = 30;
const SYSCALL_ACCEPT: usize = 31;
const SYSCALL_OPEN: usize = 56;
const SYSCALL_CLOSE: usize = 57;
const SYSCALL_PIPE: usize = 59;
@ -50,7 +52,19 @@ pub fn sys_dup(fd: usize) -> isize {
}
pub fn sys_connect(dest: u32, sport: u16, dport: u16) -> isize {
syscall(SYSCALL_CONNECT, [dest as usize, sport as usize, dport as usize])
syscall(
SYSCALL_CONNECT,
[dest as usize, sport as usize, dport as usize],
)
}
// just listen for tcp connections now
pub fn sys_listen(sport: u16) -> isize {
syscall(SYSCALL_LISTEN, [sport as usize, 0, 0])
}
pub fn sys_accept(socket_fd: usize) -> isize {
syscall(SYSCALL_ACCEPT, [socket_fd, 0, 0])
}
pub fn sys_open(path: &str, flags: u32) -> isize {
@ -164,7 +178,6 @@ pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
}
pub fn sys_framebuffer() -> isize {
syscall(SYSCALL_FRAMEBUFFER, [0, 0, 0])
}
@ -179,4 +192,4 @@ pub fn sys_event_get() -> isize {
pub fn sys_key_pressed() -> isize {
syscall(SYSCALL_KEY_PRESSED, [0, 0, 0])
}
}