Generalize the most common PRIVATE_CLIENT patterns
Most of these are extensions, and mostly they track the protocol version negotiated by the client. Given the number of extensions / privates in a typical server it's probably close to a wash (in terms of storage) to allocate an array of struct { u8 major, minor; }
for each extension and stash that in the client directly.
The other major usage is handling client disconnection. ClientStateCallback
isn't a super convenient API, there's probably a better way to do that.