libhermit-rs 0.6.3

A Rust-based library operating system
Documentation
use alloc::sync::Arc;
use core::ffi::c_void;
use core::ops::DerefMut;
use core::sync::atomic::Ordering;

use crate::errno::*;
use crate::executor::network::{NetworkState, NIC};
use crate::fd::{get_object, insert_object, FD_COUNTER, OBJECT_MAP};
use crate::syscalls::net::*;

mod tcp;
mod udp;

pub(crate) extern "C" fn __sys_socket(domain: i32, type_: i32, protocol: i32) -> i32 {
	debug!(
		"sys_socket: domain {}, type {}, protocol {}",
		domain, type_, protocol
	);

	if (domain != AF_INET && domain != AF_INET6)
		|| (type_ != SOCK_STREAM && type_ != SOCK_DGRAM)
		|| (protocol != 0 && protocol != IPPROTO_UDP && protocol != IPPROTO_TCP)
	{
		-EINVAL
	} else {
		let mut guard = NIC.lock();

		if let NetworkState::Initialized(nic) = guard.deref_mut() {
			let fd = FD_COUNTER.fetch_add(1, Ordering::SeqCst);

			if protocol == IPPROTO_UDP {
				let handle = nic.create_udp_handle().unwrap();
				let socket = self::udp::Socket::new(handle);
				if OBJECT_MAP.write().try_insert(fd, Arc::new(socket)).is_err() {
					-EINVAL
				} else {
					fd
				}
			} else {
				let handle = nic.create_tcp_handle().unwrap();
				if domain == AF_INET {
					let socket = self::tcp::Socket::<self::tcp::IPv4>::new(handle);
					if OBJECT_MAP.write().try_insert(fd, Arc::new(socket)).is_err() {
						-EINVAL
					} else {
						fd
					}
				} else {
					let socket = self::tcp::Socket::<self::tcp::IPv6>::new(handle);
					if OBJECT_MAP.write().try_insert(fd, Arc::new(socket)).is_err() {
						-EINVAL
					} else {
						fd
					}
				}
			}
		} else {
			-EINVAL
		}
	}
}

pub(crate) extern "C" fn __sys_accept(
	fd: i32,
	addr: *mut sockaddr,
	addrlen: *mut socklen_t,
) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(
		|e| e,
		|v| {
			let result = (*v).accept(addr, addrlen);
			if result >= 0 {
				let new_obj = dyn_clone::clone_box(&*v);
				insert_object(fd, Arc::from(new_obj));
				let new_fd = FD_COUNTER.fetch_add(1, Ordering::SeqCst);
				(*v).listen(1);
				insert_object(new_fd, v.clone());
				new_fd
			} else {
				result
			}
		},
	)
}

pub(crate) extern "C" fn __sys_listen(fd: i32, backlog: i32) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).listen(backlog))
}

pub(crate) extern "C" fn __sys_bind(fd: i32, name: *const sockaddr, namelen: socklen_t) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).bind(name, namelen))
}

pub(crate) extern "C" fn __sys_connect(fd: i32, name: *const sockaddr, namelen: socklen_t) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).connect(name, namelen))
}

pub(crate) extern "C" fn __sys_getsockname(
	fd: i32,
	name: *mut sockaddr,
	namelen: *mut socklen_t,
) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).getsockname(name, namelen))
}

pub(crate) extern "C" fn __sys_setsockopt(
	fd: i32,
	level: i32,
	optname: i32,
	optval: *const c_void,
	optlen: socklen_t,
) -> i32 {
	debug!(
		"sys_setsockopt: {}, level {}, optname {}",
		fd, level, optname
	);

	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).setsockopt(level, optname, optval, optlen))
}

pub(crate) extern "C" fn __sys_getsockopt(
	fd: i32,
	level: i32,
	optname: i32,
	optval: *mut c_void,
	optlen: *mut socklen_t,
) -> i32 {
	debug!(
		"sys_getsockopt: {}, level {}, optname {}",
		fd, level, optname
	);

	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).getsockopt(level, optname, optval, optlen))
}

pub(crate) extern "C" fn __sys_getpeername(
	fd: i32,
	name: *mut sockaddr,
	namelen: *mut socklen_t,
) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).getpeername(name, namelen))
}

pub extern "C" fn __sys_freeaddrinfo(_ai: *mut addrinfo) {}

pub extern "C" fn __sys_getaddrinfo(
	_nodename: *const u8,
	_servname: *const u8,
	_hints: *const addrinfo,
	_res: *mut *mut addrinfo,
) -> i32 {
	-EINVAL
}

pub extern "C" fn __sys_shutdown_socket(fd: i32, how: i32) -> i32 {
	let obj = get_object(fd);
	obj.map_or_else(|e| e, |v| (*v).shutdown(how))
}

pub extern "C" fn __sys_recv(fd: i32, buf: *mut u8, len: usize) -> isize {
	let obj = get_object(fd);
	obj.map_or_else(|e| e as isize, |v| (*v).read(buf, len))
}