From bd68d8801be38ccc0cddcab19603cc69614c2e2c Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Fri, 16 Jan 2026 12:01:30 -0600 Subject: [PATCH] SDK v6: Use unique IDs for identifying RGBControllers in SDK protocol --- NetworkClient.cpp | 432 +++++++++++----- NetworkClient.h | 22 +- NetworkProtocol.cpp | 4 +- NetworkProtocol.h | 2 +- NetworkServer.cpp | 656 ++++++++++++++++++++---- NetworkServer.h | 38 +- RGBController/RGBController_Network.cpp | 37 +- RGBController/RGBController_Network.h | 30 +- 8 files changed, 921 insertions(+), 300 deletions(-) diff --git a/NetworkClient.cpp b/NetworkClient.cpp index 43419d08b..3f1287277 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -45,10 +45,10 @@ NetworkClient::NetworkClient() detection_percent = 100; detection_string = ""; protocol_initialized = false; + protocol_version = 0; server_connected = false; - server_controller_count = 0; - server_controller_count_requested = false; - server_controller_count_received = false; + server_controller_ids_requested = false; + server_controller_ids_received = false; server_protocol_version = 0; server_reinitialize = false; change_in_progress = false; @@ -82,17 +82,6 @@ unsigned short NetworkClient::GetPort() unsigned int NetworkClient::GetProtocolVersion() { - unsigned int protocol_version = 0; - - if(server_protocol_version > OPENRGB_SDK_PROTOCOL_VERSION) - { - protocol_version = OPENRGB_SDK_PROTOCOL_VERSION; - } - else - { - protocol_version = server_protocol_version; - } - return(protocol_version); } @@ -205,50 +194,41 @@ void NetworkClient::StopClient() SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_CLIENT_STOPPED); } -void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) +void NetworkClient::SendRequest_ControllerData(unsigned int dev_id) { NetPacketHeader request_hdr; - unsigned int protocol_version; + /*---------------------------------------------------------*\ + | Clear the controller data received flag | + \*---------------------------------------------------------*/ controller_data_received = false; - memcpy(request_hdr.pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_DATA; - - if(server_protocol_version == 0) + /*---------------------------------------------------------*\ + | Protocol version 0 sends no data, all other protocols | + | send the protocol version | + \*---------------------------------------------------------*/ + if(protocol_version == 0) { - request_hdr.pkt_size = 0; - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send_in_progress.unlock(); + InitNetPacketHeader(&request_hdr, dev_id, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, 0); } else { - request_hdr.pkt_size = sizeof(unsigned int); - - /*-------------------------------------------------------------*\ - | Limit the protocol version to the highest supported by both | - | the client and the server. | - \*-------------------------------------------------------------*/ - if(server_protocol_version > OPENRGB_SDK_PROTOCOL_VERSION) - { - protocol_version = OPENRGB_SDK_PROTOCOL_VERSION; - } - else - { - protocol_version = server_protocol_version; - } - - SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_PROTOCOL_NEGOTIATED); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)&protocol_version, sizeof(unsigned int), MSG_NOSIGNAL); - send_in_progress.unlock(); + InitNetPacketHeader(&request_hdr, dev_id, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, sizeof(protocol_version)); } + + /*---------------------------------------------------------*\ + | Send the packet, including the data field if protocol is | + | greater than 0. | + \*---------------------------------------------------------*/ + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + + if(protocol_version > 0) + { + send(client_sock, (char *)&protocol_version, sizeof(unsigned int), MSG_NOSIGNAL); + } + + send_in_progress.unlock(); } void NetworkClient::SendRequest_RescanDevices() @@ -750,6 +730,8 @@ void NetworkClient::ConnectionThreadFunction() /*-----------------------------------------------------*\ | Request protocol version | \*-----------------------------------------------------*/ + server_protocol_version_received = false; + SendRequest_ProtocolVersion(); /*-----------------------------------------------------*\ @@ -779,6 +761,21 @@ void NetworkClient::ConnectionThreadFunction() } } + /*-------------------------------------------------------------*\ + | Limit the protocol version to the highest supported by both | + | the client and the server. | + \*-------------------------------------------------------------*/ + if(server_protocol_version > OPENRGB_SDK_PROTOCOL_VERSION) + { + protocol_version = OPENRGB_SDK_PROTOCOL_VERSION; + } + else + { + protocol_version = server_protocol_version; + } + + SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_PROTOCOL_NEGOTIATED); + protocol_initialized = true; } @@ -804,11 +801,11 @@ void NetworkClient::ConnectionThreadFunction() /*-----------------------------------------------------*\ | Request the server controller count | \*-----------------------------------------------------*/ - if(!server_controller_count_requested) + if(!server_controller_ids_requested) { - SendRequest_ControllerCount(); + SendRequest_ControllerIDs(); - server_controller_count_requested = true; + server_controller_ids_requested = true; } else { @@ -816,7 +813,7 @@ void NetworkClient::ConnectionThreadFunction() | Wait for the server controller count to be | | received | \*-------------------------------------------------*/ - if(server_controller_count_received) + if(server_controller_ids_received) { /*---------------------------------------------*\ | Once count is received, request controllers | @@ -824,21 +821,34 @@ void NetworkClient::ConnectionThreadFunction() | requested controllers until all controllers | | have been received | \*---------------------------------------------*/ - if(requested_controllers < server_controller_count) + if(requested_controller_index < server_controller_ids.size()) { if(!controller_data_requested) { - printf("Client: Requesting controller %d\r\n", requested_controllers); + /*-------------------------*\ + | Check if this ID already | + | exists, if not, request it| + \*-------------------------*/ + unsigned int id = server_controller_ids[requested_controller_index]; + RGBController * rgb_controller = controller_from_id(id); - controller_data_received = false; - SendRequest_ControllerData(requested_controllers); + if(rgb_controller == NULL) + { + printf("Client: Requesting controller ID %d\r\n", server_controller_ids[requested_controller_index]); - controller_data_requested = true; + controller_data_received = false; + SendRequest_ControllerData(id); + controller_data_requested = true; + } + else + { + controller_data_received = true; + } } if(controller_data_received) { - requested_controllers++; + requested_controller_index++; controller_data_requested = false; } } @@ -909,7 +919,7 @@ void NetworkClient::ListenThreadFunction() { int tmp_bytes_read = 0; - tmp_bytes_read = recv_select(client_sock, (char *)&header.pkt_dev_idx + bytes_read, sizeof(header) - sizeof(header.pkt_magic) - bytes_read, 0); + tmp_bytes_read = recv_select(client_sock, (char *)&header.pkt_dev_id + bytes_read, sizeof(header) - sizeof(header.pkt_magic) - bytes_read, 0); bytes_read += tmp_bytes_read; @@ -951,11 +961,11 @@ void NetworkClient::ListenThreadFunction() switch(header.pkt_id) { case NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: - ProcessReply_ControllerCount(header.pkt_size, data); + ProcessReply_ControllerIDs(header.pkt_size, data); break; case NET_PACKET_ID_REQUEST_CONTROLLER_DATA: - ProcessReply_ControllerData(header.pkt_size, data, header.pkt_dev_idx); + ProcessReply_ControllerData(header.pkt_size, data, header.pkt_dev_id); break; case NET_PACKET_ID_REQUEST_PROTOCOL_VERSION: @@ -1004,7 +1014,7 @@ void NetworkClient::ListenThreadFunction() break; case NET_PACKET_ID_RGBCONTROLLER_SIGNALUPDATE: - ProcessRequest_RGBController_SignalUpdate(header.pkt_size, data, header.pkt_dev_idx); + ProcessRequest_RGBController_SignalUpdate(header.pkt_size, data, header.pkt_dev_id); break; } @@ -1020,10 +1030,9 @@ listen_done: controller_data_requested = false; controller_data_received = false; protocol_initialized = false; - requested_controllers = 0; - server_controller_count = 0; - server_controller_count_requested = false; - server_controller_count_received = false; + requested_controller_index = 0; + server_controller_ids_requested = false; + server_controller_ids_received = false; server_initialized = false; server_connected = false; @@ -1049,21 +1058,7 @@ listen_done: /*---------------------------------------------------------*\ | Private Client functions | \*---------------------------------------------------------*/ -void NetworkClient::ProcessReply_ControllerCount(unsigned int data_size, char * data) -{ - if(data_size == sizeof(unsigned int)) - { - memcpy(&server_controller_count, data, sizeof(unsigned int)); - - server_controller_count_received = true; - requested_controllers = 0; - controller_data_requested = false; - - printf("Client: Received controller count from server: %d\r\n", server_controller_count); - } -} - -void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx) +void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_id) { /*-----------------------------------------------------*\ | Verify the controller description size (first 4 bytes | @@ -1073,7 +1068,10 @@ void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * d { data += sizeof(data_size); - RGBController_Network * new_controller = new RGBController_Network(this, dev_idx); + /*-------------------------------------------------*\ + | Create a new controller from the received data | + \*-------------------------------------------------*/ + RGBController_Network * new_controller = new RGBController_Network(this, dev_id); new_controller->SetDeviceDescription((unsigned char *)data, GetProtocolVersion()); @@ -1083,41 +1081,113 @@ void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * d new_controller->flags &= ~CONTROLLER_FLAG_LOCAL; new_controller->flags |= CONTROLLER_FLAG_REMOTE; - ControllerListMutex.lock(); + /*-------------------------------------------------*\ + | If no controller exists with this ID, add it to | + | the list | + \*-------------------------------------------------*/ + RGBController * existing_controller = controller_from_id(dev_id); - if(dev_idx >= server_controllers.size()) + if(existing_controller == NULL) { - server_controllers.push_back(new_controller); - - /*---------------------------------------------*\ - | Signal list updated callback | - \*---------------------------------------------*/ - SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_DEVICE_LIST_UPDATED); + UpdateDeviceList(new_controller); } + + /*-------------------------------------------------*\ + | Otherwise, update the existing controller with | + | the new controller's data | + \*-------------------------------------------------*/ else { - server_controllers[dev_idx]->active_mode = new_controller->active_mode; - server_controllers[dev_idx]->leds.clear(); - server_controllers[dev_idx]->leds = new_controller->leds; - server_controllers[dev_idx]->colors.clear(); - server_controllers[dev_idx]->colors = new_controller->colors; - for(unsigned int i = 0; i < server_controllers[dev_idx]->zones.size(); i++) - { - server_controllers[dev_idx]->zones[i].leds_count = new_controller->zones[i].leds_count; - server_controllers[dev_idx]->zones[i].segments.clear(); - server_controllers[dev_idx]->zones[i].segments = new_controller->zones[i].segments; - } - server_controllers[dev_idx]->SetupColors(); + existing_controller->active_mode = new_controller->active_mode; + existing_controller->modes.clear(); + existing_controller->modes = new_controller->modes; + existing_controller->leds.clear(); + existing_controller->leds = new_controller->leds; + existing_controller->colors.clear(); + existing_controller->colors = new_controller->colors; + existing_controller->zones.clear(); + existing_controller->zones = new_controller->zones; + existing_controller->SetupColors(); delete new_controller; } - ControllerListMutex.unlock(); - controller_data_received = true; } } +void NetworkClient::ProcessReply_ControllerIDs(unsigned int data_size, char * data_ptr) +{ + unsigned int controller_count = 0; + + /*-----------------------------------------------------*\ + | Validate packet size | + \*-----------------------------------------------------*/ + if(data_size >= sizeof(unsigned int)) + { + /*-------------------------------------------------*\ + | Copy out controller count from data | + \*-------------------------------------------------*/ + memcpy(&controller_count, data_ptr, sizeof(controller_count)); + data_ptr += sizeof(controller_count); + + /*-------------------------------------------------*\ + | On protocol versions >= 6, the server sends a | + | list of unique 32-bit IDs, one per controller. | + \*-------------------------------------------------*/ + if(protocol_version >= 6) + { + /*---------------------------------------------*\ + | Validate protocol >= 6 packet size | + \*---------------------------------------------*/ + if(data_size == (sizeof(controller_count) + (controller_count * sizeof(unsigned int)))) + { + server_controller_ids.clear(); + server_controller_ids.resize(controller_count); + + for(unsigned int controller_id_idx = 0; controller_id_idx < controller_count; controller_id_idx++) + { + memcpy(&server_controller_ids[controller_id_idx], data_ptr, sizeof(server_controller_ids[controller_id_idx])); + data_ptr += sizeof(server_controller_ids[controller_id_idx]); + } + } + else + { + server_controller_ids.clear(); + printf("Client: Received incorrect packet size for controller list, list cleared"); + } + } + /*-------------------------------------------------*\ + | On protocol versions < 6, the server only sends | + | the controller count, using the index as the ID. | + \*-------------------------------------------------*/ + else + { + server_controller_ids.clear(); + server_controller_ids.resize(controller_count); + + for(unsigned int controller_id_idx = 0; controller_id_idx < controller_count; controller_id_idx++) + { + server_controller_ids[controller_id_idx] = controller_id_idx; + } + } + + /*-------------------------------------------------*\ + | Update the device list to remove any controllers | + | no longer in the list | + \*-------------------------------------------------*/ + UpdateDeviceList(NULL); + + /*-------------------------------------------------*\ + | Reset the controller data requested index and | + | flag to begin the controller request cycle | + \*-------------------------------------------------*/ + server_controller_ids_received = true; + requested_controller_index = 0; + controller_data_requested = false; + } +} + void NetworkClient::ProcessReply_ProtocolVersion(unsigned int data_size, char * data) { if(data_size == sizeof(unsigned int)) @@ -1148,35 +1218,18 @@ void NetworkClient::ProcessRequest_DetectionProgressChanged(unsigned int data_si void NetworkClient::ProcessRequest_DeviceListChanged() { - change_in_progress = true; - /*-----------------------------------------------------*\ - | Delete all controllers from the server's controller | - | list | + | For protocol versions < 6, we need to redownload the | + | entire device list, so clear the server IDs and | + | update the device list to erase it. | \*-----------------------------------------------------*/ - ControllerListMutex.lock(); - - std::vector server_controllers_copy = server_controllers; - - server_controllers.clear(); - - /*-----------------------------------------------------*\ - | Signal list updated callback | - \*-----------------------------------------------------*/ - SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_DEVICE_LIST_UPDATED); - - for(size_t server_controller_idx = 0; server_controller_idx < server_controllers_copy.size(); server_controller_idx++) + if(protocol_version < 6) { - delete server_controllers_copy[server_controller_idx]; + server_controller_ids.clear(); + + UpdateDeviceList(NULL); } - ControllerListMutex.unlock(); - - /*-----------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-----------------------------------------------------*/ - SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_DEVICE_LIST_UPDATED); - /*-----------------------------------------------------*\ | Mark server as uninitialized and reset server | | initialization state so that it restarts the list | @@ -1184,24 +1237,25 @@ void NetworkClient::ProcessRequest_DeviceListChanged() \*-----------------------------------------------------*/ controller_data_requested = false; controller_data_received = false; - requested_controllers = 0; - server_controller_count = 0; - server_controller_count_requested = false; - server_controller_count_received = false; + requested_controller_index = 0; + server_controller_ids_requested = false; + server_controller_ids_received = false; server_initialized = false; - - change_in_progress = false; } -void NetworkClient::ProcessRequest_RGBController_SignalUpdate(unsigned int data_size, char * data, unsigned int dev_idx) +void NetworkClient::ProcessRequest_RGBController_SignalUpdate(unsigned int data_size, char * data, unsigned int dev_id) { + RGBController * controller; unsigned int pkt_data_size; unsigned int update_reason; /*-----------------------------------------------------*\ - | Ensure we have this controller in our list | + | Get the controller pointer by ID and ensure it is | + | valid | \*-----------------------------------------------------*/ - if(dev_idx >= server_controllers.size() || server_controllers.size() == 0) + controller = controller_from_id(dev_id); + + if(controller == NULL) { return; } @@ -1237,7 +1291,7 @@ void NetworkClient::ProcessRequest_RGBController_SignalUpdate(unsigned int data_ | UpdateLEDs() sends color description | \*-------------------------------------------------*/ case RGBCONTROLLER_UPDATE_REASON_UPDATELEDS: - server_controllers[dev_idx]->SetColorDescription((unsigned char *)data_ptr, GetProtocolVersion()); + controller->SetColorDescription((unsigned char *)data_ptr, GetProtocolVersion()); break; /*-------------------------------------------------*\ @@ -1252,11 +1306,11 @@ void NetworkClient::ProcessRequest_RGBController_SignalUpdate(unsigned int data_ case RGBCONTROLLER_UPDATE_REASON_HIDDEN: case RGBCONTROLLER_UPDATE_REASON_UNHIDDEN: default: - server_controllers[dev_idx]->SetDeviceDescription((unsigned char *)data_ptr, GetProtocolVersion()); + controller->SetDeviceDescription((unsigned char *)data_ptr, GetProtocolVersion()); break; } - server_controllers[dev_idx]->SignalUpdate(update_reason); + controller->SignalUpdate(update_reason); } void NetworkClient::ProcessRequest_ServerString(unsigned int data_size, char * data) @@ -1281,7 +1335,7 @@ void NetworkClient::SendData_ClientString() send_in_progress.unlock(); } -void NetworkClient::SendRequest_ControllerCount() +void NetworkClient::SendRequest_ControllerIDs() { NetPacketHeader request_hdr; @@ -1307,6 +1361,84 @@ void NetworkClient::SendRequest_ProtocolVersion() send_in_progress.unlock(); } +void NetworkClient::UpdateDeviceList(RGBController* new_controller) +{ + /*-----------------------------------------------------*\ + | Lock the controller list mutex | + \*-----------------------------------------------------*/ + ControllerListMutex.lock(); + + /*-----------------------------------------------------*\ + | Make a copy of the current controllers list | + \*-----------------------------------------------------*/ + std::vector rgb_controllers_copy = server_controllers; + + /*-----------------------------------------------------*\ + | If adding a new controller, add it to the copied list | + \*-----------------------------------------------------*/ + if(new_controller != NULL) + { + rgb_controllers_copy.push_back(new_controller); + } + + /*-----------------------------------------------------*\ + | Clear the controllers list | + \*-----------------------------------------------------*/ + server_controllers.clear(); + + /*-----------------------------------------------------*\ + | Loop through all of the controller IDs | + \*-----------------------------------------------------*/ + for(std::size_t controller_id_idx = 0; controller_id_idx < server_controller_ids.size(); controller_id_idx++) + { + /*-------------------------------------------------*\ + | Loop through all of the controllers in the copied | + | list and see if any match the ID | + \*-------------------------------------------------*/ + std::size_t controller_idx = 0; + bool match = false; + + for(; controller_idx < rgb_controllers_copy.size(); controller_idx++) + { + if(server_controller_ids[controller_id_idx] == ((RGBController_Network*)rgb_controllers_copy[controller_idx])->GetID()) + { + match = true; + break; + } + } + + /*-------------------------------------------------*\ + | If a match was found, push it into the new | + | controller list and remove it from the copy | + \*-------------------------------------------------*/ + if(match) + { + server_controllers.push_back(rgb_controllers_copy[controller_idx]); + rgb_controllers_copy.erase(rgb_controllers_copy.begin() + controller_idx); + } + } + + /*-----------------------------------------------------*\ + | The list has been updated, unlock the mutex | + \*-----------------------------------------------------*/ + ControllerListMutex.unlock(); + + /*-----------------------------------------------------*\ + | Signal list updated callback | + \*-----------------------------------------------------*/ + SignalNetworkClientUpdate(NETWORKCLIENT_UPDATE_REASON_DEVICE_LIST_UPDATED); + + /*-----------------------------------------------------*\ + | At this point, the copied list should contain only | + | controllers no longer in the current list of IDs | + | Delete them | + \*-----------------------------------------------------*/ + for(std::size_t controller_idx = 0; controller_idx < rgb_controllers_copy.size(); controller_idx++) + { + delete rgb_controllers_copy[controller_idx]; + } +} + /*---------------------------------------------------------*\ | Private ProfileManager functions | \*---------------------------------------------------------*/ @@ -1340,7 +1472,7 @@ std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int data_ptr += name_len; } - server_controller_count_received = true; + server_controller_ids_received = true; } else { @@ -1353,6 +1485,22 @@ std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int /*---------------------------------------------------------*\ | Private helper functions | \*---------------------------------------------------------*/ +RGBController * NetworkClient::controller_from_id(unsigned int id) +{ + RGBController * rgb_controller = NULL; + + for(std::size_t controller_idx = 0; controller_idx < server_controllers.size(); controller_idx++) + { + if(((RGBController_Network*)server_controllers[controller_idx])->GetID() == id) + { + rgb_controller = server_controllers[controller_idx]; + break; + } + } + + return(rgb_controller); +} + int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) { fd_set set; diff --git a/NetworkClient.h b/NetworkClient.h index 58eb15dcf..b17c1a486 100644 --- a/NetworkClient.h +++ b/NetworkClient.h @@ -69,7 +69,7 @@ public: void StartClient(); void StopClient(); - void SendRequest_ControllerData(unsigned int dev_idx); + void SendRequest_ControllerData(unsigned int dev_id); void SendRequest_RescanDevices(); /*-----------------------------------------------------*\ @@ -132,8 +132,9 @@ private: bool controller_data_received; bool controller_data_requested; bool protocol_initialized; + unsigned int protocol_version; bool change_in_progress; - unsigned int requested_controllers; + unsigned int requested_controller_index; std::mutex send_in_progress; NetPacketHeader response_header; @@ -157,9 +158,8 @@ private: bool server_connected; bool server_initialized; bool server_reinitialize; - unsigned int server_controller_count; - bool server_controller_count_requested; - bool server_controller_count_received; + bool server_controller_ids_requested; + bool server_controller_ids_received; unsigned int server_protocol_version; bool server_protocol_version_received; @@ -183,6 +183,7 @@ private: \*-----------------------------------------------------*/ std::mutex ControllerListMutex; std::vector server_controllers; + std::vector server_controller_ids; /*-----------------------------------------------------*\ | Detection variables | @@ -204,18 +205,20 @@ private: /*-----------------------------------------------------*\ | Private Client functions | \*-----------------------------------------------------*/ - void ProcessReply_ControllerCount(unsigned int data_size, char * data); - void ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx); + void ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_id); + void ProcessReply_ControllerIDs(unsigned int data_size, char * data_ptr); void ProcessReply_ProtocolVersion(unsigned int data_size, char * data); void ProcessRequest_DetectionProgressChanged(unsigned int data_size, char * data); void ProcessRequest_DeviceListChanged(); - void ProcessRequest_RGBController_SignalUpdate(unsigned int data_size, char * data, unsigned int dev_idx); + void ProcessRequest_RGBController_SignalUpdate(unsigned int data_size, char * data, unsigned int dev_id); void ProcessRequest_ServerString(unsigned int data_size, char * data); void SendData_ClientString(); - void SendRequest_ControllerCount(); + void SendRequest_ControllerIDs(); void SendRequest_ProtocolVersion(); + void UpdateDeviceList(RGBController* new_controller); + /*-----------------------------------------------------*\ | Private ProfileManager functions | \*-----------------------------------------------------*/ @@ -224,5 +227,6 @@ private: /*-----------------------------------------------------*\ | Private helper functions | \*-----------------------------------------------------*/ + RGBController * controller_from_id(unsigned int id); int recv_select(SOCKET s, char *buf, int len, int flags); }; diff --git a/NetworkProtocol.cpp b/NetworkProtocol.cpp index d72c74ab2..58359ec7d 100644 --- a/NetworkProtocol.cpp +++ b/NetworkProtocol.cpp @@ -20,14 +20,14 @@ const char openrgb_sdk_magic[OPENRGB_SDK_MAGIC_SIZE] = { 'O', 'R', 'G', 'B' }; void InitNetPacketHeader ( NetPacketHeader * pkt_hdr, - unsigned int pkt_dev_idx, + unsigned int pkt_dev_id, unsigned int pkt_id, unsigned int pkt_size ) { memcpy(pkt_hdr->pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); - pkt_hdr->pkt_dev_idx = pkt_dev_idx; + pkt_hdr->pkt_dev_id = pkt_dev_id; pkt_hdr->pkt_id = pkt_id; pkt_hdr->pkt_size = pkt_size; } diff --git a/NetworkProtocol.h b/NetworkProtocol.h index 5b74f8440..3e075af68 100644 --- a/NetworkProtocol.h +++ b/NetworkProtocol.h @@ -45,7 +45,7 @@ extern const char openrgb_sdk_magic[OPENRGB_SDK_MAGIC_SIZE]; typedef struct NetPacketHeader { char pkt_magic[4]; /* Magic value "ORGB" identifies beginning of packet */ - unsigned int pkt_dev_idx; /* Device index */ + unsigned int pkt_dev_id; /* Device ID */ unsigned int pkt_id; /* Packet ID */ unsigned int pkt_size; /* Packet size */ } NetPacketHeader; diff --git a/NetworkServer.cpp b/NetworkServer.cpp index 754d9c99e..a519ac6af 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -77,6 +77,8 @@ NetworkServer::NetworkServer(std::vector& control) : controller server_listening = false; legacy_workaround_enabled = false; + controller_next_idx = 0; + for(int i = 0; i < MAXSOCK; i++) { ConnectionThread[i] = nullptr; @@ -85,6 +87,8 @@ NetworkServer::NetworkServer(std::vector& control) : controller plugin_manager = nullptr; profile_manager = nullptr; settings_manager = nullptr; + + DeviceListUpdated(); } NetworkServer::~NetworkServer() @@ -189,6 +193,146 @@ unsigned int NetworkServer::GetClientProtocolVersion(unsigned int client_num) return result; } +/*---------------------------------------------------------*\ +| Signal that device list has been updated | +\*---------------------------------------------------------*/ +void NetworkServer::DeviceListUpdated() +{ + controller_ids_mutex.lock(); + + /*-----------------------------------------------------*\ + | Create a copy of the current controller IDs list | + \*-----------------------------------------------------*/ + std::vector controller_ids_old = controller_ids; + + /*-----------------------------------------------------*\ + | Clear the current controller IDs list | + \*-----------------------------------------------------*/ + controller_ids.clear(); + + /*-----------------------------------------------------*\ + | Resize controller IDs list to be the same size as the | + | controllers list | + \*-----------------------------------------------------*/ + controller_ids.resize(controllers.size()); + + /*-----------------------------------------------------*\ + | Loop through the controllers list and find the ID for | + | each controller, adding it to the IDs list. | + \*-----------------------------------------------------*/ + for(std::size_t controller_idx = 0; controller_idx < controller_ids.size(); controller_idx++) + { + bool match = false; + for(std::size_t controller_id_idx = 0; controller_id_idx < controller_ids_old.size(); controller_id_idx++) + { + if(controllers[controller_idx] == controller_ids_old[controller_id_idx].controller) + { + controller_ids[controller_idx] = controller_ids_old[controller_id_idx]; + match = true; + + break; + } + } + + /*-------------------------------------------------*\ + | If an ID does not already exist, create a new ID | + | for this controller | + \*-------------------------------------------------*/ + if(!match) + { + NetworkControllerID new_controller_id; + + new_controller_id.controller = controllers[controller_idx]; + new_controller_id.id = controller_next_idx; + + controller_next_idx++; + + controller_ids[controller_idx] = new_controller_id; + } + } + + controller_threads_mutex.lock(); + + /*-----------------------------------------------------*\ + | Create a copy of the current controller threads list | + \*-----------------------------------------------------*/ + std::vector controller_threads_old = controller_threads; + + /*-----------------------------------------------------*\ + | Clear the current controller threads list | + \*-----------------------------------------------------*/ + controller_threads.clear(); + + /*-----------------------------------------------------*\ + | Resize the controller threads so that there is one | + | thread per controller ID | + \*-----------------------------------------------------*/ + controller_threads.resize(controller_ids.size()); + + /*-----------------------------------------------------*\ + | Loop through the controller IDs list and find the | + | thread for each ID, adding it to the threads list. | + \*-----------------------------------------------------*/ + for(std::size_t controller_id_idx = 0; controller_id_idx < controller_ids.size(); controller_id_idx++) + { + std::size_t controller_thread_old_idx = 0; + bool match = false; + + for(; controller_thread_old_idx < controller_threads_old.size(); controller_thread_old_idx++) + { + if(controller_ids[controller_id_idx].id == controller_threads_old[controller_thread_old_idx]->id) + { + match = true; + + break; + } + } + + /*-----------------------------------------------------*\ + | If an existing thread was found with this ID, copy it | + | into the new list at the new index. | + \*-----------------------------------------------------*/ + if(match) + { + controller_threads[controller_id_idx] = controller_threads_old[controller_thread_old_idx]; + controller_threads[controller_id_idx]->index = controller_id_idx; + + controller_threads_old.erase(controller_threads_old.begin() + controller_thread_old_idx); + } + /*-----------------------------------------------------*\ + | Otherwise, if an existing thread was not found with | + |this ID, create a new one. | + \*-----------------------------------------------------*/ + else + { + NetworkServerControllerThread * new_controller_thread = new NetworkServerControllerThread; + + new_controller_thread->id = controller_ids[controller_id_idx].id; + new_controller_thread->index = controller_id_idx; + new_controller_thread->online = true; + new_controller_thread->thread = new std::thread(&NetworkServer::ControllerListenThread, this, new_controller_thread); + + controller_threads[controller_id_idx] = new_controller_thread; + } + } + + /*-----------------------------------------------------*\ + | Loop through the remaining threads in the old list | + | and shut them down, their controller IDs are no | + | longer valid. | + \*-----------------------------------------------------*/ + for(std::size_t controller_thread_old_idx = 0; controller_thread_old_idx < controller_threads_old.size(); controller_thread_old_idx++) + { + controller_threads_old[controller_thread_old_idx]->online = false; + controller_threads_old[controller_thread_old_idx]->start_cv.notify_all(); + controller_threads_old[controller_thread_old_idx]->thread->join(); + delete controller_threads_old[controller_thread_old_idx]->thread; + } + + controller_threads_mutex.unlock(); + controller_ids_mutex.unlock(); +} + /*---------------------------------------------------------*\ | Callback functions | \*---------------------------------------------------------*/ @@ -197,6 +341,7 @@ void NetworkServer::SignalResourceManagerUpdate(unsigned int update_reason) switch(update_reason) { case RESOURCEMANAGER_UPDATE_REASON_DEVICE_LIST_UPDATED: + DeviceListUpdated(); SignalDeviceListUpdated(); break; @@ -652,28 +797,26 @@ void NetworkServer::ControllerListenThread(NetworkServerControllerThread * this_ this_thread->queue.pop(); this_thread->queue_mutex.unlock(); - switch(queue_entry.id) + switch(queue_entry.pkt_id) { case NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS: - ProcessRequest_RGBController_UpdateLEDs(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); + ProcessRequest_RGBController_UpdateLEDs(this_thread->id, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); break; case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS: - ProcessRequest_RGBController_UpdateZoneLEDs(this_thread->index, (unsigned char *)queue_entry.data); + ProcessRequest_RGBController_UpdateZoneLEDs(this_thread->id, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); break; case NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE: - ProcessRequest_RGBController_UpdateSaveMode(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); - controllers[this_thread->index]->UpdateMode(); + ProcessRequest_RGBController_UpdateSaveMode(this_thread->id, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version, false); break; case NET_PACKET_ID_RGBCONTROLLER_SAVEMODE: - ProcessRequest_RGBController_UpdateSaveMode(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); - controllers[this_thread->index]->SaveMode(); + ProcessRequest_RGBController_UpdateSaveMode(this_thread->id, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version, true); break; case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE: - ProcessRequest_RGBController_UpdateZoneMode(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); + ProcessRequest_RGBController_UpdateZoneMode(this_thread->id, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); break; } @@ -730,7 +873,7 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) { int tmp_bytes_read = 0; - tmp_bytes_read = recv_select(client_sock, (char *)&header.pkt_dev_idx + bytes_read, sizeof(header) - sizeof(header.pkt_magic) - bytes_read, 0); + tmp_bytes_read = recv_select(client_sock, (char *)&header.pkt_dev_id + bytes_read, sizeof(header) - sizeof(header.pkt_magic) - bytes_read, 0); bytes_read += tmp_bytes_read; @@ -776,19 +919,32 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) | Network requests | \*-------------------------------------------------*/ case NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: - SendReply_ControllerCount(client_sock); + SendReply_ControllerCount(client_sock, client_info->client_protocol_version); break; case NET_PACKET_ID_REQUEST_CONTROLLER_DATA: { - unsigned int protocol_version = 0; - - if(header.pkt_size == sizeof(unsigned int)) + /*-------------------------------------*\ + | Protocol versions < 6 sent the client | + | protocol version with this request, | + | versions 6+ use the stored negotiated | + | protocol version instead. | + \*-------------------------------------*/ + if(client_info->client_protocol_version < 6) { - memcpy(&protocol_version, data, sizeof(unsigned int)); - } + unsigned int protocol_version = 0; - SendReply_ControllerData(client_sock, header.pkt_dev_idx, protocol_version); + if(header.pkt_size == sizeof(unsigned int)) + { + memcpy(&protocol_version, data, sizeof(unsigned int)); + } + + SendReply_ControllerData(client_sock, header.pkt_dev_id, protocol_version); + } + else + { + SendReply_ControllerData(client_sock, header.pkt_dev_id, client_info->client_protocol_version); + } } break; @@ -932,7 +1088,7 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) unsigned int plugin_pkt_id = *((unsigned int*)(data)); unsigned int plugin_pkt_size = header.pkt_size - (sizeof(unsigned int)); unsigned char* plugin_data = (unsigned char*)(data + sizeof(unsigned int)); - unsigned char* output = plugin_manager->OnSDKCommand(header.pkt_dev_idx, plugin_pkt_id, plugin_data, &plugin_pkt_size); + unsigned char* output = plugin_manager->OnSDKCommand(header.pkt_dev_id, plugin_pkt_id, plugin_data, &plugin_pkt_size); if(output != nullptr) { @@ -995,21 +1151,15 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) | RGBController functions | \*-------------------------------------------------*/ case NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE: - if(data == NULL) + if((data != NULL) + && (header.pkt_size == (2 * sizeof(int)))) { - break; + ProcessRequest_RGBController_ResizeZone(header.pkt_dev_id, (unsigned char *)data, client_info->client_protocol_version); } - - if((header.pkt_dev_idx < controllers.size()) && (header.pkt_size == (2 * sizeof(int)))) + else { - int zone; - int new_size; - - memcpy(&zone, data, sizeof(int)); - memcpy(&new_size, data + sizeof(int), sizeof(int)); - - controllers[header.pkt_dev_idx]->ResizeZone(zone, new_size); - profile_manager->SaveSizes(); + LOG_ERROR("[NetworkServer] ResizeZone packet has invalid size. Packet size: %d", header.pkt_size); + goto listen_done; } break; @@ -1018,11 +1168,6 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) case NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE: case NET_PACKET_ID_RGBCONTROLLER_SAVEMODE: case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE: - if(data == NULL) - { - break; - } - /*-----------------------------------------*\ | Verify the color description size (first | | 4 bytes of data) matches the packet size | @@ -1035,111 +1180,124 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) | of SDK applications that didn't properly | | implement the size field. | \*-----------------------------------------*/ - if((header.pkt_size == *((unsigned int*)data)) - || ((client_info->client_protocol_version <= 4) - && (legacy_workaround_enabled))) + if((data != NULL) + && ((header.pkt_size == *((unsigned int*)data)) + || ((client_info->client_protocol_version <= 4) + && (legacy_workaround_enabled)))) { - if(header.pkt_dev_idx < controllers.size()) + /*-------------------------------------*\ + | Find the controller thread matching | + | this ID | + \*-------------------------------------*/ + std::size_t controller_thread_idx = 0; + bool match = false; + + controller_threads_mutex.lock_shared(); + + for(; controller_thread_idx < controller_threads.size(); controller_thread_idx++) { - if(controller_threads.size() < controllers.size()) + if(client_info->client_protocol_version >= 6) { - for(std::size_t controller_idx = controller_threads.size(); controller_idx < controllers.size(); controller_idx++) + if(controller_threads[controller_thread_idx]->id == header.pkt_dev_id) { - NetworkServerControllerThread * new_controller_thread = new NetworkServerControllerThread; - - new_controller_thread->index = controller_idx; - new_controller_thread->online = true; - new_controller_thread->thread = new std::thread(&NetworkServer::ControllerListenThread, this, new_controller_thread); - - controller_threads.push_back(new_controller_thread); + match = true; + break; } } + else + { + if(controller_threads[controller_thread_idx]->index == header.pkt_dev_id) + { + match = true; + break; + } + } + } + + /*-------------------------------------*\ + | If this ID exists in the list, queue | + | the message to the matching thread | + \*-------------------------------------*/ + if(match) + { + controller_threads[controller_thread_idx]->queue_mutex.lock(); - controller_threads[header.pkt_dev_idx]->queue_mutex.lock(); NetworkServerControllerThreadQueueEntry new_entry; new_entry.data = data; - new_entry.id = header.pkt_id; + new_entry.pkt_id = header.pkt_id; new_entry.size = header.pkt_size; new_entry.client_protocol_version = client_info->client_protocol_version; - controller_threads[header.pkt_dev_idx]->queue.push(new_entry); - controller_threads[header.pkt_dev_idx]->queue_mutex.unlock(); - controller_threads[header.pkt_dev_idx]->start_cv.notify_all(); + controller_threads[controller_thread_idx]->queue.push(new_entry); + controller_threads[controller_thread_idx]->queue_mutex.unlock(); + controller_threads[controller_thread_idx]->start_cv.notify_all(); delete_data = false; } + + controller_threads_mutex.unlock_shared(); } else { - LOG_ERROR("[NetworkServer] RGBController packet with ID %d has invalid size. Packet size: %d, Data size: %d", header.pkt_id, header.pkt_size, *((unsigned int*)data)); + LOG_ERROR("[NetworkServer] RGBController packet with ID %d has invalid size. Packet size: %d,", header.pkt_id, header.pkt_size); goto listen_done; } break; case NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED: - if(data == NULL) - { - break; - } - /*-----------------------------------------*\ | Verify the single LED color description | | size (8 bytes) matches the packet size in | | the header | \*-----------------------------------------*/ - if(header.pkt_size == (sizeof(int) + sizeof(RGBColor))) + if((data != NULL) + && (header.pkt_size == (sizeof(int) + sizeof(RGBColor)))) { - if(header.pkt_dev_idx < controllers.size()) - { - ProcessRequest_RGBController_UpdateSingleLED(header.pkt_dev_idx, (unsigned char *)data); - } + ProcessRequest_RGBController_UpdateSingleLED(header.pkt_dev_id, (unsigned char *)data, client_info->client_protocol_version); } else { - LOG_ERROR("[NetworkServer] UpdateSingleLED packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, (sizeof(int) + sizeof(RGBColor))); + LOG_ERROR("[NetworkServer] UpdateSingleLED packet has invalid size. Packet size: %d", header.pkt_size); goto listen_done; } break; case NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE: - if(header.pkt_dev_idx < controllers.size()) - { - controllers[header.pkt_dev_idx]->SetCustomMode(); - } + ProcessRequest_RGBController_SetCustomMode(header.pkt_dev_id, client_info->client_protocol_version); break; case NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS: - if(data == NULL) + /*-----------------------------------------*\ + | Verify the data size | + \*-----------------------------------------*/ + if((data != NULL) + && (header.pkt_size == sizeof(int))) { - break; + ProcessRequest_RGBController_ClearSegments(header.pkt_dev_id, (unsigned char *)data, client_info->client_protocol_version); } - - if((header.pkt_dev_idx < controllers.size()) && (header.pkt_size == sizeof(int))) + else { - int zone; - - memcpy(&zone, data, sizeof(int)); - - controllers[header.pkt_dev_idx]->ClearSegments(zone); - profile_manager->SaveSizes(); + LOG_ERROR("[NetworkServer] ClearSegments packet has invalid size. Packet size: %d", header.pkt_size); + goto listen_done; } break; case NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT: + /*-----------------------------------------*\ + | Verify the segment description size | + | (first 4 bytes of data) matches the | + | packet size in the header | + \*-----------------------------------------*/ + if((data != NULL) + && (header.pkt_size >= sizeof(unsigned int)) + && (header.pkt_size == *((unsigned int*)data))) { - /*-------------------------------------*\ - | Verify the segment description size | - | (first 4 bytes of data) matches the | - | packet size in the header | - \*-------------------------------------*/ - if(header.pkt_size == *((unsigned int*)data)) - { - if(header.pkt_dev_idx < controllers.size()) - { - ProcessRequest_RGBController_AddSegment(header.pkt_dev_idx, (unsigned char *)data, client_info->client_protocol_version); - profile_manager->SaveSizes(); - } - } + ProcessRequest_RGBController_AddSegment(header.pkt_dev_id, (unsigned char *)data, client_info->client_protocol_version); + } + else + { + LOG_ERROR("[NetworkServer] AddSegment packet has invalid size. Packet size: %d", header.pkt_size); + goto listen_done; } break; } @@ -1233,12 +1391,31 @@ void NetworkServer::ProcessRequest_RescanDevices() ResourceManager::get()->RescanDevices(); } -void NetworkServer::ProcessRequest_RGBController_AddSegment(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +void NetworkServer::ProcessRequest_RGBController_AddSegment(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + int zone_idx; + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + + /*-----------------------------------------------------*\ + | Skip data size | + \*-----------------------------------------------------*/ + data_ptr += sizeof(unsigned int); + /*-----------------------------------------------------*\ | Copy in zone index | \*-----------------------------------------------------*/ - unsigned int zone_idx; memcpy(&zone_idx, data_ptr, sizeof(zone_idx)); data_ptr += sizeof(zone_idx); @@ -1250,10 +1427,124 @@ void NetworkServer::ProcessRequest_RGBController_AddSegment(std::size_t controll data_ptr = controllers[controller_idx]->SetSegmentDescription(data_ptr, &new_segment, protocol_version); controllers[controller_idx]->AddSegment(zone_idx, new_segment); + + /*-----------------------------------------------------*\ + | Save sizes | + \*-----------------------------------------------------*/ + profile_manager->SaveSizes(); } -void NetworkServer::ProcessRequest_RGBController_UpdateLEDs(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +void NetworkServer::ProcessRequest_RGBController_ClearSegments(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + int zone_idx; + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + + /*-----------------------------------------------------*\ + | Copy in zone index | + \*-----------------------------------------------------*/ + memcpy(&zone_idx, data_ptr, sizeof(zone_idx)); + + /*-----------------------------------------------------*\ + | Call ClearSegments on the given controller | + \*-----------------------------------------------------*/ + controllers[controller_idx]->ClearSegments(zone_idx); + + /*-----------------------------------------------------*\ + | Save sizes | + \*-----------------------------------------------------*/ + profile_manager->SaveSizes(); +} + +void NetworkServer::ProcessRequest_RGBController_ResizeZone(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + int new_size; + int zone_idx; + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + + /*-----------------------------------------------------*\ + | Copy in zone index | + \*-----------------------------------------------------*/ + memcpy(&zone_idx, data_ptr, sizeof(zone_idx)); + data_ptr += sizeof(zone_idx); + + /*-----------------------------------------------------*\ + | Copy in new zone size | + \*-----------------------------------------------------*/ + memcpy(&new_size, data_ptr, sizeof(new_size)); + + /*-----------------------------------------------------*\ + | Call ResizeZone on the given controller | + \*-----------------------------------------------------*/ + controllers[controller_idx]->ResizeZone(zone_idx, new_size); + + /*-----------------------------------------------------*\ + | Save sizes | + \*-----------------------------------------------------*/ + profile_manager->SaveSizes(); +} + +void NetworkServer::ProcessRequest_RGBController_SetCustomMode(unsigned int controller_id, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + + /*-----------------------------------------------------*\ + | Call SetCustomMode on the given controller | + \*-----------------------------------------------------*/ + controllers[controller_idx]->SetCustomMode(); +} + +void NetworkServer::ProcessRequest_RGBController_UpdateLEDs(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + /*-----------------------------------------------------*\ | Skip over data size | \*-----------------------------------------------------*/ @@ -1275,13 +1566,27 @@ void NetworkServer::ProcessRequest_RGBController_UpdateLEDs(std::size_t controll controllers[controller_idx]->AccessMutex.unlock(); /*-----------------------------------------------------*\ - | Update LEDs | + | Call UpdateLEDs on the given controller | \*-----------------------------------------------------*/ controllers[controller_idx]->UpdateLEDs(); } -void NetworkServer::ProcessRequest_RGBController_UpdateSaveMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +void NetworkServer::ProcessRequest_RGBController_UpdateSaveMode(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version, bool save_mode) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + /*-----------------------------------------------------*\ | Lock access mutex | \*-----------------------------------------------------*/ @@ -1325,10 +1630,37 @@ void NetworkServer::ProcessRequest_RGBController_UpdateSaveMode(std::size_t cont | Unlock access mutex | \*-----------------------------------------------------*/ controllers[controller_idx]->AccessMutex.unlock(); + + /*-----------------------------------------------------*\ + | Call either SaveMode or UpdateMode on the given | + | controller | + \*-----------------------------------------------------*/ + if(save_mode) + { + controllers[controller_idx]->SaveMode(); + } + else + { + controllers[controller_idx]->UpdateMode(); + } } -void NetworkServer::ProcessRequest_RGBController_UpdateSingleLED(std::size_t controller_idx, unsigned char * data_ptr) +void NetworkServer::ProcessRequest_RGBController_UpdateSingleLED(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + /*-----------------------------------------------------*\ | Lock access mutex | \*-----------------------------------------------------*/ @@ -1376,8 +1708,22 @@ void NetworkServer::ProcessRequest_RGBController_UpdateSingleLED(std::size_t con controllers[controller_idx]->UpdateSingleLED(led_idx); } -void NetworkServer::ProcessRequest_RGBController_UpdateZoneLEDs(std::size_t controller_idx, unsigned char* data_ptr) +void NetworkServer::ProcessRequest_RGBController_UpdateZoneLEDs(unsigned int controller_id, unsigned char* data_ptr, unsigned int protocol_version) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + /*-----------------------------------------------------*\ | Skip over data size | \*-----------------------------------------------------*/ @@ -1443,8 +1789,22 @@ void NetworkServer::ProcessRequest_RGBController_UpdateZoneLEDs(std::size_t cont controllers[controller_idx]->UpdateZoneLEDs(zone_idx); } -void NetworkServer::ProcessRequest_RGBController_UpdateZoneMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +void NetworkServer::ProcessRequest_RGBController_UpdateZoneMode(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version) { + /*-----------------------------------------------------*\ + | Convert ID to index | + \*-----------------------------------------------------*/ + bool idx_valid; + unsigned int controller_idx = index_from_id(controller_id, protocol_version, &idx_valid); + + /*-----------------------------------------------------*\ + | If controller ID is invalid, return | + \*-----------------------------------------------------*/ + if(!idx_valid) + { + return; + } + /*-----------------------------------------------------*\ | Lock access mutex | \*-----------------------------------------------------*/ @@ -1505,24 +1865,66 @@ void NetworkServer::ProcessRequest_RGBController_UpdateZoneMode(std::size_t cont controllers[controller_idx]->UpdateZoneMode(zone_idx); } -void NetworkServer::SendReply_ControllerCount(SOCKET client_sock) +void NetworkServer::SendReply_ControllerCount(SOCKET client_sock, unsigned int protocol_version) { + controller_ids_mutex.lock_shared(); + NetPacketHeader reply_hdr; - unsigned int reply_data; + unsigned int controller_count = (unsigned int)controller_ids.size(); + unsigned int data_size = 0; - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_CONTROLLER_COUNT, sizeof(unsigned int)); + /*-----------------------------------------------------*\ + | Determine data size | + \*-----------------------------------------------------*/ + data_size += sizeof(controller_count); - reply_data = (unsigned int)controllers.size(); + /*-----------------------------------------------------*\ + | Starting with protocol > 6, a list of controller IDs | + | is sent in addition to the size | + \*-----------------------------------------------------*/ + if(protocol_version >= 6) + { + data_size += (controller_count * sizeof(unsigned int)); + } + + unsigned char * data_buf = new unsigned char[data_size]; + unsigned char * data_ptr = data_buf; + + memcpy(data_ptr, &controller_count, sizeof(controller_count)); + data_ptr += sizeof(controller_count); + + if(protocol_version >= 6) + { + for(unsigned int controller_id_idx = 0; controller_id_idx < controller_count; controller_id_idx++) + { + memcpy(data_ptr, &controller_ids[controller_id_idx].id, sizeof(controller_ids[controller_id_idx].id)); + data_ptr += sizeof(controller_ids[controller_id_idx].id); + } + } + + controller_ids_mutex.unlock_shared(); + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_CONTROLLER_COUNT, data_size); + + controller_count = (unsigned int)controllers.size(); send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); - send(client_sock, (const char *)&reply_data, sizeof(unsigned int), 0); + send(client_sock, (const char *)data_buf, data_size, 0); send_in_progress.unlock(); + + delete[] data_buf; } -void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int dev_idx, unsigned int protocol_version) +void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int dev_id, unsigned int protocol_version) { - if(dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Convert ID to index | + \*---------------------------------------------------------*/ + bool idx_valid; + unsigned int dev_idx = index_from_id(dev_id, protocol_version, &idx_valid); + + if(idx_valid && (dev_idx < controller_ids.size())) { NetPacketHeader reply_hdr; unsigned char * reply_data; @@ -1564,7 +1966,7 @@ void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int de /*-----------------------------------------------------*\ | Initialize packet header | \*-----------------------------------------------------*/ - InitNetPacketHeader(&reply_hdr, dev_idx, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, reply_size); + InitNetPacketHeader(&reply_hdr, dev_id, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, reply_size); /*-----------------------------------------------------*\ | Send packet | @@ -2020,6 +2422,46 @@ int NetworkServer::accept_select(int sockfd) } } +unsigned int NetworkServer::index_from_id(unsigned int id, unsigned int protocol_version, bool* index_valid) +{ + /*-----------------------------------------------------*\ + | For protocol < 6, the ID is the index | + \*-----------------------------------------------------*/ + unsigned int index = id; + *index_valid = true; + + /*-----------------------------------------------------*\ + | For protocol >= 6, look up the ID from the index | + \*-----------------------------------------------------*/ + if(protocol_version >= 6) + { + controller_ids_mutex.lock_shared(); + + *index_valid = false; + + for(std::size_t controller_id_idx = 0; controller_id_idx < controller_ids.size(); controller_id_idx++) + { + if(controller_ids[controller_id_idx].id == id) + { + index = controller_id_idx; + *index_valid = true; + break; + } + } + + controller_ids_mutex.unlock_shared(); + } + else + { + if(index >= controllers.size()) + { + *index_valid = false; + } + } + + return(index); +} + int NetworkServer::recv_select(SOCKET s, char *buf, int len, int flags) { fd_set set; diff --git a/NetworkServer.h b/NetworkServer.h index 3086b3fa8..72d70c651 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -33,13 +33,14 @@ typedef void (*NetServerCallback)(void *); typedef struct { char * data; - unsigned int id; + unsigned int pkt_id; unsigned int size; unsigned int client_protocol_version; } NetworkServerControllerThreadQueueEntry; typedef struct { + unsigned int id; unsigned int index; std::queue queue; std::mutex queue_mutex; @@ -62,6 +63,12 @@ public: std::string client_ip; }; +typedef struct +{ + RGBController * controller; + unsigned int id; +} NetworkControllerID; + class NetworkServer { public: @@ -80,6 +87,11 @@ public: const char * GetClientIP(unsigned int client_num); unsigned int GetClientProtocolVersion(unsigned int client_num); + /*-----------------------------------------------------*\ + | Signal that device list has been updated | + \*-----------------------------------------------------*/ + void DeviceListUpdated(); + /*-----------------------------------------------------*\ | Callback functions | \*-----------------------------------------------------*/ @@ -131,8 +143,12 @@ private: /*-----------------------------------------------------*\ | Server controller list | \*-----------------------------------------------------*/ + std::vector controller_ids; + std::shared_mutex controller_ids_mutex; + unsigned int controller_next_idx; std::vector& controllers; std::vector controller_threads; + std::shared_mutex controller_threads_mutex; /*-----------------------------------------------------*\ | Server clients | @@ -194,15 +210,18 @@ private: void ProcessRequest_ClientString(SOCKET client_sock, unsigned int data_size, char * data); void ProcessRequest_RescanDevices(); - void ProcessRequest_RGBController_AddSegment(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); - void ProcessRequest_RGBController_UpdateLEDs(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); - void ProcessRequest_RGBController_UpdateSaveMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); - void ProcessRequest_RGBController_UpdateSingleLED(std::size_t controller_idx, unsigned char * data_ptr); - void ProcessRequest_RGBController_UpdateZoneLEDs(std::size_t controller_idx, unsigned char* data_ptr); - void ProcessRequest_RGBController_UpdateZoneMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_AddSegment(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_ClearSegments(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_ResizeZone(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_SetCustomMode(unsigned int controller_id, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateLEDs(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateSaveMode(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version, bool save_mode); + void ProcessRequest_RGBController_UpdateSingleLED(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateZoneLEDs(unsigned int controller_id, unsigned char* data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateZoneMode(unsigned int controller_id, unsigned char * data_ptr, unsigned int protocol_version); - void SendReply_ControllerCount(SOCKET client_sock); - void SendReply_ControllerData(SOCKET client_sock, unsigned int dev_idx, unsigned int protocol_version); + void SendReply_ControllerCount(SOCKET client_sock, unsigned int protocol_version); + void SendReply_ControllerData(SOCKET client_sock, unsigned int dev_id, unsigned int protocol_version); void SendReply_ProtocolVersion(SOCKET client_sock); void SendReply_ServerString(SOCKET client_sock); @@ -219,5 +238,6 @@ private: | Private helper functions | \*-----------------------------------------------------*/ int accept_select(int sockfd); + unsigned int index_from_id(unsigned int id, unsigned int protocol_version, bool* index_valid); int recv_select(SOCKET s, char *buf, int len, int flags); }; diff --git a/RGBController/RGBController_Network.cpp b/RGBController/RGBController_Network.cpp index 63975c6e6..f017128dc 100644 --- a/RGBController/RGBController_Network.cpp +++ b/RGBController/RGBController_Network.cpp @@ -14,17 +14,22 @@ #include "RGBController_Network.h" -RGBController_Network::RGBController_Network(NetworkClient * client_ptr, unsigned int dev_idx_val) +RGBController_Network::RGBController_Network(NetworkClient * client_ptr, unsigned int dev_id_val) { client = client_ptr; - dev_idx = dev_idx_val; + dev_id = dev_id_val; +} + +unsigned int RGBController_Network::GetID() +{ + return(dev_id); } void RGBController_Network::ClearSegments(int zone) { - client->SendRequest_RGBController_ClearSegments(dev_idx, zone); + client->SendRequest_RGBController_ClearSegments(dev_id, zone); - client->SendRequest_ControllerData(dev_idx); + client->SendRequest_ControllerData(dev_id); client->WaitOnControllerData(); } @@ -75,19 +80,19 @@ void RGBController_Network::AddSegment(int zone, segment new_segment) \*-----------------------------------------------------*/ AccessMutex.unlock_shared(); - client->SendRequest_RGBController_AddSegment(dev_idx, data_buf, data_size); + client->SendRequest_RGBController_AddSegment(dev_id, data_buf, data_size); delete[] data_buf; - client->SendRequest_ControllerData(dev_idx); + client->SendRequest_ControllerData(dev_id); client->WaitOnControllerData(); } void RGBController_Network::ResizeZone(int zone, int new_size) { - client->SendRequest_RGBController_ResizeZone(dev_idx, zone, new_size); + client->SendRequest_RGBController_ResizeZone(dev_id, zone, new_size); - client->SendRequest_ControllerData(dev_idx); + client->SendRequest_ControllerData(dev_id); client->WaitOnControllerData(); } @@ -98,7 +103,7 @@ void RGBController_Network::DeviceUpdateLEDs() memcpy(&size, &data[0], sizeof(unsigned int)); - client->SendRequest_RGBController_UpdateLEDs(dev_idx, data, size); + client->SendRequest_RGBController_UpdateLEDs(dev_id, data, size); delete[] data; } @@ -110,7 +115,7 @@ void RGBController_Network::DeviceUpdateZoneLEDs(int zone) memcpy(&size, &data[0], sizeof(unsigned int)); - client->SendRequest_RGBController_UpdateZoneLEDs(dev_idx, data, size); + client->SendRequest_RGBController_UpdateZoneLEDs(dev_id, data, size); delete[] data; } @@ -119,16 +124,16 @@ void RGBController_Network::DeviceUpdateSingleLED(int led) { unsigned char * data = CreateUpdateSingleLEDPacket(led); - client->SendRequest_RGBController_UpdateSingleLED(dev_idx, data, sizeof(int) + sizeof(RGBColor)); + client->SendRequest_RGBController_UpdateSingleLED(dev_id, data, sizeof(int) + sizeof(RGBColor)); delete[] data; } void RGBController_Network::SetCustomMode() { - client->SendRequest_RGBController_SetCustomMode(dev_idx); + client->SendRequest_RGBController_SetCustomMode(dev_id); - client->SendRequest_ControllerData(dev_idx); + client->SendRequest_ControllerData(dev_id); client->WaitOnControllerData(); } @@ -139,7 +144,7 @@ void RGBController_Network::DeviceUpdateMode() data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion()); - client->SendRequest_RGBController_UpdateMode(dev_idx, data, size); + client->SendRequest_RGBController_UpdateMode(dev_id, data, size); delete[] data; } @@ -151,7 +156,7 @@ void RGBController_Network::DeviceUpdateZoneMode(int zone) data = CreateUpdateZoneModePacket(zone, zones[zone].active_mode, &size, client->GetProtocolVersion()); - client->SendRequest_RGBController_UpdateZoneMode(dev_idx, data, size); + client->SendRequest_RGBController_UpdateZoneMode(dev_id, data, size); delete[] data; } @@ -163,7 +168,7 @@ void RGBController_Network::DeviceSaveMode() data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion()); - client->SendRequest_RGBController_SaveMode(dev_idx, data, size); + client->SendRequest_RGBController_SaveMode(dev_id, data, size); delete[] data; } diff --git a/RGBController/RGBController_Network.h b/RGBController/RGBController_Network.h index f2a97d3fe..61491abbb 100644 --- a/RGBController/RGBController_Network.h +++ b/RGBController/RGBController_Network.h @@ -20,25 +20,27 @@ class RGBController_Network : public RGBController public: RGBController_Network(NetworkClient * client_ptr, unsigned int dev_idx_val); - void ClearSegments(int zone); - void AddSegment(int zone, segment new_segment); - void ResizeZone(int zone, int new_size); + unsigned int GetID(); - void DeviceUpdateLEDs(); - void DeviceUpdateZoneLEDs(int zone); - void DeviceUpdateSingleLED(int led); + void ClearSegments(int zone); + void AddSegment(int zone, segment new_segment); + void ResizeZone(int zone, int new_size); - void SetCustomMode(); - void DeviceUpdateMode(); - void DeviceUpdateZoneMode(int zone); - void DeviceSaveMode(); + void DeviceUpdateLEDs(); + void DeviceUpdateZoneLEDs(int zone); + void DeviceUpdateSingleLED(int led); - void UpdateLEDs(); - void UpdateMode(); + void SetCustomMode(); + void DeviceUpdateMode(); + void DeviceUpdateZoneMode(int zone); + void DeviceSaveMode(); + + void UpdateLEDs(); + void UpdateMode(); private: - NetworkClient * client; - unsigned int dev_idx; + NetworkClient * client; + unsigned int dev_id; unsigned char * CreateUpdateLEDsPacket(unsigned int protocol_version); unsigned char * CreateUpdateModePacket(int mode_idx, unsigned int* size, unsigned int protocol_version);