texas2step 2.2.1__tar.gz → 2.2.2__tar.gz

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.
Files changed (66) hide show
  1. {texas2step-2.2.1 → texas2step-2.2.2}/PKG-INFO +1 -1
  2. {texas2step-2.2.1 → texas2step-2.2.2}/docs/roadmap.md +19 -0
  3. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/__init__.py +1 -1
  4. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/rtc.py +12 -2
  5. {texas2step-2.2.1 → texas2step-2.2.2}/.gitignore +0 -0
  6. {texas2step-2.2.1 → texas2step-2.2.2}/LICENSE.md +0 -0
  7. {texas2step-2.2.1 → texas2step-2.2.2}/README.md +0 -0
  8. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/nginx/texas2step-http.conf +0 -0
  9. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/nginx/texas2step-log.conf +0 -0
  10. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/nginx/texas2step-speedtest.conf +0 -0
  11. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/nginx/texas2step.conf +0 -0
  12. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/texas2step-update.service +0 -0
  13. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/texas2step-update.timer +0 -0
  14. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/texas2step.default +0 -0
  15. {texas2step-2.2.1 → texas2step-2.2.2}/deploy/texas2step.service +0 -0
  16. {texas2step-2.2.1 → texas2step-2.2.2}/docs/access.md +0 -0
  17. {texas2step-2.2.1 → texas2step-2.2.2}/docs/api.md +0 -0
  18. {texas2step-2.2.1 → texas2step-2.2.2}/docs/configuration.md +0 -0
  19. {texas2step-2.2.1 → texas2step-2.2.2}/docs/development.md +0 -0
  20. {texas2step-2.2.1 → texas2step-2.2.2}/docs/experience.md +0 -0
  21. {texas2step-2.2.1 → texas2step-2.2.2}/docs/images/hero-dark.jpg +0 -0
  22. {texas2step-2.2.1 → texas2step-2.2.2}/docs/images/results-dark.jpg +0 -0
  23. {texas2step-2.2.1 → texas2step-2.2.2}/docs/images/results-light.jpg +0 -0
  24. {texas2step-2.2.1 → texas2step-2.2.2}/docs/images/upload-light.jpg +0 -0
  25. {texas2step-2.2.1 → texas2step-2.2.2}/docs/install.md +0 -0
  26. {texas2step-2.2.1 → texas2step-2.2.2}/docs/methodology.md +0 -0
  27. {texas2step-2.2.1 → texas2step-2.2.2}/docs/security.md +0 -0
  28. {texas2step-2.2.1 → texas2step-2.2.2}/docs/traffic.md +0 -0
  29. {texas2step-2.2.1 → texas2step-2.2.2}/legacy/README.md +0 -0
  30. {texas2step-2.2.1 → texas2step-2.2.2}/pyproject.toml +0 -0
  31. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/__main__.py +0 -0
  32. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/access.py +0 -0
  33. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/__init__.py +0 -0
  34. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/access.py +0 -0
  35. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/measure.py +0 -0
  36. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/meta.py +0 -0
  37. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/results.py +0 -0
  38. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/api/wire.py +0 -0
  39. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/app.py +0 -0
  40. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/cli.py +0 -0
  41. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/cluster.py +0 -0
  42. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/config.py +0 -0
  43. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/config_edit.py +0 -0
  44. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/config_merge.py +0 -0
  45. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/config_template.toml +0 -0
  46. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/engine.py +0 -0
  47. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/iface.py +0 -0
  48. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/lockouts.py +0 -0
  49. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/logs.py +0 -0
  50. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/page.py +0 -0
  51. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/payload.py +0 -0
  52. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/quality.py +0 -0
  53. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/app.css +0 -0
  54. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/app.js +0 -0
  55. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/swagger/LICENSE +0 -0
  56. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/swagger/NOTICE +0 -0
  57. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/swagger/swagger-ui-bundle.js +0 -0
  58. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/swagger/swagger-ui-bundle.js.LICENSE.txt +0 -0
  59. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/assets/swagger/swagger-ui.css +0 -0
  60. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/favicon.svg +0 -0
  61. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/static/index.html +0 -0
  62. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/stats.py +0 -0
  63. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/store.py +0 -0
  64. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/traffic.py +0 -0
  65. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/update.py +0 -0
  66. {texas2step-2.2.1 → texas2step-2.2.2}/src/texas2step/words.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: texas2step
