From 2fc215792f7118712047b2a6349f985546370235 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Sun, 12 Jun 2022 21:19:00 +0530 Subject: [PATCH 01/23] websocket wrong callback --- libs/input.hpp | 1 + libs/websocket.hpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/input.hpp b/libs/input.hpp index e0db44f..b8ae2c3 100644 --- a/libs/input.hpp +++ b/libs/input.hpp @@ -58,6 +58,7 @@ void XInputs::dispatchEvents(){ for(int i = 0; i < eventCount; i++){ if(events[i] != NULL){ processInputs(events[i], 0); + events[i] = NULL; } } eventCount = 0; diff --git a/libs/websocket.hpp b/libs/websocket.hpp index 0054379..b9bf8da 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -225,6 +225,11 @@ void Websocket::handshake(char *data, int sd, int sid) break; } ptr = strtok(NULL, "\n"); + // callback + if (callBack != NULL && flag) + { + (*callBack)(sid); + } } if (!flag) { @@ -235,11 +240,6 @@ void Websocket::handshake(char *data, int sd, int sid) this->ws_client_socket[sid] = 0; clients--; } - // callback - if (callBack != NULL) - { - (*callBack)(sid); - } } void Websocket::sendText(char *text, int sid) From c9e171794fe3abcaa4b2610dd103a08e3f102fc5 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Fri, 17 Jun 2022 14:05:21 +0530 Subject: [PATCH 02/23] websocket wrong callback --- libs/websocket.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/websocket.hpp b/libs/websocket.hpp index 0054379..b9bf8da 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -225,6 +225,11 @@ void Websocket::handshake(char *data, int sd, int sid) break; } ptr = strtok(NULL, "\n"); + // callback + if (callBack != NULL && flag) + { + (*callBack)(sid); + } } if (!flag) { @@ -235,11 +240,6 @@ void Websocket::handshake(char *data, int sd, int sid) this->ws_client_socket[sid] = 0; clients--; } - // callback - if (callBack != NULL) - { - (*callBack)(sid); - } } void Websocket::sendText(char *text, int sid) From 0dc5cd6cc11fd09b0e3fb373d13924a318c44a35 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Fri, 17 Jun 2022 14:05:48 +0530 Subject: [PATCH 03/23] backout few changes --- libs/input.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/input.hpp b/libs/input.hpp index e0db44f..b8ae2c3 100644 --- a/libs/input.hpp +++ b/libs/input.hpp @@ -58,6 +58,7 @@ void XInputs::dispatchEvents(){ for(int i = 0; i < eventCount; i++){ if(events[i] != NULL){ processInputs(events[i], 0); + events[i] = NULL; } } eventCount = 0; From b04c18a9dce36b51731223fa8d241473f47f51c5 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Fri, 17 Jun 2022 16:00:06 +0530 Subject: [PATCH 04/23] Bug fixed --- libs/websocket.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/websocket.hpp b/libs/websocket.hpp index 0054379..b9bf8da 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -225,6 +225,11 @@ void Websocket::handshake(char *data, int sd, int sid) break; } ptr = strtok(NULL, "\n"); + // callback + if (callBack != NULL && flag) + { + (*callBack)(sid); + } } if (!flag) { @@ -235,11 +240,6 @@ void Websocket::handshake(char *data, int sd, int sid) this->ws_client_socket[sid] = 0; clients--; } - // callback - if (callBack != NULL) - { - (*callBack)(sid); - } } void Websocket::sendText(char *text, int sid) From a29153d097bc5485bbf91ac16ee66dc287717867 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Fri, 17 Jun 2022 16:00:41 +0530 Subject: [PATCH 05/23] fixed prev backout --- README.md | 5 ----- libs/input.hpp | 1 + libs/websocket.hpp | 10 ++++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 19a4d90..1ec91db 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,6 @@ open `http://--ip-of-raspberry-pi--:8000` from another pc browser E.g. `http://1 Open libs/appConfigs.hpp to configure this app, like PORT , MAX clients etc. HTTPS or WSS configuration will be available soon [#5_issue](/../../issues/5) -#### Configure -Open libs/appConfigs.hpp to configure this app, like PORT , MAX clients etc. -HTTPS or WSS configuration will be available soon [#5_issue](/../../issues/5) - - ### Auto start Use this auto-start method to run this app at startup ###### Note : You can use different methods also. diff --git a/libs/input.hpp b/libs/input.hpp index e0db44f..b8ae2c3 100644 --- a/libs/input.hpp +++ b/libs/input.hpp @@ -58,6 +58,7 @@ void XInputs::dispatchEvents(){ for(int i = 0; i < eventCount; i++){ if(events[i] != NULL){ processInputs(events[i], 0); + events[i] = NULL; } } eventCount = 0; diff --git a/libs/websocket.hpp b/libs/websocket.hpp index b9bf8da..fe31b75 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -226,10 +226,6 @@ void Websocket::handshake(char *data, int sd, int sid) } ptr = strtok(NULL, "\n"); // callback - if (callBack != NULL && flag) - { - (*callBack)(sid); - } } if (!flag) { @@ -240,6 +236,12 @@ void Websocket::handshake(char *data, int sd, int sid) this->ws_client_socket[sid] = 0; clients--; } + else{ + if (callBack != NULL) + { + (*callBack)(sid); + } + } } void Websocket::sendText(char *text, int sid) From 01dce4c0a91c10d9ca9c1b324ed6a26c8f3929f6 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Sat, 25 Jun 2022 14:37:04 +0530 Subject: [PATCH 06/23] massive memory leak fixed --- PIwebVNC.cpp | 6 +++--- libs/input.hpp | 9 ++++----- libs/sha1.hpp | 3 ++- libs/vncserver.hpp | 26 ++++++++++++++++++-------- libs/websocket.hpp | 16 ++++++++-------- 5 files changed, 35 insertions(+), 25 deletions(-) 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/libs/input.hpp b/libs/input.hpp index b8ae2c3..05c9f7e 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; }; @@ -49,16 +49,16 @@ void XInputs::queueInputs(char *data, int clinetSD) { if (eventCount < 30) { - events[eventCount] = data; + strcpy(events[eventCount], data); eventCount++; } } void XInputs::dispatchEvents(){ for(int i = 0; i < eventCount; i++){ - if(events[i] != NULL){ + if(events[i][0] != 0){ processInputs(events[i], 0); - events[i] = NULL; + events[i][0] = 0; } } eventCount = 0; @@ -170,7 +170,6 @@ void XInputs::processInputs(char *data, int clientSD) } } XFlush(display); - free(data); } #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..1b7fc7c 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -51,21 +51,33 @@ class VNCServer int clientSD = 0; int sleepDelay = 1000000 / FPS; int sleepLoop = 1000000 / FPS / 100000; + int bufferSize = 1000000; + char *buffer; }; VNCServer::VNCServer() { - int damage_event, damage_error, test; + int damage_event, damage_error; this->display = xdisplay.getDisplay(); this->screenInfo = xdisplay.getScreenInfo(); strcpy(config,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 * xdisplay.getBitPerLine()) + (2 * this->screenInfo.width); + this->buffer = (char *)malloc(this->bufferSize * sizeof(char)); + if (this->buffer == NULL) + { + printf("[ERROR] Memory not allocated for VNC buffer.\n"); + exit(0); + } } VNCServer::~VNCServer() { + free(buffer); + printf("[INFO] Memory released for VNC buffer.\n"); XDamageDestroy(display, damage); xdisplay.close(); } @@ -81,9 +93,7 @@ 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; + register XImage *image; const XserverRegion xregion = XFixesCreateRegion(this->display, NULL, 0); while(isRunning) { @@ -95,7 +105,7 @@ void VNCServer::start_service(Websocket &ws) image = XGetImage(this->display, this->screenInfo.root, 0, 0, this->screenInfo.width , this->screenInfo.height, AllPlanes, ZPixmap); 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"; @@ -116,13 +126,13 @@ void VNCServer::start_service(Websocket &ws) { 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); + int compressedSize = LZ4_compress_default(image->data, 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"; char *info = (char *)data.c_str(); int infoSize = strlen(info); - XDestroyImage(image); + if(!XDestroyImage(image)) free(image); ws.sendFrame(info, buffer, infoSize, compressedSize); } XFree(rect); diff --git a/libs/websocket.hpp b/libs/websocket.hpp index fe31b75..1a9ba0a 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -55,7 +55,7 @@ class Websocket void handshake(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(char *src,char * dest); void (*callBack)(int sid) = NULL; void (*callBackMsg)(void *data, int sid) = NULL; }; @@ -185,7 +185,9 @@ void Websocket::connections() { if (callBackMsg != NULL) { - callBackMsg(decode(buffer), i); + char inputData[200]={0}; + decode(buffer , inputData); + callBackMsg(inputData, i); } } } @@ -205,8 +207,8 @@ void Websocket::handshake(char *data, int sd, int sid) { 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]; } @@ -353,12 +355,11 @@ void Websocket::sendRaw(int startByte, char *data1, char *data2, long data1Size, } } -char *Websocket::decode(char *data) +void Websocket::decode(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++) { @@ -368,6 +369,5 @@ char *Websocket::decode(char *data) index = 2; } } - return result; } #endif \ No newline at end of file From df0c8a7e337144f02ff694f45102bb31b820ff3a Mon Sep 17 00:00:00 2001 From: jishan484 Date: Sat, 25 Jun 2022 23:40:54 +0530 Subject: [PATCH 07/23] sleepDelay bug fixed : moving to 15 FPS --- libs/appConfigs.hpp | 2 +- libs/vncserver.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/vncserver.hpp b/libs/vncserver.hpp index 1b7fc7c..e1b43b6 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -50,7 +50,7 @@ class VNCServer bool sendFirstFrame = false; int clientSD = 0; int sleepDelay = 1000000 / FPS; - int sleepLoop = 1000000 / FPS / 100000; + int sleepLoop = (1000000 / FPS)/sleepDelay; int bufferSize = 1000000; char *buffer; }; @@ -148,7 +148,7 @@ void VNCServer::threadSleep() while(i--) { inputs->dispatchEvents(); - usleep(100000); + usleep(sleepDelay); } } From e8fda23407b6392c10cb689f5ca6c30d72da49f0 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Sun, 26 Jun 2022 19:52:29 +0530 Subject: [PATCH 08/23] client not disconnect fixed --- libs/display.hpp | 28 +++++++-------- libs/input.hpp | 85 +++++++++++++++++++++++----------------------- libs/vncserver.hpp | 29 +++++++++------- libs/websocket.hpp | 35 ++++++++++--------- 4 files changed, 91 insertions(+), 86 deletions(-) diff --git a/libs/display.hpp b/libs/display.hpp index 927b652..f9e794c 100644 --- a/libs/display.hpp +++ b/libs/display.hpp @@ -59,7 +59,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 +67,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 +89,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 +113,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) + @@ -131,7 +131,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 +147,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/input.hpp b/libs/input.hpp index 05c9f7e..a0c28ce 100644 --- a/libs/input.hpp +++ b/libs/input.hpp @@ -47,21 +47,22 @@ XInputs::XInputs(Display * display) void XInputs::queueInputs(char *data, int clinetSD) { - if (eventCount < 30) + if (this->eventCount < 30) { - strcpy(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][0] != 0){ - processInputs(events[i], 0); - events[i][0] = 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) @@ -75,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') { @@ -89,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') { @@ -101,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') { @@ -121,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) { @@ -160,16 +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); + XFlush(this->display); } #endif \ No newline at end of file diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index e1b43b6..6d8404d 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -50,7 +50,7 @@ class VNCServer bool sendFirstFrame = false; int clientSD = 0; int sleepDelay = 1000000 / FPS; - int sleepLoop = (1000000 / FPS)/sleepDelay; + int sleepLoop = (1000000 / FPS)/this->sleepDelay; int bufferSize = 1000000; char *buffer; }; @@ -58,14 +58,14 @@ class VNCServer VNCServer::VNCServer() { int damage_event, damage_error; - this->display = xdisplay.getDisplay(); - this->screenInfo = xdisplay.getScreenInfo(); - strcpy(config,xdisplay.getDisplayConfig().c_str()); + this->display = this->xdisplay.getDisplay(); + this->screenInfo = this->xdisplay.getScreenInfo(); + strcpy(this->config,this->xdisplay.getDisplayConfig().c_str()); XDamageQueryExtension(display, &damage_event, &damage_error); this->damage = XDamageCreate(display, this->screenInfo.root, XDamageReportNonEmpty); - this->bufferSize = (this->screenInfo.height * xdisplay.getBitPerLine()) + (2 * this->screenInfo.width); + this->bufferSize = (this->screenInfo.height * this->xdisplay.getBitPerLine()) + (2 * this->screenInfo.width); this->buffer = (char *)malloc(this->bufferSize * sizeof(char)); if (this->buffer == NULL) { @@ -76,10 +76,10 @@ VNCServer::VNCServer() VNCServer::~VNCServer() { - free(buffer); + free(this->buffer); printf("[INFO] Memory released for VNC buffer.\n"); XDamageDestroy(display, damage); - xdisplay.close(); + this->xdisplay.close(); } void VNCServer::stop_service() @@ -95,7 +95,7 @@ void VNCServer::start_service(Websocket &ws) { register XImage *image; const XserverRegion xregion = XFixesCreateRegion(this->display, NULL, 0); - while(isRunning) + while(this->isRunning) { threadSleep(); if (ws.clients > 0) @@ -112,7 +112,7 @@ void VNCServer::start_service(Websocket &ws) 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); @@ -133,11 +133,16 @@ void VNCServer::start_service(Websocket &ws) char *info = (char *)data.c_str(); int infoSize = strlen(info); if(!XDestroyImage(image)) free(image); - ws.sendFrame(info, buffer, infoSize, compressedSize); + ws.sendFrame(info, this->buffer, infoSize, compressedSize); } XFree(rect); } } + else{ + while(ws.clients == 0){ + sleep(1); + } + } } } @@ -147,8 +152,8 @@ void VNCServer::threadSleep() int i = this->sleepLoop; while(i--) { - inputs->dispatchEvents(); - usleep(sleepDelay); + this->inputs->dispatchEvents(); + usleep(this->sleepDelay); } } diff --git a/libs/websocket.hpp b/libs/websocket.hpp index 1a9ba0a..3c917fc 100644 --- a/libs/websocket.hpp +++ b/libs/websocket.hpp @@ -52,10 +52,10 @@ class Websocket int socketPort = 8080; 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); - void decode(char *src,char * dest); + void decode(unsigned char *src,char * dest); void (*callBack)(int sid) = NULL; void (*callBackMsg)(void *data, int sid) = NULL; }; @@ -84,7 +84,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 +95,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,17 +105,17 @@ 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; + FD_SET(this->server_fd, &readfds); + max_sd = this->server_fd; for (int i = 0; i < 5; i++) { int sd = client_socket[i]; @@ -129,14 +129,14 @@ 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; 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++) { @@ -179,7 +179,7 @@ void Websocket::connections() client_socket[i] = 0; this->ws_client_socket[i] = 0; clients--; - printf("client dicon : %d\n", sd); + printf("Host disconnected : %d\n", sd); } else { @@ -198,10 +198,10 @@ 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) { @@ -222,7 +222,7 @@ 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; } @@ -348,14 +348,13 @@ 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 } } -void Websocket::decode(char *data , char * result) +void Websocket::decode(unsigned char *data, char *result) { if(data[0] == 0) return; // decode a websocket frame which is less than 125 bytes From 0234274a9bcd9b5ba6efa2e57f38a402cc6ebc72 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Mon, 27 Jun 2022 23:32:18 +0530 Subject: [PATCH 09/23] max client error added --- libs/httpPage.hpp | 2 +- libs/websocket.hpp | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp index 277f79b..876a8b9 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( diff --git a/libs/websocket.hpp b/libs/websocket.hpp index 3c917fc..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,6 +51,7 @@ class Websocket private: int socketPort = 8080; + int max_clients = (MAX_CLIENTS < 25) ? MAX_CLIENTS : 25; int server_fd; void connections(); void handshake(unsigned char *d, int sd, int sid); @@ -116,7 +118,7 @@ void Websocket::connections() FD_ZERO(&readfds); FD_SET(this->server_fd, &readfds); max_sd = this->server_fd; - for (int i = 0; i < 5; i++) + for (int i = 0; i < this->max_clients; i++) { int sd = client_socket[i]; if (sd > 0) @@ -137,20 +139,29 @@ void Websocket::connections() exit(EXIT_FAILURE); } 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,7 +190,7 @@ void Websocket::connections() client_socket[i] = 0; this->ws_client_socket[i] = 0; clients--; - printf("Host disconnected : %d\n", sd); + printf("Host disconnected : %d | current active clients %d\n", sd,clients); } else { From ddc4d041829a57b7cde559296d268616558f2c1a Mon Sep 17 00:00:00 2001 From: jishan484 Date: Mon, 27 Jun 2022 23:42:20 +0530 Subject: [PATCH 10/23] MouseMove delay reduced to 0 --- libs/httpPage.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp index 876a8b9..71d3397 100644 --- a/libs/httpPage.hpp +++ b/libs/httpPage.hpp @@ -9736,13 +9736,13 @@ void parseHttpPage() return false; }; canvas.onmousemove = function(e) { - clearTimeout(mouseMoveTimeOut); - mouseMoveTimeOut = setTimeout(function(){ + //clearTimeout(mouseMoveTimeOut); + //mouseMoveTimeOut = setTimeout(function(){ var x = Math.floor(e.offsetX / canvas.offsetWidth * canvas.width) var y = Math.floor(e.offsetY / canvas.offsetHeight * canvas.height) data = "M" + x + " " + y + " "; ws.send(data); - }, 200); + //}, 200); } canvas.onwheel = function(e){ e.preventDefault(); From fc3f0dd348a529c7afce542ab4c83faf80e7c625 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Mon, 27 Jun 2022 23:45:48 +0530 Subject: [PATCH 11/23] MouseMove delay reduced to 100 --- libs/httpPage.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp index 876a8b9..71d3397 100644 --- a/libs/httpPage.hpp +++ b/libs/httpPage.hpp @@ -9736,13 +9736,13 @@ void parseHttpPage() return false; }; canvas.onmousemove = function(e) { - clearTimeout(mouseMoveTimeOut); - mouseMoveTimeOut = setTimeout(function(){ + //clearTimeout(mouseMoveTimeOut); + //mouseMoveTimeOut = setTimeout(function(){ var x = Math.floor(e.offsetX / canvas.offsetWidth * canvas.width) var y = Math.floor(e.offsetY / canvas.offsetHeight * canvas.height) data = "M" + x + " " + y + " "; ws.send(data); - }, 200); + //}, 200); } canvas.onwheel = function(e){ e.preventDefault(); From 6b30064ceb24086acf741e24912035b314f9dfaf Mon Sep 17 00:00:00 2001 From: jishan484 Date: Mon, 27 Jun 2022 23:46:06 +0530 Subject: [PATCH 12/23] mouseDelay 100ms --- libs/httpPage.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp index 71d3397..220f4e7 100644 --- a/libs/httpPage.hpp +++ b/libs/httpPage.hpp @@ -9736,13 +9736,13 @@ void parseHttpPage() return false; }; canvas.onmousemove = function(e) { - //clearTimeout(mouseMoveTimeOut); - //mouseMoveTimeOut = setTimeout(function(){ + clearTimeout(mouseMoveTimeOut); + mouseMoveTimeOut = setTimeout(function(){ var x = Math.floor(e.offsetX / canvas.offsetWidth * canvas.width) 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(); From 19881c3fb82ae20f6a9f5e68425aebd90dee5c6c Mon Sep 17 00:00:00 2001 From: jishan484 Date: Mon, 27 Jun 2022 23:49:57 +0530 Subject: [PATCH 13/23] MouseDeplay to 100ms --- libs/httpPage.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/httpPage.hpp b/libs/httpPage.hpp index 86f55f9..220f4e7 100644 --- a/libs/httpPage.hpp +++ b/libs/httpPage.hpp @@ -9736,17 +9736,13 @@ void parseHttpPage() return false; }; canvas.onmousemove = function(e) { - //clearTimeout(mouseMoveTimeOut); - //mouseMoveTimeOut = setTimeout(function(){ + clearTimeout(mouseMoveTimeOut); + mouseMoveTimeOut = setTimeout(function(){ var x = Math.floor(e.offsetX / canvas.offsetWidth * canvas.width) var y = Math.floor(e.offsetY / canvas.offsetHeight * canvas.height) data = "M" + x + " " + y + " "; ws.send(data); -<<<<<<< HEAD }, 100); -======= - //}, 200); ->>>>>>> ddc4d041829a57b7cde559296d268616558f2c1a } canvas.onwheel = function(e){ e.preventDefault(); From 7568e6ff44b728435f83f541a930baacc9e1bfd8 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 01:21:28 +0530 Subject: [PATCH 14/23] first commit with Shm update --- compile.sh | 2 +- libs/display.hpp | 2 ++ libs/vncserver.hpp | 29 ++++++++++++++++++++--------- 3 files changed, 23 insertions(+), 10 deletions(-) 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/display.hpp b/libs/display.hpp index f9e794c..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; @@ -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; } diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 6d8404d..b0b7dd7 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -26,7 +26,8 @@ #include #include #include - +#include +#include #include "display.hpp" #include "input.hpp" @@ -53,6 +54,8 @@ class VNCServer int sleepLoop = (1000000 / FPS)/this->sleepDelay; int bufferSize = 1000000; char *buffer; + XShmSegmentInfo shminfo; + XImage *image; }; VNCServer::VNCServer() @@ -76,6 +79,9 @@ VNCServer::VNCServer() VNCServer::~VNCServer() { + // free image + XDestroyImage(this->image); + XShmDetach(this->display, &shminfo); free(this->buffer); printf("[INFO] Memory released for VNC buffer.\n"); XDamageDestroy(display, damage); @@ -93,7 +99,15 @@ void VNCServer::send_first_frame(int sd) } void VNCServer::start_service(Websocket &ws) { - register 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(this->isRunning) { @@ -102,8 +116,7 @@ void VNCServer::start_service(Websocket &ws) { 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, this->buffer, frameSize, this->bufferSize); std::string data = "UPD" + std::to_string(0) + " " + std::to_string(0) + " " @@ -111,7 +124,6 @@ void VNCServer::start_service(Websocket &ws) + 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(this->config, this->clientSD); ws.sendFrame(info, buffer, infoSize, compressedSize, this->clientSD); this->sendFirstFrame = false; @@ -124,15 +136,14 @@ 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, this->buffer, frameSize, this->bufferSize); + XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); + int frameSize = (rect[i].height * image->bytes_per_line) - (rect[i].x * rect[i].y); + int compressedSize = LZ4_compress_default(image->data + (rect[i].x * rect[i].y), 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"; char *info = (char *)data.c_str(); int infoSize = strlen(info); - if(!XDestroyImage(image)) free(image); ws.sendFrame(info, this->buffer, infoSize, compressedSize); } XFree(rect); From fc0f7d5512087f59c1c30acf0add5c30293ee1df Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 01:29:54 +0530 Subject: [PATCH 15/23] A little miscalculation fixed --- libs/vncserver.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index b0b7dd7..7ceebd9 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -137,8 +137,9 @@ void VNCServer::start_service(Websocket &ws) for (int i = 0; i < partCounts; i++) { XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); - int frameSize = (rect[i].height * image->bytes_per_line) - (rect[i].x * rect[i].y); - int compressedSize = LZ4_compress_default(image->data + (rect[i].x * rect[i].y), this->buffer, frameSize, this->bufferSize); + int cropx = ((rect[i].x *image->bytes_per_line) + rect[i].y); + int frameSize = (rect[i].height * image->bytes_per_line) - cropx; + int compressedSize = LZ4_compress_default(image->data + cropx, 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"; From 749846b1175cd5122baee6c108bdf253725fc81b Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 01:32:21 +0530 Subject: [PATCH 16/23] hi --- libs/vncserver.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 7ceebd9..590a429 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -134,10 +134,14 @@ void VNCServer::start_service(Websocket &ws) int partCounts = 0; XDamageSubtract(this->display, this->damage, None, xregion); XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); + rect->x = 200; + rect->y = 200; + rect->width = 100; + rect->height = 100; for (int i = 0; i < partCounts; i++) { XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); - int cropx = ((rect[i].x *image->bytes_per_line) + rect[i].y); + int cropx = ((rect[i].y *image->bytes_per_line) + rect[i].x); int frameSize = (rect[i].height * image->bytes_per_line) - cropx; int compressedSize = LZ4_compress_default(image->data + cropx, this->buffer, frameSize, this->bufferSize); std::string data = "UPD" + std::to_string(rect[i].x) + " " + std::to_string(rect[i].y) + " " From 8a6af76c44fc5c031f9d4563b9f9fcc7dd4a6e4a Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 01:33:15 +0530 Subject: [PATCH 17/23] kk --- libs/vncserver.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 590a429..2adcc0d 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -134,10 +134,6 @@ void VNCServer::start_service(Websocket &ws) int partCounts = 0; XDamageSubtract(this->display, this->damage, None, xregion); XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); - rect->x = 200; - rect->y = 200; - rect->width = 100; - rect->height = 100; for (int i = 0; i < partCounts; i++) { XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); From 2391c17ffcd5406a245689a052839fa93a7a1759 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 11:43:59 +0530 Subject: [PATCH 18/23] fixed --- libs/vncserver.hpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 2adcc0d..7147fe1 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -43,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, char *subImage); Display * display; Damage damage; ScreenInfo screenInfo; @@ -54,6 +55,7 @@ class VNCServer int sleepLoop = (1000000 / FPS)/this->sleepDelay; int bufferSize = 1000000; char *buffer; + char *tempBuffer; XShmSegmentInfo shminfo; XImage *image; }; @@ -70,6 +72,7 @@ VNCServer::VNCServer() 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"); @@ -83,6 +86,7 @@ VNCServer::~VNCServer() XDestroyImage(this->image); XShmDetach(this->display, &shminfo); free(this->buffer); + free(this->tempBuffer); printf("[INFO] Memory released for VNC buffer.\n"); XDamageDestroy(display, damage); this->xdisplay.close(); @@ -103,7 +107,6 @@ void VNCServer::start_service(Websocket &ws) 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; @@ -136,13 +139,18 @@ void VNCServer::start_service(Websocket &ws) XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); for (int i = 0; i < partCounts; i++) { + // rect[i].x = 0; + // rect[i].y = 0; + // rect[i].width -= rect[i].x; + // rect[i].height -= rect[i].y; XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); - int cropx = ((rect[i].y *image->bytes_per_line) + rect[i].x); - int frameSize = (rect[i].height * image->bytes_per_line) - cropx; - int compressedSize = LZ4_compress_default(image->data + cropx, this->buffer, frameSize, this->bufferSize); + int bytes = (image->bytes_per_line / this->screenInfo.width)*rect[i].width; + int frameSize = (rect[i].height * bytes); + this->getSubImage(image->data, rect[i].x, rect[i].y, rect[i].width, rect[i].height, 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); ws.sendFrame(info, this->buffer, infoSize, compressedSize); @@ -169,4 +177,15 @@ void VNCServer::threadSleep() } } +void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height, char *subImageData){ + int startPoint = (y * this->image->bytes_per_line) + (x); + int bytePerLine = (image->bytes_per_line / this->screenInfo.width) * width; + for (int i = 0; i < height; i++) + { + strncpy(subImageData, imageData + startPoint, bytePerLine); + subImageData += bytePerLine; + startPoint += this->image->bytes_per_line; + } +} + #endif \ No newline at end of file From e7d94755af8685dab9fe92b5080eeeadcc8367af Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 12:38:50 +0530 Subject: [PATCH 19/23] fixed --- libs/vncserver.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 7147fe1..1ecc66c 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -176,16 +176,17 @@ void VNCServer::threadSleep() usleep(this->sleepDelay); } } - void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height, char *subImageData){ int startPoint = (y * this->image->bytes_per_line) + (x); int bytePerLine = (image->bytes_per_line / this->screenInfo.width) * width; for (int i = 0; i < height; i++) { - strncpy(subImageData, imageData + startPoint, bytePerLine); + memcpy(subImageData, imageData + startPoint, bytePerLine); subImageData += bytePerLine; startPoint += this->image->bytes_per_line; } } + + #endif \ No newline at end of file From b64801e6e1eb4f2f86d8356b42f89ba00d045667 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 13:15:37 +0530 Subject: [PATCH 20/23] test --- libs/vncserver.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 1ecc66c..3f99745 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -139,10 +139,10 @@ void VNCServer::start_service(Websocket &ws) XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); for (int i = 0; i < partCounts; i++) { - // rect[i].x = 0; - // rect[i].y = 0; - // rect[i].width -= rect[i].x; - // rect[i].height -= rect[i].y; + rect[i].x = 0; + rect[i].y = 53; + rect[i].width = 173; + rect[i].height -= rect[i].y; XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); int bytes = (image->bytes_per_line / this->screenInfo.width)*rect[i].width; int frameSize = (rect[i].height * bytes); @@ -177,7 +177,11 @@ void VNCServer::threadSleep() } } void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height, char *subImageData){ - int startPoint = (y * this->image->bytes_per_line) + (x); + 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); int bytePerLine = (image->bytes_per_line / this->screenInfo.width) * width; for (int i = 0; i < height; i++) { From 13b88f51b0f2871a93af2e3ceb3df6f22a766768 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 13:34:33 +0530 Subject: [PATCH 21/23] tes t --- libs/vncserver.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 1ecc66c..3f99745 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -139,10 +139,10 @@ void VNCServer::start_service(Websocket &ws) XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); for (int i = 0; i < partCounts; i++) { - // rect[i].x = 0; - // rect[i].y = 0; - // rect[i].width -= rect[i].x; - // rect[i].height -= rect[i].y; + rect[i].x = 0; + rect[i].y = 53; + rect[i].width = 173; + rect[i].height -= rect[i].y; XShmGetImage(this->display, this->screenInfo.root, image, 0, 0, AllPlanes); int bytes = (image->bytes_per_line / this->screenInfo.width)*rect[i].width; int frameSize = (rect[i].height * bytes); @@ -177,7 +177,11 @@ void VNCServer::threadSleep() } } void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height, char *subImageData){ - int startPoint = (y * this->image->bytes_per_line) + (x); + 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); int bytePerLine = (image->bytes_per_line / this->screenInfo.width) * width; for (int i = 0; i < height; i++) { From d9a030d04601b5524ba3a0f4fab9c400ba1fa4c7 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 17:16:45 +0530 Subject: [PATCH 22/23] fixed --- libs/vncserver.hpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 3f99745..9d60be5 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -43,7 +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, char *subImage); + void getSubImage(char *image, int x, int y, int width, int height,int bpl, char *subImage); Display * display; Damage damage; ScreenInfo screenInfo; @@ -139,14 +139,12 @@ void VNCServer::start_service(Websocket &ws) XRectangle *rect = XFixesFetchRegion(this->display, xregion, &partCounts); for (int i = 0; i < partCounts; i++) { - rect[i].x = 0; - rect[i].y = 53; - rect[i].width = 173; - rect[i].height -= rect[i].y; 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, this->tempBuffer); + this->getSubImage(image->data, rect[i].x, rect[i].y, rect[i].width, rect[i].height,bytes, this->tempBuffer); + std::cout << "x:"<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) + " " @@ -176,17 +174,16 @@ void VNCServer::threadSleep() usleep(this->sleepDelay); } } -void VNCServer::getSubImage(char *imageData, int x, int y, int width, int height, char *subImageData){ +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); - int bytePerLine = (image->bytes_per_line / this->screenInfo.width) * width; + startPoint = (y * this->image->bytes_per_line) + (x << 1); for (int i = 0; i < height; i++) { - memcpy(subImageData, imageData + startPoint, bytePerLine); - subImageData += bytePerLine; + memcpy(subImageData, imageData + startPoint, bpl); + subImageData += bpl; startPoint += this->image->bytes_per_line; } } From 038b3c122ee9778d373e083987bb369f19217434 Mon Sep 17 00:00:00 2001 From: jishan484 Date: Thu, 30 Jun 2022 17:17:08 +0530 Subject: [PATCH 23/23] ss --- libs/vncserver.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/vncserver.hpp b/libs/vncserver.hpp index 9d60be5..7890404 100644 --- a/libs/vncserver.hpp +++ b/libs/vncserver.hpp @@ -144,7 +144,6 @@ void VNCServer::start_service(Websocket &ws) // 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); - std::cout << "x:"<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) + " "