add tcp support and tcp_simplehttp app
This commit is contained in:
parent
9832bafb44
commit
5a63d8e1fe
19 changed files with 666 additions and 83 deletions
189
user/src/bin/tcp_simplehttp.rs
Normal file
189
user/src/bin/tcp_simplehttp.rs
Normal 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);
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue