Skip to content

Commit 6f6622b

Browse files
committed
Cleanly split fd-vs-nofds request APIs
Most requests don't have fds, so let's optimize it a bit and avoid the callers needing to have `()` spelled out. Signed-off-by: Colin Walters <[email protected]>
1 parent d5dc71a commit 6f6622b

File tree

1 file changed

+33
-14
lines changed

1 file changed

+33
-14
lines changed

src/imageproxy.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ impl ImageProxy {
444444
};
445445

446446
// Verify semantic version
447-
let (protover, _): (String, ()) = r.impl_request("Initialize", [(); 0]).await?;
447+
let protover: String = r.impl_request("Initialize", [(); 0]).await?;
448448
tracing::debug!("Remote protocol version: {protover}");
449449
let protover = semver::Version::parse(protover.as_str())?;
450450
// Previously we had a feature to opt-in to requiring newer versions using `if cfg!()`.
@@ -460,6 +460,7 @@ impl ImageProxy {
460460
Ok(r)
461461
}
462462

463+
/// Create and send a request. Should only be used by impl_request.
463464
async fn impl_request_raw<T: serde::de::DeserializeOwned + Send + 'static, F: FromReplyFds>(
464465
sockfd: Arc<Mutex<OwnedFd>>,
465466
req: Request,
@@ -509,8 +510,13 @@ impl ImageProxy {
509510
Ok(r)
510511
}
511512

513+
/// Create a request that may return file descriptors, and also check for an unexpected
514+
/// termination of the child process.
512515
#[instrument(skip(args))]
513-
async fn impl_request<T: serde::de::DeserializeOwned + Send + 'static, F: FromReplyFds>(
516+
async fn impl_request_with_fds<
517+
T: serde::de::DeserializeOwned + Send + 'static,
518+
F: FromReplyFds,
519+
>(
514520
&self,
515521
method: &str,
516522
args: impl IntoIterator<Item = impl Into<serde_json::Value>>,
@@ -527,24 +533,36 @@ impl ImageProxy {
527533
}
528534
}
529535

536+
/// A synchronous invocation which does not return any file descriptors.
537+
async fn impl_request<T: serde::de::DeserializeOwned + Send + 'static>(
538+
&self,
539+
method: &str,
540+
args: impl IntoIterator<Item = impl Into<serde_json::Value>>,
541+
) -> Result<T> {
542+
let (r, ()) = self.impl_request_with_fds(method, args).await?;
543+
Ok(r)
544+
}
545+
530546
#[instrument]
531547
async fn finish_pipe(&self, pipeid: PipeId) -> Result<()> {
532548
tracing::debug!("closing pipe");
533-
let (r, ()) = self.impl_request("FinishPipe", [pipeid.0.get()]).await?;
549+
let (r, ()) = self
550+
.impl_request_with_fds("FinishPipe", [pipeid.0.get()])
551+
.await?;
534552
Ok(r)
535553
}
536554

537555
#[instrument]
538556
pub async fn open_image(&self, imgref: &str) -> Result<OpenedImage> {
539557
tracing::debug!("opening image");
540-
let (imgid, ()) = self.impl_request("OpenImage", [imgref]).await?;
558+
let imgid = self.impl_request("OpenImage", [imgref]).await?;
541559
Ok(OpenedImage(imgid))
542560
}
543561

