Kod nawiązywania połączenia (tzw. handshake) oraz wysyłania odpowiedzi do klienta 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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | #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 printT(uint8_t* tab, int count) { cout << "{"; for (int i = 0; i < count; i++) { cout << (unsigned int)tab[i] << ", "; } cout << "}"; } 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(8080); //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); while (1) { bytesRecv = recv(mainSocket, recvbuf, 32, 0); if (bytesRecv == 0 || bytesRecv == WSAECONNRESET) { printf("Connection closed.\n"); break; } if (bytesRecv < 0) return 1; printf("\nNew QUERY! Bytes received: %ld\n", bytesRecv); //printf("Received text: %s\n", recvbuf); for (int i = 0; i < bytesRecv; i++) { int zmienna = (uint8_t)recvbuf[i]; printf("%i,", zmienna); } int zmienna2 = (uint8_t)recvbuf[0]; unsigned int fin = zmienna2 >> 7; cout << "\nFIN: " << fin; unsigned int opcode = zmienna2 & 0b00001111; // 4 ostatnie bity cout << "\nOpcode: " << opcode; if (opcode == 0x8) { return 0; } unsigned int pay_len = recvbuf[1] & 0b01111111; cout << "\nPayload length: " << pay_len; uint8_t maska[4]; memcpy(maska, recvbuf + 2, 4); printT(maska, 4); uint8_t DECODED[1024]; char* ENCODED = recvbuf + 6; for (int i = 0; i < pay_len; i++) { DECODED[i] = ENCODED[i] ^ maska[i % 4]; } DECODED[pay_len] = '\0'; cout << "\nWiadomosc: " << DECODED; printT((uint8_t*)ENCODED, pay_len); uint8_t answer[2048]; answer[0] = 1 << 7; answer[0] |= 1; answer[1] = 0 << 7; // brak maski; w odp nie robimy maski answer[1] |= pay_len; memcpy(answer + 2, DECODED, pay_len); send(mainSocket, (char*)answer, pay_len+2, 0); } system("pause"); return 0; } |