More work on network support, need to implement spawning of one read thread for each client socket

This commit is contained in:
Adam Honse 2020-04-13 01:01:10 -05:00
parent cf69598fd1
commit 46339c5f86
6 changed files with 135 additions and 7 deletions

View file

@ -1,9 +1,66 @@
#include "NetworkServer.h"
//Include thread libraries for Windows or Linux
#ifdef WIN32
#include <process.h>
#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 <Windows.h>
#else
#include <unistd.h>
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<NetworkServer*>(param);
server->ConnectionThread();
THREADRETURN
}
THREAD listen_thread(void *param)
{
NetworkServer* server = static_cast<listen_thread_param_type*>(param)->this_ptr;
SOCKET* sock = static_cast<listen_thread_param_type*>(param)->sock_ptr;
server->ListenThread(sock);
THREADRETURN
}
NetworkServer::NetworkServer(std::vector<RGBController *>& 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:

View file

@ -10,7 +10,7 @@ public:
NetworkServer(std::vector<RGBController *>& control);
void ConnectionThread();
void ListenThread();
void ListenThread(SOCKET * client_sock);
protected:
std::vector<RGBController *>& controllers;

View file

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

View file

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

View file

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

View file

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