544562
#[instrument]
545563
pub async fn open_image_optional(&self, imgref: &str) -> Result<Option<OpenedImage>> {
546564
tracing::debug!("opening image");
547-
let (imgid, ()) = self.impl_request("OpenImageOptional", [imgref]).await?;
565+
let imgid = self.impl_request("OpenImageOptional", [imgref]).await?;
548566
if imgid == 0 {
549567
Ok(None)
550568
} else {
@@ -554,9 +572,7 @@ impl ImageProxy {
554572

555573
#[instrument]
556574
pub async fn close_image(&self, img: &OpenedImage) -> Result<()> {
557-
tracing::debug!("closing image");
558-
let (r, ()) = self.impl_request("CloseImage", [img.0]).await?;
559-
Ok(r)
575+
self.impl_request("CloseImage", [img.0]).await
560576
}
561577

562578
async fn read_finish_pipe(&self, pipe: FinishPipe) -> Result<Vec<u8>> {
@@ -574,7 +590,7 @@ impl ImageProxy {
574590
/// The original digest of the unconverted manifest is also returned.
575591
/// For more information on OCI manifests, see <https://github.com/opencontainers/image-spec/blob/main/manifest.md>
576592
pub async fn fetch_manifest_raw_oci(&self, img: &OpenedImage) -> Result<(String, Vec<u8>)> {
577-
let (digest, pipefd) = self.impl_request("GetManifest", [img.0]).await?;
593+
let (digest, pipefd) = self.impl_request_with_fds("GetManifest", [img.0]).await?;
578594
Ok((digest, self.read_finish_pipe(pipefd).await?))
579595
}
580596

@@ -592,7 +608,7 @@ impl ImageProxy {
592608
/// Fetch the config.
593609
/// For more information on OCI config, see <https://github.com/opencontainers/image-spec/blob/main/config.md>
594610
pub async fn fetch_config_raw(&self, img: &OpenedImage) -> Result<Vec<u8>> {
595-
let ((), pipe) = self.impl_request("GetFullConfig", [img.0]).await?;
611+
let ((), pipe) = self.impl_request_with_fds("GetFullConfig", [img.0]).await?;
596612
self.read_finish_pipe(pipe).await
597613
}
598614

@@ -630,7 +646,8 @@ impl ImageProxy {
630646
tracing::debug!("fetching blob");
631647
let args: Vec<serde_json::Value> =
632648
vec![img.0.into(), digest.to_string().into(), size.into()];
633-
let (bloblen, pipe): (u64, FinishPipe) = self.impl_request("GetBlob", args).await?;
649+
let (bloblen, pipe): (u64, FinishPipe) =
650+
self.impl_request_with_fds("GetBlob", args).await?;
634651
let _: u64 = bloblen;
635652
let fd = tokio::fs::File::from_std(std::fs::File::from(pipe.datafd));
636653
let fd = tokio::io::BufReader::new(fd);
@@ -679,7 +696,7 @@ impl ImageProxy {
679696
)> {
680697
tracing::debug!("fetching blob");
681698
let args: Vec<serde_json::Value> = vec![img.0.into(), digest.to_string().into()];
682-
let (bloblen, fds): (u64, DualFds) = self.impl_request("GetRawBlob", args).await?;
699+
let (bloblen, fds): (u64, DualFds) = self.impl_request_with_fds("GetRawBlob", args).await?;
683700
let fd = tokio::fs::File::from_std(std::fs::File::from(fds.datafd));
684701
let err = Self::read_blob_error(fds.errfd).boxed();
685702
Ok((bloblen, fd, err))
@@ -707,14 +724,16 @@ impl ImageProxy {
707724
) -> Result<Option<Vec<ConvertedLayerInfo>>> {
708725
tracing::debug!("Getting layer info");
709726
if layer_info_piped_proto_version().matches(&self.protover) {
710-
let ((), pipe) = self.impl_request("GetLayerInfoPiped", [img.0]).await?;
727+
let ((), pipe) = self
728+
.impl_request_with_fds("GetLayerInfoPiped", [img.0])
729+
.await?;
711730
let buf = self.read_finish_pipe(pipe).await?;
712731
return Ok(Some(serde_json::from_slice(&buf)?));
713732
}
714733
if !layer_info_proto_version().matches(&self.protover) {
715734
return Ok(None);
716735
}
717-
let (layers, ()) = self.impl_request("GetLayerInfo", [img.0]).await?;
736+
let layers = self.impl_request("GetLayerInfo", [img.0]).await?;
718737
Ok(Some(layers))
719738
}
720739

0 commit comments

Comments
 (0)