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