Expand description
An HTTP proxy for IPP-over-USB devices
§Introduction
IPP-over-USB (or IPP-USB) is a standardized protocol for transporting HTTP through USB printer class interfaces. Even though it has IPP in the name, IPP-USB allows transporting arbitrary HTTP requests and responses to a printer’s embedded web server. Some common examples of what it can be used for:
- IPP printing, scanning, and faxing (the original use case)
- Mopria eSCL scanning
- Access to a printer’s internal administrative web pages
Due to limitations in the protocol, IPP-USB cannot be treated as simply a socket that forwards between the host and device. Each HTTP request and response must be transmitted in its entirety to avoid leaving partial data in the device’s USB buffers. This is a limitation of the protocol itself, not a limitation of this crate.
This crate provides a simplified interface to IPP-USB that allows applications to make a
device look like a network HTTP server. The application is responsible for setting up a
tokio
runtime, TCP listener, and USB device; then ippusb::Bridge
internally runs an
asynchronous HTTP proxy that forwards requests until a shutdown event is signalled.
§Example
This example bridges a random TCP port on localhost to the ChromeOS virtual-usb-printer. After 30s, it tells the bridge to shut down because the device was unplugged.
use std::time::Duration;
use ippusb::{Bridge, Device, ShutdownReason};
use rusb::{Context, UsbContext};
use tokio::net::TcpListener;
use tokio::runtime::Handle;
use tokio::sync::mpsc;
use tokio::time::sleep;
async fn serve(verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
let context = Context::new()?;
let rusb_device = context.open_device_with_vid_pid(0x18d1, 0x505e)
.ok_or(ippusb::Error::NotIppUsb)?;
let ippusb_device = ippusb::Device::new(verbose, rusb_device)?;
let (tx, rx) = mpsc::channel(1);
let listener = TcpListener::bind("127.0.0.1:0").await?;
let handle = Handle::current();
handle.spawn(async move {
sleep(Duration::from_secs(30)).await;
tx.send(ShutdownReason::Unplugged);
});
let mut bridge = Bridge::new(verbose, rx, listener, ippusb_device, handle);
bridge.run().await;
Ok(())
}
Structs§
Enums§
- Error
- Errors returned while handling IPP-over-USB HTTP requests.
- Shutdown
Reason - Reason for shutting down the proxy.
Functions§
- device_
supports_ ippusb - Check if the given device supports IPP-USB.