Refactor puffin_http::Server to support client connect/disconnect callback #264
+761
−147
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.
Checklist
Description of Changes
I need the ability to enable profiling when
puffin_viewerconnects and disable when it disconnects so I decided to add a callback to support this use case (and possibly more). Implementation turned out to be more complex than I expected and I rewrote the server almost entirely.However, this is a backward-compatible change. No major version increment required.
Summary of changes:
Added
Server::set_on_state_change(),Server::unset_on_state_change()andServer::replace_on_state_change()for setting a callback that is called when first client connects or last client disconnects from server. See documentation ofServer::set_on_state_change()for the details.Added test for this new callback mechanism.
Socket listener decoupled from the profiling data processing/packet forwarding and separated into its own thread.
Dependency on
crossbeam_channelremoved.Original code contained this comment:
This is false. Std's
mpscchannels do not work like this. This is easy to test: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=2ae8d03c8910d6b709a5ef7780a433beAdded
Server::local_addr()to get an actual IP:Port that server is using. Useful when server is started on a random available port ("localhost:0").TcpStream::shutdown()is used to ensure no data loss when closing client sockets. This is very implementation defined, such problem may never happen in practice.Panics inside the service threads are propagated further now.
Added panics when some impossible states are encountered. Those can fire only if I introduced bugs somewhere.
Server example updated to show the usage of new
Serverfunctions.$CLIENT is not accepting data fast enough; dropping a framewarning will be shown only once per client to not flood the logs.Added 30-second TCP write timeout. Timed out clients are dropped.
I tried to minimize the amount of reallocations in the packet fan-out thread by keeping the maximum packet size for
Vec::with_capacity().There is a single problem with new implementation though: it is impossible to reliably shut down a TCP listener without adding additional dependencies for a proper async networking. I tried my best, but it may break in some cases:
TcpStreamto aServer::local_addr()with some small timeout. It may fail with a timeout if everything runs horribly slow for some reason.In those cases, handle of the listener thread is added into the
LEAKED_LISTENERStable. This table is checked when socket bind fails with "Address already in use" while creating newServer.Related Issues
Alternative pull request for the same feature: #257