Skip to content

Commit

Permalink
Add network syscalls (#512)
Browse files Browse the repository at this point in the history
* Add connect syscall

* Add tcp socket device

* Add socket.connect to lisp

* Rewrite tcp command to use the syscalls

* Rewrite http command to use the syscalls

* Use socket#recv_slice instead of socket#recv

* Move connect to net module

* Refactor connect

* Refactor code

* Add listen syscall

* Add accept

* Add close to FileIO

* Fix write loop

* Add poll syscall

* Rewrite socket command to use poll

* Update console polling

* Rename file handle to handle

* Remove prompt option from socket

* Make poll blocking with timeout and cancel

* Add one byte status read

* Remove poll blocking

* Fix error when connect is followed directly by close

* Change tcp and socket command arguments

* Add sleep while polling without events

* Speed up connection failure detection

* Add back some verbose output

* Fix socket listen

* Split net files

* Add UDP sockets

* Refactor host command code

* Move shared socket code to module

* Use recommended buffer size in socket file size

* Remove debug output

* Fix fallback socket size

* Update html doc

* Update network screenshot

* Update lisp manual
  • Loading branch information
vinc authored Jul 29, 2023
1 parent eab33dc commit b606c06
Show file tree
Hide file tree
Showing 39 changed files with 1,283 additions and 585 deletions.
2 changes: 2 additions & 0 deletions doc/lisp.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby!
- `let`
- `string.join` (aliased to `str.join`), `lines`, `words`, `chars`
- `regex.match?`
- `socket.connect`, `socket.listen`, `socket.accept`

### File Library
- `read`, `write`, `append`
Expand Down Expand Up @@ -199,3 +200,4 @@ language and reading from the filesystem.

### Unreleased
- Add file, number, string, and regex namespaces
- Add socket functions
39 changes: 17 additions & 22 deletions doc/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ The `dhcp` command configures the network automatically:
The `host` command performs DNS lookups:

> host example.com
example.com has address 93.184.216.34
93.184.216.34


## TCP

The `tcp` command connects to TCP sockets:

> tcp time.nist.gov 13 --verbose
> tcp time.nist.gov:13 --verbose
DEBUG: Connecting to 129.6.15.30:13

58884 20-02-05 19:19:42 00 0 0 49.2 UTC(NIST) *
Expand Down Expand Up @@ -101,18 +101,16 @@ like the `netcat` command on Unix.

For example the request made with `tcp` above is equivalent to this:

> socket time.nist.gov 13 --read-only
> socket time.nist.gov:13 --read-only

59710 22-05-11 21:44:52 50 0 0 359.3 UTC(NIST) *

And the request made with `http` is equivalent to that:

> socket moros.cc 80 --prompt
MOROS Socket v0.1.0
> socket moros.cc:80
GET /test.html HTTP/1.0
Host: moros.cc

> GET /test.html HTTP/1.0
> Host: moros.cc
>
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 11 May 2022 21:46:34 GMT
Expand All @@ -136,27 +134,24 @@ And the request made with `http` is equivalent to that:

Here's a connexion to a SMTP server to send a mail:

> socket 10.0.2.2 2500 --prompt
MOROS Socket v0.1.0

> socket 10.0.2.2:2500
220 EventMachine SMTP Server
> EHLO moros.cc
HELO moros.cc
250-Ok EventMachine SMTP Server
250-NO-SOLICITING
250 SIZE 20000000
> MAIL FROM:<[email protected]>
> RCPT TO:<[email protected]>
MAIL FROM:<[email protected]>
250 Ok
RCPT TO:<[email protected]>
250 Ok
> DATA
DATA
354 Send it
> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec
> diam vitae ex blandit malesuada nec a turpis.
> .
> QUIT
Subject: Test
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec
diam vitae ex blandit malesuada nec a turpis.
.
250 Message accepted
QUIT
221 Ok

Sending a file to a server:

> socket 10.0.2.2 1234 <= /tmp/alice.txt
> socket 10.0.2.2:1234 <= /tmp/alice.txt
Binary file modified doc/network.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions doc/shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ file while the standard error is kept:
> time read foo.txt => /dev/null

The standard output is implied as the source of a redirection, but it is
possible to explicitly redirect a file handle to another (TODO):
possible to explicitly redirect a handle to another (TODO):

> time read foo.txt [1]=>[3]

Or to redirect a file handle to a file:
Or to redirect a handle to a file:

> time read foo.txt [1]=> bar.txt

Or to pipe a file handle to another command:
Or to pipe a handle to another command:

> time read foo.txt [1]-> write bar.txt

Expand All @@ -125,7 +125,7 @@ Redirections should be declared before piping (TODO):

> write <= req.txt => /net/http/moros.cc -> find --line href -> sort

NOTE: The following file handles are available when a process is created:
NOTE: The following handles are available when a process is created:

- `stdin(0)`
- `stdout(1)`
Expand Down
18 changes: 18 additions & 0 deletions doc/syscalls.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,21 @@ The system will reboot with `0xcafe` and halt with `0xdead`.
```rust
pub fn sleep(seconds: f64)
```

## CONNECT (0xC)

```rust
pub fn connect(handle, usize, addr: &str, port: u16) -> isize
```

## LISTEN (0xD)

```rust
pub fn listen(handle, usize, port: u16) -> isize
```

## ACCEPT (0xE)

```rust
pub fn accept(handle, usize, addr: &str) -> isize
```
5 changes: 5 additions & 0 deletions src/api/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ use alloc::vec;

pub use crate::sys::fs::{FileInfo, DeviceType};

#[derive(Clone, Copy)]
pub enum IO { Read, Write }

pub trait FileIO {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()>;
fn write(&mut self, buf: &[u8]) -> Result<usize, ()>;
fn close(&mut self);
fn poll(&mut self, event: IO) -> bool;
}

pub fn dirname(pathname: &str) -> &str {
Expand Down
49 changes: 49 additions & 0 deletions src/api/syscall.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use crate::api::fs::IO;
use crate::api::process::ExitCode;
use crate::syscall;
use crate::sys::syscall::number::*;
use crate::sys::fs::FileInfo;

use smoltcp::wire::IpAddress;
use smoltcp::wire::Ipv4Address;

pub fn exit(code: ExitCode) {
unsafe { syscall!(EXIT, code as usize) };
}
Expand Down Expand Up @@ -106,6 +110,51 @@ pub fn halt() {
stop(0xdead);
}

pub fn poll(list: &[(usize, IO)]) -> Option<(usize, IO)> {
let ptr = list.as_ptr() as usize;
let len = list.len();
let idx = unsafe { syscall!(POLL, ptr, len) } as isize;
if 0 <= idx && idx < len as isize {
Some(list[idx as usize])
} else {
None
}
}

pub fn connect(handle: usize, addr: IpAddress, port: u16) -> Result<(), ()> {
let buf = addr.as_bytes();
let ptr = buf.as_ptr() as usize;
let len = buf.len();
let res = unsafe { syscall!(CONNECT, handle, ptr, len, port) } as isize;
if res >= 0 {
Ok(())
} else {
Err(())
}
}

pub fn listen(handle: usize, port: u16) -> Result<(), ()> {
let res = unsafe { syscall!(LISTEN, handle, port) } as isize;
if res >= 0 {
Ok(())
} else {
Err(())
}
}

pub fn accept(handle: usize) -> Result<IpAddress, ()> {
let addr = IpAddress::v4(0, 0, 0, 0);
let buf = addr.as_bytes();
let ptr = buf.as_ptr() as usize;
let len = buf.len();
let res = unsafe { syscall!(ACCEPT, handle, ptr, len) } as isize;
if res >= 0 {
Ok(IpAddress::from(Ipv4Address::from_bytes(buf)))
} else {
Err(())
}
}

#[test_case]
fn test_file() {
use crate::sys::fs::{mount_mem, format_mem, dismount, OpenFlag};
Expand Down
24 changes: 23 additions & 1 deletion src/sys/clock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::api::clock::DATE_TIME_ZONE;
use crate::api::fs::{FileIO, IO};
use crate::sys;
use crate::sys::cmos::CMOS;
use crate::sys::fs::FileIO;

use time::{OffsetDateTime, Duration};

Expand Down Expand Up @@ -31,9 +31,20 @@ impl FileIO for Uptime {
Err(())
}
}

fn write(&mut self, _buf: &[u8]) -> Result<usize, ()> {
unimplemented!();
}

fn close(&mut self) {
}

fn poll(&mut self, event: IO) -> bool {
match event {
IO::Read => true,
IO::Write => false,
}
}
}

// NOTE: This clock is monotonic
Expand Down Expand Up @@ -65,9 +76,20 @@ impl FileIO for Realtime {
Err(())
}
}

