Against real-world OTP 26 peers the v6 handshake "succeeded" but the first REG_SEND silently dropped on the peer side — peer accepted the connection then closed the link with no bytes when we tried to call a registered process. Hit during MPS↔portal wallet RPC smoke test. Root cause: OTP 25+ requires DFLAG_MANDATORY_25_DIGEST to be present in our advertised flag set. The digest is the hash of the OTP-25 mandatory flag set; without it the peer's dist driver loses confidence in the negotiation and drops messages from us without surfacing an error. Adds DFLAG_MANDATORY_25_DIGEST to DEFAULT_FLAGS. Also extends _decode_message to accept both legacy pass-through (0x70 ...) and dist-header framing (0x83 0x44 0x00 ...) on receive — modern OTP may send dist-headed messages even when we didn't negotiate DFLAG_DIST_HDR_ATOM_CACHE. Fragments (0x83 0x45 / 0x83 0x46) still TODO; we surface a clear ChannelError instead of silent corruption. Send side still uses pass-through framing — we don't yet implement the atom-cache encode/decode that DFLAG_DIST_HDR_ATOM_CACHE would require. Peer routes our pass-through sends without issue. 122/122 tests pass including live integration against a local Erlang node and the TLS dist suite.
72 lines
1.8 KiB
TOML
72 lines
1.8 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=68", "wheel"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "erldistpy"
|
|
version = "0.1.7"
|
|
description = "Native Python client for Erlang distribution protocol — EPMD + v6 handshake + gen_server call(), no asyncio."
|
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
requires-python = ">=3.10"
|
|
license = { text = "Unlicense" }
|
|
authors = [
|
|
{ name = "Russell Ballestrini", email = "russell.ballestrini@gmail.com" },
|
|
]
|
|
keywords = [
|
|
"erlang",
|
|
"elixir",
|
|
"distribution",
|
|
"dist",
|
|
"gen_server",
|
|
"rpc",
|
|
"etf",
|
|
"epmd",
|
|
"inet_tls_dist",
|
|
"interop",
|
|
]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"License :: Public Domain",
|
|
"Operating System :: OS Independent",
|
|
"Programming Language :: Python",
|
|
"Programming Language :: Python :: 3",
|
|
"Programming Language :: Python :: 3.10",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Programming Language :: Python :: 3 :: Only",
|
|
"Programming Language :: Erlang",
|
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
"Topic :: System :: Networking",
|
|
]
|
|
dependencies = []
|
|
|
|
[project.urls]
|
|
Homepage = "https://git.unturf.com/python/erldistpy"
|
|
Repository = "https://git.unturf.com/python/erldistpy"
|
|
"Bug Tracker" = "https://git.unturf.com/python/erldistpy/-/issues"
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest >=8.0,<9",
|
|
"pytest-cov >=5.0,<7",
|
|
"ruff >=0.6,<1",
|
|
"build >=1.0",
|
|
"twine >=5.0",
|
|
]
|
|
|
|
[tool.setuptools.packages.find]
|
|
include = ["erldistpy*"]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
addopts = "-ra --strict-markers"
|
|
|
|
[tool.ruff]
|
|
line-length = 100
|
|
target-version = "py310"
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "B", "UP", "SIM"]
|
|
ignore = ["E501"]
|