Create and map shared memory pool with libc
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -5,3 +5,12 @@ version = 4
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ChloroStart-rs"
|
name = "ChloroStart-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.171"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
|||||||
73
src/main.rs
73
src/main.rs
@@ -1,14 +1,19 @@
|
|||||||
use std::{env, error::Error, io::{Read, Write}, os::unix::net::UnixStream, u32};
|
#![feature(unix_socket_ancillary_data)]
|
||||||
|
use std::{env, error::Error, io::{Read, Write}, os::unix::net::{UnixStream, SocketAncillary, AncillaryData}, u32};
|
||||||
|
|
||||||
|
use shm::shm::ShmPool;
|
||||||
|
mod shm;
|
||||||
|
|
||||||
struct WlState {
|
struct WlState {
|
||||||
socket: UnixStream,
|
socket: UnixStream,
|
||||||
current_id: u32,
|
current_id: u32,
|
||||||
registry_id: Option<u32>,
|
registry_id: Option<u32>,
|
||||||
shm_id: Option<u32>
|
shm_id: Option<u32>,
|
||||||
|
shm_pool: Option<ShmPool>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WlHeader {
|
struct WlHeader {
|
||||||
object: u32,30334241
|
object: u32,
|
||||||
opcode: u16,
|
opcode: u16,
|
||||||
size: u16
|
size: u16
|
||||||
}
|
}
|
||||||
@@ -171,6 +176,63 @@ fn wl_shm_format(event: &Vec<u8>) {
|
|||||||
println!("Received pixel format: {:x}", event.read_u32(&mut offset));
|
println!("Received pixel format: {:x}", event.read_u32(&mut offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wl_shm_create_pool(wl_state: &mut WlState) -> Result<(), String> {
|
||||||
|
wl_state.current_id += 1;
|
||||||
|
wl_state.shm_pool = Some(match ShmPool::new(4096, wl_state.current_id) {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(err.to_string());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let object = match wl_state.shm_id {
|
||||||
|
Some(val) => val,
|
||||||
|
None => {
|
||||||
|
return Err("error in wl_shm_create_pool: shm_id not set!".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const OPCODE: u16 = 0;
|
||||||
|
const REQ_SIZE: u16 = 16;
|
||||||
|
let id = wl_state.shm_pool.as_ref().unwrap().id;
|
||||||
|
let fds = [wl_state.shm_pool.as_ref().unwrap().fd];
|
||||||
|
let shm_size = wl_state.shm_pool.as_ref().unwrap().size;
|
||||||
|
|
||||||
|
let mut request = vec![0u8; REQ_SIZE as usize];
|
||||||
|
let mut offset: usize = 0;
|
||||||
|
|
||||||
|
// Request header
|
||||||
|
request.write_u32(&object, &mut offset);
|
||||||
|
request.write_u16(&OPCODE, &mut offset);
|
||||||
|
request.write_u16(&REQ_SIZE, &mut offset);
|
||||||
|
|
||||||
|
// Id, size of shm pool
|
||||||
|
request.write_u32(&id, &mut offset);
|
||||||
|
request.write_u32(&(shm_size as u32), &mut offset);
|
||||||
|
|
||||||
|
println!("{:?}", request);
|
||||||
|
|
||||||
|
let mut ancillary_buf = [0u8; 32];
|
||||||
|
let mut ancillary = SocketAncillary::new(&mut ancillary_buf[..]);
|
||||||
|
assert!(ancillary.add_fds(&fds[..]));
|
||||||
|
|
||||||
|
match wl_state.socket.send_vectored_with_ancillary(&[std::io::IoSlice::new(&request)], &mut ancillary) {
|
||||||
|
Ok(bytes) => {
|
||||||
|
assert!(bytes == REQ_SIZE as usize);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(err.to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wl_shm_pool_resize(event: &Vec<u8>, wl_state: &mut WlState) -> std::io::Result<()> {
|
||||||
|
let mut offset: usize = 0;
|
||||||
|
let size = event.read_u32(&mut offset);
|
||||||
|
wl_state.shm_pool.as_mut().unwrap().resize(size as usize)
|
||||||
|
}
|
||||||
|
|
||||||
fn wl_registry_global(event: &Vec<u8>, wl_state: &mut WlState) -> Result<(), Box<dyn Error>> {
|
fn wl_registry_global(event: &Vec<u8>, wl_state: &mut WlState) -> Result<(), Box<dyn Error>> {
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
|
|
||||||
@@ -195,6 +257,7 @@ fn wl_registry_global(event: &Vec<u8>, wl_state: &mut WlState) -> Result<(), Box
|
|||||||
&wl_state.current_id.clone()
|
&wl_state.current_id.clone()
|
||||||
)?;
|
)?;
|
||||||
wl_state.shm_id = Some(wl_state.current_id);
|
wl_state.shm_id = Some(wl_state.current_id);
|
||||||
|
wl_shm_create_pool(wl_state)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -215,6 +278,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
current_id: 1,
|
current_id: 1,
|
||||||
registry_id: None,
|
registry_id: None,
|
||||||
shm_id: None,
|
shm_id: None,
|
||||||
|
shm_pool: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
wl_display_get_registry(&mut wl_state)?;
|
wl_display_get_registry(&mut wl_state)?;
|
||||||
@@ -243,6 +307,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
else if wl_state.shm_id.is_some() && header.object == wl_state.shm_id.unwrap() && header.opcode == 0 { // wl_shm::format
|
else if wl_state.shm_id.is_some() && header.object == wl_state.shm_id.unwrap() && header.opcode == 0 { // wl_shm::format
|
||||||
wl_shm_format(&event);
|
wl_shm_format(&event);
|
||||||
}
|
}
|
||||||
|
else if wl_state.shm_pool.is_some() && header.object == wl_state.shm_pool.as_ref().unwrap().id && header.opcode == 2 {
|
||||||
|
wl_shm_pool_resize(&event, &mut wl_state)?;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
println!(
|
println!(
|
||||||
"Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}",
|
"Received event:\n\tObject: {}\n\tOpcode: {}\n\tSize: {}",
|
||||||
|
|||||||
62
src/shm.rs
Normal file
62
src/shm.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
pub mod shm {
|
||||||
|
|
||||||
|
use libc::{c_void, ftruncate, mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_SHARED, O_CREAT, O_EXCL, O_RDWR, PROT_READ};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ShmPool {
|
||||||
|
pub fd: i32,
|
||||||
|
pub id: u32,
|
||||||
|
pub addr: *mut c_void,
|
||||||
|
pub size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShmPool {
|
||||||
|
pub fn new(size: usize, id: u32) -> std::io::Result<ShmPool> {
|
||||||
|
let shm_path: *const i8 = b"/chlorostart\0".as_ptr() as *const i8;
|
||||||
|
let fd = unsafe { shm_open(shm_path, O_RDWR | O_EXCL | O_CREAT, 0o600) };
|
||||||
|
if fd == -1 {
|
||||||
|
eprint!("shm_open in ShmPool::new() failed: ");
|
||||||
|
return Err(std::io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
if unsafe { shm_unlink(shm_path) } == -1 {
|
||||||
|
eprint!("shm_unlink in ShmPool::new() failed: ");
|
||||||
|
return Err(std::io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
if unsafe { ftruncate(fd, size as i64) } == -1 {
|
||||||
|
eprint!("ftruncate in ShmPool::new() failed: ");
|
||||||
|
return Err(std::io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
let addr = unsafe {
|
||||||
|
mmap(std::ptr::null_mut(), size, PROT_READ | PROT_READ, MAP_SHARED, fd, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
if addr == MAP_FAILED {
|
||||||
|
eprint!("mmap in ShmPool::new() failed: ");
|
||||||
|
return Err(std::io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ShmPool {
|
||||||
|
fd,
|
||||||
|
id,
|
||||||
|
addr,
|
||||||
|
size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, size: usize) -> std::io::Result<()> {
|
||||||
|
if unsafe { ftruncate(self.fd, size as i64) } == -1 {
|
||||||
|
return Err(std::io::Error::last_os_error())
|
||||||
|
};
|
||||||
|
self.size = size;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ShmPool {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { munmap(self.addr, self.size); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user