# rsync protocol notes ## rsync (C) structure Older rsync code, with fewer features, is easier to follow. rsyn is trying to support protocol 27, from 2004, the same as openrsync. The receiver process forks off a child (in `do_recv`) where the child receives the files (in `recv_files`) and the parent generates (in `generate_files`.) ## Protocol negotiation Protocol version is selected (in `exchange_version` and `setup_protocol`) as the minimum of the protocols offered by the client and server, which makes sense. There is a separate text-mode greeting, including a protocol version, in `exchange_protocols`, that sends a text string like `"@RSYNCD: %d.%d\n"`. It seems this is only used in the bare-TCP daemon (in `clientserver.c`) not over SSH or locally. In `start_inband_exchange` the client sends authentication and the module and args that it wants to use. There's also a concept of "subprotocols", and comments indicate perhaps this is for pre-release builds. This might not be deployed widely enough to worry about? This is also handled in `check_sub_protocol`. It basically seems to downgrade to the prior protocol if the peer offers a subprotocol version that the the local process doesn't support. `compat.c` looks at the `client_info` string to both determine a protocol, and to find some compatibility flags. This only ever seems to get set from `shell_cmd`, and that in turn seems to only come from the `--rsh` command line option. I don't understand how it could end up with the values this seems to expect, unless perhaps it's passed as a hack in the daemon protocol, without really representing the rsh command? I guess this is set for daemon connections from arguments constructed in `server_options`. ## varint encoding The openrsync docs say that a 8-byte long is preceded by a maximum integer, but it's actually preceded by `(int32) 0xffff_ffff`, in other words -1. (See `read_longint`. In addition to this encoding, there's also `read_varlong` which seems to read a genuinely-variable length encoding.