fn write(&mut self, _buf: &[u8]) -> Result<usize, ()> {
unimplemented!();
}

fn close(&mut self) {
}

fn poll(&mut self, event: IO) -> bool {
match event {
IO::Read => true,
IO::Write => false,
}
}
}

// NOTE: This clock is not monotonic
Expand Down
12 changes: 11 additions & 1 deletion src/sys/cmos.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::clock::{DATE_TIME, DATE_TIME_LEN};
use crate::sys::fs::FileIO;
use crate::api::fs::{FileIO, IO};

use alloc::string::String;
use bit_field::BitField;
Expand Down Expand Up @@ -83,6 +83,16 @@ impl FileIO for RTC {
CMOS::new().update_rtc(self);
Ok(buf.len())
}

fn close(&mut self) {
}

fn poll(&mut self, event: IO) -> bool {
match event {
IO::Read => true,
IO::Write => true,
}
}
}

pub struct CMOS {
Expand Down
12 changes: 11 additions & 1 deletion src/sys/console.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::fs::{FileIO, IO};
use crate::sys;
use crate::sys::fs::FileIO;
use alloc::string::String;
use alloc::string::ToString;
use core::fmt;
Expand Down Expand Up @@ -43,6 +43,16 @@ impl FileIO for Console {
print_fmt(format_args!("{}", s));
Ok(n)
}

fn close(&mut self) {
}

fn poll(&mut self, event: IO) -> bool {
match event {
IO::Read => STDIN.lock().contains('\n'),
IO::Write => true,
}
}
}

pub fn cols() -> usize {
Expand Down
Loading

0 comments on commit b606c06

Please sign in to comment.