3
- Version: 2.2.1
3
+ Version: 2.2.2
4
4
  Summary: Web-centric throughput, latency, jitter and packet-loss measurement between endpoints.
5
5
  Project-URL: Homepage, https://github.com/robert-patrick-texas/texas2step
6
6
  Project-URL: Documentation, https://robert-patrick-texas.github.io/texas2step/
@@ -64,6 +64,20 @@ links and footer credit. Three places still say texas2step:
64
64
  - [ ] **The API explorer** (`/api/docs`) is titled "texas2step - Swagger UI".
65
65
  - [ ] **The API tab's command-line examples** name the `texas2step` CLI.
66
66
 
67
+ ### Security
68
+
69
+ - [ ] **DTLS 1.3 for the UDP probe.** The probe's data channel uses DTLS 1.2
70
+ ([On the wire](security.md#on-the-wire)): the server offers nothing newer, though Chrome
71
+ and Firefox now prefer DTLS 1.3. OpenSSL added DTLS 1.3 in 4.1.0 (October 2026). The
72
+ server's WebRTC library, aiortc, uses the OpenSSL bundled in the `cryptography`
73
+ package, 4.0 for now. Once `cryptography` ships OpenSSL 4.1, a release's `make upgrade`
74
+ brings it in. Then check what a browser negotiates (`tlsVersion` `FEFC` in the
75
+ connection's statistics, not `FEFD`). aiortc may need its DTLS context set to allow
76
+ 1.3, and its 1.3 cipher suites set apart from its 1.2 cipher list. DTLS 1.3 would hide
77
+ the throwaway certificates, drop the CBC cipher suites and save a round trip, and later
78
+ allow post-quantum key exchange. The probe carries nothing secret, so this can wait for
79
+ the libraries.
80
+
67
81
  ### Updates
68
82
 
69
83
  [`texas2step update`](install.md#with-texas2step-update) could also:
@@ -102,6 +116,11 @@ links and footer credit. Three places still say texas2step:
102
116
 
103
117
  Newest first. Each release's notes have the details and its upgrade steps.
104
118
 
119
+ ### [2.2.2](https://github.com/robert-patrick-texas/texas2step/releases/tag/v2.2.2) (2026-10-24)
120
+
121
+ - [x] UDP works in Firefox: Monitor, Diag and the Test page's packet loss no longer fall
122
+ back to TCP there.
123
+
105
124
  ### [2.2.1](https://github.com/robert-patrick-texas/texas2step/releases/tag/v2.2.1) (2026-10-24)
106
125
 
107
126
  - [x] Monitor gets a server back after an outage: HTTPS checks, then a new session, or
@@ -1,3 +1,3 @@
1
1
  """texas2step: web-centric throughput, latency, jitter and packet-loss measurement."""
2
2
 
3
- __version__ = "2.2.1"
3
+ __version__ = "2.2.2"
@@ -85,11 +85,21 @@ RECEIVED_OVERHEAD = 150
85
85
  MDNS_CANDIDATE = re.compile(
86
86
  r"^a=candidate:\S+ \d+ \S+ \d+ \S+\.local \d+ [^\r\n]*\r?\n", re.M | re.I
87
87
  )
88
+ END_OF_CANDIDATES = re.compile(r"^a=end-of-candidates\r?\n", re.M)
88
89
 
89
90
 
90
91
  def without_mdns(sdp: str) -> str:
91
- """The offer without the candidates a browser names by multicast DNS."""
92
- return MDNS_CANDIDATE.sub("", sdp)
92
+ """The offer without the candidates a browser names by multicast DNS.
93
+
94
+ An offer left with none loses its end-of-candidates too. Firefox sends one: aioice
95
+ would take the empty list as final, drop the stream's only component, and answer
96
+ with no candidates of its own, so no UDP session could open. Without it, aioice waits
97
+ for the browser's checks, as with Chrome, which sends none.
98
+ """
99
+ sdp = MDNS_CANDIDATE.sub("", sdp)
100
+ if not re.search(r"^a=candidate:", sdp, re.M):
101
+ sdp = END_OF_CANDIDATES.sub("", sdp)
102
+ return sdp
93
103
 
94
104
 
95
105
  def _bind_in_range(address: str, ports: tuple[int, int]) -> socket.socket | None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes