| # p2p: Service for sharing files between Chrome OS devices |
| |
| [TOC] |
| |
| ## About |
| |
| `p2p` is a software package for advertising and discovering content on the |
| local network (LAN). It is built on top of HTTP and mDNS/DNS-SD. `p2p` is |
| written specifically for Chrome OS and uses services and conventions specific |
| to that OS. It is not intended to be portable to other OSes. |
| |
| ## Files |
| |
| Content to be shared with other devices on the LAN is to stored in an encrypted |
| part of the stateful partition. The following directory is used: |
| |
| /var/cache/p2p |
| |
| In the following this directory shall be referred to as `$(P2P_DIR)`. |
| |
| ## Theory of Operation |
| |
| Files to be shared are advertised via a DNS-SD service with the service type |
| `_cros_p2p._tcp`. |
| |
| The address and port number advertised in the DNS-SD service refer to a HTTP |
| server running on the same machine. To simplify firewall management, port 16725 |
| ("AU") is always used but in the future this may by dynamic. |
| |
| Any file with a `.p2p` file extension in `$(P2P_DIR)` is advertised as a TXT |
| record in a DNS-SD response where its value is the length of the file (decimal |
| encoding). For example, if the file `$(P2P_DIR)/some_payload.bin.p2p` exists |
| and is 123456789 bytes long, the DNS-SD response will advertise a TXT record |
| `id_some_payload.bin=123456789` (the `id_` prefix is there just for namespacing |
| purposes). By convention, this allows any client to download the file using the |
| URL |
| |
| http://<IP>:<PORT>/some_payload.bin |
| |
| where `IP` and `PORT` is taken from the DNS-SD response. Additionally, to allow |
| sharing files that are not completely downloaded yet, one can set the |
| `user.cros-p2p-filesize` extended attribute with the final size. This will make |
| the HTTP server block until content is available. Note that the mDNS/DNS-SD |
| response always returns the size of the file on disk - this is to allow a peer |
| to pick the peer with e.g. the most downloaded bytes. |
| |
| Note that the size set in the `user.cros-p2p-filesize` extended attribute - if |
| present - is always constant (because it contains the final size of the file). |
| In contrast, the size conveyed via the mDNS/DNS-SD response reflects the actual |
| size of the file which grows as more and more data is being downloaded. As |
| such, this value is not necessarily constant and in fact, by virtue of how |
| mDNS/DNS-SD works, changes to the value are propagated on the local network. To |
| conserve bandwidth with frequently changing files, file size changes are |
| propagated at most every ten seconds. |
| |
| The `$(P2P_DIR)` directory is the sole interface for other software on the |
| local system to share files with other peers. For example, if the |
| `update_engine` program (used for updating Chrome OS) is downloading an payload |
| it can create a file, say `$(P2P_DIR)/some_update_xyz.bin.p2p.tmp` and start |
| writing to it as it downloads the rest of the payload. When the `update_engine` |
| program has verified that the file is authentic (by e.g. checking a |
| cryptographic signature in the beginning of the file) and it knows the final |
| size, it can |
| |
| - sets the `user.cros-p2p-filesize` xattr to the size |
| - rename the .tmp extension away |
| - proceed to write payload to the file |
| |
| and, hey presto, the file some_`update_xyz.bin` is now shared with the rest of |
| the local network. |
| |
| In addition to advertising files, the `_cros_p2p._tcp` DNS-SD service will also |
| advertise the current number of HTTP connections in the num-connections TXT |
| attribute. This can used (in a cooperative manner) to limit the number of |
| simultaneous downloads in the LAN. |
| |
| ## Programs |
| |
| The `p2p` package is comprised of three programs. |
| |
| ### `p2p-server` |
| |
| The primary purpose of this program is to monitor the `$(P2P_DIR)` directory |
| and advertise `.p2p` files via mDNS/DNS-SD (it uses the Avahi package to do |
| this). When there is a non-zero number of .p2p files, it will start the |
| `p2p-http-server` program and when the number of `.p2p` files drop to zero it |
| will terminate kill the instance. |
| |
| This program is run as a daemon (long-running process) and is usually started |
| via an Upstart job, `p2p`, to ensure the firewall is properly configured |
| (specifically, opening the TCP port that the HTTP server will listen on), its |
| dependencies (e.g. Avahi) has started and that the program is launched with |
| appropriate privileges (using minijail0 to drop privileges). |
| |
| ### `p2p-http-server` |
| |
| The purpose of this program is to serve `.p2p` files via HTTP. It is started |
| and stopped by the `p2p-server` server, when needed. |
| |
| ### `p2p-client` |
| |
| This is a simple program to discover content available on the LAN. Given a file |
| identifier, it looks on the LAN for `_cros_p2p._tcp` DNS-SD services. If one or |
| more peers have the file, `p2p-client` picks one of them and prints the URL on |
| stdout. |
| |
| ## Users and Permissions |
| |
| ### `p2p` User and Group |
| |
| The `p2p` user (and `p2p` group) is used to run `p2p-server` and |
| `p2p-http-server` without root privileges. |
| |
| ### Permissions on `$(P2P_DIR)` |
| |
| The `$(P2P_DIR)` is owned by root and its permissions are `rwxr-xr-x`, that is |
| |
| - any (non-jailed) user on the system can read files in `$(P2P_DIR)` |
| - only root can write files |
| |
| In the future a more sophisticated ACL scheme may be introduced to allow known |
| unprivileged programs (say, `update_engine`) to share content. |
| |
| ## Frequently Asked Questions |
| |
| (TODO: write me) |