{"id":19218869,"url":"https://github.com/openprinting/ipp-usb","last_synced_at":"2025-05-15T04:04:24.148Z","repository":{"id":43062416,"uuid":"231669830","full_name":"OpenPrinting/ipp-usb","owner":"OpenPrinting","description":"ipp-usb -- HTTP reverse proxy, backed by IPP-over-USB connection to device","archived":false,"fork":false,"pushed_at":"2025-04-30T13:23:45.000Z","size":848,"stargazers_count":159,"open_issues_count":19,"forks_count":22,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-15T04:03:38.418Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenPrinting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-03T21:39:28.000Z","updated_at":"2025-05-12T08:46:30.000Z","dependencies_parsed_at":"2024-04-10T11:29:25.344Z","dependency_job_id":"4aa42d06-4791-4c49-a001-230f45ccf293","html_url":"https://github.com/OpenPrinting/ipp-usb","commit_stats":{"total_commits":461,"total_committers":8,"mean_commits":57.625,"dds":0.04338394793926248,"last_synced_commit":"85049d875e56d2819c3d66ff9a7a93a87b04439d"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fipp-usb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fipp-usb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fipp-usb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fipp-usb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenPrinting","download_url":"https://codeload.github.com/OpenPrinting/ipp-usb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270641,"owners_count":22042858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T14:28:34.531Z","updated_at":"2025-05-15T04:04:24.075Z","avatar_url":"https://github.com/OpenPrinting.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ipp-usb\n\n![GitHub](https://img.shields.io/github/license/OpenPrinting/ipp-usb)\n[![Go Report Card](https://goreportcard.com/badge/github.com/OpenPrinting/ipp-usb)](https://goreportcard.com/badge/github.com/OpenPrinting/ipp-usb)\n\n## Introduction\n\n[IPP-over-USB](https://www.usb.org/document-library/ipp-protocol-10)\nallows using the IPP protocol, normally designed for network printers,\nto be used with USB printers as well.\n\nThe idea behind this standard is simple: It allows to send HTTP\nrequests to the device via a USB connection, so enabling IPP, eSCL\n(AirScan) and web console on devices without Ethernet or WiFi\nconnections.\n\nUnfortunately, the naive implementation, which simply relays a TCP\nconnection to USB, does not work. It happens because closing the TCP\nconnection on the client side has a useful side effect of discarding\nall data sent to this connection from the server side, but it does not\nhappen with USB connections. In the case of USB, all data not received\nby the client will remain in the USB buffers, and the next time the\nclient connects to the device, it will receive unexpected data, left\nfrom the previous abnormally completed request.\n\nActually, it is an obvious flaw in the IPP-over-USB standard, but we\nhave to live with it.\n\nSo the implementation, once the HTTP request is sent, must read the\nentire HTTP response, which means that the implementation must\nunderstand the HTTP protocol, and effectively implement a HTTP reverse\nproxy, backed by the IPP-over-USB connection to the device.\n\nAnd this is what the **ipp-usb** program actually does.\n\n## Features in detail\n\n* Implements HTTP proxy, backed by USB connection to IPP-over-USB device\n* Full support of IPP printing, eSCL scanning, and web admin interface\n* DNS-SD advertising for all supported services\n* DNS-SD parameters for IPP based on IPP get-printer-attributes query\n* DNS-SD parameters for eSCL based on parsing GET /eSCL/ScannerCapabilities response\n* TCP port allocation for device is bound to particular device (combination of\nVendorID, ProductID and device serial number), so if the user has multiple\ndevices, they will receive the same TCP port when connected. This allocation\nis persisted on a disk\n* Automatic DNS-SD name conflict resolution. The finally chosen device's\nnetwork name is persisted on a disk\n* Can be started by **UDEV** or run in standalone mode\n* Can share printer to other computers on a network, or use the loopback interface only\n* Can generate very detailed logs for possible troubleshooting\n\n## Under the hood\n\nThough looks simple, ipp-usb does many non obvious things under the hood\n\n* Client-side HTTP connections are completely decoupled from printer-side HTTP-over-USB connections\n* HTTP requests are sanitized, missed headers are added\n* HTTP protocol upgraded from 1.0 to 1.1, if needed\n* Attempts to upgrade HTTP connection to winsock, if unwisely made by web console, are\nprohibited, because it can steal USB connection for a long time\n* Client HTTP requests are fairly balanced between all available 2-3 USB connections,\nregardless of number and persistence of client connections\n* Dropping connection by client properly handled in all cases, even in a middle of sending.\nIn a worst case, printer may receive truncated document, but HTTP transaction will always be\nperformed correctly\n\n## Memory footprint\n\nBeing written on Go, ipp-usb has a large executable size. However, its\nmemory consumption is not very high. When single device is connected,\nipp-usb RSS is similar or even slightly less in comparison to ippusbxd.\nAnd because ipp-usb handles all devices in a single process, it uses noticeably\nless memory that ippusbxd, when serving 2 or more devices.\n\n## External dependencies\n\nThis program has very few external dependencies, namely:\n* `libusb` for USB access\n* `libavahi-common` and `libavahi-client` for DNS-SD\n* Running Avahi daemon\n\n## Binary packages\n\nBinary packages available for the following Linux distros:\n* **Debian** (10)\n* **Fedora** (29, 30, 31 and 32)\n* **openSUSE** (Tumbleweed)\n* **Ubuntu** (18.04, 19.04, 19.10 and 20.04)\n\n**Linux Mint** users may use Ubuntu packages:\n* Linux Mint 18.x - use packages for Ubuntu 16.04\n* Linux Mint 19.x - use packages for Ubuntu 18.04\n\nFollow this link for downloads: https://download.opensuse.org/repositories/home:/pzz/\n\n## Not only Linux\n\nWe are glad to announce that `ipp-usb` was recently included into the\nFreeBSD ports: https://www.freshports.org/print/ipp-usb/\n\nHope, NetBSD/OpenBSD support will be added as well, so technology\nbecomes not Linux-only, but UNIX-wide.\n\n## The ipp-usb Snap\n\nipp-usb is also available as a Snap in the Snap Store: https://snapcraft.io/ipp-usb\n\nBefore you install the Snap, uninstall any already existing\ninstallation of ipp-usb.\n\nSimply install it via any GUI client for the Snap Store (Like \"Ubuntu\nSoftware\") or via command line:\n\n    sudo snap install --edge ipp-usb\n\nNow you can connect and disconnect IPP-over-USB devices and ipp-usb\ngets started by the Snap whenever needed. Also devices which are\nalready connected during boot, start, or update of the Snap are\nconsidered.\n\nYou can also use\n\n    ipp-usb status\n\nto check the status of the running ipp-usb daemon (supported device\nmust be connected for the ipp-usb daemon to be running, accesses only\nthe ipp-usb daemon of the Snap) and\n\n    ipp-usb check\n\nto scan the USB for the presence of potentially supported USB devices\n(7/1/4 interface protocol). This command requires access to the raw\nUSB and therefore on many systems root privileges are required.\n\nThe Snap is automatically updated when further development on ipp-usb\nhappens.\n\nThe configuration file is here:\n\n    /var/snap/ipp-usb/common/etc/ipp-usb.conf\n\nYou can edit it and afterwards restart the Snap to use the changed\nconfiguration.\n\nIncompatibilities of particular devices are handled by workarounds\ndefined in the quirk files. You find them here:\n\n    /var/snap/ipp-usb/common/quirks\n\nYou can add your own quirk files (but if they solve your problem,\nplease report an issue here, with your quirk file attached, so that\nothers with the same problem will get helped, too).\n\nFor quick tests you can also edit the existing files, but they will\nget replaced (and so your changes lost) on the next update of the\nSnap, as we are changing them on any report of further device\nincompatibilities.\n\nThe log file is here\n\n    /var/snap/ipp-usb/common/var/log\n\nand device state files (to assure that each device appears on the same\nport and with the same DNS-SD service name) are here:\n\n    /var/snap/ipp-usb/common/var/dev\n\nYou can also build the Snap locally. This is useful when\n\n* You want to modify ipp-usb\n* You want to learn about snapping Go projects\n* You want to learn about how to use UDEV from within a Snap (note that a Snap cannot install UDEV rules into the system)\n\nTo do so, run from the main directory of this source repository\n\n    snapcraft snap\n\nand then install the resulting Snap with\n\n    sudo snap install --dangerous ipp-usb*.snap\n\nAn installed Snap from the Snap Store will get overwritten/replaced by your Snap.\n\nSome technical notes about this Snap:\n\nSnapping the Go project with one Go library taken from upstream (and\nnot from Ubuntu Core) was rather straight-forward. Only observation\nwas that the Go plugin seems not to do \"make install\". So I had to use\nan \"override-build\" to manually install the auxiliary files\n(ipp-usb.conf, quirk files). I also have adapted the auxiliary file\nand state directories in paths.go in the \"override-build\" scriptlet.\n\nThe real challenge of this Snap was to trigger ipp-usb on the\nappearing (and also the presence) of IPP-over-USB devices.\n\nIn the classic installation of ipp-usb (via \"make install\" or RPM/DEB\npackage installation) a UDEV rules file and a systemd service file (in\nsystemd-udev/) are installed, so that the system automatically triggers\nthe launch of ipp-usb when an appropriate device is connected or\nalready present. A Snap is not able to do so. It cannot install any\nfiles into the system. It can only bring its own, static file system\nand create files only in its own state directory. These locations are\nnot scanned for UDEV rules.\n\nSo the Snap must discover the devices without its own UDEV rules, but\nit still can use UDEV. The trick is to do a generic monitoring of UDEV\nevents and filtering out the USB devices with IPP-over-USB interface\n(7/1/4). If such a device appears, we trigger and ipp-usb launch. We\nalso check on startup of the Snap whether there is such a device\nalready and if so, we also trigger an ipp-usb launch.\n\nipp-usb is run, as in the classic installation, with \"udev\"\nargument. This way it stops by itself when there is no device any more\n(and we do not need to observe the disappearal events of the devices)\nand it is assured that only one single instance of ipp-usb is running.\n\nTo do this with low coding effort I use the UDEV command line tool\nudevadm in a shell script (snap/local/run-ipp-usb). Once it runs in\n\"monitor\" mode to observe the UDEV events. Then we parse the output\nlines to only consider the ones for a device appearing and run\n\"udevadm info -q property\" on each device path, to get the properties\nand filter the 7/1/4 interface. In the beginning we use \"udevadm\ntrigger\" to find the already passed appearal event of a device which\nis already present. So the shell script is an auxiliary daemon to\nstart ipp-usb when needed.\n\n## The ipp-usb Rock\n\n### Install from GitHub Container Registry\n#### Prerequisites\n\n1. **Docker Installed**: Ensure Docker is installed on your system. You can download it from the [official Docker website](https://www.docker.com/get-started).\n```sh\n  sudo snap install docker\n```\n\n#### Step-by-Step Guide\n\nYou can pull the `ipp-usb` Docker image from the GitHub Container Registry.\n\n**From GitHub Container Registry** \u003cbr\u003e\nTo pull the image from the GitHub Container Registry, run the following command:\n```sh\n  sudo docker pull ghcr.io/openprinting/ipp-usb:latest\n```\n\nTo run the container after pulling the image, use:\n```sh\n  sudo docker run -d --network host \\\n      -v /dev/bus/usb:/dev/bus/usb:ro \\\n      --device-cgroup-rule='c 189:* rmw' \\\n      --name ipp-usb \\\n      ghcr.io/openprinting/ipp-usb:latest\n```\n\n- `--network host`: Uses the host network, ensuring IPP-over-USB and Avahi service discovery work correctly.\n- `-v /dev/bus/usb:/dev/bus/usb:ro`: Grants the container read-only access to USB devices.\n- `--device-cgroup-rule='c 189:* rmw'`: Grants the container permission to manage USB devices (189:* covers USB device nodes).\n\nTo check the logs of `ipp-usb`, run:\n```sh\n  sudo docker logs -f ipp-usb\n```\n\n### Building and Running `ipp-usb` Locally\n\n#### Prerequisites\n\n**Docker Installed**: Ensure Docker is installed on your system. You can download it from the [official Docker website](https://www.docker.com/get-started) or from the Snap Store:\n```sh\n  sudo snap install docker\n```\n\n**Rockcraft**: Rockcraft should be installed. You can install Rockcraft using the following command:\n```sh\n  sudo snap install rockcraft --classic\n```\n\n#### Step-by-Step Guide\n\n**Build the `ipp-usb` Rock Image**\n\nThe first step is to build the Rock from the `rockcraft.yaml`. This image will contain all the configurations and dependencies required to run `ipp-usb`.\n\nNavigate to the directory containing `rockcraft.yaml`, then run:\n```sh\n  rockcraft pack -v\n```\n\n**Compile to Docker Image**\n\nOnce the `.rock` file is built, compile a Docker image from it using:\n```sh\n  sudo rockcraft.skopeo --insecure-policy copy oci-archive:\u003crock_image_name\u003e docker-daemon:ipp-usb:latest\n```\n\n**Run the `ipp-usb` Docker Container**\n\n```sh\n  sudo docker run -d --network host \\\n      -v /dev/bus/usb:/dev/bus/usb:ro \\\n      --device-cgroup-rule='c 189:* rmw' \\\n      --name ipp-usb \\\n      ipp-usb:latest\n```\n\n### Accessing the Container Shell\n\nTo enter the running `ipp-usb` container and access a shell inside it, use:\n```sh\n  sudo docker exec -it ipp-usb bash\n```\nThis allows you to inspect logs, debug issues, or manually run commands inside the container.\n\n### Configuration\n\nThe `ipp-usb` container uses a configuration file located at:\n```\n/etc/ipp-usb.conf\n```\nTo customize the configuration, mount a modified config file:\n```sh\n  sudo docker run -d --network host \\\n      -v /dev/bus/usb:/dev/bus/usb:ro \\\n      --device-cgroup-rule='c 189:* rmw' \\\n      -v /path/to/custom/ipp-usb.conf:/etc/ipp-usb.conf:ro \\\n      --name ipp-usb \\\n      ghcr.io/openprinting/ipp-usb:latest\n```\n\n\n## Installation from source\n\nYou will need to install the following packages (exact name depends\nof your Linux distro):\n* libusb development files\n* libavahi-client and libavahi-common development files\n* gcc\n* Go compiler\n* pkg-config\n* git, make and so on\n\nBuilding is really simple:\n\n    git clone https://github.com/OpenPrinting/ipp-usb.git\n    cd ipp-usb\n    make\n\nThen you may `make install` or just try to run `./ipp-usb` directly from\nthe build directory\n\n## Avahi Notes (exposing printer to localhost)\n\nIPP-over-USB normally exposes printer to localhost only, hence it\nrequires DNS-SD announces to work for localhost.\n\nThis requires Avahi 0.8.0 or newer. Older Avahi versions do not\nsupport announcing to localhost.\n\nSome Linux distros (for example recent Ubuntu and Fedora versions)\nhave their Avahi patched to support localhost, others (for example\nDebian) not.\n\nTo determine if your Avahi supports localhost, run the following\ncommand in one terminal session:\n```\n    avahi-publish -s test _test._tcp 1234\n```\nAnd simultaneously the following command in another terminal session\non the same machine:\n```\n    avahi-browse _test._tcp -r\n```\nIf you see localhost in the avahi-browse output, like this:\n```\n    =     lo IPv4 test                                          _test._tcp           local\n       hostname = [localhost]\n       address = [127.0.0.1]\n       port = [1234]\n       txt = []\n```\nyour Avahi is OK. Otherwise, update or patching is required.\n\nSo users of distros that ship a too old Avahi and without the patch\nhave three possibilities:\n1. Update Avahi to 0.8.0 or newer\n2. Apply the patch by themself, rebuild and reinstall avahi-daemon\n3. Configure `ipp-usb` to run on all network interfaces, not only on loopback\n\nIf you decide to apply the patch, get it as `avahi/avahi-localhost.patch`\nin this package or [download it here](https://raw.githubusercontent.com/OpenPrinting/ipp-usb/master/avahi/avahi-localhost.patch).\n\nThe third method is simple to do, just replace `interface = loopback`\nwith `interface = all` in the `ipp-usb.conf` file, but this has the\ndisadvantage of exposing your local USB-connected printer to the\nentire local network, which can be an unwanted side effect, especially\nin a big corporative network.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenprinting%2Fipp-usb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenprinting%2Fipp-usb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenprinting%2Fipp-usb/lists"}