SDK v6: Use unique IDs for identifying RGBControllers in SDK protocol

This commit is contained in:
Adam Honse
2026-01-16 12:01:30 -06:00
parent cfd2bc478f
commit 9994de2c14
8 changed files with 921 additions and 300 deletions

View File

@@ -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<RGBController *> 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<RGBController*> 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<std::string> * 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<std::string> * 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;

View File

@@ -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<RGBController *> server_controllers;
std::vector<unsigned int> 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);
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -77,6 +77,8 @@ NetworkServer::NetworkServer(std::vector<RGBController *>& 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<RGBController *>& 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<NetworkControllerID> 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<NetworkServerControllerThread *> 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;

View File

@@ -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<NetworkServerControllerThreadQueueEntry> 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<NetworkControllerID> controller_ids;
std::shared_mutex controller_ids_mutex;
unsigned int controller_next_idx;
std::vector<RGBController *>& controllers;
std::vector<NetworkServerControllerThread *> 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);
};

View File

@@ -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;
}

View File

@@ -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);