T
twostars
Migrate server networking code to Asio 1.36.0 (#619)
* Add asio, build asio + servers explicitly for Windows 10+
* VersionManager: Strip "client" sockets
"Client" sockets as in the VersionManager acts as a client to connect to something else.
Stripping these as they're unused and reduce the overall code to migrate.
* VersionManager: Migrate to basic asio implementation
* VersionManager: Replace critical section and minor renaming
* VersionManager: Consolidate socket ID & instance pops/pulls
This removes a bunch of duplicate logic and ensures it's consistently guarded.
All log entries are still handled, just externally of the mutex.
* VersionManager: Pool raw sockets to avoid allocating on-demand
* VersionManager: Rework sends using a circular buffer & queueing
* AI: Strip 'client' connection logic
* Simplify; strip raw socket pool
It can just allocate these on-demand through asio internals; it's fairly cheap.
The initial dummy socket allocs under CIOCPSocket2 are also cheap and don't affect much,
so it's not really worth the extra effort managing this.
* VersionManager: Implement networking shutdown logic
* AI: Rework to use asio
* Fix async send chaining
* Move generic thread logic into shared Thread class
* Ebenezer: Migrate CUdpSocket to asio
* Ebenezer: Migrate AI & user sockets to asio
* Improve thread safety, flesh out shutdown logic
* Move, merge & rename networking implementations in shared project
For efficiency, we keep things like the Send() implementation implemented directly in the implementing class.
They tend to handle these differently, so we shouldn't try to one-size-fits-all them, even though most are similar.
We also hide away direct access to SocketManager's (formerly CIOCPort) members, so we can more consistently verify them.
To avoid any awkward deadlocks (particularly with AI connections in Ebenezer), we ensure listbox updates are done only within
the window's main thread. We queue them and post a message to trigger their update when it gets a chance.
Otherwise it will use SendMessage(), blocking until the main thread processes, which can be particularly bad if the main thread
is doing things with locks already, (e.g. already trying to connect to AI).
* Remove socket type
* VersionManager: Also handle queued listbox messages for consistency
* Ensure we're consistently calling parent implementations
* Move into Server/network project
We decouple this from shared because it's used by the client.
The client has no business knowing about any of this, and will likely down the track
end up having its own asio implementation.
This would be largely incompatible as it's designed for a server.
It makes sense, then, to decouple this and have it in its own server-specific lib project.
Also: the shared output directory was using the project default. We should just force it
to $(RootDir)bin -- i.e. $(BaseOutDir) -- and just ensure we still reference that, even from
server projects.
I'm not sure how it got missed when the other output paths got updated.
Server\network resides in the server's bin dir (Server\bin) as it's server-specific.
* Update some missed names in logs
* Allow for all queued packets being sent before finalising a disconnect
New sends will be blocked, as will handling of any new received packet data.
The intent here is to just allow for it to send any final packets before it cuts off the client.
This isn't really official behaviour at all, but it's nice to ensure.
Also just don't hold _sendMutex longer than we really need in TcpSocket::AsyncSend().
* Let's just move this comment down
* Use _recvBuffer.data() instead of &_recvBuffer[0]
* Fix misleading comments - not necessarily players
* Restore AoE check
Officially this was checked subtly ('< -1').
Github Commit Görüntüle...
See Commints...
..
* Add asio, build asio + servers explicitly for Windows 10+
* VersionManager: Strip "client" sockets
"Client" sockets as in the VersionManager acts as a client to connect to something else.
Stripping these as they're unused and reduce the overall code to migrate.
* VersionManager: Migrate to basic asio implementation
* VersionManager: Replace critical section and minor renaming
* VersionManager: Consolidate socket ID & instance pops/pulls
This removes a bunch of duplicate logic and ensures it's consistently guarded.
All log entries are still handled, just externally of the mutex.
* VersionManager: Pool raw sockets to avoid allocating on-demand
* VersionManager: Rework sends using a circular buffer & queueing
* AI: Strip 'client' connection logic
* Simplify; strip raw socket pool
It can just allocate these on-demand through asio internals; it's fairly cheap.
The initial dummy socket allocs under CIOCPSocket2 are also cheap and don't affect much,
so it's not really worth the extra effort managing this.
* VersionManager: Implement networking shutdown logic
* AI: Rework to use asio
* Fix async send chaining
* Move generic thread logic into shared Thread class
* Ebenezer: Migrate CUdpSocket to asio
* Ebenezer: Migrate AI & user sockets to asio
* Improve thread safety, flesh out shutdown logic
* Move, merge & rename networking implementations in shared project
For efficiency, we keep things like the Send() implementation implemented directly in the implementing class.
They tend to handle these differently, so we shouldn't try to one-size-fits-all them, even though most are similar.
We also hide away direct access to SocketManager's (formerly CIOCPort) members, so we can more consistently verify them.
To avoid any awkward deadlocks (particularly with AI connections in Ebenezer), we ensure listbox updates are done only within
the window's main thread. We queue them and post a message to trigger their update when it gets a chance.
Otherwise it will use SendMessage(), blocking until the main thread processes, which can be particularly bad if the main thread
is doing things with locks already, (e.g. already trying to connect to AI).
* Remove socket type
* VersionManager: Also handle queued listbox messages for consistency
* Ensure we're consistently calling parent implementations
* Move into Server/network project
We decouple this from shared because it's used by the client.
The client has no business knowing about any of this, and will likely down the track
end up having its own asio implementation.
This would be largely incompatible as it's designed for a server.
It makes sense, then, to decouple this and have it in its own server-specific lib project.
Also: the shared output directory was using the project default. We should just force it
to $(RootDir)bin -- i.e. $(BaseOutDir) -- and just ensure we still reference that, even from
server projects.
I'm not sure how it got missed when the other output paths got updated.
Server\network resides in the server's bin dir (Server\bin) as it's server-specific.
* Update some missed names in logs
* Allow for all queued packets being sent before finalising a disconnect
New sends will be blocked, as will handling of any new received packet data.
The intent here is to just allow for it to send any final packets before it cuts off the client.
This isn't really official behaviour at all, but it's nice to ensure.
Also just don't hold _sendMutex longer than we really need in TcpSocket::AsyncSend().
* Let's just move this comment down
* Use _recvBuffer.data() instead of &_recvBuffer[0]
* Fix misleading comments - not necessarily players
* Restore AoE check
Officially this was checked subtly ('< -1').
Github Commit Görüntüle...
See Commints...
..