Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions capc/src/codegen/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ pub fn register_runtime_intrinsics(ptr_ty: Type) -> HashMap<String, FnInfo> {
params: vec![AbiType::Handle, AbiType::ResultString],
ret: AbiType::ResultString,
};
let net_read = FnSig {
params: vec![AbiType::Handle, AbiType::I32],
ret: AbiType::Result(Box::new(AbiType::String), Box::new(AbiType::I32)),
};
let net_read_abi = FnSig {
params: vec![AbiType::Handle, AbiType::I32, AbiType::ResultString],
ret: AbiType::ResultString,
};
let net_write = FnSig {
params: vec![AbiType::Handle, AbiType::String],
ret: AbiType::Result(Box::new(AbiType::Unit), Box::new(AbiType::I32)),
Expand Down Expand Up @@ -727,6 +735,16 @@ pub fn register_runtime_intrinsics(ptr_ty: Type) -> HashMap<String, FnInfo> {
is_runtime: true,
},
);
map.insert(
"sys.net.TcpConn__read".to_string(),
FnInfo {
sig: net_read,
abi_sig: Some(net_read_abi),
symbol: "capable_rt_net_read".to_string(),
runtime_symbol: None,
is_runtime: true,
},
);
map.insert(
"sys.net.TcpConn__write".to_string(),
FnInfo {
Expand Down
128 changes: 40 additions & 88 deletions examples/http_server/http_server.cap
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,19 @@ use sys::args
use sys::system

fn arg_or_default(args: Args, index: i32, default: string) -> string {
if (args.len() > index) {
let res = args.at(index)
match (res) {
Ok(value) => {
return value
}
Err(_) => {
}
}
if (args.len() <= index) {
return default
}
match (args.at(index)) {
Ok(value) => { return value }
Err(_) => { return default }
}
return default
}

fn strip_query(raw_path: string) -> string {
let parts = raw_path.split(63u8)
let res = parts.get(0)
return match (res) {
Ok(path) => {
path
}
Err(_) => {
""
}
match (raw_path.split(63u8).get(0)) {
Ok(path) => { return path }
Err(_) => { return "" }
}
}

Expand All @@ -48,77 +38,51 @@ fn sanitize_segment(parts: VecString, i: i32, acc: string, seg: string) -> Resul
if (acc.len() == 0) {
return sanitize_parts(parts, i + 1, seg)
}
let next = fs::join(acc, seg)
return sanitize_parts(parts, i + 1, next)
return sanitize_parts(parts, i + 1, fs::join(acc, seg))
}

fn sanitize_parts(parts: VecString, i: i32, acc: string) -> Result[string, unit] {
if (i >= parts.len()) {
return Ok(acc)
}
let seg_res = parts.get(i)
return match (seg_res) {
Ok(seg) => {
sanitize_segment(parts, i, acc, seg)
}
Err(_) => {
Err(())
}
match (parts.get(i)) {
Ok(seg) => { return sanitize_segment(parts, i, acc, seg) }
Err(_) => { return Err(()) }
}
}

fn sanitize_path(raw_path: string) -> Result[string, unit] {
let parts = raw_path.split(47u8)
let res = sanitize_parts(parts, 0, "")
match (res) {
match (sanitize_parts(raw_path.split(47u8), 0, "")) {
Ok(path) => {
if (path.len() == 0) {
return Ok("index.html")
}
return Ok(path)
}
Err(_) => {
return Err(())
}
Err(_) => { return Err(()) }
}
}

fn parse_request_line(line: string) -> Result[string, unit] {
let trimmed = line.trim()
let parts = trimmed.split(32u8)
let method_res = parts.get(0)
match (method_res) {
let parts = line.trim().split(32u8)
match (parts.get(0)) {
Ok(method) => {
if (!method.eq("GET")) {
return Err(())
}
}
Err(_) => {
return Err(())
}
Err(_) => { return Err(()) }
}
let path_res = parts.get(1)
match (path_res) {
Ok(raw_path) => {
let cleaned = strip_query(raw_path)
return sanitize_path(cleaned)
}
Err(_) => {
return Err(())
}
match (parts.get(1)) {
Ok(raw_path) => { return sanitize_path(strip_query(raw_path)) }
Err(_) => { return Err(()) }
}
}

fn parse_request_path(req: string) -> Result[string, unit] {
let lines = req.lines()
let line_res = lines.get(0)
return match (line_res) {
Ok(line) => {
parse_request_line(line)
}
Err(_) => {
Err(())
}
match (req.lines().get(0)) {
Ok(line) => { return parse_request_line(line) }
Err(_) => { return Err(()) }
}
}

Expand All @@ -129,35 +93,27 @@ fn respond_ok(conn: &TcpConn, body: string) -> Result[unit, NetErr] {
}

fn respond_not_found(conn: &TcpConn) -> Result[unit, NetErr] {
conn.write("HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nnot found\n")?
return Ok(())
return conn.write("HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nnot found\n")
}

fn respond_bad_request(conn: &TcpConn) -> Result[unit, NetErr] {
conn.write("HTTP/1.0 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nbad request\n")?
return Ok(())
return conn.write("HTTP/1.0 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nbad request\n")
}

fn handle_request(conn: &TcpConn, readfs: ReadFS, path: string) -> Result[unit, NetErr] {
match (readfs.read_to_string(path)) {
Ok(body) => { return respond_ok(conn, body) }
Err(_) => { return respond_not_found(conn) }
}
}

fn serve_once(c: Console, net: Net, readfs: ReadFS) -> Result[unit, NetErr] {
let listener = net.listen("127.0.0.1", 8080)?
let conn = listener.accept()?
let req = conn.read_to_string()?
let path_res = parse_request_path(req)
match (path_res) {
Ok(path) => {
let file_res = readfs.read_to_string(path)
match (file_res) {
Ok(body) => {
respond_ok(conn, body)?
}
Err(_) => {
respond_not_found(conn)?
}
}
}
Err(_) => {
respond_bad_request(conn)?
}
let req = conn.read(4096)?
match (parse_request_path(req)) {
Ok(path) => { handle_request(conn, readfs, path)? }
Err(_) => { respond_bad_request(conn)? }
}
conn.close()
return Ok(())
Expand All @@ -170,13 +126,9 @@ pub fn main(rc: RootCap) -> i32 {
let root = arg_or_default(args, 1, ".")
let readfs = rc.mint_readfs(root)
c.println("listening on 127.0.0.1:8080")
let res = serve_once(c, net, readfs)
match (res) {
Ok(_) => {
}
Err(_) => {
c.println("server error")
}
match (serve_once(c, net, readfs)) {
Ok(_) => {}
Err(_) => { c.println("server error") }
}
return 0
}
33 changes: 33 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,39 @@ pub extern "C" fn capable_rt_net_read_to_string(
)
}

#[no_mangle]
pub extern "C" fn capable_rt_net_read(
conn: Handle,
max_size: i32,
out_ptr: *mut *const u8,
out_len: *mut u64,
out_err: *mut i32,
) -> u8 {
let result = with_table(&TCP_CONNS, "tcp conn table", |table| {
let Some(stream) = table.get_mut(&conn) else {
return Err(NetErr::IoError);
};
let max = max_size.max(0) as usize;
let mut buffer = vec![0u8; max];
match stream.read(&mut buffer) {
Ok(n) => {
buffer.truncate(n);
match String::from_utf8(buffer) {
Ok(s) => Ok(s),
Err(_) => Err(NetErr::InvalidData),
}
}
Err(err) => Err(map_net_err(err)),
}
});
write_string_result(
out_ptr,
out_len,
out_err,
result.map_err(|err| err as i32),
)
}

#[no_mangle]
pub extern "C" fn capable_rt_net_write(
conn: Handle,
Expand Down
4 changes: 4 additions & 0 deletions stdlib/sys/net.cap
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ impl TcpConn {
return Err(NetErr::IoError)
}

pub fn read(self: &TcpConn, max_size: i32) -> Result[string, NetErr] {
return Err(NetErr::IoError)
}

pub fn write(self: &TcpConn, data: string) -> Result[unit, NetErr] {
return Err(NetErr::IoError)
}
Expand Down