3737
3838using namespace asyncsrv ;
3939
40- namespace {
41- AsyncWebSocketClient *find_connected_client_locked (std::list<AsyncWebSocketClient> &clients, uint32_t id) {
42- const auto iter = std::find_if (clients.begin (), clients.end (), [id](const AsyncWebSocketClient &client) {
43- return client.id () == id && client.status () == WS_CONNECTED ;
44- });
45- return iter == clients.end () ? nullptr : &(*iter);
46- }
47- } // namespace
48-
4940size_t webSocketSendFrameWindow (AsyncClient *client) {
5041 if (!client || !client->canSend ()) {
5142 return 0 ;
@@ -367,6 +358,7 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time) {
367358
368359void AsyncWebSocketClient::_onPoll () {
369360 asyncsrv::unique_lock_type lock (_lock);
361+
370362 if (!_client) {
371363 return ;
372364 }
@@ -454,6 +446,7 @@ bool AsyncWebSocketClient::canSend() const {
454446
455447bool AsyncWebSocketClient::_queueControl (uint8_t opcode, const uint8_t *data, size_t len, bool mask) {
456448 asyncsrv::lock_guard_type lock (_lock);
449+
457450 if (!_client) {
458451 return false ;
459452 }
@@ -470,6 +463,7 @@ bool AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, si
470463
471464bool AsyncWebSocketClient::_queueMessage (AsyncWebSocketSharedBuffer buffer, uint8_t opcode, bool mask) {
472465 asyncsrv::unique_lock_type lock (_lock);
466+
473467 if (!_client || !buffer || buffer->empty () || _status != WS_CONNECTED ) {
474468 return false ;
475469 }
@@ -958,6 +952,7 @@ bool AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len) {
958952
959953IPAddress AsyncWebSocketClient::remoteIP () const {
960954 asyncsrv::lock_guard_type lock (_lock);
955+
961956 if (!_client) {
962957 return IPAddress ((uint32_t )0U );
963958 }
@@ -967,6 +962,7 @@ IPAddress AsyncWebSocketClient::remoteIP() const {
967962
968963uint16_t AsyncWebSocketClient::remotePort () const {
969964 asyncsrv::lock_guard_type lock (_lock);
965+
970966 if (!_client) {
971967 return 0 ;
972968 }
@@ -995,10 +991,14 @@ AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request)
995991}
996992
997993void AsyncWebSocket::_handleDisconnect (AsyncWebSocketClient *client) {
998- (void )client;
999- // Defer removal to cleanupClients(). Disconnect callbacks can fire while
1000- // iterating _clients for broadcast sends, and erasing here invalidates the
1001- // active iterator in the caller.
994+ asyncsrv::lock_guard_type lock (_lock);
995+ const auto client_id = client->id ();
996+ const auto iter = std::find_if (std::begin (_clients), std::end (_clients), [client_id](const AsyncWebSocketClient &c) {
997+ return c.id () == client_id;
998+ });
999+ if (iter != std::end (_clients)) {
1000+ _clients.erase (iter);
1001+ }
10021002}
10031003
10041004bool AsyncWebSocket::availableForWriteAll () {
@@ -1040,7 +1040,7 @@ AsyncWebSocketClient *AsyncWebSocket::client(uint32_t id) {
10401040
10411041void AsyncWebSocket::close (uint32_t id, uint16_t code, const char *message) {
10421042 asyncsrv::lock_guard_type lock (_lock);
1043- if (AsyncWebSocketClient *c = find_connected_client_locked (_clients, id)) {
1043+ if (AsyncWebSocketClient *c = client ( id)) {
10441044 c->close (code, message);
10451045 }
10461046}
@@ -1055,37 +1055,24 @@ void AsyncWebSocket::closeAll(uint16_t code, const char *message) {
10551055}
10561056
10571057void AsyncWebSocket::cleanupClients (uint16_t maxClients) {
1058- std::list<AsyncWebSocketClient> removed_clients;
1059- {
1060- asyncsrv::lock_guard_type lock (_lock);
1061- const size_t connected = std::count_if (std::begin (_clients), std::end (_clients), [](const AsyncWebSocketClient &c) {
1062- return c.status () == WS_CONNECTED ;
1063- });
1064-
1065- if (connected > maxClients) {
1066- const auto connected_iter = std::find_if (std::begin (_clients), std::end (_clients), [](const AsyncWebSocketClient &c) {
1067- return c.status () == WS_CONNECTED ;
1068- });
1069- if (connected_iter != std::end (_clients)) {
1070- async_ws_log_v (" [%s] CLEANUP %" PRIu32 " (%u/%" PRIu16 " )" , _url.c_str (), connected_iter->id (), connected, maxClients);
1071- connected_iter->close ();
1072- }
1073- }
1058+ asyncsrv::lock_guard_type lock (_lock);
1059+ const size_t c = count ();
1060+ if (c > maxClients) {
1061+ async_ws_log_v (" [%s] CLEANUP %" PRIu32 " (%u/%" PRIu16 " )" , _url.c_str (), _clients.front ().id (), c, maxClients);
1062+ _clients.front ().close ();
1063+ }
10741064
1075- for (auto iter = _clients.begin (); iter != _clients.end ();) {
1076- if (iter->shouldBeDeleted ()) {
1077- auto current = iter++;
1078- removed_clients.splice (removed_clients.end (), _clients, current);
1079- } else {
1080- ++iter;
1081- }
1065+ for (auto i = _clients.begin (); i != _clients.end (); ++i) {
1066+ if (i->shouldBeDeleted ()) {
1067+ _clients.erase (i);
1068+ break ;
10821069 }
10831070 }
10841071}
10851072
10861073bool AsyncWebSocket::ping (uint32_t id, const uint8_t *data, size_t len) {
10871074 asyncsrv::lock_guard_type lock (_lock);
1088- AsyncWebSocketClient *c = find_connected_client_locked (_clients, id);
1075+ AsyncWebSocketClient *c = client ( id);
10891076 return c && c->ping (data, len);
10901077}
10911078
@@ -1105,7 +1092,7 @@ AsyncWebSocket::SendStatus AsyncWebSocket::pingAll(const uint8_t *data, size_t l
11051092
11061093bool AsyncWebSocket::text (uint32_t id, const uint8_t *message, size_t len) {
11071094 asyncsrv::lock_guard_type lock (_lock);
1108- AsyncWebSocketClient *c = find_connected_client_locked (_clients, id);
1095+ AsyncWebSocketClient *c = client ( id);
11091096 return c && c->text (makeSharedBuffer (message, len));
11101097}
11111098bool AsyncWebSocket::text (uint32_t id, const char *message, size_t len) {
@@ -1152,7 +1139,7 @@ bool AsyncWebSocket::text(uint32_t id, AsyncWebSocketMessageBuffer *buffer) {
11521139}
11531140bool AsyncWebSocket::text (uint32_t id, AsyncWebSocketSharedBuffer buffer) {
11541141 asyncsrv::lock_guard_type lock (_lock);
1155- AsyncWebSocketClient *c = find_connected_client_locked (_clients, id);
1142+ AsyncWebSocketClient *c = client ( id);
11561143 return c && c->text (buffer);
11571144}
11581145
@@ -1216,7 +1203,7 @@ AsyncWebSocket::SendStatus AsyncWebSocket::textAll(AsyncWebSocketSharedBuffer bu
12161203
12171204bool AsyncWebSocket::binary (uint32_t id, const uint8_t *message, size_t len) {
12181205 asyncsrv::lock_guard_type lock (_lock);
1219- AsyncWebSocketClient *c = find_connected_client_locked (_clients, id);
1206+ AsyncWebSocketClient *c = client ( id);
12201207 return c && c->binary (makeSharedBuffer (message, len));
12211208}
12221209bool AsyncWebSocket::binary (uint32_t id, const char *message, size_t len) {
@@ -1253,7 +1240,7 @@ bool AsyncWebSocket::binary(uint32_t id, AsyncWebSocketMessageBuffer *buffer) {
12531240}
12541241bool AsyncWebSocket::binary (uint32_t id, AsyncWebSocketSharedBuffer buffer) {
12551242 asyncsrv::lock_guard_type lock (_lock);
1256- AsyncWebSocketClient *c = find_connected_client_locked (_clients, id);
1243+ AsyncWebSocketClient *c = client ( id);
12571244 return c && c->binary (buffer);
12581245}
12591246
0 commit comments