diff --git a/NetworkServer.cpp b/NetworkServer.cpp index 2bd0ef9c..073f1f5d 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -1,9 +1,66 @@ #include "NetworkServer.h" +//Include thread libraries for Windows or Linux +#ifdef WIN32 +#include +#else +#include "pthread.h" +#include "unistd.h" +#endif + +//Thread functions have different types in Windows and Linux +#ifdef WIN32 +#define THREAD static void +#define THREADRETURN +#else +#define THREAD static void* +#define THREADRETURN return(NULL); +#endif + +#ifdef WIN32 +#include +#else +#include + +typedef struct listen_thread_param_type +{ + NetworkServer * this_ptr; + SOCKET * sock_ptr; +}; + +static void Sleep(unsigned int milliseconds) +{ + usleep(1000 * milliseconds); +} +#endif + +THREAD connection_thread(void *param) +{ + NetworkServer* server = static_cast(param); + server->ConnectionThread(); + THREADRETURN +} + +THREAD listen_thread(void *param) +{ + NetworkServer* server = static_cast(param)->this_ptr; + SOCKET* sock = static_cast(param)->sock_ptr; + server->ListenThread(sock); + THREADRETURN +} + NetworkServer::NetworkServer(std::vector& control) : controllers(control) { //Start a TCP server and launch threads port.tcp_server("1337"); + + //Start the connection thread +#ifdef WIN32 + _beginthread(connection_thread, 0, this); +#else + pthread_t thread; + pthread_create(&thread, NULL, &connection_thread, this); +#endif } void NetworkServer::ConnectionThread() @@ -12,16 +69,25 @@ void NetworkServer::ConnectionThread() while(1) { port.tcp_server_listen(); + + //Start a listener thread for the new client socket +#ifdef WIN32 + _beginthread(listen_thread, 0, this); +#else + pthread_t thread; + pthread_create(&thread, NULL, &listen_thread, this); +#endif } } -void NetworkServer::ListenThread() +void NetworkServer::ListenThread(SOCKET * client_sock) { //This thread handles messages received from clients while(1) { NetPacketHeader header; - int bytes_read = 0; + char * data = NULL; + int bytes_read = 0; //Read first byte of magic do @@ -35,6 +101,8 @@ void NetworkServer::ListenThread() continue; } + printf("Magic: 'O'\r\n"); + //Read second byte of magic do { @@ -47,6 +115,8 @@ void NetworkServer::ListenThread() continue; } + printf("Magic: 'R'\r\n"); + //Read third byte of magic do { @@ -59,6 +129,8 @@ void NetworkServer::ListenThread() continue; } + printf("Magic: 'G'\r\n"); + //Read fourth byte of magic do { @@ -71,6 +143,8 @@ void NetworkServer::ListenThread() continue; } + printf("Magic: 'B'\r\n"); + //If we get to this point, the magic is correct. Read the rest of the header do { @@ -80,14 +154,22 @@ void NetworkServer::ListenThread() //Header received, now receive the data if(header.pkt_size > 0) { + unsigned int bytes_read = 0; + data = new char[header.pkt_size]; + + do + { + bytes_read += port.tcp_listen(&data[bytes_read], 128); + } while (bytes_read < header.pkt_size); } + printf( "Received header and data\r\n" ); + //Entire request received, select functionality based on request ID switch(header.pkt_id) { NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: - break; NET_PACKET_ID_REQUEST_CONTROLLER_DATA: diff --git a/NetworkServer.h b/NetworkServer.h index e808fec6..606af54a 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -10,7 +10,7 @@ public: NetworkServer(std::vector& control); void ConnectionThread(); - void ListenThread(); + void ListenThread(SOCKET * client_sock); protected: std::vector& controllers; diff --git a/OpenRGB.pro b/OpenRGB.pro index 55fa7672..74e5591e 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -68,6 +68,9 @@ SOURCES += \ main.cpp \ cli.cpp \ OpenRGB.cpp \ + NetworkClient.cpp \ + NetworkProtocol.cpp \ + NetworkServer.cpp \ ProfileManager.cpp \ qt/OpenRGBDeviceInfoPage.cpp \ qt/OpenRGBDevicePage.cpp \ @@ -176,6 +179,9 @@ SOURCES += \ HEADERS += \ dependencies/ColorWheel/ColorWheel.h \ + NetworkClient.h \ + NetworkProtocol.h \ + NetworkServer.h \ ProfileManager.h \ qt/OpenRGBDeviceInfoPage.h \ qt/OpenRGBDevicePage.h \ diff --git a/main.cpp b/main.cpp index f12b12a0..09530ba2 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ * * \******************************************************************************************/ +#include "NetworkServer.h" #include "OpenRGB.h" #include "ProfileManager.h" #include "RGBController.h" @@ -44,6 +45,8 @@ int main(int argc, char* argv[]) return cli_main(argc, argv, rgb_controllers, &profile_manager); } + NetworkServer server(rgb_controllers); + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication a(argc, argv); diff --git a/net_port/net_port.cpp b/net_port/net_port.cpp index 9e4ad970..cfa349db 100644 --- a/net_port/net_port.cpp +++ b/net_port/net_port.cpp @@ -187,6 +187,9 @@ bool net_port::tcp_server(const char * port) { sockaddr_in myAddress; + /*-------------------------------------------------*\ + | Windows requires WSAStartup before using sockets | + \*-------------------------------------------------*/ #ifdef WIN32 if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR) { @@ -195,6 +198,9 @@ bool net_port::tcp_server(const char * port) } #endif + /*-------------------------------------------------*\ + | Create the server socket | + \*-------------------------------------------------*/ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { @@ -202,32 +208,61 @@ bool net_port::tcp_server(const char * port) return false; } + /*-------------------------------------------------*\ + | Fill in server address info with port value | + \*-------------------------------------------------*/ port = strtok((char *)port, "\r"); myAddress.sin_family = AF_INET; myAddress.sin_addr.s_addr = inet_addr("0.0.0.0"); myAddress.sin_port = htons(atoi(port)); + /*-------------------------------------------------*\ + | Bind the server socket | + \*-------------------------------------------------*/ if (bind(sock, (sockaddr*)&myAddress, sizeof(myAddress)) == SOCKET_ERROR) { WSACleanup(); return false; } + /*-------------------------------------------------*\ + | Set socket options - no delay | + \*-------------------------------------------------*/ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); return(true); } -void net_port::tcp_server_listen() +SOCKET * net_port::tcp_server_listen() { + /*-------------------------------------------------*\ + | Create new socket for client connection | + \*-------------------------------------------------*/ SOCKET * client = new SOCKET(); + + /*-------------------------------------------------*\ + | Listen for incoming client connection on the | + | server socket. This call blocks until a | + | connection is established | + \*-------------------------------------------------*/ listen(sock, 10); + + /*-------------------------------------------------*\ + | Accept the client connection | + \*-------------------------------------------------*/ *client = accept(sock, NULL, NULL); + + /*-------------------------------------------------*\ + | Get the new client socket and store it in the | + | clients vector | + \*-------------------------------------------------*/ u_long arg = 0; ioctlsocket(*client, FIONBIO, &arg); setsockopt(*client, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); clients.push_back(client); + + return client; } void net_port::tcp_close() diff --git a/net_port/net_port.h b/net_port/net_port.h index a47b6096..a97e23ff 100644 --- a/net_port/net_port.h +++ b/net_port/net_port.h @@ -54,8 +54,10 @@ public: bool tcp_client_connect(); //Function to open a server - bool tcp_server(const char * port); - void tcp_server_listen(); + bool tcp_server(const char * port); + std::size_t tcp_server_num_clients(); + SOCKET * tcp_server_get_client(std::size_t client_idx); + SOCKET * tcp_server_listen(); int udp_listen(char * recv_data, int length); int tcp_listen(char * recv_data, int length);