mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-24 18:36:24 +04:00
add tcp support and tcp_simplehttp app
This commit is contained in:
parent
3897e6e50f
commit
2a4c7c2cc3
@ -15,7 +15,7 @@ bitflags = "1.2.1"
|
|||||||
xmas-elf = "0.7.0"
|
xmas-elf = "0.7.0"
|
||||||
volatile = "0.3"
|
volatile = "0.3"
|
||||||
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" }
|
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" }
|
||||||
lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "3f467dd" }
|
lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "db42380" }
|
||||||
easy-fs = { path = "../easy-fs" }
|
easy-fs = { path = "../easy-fs" }
|
||||||
embedded-graphics = "0.7.1"
|
embedded-graphics = "0.7.1"
|
||||||
tinybmp = "0.3.1"
|
tinybmp = "0.3.1"
|
||||||
|
@ -86,7 +86,7 @@ run-inner-none: build
|
|||||||
-device virtio-keyboard-device \
|
-device virtio-keyboard-device \
|
||||||
-device virtio-mouse-device \
|
-device virtio-mouse-device \
|
||||||
-device virtio-net-device,netdev=net0 \
|
-device virtio-net-device,netdev=net0 \
|
||||||
-netdev user,id=net0,hostfwd=udp::6200-:2000 \
|
-netdev user,id=net0,hostfwd=udp::6200-:2000,hostfwd=tcp::6201-:80 \
|
||||||
-serial stdio
|
-serial stdio
|
||||||
|
|
||||||
run-inner: build
|
run-inner: build
|
||||||
@ -102,7 +102,7 @@ run-inner: build
|
|||||||
-device virtio-keyboard-device \
|
-device virtio-keyboard-device \
|
||||||
-device virtio-mouse-device \
|
-device virtio-mouse-device \
|
||||||
-device virtio-net-device,netdev=net0 \
|
-device virtio-net-device,netdev=net0 \
|
||||||
-netdev user,id=net0,hostfwd=udp::6200-:2000 \
|
-netdev user,id=net0,hostfwd=udp::6200-:2000,hostfwd=tcp::6201-:80 \
|
||||||
-serial stdio
|
-serial stdio
|
||||||
|
|
||||||
fdt:
|
fdt:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::mm::{
|
use crate::mm::{
|
||||||
frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
|
frame_alloc_more, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
|
||||||
StepByOne, VirtAddr, frame_alloc_more,
|
StepByOne, VirtAddr,
|
||||||
};
|
};
|
||||||
use crate::sync::UPIntrFreeCell;
|
use crate::sync::UPIntrFreeCell;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
@ -18,7 +18,9 @@ impl Hal for VirtioHal {
|
|||||||
fn dma_alloc(pages: usize) -> usize {
|
fn dma_alloc(pages: usize) -> usize {
|
||||||
let trakcers = frame_alloc_more(pages);
|
let trakcers = frame_alloc_more(pages);
|
||||||
let ppn_base = trakcers.as_ref().unwrap().last().unwrap().ppn;
|
let ppn_base = trakcers.as_ref().unwrap().last().unwrap().ppn;
|
||||||
QUEUE_FRAMES.exclusive_access().append(&mut trakcers.unwrap());
|
QUEUE_FRAMES
|
||||||
|
.exclusive_access()
|
||||||
|
.append(&mut trakcers.unwrap());
|
||||||
let pa: PhysAddr = ppn_base.into();
|
let pa: PhysAddr = ppn_base.into();
|
||||||
pa.0
|
pa.0
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
use lazy_static::*;
|
|
||||||
use virtio_drivers::{VirtIONet, VirtIOHeader};
|
|
||||||
use crate::drivers::virtio::VirtioHal;
|
use crate::drivers::virtio::VirtioHal;
|
||||||
use crate::sync::UPIntrFreeCell;
|
use crate::sync::UPIntrFreeCell;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use lazy_static::*;
|
||||||
|
use virtio_drivers::{VirtIOHeader, VirtIONet};
|
||||||
|
|
||||||
const VIRTIO8: usize = 0x10004000;
|
const VIRTIO8: usize = 0x10004000;
|
||||||
|
|
||||||
@ -21,21 +21,26 @@ pub struct VirtIONetWrapper(UPIntrFreeCell<VirtIONet<'static, VirtioHal>>);
|
|||||||
|
|
||||||
impl NetDevice for VirtIONetWrapper {
|
impl NetDevice for VirtIONetWrapper {
|
||||||
fn transmit(&self, data: &[u8]) {
|
fn transmit(&self, data: &[u8]) {
|
||||||
self.0.exclusive_access().send(data).expect("can't send data")
|
self.0
|
||||||
|
.exclusive_access()
|
||||||
|
.send(data)
|
||||||
|
.expect("can't send data")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&self, data: &mut [u8]) -> usize {
|
fn receive(&self, data: &mut [u8]) -> usize {
|
||||||
self.0.exclusive_access().recv(data).expect("can't receive data")
|
self.0
|
||||||
|
.exclusive_access()
|
||||||
|
.recv(data)
|
||||||
|
.expect("can't receive data")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtIONetWrapper {
|
impl VirtIONetWrapper {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let virtio =
|
let virtio = VirtIONet::<VirtioHal>::new(&mut *(VIRTIO8 as *mut VirtIOHeader))
|
||||||
VirtIONet::<VirtioHal>::new(&mut *(VIRTIO8 as *mut VirtIOHeader))
|
|
||||||
.expect("can't create net device by virtio");
|
.expect("can't create net device by virtio");
|
||||||
VirtIONetWrapper(UPIntrFreeCell::new(virtio))
|
VirtIONetWrapper(UPIntrFreeCell::new(virtio))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,13 @@ mod drivers;
|
|||||||
mod fs;
|
mod fs;
|
||||||
mod lang_items;
|
mod lang_items;
|
||||||
mod mm;
|
mod mm;
|
||||||
|
mod net;
|
||||||
mod sbi;
|
mod sbi;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod syscall;
|
mod syscall;
|
||||||
mod task;
|
mod task;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod trap;
|
mod trap;
|
||||||
mod net;
|
|
||||||
|
|
||||||
use riscv::register::*;
|
use riscv::register::*;
|
||||||
// mod riscvreg;
|
// mod riscvreg;
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
pub mod udp;
|
|
||||||
pub mod socket;
|
pub mod socket;
|
||||||
|
pub mod tcp;
|
||||||
|
pub mod udp;
|
||||||
|
pub mod port_table;
|
||||||
|
|
||||||
pub use lose_net_stack::IPv4;
|
pub use lose_net_stack::IPv4;
|
||||||
|
|
||||||
use alloc::{vec, sync::Arc};
|
use alloc::{sync::Arc, vec};
|
||||||
use lose_net_stack::{LoseStack, MacAddress, results::Packet};
|
use lose_net_stack::{results::Packet, LoseStack, MacAddress, TcpFlags};
|
||||||
|
|
||||||
use crate::{drivers::NET_DEVICE, sync::UPIntrFreeCell, net::socket::{get_socket, push_data}};
|
use crate::{
|
||||||
|
drivers::NET_DEVICE,
|
||||||
|
net::socket::{get_socket, push_data},
|
||||||
|
sync::UPIntrFreeCell,
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::{port_table::check_accept, socket::set_s_a_by_index};
|
||||||
|
|
||||||
pub struct NetStack(UPIntrFreeCell<LoseStack>);
|
pub struct NetStack(UPIntrFreeCell<LoseStack>);
|
||||||
|
|
||||||
@ -15,7 +23,7 @@ impl NetStack {
|
|||||||
unsafe {
|
unsafe {
|
||||||
NetStack(UPIntrFreeCell::new(LoseStack::new(
|
NetStack(UPIntrFreeCell::new(LoseStack::new(
|
||||||
IPv4::new(10, 0, 2, 15),
|
IPv4::new(10, 0, 2, 15),
|
||||||
MacAddress::new([0x52, 0x54, 0x00, 0x12, 0x34, 0x56])
|
MacAddress::new([0x52, 0x54, 0x00, 0x12, 0x34, 0x56]),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,34 +33,70 @@ lazy_static::lazy_static! {
|
|||||||
static ref LOSE_NET_STACK: Arc<NetStack> = Arc::new(NetStack::new());
|
static ref LOSE_NET_STACK: Arc<NetStack> = Arc::new(NetStack::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn net_interrupt_handler() {
|
pub fn net_interrupt_handler() {
|
||||||
let mut recv_buf = vec![0u8; 1024];
|
let mut recv_buf = vec![0u8; 1024];
|
||||||
|
|
||||||
let len = NET_DEVICE.receive(&mut recv_buf);
|
let len = NET_DEVICE.receive(&mut recv_buf);
|
||||||
|
|
||||||
let packet = LOSE_NET_STACK.0.exclusive_access().analysis(&recv_buf[..len]);
|
let packet = LOSE_NET_STACK
|
||||||
|
.0
|
||||||
|
.exclusive_access()
|
||||||
|
.analysis(&recv_buf[..len]);
|
||||||
|
|
||||||
// println!("[kernel] receive a packet");
|
// println!("[kernel] receive a packet");
|
||||||
// hexdump(&recv_buf[..len]);
|
// hexdump(&recv_buf[..len]);
|
||||||
|
|
||||||
match packet {
|
match packet {
|
||||||
Packet::ARP(arp_packet) => {
|
Packet::ARP(arp_packet) => {
|
||||||
let lose_stack = LOSE_NET_STACK.0.exclusive_access();
|
let lose_stack = LOSE_NET_STACK.0.exclusive_access();
|
||||||
let reply_packet = arp_packet.reply_packet(lose_stack.ip, lose_stack.mac).expect("can't build reply");
|
let reply_packet = arp_packet
|
||||||
|
.reply_packet(lose_stack.ip, lose_stack.mac)
|
||||||
|
.expect("can't build reply");
|
||||||
let reply_data = reply_packet.build_data();
|
let reply_data = reply_packet.build_data();
|
||||||
NET_DEVICE.transmit(&reply_data)
|
NET_DEVICE.transmit(&reply_data)
|
||||||
},
|
}
|
||||||
|
|
||||||
Packet::UDP(udp_packet) => {
|
Packet::UDP(udp_packet) => {
|
||||||
let target = udp_packet.source_ip;
|
let target = udp_packet.source_ip;
|
||||||
let lport = udp_packet.dest_port;
|
let lport = udp_packet.dest_port;
|
||||||
let rport = udp_packet.source_port;
|
let rport = udp_packet.source_port;
|
||||||
|
|
||||||
if let Some(socket_index) = get_socket(target, lport, rport) {
|
if let Some(socket_index) = get_socket(target, lport, rport) {
|
||||||
push_data(socket_index, udp_packet.data.to_vec());
|
push_data(socket_index, udp_packet.data.to_vec());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Packet::TCP(tcp_packet) => {
|
||||||
|
let target = tcp_packet.source_ip;
|
||||||
|
let lport = tcp_packet.dest_port;
|
||||||
|
let rport = tcp_packet.source_port;
|
||||||
|
let flags = tcp_packet.flags;
|
||||||
|
|
||||||
|
if flags.contains(TcpFlags::S) {
|
||||||
|
// if it has a port to accept, then response the request
|
||||||
|
if check_accept(lport, &tcp_packet).is_some() {
|
||||||
|
let mut reply_packet = tcp_packet.ack();
|
||||||
|
reply_packet.flags = TcpFlags::S | TcpFlags::A;
|
||||||
|
NET_DEVICE.transmit(&reply_packet.build_data());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if tcp_packet.flags.contains(TcpFlags::F) {
|
||||||
|
// tcp disconnected
|
||||||
|
let reply_packet = tcp_packet.ack();
|
||||||
|
NET_DEVICE.transmit(&reply_packet.build_data());
|
||||||
|
|
||||||
|
let mut end_packet = reply_packet.ack();
|
||||||
|
end_packet.flags |= TcpFlags::F;
|
||||||
|
NET_DEVICE.transmit(&end_packet.build_data());
|
||||||
|
} else if tcp_packet.flags.contains(TcpFlags::A) && tcp_packet.data_len == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(socket_index) = get_socket(target, lport, rport) {
|
||||||
|
push_data(socket_index, tcp_packet.data.to_vec());
|
||||||
|
set_s_a_by_index(socket_index, tcp_packet.seq, tcp_packet.ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,8 +129,8 @@ pub fn hexdump(data: &[u8]) {
|
|||||||
print!("{:02} ", "");
|
print!("{:02} ", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
println!("[kernel] {:-^1$}", " hexdump end ", PRELAND_WIDTH);
|
println!("[kernel] {:-^1$}", " hexdump end ", PRELAND_WIDTH);
|
||||||
}
|
}
|
||||||
|
131
os/src/net/port_table.rs
Normal file
131
os/src/net/port_table.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use alloc::{vec::Vec, sync::Arc};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use lose_net_stack::packets::tcp::TCPPacket;
|
||||||
|
|
||||||
|
use crate::{sync::UPIntrFreeCell, fs::File, task::{TaskControlBlock, wakeup_task}};
|
||||||
|
|
||||||
|
use super::tcp::TCP;
|
||||||
|
|
||||||
|
pub struct Port {
|
||||||
|
pub port: u16,
|
||||||
|
pub receivable: bool,
|
||||||
|
pub schedule: Option<Arc<TaskControlBlock>>
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref LISTEN_TABLE: UPIntrFreeCell<Vec<Option<Port>>> =
|
||||||
|
unsafe { UPIntrFreeCell::new(Vec::new()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn listen(port: u16) -> Option<usize> {
|
||||||
|
let mut listen_table = LISTEN_TABLE.exclusive_access();
|
||||||
|
let mut index = usize::MAX;
|
||||||
|
for i in 0..listen_table.len() {
|
||||||
|
if listen_table[i].is_none() {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let listen_port = Port {
|
||||||
|
port,
|
||||||
|
receivable: false,
|
||||||
|
schedule: None
|
||||||
|
};
|
||||||
|
|
||||||
|
if index == usize::MAX {
|
||||||
|
listen_table.push(Some(listen_port));
|
||||||
|
Some(listen_table.len() - 1)
|
||||||
|
} else {
|
||||||
|
listen_table[index] = Some(listen_port);
|
||||||
|
Some(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// can accept request
|
||||||
|
pub fn accept(listen_index: usize, task: Arc<TaskControlBlock>) {
|
||||||
|
let mut listen_table = LISTEN_TABLE.exclusive_access();
|
||||||
|
assert!(listen_index < listen_table.len());
|
||||||
|
let listen_port = listen_table[listen_index].as_mut();
|
||||||
|
assert!(listen_port.is_some());
|
||||||
|
let listen_port = listen_port.unwrap();
|
||||||
|
listen_port.receivable = true;
|
||||||
|
listen_port.schedule = Some(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn port_acceptable(listen_index: usize) -> bool {
|
||||||
|
let mut listen_table = LISTEN_TABLE.exclusive_access();
|
||||||
|
assert!(listen_index < listen_table.len());
|
||||||
|
|
||||||
|
let listen_port = listen_table[listen_index].as_mut();
|
||||||
|
listen_port.map_or(false, |x| x.receivable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether it can accept request
|
||||||
|
pub fn check_accept(port: u16, tcp_packet: &TCPPacket) -> Option<()> {
|
||||||
|
LISTEN_TABLE.exclusive_session(|listen_table| {
|
||||||
|
let mut listen_ports: Vec<&mut Option<Port>> = listen_table.iter_mut().filter(|x| match x {
|
||||||
|
Some(t) => t.port == port && t.receivable == true,
|
||||||
|
None => false,
|
||||||
|
}).collect();
|
||||||
|
if listen_ports.len() == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let listen_port = listen_ports[0].as_mut().unwrap();
|
||||||
|
let task = listen_port.schedule.clone().unwrap();
|
||||||
|
// wakeup_task(Arc::clone(&listen_port.schedule.clone().unwrap()));
|
||||||
|
listen_port.schedule = None;
|
||||||
|
listen_port.receivable = false;
|
||||||
|
|
||||||
|
accept_connection(port, tcp_packet, task);
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accept_connection(port: u16, tcp_packet: &TCPPacket, task: Arc<TaskControlBlock>) {
|
||||||
|
let process = task.process.upgrade().unwrap();
|
||||||
|
let mut inner = process.inner_exclusive_access();
|
||||||
|
let fd = inner.alloc_fd();
|
||||||
|
|
||||||
|
let tcp_socket = TCP::new(tcp_packet.source_ip, tcp_packet.dest_port, tcp_packet.source_port, tcp_packet.seq, tcp_packet.ack);
|
||||||
|
|
||||||
|
inner.fd_table[fd] = Some(Arc::new(tcp_socket));
|
||||||
|
|
||||||
|
let cx = task.inner_exclusive_access().get_trap_cx();
|
||||||
|
cx.x[10] = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store in the fd_table, delete the listen table when close the application.
|
||||||
|
pub struct PortFd(usize);
|
||||||
|
|
||||||
|
impl PortFd {
|
||||||
|
pub fn new(port_index: usize) -> Self {
|
||||||
|
PortFd(port_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PortFd {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
LISTEN_TABLE.exclusive_access()[self.0] = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for PortFd {
|
||||||
|
fn readable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, _buf: crate::mm::UserBuffer) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, _buf: crate::mm::UserBuffer) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,19 +5,47 @@ use lose_net_stack::IPv4;
|
|||||||
|
|
||||||
use crate::sync::UPIntrFreeCell;
|
use crate::sync::UPIntrFreeCell;
|
||||||
|
|
||||||
|
|
||||||
// TODO: specify the protocol, TCP or UDP
|
// TODO: specify the protocol, TCP or UDP
|
||||||
pub struct Socket {
|
pub struct Socket {
|
||||||
pub raddr: IPv4, // remote address
|
pub raddr: IPv4, // remote address
|
||||||
pub lport: u16, // local port
|
pub lport: u16, // local port
|
||||||
pub rport: u16, // rempote port
|
pub rport: u16, // rempote port
|
||||||
pub buffers: VecDeque<Vec<u8>> // datas
|
pub buffers: VecDeque<Vec<u8>>, // datas
|
||||||
|
pub seq: u32,
|
||||||
|
pub ack: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SOCKET_TABLE:UPIntrFreeCell<Vec<Option<Socket>>> = unsafe {
|
static ref SOCKET_TABLE: UPIntrFreeCell<Vec<Option<Socket>>> =
|
||||||
UPIntrFreeCell::new(Vec::new())
|
unsafe { UPIntrFreeCell::new(Vec::new()) };
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/// get the seq and ack by socket index
|
||||||
|
pub fn get_s_a_by_index(index: usize) -> Option<(u32, u32)> {
|
||||||
|
let socket_table = SOCKET_TABLE.exclusive_access();
|
||||||
|
|
||||||
|
assert!(index < socket_table.len());
|
||||||
|
|
||||||
|
socket_table.get(index).map_or(None, |x| {
|
||||||
|
match x {
|
||||||
|
Some(x) => Some((x.seq, x.ack)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_s_a_by_index(index: usize, seq: u32, ack: u32) {
|
||||||
|
let mut socket_table = SOCKET_TABLE.exclusive_access();
|
||||||
|
|
||||||
|
assert!(socket_table.len() > index);
|
||||||
|
assert!(socket_table[index].is_some());
|
||||||
|
|
||||||
|
let sock = socket_table[index]
|
||||||
|
.as_mut()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
sock.ack = ack;
|
||||||
|
sock.seq = seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_socket(raddr: IPv4, lport: u16, rport: u16) -> Option<usize> {
|
pub fn get_socket(raddr: IPv4, lport: u16, rport: u16) -> Option<usize> {
|
||||||
@ -30,7 +58,7 @@ pub fn get_socket(raddr: IPv4, lport: u16, rport: u16) -> Option<usize> {
|
|||||||
|
|
||||||
let sock = sock.as_ref().unwrap();
|
let sock = sock.as_ref().unwrap();
|
||||||
if sock.raddr == raddr && sock.lport == lport && sock.rport == rport {
|
if sock.raddr == raddr && sock.lport == lport && sock.rport == rport {
|
||||||
return Some(i)
|
return Some(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -54,7 +82,9 @@ pub fn add_socket(raddr: IPv4, lport: u16, rport: u16) -> Option<usize> {
|
|||||||
raddr,
|
raddr,
|
||||||
lport,
|
lport,
|
||||||
rport,
|
rport,
|
||||||
buffers: VecDeque::new()
|
buffers: VecDeque::new(),
|
||||||
|
seq: 0,
|
||||||
|
ack: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if index == usize::MAX {
|
if index == usize::MAX {
|
||||||
@ -80,7 +110,11 @@ pub fn push_data(index: usize, data: Vec<u8>) {
|
|||||||
assert!(socket_table.len() > index);
|
assert!(socket_table.len() > index);
|
||||||
assert!(socket_table[index].is_some());
|
assert!(socket_table[index].is_some());
|
||||||
|
|
||||||
socket_table[index].as_mut().unwrap().buffers.push_back(data);
|
socket_table[index]
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.buffers
|
||||||
|
.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_data(index: usize) -> Option<Vec<u8>> {
|
pub fn pop_data(index: usize) -> Option<Vec<u8>> {
|
||||||
@ -90,4 +124,4 @@ pub fn pop_data(index: usize) -> Option<Vec<u8>> {
|
|||||||
assert!(socket_table[index].is_some());
|
assert!(socket_table[index].is_some());
|
||||||
|
|
||||||
socket_table[index].as_mut().unwrap().buffers.pop_front()
|
socket_table[index].as_mut().unwrap().buffers.pop_front()
|
||||||
}
|
}
|
||||||
|
113
os/src/net/tcp.rs
Normal file
113
os/src/net/tcp.rs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
use alloc::vec;
|
||||||
|
use lose_net_stack::MacAddress;
|
||||||
|
use lose_net_stack::IPv4;
|
||||||
|
use lose_net_stack::TcpFlags;
|
||||||
|
use lose_net_stack::packets::tcp::TCPPacket;
|
||||||
|
|
||||||
|
use crate::{drivers::NET_DEVICE, fs::File};
|
||||||
|
|
||||||
|
use super::socket::get_s_a_by_index;
|
||||||
|
use super::{
|
||||||
|
net_interrupt_handler,
|
||||||
|
socket::{add_socket, pop_data, remove_socket},
|
||||||
|
LOSE_NET_STACK,
|
||||||
|
};
|
||||||
|
|
||||||
|
// add tcp packet info to this structure
|
||||||
|
pub struct TCP {
|
||||||
|
pub target: IPv4,
|
||||||
|
pub sport: u16,
|
||||||
|
pub dport: u16,
|
||||||
|
pub seq: u32,
|
||||||
|
pub ack: u32,
|
||||||
|
pub socket_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TCP {
|
||||||
|
pub fn new(target: IPv4, sport: u16, dport: u16, seq: u32, ack: u32) -> Self {
|
||||||
|
let index = add_socket(target, sport, dport).expect("can't add socket");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
target,
|
||||||
|
sport,
|
||||||
|
dport,
|
||||||
|
seq,
|
||||||
|
ack,
|
||||||
|
socket_index: index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for TCP {
|
||||||
|
fn readable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, mut buf: crate::mm::UserBuffer) -> usize {
|
||||||
|
loop {
|
||||||
|
if let Some(data) = pop_data(self.socket_index) {
|
||||||
|
let data_len = data.len();
|
||||||
|
let mut left = 0;
|
||||||
|
for i in 0..buf.buffers.len() {
|
||||||
|
let buffer_i_len = buf.buffers[i].len().min(data_len - left);
|
||||||
|
|
||||||
|
buf.buffers[i][..buffer_i_len]
|
||||||
|
.copy_from_slice(&data[left..(left + buffer_i_len)]);
|
||||||
|
|
||||||
|
left += buffer_i_len;
|
||||||
|
if left == data_len {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
} else {
|
||||||
|
net_interrupt_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: crate::mm::UserBuffer) -> usize {
|
||||||
|
let lose_net_stack = LOSE_NET_STACK.0.exclusive_access();
|
||||||
|
|
||||||
|
let mut data = vec![0u8; buf.len()];
|
||||||
|
|
||||||
|
let mut left = 0;
|
||||||
|
for i in 0..buf.buffers.len() {
|
||||||
|
data[left..(left + buf.buffers[i].len())].copy_from_slice(buf.buffers[i]);
|
||||||
|
left += buf.buffers[i].len();
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = data.len();
|
||||||
|
|
||||||
|
// get sock and sequence
|
||||||
|
let (ack, seq) = get_s_a_by_index(self.socket_index).map_or((0, 0), |x| x);
|
||||||
|
|
||||||
|
let tcp_packet = TCPPacket {
|
||||||
|
source_ip: lose_net_stack.ip,
|
||||||
|
source_mac: lose_net_stack.mac,
|
||||||
|
source_port: self.sport,
|
||||||
|
dest_ip: self.target,
|
||||||
|
dest_mac: MacAddress::new([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
|
||||||
|
dest_port: self.dport,
|
||||||
|
data_len: len,
|
||||||
|
seq,
|
||||||
|
ack,
|
||||||
|
flags: TcpFlags::A,
|
||||||
|
win: 65535,
|
||||||
|
urg: 0,
|
||||||
|
data: data.as_ref(),
|
||||||
|
};
|
||||||
|
NET_DEVICE.transmit(&tcp_packet.build_data());
|
||||||
|
len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TCP {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
remove_socket(self.socket_index)
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,18 @@
|
|||||||
use alloc::vec;
|
|
||||||
use lose_net_stack::MacAddress;
|
|
||||||
use lose_net_stack::packets::udp::UDPPacket;
|
|
||||||
use lose_net_stack::IPv4;
|
|
||||||
use crate::fs::File;
|
|
||||||
use super::net_interrupt_handler;
|
use super::net_interrupt_handler;
|
||||||
use super::socket::{add_socket, remove_socket, pop_data};
|
use super::socket::{add_socket, pop_data, remove_socket};
|
||||||
use super::LOSE_NET_STACK;
|
use super::LOSE_NET_STACK;
|
||||||
use super::NET_DEVICE;
|
use super::NET_DEVICE;
|
||||||
|
use crate::fs::File;
|
||||||
|
use alloc::vec;
|
||||||
|
use lose_net_stack::packets::udp::UDPPacket;
|
||||||
|
use lose_net_stack::IPv4;
|
||||||
|
use lose_net_stack::MacAddress;
|
||||||
|
|
||||||
pub struct UDP{
|
pub struct UDP {
|
||||||
pub target: IPv4,
|
pub target: IPv4,
|
||||||
pub sport: u16,
|
pub sport: u16,
|
||||||
pub dport: u16,
|
pub dport: u16,
|
||||||
pub socket_index: usize
|
pub socket_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UDP {
|
impl UDP {
|
||||||
@ -23,7 +23,7 @@ impl UDP {
|
|||||||
target,
|
target,
|
||||||
sport,
|
sport,
|
||||||
dport,
|
dport,
|
||||||
socket_index: index
|
socket_index: index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,9 +44,10 @@ impl File for UDP {
|
|||||||
let mut left = 0;
|
let mut left = 0;
|
||||||
for i in 0..buf.buffers.len() {
|
for i in 0..buf.buffers.len() {
|
||||||
let buffer_i_len = buf.buffers[i].len().min(data_len - left);
|
let buffer_i_len = buf.buffers[i].len().min(data_len - left);
|
||||||
|
|
||||||
buf.buffers[i][..buffer_i_len].copy_from_slice(&data[left..(left + buffer_i_len)]);
|
buf.buffers[i][..buffer_i_len]
|
||||||
|
.copy_from_slice(&data[left..(left + buffer_i_len)]);
|
||||||
|
|
||||||
left += buffer_i_len;
|
left += buffer_i_len;
|
||||||
if left == data_len {
|
if left == data_len {
|
||||||
break;
|
break;
|
||||||
@ -63,7 +64,7 @@ impl File for UDP {
|
|||||||
let lose_net_stack = LOSE_NET_STACK.0.exclusive_access();
|
let lose_net_stack = LOSE_NET_STACK.0.exclusive_access();
|
||||||
|
|
||||||
let mut data = vec![0u8; buf.len()];
|
let mut data = vec![0u8; buf.len()];
|
||||||
|
|
||||||
let mut left = 0;
|
let mut left = 0;
|
||||||
for i in 0..buf.buffers.len() {
|
for i in 0..buf.buffers.len() {
|
||||||
data[left..(left + buf.buffers[i].len())].copy_from_slice(buf.buffers[i]);
|
data[left..(left + buf.buffers[i].len())].copy_from_slice(buf.buffers[i]);
|
||||||
@ -73,14 +74,14 @@ impl File for UDP {
|
|||||||
let len = data.len();
|
let len = data.len();
|
||||||
|
|
||||||
let udp_packet = UDPPacket::new(
|
let udp_packet = UDPPacket::new(
|
||||||
lose_net_stack.ip,
|
lose_net_stack.ip,
|
||||||
lose_net_stack.mac,
|
lose_net_stack.mac,
|
||||||
self.sport,
|
self.sport,
|
||||||
self.target,
|
self.target,
|
||||||
MacAddress::new([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
|
MacAddress::new([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
|
||||||
self.dport,
|
self.dport,
|
||||||
len,
|
len,
|
||||||
data.as_ref()
|
data.as_ref(),
|
||||||
);
|
);
|
||||||
NET_DEVICE.transmit(&udp_packet.build_data());
|
NET_DEVICE.transmit(&udp_packet.build_data());
|
||||||
len
|
len
|
||||||
@ -91,4 +92,4 @@ impl Drop for UDP {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
remove_socket(self.socket_index)
|
remove_socket(self.socket_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const SYSCALL_DUP: usize = 24;
|
const SYSCALL_DUP: usize = 24;
|
||||||
const SYSCALL_CONNECT: usize = 29;
|
const SYSCALL_CONNECT: usize = 29;
|
||||||
|
const SYSCALL_LISTEN: usize = 30;
|
||||||
|
const SYSCALL_ACCEPT: usize = 31;
|
||||||
const SYSCALL_OPEN: usize = 56;
|
const SYSCALL_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
const SYSCALL_PIPE: usize = 59;
|
||||||
@ -34,23 +36,25 @@ const SYSCALL_KEY_PRESSED: usize = 3001;
|
|||||||
mod fs;
|
mod fs;
|
||||||
mod gui;
|
mod gui;
|
||||||
mod input;
|
mod input;
|
||||||
|
mod net;
|
||||||
mod process;
|
mod process;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod thread;
|
mod thread;
|
||||||
mod net;
|
|
||||||
|
|
||||||
use fs::*;
|
use fs::*;
|
||||||
use gui::*;
|
use gui::*;
|
||||||
use input::*;
|
use input::*;
|
||||||
|
use net::*;
|
||||||
use process::*;
|
use process::*;
|
||||||
use sync::*;
|
use sync::*;
|
||||||
use thread::*;
|
use thread::*;
|
||||||
use net::*;
|
|
||||||
|
|
||||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||||
match syscall_id {
|
match syscall_id {
|
||||||
SYSCALL_DUP => sys_dup(args[0]),
|
SYSCALL_DUP => sys_dup(args[0]),
|
||||||
SYSCALL_CONNECT => sys_connect(args[0] as _, args[1] as _, args[2] as _),
|
SYSCALL_CONNECT => sys_connect(args[0] as _, args[1] as _, args[2] as _),
|
||||||
|
SYSCALL_LISTEN => sys_listen(args[0] as _),
|
||||||
|
SYSCALL_ACCEPT => sys_accept(args[0] as _),
|
||||||
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
||||||
SYSCALL_CLOSE => sys_close(args[0]),
|
SYSCALL_CLOSE => sys_close(args[0]),
|
||||||
SYSCALL_PIPE => sys_pipe(args[0] as *mut usize),
|
SYSCALL_PIPE => sys_pipe(args[0] as *mut usize),
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use alloc::sync::Arc;
|
use crate::net::port_table::{listen, PortFd, accept, port_acceptable};
|
||||||
use crate::net::IPv4;
|
|
||||||
use crate::net::udp::UDP;
|
use crate::net::udp::UDP;
|
||||||
use crate::task::current_process;
|
use crate::net::{IPv4, net_interrupt_handler};
|
||||||
|
use crate::task::{current_process, block_current_and_run_next, current_task, current_trap_cx};
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
// just support udp
|
// just support udp
|
||||||
pub fn sys_connect(raddr: u32, lport: u16, rport: u16) -> isize {
|
pub fn sys_connect(raddr: u32, lport: u16, rport: u16) -> isize {
|
||||||
@ -10,5 +11,43 @@ pub fn sys_connect(raddr: u32, lport: u16, rport: u16) -> isize {
|
|||||||
let fd = inner.alloc_fd();
|
let fd = inner.alloc_fd();
|
||||||
let udp_node = UDP::new(IPv4::from_u32(raddr), lport, rport);
|
let udp_node = UDP::new(IPv4::from_u32(raddr), lport, rport);
|
||||||
inner.fd_table[fd] = Some(Arc::new(udp_node));
|
inner.fd_table[fd] = Some(Arc::new(udp_node));
|
||||||
fd as isize
|
fd as isize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// listen a port
|
||||||
|
pub fn sys_listen(port: u16) -> isize {
|
||||||
|
match listen(port) {
|
||||||
|
Some(port_index) => {
|
||||||
|
let process = current_process();
|
||||||
|
let mut inner = process.inner_exclusive_access();
|
||||||
|
let fd = inner.alloc_fd();
|
||||||
|
let port_fd = PortFd::new(port_index);
|
||||||
|
inner.fd_table[fd] = Some(Arc::new(port_fd));
|
||||||
|
|
||||||
|
// NOTICE: this return the port index, not the fd
|
||||||
|
port_index as isize
|
||||||
|
}
|
||||||
|
None => -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// accept a tcp connection
|
||||||
|
pub fn sys_accept(port_index: usize) -> isize {
|
||||||
|
println!("accepting port {}", port_index);
|
||||||
|
|
||||||
|
let task = current_task().unwrap();
|
||||||
|
accept(port_index, task);
|
||||||
|
// block_current_and_run_next();
|
||||||
|
|
||||||
|
// NOTICE: There does not have interrupt handler, just call it munually.
|
||||||
|
loop {
|
||||||
|
net_interrupt_handler();
|
||||||
|
|
||||||
|
if !port_acceptable(port_index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cx = current_trap_cx();
|
||||||
|
cx.x[10] as isize
|
||||||
|
}
|
||||||
|
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]
|
#[macro_use]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use user_lib::{connect, write, read};
|
use user_lib::{connect, read, write};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("udp test open!");
|
println!("udp test open!");
|
||||||
|
|
||||||
let udp_fd = connect(10 << 24 | 0 << 16 | 2 << 8 | 2, 2001, 26099);
|
let udp_fd = connect(10 << 24 | 0 << 16 | 2 << 8 | 2, 2001, 26099);
|
||||||
|
|
||||||
if udp_fd < 0 {
|
if udp_fd < 0 {
|
||||||
@ -43,4 +43,4 @@ pub fn main() -> i32 {
|
|||||||
println!("receive reply <{}>", recv_str);
|
println!("receive reply <{}>", recv_str);
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -27,4 +27,4 @@ pub fn read(fd: usize, buf: &mut [u8]) -> isize {
|
|||||||
}
|
}
|
||||||
pub fn write(fd: usize, buf: &[u8]) -> isize {
|
pub fn write(fd: usize, buf: &[u8]) -> isize {
|
||||||
sys_write(fd, buf)
|
sys_write(fd, buf)
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod console;
|
pub mod console;
|
||||||
mod lang_items;
|
|
||||||
mod syscall;
|
|
||||||
mod file;
|
mod file;
|
||||||
mod task;
|
|
||||||
mod sync;
|
|
||||||
mod io;
|
mod io;
|
||||||
|
mod lang_items;
|
||||||
mod net;
|
mod net;
|
||||||
|
mod sync;
|
||||||
|
mod syscall;
|
||||||
|
mod task;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -20,12 +20,12 @@ extern crate bitflags;
|
|||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use buddy_system_allocator::LockedHeap;
|
use buddy_system_allocator::LockedHeap;
|
||||||
use syscall::*;
|
|
||||||
pub use file::*;
|
pub use file::*;
|
||||||
pub use task::*;
|
|
||||||
pub use sync::*;
|
|
||||||
pub use io::*;
|
pub use io::*;
|
||||||
pub use net::*;
|
pub use net::*;
|
||||||
|
pub use sync::*;
|
||||||
|
use syscall::*;
|
||||||
|
pub use task::*;
|
||||||
|
|
||||||
const USER_HEAP_SIZE: usize = 32768;
|
const USER_HEAP_SIZE: usize = 32768;
|
||||||
|
|
||||||
|
@ -2,4 +2,12 @@ use super::*;
|
|||||||
|
|
||||||
pub fn connect(ip: u32, sport: u16, dport: u16) -> isize {
|
pub fn connect(ip: u32, sport: u16, dport: u16) -> isize {
|
||||||
sys_connect(ip, sport, dport)
|
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) {
|
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
|
||||||
sys_condvar_wait(condvar_id, mutex_id);
|
sys_condvar_wait(condvar_id, mutex_id);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const SYSCALL_DUP: usize = 24;
|
const SYSCALL_DUP: usize = 24;
|
||||||
const SYSCALL_CONNECT: usize = 29;
|
const SYSCALL_CONNECT: usize = 29;
|
||||||
|
const SYSCALL_LISTEN: usize = 30;
|
||||||
|
const SYSCALL_ACCEPT: usize = 31;
|
||||||
const SYSCALL_OPEN: usize = 56;
|
const SYSCALL_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
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 {
|
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 {
|
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])
|
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn sys_framebuffer() -> isize {
|
pub fn sys_framebuffer() -> isize {
|
||||||
syscall(SYSCALL_FRAMEBUFFER, [0, 0, 0])
|
syscall(SYSCALL_FRAMEBUFFER, [0, 0, 0])
|
||||||
}
|
}
|
||||||
@ -179,4 +192,4 @@ pub fn sys_event_get() -> isize {
|
|||||||
|
|
||||||
pub fn sys_key_pressed() -> isize {
|
pub fn sys_key_pressed() -> isize {
|
||||||
syscall(SYSCALL_KEY_PRESSED, [0, 0, 0])
|
syscall(SYSCALL_KEY_PRESSED, [0, 0, 0])
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user