John Lowe
/
WebSockets2
Embedded WebSockets Experiment
Embed:
(wiki syntax)
Show/hide line numbers
HTTPWebSocketHandler.cpp
00001 #include "HTTPWebSocketHandler.h" 00002 #include "md5.h" 00003 #include "TemperatureSensor.h" 00004 #include "RGBLed.h" 00005 00006 extern TemperatureSensor sensor; 00007 extern RGBLed rgb; 00008 00009 HTTPWebSocketConnectingState::HTTPWebSocketConnectingState() { 00010 memset(challange, 0, 16); 00011 } 00012 00013 HTTPStatus HTTPWebSocketConnectingState::init(HTTPConnection *conn) { 00014 uint32_t key1Part= computeKeyPart(conn->getField("Sec-WebSocket-Key1")); 00015 uint32_t key2Part= computeKeyPart(conn->getField("Sec-WebSocket-Key2")); 00016 00017 challange[0]= (key1Part >> 24) & 0xFF; 00018 challange[1]= (key1Part >> 16) & 0xFF; 00019 challange[2]= (key1Part >> 8) & 0xFF; 00020 challange[3]= (key1Part >> 0) & 0xFF; 00021 challange[4]= (key2Part >> 24) & 0xFF; 00022 challange[5]= (key2Part >> 16) & 0xFF; 00023 challange[6]= (key2Part >> 8) & 0xFF; 00024 challange[7]= (key2Part >> 0) & 0xFF; 00025 00026 char headers[1024]; 00027 char *str; 00028 00029 memset(headers, 0, 1024); 00030 strcat(headers, "Upgrade: WebSocket\r\n"); 00031 strcat(headers, "Connection: Upgrade\r\n"); 00032 00033 // The host field string can have junk at the end... 00034 str= (char*) conn->getField("Host"); 00035 for (char *p= str; *p != 0; p++) { 00036 if(!isprint(*p)) { 00037 *p= 0; 00038 } 00039 } 00040 strcat(headers, "Sec-WebSocket-Location: ws://"); 00041 strcat(headers, str); 00042 strcat(headers, conn->getURL()); 00043 strcat(headers, "\r\n"); 00044 00045 // The host field string can have junk at the end... 00046 str= (char*) conn->getField("Origin"); 00047 for (char *p= str; *p != 0; p++) { 00048 if(!isprint(*p)) { 00049 *p= 0; 00050 } 00051 } 00052 strcat(headers, "Sec-WebSocket-Origin: "); 00053 strcat(headers, str); 00054 strcat(headers, "\r\n"); 00055 conn->setLength(16); 00056 conn->setHeaderFields(headers); 00057 00058 printf("\n%s\n", headers); 00059 00060 return HTTP_SwitchProtocols; 00061 } 00062 00063 HTTPHandle HTTPWebSocketConnectingState::data(HTTPConnection *conn, void *data, int len) { 00064 // The body needs to hold key3, and only key3 00065 if (len != 8) { 00066 printf("key3 length error\n"); 00067 return HTTP_Failed; 00068 } 00069 00070 // Copy key3 into the challange 00071 memcpy(challange+8, data, 8); 00072 00073 printf("Challange: "); 00074 for (int i= 0; i<16; i++) { 00075 printf("%02x ", challange[i]); 00076 } 00077 printf("\n"); 00078 00079 return HTTP_Success; 00080 } 00081 00082 HTTPHandle HTTPWebSocketConnectingState::send(HTTPConnection *conn, int maxData) { 00083 MD5 md5; 00084 md5.update(challange, 16); 00085 const char *hex= md5.finalize().hexdigest().c_str(); 00086 char binary[16]; 00087 hexStringToBinary(hex, binary); 00088 conn->write(binary, 16, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE)); 00089 00090 printf("MD5 bin: "); 00091 for (int i= 0; i<16; i++) { 00092 printf("%02x ", binary[i]); 00093 } 00094 printf("\n"); 00095 00096 delete conn->data; 00097 conn->data= new HTTPWebSocketStreamingState(); 00098 return HTTP_Success; 00099 } 00100 00101 uint32_t HTTPWebSocketConnectingState::extractNumber(const char *keyValue) { 00102 uint32_t value= 0; 00103 while (*keyValue) { 00104 if (isdigit(*keyValue)) { 00105 value= value*10 + (*keyValue-'0'); 00106 }; 00107 keyValue++; 00108 }; 00109 return value; 00110 } 00111 00112 uint32_t HTTPWebSocketConnectingState::countSpaces(const char *keyValue) { 00113 uint32_t count= 0; 00114 while (*keyValue) { 00115 if (*keyValue == 0x20) { 00116 count++; 00117 } 00118 keyValue++; 00119 } 00120 return count; 00121 } 00122 00123 uint32_t HTTPWebSocketConnectingState::computeKeyPart(const char *keyValue) { 00124 if (keyValue != NULL) { 00125 printf("key:%s:\n", keyValue); 00126 uint32_t keyPart= extractNumber(keyValue) / countSpaces(keyValue); 00127 printf("keyPart: %08x\n", keyPart); 00128 return keyPart; 00129 } 00130 // No key value 00131 return 0; 00132 } 00133 00134 void HTTPWebSocketConnectingState::hexStringToBinary(const char *hex, char *binary) { 00135 while (*hex) { 00136 char c; 00137 00138 c= *hex++; 00139 *binary= (c < '@' ? c-'0' : c-'a'+10) << 4; 00140 c= *hex++; 00141 *binary |= (c < '@' ? c-'0' : c-'a'+10); 00142 binary++; 00143 } 00144 } 00145 00146 //----- 00147 00148 HTTPWebSocketStreamingState::HTTPWebSocketStreamingState() : led(LED2) { 00149 sendCnt= 0; 00150 } 00151 00152 HTTPStatus HTTPWebSocketStreamingState::init(HTTPConnection *conn) { 00153 return HTTP_InternalServerError; // ignored 00154 } 00155 00156 HTTPHandle HTTPWebSocketStreamingState::data(HTTPConnection *conn, void *data, int len) { 00157 char *str= ((char*)data)+1; // skip leading 0x00 00158 str[len]= 0; // stop on trailing 0xFF 00159 //printf("IN:%d:%s\n", len, str); 00160 rgb.setRgb(str); 00161 return HTTP_Success; 00162 } 00163 00164 HTTPHandle HTTPWebSocketStreamingState::send(HTTPConnection *conn, int maxData) { 00165 char buffer[80]; 00166 int len; 00167 00168 if (sendCnt > 1000) { 00169 sprintf(buffer, "%c%f,%f,%f\n%c", 0x00, sensor.getPercentOfScale(), sensor.getResistance(), sensor.getKelvin(), 0xFF); 00170 len= strlen(buffer+1); 00171 conn->write(buffer, len+1); 00172 sendCnt= 0; 00173 //led= !led; 00174 } else { 00175 sensor.measure(); 00176 sendCnt++; 00177 } 00178 00179 return HTTP_Success; 00180 } 00181 00182 //----- 00183 00184 // Register headers required by this handler. Headers that are not registered will 00185 // be stripped by the server. 00186 void HTTPWebSocketHandler::reg(HTTPServer *server) { 00187 server->registerField("Sec-WebSocket-Key1"); 00188 server->registerField("Sec-WebSocket-Key2"); 00189 server->registerField("Host"); 00190 server->registerField("Origin"); 00191 } 00192 00193 HTTPStatus HTTPWebSocketHandler::init(HTTPConnection *conn) const { 00194 // Todo: validate headers 00195 HTTPWebSocketState *state= new HTTPWebSocketConnectingState(); 00196 conn->data= state; 00197 HTTPStatus status= state->init(conn); 00198 printf("init: %d\n", status); 00199 return status; 00200 } 00201 00202 HTTPHandle HTTPWebSocketHandler::data(HTTPConnection *conn, void *data, int len) const { 00203 HTTPWebSocketState *state= (HTTPWebSocketState *) conn->data; 00204 HTTPHandle result= state->data(conn, data, len); 00205 //printf("data: %d\n", result); 00206 return result; 00207 } 00208 00209 HTTPHandle HTTPWebSocketHandler::send(HTTPConnection *conn, int maxData) const { 00210 HTTPWebSocketState *state= (HTTPWebSocketState *) conn->data; 00211 HTTPHandle result= state->send(conn, maxData); 00212 //printf("send: %d\n", result); 00213 return result; 00214 } 00215
Generated on Wed Jul 13 2022 23:42:33 by 1.7.2