More work on network support, need to implement spawning of one read thread for each client socket
This commit is contained in:
parent
cf69598fd1
commit
46339c5f86
6 changed files with 135 additions and 7 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public:
|
|||
NetworkServer(std::vector<RGBController *>& control);
|
||||
|
||||
void ConnectionThread();
|
||||
void ListenThread();
|
||||
void ListenThread(SOCKET * client_sock);
|
||||
|
||||
protected:
|
||||
std::vector<RGBController *>& controllers;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
3
main.cpp
3
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue