Embedded WebSockets Experiment

Dependencies:   mbed MD5

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPWebSocketHandler.cpp Source File

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