matrix-synapse 1.142.0rc3__cp314-abi3-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matrix-synapse might be problematic. Click here for more details.

Files changed (1057) hide show
  1. matrix_synapse-1.142.0rc3.dist-info/AUTHORS.rst +51 -0
  2. matrix_synapse-1.142.0rc3.dist-info/LICENSE-AGPL-3.0 +661 -0
  3. matrix_synapse-1.142.0rc3.dist-info/LICENSE-COMMERCIAL +6 -0
  4. matrix_synapse-1.142.0rc3.dist-info/METADATA +375 -0
  5. matrix_synapse-1.142.0rc3.dist-info/RECORD +1057 -0
  6. matrix_synapse-1.142.0rc3.dist-info/WHEEL +4 -0
  7. matrix_synapse-1.142.0rc3.dist-info/entry_points.txt +14 -0
  8. matrix_synapse.libs/libgcc_s-2d945d6c.so.1 +0 -0
  9. synapse/__init__.py +97 -0
  10. synapse/_scripts/__init__.py +0 -0
  11. synapse/_scripts/export_signing_key.py +109 -0
  12. synapse/_scripts/generate_config.py +83 -0
  13. synapse/_scripts/generate_log_config.py +56 -0
  14. synapse/_scripts/generate_signing_key.py +55 -0
  15. synapse/_scripts/generate_workers_map.py +318 -0
  16. synapse/_scripts/hash_password.py +95 -0
  17. synapse/_scripts/move_remote_media_to_new_store.py +128 -0
  18. synapse/_scripts/register_new_matrix_user.py +374 -0
  19. synapse/_scripts/review_recent_signups.py +212 -0
  20. synapse/_scripts/synapse_port_db.py +1603 -0
  21. synapse/_scripts/synctl.py +365 -0
  22. synapse/_scripts/update_synapse_database.py +130 -0
  23. synapse/api/__init__.py +20 -0
  24. synapse/api/auth/__init__.py +207 -0
  25. synapse/api/auth/base.py +406 -0
  26. synapse/api/auth/internal.py +299 -0
  27. synapse/api/auth/mas.py +457 -0
  28. synapse/api/auth/msc3861_delegated.py +617 -0
  29. synapse/api/auth_blocking.py +144 -0
  30. synapse/api/constants.py +362 -0
  31. synapse/api/errors.py +907 -0
  32. synapse/api/filtering.py +539 -0
  33. synapse/api/presence.py +104 -0
  34. synapse/api/ratelimiting.py +482 -0
  35. synapse/api/room_versions.py +535 -0
  36. synapse/api/urls.py +119 -0
  37. synapse/app/__init__.py +60 -0
  38. synapse/app/_base.py +866 -0
  39. synapse/app/admin_cmd.py +388 -0
  40. synapse/app/appservice.py +30 -0
  41. synapse/app/client_reader.py +30 -0
  42. synapse/app/complement_fork_starter.py +206 -0
  43. synapse/app/event_creator.py +29 -0
  44. synapse/app/federation_reader.py +30 -0
  45. synapse/app/federation_sender.py +30 -0
  46. synapse/app/frontend_proxy.py +30 -0
  47. synapse/app/generic_worker.py +475 -0
  48. synapse/app/homeserver.py +504 -0
  49. synapse/app/media_repository.py +30 -0
  50. synapse/app/phone_stats_home.py +296 -0
  51. synapse/app/pusher.py +30 -0
  52. synapse/app/synchrotron.py +30 -0
  53. synapse/app/user_dir.py +31 -0
  54. synapse/appservice/__init__.py +461 -0
  55. synapse/appservice/api.py +569 -0
  56. synapse/appservice/scheduler.py +567 -0
  57. synapse/config/__init__.py +27 -0
  58. synapse/config/__main__.py +62 -0
  59. synapse/config/_base.py +1108 -0
  60. synapse/config/_base.pyi +217 -0
  61. synapse/config/_util.py +99 -0
  62. synapse/config/account_validity.py +116 -0
  63. synapse/config/api.py +141 -0
  64. synapse/config/appservice.py +210 -0
  65. synapse/config/auth.py +80 -0
  66. synapse/config/auto_accept_invites.py +43 -0
  67. synapse/config/background_updates.py +44 -0
  68. synapse/config/cache.py +231 -0
  69. synapse/config/captcha.py +90 -0
  70. synapse/config/cas.py +116 -0
  71. synapse/config/consent.py +73 -0
  72. synapse/config/database.py +184 -0
  73. synapse/config/emailconfig.py +367 -0
  74. synapse/config/experimental.py +595 -0
  75. synapse/config/federation.py +114 -0
  76. synapse/config/homeserver.py +141 -0
  77. synapse/config/jwt.py +55 -0
  78. synapse/config/key.py +447 -0
  79. synapse/config/logger.py +390 -0
  80. synapse/config/mas.py +191 -0
  81. synapse/config/matrixrtc.py +66 -0
  82. synapse/config/metrics.py +84 -0
  83. synapse/config/modules.py +40 -0
  84. synapse/config/oembed.py +185 -0
  85. synapse/config/oidc.py +509 -0
  86. synapse/config/password_auth_providers.py +82 -0
  87. synapse/config/push.py +64 -0
  88. synapse/config/ratelimiting.py +254 -0
  89. synapse/config/redis.py +74 -0
  90. synapse/config/registration.py +296 -0
  91. synapse/config/repository.py +311 -0
  92. synapse/config/retention.py +162 -0
  93. synapse/config/room.py +88 -0
  94. synapse/config/room_directory.py +165 -0
  95. synapse/config/saml2.py +251 -0
  96. synapse/config/server.py +1170 -0
  97. synapse/config/server_notices.py +84 -0
  98. synapse/config/spam_checker.py +66 -0
  99. synapse/config/sso.py +121 -0
  100. synapse/config/stats.py +54 -0
  101. synapse/config/third_party_event_rules.py +40 -0
  102. synapse/config/tls.py +192 -0
  103. synapse/config/tracer.py +71 -0
  104. synapse/config/user_directory.py +47 -0
  105. synapse/config/user_types.py +44 -0
  106. synapse/config/voip.py +59 -0
  107. synapse/config/workers.py +642 -0
  108. synapse/crypto/__init__.py +20 -0
  109. synapse/crypto/context_factory.py +278 -0
  110. synapse/crypto/event_signing.py +194 -0
  111. synapse/crypto/keyring.py +931 -0
  112. synapse/event_auth.py +1266 -0
  113. synapse/events/__init__.py +668 -0
  114. synapse/events/auto_accept_invites.py +216 -0
  115. synapse/events/builder.py +387 -0
  116. synapse/events/presence_router.py +245 -0
  117. synapse/events/snapshot.py +559 -0
  118. synapse/events/utils.py +928 -0
  119. synapse/events/validator.py +305 -0
  120. synapse/federation/__init__.py +22 -0
  121. synapse/federation/federation_base.py +383 -0
  122. synapse/federation/federation_client.py +2134 -0
  123. synapse/federation/federation_server.py +1544 -0
  124. synapse/federation/persistence.py +71 -0
  125. synapse/federation/send_queue.py +532 -0
  126. synapse/federation/sender/__init__.py +1165 -0
  127. synapse/federation/sender/per_destination_queue.py +884 -0
  128. synapse/federation/sender/transaction_manager.py +210 -0
  129. synapse/federation/transport/__init__.py +28 -0
  130. synapse/federation/transport/client.py +1201 -0
  131. synapse/federation/transport/server/__init__.py +334 -0
  132. synapse/federation/transport/server/_base.py +429 -0
  133. synapse/federation/transport/server/federation.py +912 -0
  134. synapse/federation/units.py +133 -0
  135. synapse/handlers/__init__.py +20 -0
  136. synapse/handlers/account.py +162 -0
  137. synapse/handlers/account_data.py +362 -0
  138. synapse/handlers/account_validity.py +361 -0
  139. synapse/handlers/admin.py +618 -0
  140. synapse/handlers/appservice.py +991 -0
  141. synapse/handlers/auth.py +2494 -0
  142. synapse/handlers/cas.py +413 -0
  143. synapse/handlers/deactivate_account.py +363 -0
  144. synapse/handlers/delayed_events.py +635 -0
  145. synapse/handlers/device.py +1873 -0
  146. synapse/handlers/devicemessage.py +399 -0
  147. synapse/handlers/directory.py +554 -0
  148. synapse/handlers/e2e_keys.py +1834 -0
  149. synapse/handlers/e2e_room_keys.py +455 -0
  150. synapse/handlers/event_auth.py +390 -0
  151. synapse/handlers/events.py +201 -0
  152. synapse/handlers/federation.py +2043 -0
  153. synapse/handlers/federation_event.py +2420 -0
  154. synapse/handlers/identity.py +812 -0
  155. synapse/handlers/initial_sync.py +528 -0
  156. synapse/handlers/jwt.py +120 -0
  157. synapse/handlers/message.py +2347 -0
  158. synapse/handlers/oidc.py +1803 -0
  159. synapse/handlers/pagination.py +768 -0
  160. synapse/handlers/password_policy.py +102 -0
  161. synapse/handlers/presence.py +2638 -0
  162. synapse/handlers/profile.py +655 -0
  163. synapse/handlers/push_rules.py +164 -0
  164. synapse/handlers/read_marker.py +79 -0
  165. synapse/handlers/receipts.py +351 -0
  166. synapse/handlers/register.py +1060 -0
  167. synapse/handlers/relations.py +624 -0
  168. synapse/handlers/reports.py +98 -0
  169. synapse/handlers/room.py +2447 -0
  170. synapse/handlers/room_list.py +632 -0
  171. synapse/handlers/room_member.py +2365 -0
  172. synapse/handlers/room_member_worker.py +146 -0
  173. synapse/handlers/room_policy.py +186 -0
  174. synapse/handlers/room_summary.py +1057 -0
  175. synapse/handlers/saml.py +524 -0
  176. synapse/handlers/search.py +723 -0
  177. synapse/handlers/send_email.py +209 -0
  178. synapse/handlers/set_password.py +71 -0
  179. synapse/handlers/sliding_sync/__init__.py +1701 -0
  180. synapse/handlers/sliding_sync/extensions.py +970 -0
  181. synapse/handlers/sliding_sync/room_lists.py +2266 -0
  182. synapse/handlers/sliding_sync/store.py +128 -0
  183. synapse/handlers/sso.py +1292 -0
  184. synapse/handlers/state_deltas.py +82 -0
  185. synapse/handlers/stats.py +322 -0
  186. synapse/handlers/sync.py +3109 -0
  187. synapse/handlers/thread_subscriptions.py +190 -0
  188. synapse/handlers/typing.py +606 -0
  189. synapse/handlers/ui_auth/__init__.py +48 -0
  190. synapse/handlers/ui_auth/checkers.py +332 -0
  191. synapse/handlers/user_directory.py +783 -0
  192. synapse/handlers/worker_lock.py +365 -0
  193. synapse/http/__init__.py +106 -0
  194. synapse/http/additional_resource.py +62 -0
  195. synapse/http/client.py +1360 -0
  196. synapse/http/connectproxyclient.py +309 -0
  197. synapse/http/federation/__init__.py +19 -0
  198. synapse/http/federation/matrix_federation_agent.py +490 -0
  199. synapse/http/federation/srv_resolver.py +196 -0
  200. synapse/http/federation/well_known_resolver.py +367 -0
  201. synapse/http/matrixfederationclient.py +1875 -0
  202. synapse/http/proxy.py +290 -0
  203. synapse/http/proxyagent.py +497 -0
  204. synapse/http/replicationagent.py +203 -0
  205. synapse/http/request_metrics.py +309 -0
  206. synapse/http/server.py +1114 -0
  207. synapse/http/servlet.py +1019 -0
  208. synapse/http/site.py +825 -0
  209. synapse/http/types.py +27 -0
  210. synapse/logging/__init__.py +31 -0
  211. synapse/logging/_remote.py +261 -0
  212. synapse/logging/_terse_json.py +95 -0
  213. synapse/logging/context.py +1211 -0
  214. synapse/logging/formatter.py +63 -0
  215. synapse/logging/handlers.py +99 -0
  216. synapse/logging/loggers.py +25 -0
  217. synapse/logging/opentracing.py +1132 -0
  218. synapse/logging/scopecontextmanager.py +161 -0
  219. synapse/media/_base.py +827 -0
  220. synapse/media/filepath.py +417 -0
  221. synapse/media/media_repository.py +1580 -0
  222. synapse/media/media_storage.py +704 -0
  223. synapse/media/oembed.py +277 -0
  224. synapse/media/preview_html.py +559 -0
  225. synapse/media/storage_provider.py +195 -0
  226. synapse/media/thumbnailer.py +833 -0
  227. synapse/media/url_previewer.py +875 -0
  228. synapse/metrics/__init__.py +754 -0
  229. synapse/metrics/_gc.py +219 -0
  230. synapse/metrics/_reactor_metrics.py +171 -0
  231. synapse/metrics/_types.py +38 -0
  232. synapse/metrics/background_process_metrics.py +556 -0
  233. synapse/metrics/common_usage_metrics.py +94 -0
  234. synapse/metrics/jemalloc.py +248 -0
  235. synapse/module_api/__init__.py +2154 -0
  236. synapse/module_api/callbacks/__init__.py +50 -0
  237. synapse/module_api/callbacks/account_validity_callbacks.py +106 -0
  238. synapse/module_api/callbacks/media_repository_callbacks.py +160 -0
  239. synapse/module_api/callbacks/ratelimit_callbacks.py +79 -0
  240. synapse/module_api/callbacks/spamchecker_callbacks.py +1113 -0
  241. synapse/module_api/callbacks/third_party_event_rules_callbacks.py +599 -0
  242. synapse/module_api/errors.py +42 -0
  243. synapse/notifier.py +972 -0
  244. synapse/push/__init__.py +212 -0
  245. synapse/push/bulk_push_rule_evaluator.py +637 -0
  246. synapse/push/clientformat.py +126 -0
  247. synapse/push/emailpusher.py +333 -0
  248. synapse/push/httppusher.py +564 -0
  249. synapse/push/mailer.py +1012 -0
  250. synapse/push/presentable_names.py +216 -0
  251. synapse/push/push_tools.py +114 -0
  252. synapse/push/push_types.py +141 -0
  253. synapse/push/pusher.py +87 -0
  254. synapse/push/pusherpool.py +501 -0
  255. synapse/push/rulekinds.py +33 -0
  256. synapse/py.typed +0 -0
  257. synapse/replication/__init__.py +20 -0
  258. synapse/replication/http/__init__.py +68 -0
  259. synapse/replication/http/_base.py +468 -0
  260. synapse/replication/http/account_data.py +297 -0
  261. synapse/replication/http/deactivate_account.py +81 -0
  262. synapse/replication/http/delayed_events.py +62 -0
  263. synapse/replication/http/devices.py +254 -0
  264. synapse/replication/http/federation.py +334 -0
  265. synapse/replication/http/login.py +106 -0
  266. synapse/replication/http/membership.py +364 -0
  267. synapse/replication/http/presence.py +133 -0
  268. synapse/replication/http/push.py +156 -0
  269. synapse/replication/http/register.py +172 -0
  270. synapse/replication/http/send_events.py +182 -0
  271. synapse/replication/http/state.py +82 -0
  272. synapse/replication/http/streams.py +101 -0
  273. synapse/replication/tcp/__init__.py +56 -0
  274. synapse/replication/tcp/client.py +552 -0
  275. synapse/replication/tcp/commands.py +569 -0
  276. synapse/replication/tcp/context.py +41 -0
  277. synapse/replication/tcp/external_cache.py +156 -0
  278. synapse/replication/tcp/handler.py +942 -0
  279. synapse/replication/tcp/protocol.py +608 -0
  280. synapse/replication/tcp/redis.py +509 -0
  281. synapse/replication/tcp/resource.py +348 -0
  282. synapse/replication/tcp/streams/__init__.py +96 -0
  283. synapse/replication/tcp/streams/_base.py +766 -0
  284. synapse/replication/tcp/streams/events.py +287 -0
  285. synapse/replication/tcp/streams/federation.py +92 -0
  286. synapse/replication/tcp/streams/partial_state.py +80 -0
  287. synapse/res/providers.json +29 -0
  288. synapse/res/templates/_base.html +29 -0
  289. synapse/res/templates/account_previously_renewed.html +6 -0
  290. synapse/res/templates/account_renewed.html +6 -0
  291. synapse/res/templates/add_threepid.html +8 -0
  292. synapse/res/templates/add_threepid.txt +6 -0
  293. synapse/res/templates/add_threepid_failure.html +7 -0
  294. synapse/res/templates/add_threepid_success.html +6 -0
  295. synapse/res/templates/already_in_use.html +12 -0
  296. synapse/res/templates/already_in_use.txt +10 -0
  297. synapse/res/templates/auth_success.html +21 -0
  298. synapse/res/templates/invalid_token.html +6 -0
  299. synapse/res/templates/mail-Element.css +7 -0
  300. synapse/res/templates/mail-Vector.css +7 -0
  301. synapse/res/templates/mail-expiry.css +4 -0
  302. synapse/res/templates/mail.css +156 -0
  303. synapse/res/templates/notice_expiry.html +46 -0
  304. synapse/res/templates/notice_expiry.txt +7 -0
  305. synapse/res/templates/notif.html +51 -0
  306. synapse/res/templates/notif.txt +22 -0
  307. synapse/res/templates/notif_mail.html +59 -0
  308. synapse/res/templates/notif_mail.txt +10 -0
  309. synapse/res/templates/password_reset.html +10 -0
  310. synapse/res/templates/password_reset.txt +7 -0
  311. synapse/res/templates/password_reset_confirmation.html +15 -0
  312. synapse/res/templates/password_reset_failure.html +7 -0
  313. synapse/res/templates/password_reset_success.html +6 -0
  314. synapse/res/templates/recaptcha.html +42 -0
  315. synapse/res/templates/registration.html +12 -0
  316. synapse/res/templates/registration.txt +10 -0
  317. synapse/res/templates/registration_failure.html +6 -0
  318. synapse/res/templates/registration_success.html +6 -0
  319. synapse/res/templates/registration_token.html +18 -0
  320. synapse/res/templates/room.html +33 -0
  321. synapse/res/templates/room.txt +9 -0
  322. synapse/res/templates/sso.css +129 -0
  323. synapse/res/templates/sso_account_deactivated.html +25 -0
  324. synapse/res/templates/sso_auth_account_details.html +186 -0
  325. synapse/res/templates/sso_auth_account_details.js +116 -0
  326. synapse/res/templates/sso_auth_bad_user.html +26 -0
  327. synapse/res/templates/sso_auth_confirm.html +27 -0
  328. synapse/res/templates/sso_auth_success.html +26 -0
  329. synapse/res/templates/sso_error.html +71 -0
  330. synapse/res/templates/sso_footer.html +19 -0
  331. synapse/res/templates/sso_login_idp_picker.html +60 -0
  332. synapse/res/templates/sso_new_user_consent.html +30 -0
  333. synapse/res/templates/sso_partial_profile.html +19 -0
  334. synapse/res/templates/sso_redirect_confirm.html +39 -0
  335. synapse/res/templates/style.css +33 -0
  336. synapse/res/templates/terms.html +27 -0
  337. synapse/rest/__init__.py +197 -0
  338. synapse/rest/admin/__init__.py +390 -0
  339. synapse/rest/admin/_base.py +72 -0
  340. synapse/rest/admin/background_updates.py +171 -0
  341. synapse/rest/admin/devices.py +221 -0
  342. synapse/rest/admin/event_reports.py +173 -0
  343. synapse/rest/admin/events.py +69 -0
  344. synapse/rest/admin/experimental_features.py +137 -0
  345. synapse/rest/admin/federation.py +243 -0
  346. synapse/rest/admin/media.py +540 -0
  347. synapse/rest/admin/registration_tokens.py +358 -0
  348. synapse/rest/admin/rooms.py +1061 -0
  349. synapse/rest/admin/scheduled_tasks.py +70 -0
  350. synapse/rest/admin/server_notice_servlet.py +132 -0
  351. synapse/rest/admin/statistics.py +132 -0
  352. synapse/rest/admin/username_available.py +58 -0
  353. synapse/rest/admin/users.py +1608 -0
  354. synapse/rest/client/__init__.py +20 -0
  355. synapse/rest/client/_base.py +113 -0
  356. synapse/rest/client/account.py +930 -0
  357. synapse/rest/client/account_data.py +319 -0
  358. synapse/rest/client/account_validity.py +103 -0
  359. synapse/rest/client/appservice_ping.py +125 -0
  360. synapse/rest/client/auth.py +218 -0
  361. synapse/rest/client/auth_metadata.py +122 -0
  362. synapse/rest/client/capabilities.py +121 -0
  363. synapse/rest/client/delayed_events.py +111 -0
  364. synapse/rest/client/devices.py +587 -0
  365. synapse/rest/client/directory.py +211 -0
  366. synapse/rest/client/events.py +116 -0
  367. synapse/rest/client/filter.py +112 -0
  368. synapse/rest/client/initial_sync.py +65 -0
  369. synapse/rest/client/keys.py +678 -0
  370. synapse/rest/client/knock.py +104 -0
  371. synapse/rest/client/login.py +754 -0
  372. synapse/rest/client/login_token_request.py +127 -0
  373. synapse/rest/client/logout.py +93 -0
  374. synapse/rest/client/matrixrtc.py +52 -0
  375. synapse/rest/client/media.py +286 -0
  376. synapse/rest/client/mutual_rooms.py +93 -0
  377. synapse/rest/client/notifications.py +137 -0
  378. synapse/rest/client/openid.py +109 -0
  379. synapse/rest/client/password_policy.py +69 -0
  380. synapse/rest/client/presence.py +131 -0
  381. synapse/rest/client/profile.py +291 -0
  382. synapse/rest/client/push_rule.py +331 -0
  383. synapse/rest/client/pusher.py +181 -0
  384. synapse/rest/client/read_marker.py +104 -0
  385. synapse/rest/client/receipts.py +165 -0
  386. synapse/rest/client/register.py +1067 -0
  387. synapse/rest/client/relations.py +138 -0
  388. synapse/rest/client/rendezvous.py +76 -0
  389. synapse/rest/client/reporting.py +207 -0
  390. synapse/rest/client/room.py +1669 -0
  391. synapse/rest/client/room_keys.py +426 -0
  392. synapse/rest/client/room_upgrade_rest_servlet.py +112 -0
  393. synapse/rest/client/sendtodevice.py +85 -0
  394. synapse/rest/client/sync.py +1131 -0
  395. synapse/rest/client/tags.py +129 -0
  396. synapse/rest/client/thirdparty.py +130 -0
  397. synapse/rest/client/thread_subscriptions.py +247 -0
  398. synapse/rest/client/tokenrefresh.py +52 -0
  399. synapse/rest/client/transactions.py +149 -0
  400. synapse/rest/client/user_directory.py +90 -0
  401. synapse/rest/client/versions.py +191 -0
  402. synapse/rest/client/voip.py +88 -0
  403. synapse/rest/consent/__init__.py +0 -0
  404. synapse/rest/consent/consent_resource.py +210 -0
  405. synapse/rest/health.py +38 -0
  406. synapse/rest/key/__init__.py +20 -0
  407. synapse/rest/key/v2/__init__.py +40 -0
  408. synapse/rest/key/v2/local_key_resource.py +125 -0
  409. synapse/rest/key/v2/remote_key_resource.py +302 -0
  410. synapse/rest/media/__init__.py +0 -0
  411. synapse/rest/media/config_resource.py +53 -0
  412. synapse/rest/media/create_resource.py +90 -0
  413. synapse/rest/media/download_resource.py +110 -0
  414. synapse/rest/media/media_repository_resource.py +113 -0
  415. synapse/rest/media/preview_url_resource.py +77 -0
  416. synapse/rest/media/thumbnail_resource.py +142 -0
  417. synapse/rest/media/upload_resource.py +187 -0
  418. synapse/rest/media/v1/__init__.py +39 -0
  419. synapse/rest/media/v1/_base.py +23 -0
  420. synapse/rest/media/v1/media_storage.py +23 -0
  421. synapse/rest/media/v1/storage_provider.py +23 -0
  422. synapse/rest/synapse/__init__.py +20 -0
  423. synapse/rest/synapse/client/__init__.py +93 -0
  424. synapse/rest/synapse/client/federation_whitelist.py +66 -0
  425. synapse/rest/synapse/client/jwks.py +77 -0
  426. synapse/rest/synapse/client/new_user_consent.py +115 -0
  427. synapse/rest/synapse/client/oidc/__init__.py +45 -0
  428. synapse/rest/synapse/client/oidc/backchannel_logout_resource.py +42 -0
  429. synapse/rest/synapse/client/oidc/callback_resource.py +48 -0
  430. synapse/rest/synapse/client/password_reset.py +129 -0
  431. synapse/rest/synapse/client/pick_idp.py +107 -0
  432. synapse/rest/synapse/client/pick_username.py +153 -0
  433. synapse/rest/synapse/client/rendezvous.py +58 -0
  434. synapse/rest/synapse/client/saml2/__init__.py +42 -0
  435. synapse/rest/synapse/client/saml2/metadata_resource.py +46 -0
  436. synapse/rest/synapse/client/saml2/response_resource.py +52 -0
  437. synapse/rest/synapse/client/sso_register.py +56 -0
  438. synapse/rest/synapse/client/unsubscribe.py +88 -0
  439. synapse/rest/synapse/mas/__init__.py +71 -0
  440. synapse/rest/synapse/mas/_base.py +55 -0
  441. synapse/rest/synapse/mas/devices.py +239 -0
  442. synapse/rest/synapse/mas/users.py +469 -0
  443. synapse/rest/well_known.py +148 -0
  444. synapse/server.py +1258 -0
  445. synapse/server_notices/__init__.py +0 -0
  446. synapse/server_notices/consent_server_notices.py +136 -0
  447. synapse/server_notices/resource_limits_server_notices.py +215 -0
  448. synapse/server_notices/server_notices_manager.py +388 -0
  449. synapse/server_notices/server_notices_sender.py +67 -0
  450. synapse/server_notices/worker_server_notices_sender.py +46 -0
  451. synapse/spam_checker_api/__init__.py +31 -0
  452. synapse/state/__init__.py +1022 -0
  453. synapse/state/v1.py +370 -0
  454. synapse/state/v2.py +985 -0
  455. synapse/static/client/login/index.html +47 -0
  456. synapse/static/client/login/js/jquery-3.4.1.min.js +2 -0
  457. synapse/static/client/login/js/login.js +291 -0
  458. synapse/static/client/login/spinner.gif +0 -0
  459. synapse/static/client/login/style.css +79 -0
  460. synapse/static/index.html +63 -0
  461. synapse/storage/__init__.py +43 -0
  462. synapse/storage/_base.py +245 -0
  463. synapse/storage/admin_client_config.py +26 -0
  464. synapse/storage/background_updates.py +1189 -0
  465. synapse/storage/controllers/__init__.py +57 -0
  466. synapse/storage/controllers/persist_events.py +1239 -0
  467. synapse/storage/controllers/purge_events.py +456 -0
  468. synapse/storage/controllers/state.py +954 -0
  469. synapse/storage/controllers/stats.py +119 -0
  470. synapse/storage/database.py +2720 -0
  471. synapse/storage/databases/__init__.py +175 -0
  472. synapse/storage/databases/main/__init__.py +424 -0
  473. synapse/storage/databases/main/account_data.py +1060 -0
  474. synapse/storage/databases/main/appservice.py +473 -0
  475. synapse/storage/databases/main/cache.py +911 -0
  476. synapse/storage/databases/main/censor_events.py +225 -0
  477. synapse/storage/databases/main/client_ips.py +817 -0
  478. synapse/storage/databases/main/delayed_events.py +560 -0
  479. synapse/storage/databases/main/deviceinbox.py +1272 -0
  480. synapse/storage/databases/main/devices.py +2581 -0
  481. synapse/storage/databases/main/directory.py +212 -0
  482. synapse/storage/databases/main/e2e_room_keys.py +690 -0
  483. synapse/storage/databases/main/end_to_end_keys.py +1896 -0
  484. synapse/storage/databases/main/event_federation.py +2509 -0
  485. synapse/storage/databases/main/event_push_actions.py +1937 -0
  486. synapse/storage/databases/main/events.py +3746 -0
  487. synapse/storage/databases/main/events_bg_updates.py +2910 -0
  488. synapse/storage/databases/main/events_forward_extremities.py +126 -0
  489. synapse/storage/databases/main/events_worker.py +2784 -0
  490. synapse/storage/databases/main/experimental_features.py +130 -0
  491. synapse/storage/databases/main/filtering.py +231 -0
  492. synapse/storage/databases/main/keys.py +291 -0
  493. synapse/storage/databases/main/lock.py +553 -0
  494. synapse/storage/databases/main/media_repository.py +1070 -0
  495. synapse/storage/databases/main/metrics.py +460 -0
  496. synapse/storage/databases/main/monthly_active_users.py +443 -0
  497. synapse/storage/databases/main/openid.py +61 -0
  498. synapse/storage/databases/main/presence.py +511 -0
  499. synapse/storage/databases/main/profile.py +541 -0
  500. synapse/storage/databases/main/purge_events.py +511 -0
  501. synapse/storage/databases/main/push_rule.py +972 -0
  502. synapse/storage/databases/main/pusher.py +794 -0
  503. synapse/storage/databases/main/receipts.py +1342 -0
  504. synapse/storage/databases/main/registration.py +3076 -0
  505. synapse/storage/databases/main/rejections.py +38 -0
  506. synapse/storage/databases/main/relations.py +1118 -0
  507. synapse/storage/databases/main/room.py +2781 -0
  508. synapse/storage/databases/main/roommember.py +2112 -0
  509. synapse/storage/databases/main/search.py +941 -0
  510. synapse/storage/databases/main/session.py +151 -0
  511. synapse/storage/databases/main/signatures.py +94 -0
  512. synapse/storage/databases/main/sliding_sync.py +603 -0
  513. synapse/storage/databases/main/state.py +1006 -0
  514. synapse/storage/databases/main/state_deltas.py +329 -0
  515. synapse/storage/databases/main/stats.py +791 -0
  516. synapse/storage/databases/main/stream.py +2580 -0
  517. synapse/storage/databases/main/tags.py +360 -0
  518. synapse/storage/databases/main/task_scheduler.py +225 -0
  519. synapse/storage/databases/main/thread_subscriptions.py +591 -0
  520. synapse/storage/databases/main/transactions.py +681 -0
  521. synapse/storage/databases/main/ui_auth.py +420 -0
  522. synapse/storage/databases/main/user_directory.py +1331 -0
  523. synapse/storage/databases/main/user_erasure_store.py +117 -0
  524. synapse/storage/databases/state/__init__.py +22 -0
  525. synapse/storage/databases/state/bg_updates.py +499 -0
  526. synapse/storage/databases/state/deletion.py +558 -0
  527. synapse/storage/databases/state/store.py +949 -0
  528. synapse/storage/engines/__init__.py +70 -0
  529. synapse/storage/engines/_base.py +154 -0
  530. synapse/storage/engines/postgres.py +261 -0
  531. synapse/storage/engines/sqlite.py +199 -0
  532. synapse/storage/invite_rule.py +112 -0
  533. synapse/storage/keys.py +40 -0
  534. synapse/storage/prepare_database.py +731 -0
  535. synapse/storage/push_rule.py +28 -0
  536. synapse/storage/roommember.py +89 -0
  537. synapse/storage/schema/README.md +4 -0
  538. synapse/storage/schema/__init__.py +182 -0
  539. synapse/storage/schema/common/delta/25/00background_updates.sql +40 -0
  540. synapse/storage/schema/common/delta/35/00background_updates_add_col.sql +36 -0
  541. synapse/storage/schema/common/delta/58/00background_update_ordering.sql +38 -0
  542. synapse/storage/schema/common/full_schemas/72/full.sql.postgres +8 -0
  543. synapse/storage/schema/common/full_schemas/72/full.sql.sqlite +6 -0
  544. synapse/storage/schema/common/schema_version.sql +60 -0
  545. synapse/storage/schema/main/delta/12/v12.sql +82 -0
  546. synapse/storage/schema/main/delta/13/v13.sql +38 -0
  547. synapse/storage/schema/main/delta/14/v14.sql +42 -0
  548. synapse/storage/schema/main/delta/15/appservice_txns.sql +50 -0
  549. synapse/storage/schema/main/delta/15/presence_indices.sql +2 -0
  550. synapse/storage/schema/main/delta/15/v15.sql +24 -0
  551. synapse/storage/schema/main/delta/16/events_order_index.sql +4 -0
  552. synapse/storage/schema/main/delta/16/remote_media_cache_index.sql +2 -0
  553. synapse/storage/schema/main/delta/16/remove_duplicates.sql +9 -0
  554. synapse/storage/schema/main/delta/16/room_alias_index.sql +3 -0
  555. synapse/storage/schema/main/delta/16/unique_constraints.sql +72 -0
  556. synapse/storage/schema/main/delta/16/users.sql +56 -0
  557. synapse/storage/schema/main/delta/17/drop_indexes.sql +37 -0
  558. synapse/storage/schema/main/delta/17/server_keys.sql +43 -0
  559. synapse/storage/schema/main/delta/17/user_threepids.sql +9 -0
  560. synapse/storage/schema/main/delta/18/server_keys_bigger_ints.sql +51 -0
  561. synapse/storage/schema/main/delta/19/event_index.sql +38 -0
  562. synapse/storage/schema/main/delta/20/dummy.sql +1 -0
  563. synapse/storage/schema/main/delta/20/pushers.py +93 -0
  564. synapse/storage/schema/main/delta/21/end_to_end_keys.sql +53 -0
  565. synapse/storage/schema/main/delta/21/receipts.sql +57 -0
  566. synapse/storage/schema/main/delta/22/receipts_index.sql +41 -0
  567. synapse/storage/schema/main/delta/22/user_threepids_unique.sql +19 -0
  568. synapse/storage/schema/main/delta/24/stats_reporting.sql +37 -0
  569. synapse/storage/schema/main/delta/25/fts.py +81 -0
  570. synapse/storage/schema/main/delta/25/guest_access.sql +44 -0
  571. synapse/storage/schema/main/delta/25/history_visibility.sql +44 -0
  572. synapse/storage/schema/main/delta/25/tags.sql +57 -0
  573. synapse/storage/schema/main/delta/26/account_data.sql +36 -0
  574. synapse/storage/schema/main/delta/27/account_data.sql +55 -0
  575. synapse/storage/schema/main/delta/27/forgotten_memberships.sql +45 -0
  576. synapse/storage/schema/main/delta/27/ts.py +61 -0
  577. synapse/storage/schema/main/delta/28/event_push_actions.sql +46 -0
  578. synapse/storage/schema/main/delta/28/events_room_stream.sql +39 -0
  579. synapse/storage/schema/main/delta/28/public_roms_index.sql +39 -0
  580. synapse/storage/schema/main/delta/28/receipts_user_id_index.sql +41 -0
  581. synapse/storage/schema/main/delta/28/upgrade_times.sql +40 -0
  582. synapse/storage/schema/main/delta/28/users_is_guest.sql +41 -0
  583. synapse/storage/schema/main/delta/29/push_actions.sql +54 -0
  584. synapse/storage/schema/main/delta/30/alias_creator.sql +35 -0
  585. synapse/storage/schema/main/delta/30/as_users.py +82 -0
  586. synapse/storage/schema/main/delta/30/deleted_pushers.sql +44 -0
  587. synapse/storage/schema/main/delta/30/presence_stream.sql +49 -0
  588. synapse/storage/schema/main/delta/30/public_rooms.sql +42 -0
  589. synapse/storage/schema/main/delta/30/push_rule_stream.sql +57 -0
  590. synapse/storage/schema/main/delta/30/threepid_guest_access_tokens.sql +43 -0
  591. synapse/storage/schema/main/delta/31/invites.sql +61 -0
  592. synapse/storage/schema/main/delta/31/local_media_repository_url_cache.sql +46 -0
  593. synapse/storage/schema/main/delta/31/pushers_0.py +92 -0
  594. synapse/storage/schema/main/delta/31/pushers_index.sql +41 -0
  595. synapse/storage/schema/main/delta/31/search_update.py +65 -0
  596. synapse/storage/schema/main/delta/32/events.sql +35 -0
  597. synapse/storage/schema/main/delta/32/openid.sql +9 -0
  598. synapse/storage/schema/main/delta/32/pusher_throttle.sql +42 -0
  599. synapse/storage/schema/main/delta/32/remove_indices.sql +52 -0
  600. synapse/storage/schema/main/delta/32/reports.sql +44 -0
  601. synapse/storage/schema/main/delta/33/access_tokens_device_index.sql +36 -0
  602. synapse/storage/schema/main/delta/33/devices.sql +40 -0
  603. synapse/storage/schema/main/delta/33/devices_for_e2e_keys.sql +38 -0
  604. synapse/storage/schema/main/delta/33/devices_for_e2e_keys_clear_unknown_device.sql +39 -0
  605. synapse/storage/schema/main/delta/33/event_fields.py +61 -0
  606. synapse/storage/schema/main/delta/33/remote_media_ts.py +43 -0
  607. synapse/storage/schema/main/delta/33/user_ips_index.sql +36 -0
  608. synapse/storage/schema/main/delta/34/appservice_stream.sql +42 -0
  609. synapse/storage/schema/main/delta/34/cache_stream.py +50 -0
  610. synapse/storage/schema/main/delta/34/device_inbox.sql +43 -0
  611. synapse/storage/schema/main/delta/34/push_display_name_rename.sql +39 -0
  612. synapse/storage/schema/main/delta/34/received_txn_purge.py +36 -0
  613. synapse/storage/schema/main/delta/35/contains_url.sql +36 -0
  614. synapse/storage/schema/main/delta/35/device_outbox.sql +58 -0
  615. synapse/storage/schema/main/delta/35/device_stream_id.sql +40 -0
  616. synapse/storage/schema/main/delta/35/event_push_actions_index.sql +36 -0
  617. synapse/storage/schema/main/delta/35/public_room_list_change_stream.sql +52 -0
  618. synapse/storage/schema/main/delta/35/stream_order_to_extrem.sql +56 -0
  619. synapse/storage/schema/main/delta/36/readd_public_rooms.sql +45 -0
  620. synapse/storage/schema/main/delta/37/remove_auth_idx.py +89 -0
  621. synapse/storage/schema/main/delta/37/user_threepids.sql +71 -0
  622. synapse/storage/schema/main/delta/38/postgres_fts_gist.sql +38 -0
  623. synapse/storage/schema/main/delta/39/appservice_room_list.sql +48 -0
  624. synapse/storage/schema/main/delta/39/device_federation_stream_idx.sql +35 -0
  625. synapse/storage/schema/main/delta/39/event_push_index.sql +36 -0
  626. synapse/storage/schema/main/delta/39/federation_out_position.sql +41 -0
  627. synapse/storage/schema/main/delta/39/membership_profile.sql +39 -0
  628. synapse/storage/schema/main/delta/40/current_state_idx.sql +36 -0
  629. synapse/storage/schema/main/delta/40/device_inbox.sql +40 -0
  630. synapse/storage/schema/main/delta/40/device_list_streams.sql +79 -0
  631. synapse/storage/schema/main/delta/40/event_push_summary.sql +57 -0
  632. synapse/storage/schema/main/delta/40/pushers.sql +58 -0
  633. synapse/storage/schema/main/delta/41/device_list_stream_idx.sql +36 -0
  634. synapse/storage/schema/main/delta/41/device_outbound_index.sql +35 -0
  635. synapse/storage/schema/main/delta/41/event_search_event_id_idx.sql +36 -0
  636. synapse/storage/schema/main/delta/41/ratelimit.sql +41 -0
  637. synapse/storage/schema/main/delta/42/current_state_delta.sql +48 -0
  638. synapse/storage/schema/main/delta/42/device_list_last_id.sql +52 -0
  639. synapse/storage/schema/main/delta/42/event_auth_state_only.sql +36 -0
  640. synapse/storage/schema/main/delta/42/user_dir.py +88 -0
  641. synapse/storage/schema/main/delta/43/blocked_rooms.sql +40 -0
  642. synapse/storage/schema/main/delta/43/quarantine_media.sql +36 -0
  643. synapse/storage/schema/main/delta/43/url_cache.sql +35 -0
  644. synapse/storage/schema/main/delta/43/user_share.sql +52 -0
  645. synapse/storage/schema/main/delta/44/expire_url_cache.sql +60 -0
  646. synapse/storage/schema/main/delta/45/group_server.sql +186 -0
  647. synapse/storage/schema/main/delta/45/profile_cache.sql +47 -0
  648. synapse/storage/schema/main/delta/46/drop_refresh_tokens.sql +36 -0
  649. synapse/storage/schema/main/delta/46/drop_unique_deleted_pushers.sql +54 -0
  650. synapse/storage/schema/main/delta/46/group_server.sql +51 -0
  651. synapse/storage/schema/main/delta/46/local_media_repository_url_idx.sql +43 -0
  652. synapse/storage/schema/main/delta/46/user_dir_null_room_ids.sql +54 -0
  653. synapse/storage/schema/main/delta/46/user_dir_typos.sql +43 -0
  654. synapse/storage/schema/main/delta/47/last_access_media.sql +35 -0
  655. synapse/storage/schema/main/delta/47/postgres_fts_gin.sql +36 -0
  656. synapse/storage/schema/main/delta/47/push_actions_staging.sql +47 -0
  657. synapse/storage/schema/main/delta/48/add_user_consent.sql +37 -0
  658. synapse/storage/schema/main/delta/48/add_user_ips_last_seen_index.sql +36 -0
  659. synapse/storage/schema/main/delta/48/deactivated_users.sql +44 -0
  660. synapse/storage/schema/main/delta/48/group_unique_indexes.py +67 -0
  661. synapse/storage/schema/main/delta/48/groups_joinable.sql +41 -0
  662. synapse/storage/schema/main/delta/49/add_user_consent_server_notice_sent.sql +39 -0
  663. synapse/storage/schema/main/delta/49/add_user_daily_visits.sql +40 -0
  664. synapse/storage/schema/main/delta/49/add_user_ips_last_seen_only_index.sql +36 -0
  665. synapse/storage/schema/main/delta/50/add_creation_ts_users_index.sql +38 -0
  666. synapse/storage/schema/main/delta/50/erasure_store.sql +40 -0
  667. synapse/storage/schema/main/delta/50/make_event_content_nullable.py +102 -0
  668. synapse/storage/schema/main/delta/51/e2e_room_keys.sql +58 -0
  669. synapse/storage/schema/main/delta/51/monthly_active_users.sql +46 -0
  670. synapse/storage/schema/main/delta/52/add_event_to_state_group_index.sql +38 -0
  671. synapse/storage/schema/main/delta/52/device_list_streams_unique_idx.sql +55 -0
  672. synapse/storage/schema/main/delta/52/e2e_room_keys.sql +72 -0
  673. synapse/storage/schema/main/delta/53/add_user_type_to_users.sql +38 -0
  674. synapse/storage/schema/main/delta/53/drop_sent_transactions.sql +35 -0
  675. synapse/storage/schema/main/delta/53/event_format_version.sql +35 -0
  676. synapse/storage/schema/main/delta/53/user_dir_populate.sql +49 -0
  677. synapse/storage/schema/main/delta/53/user_ips_index.sql +49 -0
  678. synapse/storage/schema/main/delta/53/user_share.sql +63 -0
  679. synapse/storage/schema/main/delta/53/user_threepid_id.sql +48 -0
  680. synapse/storage/schema/main/delta/53/users_in_public_rooms.sql +47 -0
  681. synapse/storage/schema/main/delta/54/account_validity_with_renewal.sql +49 -0
  682. synapse/storage/schema/main/delta/54/add_validity_to_server_keys.sql +42 -0
  683. synapse/storage/schema/main/delta/54/delete_forward_extremities.sql +42 -0
  684. synapse/storage/schema/main/delta/54/drop_legacy_tables.sql +49 -0
  685. synapse/storage/schema/main/delta/54/drop_presence_list.sql +35 -0
  686. synapse/storage/schema/main/delta/54/relations.sql +46 -0
  687. synapse/storage/schema/main/delta/54/stats.sql +99 -0
  688. synapse/storage/schema/main/delta/54/stats2.sql +47 -0
  689. synapse/storage/schema/main/delta/55/access_token_expiry.sql +37 -0
  690. synapse/storage/schema/main/delta/55/track_threepid_validations.sql +50 -0
  691. synapse/storage/schema/main/delta/55/users_alter_deactivated.sql +38 -0
  692. synapse/storage/schema/main/delta/56/add_spans_to_device_lists.sql +39 -0
  693. synapse/storage/schema/main/delta/56/current_state_events_membership.sql +41 -0
  694. synapse/storage/schema/main/delta/56/current_state_events_membership_mk2.sql +43 -0
  695. synapse/storage/schema/main/delta/56/delete_keys_from_deleted_backups.sql +44 -0
  696. synapse/storage/schema/main/delta/56/destinations_failure_ts.sql +44 -0
  697. synapse/storage/schema/main/delta/56/destinations_retry_interval_type.sql.postgres +18 -0
  698. synapse/storage/schema/main/delta/56/device_stream_id_insert.sql +39 -0
  699. synapse/storage/schema/main/delta/56/devices_last_seen.sql +43 -0
  700. synapse/storage/schema/main/delta/56/drop_unused_event_tables.sql +39 -0
  701. synapse/storage/schema/main/delta/56/event_expiry.sql +40 -0
  702. synapse/storage/schema/main/delta/56/event_labels.sql +49 -0
  703. synapse/storage/schema/main/delta/56/event_labels_background_update.sql +36 -0
  704. synapse/storage/schema/main/delta/56/fix_room_keys_index.sql +37 -0
  705. synapse/storage/schema/main/delta/56/hidden_devices.sql +37 -0
  706. synapse/storage/schema/main/delta/56/hidden_devices_fix.sql.sqlite +42 -0
  707. synapse/storage/schema/main/delta/56/nuke_empty_communities_from_db.sql +48 -0
  708. synapse/storage/schema/main/delta/56/public_room_list_idx.sql +35 -0
  709. synapse/storage/schema/main/delta/56/redaction_censor.sql +35 -0
  710. synapse/storage/schema/main/delta/56/redaction_censor2.sql +41 -0
  711. synapse/storage/schema/main/delta/56/redaction_censor3_fix_update.sql.postgres +25 -0
  712. synapse/storage/schema/main/delta/56/redaction_censor4.sql +35 -0
  713. synapse/storage/schema/main/delta/56/remove_tombstoned_rooms_from_directory.sql +38 -0
  714. synapse/storage/schema/main/delta/56/room_key_etag.sql +36 -0
  715. synapse/storage/schema/main/delta/56/room_membership_idx.sql +37 -0
  716. synapse/storage/schema/main/delta/56/room_retention.sql +52 -0
  717. synapse/storage/schema/main/delta/56/signing_keys.sql +75 -0
  718. synapse/storage/schema/main/delta/56/signing_keys_nonunique_signatures.sql +41 -0
  719. synapse/storage/schema/main/delta/56/stats_separated.sql +175 -0
  720. synapse/storage/schema/main/delta/56/unique_user_filter_index.py +46 -0
  721. synapse/storage/schema/main/delta/56/user_external_ids.sql +43 -0
  722. synapse/storage/schema/main/delta/56/users_in_public_rooms_idx.sql +36 -0
  723. synapse/storage/schema/main/delta/57/delete_old_current_state_events.sql +41 -0
  724. synapse/storage/schema/main/delta/57/device_list_remote_cache_stale.sql +44 -0
  725. synapse/storage/schema/main/delta/57/local_current_membership.py +111 -0
  726. synapse/storage/schema/main/delta/57/remove_sent_outbound_pokes.sql +40 -0
  727. synapse/storage/schema/main/delta/57/rooms_version_column.sql +43 -0
  728. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.postgres +35 -0
  729. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.sqlite +22 -0
  730. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.postgres +39 -0
  731. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.sqlite +23 -0
  732. synapse/storage/schema/main/delta/58/02remove_dup_outbound_pokes.sql +41 -0
  733. synapse/storage/schema/main/delta/58/03persist_ui_auth.sql +55 -0
  734. synapse/storage/schema/main/delta/58/05cache_instance.sql.postgres +30 -0
  735. synapse/storage/schema/main/delta/58/06dlols_unique_idx.py +83 -0
  736. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.postgres +33 -0
  737. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.sqlite +44 -0
  738. synapse/storage/schema/main/delta/58/07persist_ui_auth_ips.sql +44 -0
  739. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.postgres +18 -0
  740. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.sqlite +18 -0
  741. synapse/storage/schema/main/delta/58/09shadow_ban.sql +37 -0
  742. synapse/storage/schema/main/delta/58/10_pushrules_enabled_delete_obsolete.sql +47 -0
  743. synapse/storage/schema/main/delta/58/10drop_local_rejections_stream.sql +41 -0
  744. synapse/storage/schema/main/delta/58/10federation_pos_instance_name.sql +41 -0
  745. synapse/storage/schema/main/delta/58/11dehydration.sql +39 -0
  746. synapse/storage/schema/main/delta/58/11fallback.sql +43 -0
  747. synapse/storage/schema/main/delta/58/11user_id_seq.py +38 -0
  748. synapse/storage/schema/main/delta/58/12room_stats.sql +51 -0
  749. synapse/storage/schema/main/delta/58/13remove_presence_allow_inbound.sql +36 -0
  750. synapse/storage/schema/main/delta/58/14events_instance_name.sql +35 -0
  751. synapse/storage/schema/main/delta/58/14events_instance_name.sql.postgres +28 -0
  752. synapse/storage/schema/main/delta/58/15_catchup_destination_rooms.sql +61 -0
  753. synapse/storage/schema/main/delta/58/15unread_count.sql +45 -0
  754. synapse/storage/schema/main/delta/58/16populate_stats_process_rooms_fix.sql +41 -0
  755. synapse/storage/schema/main/delta/58/17_catchup_last_successful.sql +40 -0
  756. synapse/storage/schema/main/delta/58/18stream_positions.sql +41 -0
  757. synapse/storage/schema/main/delta/58/19instance_map.sql.postgres +25 -0
  758. synapse/storage/schema/main/delta/58/19txn_id.sql +59 -0
  759. synapse/storage/schema/main/delta/58/20instance_name_event_tables.sql +36 -0
  760. synapse/storage/schema/main/delta/58/20user_daily_visits.sql +37 -0
  761. synapse/storage/schema/main/delta/58/21as_device_stream.sql +36 -0
  762. synapse/storage/schema/main/delta/58/21drop_device_max_stream_id.sql +1 -0
  763. synapse/storage/schema/main/delta/58/22puppet_token.sql +36 -0
  764. synapse/storage/schema/main/delta/58/22users_have_local_media.sql +2 -0
  765. synapse/storage/schema/main/delta/58/23e2e_cross_signing_keys_idx.sql +36 -0
  766. synapse/storage/schema/main/delta/58/24drop_event_json_index.sql +38 -0
  767. synapse/storage/schema/main/delta/58/25user_external_ids_user_id_idx.sql +36 -0
  768. synapse/storage/schema/main/delta/58/26access_token_last_validated.sql +37 -0
  769. synapse/storage/schema/main/delta/58/27local_invites.sql +37 -0
  770. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.postgres +16 -0
  771. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.sqlite +62 -0
  772. synapse/storage/schema/main/delta/59/01ignored_user.py +85 -0
  773. synapse/storage/schema/main/delta/59/02shard_send_to_device.sql +37 -0
  774. synapse/storage/schema/main/delta/59/03shard_send_to_device_sequence.sql.postgres +25 -0
  775. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql +71 -0
  776. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql.postgres +16 -0
  777. synapse/storage/schema/main/delta/59/04drop_account_data.sql +36 -0
  778. synapse/storage/schema/main/delta/59/05cache_invalidation.sql +36 -0
  779. synapse/storage/schema/main/delta/59/06chain_cover_index.sql +36 -0
  780. synapse/storage/schema/main/delta/59/06shard_account_data.sql +39 -0
  781. synapse/storage/schema/main/delta/59/06shard_account_data.sql.postgres +32 -0
  782. synapse/storage/schema/main/delta/59/07shard_account_data_fix.sql +37 -0
  783. synapse/storage/schema/main/delta/59/08delete_pushers_for_deactivated_accounts.sql +39 -0
  784. synapse/storage/schema/main/delta/59/08delete_stale_pushers.sql +39 -0
  785. synapse/storage/schema/main/delta/59/09rejected_events_metadata.sql +45 -0
  786. synapse/storage/schema/main/delta/59/10delete_purged_chain_cover.sql +36 -0
  787. synapse/storage/schema/main/delta/59/11add_knock_members_to_stats.sql +39 -0
  788. synapse/storage/schema/main/delta/59/11drop_thumbnail_constraint.sql.postgres +22 -0
  789. synapse/storage/schema/main/delta/59/12account_validity_token_used_ts_ms.sql +37 -0
  790. synapse/storage/schema/main/delta/59/12presence_stream_instance.sql +37 -0
  791. synapse/storage/schema/main/delta/59/12presence_stream_instance_seq.sql.postgres +20 -0
  792. synapse/storage/schema/main/delta/59/13users_to_send_full_presence_to.sql +53 -0
  793. synapse/storage/schema/main/delta/59/14refresh_tokens.sql +53 -0
  794. synapse/storage/schema/main/delta/59/15locks.sql +56 -0
  795. synapse/storage/schema/main/delta/59/16federation_inbound_staging.sql +51 -0
  796. synapse/storage/schema/main/delta/60/01recreate_stream_ordering.sql.postgres +45 -0
  797. synapse/storage/schema/main/delta/60/02change_stream_ordering_columns.sql.postgres +30 -0
  798. synapse/storage/schema/main/delta/61/01change_appservices_txns.sql.postgres +23 -0
  799. synapse/storage/schema/main/delta/61/01insertion_event_lookups.sql +68 -0
  800. synapse/storage/schema/main/delta/61/02drop_redundant_room_depth_index.sql +37 -0
  801. synapse/storage/schema/main/delta/61/03recreate_min_depth.py +74 -0
  802. synapse/storage/schema/main/delta/62/01insertion_event_extremities.sql +43 -0
  803. synapse/storage/schema/main/delta/63/01create_registration_tokens.sql +42 -0
  804. synapse/storage/schema/main/delta/63/02delete_unlinked_email_pushers.sql +39 -0
  805. synapse/storage/schema/main/delta/63/02populate-rooms-creator.sql +36 -0
  806. synapse/storage/schema/main/delta/63/03session_store.sql +42 -0
  807. synapse/storage/schema/main/delta/63/04add_presence_stream_not_offline_index.sql +37 -0
  808. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.postgres +23 -0
  809. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.sqlite +37 -0
  810. synapse/storage/schema/main/delta/65/01msc2716_insertion_event_edges.sql +38 -0
  811. synapse/storage/schema/main/delta/65/03remove_hidden_devices_from_device_inbox.sql +41 -0
  812. synapse/storage/schema/main/delta/65/04_local_group_updates.sql +37 -0
  813. synapse/storage/schema/main/delta/65/05_remove_room_stats_historical_and_user_stats_historical.sql +38 -0
  814. synapse/storage/schema/main/delta/65/06remove_deleted_devices_from_device_inbox.sql +53 -0
  815. synapse/storage/schema/main/delta/65/07_arbitrary_relations.sql +37 -0
  816. synapse/storage/schema/main/delta/65/08_device_inbox_background_updates.sql +37 -0
  817. synapse/storage/schema/main/delta/65/10_expirable_refresh_tokens.sql +47 -0
  818. synapse/storage/schema/main/delta/65/11_devices_auth_provider_session.sql +46 -0
  819. synapse/storage/schema/main/delta/67/01drop_public_room_list_stream.sql +37 -0
  820. synapse/storage/schema/main/delta/68/01event_columns.sql +45 -0
  821. synapse/storage/schema/main/delta/68/02_msc2409_add_device_id_appservice_stream_type.sql +40 -0
  822. synapse/storage/schema/main/delta/68/03_delete_account_data_for_deactivated_accounts.sql +39 -0
  823. synapse/storage/schema/main/delta/68/04_refresh_tokens_index_next_token_id.sql +47 -0
  824. synapse/storage/schema/main/delta/68/04partial_state_rooms.sql +60 -0
  825. synapse/storage/schema/main/delta/68/05_delete_non_strings_from_event_search.sql.sqlite +22 -0
  826. synapse/storage/schema/main/delta/68/05partial_state_rooms_triggers.py +80 -0
  827. synapse/storage/schema/main/delta/68/06_msc3202_add_device_list_appservice_stream_type.sql +42 -0
  828. synapse/storage/schema/main/delta/69/01as_txn_seq.py +54 -0
  829. synapse/storage/schema/main/delta/69/01device_list_oubound_by_room.sql +57 -0
  830. synapse/storage/schema/main/delta/69/02cache_invalidation_index.sql +37 -0
  831. synapse/storage/schema/main/delta/70/01clean_table_purged_rooms.sql +39 -0
  832. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.postgres +43 -0
  833. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.sqlite +47 -0
  834. synapse/storage/schema/main/delta/71/01remove_noop_background_updates.sql +80 -0
  835. synapse/storage/schema/main/delta/71/02event_push_summary_unique.sql +37 -0
  836. synapse/storage/schema/main/delta/72/01add_room_type_to_state_stats.sql +38 -0
  837. synapse/storage/schema/main/delta/72/01event_push_summary_receipt.sql +54 -0
  838. synapse/storage/schema/main/delta/72/02event_push_actions_index.sql +38 -0
  839. synapse/storage/schema/main/delta/72/03bg_populate_events_columns.py +57 -0
  840. synapse/storage/schema/main/delta/72/03drop_event_reference_hashes.sql +36 -0
  841. synapse/storage/schema/main/delta/72/03remove_groups.sql +50 -0
  842. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.postgres +17 -0
  843. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.sqlite +40 -0
  844. synapse/storage/schema/main/delta/72/05receipts_event_stream_ordering.sql +38 -0
  845. synapse/storage/schema/main/delta/72/05remove_unstable_private_read_receipts.sql +38 -0
  846. synapse/storage/schema/main/delta/72/06add_consent_ts_to_users.sql +35 -0
  847. synapse/storage/schema/main/delta/72/06thread_notifications.sql +49 -0
  848. synapse/storage/schema/main/delta/72/07force_update_current_state_events_membership.py +67 -0
  849. synapse/storage/schema/main/delta/72/07thread_receipts.sql.postgres +30 -0
  850. synapse/storage/schema/main/delta/72/07thread_receipts.sql.sqlite +70 -0
  851. synapse/storage/schema/main/delta/72/08begin_cache_invalidation_seq_at_2.sql.postgres +23 -0
  852. synapse/storage/schema/main/delta/72/08thread_receipts.sql +39 -0
  853. synapse/storage/schema/main/delta/72/09partial_indices.sql.sqlite +56 -0
  854. synapse/storage/schema/main/delta/73/01event_failed_pull_attempts.sql +48 -0
  855. synapse/storage/schema/main/delta/73/02add_pusher_enabled.sql +35 -0
  856. synapse/storage/schema/main/delta/73/02room_id_indexes_for_purging.sql +41 -0
  857. synapse/storage/schema/main/delta/73/03pusher_device_id.sql +39 -0
  858. synapse/storage/schema/main/delta/73/03users_approved_column.sql +39 -0
  859. synapse/storage/schema/main/delta/73/04partial_join_details.sql +42 -0
  860. synapse/storage/schema/main/delta/73/04pending_device_list_updates.sql +47 -0
  861. synapse/storage/schema/main/delta/73/05old_push_actions.sql.postgres +22 -0
  862. synapse/storage/schema/main/delta/73/05old_push_actions.sql.sqlite +24 -0
  863. synapse/storage/schema/main/delta/73/06thread_notifications_thread_id_idx.sql +42 -0
  864. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.postgres +23 -0
  865. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.sqlite +76 -0
  866. synapse/storage/schema/main/delta/73/09partial_joined_via_destination.sql +37 -0
  867. synapse/storage/schema/main/delta/73/09threads_table.sql +49 -0
  868. synapse/storage/schema/main/delta/73/10_update_sqlite_fts4_tokenizer.py +71 -0
  869. synapse/storage/schema/main/delta/73/10login_tokens.sql +54 -0
  870. synapse/storage/schema/main/delta/73/11event_search_room_id_n_distinct.sql.postgres +33 -0
  871. synapse/storage/schema/main/delta/73/12refactor_device_list_outbound_pokes.sql +72 -0
  872. synapse/storage/schema/main/delta/73/13add_device_lists_index.sql +39 -0
  873. synapse/storage/schema/main/delta/73/20_un_partial_stated_room_stream.sql +51 -0
  874. synapse/storage/schema/main/delta/73/21_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  875. synapse/storage/schema/main/delta/73/22_rebuild_user_dir_stats.sql +48 -0
  876. synapse/storage/schema/main/delta/73/22_un_partial_stated_event_stream.sql +53 -0
  877. synapse/storage/schema/main/delta/73/23_fix_thread_index.sql +52 -0
  878. synapse/storage/schema/main/delta/73/23_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  879. synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql +36 -0
  880. synapse/storage/schema/main/delta/73/25drop_presence.sql +36 -0
  881. synapse/storage/schema/main/delta/74/01_user_directory_stale_remote_users.sql +58 -0
  882. synapse/storage/schema/main/delta/74/02_set_device_id_for_pushers_bg_update.sql +38 -0
  883. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.postgres +29 -0
  884. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.sqlite +23 -0
  885. synapse/storage/schema/main/delta/74/03_room_membership_index.sql +38 -0
  886. synapse/storage/schema/main/delta/74/04_delete_e2e_backup_keys_for_deactivated_users.sql +36 -0
  887. synapse/storage/schema/main/delta/74/04_membership_tables_event_stream_ordering_triggers.py +87 -0
  888. synapse/storage/schema/main/delta/74/05_events_txn_id_device_id.sql +72 -0
  889. synapse/storage/schema/main/delta/74/90COMMENTS_destinations.sql.postgres +52 -0
  890. synapse/storage/schema/main/delta/76/01_add_profiles_full_user_id_column.sql +39 -0
  891. synapse/storage/schema/main/delta/76/02_add_user_filters_full_user_id_column.sql +39 -0
  892. synapse/storage/schema/main/delta/76/03_per_user_experimental_features.sql +46 -0
  893. synapse/storage/schema/main/delta/76/04_add_room_forgetter.sql +43 -0
  894. synapse/storage/schema/main/delta/77/01_add_profiles_not_valid_check.sql.postgres +16 -0
  895. synapse/storage/schema/main/delta/77/02_add_user_filters_not_valid_check.sql.postgres +16 -0
  896. synapse/storage/schema/main/delta/77/03bg_populate_full_user_id_profiles.sql +35 -0
  897. synapse/storage/schema/main/delta/77/04bg_populate_full_user_id_user_filters.sql +35 -0
  898. synapse/storage/schema/main/delta/77/05thread_notifications_backfill.sql +67 -0
  899. synapse/storage/schema/main/delta/77/06thread_notifications_not_null.sql.sqlite +102 -0
  900. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions.sql.postgres +27 -0
  901. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions_staging.sql.postgres +27 -0
  902. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_summary.sql.postgres +29 -0
  903. synapse/storage/schema/main/delta/77/14bg_indices_event_stream_ordering.sql +39 -0
  904. synapse/storage/schema/main/delta/78/01_validate_and_update_profiles.py +99 -0
  905. synapse/storage/schema/main/delta/78/02_validate_and_update_user_filters.py +100 -0
  906. synapse/storage/schema/main/delta/78/03_remove_unused_indexes_user_filters.py +72 -0
  907. synapse/storage/schema/main/delta/78/03event_extremities_constraints.py +65 -0
  908. synapse/storage/schema/main/delta/78/04_add_full_user_id_index_user_filters.py +32 -0
  909. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.postgres +102 -0
  910. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.sqlite +72 -0
  911. synapse/storage/schema/main/delta/79/04_mitigate_stream_ordering_update_race.py +70 -0
  912. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.postgres +69 -0
  913. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.sqlite +65 -0
  914. synapse/storage/schema/main/delta/80/01_users_alter_locked.sql +35 -0
  915. synapse/storage/schema/main/delta/80/02_read_write_locks_unlogged.sql.postgres +30 -0
  916. synapse/storage/schema/main/delta/80/02_scheduled_tasks.sql +47 -0
  917. synapse/storage/schema/main/delta/80/03_read_write_locks_triggers.sql.postgres +37 -0
  918. synapse/storage/schema/main/delta/80/04_read_write_locks_deadlock.sql.postgres +71 -0
  919. synapse/storage/schema/main/delta/82/02_scheduled_tasks_index.sql +35 -0
  920. synapse/storage/schema/main/delta/82/04_add_indices_for_purging_rooms.sql +39 -0
  921. synapse/storage/schema/main/delta/82/05gaps.sql +44 -0
  922. synapse/storage/schema/main/delta/83/01_drop_old_tables.sql +43 -0
  923. synapse/storage/schema/main/delta/83/03_instance_name_receipts.sql.sqlite +17 -0
  924. synapse/storage/schema/main/delta/83/05_cross_signing_key_update_grant.sql +34 -0
  925. synapse/storage/schema/main/delta/83/06_event_push_summary_room.sql +36 -0
  926. synapse/storage/schema/main/delta/84/01_auth_links_stats.sql.postgres +20 -0
  927. synapse/storage/schema/main/delta/84/02_auth_links_index.sql +16 -0
  928. synapse/storage/schema/main/delta/84/03_auth_links_analyze.sql.postgres +16 -0
  929. synapse/storage/schema/main/delta/84/04_access_token_index.sql +15 -0
  930. synapse/storage/schema/main/delta/85/01_add_suspended.sql +14 -0
  931. synapse/storage/schema/main/delta/85/02_add_instance_names.sql +27 -0
  932. synapse/storage/schema/main/delta/85/03_new_sequences.sql.postgres +54 -0
  933. synapse/storage/schema/main/delta/85/04_cleanup_device_federation_outbox.sql +15 -0
  934. synapse/storage/schema/main/delta/85/05_add_instance_names_converted_pos.sql +16 -0
  935. synapse/storage/schema/main/delta/85/06_add_room_reports.sql +20 -0
  936. synapse/storage/schema/main/delta/86/01_authenticate_media.sql +15 -0
  937. synapse/storage/schema/main/delta/86/02_receipts_event_id_index.sql +15 -0
  938. synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql +169 -0
  939. synapse/storage/schema/main/delta/87/02_per_connection_state.sql +81 -0
  940. synapse/storage/schema/main/delta/87/03_current_state_index.sql +19 -0
  941. synapse/storage/schema/main/delta/88/01_add_delayed_events.sql +43 -0
  942. synapse/storage/schema/main/delta/88/01_custom_profile_fields.sql +15 -0
  943. synapse/storage/schema/main/delta/88/02_fix_sliding_sync_membership_snapshots_forgotten_column.sql +21 -0
  944. synapse/storage/schema/main/delta/88/03_add_otk_ts_added_index.sql +18 -0
  945. synapse/storage/schema/main/delta/88/04_current_state_delta_index.sql +18 -0
  946. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.postgres +19 -0
  947. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.sqlite +19 -0
  948. synapse/storage/schema/main/delta/88/05_sliding_sync_room_config_index.sql +20 -0
  949. synapse/storage/schema/main/delta/88/06_events_received_ts_index.sql +17 -0
  950. synapse/storage/schema/main/delta/89/01_sliding_sync_membership_snapshot_index.sql +15 -0
  951. synapse/storage/schema/main/delta/90/01_add_column_participant_room_memberships_table.sql +16 -0
  952. synapse/storage/schema/main/delta/91/01_media_hash.sql +28 -0
  953. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.postgres +16 -0
  954. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.sqlite +16 -0
  955. synapse/storage/schema/main/delta/92/02_remove_populate_participant_bg_update.sql +17 -0
  956. synapse/storage/schema/main/delta/92/04_ss_membership_snapshot_idx.sql +16 -0
  957. synapse/storage/schema/main/delta/92/04_thread_subscriptions.sql +59 -0
  958. synapse/storage/schema/main/delta/92/04_thread_subscriptions_seq.sql.postgres +19 -0
  959. synapse/storage/schema/main/delta/92/05_fixup_max_depth_cap.sql +17 -0
  960. synapse/storage/schema/main/delta/92/05_thread_subscriptions_comments.sql.postgres +18 -0
  961. synapse/storage/schema/main/delta/92/06_device_federation_inbox_index.sql +16 -0
  962. synapse/storage/schema/main/delta/92/06_threads_last_sent_stream_ordering_comments.sql.postgres +24 -0
  963. synapse/storage/schema/main/delta/92/07_add_user_reports.sql +22 -0
  964. synapse/storage/schema/main/delta/92/07_event_txn_id_device_id_txn_id2.sql +15 -0
  965. synapse/storage/schema/main/delta/92/08_room_ban_redactions.sql +21 -0
  966. synapse/storage/schema/main/delta/92/08_thread_subscriptions_seq_fixup.sql.postgres +19 -0
  967. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql +20 -0
  968. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql.postgres +18 -0
  969. synapse/storage/schema/main/full_schemas/72/full.sql.postgres +1344 -0
  970. synapse/storage/schema/main/full_schemas/72/full.sql.sqlite +646 -0
  971. synapse/storage/schema/state/delta/23/drop_state_index.sql +35 -0
  972. synapse/storage/schema/state/delta/32/remove_state_indices.sql +38 -0
  973. synapse/storage/schema/state/delta/35/add_state_index.sql +36 -0
  974. synapse/storage/schema/state/delta/35/state.sql +41 -0
  975. synapse/storage/schema/state/delta/35/state_dedupe.sql +36 -0
  976. synapse/storage/schema/state/delta/47/state_group_seq.py +38 -0
  977. synapse/storage/schema/state/delta/56/state_group_room_idx.sql +36 -0
  978. synapse/storage/schema/state/delta/61/02state_groups_state_n_distinct.sql.postgres +34 -0
  979. synapse/storage/schema/state/delta/70/08_state_group_edges_unique.sql +36 -0
  980. synapse/storage/schema/state/delta/89/01_state_groups_deletion.sql +39 -0
  981. synapse/storage/schema/state/delta/90/02_delete_unreferenced_state_groups.sql +16 -0
  982. synapse/storage/schema/state/delta/90/03_remove_old_deletion_bg_update.sql +15 -0
  983. synapse/storage/schema/state/full_schemas/72/full.sql.postgres +30 -0
  984. synapse/storage/schema/state/full_schemas/72/full.sql.sqlite +20 -0
  985. synapse/storage/types.py +185 -0
  986. synapse/storage/util/__init__.py +20 -0
  987. synapse/storage/util/id_generators.py +909 -0
  988. synapse/storage/util/partial_state_events_tracker.py +194 -0
  989. synapse/storage/util/sequence.py +315 -0
  990. synapse/streams/__init__.py +43 -0
  991. synapse/streams/config.py +92 -0
  992. synapse/streams/events.py +203 -0
  993. synapse/synapse_rust/__init__.pyi +3 -0
  994. synapse/synapse_rust/acl.pyi +20 -0
  995. synapse/synapse_rust/events.pyi +136 -0
  996. synapse/synapse_rust/http_client.pyi +32 -0
  997. synapse/synapse_rust/push.pyi +86 -0
  998. synapse/synapse_rust/rendezvous.pyi +30 -0
  999. synapse/synapse_rust/segmenter.pyi +1 -0
  1000. synapse/synapse_rust.abi3.so +0 -0
  1001. synapse/types/__init__.py +1600 -0
  1002. synapse/types/handlers/__init__.py +93 -0
  1003. synapse/types/handlers/policy_server.py +16 -0
  1004. synapse/types/handlers/sliding_sync.py +909 -0
  1005. synapse/types/rest/__init__.py +25 -0
  1006. synapse/types/rest/client/__init__.py +415 -0
  1007. synapse/types/state.py +635 -0
  1008. synapse/types/storage/__init__.py +66 -0
  1009. synapse/util/__init__.py +170 -0
  1010. synapse/util/async_helpers.py +1067 -0
  1011. synapse/util/batching_queue.py +202 -0
  1012. synapse/util/caches/__init__.py +300 -0
  1013. synapse/util/caches/cached_call.py +143 -0
  1014. synapse/util/caches/deferred_cache.py +530 -0
  1015. synapse/util/caches/descriptors.py +694 -0
  1016. synapse/util/caches/dictionary_cache.py +350 -0
  1017. synapse/util/caches/expiringcache.py +251 -0
  1018. synapse/util/caches/lrucache.py +977 -0
  1019. synapse/util/caches/response_cache.py +323 -0
  1020. synapse/util/caches/stream_change_cache.py +370 -0
  1021. synapse/util/caches/treecache.py +189 -0
  1022. synapse/util/caches/ttlcache.py +197 -0
  1023. synapse/util/cancellation.py +63 -0
  1024. synapse/util/check_dependencies.py +335 -0
  1025. synapse/util/clock.py +500 -0
  1026. synapse/util/constants.py +22 -0
  1027. synapse/util/daemonize.py +165 -0
  1028. synapse/util/distributor.py +159 -0
  1029. synapse/util/events.py +134 -0
  1030. synapse/util/file_consumer.py +164 -0
  1031. synapse/util/frozenutils.py +57 -0
  1032. synapse/util/gai_resolver.py +180 -0
  1033. synapse/util/hash.py +38 -0
  1034. synapse/util/httpresourcetree.py +108 -0
  1035. synapse/util/iterutils.py +189 -0
  1036. synapse/util/json.py +56 -0
  1037. synapse/util/linked_list.py +156 -0
  1038. synapse/util/logcontext.py +46 -0
  1039. synapse/util/logformatter.py +28 -0
  1040. synapse/util/macaroons.py +325 -0
  1041. synapse/util/manhole.py +191 -0
  1042. synapse/util/metrics.py +340 -0
  1043. synapse/util/module_loader.py +116 -0
  1044. synapse/util/msisdn.py +51 -0
  1045. synapse/util/patch_inline_callbacks.py +250 -0
  1046. synapse/util/pydantic_models.py +56 -0
  1047. synapse/util/ratelimitutils.py +420 -0
  1048. synapse/util/retryutils.py +339 -0
  1049. synapse/util/rlimit.py +42 -0
  1050. synapse/util/rust.py +134 -0
  1051. synapse/util/sentinel.py +21 -0
  1052. synapse/util/stringutils.py +293 -0
  1053. synapse/util/task_scheduler.py +493 -0
  1054. synapse/util/templates.py +126 -0
  1055. synapse/util/threepids.py +123 -0
  1056. synapse/util/wheel_timer.py +112 -0
  1057. synapse/visibility.py +836 -0
