Files
ziti/common/ctrl_msg
Paul Lorenz 67eba590e2 Implement connect-v2. Fixes #3884
Implements the router-side Connect-V2 sessionless dial path. Dials are
authorized locally via the RouterDataModel instead of a controller-issued
service session token; circuit creation flows through the existing
`CreateCircuitV3` controller endpoint (#3721). Builds on the sdk-golang
v2 migration.

- Adds `processConnectV2` on `edgeClientConn`: resolves the service by id
  or name via the RouterDataModel, checks dial access, and dispatches to
  the controller via `sendCreateCircuitV3Msg`. Supports both
  `xgEdgeForwarder` (SDK xgress) and `nonXgConnectHandler` flow-control
  modes, selected by the SDK's `UseXgressToSdkHeader`.
- Makes `CircuitId` optional in `DecodeCreateCircuitV3Request`. The V2
  router path does not pre-assign a circuit ID; the controller generates
  it as V1/V2 already do. Without this the decoder rejected the empty
  header and every V2 dial hung until timeout. Adds a regression test.
- Splits `checkAccess` to close a posture-check bypass on the V2 path.
  The old single `checkAccess` short-circuited to nil for non-OIDC
  sessions (V1 ran posture at the controller during `CreateSession`); V2
  has no such step, so posture would have been skipped. `checkAccess` now
  always runs the RDM `HasAccess` (policy + posture) check;
  `checkAccessIfOidc` keeps the OIDC-only gate for the V1 and bind paths.
- Sends the V2 `state_connected` on the default (data) sender rather than
  the control sender. On multi-underlay channels the two senders are
  independently ordered, so an early terminator payload on the data
  sender could beat `state_connected` to the SDK and be dropped (channel/v5
  has no message-priority API).
- Updates `xgEdgeForwarder.lastRx` on every forward path, including the
  fast `timeout == 0` `TrySend` branch used for normal payload dispatch.
  The old code only updated it on the `timeout > 0` path, so active V2
  circuits looked idle and could be unrouted prematurely.
- Adds `state.ConnState.ServiceId`, populated by the connect handlers from
  the service session token (V1) or the request header (V2). The
  non-xgress V2 path previously left this empty, so `handleDialAccessLost`
  could not identify and close V2 non-xgress circuits when dial access was
  revoked.
- Skips conns with no `ServiceSessionToken` in `RemoveLegacyServiceSession`;
  a sessionless V2 conn's token is nil and the cleanup loop previously
  dereferenced it unconditionally, which would panic the router.
- Advertises Connect-V2 via the `RouterCapabilityConnectV2` bit in the
  listener hello so SDKs can detect V2 support.
- Wires `ContentTypeConnectV2` and `ContentTypeXgControl` handlers in
  `Acceptor.BindChannel`, and adds `handleXgControl` for SDK-side xgress
  control messages, preserving `ControlUserVal` so trace-route responses
  correlate back to the initiator's `SendForReply` waiter.
- Adds `RouterDataModel.serviceNameIndex` for O(1) name->id lookup in the
  V2 dial path, maintained with rename safety at the `HandleServiceEvent`
  mutation points.
- Adds `tests/connect_v2_test.go` covering end-to-end V2 dataflow and the
  V1 fallback (`ForceConnectV1`), asserting the dial path via the SDK
  `DialEvent`.

- Propagates a V2 initiator's graceful half-close to legacy hosts via
  `edgeXgressConn.FlowFromFabricToXgressClosed`, which emits an edge FIN
  when the fabric->app half of the circuit closes. The SDK signals
  half-close to its router xgress peer with the native xgress EOF flag;
  without translating that to an edge FIN, a legacy host reading to EOF
  stalled until teardown.
- Records the dialing identity id as the circuit `ClientId` for
  sessionless V2 dials, since there is no dial session to key on; updates
  `Test_OidcEvents` to match.
- Adds `tests/connect_v2_teardown_test.go` covering client- and
  host-initiated close propagation on both the V2 and forced-V1 paths.
- Polls for the asynchronous conn close in the SDK posture-check tests
  (`awaitClientConnClosed`): revocation tears the circuit down out of
  band, so checking `IsClosed` immediately after the first read error was
  racy.
- Temporarily pins sdk-golang/v2 to the openziti/sdk-golang#959 commit,
  which carries the matching xgress conn-close-on-teardown fix the V2
  posture tests depend on; to be repointed at the next sdk-golang
  pre-release before merge.

For openziti/sdk-golang#936.
2026-06-24 16:40:40 -04:00
..
2026-06-24 16:40:40 -04:00