Repository navigation
Conversation
Failures handled inside the toolkit only reach SLF4J, so an integrator cannot report them to a monitoring system. Add a provider-agnostic event and listener in utils, the one module the WAMP and SOAP stacks both see. notifySafely isolates the caller from whatever the listener throws, including an Error such as a monitoring class missing at runtime. Calling it with ?. builds no event without a listener.
Report malformed messages, calls without a handler, throwing handlers and transport failures. The answers sent to the charging station do not change. http4k routes whatever escapes ws.onMessage to ws.onError, which makes it the only place reporting that path. An executor running calls on the message thread sends an already reported failure back there too, so the connection remembers it to report it once.
The single catch converting failures to a CALLERROR covers three stages. Track the current one to tell a payload that cannot be parsed or serialized from a throwing callback. The CALLERROR does not change.
Report unknown actions, malformed envelopes, throwing callbacks and responses that cannot be serialized. Failures still propagate to http4k, so the HTTP answers do not change.
One registration covers the WebSocket and SOAP servers. Document it in the README, with an example reporting to a monitoring system.
The KDoc and the README said a blocked listener only delays its own charging station. Malformed messages, rejected calls and WebSocket errors are reported on the I/O thread shared by many connections, so it delays every station served by that thread. Addresses review: IZIVIA#128 (comment)
…uses
The accept predicate tested `filter { ... } != null`, which is true
for any extracted id. A refused station got a 101, fired
onWsConnectHandler and could evict an accepted station whose id
differs only by case, since connection keys are lowercased.
Accept only when a handler accepts, and memoize only non-empty lists,
so an unknown id no longer adds an entry to selectedHandler. The entry
of a station refused later stays: newConnection reads it after
registering the connection, so removing it could fail a handshake in
flight, and the predicate rewrites it before any read.
Answer the refusal with the 404 that OCPP-J asks for (SHOULD, 1.6
section 3.2 and 2.1 part 4), instead of falling through to the HTTP
handler, whose status depended on SOAP sharing the port.
Stations with acceptConnection = false used to connect and now fail
their handshake, and a server with no handler refuses every station.
Fixes IZIVIA#130
juherr
force-pushed
the
juherr/ocpp-toolkit-152
branch
from
November 8, 2026 14:57
2de9122 to
aea5498
Compare
…grade request Security profiles 1 and 2 authenticate a charging station with HTTP Basic authentication on its upgrade request, which the toolkit could not check: OcppWampServerHandler.accept only sees the station id. A ConnectionAuthorizer given to the server now decides from a ConnectionRequest holding the id and the headers of the request, once per upgrade and before any handler's accept. The request is a class so that it can later carry the client certificate of security profile 3 without breaking authorizers, and its toString leaves the headers out. A refused station gets a 401 with a Basic challenge, and is never memoized, registered nor notified. Running it first means an unknown station without valid credentials gets a 401 as well, rather than a 404 that would tell its id apart. The authorizer fails closed: one that throws refuses the station. Only the station id and the exception class are logged, since the headers and the exception message may carry credentials. For the same reason, the upgrade request is now logged without its Authorization header once a station is accepted: the debug log of the connection attempt and the errors of a new connection printed it. BREAKING CHANGE: WsServerConfig.acceptWebSocketPredicate and the acceptWebSocketPredicate parameter of Undertow are replaced by admitWebSocket, which returns a WebSocketUpgradeDecision, or null when the request is not for that endpoint, instead of a Boolean. Refs IZIVIA#152
WebsocketServer takes the ConnectionAuthorizer of its OcppWampServer, so that a CSMS built on the transport can check the Basic authentication of its charging stations. Refs IZIVIA#152
ServerSetting.authorizer reaches the WebSocket server of the setting, and is ignored for SOAP. When several WebSocket servers share a port, the first one claiming the upgrade request decides. Refs IZIVIA#152
juherr
force-pushed
the
juherr/ocpp-toolkit-152
branch
from
November 8, 2026 15:04
aea5498 to
82df971
Compare
|
This was referenced Nov 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Closes #152; this is stacked on #134 (itself on #128), so the diff also shows their commits, the optional
OcppErrorListenerof #128 and the 404 refused handshake of #134, and only the last four commits belong here.A server-level
ConnectionAuthorizer(given toOcppWampServer.newServer,WebsocketServerorServerSetting.authorizer) decides from aConnectionRequestholding the station id and the headers of its upgrade request, before any handler'saccept: a refused or throwing check answers a 401 with aWWW-Authenticate: Basicchallenge, and the station is never registered nor notified.Breaking:
WsServerConfig.acceptWebSocketPredicateand theacceptWebSocketPredicateparameter ofUndertowbecomeadmitWebSocket, which returns aWebSocketUpgradeDecision(ornullwhen the request is not for that endpoint), andCSMSlets the first endpoint claiming the request decide.The upgrade request is no longer logged with its
Authorizationheader, and the README shows how to check the Basic authentication of a station, comparing bytes so that the binaryAuthorizationKeyof the OCPP 1.6 Security Whitepaper works as well as the UTF-8 password of OCPP 2.0.1.