@@ -0,0 +1,1875 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright 2014-2021 The Matrix.org Foundation C.I.C.
5
+ # Copyright (C) 2023 New Vector, Ltd
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # See the GNU Affero General Public License for more details:
13
+ # <https://www.gnu.org/licenses/agpl-3.0.html>.
14
+ #
15
+ # Originally licensed under the Apache License, Version 2.0:
16
+ # <http://www.apache.org/licenses/LICENSE-2.0>.
17
+ #
18
+ # [This file includes modifications made by New Vector Limited]
19
+ #
20
+ #
21
+ import abc
22
+ import codecs
23
+ import logging
24
+ import random
25
+ import sys
26
+ import urllib.parse
27
+ from http import HTTPStatus
28
+ from io import BytesIO, StringIO
29
+ from typing import (
30
+ TYPE_CHECKING,
31
+ Any,
32
+ BinaryIO,
33
+ Callable,
34
+ Generic,
35
+ Literal,
36
+ Optional,
37
+ TextIO,
38
+ TypeVar,
39
+ Union,
40
+ cast,
41
+ overload,
42
+ )
43
+
44
+ import attr
45
+ import treq
46
+ from canonicaljson import encode_canonical_json
47
+ from prometheus_client import Counter
48
+ from signedjson.sign import sign_json
49
+
50
+ from twisted.internet import defer
51
+ from twisted.internet.error import DNSLookupError
52
+ from twisted.internet.interfaces import IReactorTime
53
+ from twisted.internet.task import Cooperator
54
+ from twisted.web.client import ResponseFailed
55
+ from twisted.web.http_headers import Headers
56
+ from twisted.web.iweb import UNKNOWN_LENGTH, IAgent, IBodyProducer, IResponse
57
+
58
+ import synapse.metrics
59
+ import synapse.util.retryutils
60
+ from synapse.api.errors import (
61
+ Codes,
62
+ FederationDeniedError,
63
+ HttpResponseException,
64
+ RequestSendFailed,
65
+ SynapseError,
66
+ )
67
+ from synapse.api.ratelimiting import Ratelimiter
68
+ from synapse.crypto.context_factory import FederationPolicyForHTTPS
69
+ from synapse.http import QuieterFileBodyProducer
70
+ from synapse.http.client import (
71
+ BlocklistingAgentWrapper,
72
+ BodyExceededMaxSize,
73
+ ByteWriteable,
74
+ SimpleHttpClient,
75
+ _make_scheduler,
76
+ encode_query_args,
77
+ read_body_with_max_size,
78
+ read_multipart_response,
79
+ )
80
+ from synapse.http.connectproxyclient import BearerProxyCredentials
81
+ from synapse.http.federation.matrix_federation_agent import MatrixFederationAgent
82
+ from synapse.http.proxyagent import ProxyAgent
83
+ from synapse.http.types import QueryParams
84
+ from synapse.logging import opentracing
85
+ from synapse.logging.context import make_deferred_yieldable, run_in_background
86
+ from synapse.logging.opentracing import set_tag, start_active_span, tags
87
+ from synapse.metrics import SERVER_NAME_LABEL
88
+ from synapse.types import JsonDict
89
+ from synapse.util.async_helpers import AwakenableSleeper, Linearizer, timeout_deferred
90
+ from synapse.util.clock import Clock
91
+ from synapse.util.json import json_decoder
92
+ from synapse.util.metrics import Measure
93
+ from synapse.util.stringutils import parse_and_validate_server_name
94
+
95
+ if TYPE_CHECKING:
96
+ from synapse.server import HomeServer
97
+
98
+ logger = logging.getLogger(__name__)
99
+
100
+ outgoing_requests_counter = Counter(
101
+ "synapse_http_matrixfederationclient_requests",
102
+ "",
103
+ labelnames=["method", SERVER_NAME_LABEL],
104
+ )
105
+ incoming_responses_counter = Counter(
106
+ "synapse_http_matrixfederationclient_responses",
107
+ "",
108
+ labelnames=["method", "code", SERVER_NAME_LABEL],
109
+ )
110
+
111
+
112
+ MAXINT = sys.maxsize
113
+
114
+
115
+ _next_id = 1
116
+
117
+ T = TypeVar("T")
118
+
119
+
120
+ class ByteParser(ByteWriteable, Generic[T], abc.ABC):
121
+ """A `ByteWriteable` that has an additional `finish` function that returns
122
+ the parsed data.
123
+ """
124
+
125
+ CONTENT_TYPE: str = abc.abstractproperty() # type: ignore
126
+ """The expected content type of the response, e.g. `application/json`. If
127
+ the content type doesn't match we fail the request.
128
+ """
129
+
130
+ # a federation response can be rather large (eg a big state_ids is 50M or so), so we
131
+ # need a generous limit here.
132
+ MAX_RESPONSE_SIZE: int = 100 * 1024 * 1024
133
+ """The largest response this parser will accept."""
134
+
135
+ @abc.abstractmethod
136
+ def finish(self) -> T:
137
+ """Called when response has finished streaming and the parser should
138
+ return the final result (or error).
139
+ """
140
+
141
+
142
+ @attr.s(slots=True, frozen=True, auto_attribs=True)
143
+ class MatrixFederationRequest:
144
+ method: str
145
+ """HTTP method
146
+ """
147
+
148
+ path: str
149
+ """HTTP path
150
+ """
151
+
152
+ destination: str
153
+ """The remote server to send the HTTP request to.
154
+ """
155
+
156
+ json: Optional[JsonDict] = None
157
+ """JSON to send in the body.
158
+ """
159
+
160
+ json_callback: Optional[Callable[[], JsonDict]] = None
161
+ """A callback to generate the JSON.
162
+ """
163
+
164
+ query: Optional[QueryParams] = None
165
+ """Query arguments.
166
+ """
167
+
168
+ txn_id: str = attr.ib(init=False)
169
+ """Unique ID for this request (for logging), this is autogenerated.
170
+ """
171
+
172
+ uri: bytes = b""
173
+ """The URI of this request, usually generated from the above information.
174
+ """
175
+
176
+ _generate_uri: bool = True
177
+ """True to automatically generate the uri field based on the above information.
178
+
179
+ Set to False if manually configuring the URI.
180
+ """
181
+
182
+ def __attrs_post_init__(self) -> None:
183
+ global _next_id
184
+ txn_id = "%s-O-%s" % (self.method, _next_id)
185
+ _next_id = (_next_id + 1) % (MAXINT - 1)
186
+
187
+ object.__setattr__(self, "txn_id", txn_id)
188
+
189
+ if self._generate_uri:
190
+ destination_bytes = self.destination.encode("ascii")
191
+ path_bytes = self.path.encode("ascii")
192
+ query_bytes = encode_query_args(self.query)
193
+
194
+ # The object is frozen so we can pre-compute this.
195
+ uri = urllib.parse.urlunparse(
196
+ (
197
+ b"matrix-federation",
198
+ destination_bytes,
199
+ path_bytes,
200
+ None,
201
+ query_bytes,
202
+ b"",
203
+ )
204
+ )
205
+ object.__setattr__(self, "uri", uri)
206
+
207
+ def get_json(self) -> Optional[JsonDict]:
208
+ if self.json_callback:
209
+ return self.json_callback()
210
+ return self.json
211
+
212
+
213
+ class _BaseJsonParser(ByteParser[T]):
214
+ """A parser that buffers the response and tries to parse it as JSON."""
215
+
216
+ CONTENT_TYPE = "application/json"
217
+
218
+ def __init__(
219
+ self, validator: Optional[Callable[[Optional[object]], bool]] = None
220
+ ) -> None:
221
+ """
222
+ Args:
223
+ validator: A callable which takes the parsed JSON value and returns
224
+ true if the value is valid.
225
+ """
226
+ self._buffer = StringIO()
227
+ self._binary_wrapper = BinaryIOWrapper(self._buffer)
228
+ self._validator = validator
229
+
230
+ def write(self, data: bytes) -> int:
231
+ return self._binary_wrapper.write(data)
232
+
233
+ def finish(self) -> T:
234
+ result = json_decoder.decode(self._buffer.getvalue())
235
+ if self._validator is not None and not self._validator(result):
236
+ raise ValueError(
237
+ f"Received incorrect JSON value: {result.__class__.__name__}"
238
+ )
239
+ return result
240
+
241
+
242
+ class JsonParser(_BaseJsonParser[JsonDict]):
243
+ """A parser that buffers the response and tries to parse it as a JSON object."""
244
+
245
+ def __init__(self) -> None:
246
+ super().__init__(self._validate)
247
+
248
+ @staticmethod
249
+ def _validate(v: Any) -> bool:
250
+ return isinstance(v, dict)
251
+
252
+
253
+ class LegacyJsonSendParser(_BaseJsonParser[tuple[int, JsonDict]]):
254
+ """Ensure the legacy responses of /send_join & /send_leave are correct."""
255
+
256
+ def __init__(self) -> None:
257
+ super().__init__(self._validate)
258
+
259
+ @staticmethod
260
+ def _validate(v: Any) -> bool:
261
+ # Match [integer, JSON dict]
262
+ return (
263
+ isinstance(v, list)
264
+ and len(v) == 2
265
+ and type(v[0]) == int # noqa: E721
266
+ and isinstance(v[1], dict)
267
+ )
268
+
269
+
270
+ async def _handle_response(
271
+ clock: Clock,
272
+ reactor: IReactorTime,
273
+ timeout_sec: float,
274
+ request: MatrixFederationRequest,
275
+ response: IResponse,
276
+ start_ms: int,
277
+ parser: ByteParser[T],
278
+ ) -> T:
279
+ """
280
+ Reads the body of a response with a timeout and sends it to a parser
281
+
282
+ Args:
283
+ reactor: twisted reactor, for the timeout
284
+ timeout_sec: number of seconds to wait for response to complete
285
+ request: the request that triggered the response
286
+ response: response to the request
287
+ start_ms: Timestamp when request was made
288
+ parser: The parser for the response
289
+
290
+ Returns:
291
+ The parsed response
292
+ """
293
+
294
+ max_response_size = parser.MAX_RESPONSE_SIZE
295
+
296
+ finished = False
297
+ try:
298
+ check_content_type_is(response.headers, parser.CONTENT_TYPE)
299
+
300
+ d = read_body_with_max_size(response, parser, max_response_size)
301
+ d = timeout_deferred(
302
+ deferred=d,
303
+ timeout=timeout_sec,
304
+ clock=clock,
305
+ )
306
+
307
+ length = await make_deferred_yieldable(d)
308
+
309
+ finished = True
310
+ value = parser.finish()
311
+ except BodyExceededMaxSize as e:
312
+ # The response was too big.
313
+ logger.warning(
314
+ "{%s} [%s] JSON response exceeded max size %i - %s %s",
315
+ request.txn_id,
316
+ request.destination,
317
+ max_response_size,
318
+ request.method,
319
+ request.uri.decode("ascii"),
320
+ )
321
+ raise RequestSendFailed(e, can_retry=False) from e
322
+ except ValueError as e:
323
+ # The content was invalid.
324
+ logger.warning(
325
+ "{%s} [%s] Failed to parse response - %s %s",
326
+ request.txn_id,
327
+ request.destination,
328
+ request.method,
329
+ request.uri.decode("ascii"),
330
+ )
331
+ raise RequestSendFailed(e, can_retry=False) from e
332
+ except defer.TimeoutError as e:
333
+ logger.warning(
334
+ "{%s} [%s] Timed out reading response - %s %s",
335
+ request.txn_id,
336
+ request.destination,
337
+ request.method,
338
+ request.uri.decode("ascii"),
339
+ )
340
+ raise RequestSendFailed(e, can_retry=True) from e
341
+ except ResponseFailed as e:
342
+ logger.warning(
343
+ "{%s} [%s] Failed to read response - %s %s",
344
+ request.txn_id,
345
+ request.destination,
346
+ request.method,
347
+ request.uri.decode("ascii"),
348
+ )
349
+ raise RequestSendFailed(e, can_retry=True) from e
350
+ except Exception as e:
351
+ logger.warning(
352
+ "{%s} [%s] Error reading response %s %s: %s",
353
+ request.txn_id,
354
+ request.destination,
355
+ request.method,
356
+ request.uri.decode("ascii"),
357
+ e,
358
+ )
359
+ raise
360
+ finally:
361
+ if not finished:
362
+ # There was an exception and we didn't `finish()` the parse.
363
+ # Let the parser know that it can free up any resources.
364
+ try:
365
+ parser.finish()
366
+ except Exception:
367
+ # Ignore any additional exceptions.
368
+ pass
369
+
370
+ time_taken_secs = reactor.seconds() - start_ms / 1000
371
+
372
+ logger.info(
373
+ "{%s} [%s] Completed request: %d %s in %.2f secs, got %d bytes - %s %s",
374
+ request.txn_id,
375
+ request.destination,
376
+ response.code,
377
+ response.phrase.decode("ascii", errors="replace"),
378
+ time_taken_secs,
379
+ length,
380
+ request.method,
381
+ request.uri.decode("ascii"),
382
+ )
383
+ return value
384
+
385
+
386
+ class BinaryIOWrapper:
387
+ """A wrapper for a TextIO which converts from bytes on the fly."""
388
+
389
+ def __init__(self, file: TextIO, encoding: str = "utf-8", errors: str = "strict"):
390
+ self.decoder = codecs.getincrementaldecoder(encoding)(errors)
391
+ self.file = file
392
+
393
+ def write(self, b: Union[bytes, bytearray]) -> int:
394
+ self.file.write(self.decoder.decode(b))
395
+ return len(b)
396
+
397
+
398
+ class MatrixFederationHttpClient:
399
+ """HTTP client used to talk to other homeservers over the federation
400
+ protocol. Send client certificates and signs requests.
401
+
402
+ Attributes:
403
+ agent (twisted.web.client.Agent): The twisted Agent used to send the
404
+ requests.
405
+ """
406
+
407
+ def __init__(
408
+ self,
409
+ hs: "HomeServer",
410
+ tls_client_options_factory: Optional[FederationPolicyForHTTPS],
411
+ ):
412
+ self.hs = hs
413
+ self.signing_key = hs.signing_key
414
+ self.server_name = hs.hostname
415
+
416
+ self.reactor = hs.get_reactor()
417
+ self.clock = hs.get_clock()
418
+
419
+ user_agent = hs.version_string
420
+ if hs.config.server.user_agent_suffix:
421
+ user_agent = "%s %s" % (user_agent, hs.config.server.user_agent_suffix)
422
+
423
+ outbound_federation_restricted_to = (
424
+ hs.config.worker.outbound_federation_restricted_to
425
+ )
426
+ if hs.get_instance_name() in outbound_federation_restricted_to:
427
+ # Talk to federation directly
428
+ federation_agent: IAgent = MatrixFederationAgent(
429
+ server_name=self.server_name,
430
+ reactor=self.reactor,
431
+ clock=self.clock,
432
+ tls_client_options_factory=tls_client_options_factory,
433
+ user_agent=user_agent.encode("ascii"),
434
+ ip_allowlist=hs.config.server.federation_ip_range_allowlist,
435
+ ip_blocklist=hs.config.server.federation_ip_range_blocklist,
436
+ proxy_config=hs.config.server.proxy_config,
437
+ )
438
+ else:
439
+ proxy_authorization_secret = hs.config.worker.worker_replication_secret
440
+ assert proxy_authorization_secret is not None, (
441
+ "`worker_replication_secret` must be set when using `outbound_federation_restricted_to` (used to authenticate requests across workers)"
442
+ )
443
+ federation_proxy_credentials = BearerProxyCredentials(
444
+ proxy_authorization_secret.encode("ascii")
445
+ )
446
+
447
+ # We need to talk to federation via the proxy via one of the configured
448
+ # locations
449
+ federation_proxy_locations = outbound_federation_restricted_to.locations
450
+ federation_agent = ProxyAgent(
451
+ reactor=self.reactor,
452
+ proxy_reactor=self.reactor,
453
+ contextFactory=tls_client_options_factory,
454
+ federation_proxy_locations=federation_proxy_locations,
455
+ federation_proxy_credentials=federation_proxy_credentials,
456
+ )
457
+
458
+ # Use a BlocklistingAgentWrapper to prevent circumventing the IP
459
+ # blocking via IP literals in server names
460
+ self.agent: IAgent = BlocklistingAgentWrapper(
461
+ federation_agent,
462
+ ip_blocklist=hs.config.server.federation_ip_range_blocklist,
463
+ )
464
+
465
+ self._store = hs.get_datastores().main
466
+ self.version_string_bytes = hs.version_string.encode("ascii")
467
+ self.default_timeout_seconds = hs.config.federation.client_timeout_ms / 1000
468
+ self.max_long_retry_delay_seconds = (
469
+ hs.config.federation.max_long_retry_delay_ms / 1000
470
+ )
471
+ self.max_short_retry_delay_seconds = (
472
+ hs.config.federation.max_short_retry_delay_ms / 1000
473
+ )
474
+ self.max_long_retries = hs.config.federation.max_long_retries
475
+ self.max_short_retries = hs.config.federation.max_short_retries
476
+
477
+ self._cooperator = Cooperator(scheduler=_make_scheduler(self.clock))
478
+
479
+ self._sleeper = AwakenableSleeper(self.clock)
480
+
481
+ self._simple_http_client = SimpleHttpClient(
482
+ hs,
483
+ ip_blocklist=hs.config.server.federation_ip_range_blocklist,
484
+ ip_allowlist=hs.config.server.federation_ip_range_allowlist,
485
+ use_proxy=True,
486
+ )
487
+
488
+ self.remote_download_linearizer = Linearizer(
489
+ name="remote_download_linearizer", max_count=6, clock=self.clock
490
+ )
491
+ self._is_shutdown = False
492
+
493
+ def shutdown(self) -> None:
494
+ self._is_shutdown = True
495
+
496
+ def wake_destination(self, destination: str) -> None:
497
+ """Called when the remote server may have come back online."""
498
+
499
+ self._sleeper.wake(destination)
500
+
501
+ async def _send_request_with_optional_trailing_slash(
502
+ self,
503
+ request: MatrixFederationRequest,
504
+ try_trailing_slash_on_400: bool = False,
505
+ **send_request_args: Any,
506
+ ) -> IResponse:
507
+ """Wrapper for _send_request which can optionally retry the request
508
+ upon receiving a combination of a 400 HTTP response code and a
509
+ 'M_UNRECOGNIZED' errcode. This is a workaround for Synapse <= v0.99.3
510
+ due to https://github.com/matrix-org/synapse/issues/3622.
511
+
512
+ Args:
513
+ request: details of request to be sent
514
+ try_trailing_slash_on_400: Whether on receiving a 400
515
+ 'M_UNRECOGNIZED' from the server to retry the request with a
516
+ trailing slash appended to the request path.
517
+ send_request_args: A dictionary of arguments to pass to `_send_request()`.
518
+
519
+ Raises:
520
+ HttpResponseException: If we get an HTTP response code >= 300
521
+ (except 429).
522
+
523
+ Returns:
524
+ Parsed JSON response body.
525
+ """
526
+ try:
527
+ response = await self._send_request(request, **send_request_args)
528
+ except HttpResponseException as e:
529
+ # Received an HTTP error > 300. Check if it meets the requirements
530
+ # to retry with a trailing slash
531
+ if not try_trailing_slash_on_400:
532
+ raise
533
+
534
+ if e.code != 400 or e.to_synapse_error().errcode != "M_UNRECOGNIZED":
535
+ raise
536
+
537
+ # Retry with a trailing slash if we received a 400 with
538
+ # 'M_UNRECOGNIZED' which some endpoints can return when omitting a
539
+ # trailing slash on Synapse <= v0.99.3.
540
+ logger.info("Retrying request with trailing slash")
541
+
542
+ # Request is frozen so we create a new instance
543
+ request = attr.evolve(request, path=request.path + "/")
544
+
545
+ response = await self._send_request(request, **send_request_args)
546
+
547
+ return response
548
+
549
+ async def _send_request(
550
+ self,
551
+ request: MatrixFederationRequest,
552
+ retry_on_dns_fail: bool = True,
553
+ timeout: Optional[int] = None,
554
+ long_retries: bool = False,
555
+ ignore_backoff: bool = False,
556
+ backoff_on_404: bool = False,
557
+ backoff_on_all_error_codes: bool = False,
558
+ follow_redirects: bool = False,
559
+ ) -> IResponse:
560
+ """
561
+ Sends a request to the given server.
562
+
563
+ Args:
564
+ request: details of request to be sent
565
+
566
+ retry_on_dns_fail: true if the request should be retried on DNS failures
567
+
568
+ timeout: number of milliseconds to wait for the response headers
569
+ (including connecting to the server), *for each attempt*.
570
+ 60s by default.
571
+
572
+ long_retries: whether to use the long retry algorithm.
573
+
574
+ The regular retry algorithm makes 4 attempts, with intervals
575
+ [0.5s, 1s, 2s].
576
+
577
+ The long retry algorithm makes 11 attempts, with intervals
578
+ [4s, 16s, 60s, 60s, ...]
579
+
580
+ Both algorithms add -20%/+40% jitter to the retry intervals.
581
+
582
+ Note that the above intervals are *in addition* to the time spent
583
+ waiting for the request to complete (up to `timeout` ms).
584
+
585
+ NB: the long retry algorithm takes over 20 minutes to complete, with a
586
+ default timeout of 60s! It's best not to use the `long_retries` option
587
+ for something that is blocking a client so we don't make them wait for
588
+ aaaaages, whereas some things like sending transactions (server to
589
+ server) we can be a lot more lenient but its very fuzzy / hand-wavey.
590
+
591
+ In the future, we could be more intelligent about doing this sort of
592
+ thing by looking at things with the bigger picture in mind,
593
+ https://github.com/matrix-org/synapse/issues/8917
594
+
595
+ ignore_backoff: true to ignore the historical backoff data
596
+ and try the request anyway.
597
+
598
+ backoff_on_404: Back off if we get a 404
599
+ backoff_on_all_error_codes: Back off if we get any error response
600
+
601
+ follow_redirects: True to follow the Location header of 307/308 redirect
602
+ responses. This does not recurse.
603
+
604
+ Returns:
605
+ Resolves with the HTTP response object on success.
606
+
607
+ Raises:
608
+ HttpResponseException: If we get an HTTP response code >= 300
609
+ (except 429).
610
+ NotRetryingDestination: If we are not yet ready to retry this
611
+ server.
612
+ FederationDeniedError: If this destination is not on our
613
+ federation whitelist
614
+ RequestSendFailed: If there were problems connecting to the
615
+ remote, due to e.g. DNS failures, connection timeouts etc.
616
+ """
617
+ # Validate server name and log if it is an invalid destination, this is
618
+ # partially to help track down code paths where we haven't validated before here
619
+ try:
620
+ parse_and_validate_server_name(request.destination)
621
+ except ValueError:
622
+ logger.exception("Invalid destination: %s.", request.destination)
623
+ raise FederationDeniedError(request.destination)
624
+
625
+ if timeout is not None:
626
+ _sec_timeout = timeout / 1000
627
+ else:
628
+ _sec_timeout = self.default_timeout_seconds
629
+
630
+ if (
631
+ self.hs.config.federation.federation_domain_whitelist is not None
632
+ and request.destination
633
+ not in self.hs.config.federation.federation_domain_whitelist
634
+ ):
635
+ raise FederationDeniedError(request.destination)
636
+
637
+ limiter = await synapse.util.retryutils.get_retry_limiter(
638
+ destination=request.destination,
639
+ our_server_name=self.server_name,
640
+ hs=self.hs,
641
+ clock=self.clock,
642
+ store=self._store,
643
+ backoff_on_404=backoff_on_404,
644
+ ignore_backoff=ignore_backoff,
645
+ notifier=self.hs.get_notifier(),
646
+ replication_client=self.hs.get_replication_command_handler(),
647
+ backoff_on_all_error_codes=backoff_on_all_error_codes,
648
+ )
649
+
650
+ method_bytes = request.method.encode("ascii")
651
+ destination_bytes = request.destination.encode("ascii")
652
+ path_bytes = request.path.encode("ascii")
653
+ query_bytes = encode_query_args(request.query)
654
+
655
+ scope = start_active_span(
656
+ "outgoing-federation-request",
657
+ tags={
658
+ tags.SPAN_KIND: tags.SPAN_KIND_RPC_CLIENT,
659
+ tags.PEER_ADDRESS: request.destination,
660
+ tags.HTTP_METHOD: request.method,
661
+ tags.HTTP_URL: request.path,
662
+ },
663
+ finish_on_close=True,
664
+ )
665
+
666
+ # Inject the span into the headers
667
+ headers_dict: dict[bytes, list[bytes]] = {}
668
+ opentracing.inject_header_dict(headers_dict, request.destination)
669
+
670
+ headers_dict[b"User-Agent"] = [self.version_string_bytes]
671
+
672
+ with limiter, scope:
673
+ # XXX: Would be much nicer to retry only at the transaction-layer
674
+ # (once we have reliable transactions in place)
675
+ if long_retries:
676
+ retries_left = self.max_long_retries
677
+ else:
678
+ retries_left = self.max_short_retries
679
+
680
+ url_bytes = request.uri
681
+ url_str = url_bytes.decode("ascii")
682
+
683
+ url_to_sign_bytes = urllib.parse.urlunparse(
684
+ (b"", b"", path_bytes, None, query_bytes, b"")
685
+ )
686
+
687
+ while not self._is_shutdown:
688
+ try:
689
+ json = request.get_json()
690
+ if json:
691
+ headers_dict[b"Content-Type"] = [b"application/json"]
692
+ auth_headers = self.build_auth_headers(
693
+ destination_bytes, method_bytes, url_to_sign_bytes, json
694
+ )
695
+ data = encode_canonical_json(json)
696
+ producer: Optional[IBodyProducer] = QuieterFileBodyProducer(
697
+ BytesIO(data), cooperator=self._cooperator
698
+ )
699
+ else:
700
+ producer = None
701
+ auth_headers = self.build_auth_headers(
702
+ destination_bytes, method_bytes, url_to_sign_bytes
703
+ )
704
+
705
+ headers_dict[b"Authorization"] = auth_headers
706
+
707
+ logger.debug(
708
+ "{%s} [%s] Sending request: %s %s; timeout %fs",
709
+ request.txn_id,
710
+ request.destination,
711
+ request.method,
712
+ url_str,
713
+ _sec_timeout,
714
+ )
715
+
716
+ outgoing_requests_counter.labels(
717
+ method=request.method, **{SERVER_NAME_LABEL: self.server_name}
718
+ ).inc()
719
+
720
+ try:
721
+ with Measure(
722
+ self.clock,
723
+ name="outbound_request",
724
+ server_name=self.server_name,
725
+ ):
726
+ # we don't want all the fancy cookie and redirect handling
727
+ # that treq.request gives: just use the raw Agent.
728
+
729
+ # To preserve the logging context, the timeout is treated
730
+ # in a similar way to `defer.gatherResults`:
731
+ # * Each logging context-preserving fork is wrapped in
732
+ # `run_in_background`. In this case there is only one,
733
+ # since the timeout fork is not logging-context aware.
734
+ # * The `Deferred` that joins the forks back together is
735
+ # wrapped in `make_deferred_yieldable` to restore the
736
+ # logging context regardless of the path taken.
737
+ request_deferred = run_in_background(
738
+ self.agent.request,
739
+ method_bytes,
740
+ url_bytes,
741
+ headers=Headers(headers_dict),
742
+ bodyProducer=producer,
743
+ )
744
+ request_deferred = timeout_deferred(
745
+ deferred=request_deferred,
746
+ timeout=_sec_timeout,
747
+ clock=self.clock,
748
+ )
749
+
750
+ response = await make_deferred_yieldable(request_deferred)
751
+ except DNSLookupError as e:
752
+ raise RequestSendFailed(e, can_retry=retry_on_dns_fail) from e
753
+ except Exception as e:
754
+ raise RequestSendFailed(e, can_retry=True) from e
755
+
756
+ incoming_responses_counter.labels(
757
+ method=request.method,
758
+ code=response.code,
759
+ **{SERVER_NAME_LABEL: self.server_name},
760
+ ).inc()
761
+
762
+ set_tag(tags.HTTP_STATUS_CODE, response.code)
763
+ response_phrase = response.phrase.decode("ascii", errors="replace")
764
+
765
+ if 200 <= response.code < 300:
766
+ logger.debug(
767
+ "{%s} [%s] Got response headers: %d %s",
768
+ request.txn_id,
769
+ request.destination,
770
+ response.code,
771
+ response_phrase,
772
+ )
773
+ elif (
774
+ response.code in (307, 308)
775
+ and follow_redirects
776
+ and response.headers.hasHeader("Location")
777
+ ):
778
+ # The Location header *might* be relative so resolve it.
779
+ location = response.headers.getRawHeaders(b"Location")[0]
780
+ new_uri = urllib.parse.urljoin(request.uri, location)
781
+
782
+ return await self._send_request(
783
+ attr.evolve(request, uri=new_uri, generate_uri=False),
784
+ retry_on_dns_fail,
785
+ timeout,
786
+ long_retries,
787
+ ignore_backoff,
788
+ backoff_on_404,
789
+ backoff_on_all_error_codes,
790
+ # Do not continue following redirects.
791
+ follow_redirects=False,
792
+ )
793
+ else:
794
+ logger.info(
795
+ "{%s} [%s] Got response headers: %d %s",
796
+ request.txn_id,
797
+ request.destination,
798
+ response.code,
799
+ response_phrase,
800
+ )
801
+ # :'(
802
+ # Update transactions table?
803
+ d = treq.content(response)
804
+ d = timeout_deferred(
805
+ deferred=d,
806
+ timeout=_sec_timeout,
807
+ clock=self.clock,
808
+ )
809
+
810
+ try:
811
+ body = await make_deferred_yieldable(d)
812
+ except Exception as e:
813
+ # Eh, we're already going to raise an exception so lets
814
+ # ignore if this fails.
815
+ logger.warning(
816
+ "{%s} [%s] Failed to get error response: %s %s: %s",
817
+ request.txn_id,
818
+ request.destination,
819
+ request.method,
820
+ url_str,
821
+ _flatten_response_never_received(e),
822
+ )
823
+ body = b""
824
+
825
+ exc = HttpResponseException(
826
+ response.code, response_phrase, body
827
+ )
828
+
829
+ # Retry if the error is a 5xx or a 429 (Too Many
830
+ # Requests), otherwise just raise a standard
831
+ # `HttpResponseException`
832
+ if 500 <= response.code < 600 or response.code == 429:
833
+ raise RequestSendFailed(exc, can_retry=True) from exc
834
+ else:
835
+ raise exc
836
+
837
+ break
838
+ except RequestSendFailed as e:
839
+ logger.info(
840
+ "{%s} [%s] Request failed: %s %s: %s",
841
+ request.txn_id,
842
+ request.destination,
843
+ request.method,
844
+ url_str,
845
+ _flatten_response_never_received(e.inner_exception),
846
+ )
847
+
848
+ if not e.can_retry:
849
+ raise
850
+
851
+ if retries_left and not timeout:
852
+ if long_retries:
853
+ delay_seconds = 4 ** (
854
+ self.max_long_retries + 1 - retries_left
855
+ )
856
+ delay_seconds = min(
857
+ delay_seconds, self.max_long_retry_delay_seconds
858
+ )
859
+ delay_seconds *= random.uniform(0.8, 1.4)
860
+ else:
861
+ delay_seconds = 0.5 * 2 ** (
862
+ self.max_short_retries - retries_left
863
+ )
864
+ delay_seconds = min(
865
+ delay_seconds, self.max_short_retry_delay_seconds
866
+ )
867
+ delay_seconds *= random.uniform(0.8, 1.4)
868
+
869
+ logger.debug(
870
+ "{%s} [%s] Waiting %ss before re-sending...",
871
+ request.txn_id,
872
+ request.destination,
873
+ delay_seconds,
874
+ )
875
+
876
+ if self._is_shutdown:
877
+ # Immediately fail sending the request instead of starting a
878
+ # potentially long sleep after the server has requested
879
+ # shutdown.
880
+ # This is the code path followed when the
881
+ # `federation_transaction_transmission_loop` has been
882
+ # cancelled.
883
+ raise
884
+
885
+ # Sleep for the calculated delay, or wake up immediately
886
+ # if we get notified that the server is back up.
887
+ await self._sleeper.sleep(
888
+ request.destination, delay_seconds * 1000
889
+ )
890
+ retries_left -= 1
891
+ else:
892
+ raise
893
+
894
+ except Exception as e:
895
+ logger.warning(
896
+ "{%s} [%s] Request failed: %s %s: %s",
897
+ request.txn_id,
898
+ request.destination,
899
+ request.method,
900
+ url_str,
901
+ _flatten_response_never_received(e),
902
+ )
903
+ raise
904
+ return response
905
+
906
+ def build_auth_headers(
907
+ self,
908
+ destination: Optional[bytes],
909
+ method: bytes,
910
+ url_bytes: bytes,
911
+ content: Optional[JsonDict] = None,
912
+ destination_is: Optional[bytes] = None,
913
+ ) -> list[bytes]:
914
+ """
915
+ Builds the Authorization headers for a federation request
916
+ Args:
917
+ destination: The destination homeserver of the request.
918
+ May be None if the destination is an identity server, in which case
919
+ destination_is must be non-None.
920
+ method: The HTTP method of the request
921
+ url_bytes: The URI path of the request
922
+ content: The body of the request
923
+ destination_is: As 'destination', but if the destination is an
924
+ identity server
925
+
926
+ Returns:
927
+ A list of headers to be added as "Authorization:" headers
928
+ """
929
+ if not destination and not destination_is:
930
+ raise ValueError(
931
+ "At least one of the arguments destination and destination_is "
932
+ "must be a nonempty bytestring."
933
+ )
934
+
935
+ request: JsonDict = {
936
+ "method": method.decode("ascii"),
937
+ "uri": url_bytes.decode("ascii"),
938
+ "origin": self.server_name,
939
+ }
940
+
941
+ if destination is not None:
942
+ request["destination"] = destination.decode("ascii")
943
+
944
+ if destination_is is not None:
945
+ request["destination_is"] = destination_is.decode("ascii")
946
+
947
+ if content is not None:
948
+ request["content"] = content
949
+
950
+ request = sign_json(request, self.server_name, self.signing_key)
951
+
952
+ auth_headers = []
953
+
954
+ for key, sig in request["signatures"][self.server_name].items():
955
+ auth_headers.append(
956
+ (
957
+ 'X-Matrix origin="%s",key="%s",sig="%s",destination="%s"'
958
+ % (
959
+ self.server_name,
960
+ key,
961
+ sig,
962
+ request.get("destination") or request["destination_is"],
963
+ )
964
+ ).encode("ascii")
965
+ )
966
+ return auth_headers
967
+
968
+ @overload
969
+ async def put_json(
970
+ self,
971
+ destination: str,
972
+ path: str,
973
+ args: Optional[QueryParams] = None,
974
+ data: Optional[JsonDict] = None,
975
+ json_data_callback: Optional[Callable[[], JsonDict]] = None,
976
+ long_retries: bool = False,
977
+ timeout: Optional[int] = None,
978
+ ignore_backoff: bool = False,
979
+ backoff_on_404: bool = False,
980
+ try_trailing_slash_on_400: bool = False,
981
+ parser: Literal[None] = None,
982
+ backoff_on_all_error_codes: bool = False,
983
+ ) -> JsonDict: ...
984
+
985
+ @overload
986
+ async def put_json(
987
+ self,
988
+ destination: str,
989
+ path: str,
990
+ args: Optional[QueryParams] = None,
991
+ data: Optional[JsonDict] = None,
992
+ json_data_callback: Optional[Callable[[], JsonDict]] = None,
993
+ long_retries: bool = False,
994
+ timeout: Optional[int] = None,
995
+ ignore_backoff: bool = False,
996
+ backoff_on_404: bool = False,
997
+ try_trailing_slash_on_400: bool = False,
998
+ parser: Optional[ByteParser[T]] = None,
999
+ backoff_on_all_error_codes: bool = False,
1000
+ ) -> T: ...
1001
+
1002
+ async def put_json(
1003
+ self,
1004
+ destination: str,
1005
+ path: str,
1006
+ args: Optional[QueryParams] = None,
1007
+ data: Optional[JsonDict] = None,
1008
+ json_data_callback: Optional[Callable[[], JsonDict]] = None,
1009
+ long_retries: bool = False,
1010
+ timeout: Optional[int] = None,
1011
+ ignore_backoff: bool = False,
1012
+ backoff_on_404: bool = False,
1013
+ try_trailing_slash_on_400: bool = False,
1014
+ parser: Optional[ByteParser[T]] = None,
1015
+ backoff_on_all_error_codes: bool = False,
1016
+ ) -> Union[JsonDict, T]:
1017
+ """Sends the specified json data using PUT
1018
+
1019
+ Args:
1020
+ destination: The remote server to send the HTTP request to.
1021
+ path: The HTTP path.
1022
+ args: query params
1023
+ data: A dict containing the data that will be used as
1024
+ the request body. This will be encoded as JSON.
1025
+ json_data_callback: A callable returning the dict to
1026
+ use as the request body.
1027
+
1028
+ long_retries: whether to use the long retry algorithm. See
1029
+ docs on _send_request for details.
1030
+
1031
+ timeout: number of milliseconds to wait for the response.
1032
+ self._default_timeout (60s) by default.
1033
+
1034
+ Note that we may make several attempts to send the request; this
1035
+ timeout applies to the time spent waiting for response headers for
1036
+ *each* attempt (including connection time) as well as the time spent
1037
+ reading the response body after a 200 response.
1038
+
1039
+ ignore_backoff: true to ignore the historical backoff data
1040
+ and try the request anyway.
1041
+ backoff_on_404: True if we should count a 404 response as
1042
+ a failure of the server (and should therefore back off future
1043
+ requests).
1044
+ try_trailing_slash_on_400: True if on a 400 M_UNRECOGNIZED
1045
+ response we should try appending a trailing slash to the end
1046
+ of the request. Workaround for https://github.com/matrix-org/synapse/issues/3622
1047
+ in Synapse <= v0.99.3. This will be attempted before backing off if
1048
+ backing off has been enabled.
1049
+ parser: The parser to use to decode the response. Defaults to
1050
+ parsing as JSON.
1051
+ backoff_on_all_error_codes: Back off if we get any error response
1052
+
1053
+ Returns:
1054
+ Succeeds when we get a 2xx HTTP response. The
1055
+ result will be the decoded JSON body.
1056
+
1057
+ Raises:
1058
+ HttpResponseException: If we get an HTTP response code >= 300
1059
+ (except 429).
1060
+ NotRetryingDestination: If we are not yet ready to retry this
1061
+ server.
1062
+ FederationDeniedError: If this destination is not on our
1063
+ federation whitelist
1064
+ RequestSendFailed: If there were problems connecting to the
1065
+ remote, due to e.g. DNS failures, connection timeouts etc.
1066
+ """
1067
+ request = MatrixFederationRequest(
1068
+ method="PUT",
1069
+ destination=destination,
1070
+ path=path,
1071
+ query=args,
1072
+ json_callback=json_data_callback,
1073
+ json=data,
1074
+ )
1075
+
1076
+ start_ms = self.clock.time_msec()
1077
+
1078
+ response = await self._send_request_with_optional_trailing_slash(
1079
+ request,
1080
+ try_trailing_slash_on_400,
1081
+ backoff_on_404=backoff_on_404,
1082
+ ignore_backoff=ignore_backoff,
1083
+ long_retries=long_retries,
1084
+ timeout=timeout,
1085
+ backoff_on_all_error_codes=backoff_on_all_error_codes,
1086
+ )
1087
+
1088
+ if timeout is not None:
1089
+ _sec_timeout = timeout / 1000
1090
+ else:
1091
+ _sec_timeout = self.default_timeout_seconds
1092
+
1093
+ if parser is None:
1094
+ parser = cast(ByteParser[T], JsonParser())
1095
+
1096
+ body = await _handle_response(
1097
+ self.clock,
1098
+ self.reactor,
1099
+ _sec_timeout,
1100
+ request,
1101
+ response,
1102
+ start_ms,
1103
+ parser=parser,
1104
+ )
1105
+
1106
+ return body
1107
+
1108
+ async def post_json(
1109
+ self,
1110
+ destination: str,
1111
+ path: str,
1112
+ data: Optional[JsonDict] = None,
1113
+ long_retries: bool = False,
1114
+ timeout: Optional[int] = None,
1115
+ ignore_backoff: bool = False,
1116
+ args: Optional[QueryParams] = None,
1117
+ ) -> JsonDict:
1118
+ """Sends the specified json data using POST
1119
+
1120
+ Args:
1121
+ destination: The remote server to send the HTTP request to.
1122
+
1123
+ path: The HTTP path.
1124
+
1125
+ data: A dict containing the data that will be used as
1126
+ the request body. This will be encoded as JSON.
1127
+
1128
+ long_retries: whether to use the long retry algorithm. See
1129
+ docs on _send_request for details.
1130
+
1131
+ timeout: number of milliseconds to wait for the response.
1132
+ self._default_timeout (60s) by default.
1133
+
1134
+ Note that we may make several attempts to send the request; this
1135
+ timeout applies to the time spent waiting for response headers for
1136
+ *each* attempt (including connection time) as well as the time spent
1137
+ reading the response body after a 200 response.
1138
+
1139
+ ignore_backoff: true to ignore the historical backoff data and
1140
+ try the request anyway.
1141
+
1142
+ args: query params
1143
+ Returns:
1144
+ Succeeds when we get a 2xx HTTP response. The result will be the decoded JSON body.
1145
+
1146
+ Raises:
1147
+ HttpResponseException: If we get an HTTP response code >= 300
1148
+ (except 429).
1149
+ NotRetryingDestination: If we are not yet ready to retry this
1150
+ server.
1151
+ FederationDeniedError: If this destination is not on our
1152
+ federation whitelist
1153
+ RequestSendFailed: If there were problems connecting to the
1154
+ remote, due to e.g. DNS failures, connection timeouts etc.
1155
+ """
1156
+
1157
+ request = MatrixFederationRequest(
1158
+ method="POST", destination=destination, path=path, query=args, json=data
1159
+ )
1160
+
1161
+ start_ms = self.clock.time_msec()
1162
+
1163
+ response = await self._send_request(
1164
+ request,
1165
+ long_retries=long_retries,
1166
+ timeout=timeout,
1167
+ ignore_backoff=ignore_backoff,
1168
+ )
1169
+
1170
+ if timeout is not None:
1171
+ _sec_timeout = timeout / 1000
1172
+ else:
1173
+ _sec_timeout = self.default_timeout_seconds
1174
+
1175
+ body = await _handle_response(
1176
+ self.clock,
1177
+ self.reactor,
1178
+ _sec_timeout,
1179
+ request,
1180
+ response,
1181
+ start_ms,
1182
+ parser=JsonParser(),
1183
+ )
1184
+ return body
1185
+
1186
+ @overload
1187
+ async def get_json(
1188
+ self,
1189
+ destination: str,
1190
+ path: str,
1191
+ args: Optional[QueryParams] = None,
1192
+ retry_on_dns_fail: bool = True,
1193
+ timeout: Optional[int] = None,
1194
+ ignore_backoff: bool = False,
1195
+ try_trailing_slash_on_400: bool = False,
1196
+ parser: Literal[None] = None,
1197
+ ) -> JsonDict: ...
1198
+
1199
+ @overload
1200
+ async def get_json(
1201
+ self,
1202
+ destination: str,
1203
+ path: str,
1204
+ args: Optional[QueryParams] = ...,
1205
+ retry_on_dns_fail: bool = ...,
1206
+ timeout: Optional[int] = ...,
1207
+ ignore_backoff: bool = ...,
1208
+ try_trailing_slash_on_400: bool = ...,
1209
+ parser: ByteParser[T] = ...,
1210
+ ) -> T: ...
1211
+
1212
+ async def get_json(
1213
+ self,
1214
+ destination: str,
1215
+ path: str,
1216
+ args: Optional[QueryParams] = None,
1217
+ retry_on_dns_fail: bool = True,
1218
+ timeout: Optional[int] = None,
1219
+ ignore_backoff: bool = False,
1220
+ try_trailing_slash_on_400: bool = False,
1221
+ parser: Optional[ByteParser[T]] = None,
1222
+ ) -> Union[JsonDict, T]:
1223
+ """GETs some json from the given host homeserver and path
1224
+
1225
+ Args:
1226
+ destination: The remote server to send the HTTP request to.
1227
+
1228
+ path: The HTTP path.
1229
+
1230
+ args: A dictionary used to create query strings, defaults to
1231
+ None.
1232
+
1233
+ retry_on_dns_fail: true if the request should be retried on DNS failures
1234
+
1235
+ timeout: number of milliseconds to wait for the response.
1236
+ self._default_timeout (60s) by default.
1237
+
1238
+ Note that we may make several attempts to send the request; this
1239
+ timeout applies to the time spent waiting for response headers for
1240
+ *each* attempt (including connection time) as well as the time spent
1241
+ reading the response body after a 200 response.
1242
+
1243
+ ignore_backoff: true to ignore the historical backoff data
1244
+ and try the request anyway.
1245
+
1246
+ try_trailing_slash_on_400: True if on a 400 M_UNRECOGNIZED
1247
+ response we should try appending a trailing slash to the end of
1248
+ the request. Workaround for https://github.com/matrix-org/synapse/issues/3622
1249
+ in Synapse <= v0.99.3.
1250
+
1251
+ parser: The parser to use to decode the response. Defaults to
1252
+ parsing as JSON.
1253
+
1254
+ Returns:
1255
+ Succeeds when we get a 2xx HTTP response. The
1256
+ result will be the decoded JSON body.
1257
+
1258
+ Raises:
1259
+ HttpResponseException: If we get an HTTP response code >= 300
1260
+ (except 429).
1261
+ NotRetryingDestination: If we are not yet ready to retry this
1262
+ server.
1263
+ FederationDeniedError: If this destination is not on our
1264
+ federation whitelist
1265
+ RequestSendFailed: If there were problems connecting to the
1266
+ remote, due to e.g. DNS failures, connection timeouts etc.
1267
+ """
1268
+ json_dict, _ = await self.get_json_with_headers(
1269
+ destination=destination,
1270
+ path=path,
1271
+ args=args,
1272
+ retry_on_dns_fail=retry_on_dns_fail,
1273
+ timeout=timeout,
1274
+ ignore_backoff=ignore_backoff,
1275
+ try_trailing_slash_on_400=try_trailing_slash_on_400,
1276
+ parser=parser,
1277
+ )
1278
+ return json_dict
1279
+
1280
+ @overload
1281
+ async def get_json_with_headers(
1282
+ self,
1283
+ destination: str,
1284
+ path: str,
1285
+ args: Optional[QueryParams] = None,
1286
+ retry_on_dns_fail: bool = True,
1287
+ timeout: Optional[int] = None,
1288
+ ignore_backoff: bool = False,
1289
+ try_trailing_slash_on_400: bool = False,
1290
+ parser: Literal[None] = None,
1291
+ ) -> tuple[JsonDict, dict[bytes, list[bytes]]]: ...
1292
+
1293
+ @overload
1294
+ async def get_json_with_headers(
1295
+ self,
1296
+ destination: str,
1297
+ path: str,
1298
+ args: Optional[QueryParams] = ...,
1299
+ retry_on_dns_fail: bool = ...,
1300
+ timeout: Optional[int] = ...,
1301
+ ignore_backoff: bool = ...,
1302
+ try_trailing_slash_on_400: bool = ...,
1303
+ parser: ByteParser[T] = ...,
1304
+ ) -> tuple[T, dict[bytes, list[bytes]]]: ...
1305
+
1306
+ async def get_json_with_headers(
1307
+ self,
1308
+ destination: str,
1309
+ path: str,
1310
+ args: Optional[QueryParams] = None,
1311
+ retry_on_dns_fail: bool = True,
1312
+ timeout: Optional[int] = None,
1313
+ ignore_backoff: bool = False,
1314
+ try_trailing_slash_on_400: bool = False,
1315
+ parser: Optional[ByteParser[T]] = None,
1316
+ ) -> tuple[Union[JsonDict, T], dict[bytes, list[bytes]]]:
1317
+ """GETs some json from the given host homeserver and path
1318
+
1319
+ Args:
1320
+ destination: The remote server to send the HTTP request to.
1321
+
1322
+ path: The HTTP path.
1323
+
1324
+ args: A dictionary used to create query strings, defaults to
1325
+ None.
1326
+
1327
+ retry_on_dns_fail: true if the request should be retried on DNS failures
1328
+
1329
+ timeout: number of milliseconds to wait for the response.
1330
+ self._default_timeout (60s) by default.
1331
+
1332
+ Note that we may make several attempts to send the request; this
1333
+ timeout applies to the time spent waiting for response headers for
1334
+ *each* attempt (including connection time) as well as the time spent
1335
+ reading the response body after a 200 response.
1336
+
1337
+ ignore_backoff: true to ignore the historical backoff data
1338
+ and try the request anyway.
1339
+
1340
+ try_trailing_slash_on_400: True if on a 400 M_UNRECOGNIZED
1341
+ response we should try appending a trailing slash to the end of
1342
+ the request. Workaround for https://github.com/matrix-org/synapse/issues/3622
1343
+ in Synapse <= v0.99.3.
1344
+
1345
+ parser: The parser to use to decode the response. Defaults to
1346
+ parsing as JSON.
1347
+
1348
+ Returns:
1349
+ Succeeds when we get a 2xx HTTP response. The result will be a tuple of the
1350
+ decoded JSON body and a dict of the response headers.
1351
+
1352
+ Raises:
1353
+ HttpResponseException: If we get an HTTP response code >= 300
1354
+ (except 429).
1355
+ NotRetryingDestination: If we are not yet ready to retry this
1356
+ server.
1357
+ FederationDeniedError: If this destination is not on our
1358
+ federation whitelist
1359
+ RequestSendFailed: If there were problems connecting to the
1360
+ remote, due to e.g. DNS failures, connection timeouts etc.
1361
+ """
1362
+ request = MatrixFederationRequest(
1363
+ method="GET", destination=destination, path=path, query=args
1364
+ )
1365
+
1366
+ start_ms = self.clock.time_msec()
1367
+
1368
+ response = await self._send_request_with_optional_trailing_slash(
1369
+ request,
1370
+ try_trailing_slash_on_400,
1371
+ backoff_on_404=False,
1372
+ ignore_backoff=ignore_backoff,
1373
+ retry_on_dns_fail=retry_on_dns_fail,
1374
+ timeout=timeout,
1375
+ )
1376
+
1377
+ headers = dict(response.headers.getAllRawHeaders())
1378
+
1379
+ if timeout is not None:
1380
+ _sec_timeout = timeout / 1000
1381
+ else:
1382
+ _sec_timeout = self.default_timeout_seconds
1383
+
1384
+ if parser is None:
1385
+ parser = cast(ByteParser[T], JsonParser())
1386
+
1387
+ body = await _handle_response(
1388
+ self.clock,
1389
+ self.reactor,
1390
+ _sec_timeout,
1391
+ request,
1392
+ response,
1393
+ start_ms,
1394
+ parser=parser,
1395
+ )
1396
+
1397
+ return body, headers
1398
+
1399
+ async def delete_json(
1400
+ self,
1401
+ destination: str,
1402
+ path: str,
1403
+ long_retries: bool = False,
1404
+ timeout: Optional[int] = None,
1405
+ ignore_backoff: bool = False,
1406
+ args: Optional[QueryParams] = None,
1407
+ ) -> JsonDict:
1408
+ """Send a DELETE request to the remote expecting some json response
1409
+
1410
+ Args:
1411
+ destination: The remote server to send the HTTP request to.
1412
+ path: The HTTP path.
1413
+
1414
+ long_retries: whether to use the long retry algorithm. See
1415
+ docs on _send_request for details.
1416
+
1417
+ timeout: number of milliseconds to wait for the response.
1418
+ self._default_timeout (60s) by default.
1419
+
1420
+ Note that we may make several attempts to send the request; this
1421
+ timeout applies to the time spent waiting for response headers for
1422
+ *each* attempt (including connection time) as well as the time spent
1423
+ reading the response body after a 200 response.
1424
+
1425
+ ignore_backoff: true to ignore the historical backoff data and
1426
+ try the request anyway.
1427
+
1428
+ args: query params
1429
+ Returns:
1430
+ Succeeds when we get a 2xx HTTP response. The
1431
+ result will be the decoded JSON body.
1432
+
1433
+ Raises:
1434
+ HttpResponseException: If we get an HTTP response code >= 300
1435
+ (except 429).
1436
+ NotRetryingDestination: If we are not yet ready to retry this
1437
+ server.
1438
+ FederationDeniedError: If this destination is not on our
1439
+ federation whitelist
1440
+ RequestSendFailed: If there were problems connecting to the
1441
+ remote, due to e.g. DNS failures, connection timeouts etc.
1442
+ """
1443
+ request = MatrixFederationRequest(
1444
+ method="DELETE", destination=destination, path=path, query=args
1445
+ )
1446
+
1447
+ start_ms = self.clock.time_msec()
1448
+
1449
+ response = await self._send_request(
1450
+ request,
1451
+ long_retries=long_retries,
1452
+ timeout=timeout,
1453
+ ignore_backoff=ignore_backoff,
1454
+ )
1455
+
1456
+ if timeout is not None:
1457
+ _sec_timeout = timeout / 1000
1458
+ else:
1459
+ _sec_timeout = self.default_timeout_seconds
1460
+
1461
+ body = await _handle_response(
1462
+ self.clock,
1463
+ self.reactor,
1464
+ _sec_timeout,
1465
+ request,
1466
+ response,
1467
+ start_ms,
1468
+ parser=JsonParser(),
1469
+ )
1470
+ return body
1471
+
1472
+ async def get_file(
1473
+ self,
1474
+ destination: str,
1475
+ path: str,
1476
+ output_stream: BinaryIO,
1477
+ download_ratelimiter: Ratelimiter,
1478
+ ip_address: str,
1479
+ max_size: int,
1480
+ args: Optional[QueryParams] = None,
1481
+ retry_on_dns_fail: bool = True,
1482
+ ignore_backoff: bool = False,
1483
+ follow_redirects: bool = False,
1484
+ ) -> tuple[int, dict[bytes, list[bytes]]]:
1485
+ """GETs a file from a given homeserver
1486
+ Args:
1487
+ destination: The remote server to send the HTTP request to.
1488
+ path: The HTTP path to GET.
1489
+ output_stream: File to write the response body to.
1490
+ download_ratelimiter: a ratelimiter to limit remote media downloads, keyed to
1491
+ requester IP
1492
+ ip_address: IP address of the requester
1493
+ max_size: maximum allowable size in bytes of the file
1494
+ args: Optional dictionary used to create the query string.
1495
+ ignore_backoff: true to ignore the historical backoff data
1496
+ and try the request anyway.
1497
+ follow_redirects: True to follow the Location header of 307/308 redirect
1498
+ responses. This does not recurse.
1499
+
1500
+ Returns:
1501
+ Resolves with an (int,dict) tuple of
1502
+ the file length and a dict of the response headers.
1503
+
1504
+ Raises:
1505
+ HttpResponseException: If we get an HTTP response code >= 300
1506
+ (except 429).
1507
+ NotRetryingDestination: If we are not yet ready to retry this
1508
+ server.
1509
+ FederationDeniedError: If this destination is not on our
1510
+ federation whitelist
1511
+ RequestSendFailed: If there were problems connecting to the
1512
+ remote, due to e.g. DNS failures, connection timeouts etc.
1513
+ SynapseError: If the requested file exceeds ratelimits
1514
+ """
1515
+ request = MatrixFederationRequest(
1516
+ method="GET", destination=destination, path=path, query=args
1517
+ )
1518
+
1519
+ # check for a minimum balance of 1MiB in ratelimiter before initiating request
1520
+ send_req, _ = await download_ratelimiter.can_do_action(
1521
+ requester=None, key=ip_address, n_actions=1048576, update=False
1522
+ )
1523
+
1524
+ if not send_req:
1525
+ msg = "Requested file size exceeds ratelimits"
1526
+ logger.warning(
1527
+ "{%s} [%s] %s",
1528
+ request.txn_id,
1529
+ request.destination,
1530
+ msg,
1531
+ )
1532
+ raise SynapseError(HTTPStatus.TOO_MANY_REQUESTS, msg, Codes.LIMIT_EXCEEDED)
1533
+
1534
+ response = await self._send_request(
1535
+ request,
1536
+ retry_on_dns_fail=retry_on_dns_fail,
1537
+ ignore_backoff=ignore_backoff,
1538
+ follow_redirects=follow_redirects,
1539
+ )
1540
+
1541
+ headers = dict(response.headers.getAllRawHeaders())
1542
+ expected_size = response.length
1543
+
1544
+ if expected_size == UNKNOWN_LENGTH:
1545
+ expected_size = max_size
1546
+ else:
1547
+ if int(expected_size) > max_size:
1548
+ msg = "Requested file is too large > %r bytes" % (max_size,)
1549
+ logger.warning(
1550
+ "{%s} [%s] %s",
1551
+ request.txn_id,
1552
+ request.destination,
1553
+ msg,
1554
+ )
1555
+ raise SynapseError(HTTPStatus.BAD_GATEWAY, msg, Codes.TOO_LARGE)
1556
+
1557
+ read_body, _ = await download_ratelimiter.can_do_action(
1558
+ requester=None,
1559
+ key=ip_address,
1560
+ n_actions=expected_size,
1561
+ )
1562
+ if not read_body:
1563
+ msg = "Requested file size exceeds ratelimits"
1564
+ logger.warning(
1565
+ "{%s} [%s] %s",
1566
+ request.txn_id,
1567
+ request.destination,
1568
+ msg,
1569
+ )
1570
+ raise SynapseError(
1571
+ HTTPStatus.TOO_MANY_REQUESTS, msg, Codes.LIMIT_EXCEEDED
1572
+ )
1573
+
1574
+ try:
1575
+ async with self.remote_download_linearizer.queue(ip_address):
1576
+ # add a byte of headroom to max size as function errs at >=
1577
+ d = read_body_with_max_size(response, output_stream, expected_size + 1)
1578
+ d.addTimeout(self.default_timeout_seconds, self.reactor)
1579
+ length = await make_deferred_yieldable(d)
1580
+ except BodyExceededMaxSize:
1581
+ msg = "Requested file is too large > %r bytes" % (expected_size,)
1582
+ logger.warning(
1583
+ "{%s} [%s] %s",
1584
+ request.txn_id,
1585
+ request.destination,
1586
+ msg,
1587
+ )
1588
+ raise SynapseError(HTTPStatus.BAD_GATEWAY, msg, Codes.TOO_LARGE)
1589
+ except defer.TimeoutError as e:
1590
+ logger.warning(
1591
+ "{%s} [%s] Timed out reading response - %s %s",
1592
+ request.txn_id,
1593
+ request.destination,
1594
+ request.method,
1595
+ request.uri.decode("ascii"),
1596
+ )
1597
+ raise RequestSendFailed(e, can_retry=True) from e
1598
+ except ResponseFailed as e:
1599
+ logger.warning(
1600
+ "{%s} [%s] Failed to read response - %s %s",
1601
+ request.txn_id,
1602
+ request.destination,
1603
+ request.method,
1604
+ request.uri.decode("ascii"),
1605
+ )
1606
+ raise RequestSendFailed(e, can_retry=True) from e
1607
+ except Exception as e:
1608
+ logger.warning(
1609
+ "{%s} [%s] Error reading response: %s",
1610
+ request.txn_id,
1611
+ request.destination,
1612
+ e,
1613
+ )
1614
+ raise
1615
+ logger.info(
1616
+ "{%s} [%s] Completed: %d %s [%d bytes] %s %s",
1617
+ request.txn_id,
1618
+ request.destination,
1619
+ response.code,
1620
+ response.phrase.decode("ascii", errors="replace"),
1621
+ length,
1622
+ request.method,
1623
+ request.uri.decode("ascii"),
1624
+ )
1625
+
1626
+ # if we didn't know the length upfront, decrement the actual size from ratelimiter
1627
+ if response.length == UNKNOWN_LENGTH:
1628
+ download_ratelimiter.record_action(
1629
+ requester=None, key=ip_address, n_actions=length
1630
+ )
1631
+
1632
+ return length, headers
1633
+
1634
+ async def federation_get_file(
1635
+ self,
1636
+ destination: str,
1637
+ path: str,
1638
+ output_stream: BinaryIO,
1639
+ download_ratelimiter: Ratelimiter,
1640
+ ip_address: str,
1641
+ max_size: int,
1642
+ args: Optional[QueryParams] = None,
1643
+ retry_on_dns_fail: bool = True,
1644
+ ignore_backoff: bool = False,
1645
+ ) -> tuple[int, dict[bytes, list[bytes]], bytes]:
1646
+ """GETs a file from a given homeserver over the federation /download endpoint
1647
+ Args:
1648
+ destination: The remote server to send the HTTP request to.
1649
+ path: The HTTP path to GET.
1650
+ output_stream: File to write the response body to.
1651
+ download_ratelimiter: a ratelimiter to limit remote media downloads, keyed to
1652
+ requester IP
1653
+ ip_address: IP address of the requester
1654
+ max_size: maximum allowable size in bytes of the file
1655
+ args: Optional dictionary used to create the query string.
1656
+ ignore_backoff: true to ignore the historical backoff data
1657
+ and try the request anyway.
1658
+
1659
+ Returns:
1660
+ Resolves to an (int, dict, bytes) tuple of
1661
+ the file length, a dict of the response headers, and the file json
1662
+
1663
+ Raises:
1664
+ HttpResponseException: If we get an HTTP response code >= 300
1665
+ (except 429).
1666
+ NotRetryingDestination: If we are not yet ready to retry this
1667
+ server.
1668
+ FederationDeniedError: If this destination is not on our
1669
+ federation whitelist
1670
+ RequestSendFailed: If there were problems connecting to the
1671
+ remote, due to e.g. DNS failures, connection timeouts etc.
1672
+ SynapseError: If the requested file exceeds ratelimits or the response from the
1673
+ remote server is not a multipart response
1674
+ AssertionError: if the resolved multipart response's length is None
1675
+ """
1676
+ request = MatrixFederationRequest(
1677
+ method="GET", destination=destination, path=path, query=args
1678
+ )
1679
+
1680
+ # check for a minimum balance of 1MiB in ratelimiter before initiating request
1681
+ send_req, _ = await download_ratelimiter.can_do_action(
1682
+ requester=None, key=ip_address, n_actions=1048576, update=False
1683
+ )
1684
+
1685
+ if not send_req:
1686
+ msg = "Requested file size exceeds ratelimits"
1687
+ logger.warning(
1688
+ "{%s} [%s] %s",
1689
+ request.txn_id,
1690
+ request.destination,
1691
+ msg,
1692
+ )
1693
+ raise SynapseError(HTTPStatus.TOO_MANY_REQUESTS, msg, Codes.LIMIT_EXCEEDED)
1694
+
1695
+ response = await self._send_request(
1696
+ request,
1697
+ retry_on_dns_fail=retry_on_dns_fail,
1698
+ ignore_backoff=ignore_backoff,
1699
+ )
1700
+
1701
+ headers = dict(response.headers.getAllRawHeaders())
1702
+ expected_size = response.length
1703
+
1704
+ if expected_size == UNKNOWN_LENGTH:
1705
+ expected_size = max_size
1706
+ else:
1707
+ if int(expected_size) > max_size:
1708
+ msg = "Requested file is too large > %r bytes" % (max_size,)
1709
+ logger.warning(
1710
+ "{%s} [%s] %s",
1711
+ request.txn_id,
1712
+ request.destination,
1713
+ msg,
1714
+ )
1715
+ raise SynapseError(HTTPStatus.BAD_GATEWAY, msg, Codes.TOO_LARGE)
1716
+
1717
+ read_body, _ = await download_ratelimiter.can_do_action(
1718
+ requester=None,
1719
+ key=ip_address,
1720
+ n_actions=expected_size,
1721
+ )
1722
+ if not read_body:
1723
+ msg = "Requested file size exceeds ratelimits"
1724
+ logger.warning(
1725
+ "{%s} [%s] %s",
1726
+ request.txn_id,
1727
+ request.destination,
1728
+ msg,
1729
+ )
1730
+ raise SynapseError(
1731
+ HTTPStatus.TOO_MANY_REQUESTS, msg, Codes.LIMIT_EXCEEDED
1732
+ )
1733
+
1734
+ # this should be a multipart/mixed response with the boundary string in the header
1735
+ try:
1736
+ raw_content_type = headers.get(b"Content-Type")
1737
+ assert raw_content_type is not None
1738
+ content_type = raw_content_type[0].decode("UTF-8")
1739
+ content_type_parts = content_type.split("boundary=")
1740
+ boundary = content_type_parts[1]
1741
+ except Exception:
1742
+ msg = "Remote response is malformed: expected Content-Type of multipart/mixed with a boundary present."
1743
+ logger.warning(
1744
+ "{%s} [%s] %s",
1745
+ request.txn_id,
1746
+ request.destination,
1747
+ msg,
1748
+ )
1749
+ raise SynapseError(HTTPStatus.BAD_GATEWAY, msg)
1750
+
1751
+ try:
1752
+ async with self.remote_download_linearizer.queue(ip_address):
1753
+ # add a byte of headroom to max size as `_MultipartParserProtocol.dataReceived` errs at >=
1754
+ deferred = read_multipart_response(
1755
+ response, output_stream, boundary, expected_size + 1
1756
+ )
1757
+ deferred.addTimeout(self.default_timeout_seconds, self.reactor)
1758
+ multipart_response = await make_deferred_yieldable(deferred)
1759
+ except BodyExceededMaxSize:
1760
+ msg = "Requested file is too large > %r bytes" % (expected_size,)
1761
+ logger.warning(
1762
+ "{%s} [%s] %s",
1763
+ request.txn_id,
1764
+ request.destination,
1765
+ msg,
1766
+ )
1767
+ raise SynapseError(HTTPStatus.BAD_GATEWAY, msg, Codes.TOO_LARGE)
1768
+ except defer.TimeoutError as e:
1769
+ logger.warning(
1770
+ "{%s} [%s] Timed out reading response - %s %s",
1771
+ request.txn_id,
1772
+ request.destination,
1773
+ request.method,
1774
+ request.uri.decode("ascii"),
1775
+ )
1776
+ raise RequestSendFailed(e, can_retry=True) from e
1777
+ except ResponseFailed as e:
1778
+ logger.warning(
1779
+ "{%s} [%s] Failed to read response - %s %s",
1780
+ request.txn_id,
1781
+ request.destination,
1782
+ request.method,
1783
+ request.uri.decode("ascii"),
1784
+ )
1785
+ raise RequestSendFailed(e, can_retry=True) from e
1786
+ except Exception as e:
1787
+ logger.warning(
1788
+ "{%s} [%s] Error reading response: %s",
1789
+ request.txn_id,
1790
+ request.destination,
1791
+ e,
1792
+ )
1793
+ raise
1794
+
1795
+ if not multipart_response.url:
1796
+ assert multipart_response.length is not None
1797
+ length = multipart_response.length
1798
+ headers[b"Content-Type"] = [multipart_response.content_type]
1799
+ headers[b"Content-Disposition"] = [multipart_response.disposition]
1800
+
1801
+ # the response contained a redirect url to download the file from
1802
+ else:
1803
+ str_url = multipart_response.url.decode("utf-8")
1804
+ logger.info(
1805
+ "{%s} [%s] File download redirected, now downloading from: %s",
1806
+ request.txn_id,
1807
+ request.destination,
1808
+ str_url,
1809
+ )
1810
+ # We don't know how large the response will be upfront, so limit it to
1811
+ # the `max_size` config value.
1812
+ length, headers, _, _ = await self._simple_http_client.get_file(
1813
+ str_url, output_stream, max_size
1814
+ )
1815
+
1816
+ logger.info(
1817
+ "{%s} [%s] Completed: %d %s [%d bytes] %s %s",
1818
+ request.txn_id,
1819
+ request.destination,
1820
+ response.code,
1821
+ response.phrase.decode("ascii", errors="replace"),
1822
+ length,
1823
+ request.method,
1824
+ request.uri.decode("ascii"),
1825
+ )
1826
+
1827
+ # if we didn't know the length upfront, decrement the actual size from ratelimiter
1828
+ if response.length == UNKNOWN_LENGTH:
1829
+ download_ratelimiter.record_action(
1830
+ requester=None, key=ip_address, n_actions=length
1831
+ )
1832
+
1833
+ return length, headers, multipart_response.json
1834
+
1835
+
1836
+ def _flatten_response_never_received(e: BaseException) -> str:
1837
+ if hasattr(e, "reasons"):
1838
+ reasons = ", ".join(
1839
+ _flatten_response_never_received(f.value) for f in e.reasons
1840
+ )
1841
+
1842
+ return "%s:[%s]" % (type(e).__name__, reasons)
1843
+ else:
1844
+ return repr(e)
1845
+
1846
+
1847
+ def check_content_type_is(headers: Headers, expected_content_type: str) -> None:
1848
+ """
1849
+ Check that a set of HTTP headers have a Content-Type header, and that it
1850
+ is the expected value..
1851
+
1852
+ Args:
1853
+ headers: headers to check
1854
+
1855
+ Raises:
1856
+ RequestSendFailed: if the Content-Type header is missing or doesn't match
1857
+
1858
+ """
1859
+ content_type_headers = headers.getRawHeaders(b"Content-Type")
1860
+ if content_type_headers is None:
1861
+ raise RequestSendFailed(
1862
+ RuntimeError("No Content-Type header received from remote server"),
1863
+ can_retry=False,
1864
+ )
1865
+
1866
+ c_type = content_type_headers[0].decode("ascii") # only the first header
1867
+ # Extract the 'essence' of the mimetype, removing any parameter
1868
+ c_type_parsed = c_type.split(";", 1)[0].strip()
1869
+ if c_type_parsed != expected_content_type:
1870
+ raise RequestSendFailed(
1871
+ RuntimeError(
1872
+ f"Remote server sent Content-Type header of '{c_type}', not '{expected_content_type}'",
1873
+ ),
1874
+ can_retry=False,
1875
+ )