You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

178 lines
7.0 KiB

  1. ============================
  2. Synapse Server-to-Server API
  3. ============================
  4. A description of the protocol used to communicate between Synapse home servers;
  5. also known as Federation.
  6. Overview
  7. ========
  8. The server-server API is a mechanism by which two home servers can exchange
  9. Synapse event messages, both as a real-time push of current events, and as a
  10. historic fetching mechanism to synchronise past history for clients to view. It
  11. uses HTTP connections between each pair of servers involved as the underlying
  12. transport. Messages are exchanged between servers in real-time by active pushing
  13. from each server's HTTP client into the server of the other. Queries to fetch
  14. historic data for the purpose of back-filling scrollback buffers and the like
  15. can also be performed.
  16. { Synapse entities } { Synapse entities }
  17. ^ | ^ |
  18. | events | | events |
  19. | V | V
  20. +------------------+ +------------------+
  21. | |---------( HTTP )---------->| |
  22. | Home Server | | Home Server |
  23. | |<--------( HTTP )-----------| |
  24. +------------------+ +------------------+
  25. Transactions and PDUs
  26. =====================
  27. The communication between home servers is performed by a bidirectional exchange
  28. of messages. These messages are called Transactions, and are encoded as JSON
  29. objects with a dict as the top-level element, passed over HTTP. A Transaction is
  30. meaningful only to the pair of home servers that exchanged it; they are not
  31. globally-meaningful.
  32. Each transaction has an opaque ID and timestamp (UNIX epoch time in miliseconds)
  33. generated by its origin server, an origin and destination server name, a list of
  34. "previous IDs", and a list of PDUs - the actual message payload that the
  35. Transaction carries.
  36. {"transaction_id":"916d630ea616342b42e98a3be0b74113",
  37. "ts":1404835423000,
  38. "origin":"red",
  39. "destination":"blue",
  40. "prev_ids":["e1da392e61898be4d2009b9fecce5325"],
  41. "pdus":[...]}
  42. The "previous IDs" field will contain a list of previous transaction IDs that
  43. the origin server has sent to this destination. Its purpose is to act as a
  44. sequence checking mechanism - the destination server can check whether it has
  45. successfully received that Transaction, or ask for a retransmission if not.
  46. The "pdus" field of a transaction is a list, containing zero or more PDUs.[*]
  47. Each PDU is itself a dict containing a number of keys, the exact details of
  48. which will vary depending on the type of PDU.
  49. (* Normally the PDU list will be non-empty, but the server should cope with
  50. receiving an "empty" transaction, as this is useful for informing peers of other
  51. transaction IDs they should be aware of. This effectively acts as a push
  52. mechanism to encourage peers to continue to replicate content.)
  53. All PDUs have an ID, a context, a declaration of their type, a list of other PDU
  54. IDs that have been seen recently on that context (regardless of which origin
  55. sent them), and a nested content field containing the actual event content.
  56. [[TODO(paul): Update this structure so that 'pdu_id' is a two-element
  57. [origin,ref] pair like the prev_pdus are]]
  58. {"pdu_id":"a4ecee13e2accdadf56c1025af232176",
  59. "context":"#example.green",
  60. "origin":"green",
  61. "ts":1404838188000,
  62. "pdu_type":"m.text",
  63. "prev_pdus":[["blue","99d16afbc857975916f1d73e49e52b65"]],
  64. "content":...
  65. "is_state":false}
  66. In contrast to the transaction layer, it is important to note that the prev_pdus
  67. field of a PDU refers to PDUs that any origin server has sent, rather than
  68. previous IDs that this origin has sent. This list may refer to other PDUs sent
  69. by the same origin as the current one, or other origins.
  70. Because of the distributed nature of participants in a Synapse conversation, it
  71. is impossible to establish a globally-consistent total ordering on the events.
  72. However, by annotating each outbound PDU at its origin with IDs of other PDUs it
  73. has received, a partial ordering can be constructed allowing causallity
  74. relationships to be preserved. A client can then display these messages to the
  75. end-user in some order consistent with their content and ensure that no message
  76. that is semantically in reply of an earlier one is ever displayed before it.
  77. PDUs fall into two main categories: those that deliver Events, and those that
  78. synchronise State. For PDUs that relate to State synchronisation, additional
  79. keys exist to support this:
  80. {...,
  81. "is_state":true,
  82. "state_key":TODO
  83. "power_level":TODO
  84. "prev_state_id":TODO
  85. "prev_state_origin":TODO}
  86. [[TODO(paul): At this point we should probably have a long description of how
  87. State management works, with descriptions of clobbering rules, power levels, etc
  88. etc... But some of that detail is rather up-in-the-air, on the whiteboard, and
  89. so on. This part needs refining. And writing in its own document as the details
  90. relate to the server/system as a whole, not specifically to server-server
  91. federation.]]
  92. Protocol URLs
  93. =============
  94. For active pushing of messages representing live activity "as it happens":
  95. PUT /send/:transaction_id/
  96. Body: JSON encoding of a single Transaction
  97. Response: [[TODO(paul): I don't actually understand what
  98. ReplicationLayer.on_transaction() is doing here, so I'm not sure what the
  99. response ought to be]]
  100. The transaction_id path argument will override any ID given in the JSON body.
  101. The destination name will be set to that of the receiving server itself. Each
  102. embedded PDU in the transaction body will be processed.
  103. To fetch a particular PDU:
  104. GET /pdu/:origin/:pdu_id/
  105. Response: JSON encoding of a single Transaction containing one PDU
  106. Retrieves a given PDU from the server. The response will contain a single new
  107. Transaction, inside which will be the requested PDU.
  108. To fetch all the state of a given context:
  109. GET /state/:context/
  110. Response: JSON encoding of a single Transaction containing multiple PDUs
  111. Retrieves a snapshot of the entire current state of the given context. The
  112. response will contain a single Transaction, inside which will be a list of
  113. PDUs that encode the state.
  114. To paginate events on a given context:
  115. GET /paginate/:context/
  116. Query args: v, limit
  117. Response: JSON encoding of a single Transaction containing multiple PDUs
  118. Retrieves a sliding-window history of previous PDUs that occurred on the
  119. given context. Starting from the PDU ID(s) given in the "v" argument, the
  120. PDUs that preceeded it are retrieved, up to a total number given by the
  121. "limit" argument. These are then returned in a new Transaction containing all
  122. off the PDUs.
  123. To stream events all the events:
  124. GET /pull/
  125. Query args: origin, v
  126. Response: JSON encoding of a single Transaction consisting of multiple PDUs
  127. Retrieves all of the transactions later than any version given by the "v"
  128. arguments. [[TODO(paul): I'm not sure what the "origin" argument does because
  129. I think at some point in the code it's got swapped around.]]