diff --git a/PIwebVNC.cpp b/PIwebVNC.cpp
index 1934325..31884d9 100644
--- a/PIwebVNC.cpp
+++ b/PIwebVNC.cpp
@@ -34,9 +34,9 @@ XInputs *xinputs; // XInputs object
/**
* main loop to send frames to the client
*/
-void frameLoop(Websocket *ws)
+void frameLoop()
{
- vncServer.start_service(*ws);
+ vncServer.start_service(*wss);
}
void firstFrame(int sid)
@@ -72,7 +72,7 @@ int main(int argc, char *argv[])
xinputs = &input;
signal(SIGINT, handle_sigint);
std::thread t1 = ws.begin(SERVER_PORT);
- std::thread t2(frameLoop, &ws);
+ std::thread t2(frameLoop);
ws.onMessage(onMessageCLBK);
ws.onConnect(firstFrame);
diff --git a/compile.sh b/compile.sh
index d57d978..cf8ce57 100644
--- a/compile.sh
+++ b/compile.sh
@@ -1,6 +1,6 @@
apt install -y libx11-dev libxdamage-dev libxfixes-dev libxtst-dev liblz4-dev g++
-g++ PIwebVNC.cpp -lX11 -lXdamage -lXfixes -pthread -lXtst -llz4 -o PiWebVNC
+g++ PIwebVNC.cpp -lX11 -lXdamage -lXfixes -pthread -lXtst -lXext -llz4 -o PiWebVNC
echo "Compile Successful."
diff --git a/libs/appConfigs.hpp b/libs/appConfigs.hpp
index fb7c932..27f242c 100644
--- a/libs/appConfigs.hpp
+++ b/libs/appConfigs.hpp
@@ -15,7 +15,7 @@
#define MAX_BUFFER_SIZE 1024
// =======display=========
-#define FPS 10 // for pi zero set 5 [max 10 for pi4]
+#define FPS 15 // for pi zero set 5 [max 10 for pi4]
#define FRAME_SEGMENTS_DELAY_MS 20 // for pi zero set 100
#endif
\ No newline at end of file
diff --git a/libs/display.hpp b/libs/display.hpp
index 927b652..731dccd 100644
--- a/libs/display.hpp
+++ b/libs/display.hpp
@@ -47,6 +47,7 @@ class XDisplay
ScreenInfo getScreenInfo();
std::string getCursorName();
int getBitPerLine();
+ int depth;
private:
Display *display = 0;
@@ -59,7 +60,7 @@ XDisplay::XDisplay()
try
{
std::string envDisplay = std::string(getenv("DISPLAY"));
- display = XOpenDisplay(envDisplay.c_str());
+ this->display = XOpenDisplay(envDisplay.c_str());
}
catch (std::exception &e)
{
@@ -67,15 +68,15 @@ XDisplay::XDisplay()
std::cout << "[LOG] No env set for display. Trying default.[0 to 9]." << std::endl;
#endif
int displayNumber = 0;
- while (display == 0 && displayNumber < 10)
+ while (this->display == 0 && displayNumber < 10)
{
std::string displayNumberStr = ":" + std::to_string(displayNumber);
std::cout << "[LOG] Trying display number " << displayNumberStr << std::endl;
- display = XOpenDisplay(displayNumberStr.c_str());
+ this->display = XOpenDisplay(displayNumberStr.c_str());
displayNumber++;
}
}
- if (display == 0)
+ if (this->display == 0)
{
#if ERROR || DEBUG
std::cout << "[ERROR][EXIT APP] Could not open display. Please pass --display [id].\n\t eg: --display 18." << std::endl;
@@ -89,23 +90,23 @@ XDisplay::XDisplay()
XDisplay::~XDisplay()
{
// free display
- if(display != 0) {
+ if(this->display != 0) {
#if LOG
std::cout << "[LOG] Closing display." << std::endl;
#endif
- XCloseDisplay(display);
- display = 0;
+ XCloseDisplay(this->display);
+ this->display = 0;
}
}
Display * XDisplay::getDisplay()
{
- return display;
+ return this->display;
}
int XDisplay::getBitPerLine()
{
- return bitPerLine;
+ return this->bitPerLine;
}
std::string XDisplay::getDisplayConfig()
@@ -113,7 +114,7 @@ std::string XDisplay::getDisplayConfig()
ScreenInfo screenInfo = getScreenInfo();
int width = screenInfo.width;
int height = screenInfo.height;
- XImage * img = XGetImage(display, DefaultRootWindow(display), 0, 0, width, height, AllPlanes, ZPixmap);
+ XImage * img = XGetImage(this->display, DefaultRootWindow(this->display), 0, 0, width, height, AllPlanes, ZPixmap);
std::string config = "{ 'bytePerLine':" + std::to_string(img->bytes_per_line) +
",'redMask':" + std::to_string(img->red_mask) +
",'greenMask':" + std::to_string(img->green_mask) +
@@ -124,6 +125,7 @@ std::string XDisplay::getDisplayConfig()
",'fps':" + std::to_string(FPS) +
+" }";
this->bitPerLine = img->bytes_per_line;
+ this->depth = img->depth;
XDestroyImage(img);
return config;
}
@@ -131,7 +133,7 @@ std::string XDisplay::getDisplayConfig()
std::string XDisplay::getCursorName()
{
// get cursor name using xfixes
- XFixesCursorImage *cursorImage = XFixesGetCursorImage(display);
+ XFixesCursorImage *cursorImage = XFixesGetCursorImage(this->display);
if (cursorImage == 0)
{
#if ERROR || DEBUG
@@ -147,9 +149,9 @@ ScreenInfo XDisplay::getScreenInfo()
{
ScreenInfo screenInfo;
// get screen info from root window
- screenInfo.root = DefaultRootWindow(display);
- screenInfo.width = DisplayWidth(display, DefaultScreen(display));
- screenInfo.height = DisplayHeight(display, DefaultScreen(display));
+ screenInfo.root = DefaultRootWindow(this->display);
+ screenInfo.width = DisplayWidth(this->display, DefaultScreen(this->display));
+ screenInfo.height = DisplayHeight(this->display, DefaultScreen(this->display));
return screenInfo;
}
diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp
index 277f79b..220f4e7 100644
--- a/libs/httpPage.hpp
+++ b/libs/httpPage.hpp
@@ -12,7 +12,7 @@ struct HttpHTMLPage
void parseHttpPage()
{
- htmlPage.index_html = std::string("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n") + R"html(
+ htmlPage.index_html = std::string("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nServer: PIwebVNC (by Jishan)\r\n\r\n") + R"html(
@@ -9742,7 +9742,7 @@ void parseHttpPage()
var y = Math.floor(e.offsetY / canvas.offsetHeight * canvas.height)
data = "M" + x + " " + y + " ";
ws.send(data);
- }, 200);
+ }, 100);
}
canvas.onwheel = function(e){
e.preventDefault();
diff --git a/libs/input.hpp b/libs/input.hpp
index e0db44f..a0c28ce 100644
--- a/libs/input.hpp
+++ b/libs/input.hpp
@@ -36,7 +36,7 @@ class XInputs
void dispatchEvents();
private:
Display *display;
- char* events[30] = {0};
+ char events[30][100] = {0};
int eventCount = 0;
};
@@ -47,20 +47,22 @@ XInputs::XInputs(Display * display)
void XInputs::queueInputs(char *data, int clinetSD)
{
- if (eventCount < 30)
+ if (this->eventCount < 30)
{
- events[eventCount] = data;
- eventCount++;
+ strcpy(this->events[this->eventCount], data);
+ this->eventCount++;
}
}
void XInputs::dispatchEvents(){
- for(int i = 0; i < eventCount; i++){
- if(events[i] != NULL){
- processInputs(events[i], 0);
+ for(int i = 0; i < this->eventCount; i++){
+ if (events[i][0] != 0)
+ {
+ processInputs(this->events[i], 0);
+ this->events[i][0] = 0;
}
}
- eventCount = 0;
+ this->eventCount = 0;
}
void XInputs::processInputs(char *data, int clientSD)
@@ -74,12 +76,12 @@ void XInputs::processInputs(char *data, int clientSD)
i++;
while (data[i] != 32 && i < len)
y = y * 10 + data[i++] - 48;
- if (display == 0)
+ if (this->display == 0)
return;
- XTestFakeMotionEvent(display, -1, x, y, CurrentTime);
- XTestFakeButtonEvent(display, 1, True, CurrentTime);
- XTestFakeButtonEvent(display, 1, False, CurrentTime);
- XFlush(display);
+ XTestFakeMotionEvent(this->display, -1, x, y, CurrentTime);
+ XTestFakeButtonEvent(this->display, 1, True, CurrentTime);
+ XTestFakeButtonEvent(this->display, 1, False, CurrentTime);
+ XFlush(this->display);
}
else if (data[0] == 'M')
{
@@ -88,10 +90,10 @@ void XInputs::processInputs(char *data, int clientSD)
i++;
while (data[i] != 32 && i < len)
y = y * 10 + data[i++] - 48;
- if (display == 0)
+ if (this->display == 0)
return;
- XTestFakeMotionEvent(display, -1, x, y, CurrentTime);
- XFlush(display);
+ XTestFakeMotionEvent(this->display, -1, x, y, CurrentTime);
+ XFlush(this->display);
}
else if (data[0] == 'R')
{
@@ -100,12 +102,12 @@ void XInputs::processInputs(char *data, int clientSD)
i++;
while (data[i] != 32 && i < len)
y = y * 10 + data[i++] - 48;
- if (display == 0)
+ if (this->display == 0)
return;
- XTestFakeMotionEvent(display, -1, x, y, CurrentTime);
- XTestFakeButtonEvent(display, 3, True, CurrentTime);
- XTestFakeButtonEvent(display, 3, False, CurrentTime);
- XFlush(display);
+ XTestFakeMotionEvent(this->display, -1, x, y, CurrentTime);
+ XTestFakeButtonEvent(this->display, 3, True, CurrentTime);
+ XTestFakeButtonEvent(this->display, 3, False, CurrentTime);
+ XFlush(this->display);
}
else if (data[0] == 'D')
{
@@ -120,34 +122,34 @@ void XInputs::processInputs(char *data, int clientSD)
i++;
while (data[i] != 32 && i < len)
y2 = y2 * 10 + data[i++] - 48;
- if (display == 0)
+ if (this->display == 0)
return;
- XTestFakeMotionEvent(display, -1, x, y, CurrentTime);
- XTestFakeButtonEvent(display, 1, True, CurrentTime);
- XTestFakeMotionEvent(display, -1, x2, y2, CurrentTime);
- XFlush(display);
+ XTestFakeMotionEvent(this->display, -1, x, y, CurrentTime);
+ XTestFakeButtonEvent(this->display, 1, True, CurrentTime);
+ XTestFakeMotionEvent(this->display, -1, x2, y2, CurrentTime);
+ XFlush(this->display);
}
else if (data[0] == 'S')
{
if (data[1] == 'U')
{
- XTestFakeButtonEvent(display, 4, 1, 0);
- XTestFakeButtonEvent(display, 4, 0, 70);
+ XTestFakeButtonEvent(this->display, 4, 1, 0);
+ XTestFakeButtonEvent(this->display, 4, 0, 70);
}
else
{
- XTestFakeButtonEvent(display, 5, 1, 0);
- XTestFakeButtonEvent(display, 5, 0, 70);
+ XTestFakeButtonEvent(this->display, 5, 1, 0);
+ XTestFakeButtonEvent(this->display, 5, 0, 70);
}
}
else if (data[0] == 'K')
{
if (data[1] == 49)
{
- int keycode = XKeysymToKeycode(display, XStringToKeysym(data + 2));
- XTestFakeKeyEvent(display, keycode, True, CurrentTime);
- XTestFakeKeyEvent(display, keycode, False, CurrentTime);
- XFlush(display);
+ int keycode = XKeysymToKeycode(this->display, XStringToKeysym(data + 2));
+ XTestFakeKeyEvent(this->display, keycode, True, CurrentTime);
+ XTestFakeKeyEvent(this->display, keycode, False, CurrentTime);
+ XFlush(this->display);
}
else if (data[1] == 50)
{
@@ -159,17 +161,16 @@ void XInputs::processInputs(char *data, int clientSD)
i++;
}
i++;
- int keycode1 = XKeysymToKeycode(display, XStringToKeysym(buffer));
- int keycode2 = XKeysymToKeycode(display, XStringToKeysym(data + i));
- XTestFakeKeyEvent(display, keycode1, True, 0);
- XTestFakeKeyEvent(display, keycode2, True, 0);
- XTestFakeKeyEvent(display, keycode2, False, 0);
- XTestFakeKeyEvent(display, keycode1, False, 0);
- XFlush(display);
+ int keycode1 = XKeysymToKeycode(this->display, XStringToKeysym(buffer));
+ int keycode2 = XKeysymToKeycode(this->display, XStringToKeysym(data + i));
+ XTestFakeKeyEvent(this->display, keycode1, True, 0);
+ XTestFakeKeyEvent(this->display, keycode2, True, 0);
+ XTestFakeKeyEvent(this->display, keycode2, False, 0);
+ XTestFakeKeyEvent(this->display, keycode1, False, 0);
+ XFlush(this->display);
}
}
- XFlush(display);
- free(data);
+ XFlush(this->display);
}
#endif
\ No newline at end of file
diff --git a/libs/sha1.hpp b/libs/sha1.hpp
index fd276c0..d626ccd 100644
--- a/libs/sha1.hpp
+++ b/libs/sha1.hpp
@@ -248,7 +248,8 @@ int char2int(char input)
std::string hex2bin(std::string src)
{
std::string target = "";
- for (int i = 0; i < src.length(); i += 2)
+ int len = src.length();
+ for (int i = 0; i < len; i += 2)
{
target += char2int(src[i]) * 16 + char2int(src[i + 1]);
}
diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp
index 670fcd7..7890404 100644
--- a/libs/vncserver.hpp
+++ b/libs/vncserver.hpp
@@ -26,7 +26,8 @@
#include
#include
#include
-
+#include
+#include
#include "display.hpp"
#include "input.hpp"
@@ -42,6 +43,7 @@ class VNCServer
void send_first_frame(int sd); // send the first frame to the client
private:
void threadSleep();
+ void getSubImage(char *image, int x, int y, int width, int height,int bpl, char *subImage);
Display * display;
Damage damage;
ScreenInfo screenInfo;
@@ -50,24 +52,44 @@ class VNCServer
bool sendFirstFrame = false;
int clientSD = 0;
int sleepDelay = 1000000 / FPS;
- int sleepLoop = 1000000 / FPS / 100000;
+ int sleepLoop = (1000000 / FPS)/this->sleepDelay;
+ int bufferSize = 1000000;
+ char *buffer;
+ char *tempBuffer;
+ XShmSegmentInfo shminfo;
+ XImage *image;
};
VNCServer::VNCServer()
{
- int damage_event, damage_error, test;
- this->display = xdisplay.getDisplay();
- this->screenInfo = xdisplay.getScreenInfo();
- strcpy(config,xdisplay.getDisplayConfig().c_str());
+ int damage_event, damage_error;
+ this->display = this->xdisplay.getDisplay();
+ this->screenInfo = this->xdisplay.getScreenInfo();
+ strcpy(this->config,this->xdisplay.getDisplayConfig().c_str());
- test = XDamageQueryExtension(display, &damage_event, &damage_error);
+ XDamageQueryExtension(display, &damage_event, &damage_error);
this->damage = XDamageCreate(display, this->screenInfo.root, XDamageReportNonEmpty);
+
+ this->bufferSize = (this->screenInfo.height * this->xdisplay.getBitPerLine()) + (2 * this->screenInfo.width);
+ this->buffer = (char *)malloc(this->bufferSize * sizeof(char));
+ this->tempBuffer = (char *)malloc(this->bufferSize * sizeof(char));
+ if (this->buffer == NULL)
+ {
+ printf("[ERROR] Memory not allocated for VNC buffer.\n");
+ exit(0);
+ }
}
VNCServer::~VNCServer()
{
+ // free image
+ XDestroyImage(this->image);
+ XShmDetach(this->display, &shminfo);
+ free(this->buffer);
+ free(this->tempBuffer);
+ printf("[INFO] Memory released for VNC buffer.\n");
XDamageDestroy(display, damage);
- xdisplay.close();
+ this->xdisplay.close();
}
void VNCServer::stop_service()
@@ -81,28 +103,31 @@ void VNCServer::send_first_frame(int sd)
}
void VNCServer::start_service(Websocket &ws)
{
- int bufferSize = (this->screenInfo.height * xdisplay.getBitPerLine()) + (2 * this->screenInfo.width);
- char buffer[bufferSize] = {0};
- XImage *image;
+ image = XShmCreateImage(display, DefaultVisual(display, DefaultScreen(display)), xdisplay.depth, ZPixmap, NULL, &shminfo, this->screenInfo.width, this->screenInfo.height);
+ shminfo.shmid = shmget(IPC_PRIVATE,
+ image->bytes_per_line * image->height,
+ IPC_CREAT | 0777);
+ image->data = (char *)shmat(shminfo.shmid, 0, 0);
+ shminfo.shmaddr = image->data;
+ shminfo.readOnly = False;
+ XShmAttach(display, &shminfo);
const XserverRegion xregion = XFixesCreateRegion(this->display, NULL, 0);
- while(isRunning)
+ while(this->isRunning)
{
threadSleep();
if (ws.clients > 0)
{
if (this->sendFirstFrame)
{
- image = XGetImage(this->display, this->screenInfo.root, 0, 0, this->screenInfo.width
- , this->screenInfo.height, AllPlanes, ZPixmap);
+ XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes);
int frameSize = ((this->screenInfo.height - 1) * image->bytes_per_line + (this->screenInfo.width - 1));
- int compressedSize = LZ4_compress_default(image->data, buffer, frameSize, bufferSize);
+ int compressedSize = LZ4_compress_default(image->data, this->buffer, frameSize, this->bufferSize);
std::string data = "UPD" + std::to_string(0) + " " + std::to_string(0) + " "
+ std::to_string(this->screenInfo.width) + " " + std::to_string(this->screenInfo.height) + " "
+ std::to_string(image->bytes_per_line) + " " + std::to_string(compressedSize) + " \n";
char *info = (char *)data.c_str();
int infoSize = strlen(info);
- XDestroyImage(image);
- ws.sendText(config, this->clientSD);
+ ws.sendText(this->config, this->clientSD);
ws.sendFrame(info, buffer, infoSize, compressedSize, this->clientSD);
this->sendFirstFrame = false;
usleep(100000);
@@ -114,20 +139,27 @@ void VNCServer::start_service(Websocket &ws)
XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts);
for (int i = 0; i < partCounts; i++)
{
- image = XGetImage(display, this->screenInfo.root, rect[i].x, rect[i].y, rect[i].width, rect[i].height, AllPlanes, ZPixmap);
- int frameSize = (rect[i].height * image->bytes_per_line);
- int compressedSize = LZ4_compress_default(image->data, buffer, frameSize, bufferSize);
+ XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes);
+ int bytes = (image->bytes_per_line / this->screenInfo.width)*rect[i].width;
+ // bytes = rect[i].width * (xdisplay.depth / 8);
+ int frameSize = (rect[i].height * bytes);
+ this->getSubImage(image->data, rect[i].x, rect[i].y, rect[i].width, rect[i].height,bytes, this->tempBuffer);
+ int compressedSize = LZ4_compress_default(this->tempBuffer, this->buffer, frameSize, this->bufferSize);
std::string data = "UPD" + std::to_string(rect[i].x) + " " + std::to_string(rect[i].y) + " "
+ std::to_string(rect[i].width) + " " + std::to_string(rect[i].height) + " "
- + std::to_string(image->bytes_per_line) + " " + std::to_string(compressedSize) + " \n";
+ + std::to_string(bytes) + " " + std::to_string(compressedSize) + " \n";
char *info = (char *)data.c_str();
int infoSize = strlen(info);
- XDestroyImage(image);
- ws.sendFrame(info, buffer, infoSize, compressedSize);
+ ws.sendFrame(info, this->buffer, infoSize, compressedSize);
}
XFree(rect);
}
}
+ else{
+ while(ws.clients == 0){
+ sleep(1);
+ }
+ }
}
}
@@ -137,9 +169,24 @@ void VNCServer::threadSleep()
int i = this->sleepLoop;
while(i--)
{
- inputs->dispatchEvents();
- usleep(100000);
+ this->inputs->dispatchEvents();
+ usleep(this->sleepDelay);
}
}
+void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height,int bpl, char *subImageData){
+ int startPoint = 0;
+ if (xdisplay.depth == 24)
+ startPoint = (y * this->image->bytes_per_line) + (x << 2);
+ else
+ startPoint = (y * this->image->bytes_per_line) + (x << 1);
+ for (int i = 0; i < height; i++)
+ {
+ memcpy(subImageData, imageData + startPoint, bpl);
+ subImageData += bpl;
+ startPoint += this->image->bytes_per_line;
+ }
+}
+
+
#endif
\ No newline at end of file
diff --git a/libs/websocket.hpp b/libs/websocket.hpp
index 0054379..47d7cc8 100644
--- a/libs/websocket.hpp
+++ b/libs/websocket.hpp
@@ -29,6 +29,7 @@
#include "sha1.hpp"
#include "base64.hpp"
#include "httpPage.hpp"
+#include "appConfigs.hpp"
#define PORT 8080
@@ -50,12 +51,13 @@ class Websocket
private:
int socketPort = 8080;
+ int max_clients = (MAX_CLIENTS < 25) ? MAX_CLIENTS : 25;
int server_fd;
void connections();
- void handshake(char *d, int sd, int sid);
+ void handshake(unsigned char *d, int sd, int sid);
void sendRaw(int startByte, char *data, long imgSize, int sid);
void sendRaw(int startByte, char *data, char *data2, long data1Size, long data2Size, int sid);
- char *decode(char *data);
+ void decode(unsigned char *src,char * dest);
void (*callBack)(int sid) = NULL;
void (*callBackMsg)(void *data, int sid) = NULL;
};
@@ -84,7 +86,7 @@ void Websocket::connections()
struct sockaddr_in address;
int opt = 1, max_sd = 0;
int addrlen = sizeof(address);
- char buffer[1024] = {0};
+ unsigned char buffer[1024] = {0};
fd_set readfds;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
@@ -95,7 +97,7 @@ void Websocket::connections()
perror("socket failed");
exit(EXIT_FAILURE);
}
- if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
+ if (setsockopt(this->server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
@@ -105,18 +107,18 @@ void Websocket::connections()
perror("bind failed");
exit(EXIT_FAILURE);
}
- if (listen(server_fd, 3) < 0)
+ if (listen(this->server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
std::cout << "[I] Waiting for connections ...port " << this->socketPort << " opened (HTTP/WS)\n";
- while (!stop)
+ while (!this->stop)
{
FD_ZERO(&readfds);
- FD_SET(server_fd, &readfds);
- max_sd = server_fd;
- for (int i = 0; i < 5; i++)
+ FD_SET(this->server_fd, &readfds);
+ max_sd = this->server_fd;
+ for (int i = 0; i < this->max_clients; i++)
{
int sd = client_socket[i];
if (sd > 0)
@@ -129,28 +131,37 @@ void Websocket::connections()
{
perror("bind failed");
}
- if (FD_ISSET(server_fd, &readfds))
+ if (FD_ISSET(this->server_fd, &readfds))
{
- if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
+ if ((new_socket = accept(this->server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
- ready = 1;
+ this->ready = 1;
+ bool isAccespted = false;
printf("[I] New connection , socket fd is %d , ip is : %s , port : %d \n", new_socket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));
- for (int i = 0; i < 30; i++)
+ for (int i = 0; i < this->max_clients; i++)
{
- if (client_socket[i] == 0)
+ if (client_socket[i] == 0 && clients < this->max_clients)
{
client_socket[i] = new_socket;
clients++;
+ isAccespted = true;
break;
}
}
+ if (!isAccespted)
+ {
+ //reject connection
+ send(new_socket, "HTTP/1.1 400 Bad Request\r\n\r\n", 25, 0);
+ close(new_socket);
+ printf("[E] Max connections reached\n");
+ }
}
else
{
- for (int i = 0; i < 30; i++)
+ for (int i = 0; i < this->max_clients; i++)
{
if (client_socket[i] == 0)
continue;
@@ -179,13 +190,15 @@ void Websocket::connections()
client_socket[i] = 0;
this->ws_client_socket[i] = 0;
clients--;
- printf("client dicon : %d\n", sd);
+ printf("Host disconnected : %d | current active clients %d\n", sd,clients);
}
else
{
if (callBackMsg != NULL)
{
- callBackMsg(decode(buffer), i);
+ char inputData[200]={0};
+ decode(buffer , inputData);
+ callBackMsg(inputData, i);
}
}
}
@@ -196,17 +209,17 @@ void Websocket::connections()
std::cout << "[I] Server closed\n";
}
-void Websocket::handshake(char *data, int sd, int sid)
+void Websocket::handshake(unsigned char *data, int sd, int sid)
{
bool flag = false;
- char *ptr = strtok(data, "\n");
+ char *ptr = strtok((char *)data, "\n");
std::string key;
while (ptr != NULL)
{
if (ptr[0] == 'S' && ptr[4] == 'W' && ptr[14] == 'K')
{
- int i = 18;
- while (i++ < strlen(ptr) - 2)
+ int i = 18, len = strlen(ptr) - 2;
+ while (i++ < len)
{
key += ptr[i];
}
@@ -220,11 +233,12 @@ void Websocket::handshake(char *data, int sd, int sid)
strcpy(char_array, response.c_str());
send(sd, char_array, response.length(), 0);
this->ws_client_socket[sid] = 1;
- ready = 1;
+ this->ready = 1;
flag = true;
break;
}
ptr = strtok(NULL, "\n");
+ // callback
}
if (!flag)
{
@@ -235,10 +249,11 @@ void Websocket::handshake(char *data, int sd, int sid)
this->ws_client_socket[sid] = 0;
clients--;
}
- // callback
- if (callBack != NULL)
- {
- (*callBack)(sid);
+ else{
+ if (callBack != NULL)
+ {
+ (*callBack)(sid);
+ }
}
}
@@ -344,19 +359,17 @@ void Websocket::sendRaw(int startByte, char *data1, char *data2, long data1Size,
{
if (client_socket[i] == 0 || this->ws_client_socket[i] == 0)
continue;
- // max optimisation for sending data
- send(client_socket[i], header, moded, 0); // for websocket header
+ send(client_socket[i], header, moded, 0); // for websocket header
send(client_socket[i], data1, data1Size, 0); // for websocket data 1
send(client_socket[i], data2, data2Size, 0); // for websocket data 2
}
}
-char *Websocket::decode(char *data)
+void Websocket::decode(unsigned char *data, char *result)
{
+ if(data[0] == 0) return;
// decode a websocket frame which is less than 125 bytes
- char *result;
int size = data[1] & 127;
- result = (char *)malloc(size * sizeof(char));
int index = 2;
for (int i = 6; i < size + 6; i++)
{
@@ -366,6 +379,5 @@ char *Websocket::decode(char *data)
index = 2;
}
}
- return result;
}
#endif
\ No newline at end of file