diff --git a/_static/syncthing.css b/_static/syncthing.css index 4044c7f6b..e08a66d37 100644 --- a/_static/syncthing.css +++ b/_static/syncthing.css @@ -1,7 +1,7 @@ /* These don't get the default font size from the theme for whatever reason. */ -.rst-content blockquote, .rst-content li, .rst-content dd, .rst-content dt { - font-size: 18px; - line-height: 27px; +.rst-content blockquote, .rst-content li, .rst-content dd, .rst-content dt, .rst-content th, .rst-content td { + font-size: 18px !important; + line-height: 27px !important; } /* The theme sets this to 75% which seems to small to me. */ .rst-content code { diff --git a/index.rst b/index.rst index d1e34a844..9777f809e 100644 --- a/index.rst +++ b/index.rst @@ -70,6 +70,13 @@ can use the headings in the left sidebar to navigate the site. Introduction dev/* +.. toctree:: + :caption: Specifications + :maxdepth: 1 + :glob: + + specs/* + .. _`contribution guidelines`: https://github.com/syncthing/syncthing/blob/master/CONTRIBUTING.md .. _Github: https://github.com/syncthing/docs .. _`issue tracker`: https://github.com/syncthing/syncthing/issues diff --git a/specs/bep-v1.rst b/specs/bep-v1.rst new file mode 100644 index 000000000..2f990fbba --- /dev/null +++ b/specs/bep-v1.rst @@ -0,0 +1,925 @@ +Block Exchange Protocol v1 +========================== + +Introduction and Definitions +---------------------------- + +BEP is used between two or more *devices* thus forming a *cluster*. Each +device has one or more *folders* of files described by the *local +model*, containing metadata and block hashes. The local model is sent to +the other devices in the cluster. The union of all files in the local +models, with files selected for highest change version, forms the +*global model*. Each device strives to get its folders in sync with the +global model by requesting missing or outdated blocks from the other +devices in the cluster. + +File data is described and transferred in units of *blocks*, each being +128 KiB (131072 bytes) in size. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in RFC 2119. + +Transport and Authentication +---------------------------- + +BEP is deployed as the highest level in a protocol stack, with the lower +level protocols providing encryption and authentication. + +:: + + +-----------------------------| + | Block Exchange Protocol | + |-----------------------------| + | Encryption & Auth (TLS 1.2) | + |-----------------------------| + | TCP | + |-----------------------------| + v ... v + +The encryption and authentication layer SHALL use TLS 1.2 or a higher +revision. A strong cipher suite SHALL be used, with "strong cipher +suite" being defined as being without known weaknesses and providing +Perfect Forward Secrecy (PFS). Examples of strong cipher suites are +given at the end of this document. This is not to be taken as an +exhaustive list of allowed cipher suites but represents best practices +at the time of writing. + +The exact nature of the authentication is up to the application, however +it SHALL be based on the TLS certificate presented at the start of the +connection. Possibilities include certificates signed by a common +trusted CA, preshared certificates, preshared certificate fingerprints +or certificate pinning combined with some out of band first +verification. The reference implementation uses preshared certificate +fingerprints (SHA-256) referred to as "Device IDs". + +There is no required order or synchronization among BEP messages except +as noted per message type - any message type may be sent at any time and +the sender need not await a response to one message before sending +another. Responses MUST however be sent in the same order as the +requests are received. + +The underlying transport protocol MUST be TCP. + +Messages +-------- + +Every message starts with one 32 bit word indicating the message +version, type and ID, followed by the length of the message. The header +is in network byte order, i.e. big endian. + +:: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Ver | Message ID | Type | Reserved |C| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +For BEP v1 the Version field is set to zero. Future versions with +incompatible message formats will increment the Version field. A message +with an unknown version is a protocol error and MUST result in the +connection being terminated. A client supporting multiple versions MAY +retry with a different protocol version upon disconnection. + +The Message ID is set to a unique value for each transmitted request +message. In response messages it is set to the Message ID of the +corresponding request message. The uniqueness requirement implies that +no more than 4096 messages may be outstanding at any given moment. The +ordering requirement implies that a response to a given message ID also +means that all preceding messages have been received, specifically those +which do not otherwise demand a response. Hence their message ID:s may +be reused. + +The Type field indicates the type of data following the message header +and is one of the integers defined below. A message of an unknown type +is a protocol error and MUST result in the connection being terminated. + +The Compression bit "C" indicates the compression used for the message. + +For C=1: + +- The Length field contains the length, in bytes, of the compressed + message data plus a four byte uncompressed length field. + +- The compressed message data is preceeded by a 32 bit field denoting + the length of the uncompressed message. + +- The message data is compressed using the LZ4 format and algorithm + described in http://www.lz4.org/. + +For C=0: + +- The Length field contains the length, in bytes, of the uncompressed + message data. + +- The message is not compressed. + +All data within the message (post decompression, if compression is in +use) MUST be in XDR (RFC 1014) encoding. All fields shorter than 32 bits +and all variable length data MUST be padded to a multiple of 32 bits. +The actual data types in use by BEP, in XDR naming convention, are the +following: + +:(unsigned) int: (unsigned) 32 bit integer +:(unsigned) hyper: (unsigned) 64 bit integer +:opaque<>: variable length opaque data +:string<>: variable length string + +The transmitted length of string and opaque data is the length of actual +data, excluding any added padding. The encoding of opaque<> and string<> +are identical, the distinction being solely one of interpretation. +Opaque data should not be interpreted but can be compared bytewise to +other opaque data. All strings MUST use the Unicode UTF-8 encoding, +normalization form C. + +Cluster Config (Type = 0) +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This informational message provides information about the cluster +configuration as it pertains to the current connection. A Cluster Config +message MUST be the first message sent on a BEP connection. Additional +Cluster Config messages MUST NOT be sent after the initial exchange. + +Graphical Representation +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + ClusterConfigMessage Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of ClientName | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ ClientName (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of ClientVersion | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ ClientVersion (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Folders | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Folder Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Options | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Option Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Folder Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ ID (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Devices | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Device Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Options | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Option Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Device Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ ID (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Max Local Version (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Options | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Option Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Option Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Key | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Key (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Value | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Value (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Fields +^^^^^^ + +The ClientName and ClientVersion fields identify the implementation. The +values SHOULD be simple strings identifying the implementation name, as +a user would expect to see it, and the version string in the same +manner. An example ClientName is "syncthing" and an example +ClientVersion is "v0.7.2". The ClientVersion field SHOULD follow the +patterns laid out in the `Semantic Versioning `__ +standard. + +The Folders field lists all folders that will be synchronized over the +current connection. Each folder has a list of participating Devices, +Flags and Options. Currently no flags are defined so the field MUST be +set to all zeroes. The Options field is implementation specific and +described below. + +The Device ID is a 32 byte number that uniquely identifies the device. +For instance, the reference implementation uses the SHA-256 of the +device X.509 certificate. + +Each device has an associated Flags field to indicate the sharing mode +of that device for the folder in question. See the discussion on Sharing +Modes. The Device Flags field contains the following single bit flags: + +:: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved |Pri| Reserved |I|R|T| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +:Bit 31 ("T", Trusted): is set for devices that participate in trusted + mode. + +:Bit 30 ("R", Read Only): is set for devices that participate in read + only mode. + +:Bit 29 ("I", Introducer): is set for devices that are trusted as + cluster introducers. + +:Bits 16 through 28: are reserved and MUST be set to zero. + +:Bits 14-15 ("Pri): indicate the device's upload priority for this + folder. Possible values are: + + :00: The default. Normal priority. + + :01: High priority. Other devices SHOULD favour requesting files + from this device over devices with normal or low priority. + + :10: Low priority. Other devices SHOULD avoid requesting files from + this device when they are available from other devices. + + :11: Sharing disabled. Other devices SHOULD NOT request files from + this device. + +:Bits 0 through 14: are reserved and MUST be set to zero. + +Exactly one of the T and R bits MUST be set. + +The per device Max Local Version field contains the highest local file +version number of the files already known to be in the index sent by +this device. If nothing is known about the index of a given device, this +field MUST be set to zero. When receiving a Cluster Config message with +a non-zero Max Local Version for the local device ID, a device MAY elect +to send an Index Update message containing only files with higher local +version numbers in place of the initial Index message. + +The Options field contain option values to be used in an implementation +specific manner. The options list is conceptually a map of Key => Value +items, although it is transmitted in the form of a list of (Key, Value) +pairs, both of string type. Key ID:s are implementation specific. An +implementation MUST ignore unknown keys. An implementation MAY impose +limits on the length keys and values. The options list may be used to +inform devices of relevant local configuration options such as rate +limiting or make recommendations about request parallelism, device +priorities, etc. An empty options list is valid for devices not having +any such information to share. Devices MAY NOT make any assumptions +about peers acting in a specific manner as a result of sent options. + +XDR +^^^ + +:: + + struct ClusterConfigMessage { + string ClientName<>; + string ClientVersion<>; + Folder Folders<>; + Option Options<>; + } + + struct Folder { + string ID<64>; + Device Devices<>; + unsigned int Flags; + Option Options<64>; + } + + struct Device { + opaque ID<32>; + hyper MaxLocalVersion; + unsigned int Flags; + Option Options<64>; + } + + struct Option { + string Key<>; + string Value<>; + } + +Index (Type = 1) and Index Update (Type = 6) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Index and Index Update messages define the contents of the senders +folder. An Index message represents the full contents of the folder and +thus supersedes any previous index. An Index Update amends an existing +index with new information, not affecting any entries not included in +the message. An Index Update MAY NOT be sent unless preceded by an +Index, unless a non-zero Max Local Version has been announced for the +given folder by the peer device. + +Graphical Representation +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + IndexMessage Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Folder | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Folder (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Files | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more FileInfo Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Options | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Option Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + FileInfo Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Name | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Name (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Modified (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Vector Structure \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Local Version (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Blocks | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more BlockInfo Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Vector Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Counters | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Counter Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Counter Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + ID (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Value (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + BlockInfo Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Hash | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Hash (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Fields +^^^^^^ + +The Folder field identifies the folder that the index message pertains +to. For single folder implementations the device MUST use the string +"default". + +The Name is the file name path relative to the folder root. Like all +strings in BEP, the Name is always in UTF-8 NFC regardless of operating +system or file system specific conventions. The Name field uses the +slash character ("/") as path separator, regardless of the +implementation's operating system conventions. The combination of Folder +and Name uniquely identifies each file in a cluster. + +The Version field is a version vector describing the updates performed +to file by all members in the cluster. Each counter in the version +vector is an ID-Value tuple. The ID is used the first 64 bits of the +device ID. The Value is a simple incrementing counter, starting at zero. +The combination of Folder, Name and Version uniquely identifies the +contents of a file at a given point in time. + +The Local Version field is the value of a device local monotonic clock +at the time of last local database update to a file. The clock ticks on +every local database update. + +The Flags field (per FileInfo) is made up of the following single bit +flags: + +:: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved |U|S|P|I|D| Unix Perm. & Mode | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +:The lower 12 bits: hold the common Unix permission and mode bits. An + implementation MAY ignore or interpret these as is suitable on the + host operating system. + +:Bit 19 ("D"): is set when the file has been deleted. The block list + SHALL be of length zero and the modification time indicates the time + of deletion or, if the time of deletion is not reliably determinable, + the last known modification time. + +:Bit 18 ("I"): is set when the file is invalid and unavailable for + synchronization. A peer MAY set this bit to indicate that it can + temporarily not serve data for the file. + +:Bit 17 ("P"): is set when there is no permission information for the + file. This is the case when it originates on a non-permission- + supporting file system. Changes to only permission bits SHOULD be + disregarded on files with this bit set. The permissions bits MUST be + set to the octal value 0666. + +:Bit 16 ("S"): is set when the file is a symbolic link. The block list + SHALL be of one or more blocks since the target of the symlink is + stored within the blocks of the file. + +:Bit 15 ("U"): is set when the symbolic links target does not exist. On + systems where symbolic links have types, this bit being means that + the default file symlink SHALL be used. If this bit is unset bit 19 + will decide the type of symlink to be created. + +:Bit 0 through 14: are reserved for future use and SHALL be set to + zero. + +The hash algorithm is implied by the Hash length. Currently, the hash +MUST be 32 bytes long and computed by SHA256. + +The Modified time is expressed as the number of seconds since the Unix +Epoch (1970-01-01 00:00:00 UTC). + +In the rare occasion that a file is simultaneously and independently +modified by two devices in the same cluster and thus end up on the same +Version number after modification, the Modified field is used as a tie +breaker (higher being better), followed by the hash values of the file +blocks (lower being better). + +The Blocks list contains the size and hash for each block in the file. +Each block represents a 128 KiB slice of the file, except for the last +block which may represent a smaller amount of data. + +The Flags field (in IndexMessage) is reserved for future use and MUST +currently be set to zero. The Options list is implementation defined and +as described in the ClusterConfig message section. + +XDR +^^^ + +:: + + struct IndexMessage { + string Folder<>; + FileInfo Files<>; + unsigned int Flags; + Option Options<64>; + } + + struct FileInfo { + string Name<8192>; + unsigned int Flags; + hyper Modified; + Vector Version; + hyper LocalVersion; + BlockInfo Blocks<>; + } + + struct Vector { + Counter Counters<> + } + + struct Counter { + unsigned hyper ID + unsigned hyper Value + } + + struct BlockInfo { + unsigned int Size; + opaque Hash<>; + } + +Request (Type = 2) +~~~~~~~~~~~~~~~~~~ + +The Request message expresses the desire to receive a data block +corresponding to a part of a certain file in the peer's folder. + +Graphical Representation +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + RequestMessage Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Folder | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Folder (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Name | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Name (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Offset (64 bits) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Hash | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Hash (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Options | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Option Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Fields +^^^^^^ + +The Folder and Name fields are as documented for the Index message. The +Offset and Size fields specify the region of the file to be transferred. +This SHOULD equate to exactly one block as seen in an Index message. + +The Hash field MAY be set to the expected hash value of the block, or +may be left empty (zero length). If set, the other device SHOULD ensure +that the transmitted block matches the requested hash. The other device +MAY reuse a block from a different file and offset having the same size +and hash, if one exists. + +The Flags field is reserved for future use and MUST currently be set to +zero. The Options list is implementation defined and as described in the +ClusterConfig message section. + +XDR +^^^ + +:: + + struct RequestMessage { + string Folder<64>; + string Name<8192>; + hyper Offset; + int Size; + opaque Hash<64>; + unsigned int Flags; + Option Options<64>; + } + +Response (Type = 3) +~~~~~~~~~~~~~~~~~~~ + +The Response message is sent in response to a Request message. + +Graphical Representation +^^^^^^^^^^^^^^^^^^^^^^^^ + +ResponseMessage Structure: + +:: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Data | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Data (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Code | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Fields +^^^^^^ + +The Data field contains either a full 128 KiB block, a shorter block in +the case of the last block in a file, or is empty (zero length) if the +requested block is not available. + +The Code field contains an error code describing the reason a Request +could not be fulfilled, in the case where a zero length Data was +returned. The following values are defined: + +:0: No Error (Data should be present) + +:1: Generic Error + +:2: No Such File (the requested file does not exist, or the offset is + outside the acceptable range for the file) + +:3: Invalid (file exists but has invalid bit set or is otherwise + unavailable) + +XDR +^^^ + +:: + + struct ResponseMessage { + opaque Data<>; + int Code; + } + +Ping (Type = 4) +~~~~~~~~~~~~~~~ + +The Ping message is used to determine that a connection is alive, and to +keep connections alive through state tracking network elements such as +firewalls and NAT gateways. The Ping message has no contents. + +Pong (Type = 5) +~~~~~~~~~~~~~~~ + +The Pong message is sent in response to a Ping. The Pong message has no +contents, but copies the Message ID from the Ping. + +Close (Type = 7) +~~~~~~~~~~~~~~~~ + +The Close message MAY be sent to indicate that the connection will be +torn down due to an error condition. A Close message MUST NOT be +followed by further messages. + +Graphical Representation +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + CloseMessage Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of Reason | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Reason (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Code | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Fields +^^^^^^ + +The Reason field contains a human description of the error condition, +suitable for consumption by a human. The Code field is for a machine +readable error code. Codes are reserved for future use and MUST +currently be set to zero. + +:: + + struct CloseMessage { + string Reason<1024>; + int Code; + } + +Sharing Modes +------------- + +Trusted +~~~~~~~ + +Trusted mode is the default sharing mode. Updates are exchanged in both +directions. + +:: + + +------------+ Updates /---------\ + | | -----------> / \ + | Device | | Cluster | + | | <----------- \ / + +------------+ Updates \---------/ + +Read Only +~~~~~~~~~ + +In read only mode, a device does not synchronize the local folder to the +cluster, but publishes changes to its local folder contents as usual. +The local folder can be seen as a "master copy" that is never affected +by the actions of other cluster devices. + +:: + + +------------+ Updates /---------\ + | | -----------> / \ + | Device | | Cluster | + | | \ / + +------------+ \---------/ + +Message Limits +-------------- + +An implementation MAY impose reasonable limits on the length of messages +and message fields to aid robustness in the face of corruption or broken +implementations. These limits, if imposed, SHOULD NOT be more +restrictive than the following. An implementation should strive to keep +messages short and to the point, favouring more and smaller messages +over fewer and larger. For example, favour a smaller Index message +followed by one or more Index Update messages rather than sending a very +large Index message. + +=================== =================== ============= +Message Type Field Limit +=================== =================== ============= +**All Messages** +----------------------------------------------------- +| Total length 64 MiB + +**Index and Index Update Messages** +----------------------------------------------------- +| Folder 64 bytes +| Number of Files 1.000.000 +| Name 8192 bytes +| Number of Blocks 1.000.000 +| Hash 64 bytes +| Number of Counters 1.000.000 + +**Request Messages** +----------------------------------------------------- +| Folder 64 bytes +| Name 8192 bytes + +**Response Messages** +----------------------------------------------------- +| Data 256 KiB + +**Cluster Config Message** +----------------------------------------------------- +| Number of Folders 1.000.000 +| Number of Devices 1.000.000 +| Number of Options 64 +| Key 64 bytes +| Value 1024 bytes +=================== =================== ============= + +Example Exchange +---------------- + +=== ======================= ====================== + # A B +=== ======================= ====================== + 1 ClusterConfiguration-> <-ClusterConfiguration + 2 Index-> <-Index + 3 IndexUpdate-> <-IndexUpdate + 4 IndexUpdate-> + 5 Request-> + 6 Request-> + 7 Request-> + 8 Request-> + 9 <-Response +10 <-Response +11 <-Response +12 <-Response +13 Index Update-> +... +14 <-Ping +15 Ping-> +=== ======================= ====================== + +The connection is established and at 1. both peers send +ClusterConfiguration messages and then Index records. The Index records +are received and both peers recompute their knowledge of the data in the +cluster. In this example, peer A has four missing or outdated blocks. At +2 through 5 peer A sends requests for these blocks. The requests are +received by peer B, who retrieves the data from the folder and transmits +Response records (6 through 9). Device A updates their folder contents +and transmits an Index Update message (10). Both peers enter idle state +after 10. At some later time 11, peer A determines that it has not seen +data from B for some time and sends a Ping request. A response is sent +at 12. + +Examples of Strong Cipher Suites +-------------------------------- + +====== =========================== ================================== +ID Name Description +====== =========================== ================================== +0x009F DHE-RSA-AES256-GCM-SHA384 TLSv1.2 DH RSA AESGCM(256) AEAD +0x006B DHE-RSA-AES256-SHA256 TLSv1.2 DH RSA AES(256) SHA256 +0xC030 ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 ECDH RSA AESGCM(256) AEAD +0xC028 ECDHE-RSA-AES256-SHA384 TLSv1.2 ECDH RSA AES(256) SHA384 +0x009E DHE-RSA-AES128-GCM-SHA256 TLSv1.2 DH RSA AESGCM(128) AEAD +0x0067 DHE-RSA-AES128-SHA256 TLSv1.2 DH RSA AES(128) SHA256 +0xC02F ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 ECDH RSA AESGCM(128) AEAD +0xC027 ECDHE-RSA-AES128-SHA256 TLSv1.2 ECDH RSA AES(128) SHA256 +====== =========================== ================================== + diff --git a/specs/localdisco-v3.rst b/specs/localdisco-v3.rst new file mode 100644 index 000000000..0a89053bc --- /dev/null +++ b/specs/localdisco-v3.rst @@ -0,0 +1,145 @@ +Local Discovery Protocol v3 +=========================== + +Mode of Operation +----------------- + +Each participating device periodically sends an Announcement packet. It also +keeps a table of the announcements it has seen. There is no way to solicit a +reply; the only message type is Announcement. + +On multihomed hosts the announcement packets should be sent on each interface +on which Syncthing will accept connections. + +For IPv4, the Announcement packet is broadcasted either to the link-specific +broadcast address, or to the generic link-local broadcast address +``255.255.255.255``, with destination port 21027. + +For IPv6, the Announcement packet is multicasted to the transient link-local +multicast address ``[ff12::8384]``, with destination port 21027. + +It is recommended that local discovery Announcement packets be sent on a 30 to +60 second interval, possibly with immediate transmissions when a previously +unknown device is discovered. + +Device ID +--------- + +The device ID is the SHA-256 (32 bytes) of the device X.509 certificate. See +:ref:`device-ids` in the Syncthing documentation. + +Announcement packet +------------------- + +The Announcement packet has the following structure:: + + Announce Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Magic | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Device Structure \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Extra | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Device Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Device Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ ID (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Addresses | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Address Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Number of Relays | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ Zero or more Relay Structures \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Address Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of URL | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ URL (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Relay Structure: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length of URL | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ URL (variable length) \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Latency | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +The corresponding XDR representation is as follows (see +`RFC4506 `__ for the XDR format): + +:: + + struct Announcement { + unsigned int Magic; + Device This; + Device Extra<>; + } + + struct Device { + opaque ID<32>; + Address Addresses<16>; + Relay Relays<16>; + } + + struct Address { + string URL<2083>; + } + + struct Relay { + string URL<2083>; + int Latency; + } + +The first Device structure contains information about the sending +device. The following zero or more Extra devices contain information +about other devices known to the sending device. + +In the ``Device`` structure, field ``DeviceID`` is the SHA-256 (32 +bytes) of the device X.509 certificate, as explained in section *Device +ID*. + +For each ``Address`` and ``Relay`` the ``URL`` field contains the actual +target address. For direction connections (the ``Address`` list) these will +typically have the ``tcp://`` scheme. Relay connections will typically use the +``relay://`` scheme. + +The ``Latency`` field contains the approximate latency for a TCP handshake +(i.e. three packet round trips) between the other device and the relay, in +milliseconds.