Kod nawiązywania połączenia (tzw. handshake) w C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <iostream> #include <string> #include "base64.c" #include "sha1.c" #include <fstream> #include <sstream> #pragma comment(lib, "Ws2_32.lib") using namespace std; void wifi_ws_generate_ssh1(char* source, char* generated) { //Generuje odpowiedź da klucza wysłanego przez klienta websocket na HANDSHAKE (pierwszy GET) //UWAGA! Musi być przyznana pamięć dla generated 128 //TODO wygenerować swoj Magic Key: const char* magicStringFX = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";//"7AC87B2C-9579-4E7D-8E5D-663F60E4797B";//"7ac87b2c-9579-4e7d-8e5d-663f60e4797b"; //char *magicTest = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; char shaSourceGUID[128];//"dGhlIHNhbXBsZSBub25jZQ=="; //24 strcpy_s(shaSourceGUID, source); //pierwsza czesc stringu to kopia strcat_s(shaSourceGUID, magicStringFX); char SHA1result[32];//21 SHA1(SHA1result, shaSourceGUID, strlen(shaSourceGUID)); Base64encode(generated, SHA1result, strlen(SHA1result)); } void wifi_ws_handshake_send(char* wsKey, uint8_t channel, char* handShake) { char wsKeyResponse[128]; wifi_ws_generate_ssh1(wsKey, wsKeyResponse); snprintf(handShake, 1023, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\nSec-WebSocket-Protocol: lws-minimal\r\nAccess-Control-Allow-Origin: *\r\n\n", wsKeyResponse); //"HTTP/1.1 101 Switching Protocols\nUpgrade: WebSocket\nConnection: Upgrade\nSec-WebSocket-Accept: BG/pdcLBIS/cwqVQmA3LWkinc7U=\nSec-WebSocket-Protocol: lws-minimal\n"); signed int l = strlen(handShake); } int main() { WSADATA wsaData; int result = WSAStartup(MAKEWORD(2, 2), &wsaData); if (result != NO_ERROR) printf("Initialization error.\n"); //cz2 SOCKET mainSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (mainSocket == INVALID_SOCKET) { printf("Error creating socket: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } //cz3 sockaddr_in service; memset(&service, 0, sizeof(service)); service.sin_family = AF_INET; //service.sin_addr.s_addr = inet_addr("127.0.0.1"); InetPton(AF_INET, (PCWSTR)"127.0.0.1", &service.sin_addr.s_addr); //adres nasłuchujący service.sin_port = htons(27015); //port if (bind(mainSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) { printf("bind() failed.\n"); closesocket(mainSocket); return 1; } if (listen(mainSocket, 1) == SOCKET_ERROR) printf("Error listening on socket.\n"); SOCKET acceptSocket = SOCKET_ERROR; printf("Waiting for a client to connect...\n"); while (acceptSocket == SOCKET_ERROR) { acceptSocket = accept(mainSocket, NULL, NULL); } printf("Client connected.\n"); mainSocket = acceptSocket; int bytesSent; int bytesRecv = SOCKET_ERROR; char sendbuf[4048] = "Server says hello!"; char recvbuf[4048] = ""; bytesRecv = recv(mainSocket, recvbuf, 4048, 0); printf("Bytes received: %ld\n", bytesRecv); printf("Received text: %s\n", recvbuf); char handShake[1024]; //Access-Control-Allow-Origin: * char* websocketKey = strstr((char*)recvbuf, "Sec-WebSocket-Key: "); if (websocketKey) { //znaleziono klucz Handshake w żądaniu HTTP websocketKey += 19; //"Sec-WebSocket-Key: " dalej printf("Websocket connection! Sending HTTP handshake.\r\n"); char* websocketKeyEnd = strchr(websocketKey, '\r'); if (!websocketKeyEnd) websocketKeyEnd = strchr(websocketKey, '\n'); if (!websocketKeyEnd) { printf("ERROR: \r or \n not found after the key!"); } else { //znaleziono \r lun \n po kluczu handshake char wsKey[64]; uint8_t wsKeyLen = websocketKeyEnd - websocketKey; //dlugosc to wskaznik konca-poczatku if (wsKeyLen <= 63) { //max dlugosc klucza hs memcpy(wsKey, websocketKey, wsKeyLen); //zapisz klucz do nowej zmiennej wsKey[wsKeyLen] = '\0'; //zakoncz string wifi_ws_handshake_send(wsKey, 0, handShake); //wyslij odpowiedz handshake z nowym kluczem } else {//za dlugi klucz w naglowku HTTP (powinno być <32 znaki ma 64 ale i to nie starczylo printf("ERROR: too long websocketKey: %i\r\n", wsKeyLen); } } } else { printf("Websocket key not received from client - broken HTTP header!\r\n"); } //wysyłamy odpowiedź bytesSent = send(mainSocket, handShake, strlen(handShake), 0); printf("Bytes sent: %ld\n", bytesSent); system("pause"); return 0; } |
Nawiązujemy połączenie klikając TEST
Kod po stronie klienta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Testing websocket</title> </head> <body> <button onclick="testWebSocket()">TEST</button> <br /> <button onclick="doSend('7')">Send 7</button> <button onclick="doSend('0')">Send 0</button> <button onclick="doSend('1')">Send 1</button> <button onclick="doSend('Hi')">Send Hi</button> <button onclick="doSend('Hello')">Send Hello</button><br /> <button onclick="doSend('DISCONNECT')">DISCONNECT SEND</button><br /> <button onclick="websocket.close()">Close</button> <script> var wsUri = "ws://127.0.0.1:27015"; // "wss://echo.websocket.org/"; var output; function testWebSocket() { websocket = new WebSocket(wsUri, "lws-minimal"); //lws-minimal BARDZO WAŻNE: lws-minimal oznacza naszą bibliotekę z C++ i jej protokół websocket.onopen = function (evt) { onOpen(evt); }; websocket.onclose = function (evt) { onClose(evt); }; websocket.onmessage = function (evt) { onMessage(evt); }; websocket.onerror = function (evt) { onError(evt); }; } function onOpen(evt) { console.log("CONNECTED"); } function onClose(evt) { console.log("DISCONNECTED"); } function onMessage(evt) { console.log("RESPONSE: " + evt.data + ""); if (evt.data == "DISCONNECT") websocket.close(); } function onError(evt) { console.log("ERROR: " + JSON.stringify(evt)); } function doSend(message) { console.log("SENT: " + message); websocket.send(message); } </script> </body> </html> |