Skip to content

Commit

Permalink
release: airup v0.10.3
Browse files Browse the repository at this point in the history
This version contains bug fixes, performance improvements and breaking
changes. See CHANGELOG for details.
  • Loading branch information
sisungo committed Jun 16, 2024
1 parent 6b2f83e commit a3e6722
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 47 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Changes in v0.10.3:
* fix: line pipers (used for stdio logging) removes `\n`, `\r` or `\0` which is placed on the end of a line
* BREAKING: make `system.refresh` return `[(string, error)]` instead of `null`
* BREAKING: error code `NO_SUCH_METHOD` is renamed to `NOT_IMPLEMENTED`
* performance improvements

Changes in v0.10.2:
* fix: cannot actually unset an environment variable becuase toml lacks support of `null`
* fix: #33 "reboot-in-reboot"
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Supported Versions
The `HEAD` and the latest release are supported by the Airup developers. The maintained versions are:
- Mainline: `0.10.3`
- Stable: `0.10.2`
- Stable: `0.10.3`

## Reporting a Vulnerability
Please [contact @sisungo](mailto:[email protected]) to report a vulnerability.
26 changes: 12 additions & 14 deletions airup-sdk/src/blocking/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,24 @@ impl Connection {

/// Receives a datagram and deserializes it from CBOR to `T`.
pub fn recv<T: DeserializeOwned>(&mut self) -> Result<T, IpcError> {
Ok(ciborium::from_reader(&self.0.recv()?[..])?)
let mut buf = Vec::new();
self.0.recv(&mut buf)?;
Ok(ciborium::from_reader(&buf[..])?)
}

/// Receives a request from the underlying protocol.
pub fn recv_req(&mut self) -> Result<Request, IpcError> {
let req: Request = ciborium::from_reader(&self.0.recv()?[..]).unwrap_or_else(|err| {
let mut buf = Vec::new();
self.0.recv(&mut buf)?;
let req: Request = ciborium::from_reader(&buf[..]).unwrap_or_else(|err| {
Request::new(
"debug.echo_raw",
Response::Err(ApiError::bad_request("InvalidJson", err.to_string())),
Response::Err(ApiError::bad_request("InvalidCbor", err.to_string())),
)
});
Ok(req)
}

/// Receives a response from the underlying protocol.
pub fn recv_resp(&mut self) -> Result<Response, IpcError> {
self.recv()
}

/// Sends a datagram with CBOR-serialized given object.
pub fn send<T: Serialize>(&mut self, obj: &T) -> Result<(), IpcError> {
let mut buffer = Vec::with_capacity(128);
Expand All @@ -64,24 +63,23 @@ impl DerefMut for Connection {

pub trait MessageProtoRecvExt {
/// Receives a message from the stream.
fn recv(&mut self) -> Result<Vec<u8>, IpcError>;
fn recv(&mut self, buf: &mut Vec<u8>) -> Result<(), IpcError>;
}
pub trait MessageProtoSendExt {
/// Sends a message to the stream
fn send(&mut self, blob: &[u8]) -> Result<(), IpcError>;
}
impl<T: Read> MessageProtoRecvExt for MessageProto<T> {
fn recv(&mut self) -> Result<Vec<u8>, IpcError> {
fn recv(&mut self, buf: &mut Vec<u8>) -> Result<(), IpcError> {
let mut len = [0u8; 8];
self.inner.read_exact(&mut len)?;
let len = u64::from_le_bytes(len) as usize;
if len > self.size_limit {
return Err(IpcError::MessageTooLong(len));
}
let mut blob = vec![0u8; len];
self.inner.read_exact(&mut blob)?;

Ok(blob)
buf.resize(len, 0u8);
self.inner.read_exact(buf)?;
Ok(())
}
}
impl<T: Write> MessageProtoSendExt for MessageProto<T> {
Expand Down
9 changes: 7 additions & 2 deletions airup-sdk/src/blocking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ impl Connection {

/// Receives a raw message.
pub fn recv_raw(&mut self) -> Result<Vec<u8>, IpcError> {
(*self.underlying).recv()
let mut buf = Vec::new();
(*self.underlying).recv(&mut buf)?;
Ok(buf)
}

/// Invokes an RPC method.
Expand All @@ -44,7 +46,10 @@ impl Connection {
) -> Result<Result<T, ApiError>, IpcError> {
let req = Request::new(method, params);
self.underlying.send(&req)?;
Ok(self.underlying.recv_resp()?.into_result())
Ok(self
.underlying
.recv::<crate::ipc::Response>()?
.into_result())
}
}
impl Deref for Connection {
Expand Down
2 changes: 1 addition & 1 deletion airup-sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use thiserror::Error;
pub enum ApiError {
/// The requested method was not found.
#[error("function not implemented")]
NoSuchMethod,
NotImplemented,

/// The requested method's parameter requirements wasn't satisfied.
#[error("invalid parameters: {message}")]
Expand Down
2 changes: 1 addition & 1 deletion airup-sdk/src/ffi/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn api_function_complex<
}
Err(err) => {
let err = crate::Error::Io {
message: err.to_string(),
message: err.to_string().into(),
};
set_last_error(err.into());
None
Expand Down
34 changes: 16 additions & 18 deletions airup-sdk/src/nonblocking/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,24 @@ impl Connection {

/// Receives a datagram and deserializes it from CBOR to `T`.
pub async fn recv<T: DeserializeOwned>(&mut self) -> Result<T, IpcError> {
Ok(ciborium::from_reader(Cursor::new(self.0.recv().await?))?)
let mut buf = Vec::new();
self.0.recv(&mut buf).await?;
Ok(ciborium::from_reader(&buf[..])?)
}

/// Receives a request from the underlying protocol.
pub async fn recv_req(&mut self) -> Result<Request, IpcError> {
let req: Request =
ciborium::from_reader(Cursor::new(self.0.recv().await?)).unwrap_or_else(|err| {
Request::new(
"debug.echo_raw",
Response::Err(ApiError::bad_request("InvalidJson", err.to_string())),
)
});
let mut buf = Vec::new();
self.0.recv(&mut buf).await?;
let req: Request = ciborium::from_reader(&buf[..]).unwrap_or_else(|err| {
Request::new(
"debug.echo_raw",
Response::Err(ApiError::bad_request("InvalidCbor", err.to_string())),
)
});
Ok(req)
}

/// Receives a response from the underlying protocol.
pub async fn recv_resp(&mut self) -> Result<Response, IpcError> {
self.recv().await
}

/// Sends a datagram with CBOR-serialized given object.
pub async fn send<T: Serialize>(&mut self, obj: &T) -> Result<(), IpcError> {
let mut buffer = Cursor::new(Vec::with_capacity(128));
Expand Down Expand Up @@ -84,22 +82,22 @@ impl Server {

pub trait MessageProtoRecvExt {
/// Receives a message from the stream.
fn recv(&mut self) -> impl Future<Output = Result<Vec<u8>, IpcError>>;
fn recv(&mut self, buf: &mut Vec<u8>) -> impl Future<Output = Result<(), IpcError>>;
}
pub trait MessageProtoSendExt {
/// Sends a message to the stream.
fn send(&mut self, blob: &[u8]) -> impl Future<Output = Result<(), IpcError>>;
}
impl<T: AsyncRead + Unpin> MessageProtoRecvExt for MessageProto<T> {
async fn recv(&mut self) -> Result<Vec<u8>, IpcError> {
async fn recv(&mut self, buf: &mut Vec<u8>) -> Result<(), IpcError> {
let len = self.inner.read_u64_le().await? as usize;
if len > self.size_limit {
return Err(IpcError::MessageTooLong(len));
}
let mut blob = vec![0u8; len];
self.inner.read_exact(&mut blob).await?;
buf.resize(len, 0u8);
self.inner.read_exact(buf).await?;

Ok(blob)
Ok(())
}
}
impl<T: AsyncWrite + Unpin> MessageProtoSendExt for MessageProto<T> {
Expand Down
10 changes: 8 additions & 2 deletions airup-sdk/src/nonblocking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ impl Connection {

/// Receives a raw message.
pub async fn recv_raw(&mut self) -> Result<Vec<u8>, IpcError> {
(*self.underlying).recv().await
let mut buf = Vec::new();
(*self.underlying).recv(&mut buf).await?;
Ok(buf)
}

/// Invokes an RPC method.
Expand All @@ -46,7 +48,11 @@ impl Connection {
) -> Result<Result<T, ApiError>, IpcError> {
let req = Request::new(method, params);
self.underlying.send(&req).await?;
Ok(self.underlying.recv_resp().await?.into_result())
Ok(self
.underlying
.recv::<crate::ipc::Response>()
.await?
.into_result())
}
}
impl Deref for Connection {
Expand Down
9 changes: 5 additions & 4 deletions airupd/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl Extensions {
Extension::new(name, path)
.await
.map_err(|x| airup_sdk::Error::Io {
message: x.to_string(),
message: x.to_string().into(),
})?,
),
);
Expand All @@ -44,10 +44,10 @@ impl Extensions {
let mut method_splited = req.method.splitn(2, '.');
let extension = method_splited.next().unwrap();
let Some(ext_method) = method_splited.next() else {
return airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NoSuchMethod));
return airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NotImplemented));
};
let Some(ext) = self.0.read().await.get(extension).cloned() else {
return airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NoSuchMethod));
return airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NotImplemented));
};
req.method = ext_method.into();

Expand Down Expand Up @@ -143,8 +143,9 @@ impl ExtensionHost {
let mut handler = {
let reqs = Arc::clone(&reqs);
tokio::spawn(async move {
let mut buf = Vec::with_capacity(4096);
loop {
let Ok(buf) = rx.recv().await else {
if rx.recv(&mut buf).await.is_err() {
return;
};
let Ok(resp) = ciborium::from_reader::<Response, _>(&buf[..]) else {
Expand Down
2 changes: 1 addition & 1 deletion airupd/src/ipc/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Manager {
let method = self.methods.get(&req.method[..]).copied();
match method {
Some(method) => Response::new(method(req).await),
None => Response::Err(Error::NoSuchMethod),
None => Response::Err(Error::NotImplemented),
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions airupfx/airupfx-extensions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,10 @@ impl Session {
}

pub async fn run(mut self) -> anyhow::Result<()> {
let mut buf = Vec::with_capacity(4096);
loop {
let request: airup_sdk::extension::Request =
ciborium::from_reader(&self.rx.recv().await?[..])?;
self.rx.recv(&mut buf).await?;
let request: airup_sdk::extension::Request = ciborium::from_reader(&buf[..])?;
self.handle_request(request);
}
}
Expand Down Expand Up @@ -171,7 +172,7 @@ impl Session {
) -> airup_sdk::ipc::Response {
match rpc_methods.get(&request.method) {
Some(method) => airup_sdk::ipc::Response::new(method(request).await),
None => airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NoSuchMethod)),
None => airup_sdk::ipc::Response::new::<()>(Err(airup_sdk::Error::NotImplemented)),
}
}
}
Expand Down

0 comments on commit a3e6722

Please sign in to comment.