Repository navigation
Build the DTLS connection at one site per caller - #120
Conversation
A session built SSL.Context, called configure_context and built SSL.Connection inline in connect(), and the diagnostic did the same thing again in its own function. Reaching any engine other than pyOpenSSL from there means an isinstance fork at both sites and a third in the reader loop, which is what the closed #115 had to do. So both sites now go through one function that asks the provider for a connection first and falls back to the context path. No provider carries a factory yet, so nothing changes behaviour: the existing 947 tests pass untouched. The factory is private and deliberately not a verb on AuthenticationProvider. That Protocol is runtime_checkable and __init__ gates on isinstance, so a required method would reject every third-party provider that has not grown one -- Jason-Morcos's objection on #117, and the reason Phase 0 of the plan is not being followed as written. A public connection-provider interface stays available as a separate opt-in thing. Two orderings matter and both have a test. The session checks cancellation around the provider's work rather than inside it, so a configure_context that loads a PEM chain off disk stays interruptible. The diagnostic asks the factory before the context path, because _validate_diagnostic_auth only duck-checks configure_context and a provider owning its own engine keeps that method -- so the order is the only thing deciding which engine sees the credential, and a session-working credential failing in the diagnostic would break what 47e09b3 added auth= for. _client_hello_flight stays on OpenSSL: it takes no provider, and a credential's engine would turn a stateless liveness probe into a handshake attempt.
|
@Jason-Morcos This is the seam from your note on #117, separated so it lands before anything is wired to it. Details are in issuecomment-6001440451; nothing here needs re-reading from that. One judgement call in it is mine, and it is cheap to change now and awkward once the wiring stacks on top. You said a small internal factory. I read that as dispatch: Which did you mean? |
|
@QuiteYellow I meant the The contract I'd spell out is: return a fresh, client-ready, socket-free connection for this attempt, with the requested MTU applied, and leave sockets, cancellation/deadline handling and session publication to the caller. The hook shouldn't start network I/O. That also makes the existing exception/callback expectations clear for anyone experimenting with another engine. I reviewed One small wording fix: the docstring says a slow |
Two corrections from @Jason-Morcos's review of f5cbde2 on #120. The docstring said a slow configure_context "stays interruptible". It does not: the checks run before and after the provider's work, so a call already blocked on a PEM read is never interrupted. What they do guarantee is that cancellation set during that work stops the attempt before any socket exists -- narrower, and true. Two tests through the public connect() pin it, cancellation inside the factory and a factory that eats the whole deadline, each failing if a socket is opened. He had verified both by hand; this is them written down. The hook also had no written contract, leaving anyone trying another engine to infer it from the pyOpenSSL path. Now stated: return a fresh connection already in client state with mtu applied, own no socket, start no network I/O, and raise like the memory-BIO subset of SSL.Connection that _drive_dtls_handshake drives. The caller keeps the socket, the deadline and cancellation handling, and session publication. Also drops "built-in" from the description of which providers the getattr dispatch reaches. He confirmed getattr is what he intended and that a third-party provider deliberately supplying the private hook may use it, so describing it as built-in-only was wrong. It stays unsupported as an extension API; a real one gets designed separately.
|
Addressed in Full detail on #117, since the cookie correction belonged there anyway. |
A session built
SSL.Context, calledconfigure_contextand builtSSL.Connectioninline inconnect(), and the diagnostic did the same again in its own function. Reaching any engine other than pyOpenSSL from there costs anisinstancefork at both sites and a third in the reader loop, which is what the closed #115 had to do.Both sites now go through one function that asks the provider for a connection and falls back to the context path. No provider carries a factory yet, so this changes no behaviour: the existing suite passes untouched, plus 9 tests of which 7 fail without the change.
The factory is private, and deliberately not a verb on
AuthenticationProvider. That Protocol isruntime_checkableand__init__gates onisinstance(dtls_session.py:549), so a required method would reject every third-party provider that has not grown one. @Jason-Morcos raised this on #117 and it is his call that shaped it; a public connection-provider interface stays available later as a separate opt-in thing.getattrdispatch on a private name is the existing pattern here rather than a new one, sinceconnect()already looks up_authenticated_server_identitythat way.Two orderings matter and both have a test:
configure_contextalready blocked on a PEM read runs to completion; what the checks guarantee is that no socket is created once cancellation is set. Two tests through the publicconnect()pin that. The certificate path is otherwise a verbatim move — traced againstmainwith a realCertificateAuth, the call sequence is 16 identical steps._validate_diagnostic_authonly duck-checksconfigure_contextand a provider owning its own engine keeps that method. The order is the only thing deciding which engine sees the credential, and a session-working credential failing in the diagnostic would break what47e09b3addedauth=for._client_hello_flightstays on OpenSSL: it takes no provider, and a credential's engine would turn a stateless liveness probe into a handshake attempt against the appliance.Worth having whichever engine ships, which is why it is separate.
feat/psk-engine-wiringstacks the PSK engine on top of this.