Network Services

Dependents:   PwrCond_mbed5

Fork of W5500Interface_K22F by Andrew McCartney

Committer:
dgriffin65
Date:
Thu Jun 15 20:29:03 2017 +0000
Revision:
15:14382459c8b7
Converted to a single library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgriffin65 15:14382459c8b7 1 /* Copyright (C) 2013 Hiroshi Suga, MIT License
dgriffin65 15:14382459c8b7 2 *
dgriffin65 15:14382459c8b7 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
dgriffin65 15:14382459c8b7 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
dgriffin65 15:14382459c8b7 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
dgriffin65 15:14382459c8b7 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
dgriffin65 15:14382459c8b7 7 * furnished to do so, subject to the following conditions:
dgriffin65 15:14382459c8b7 8 *
dgriffin65 15:14382459c8b7 9 * The above copyright notice and this permission notice shall be included in all copies or
dgriffin65 15:14382459c8b7 10 * substantial portions of the Software.
dgriffin65 15:14382459c8b7 11 *
dgriffin65 15:14382459c8b7 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
dgriffin65 15:14382459c8b7 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
dgriffin65 15:14382459c8b7 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
dgriffin65 15:14382459c8b7 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
dgriffin65 15:14382459c8b7 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
dgriffin65 15:14382459c8b7 17 */
dgriffin65 15:14382459c8b7 18
dgriffin65 15:14382459c8b7 19 #include "HTTPD.h"
dgriffin65 15:14382459c8b7 20 #include "sha1.h"
dgriffin65 15:14382459c8b7 21
dgriffin65 15:14382459c8b7 22 void HTTPD::recvWS (int id, char c) {
dgriffin65 15:14382459c8b7 23
dgriffin65 15:14382459c8b7 24 switch (_state[id].mode) {
dgriffin65 15:14382459c8b7 25 case MODE_WEBSOCKET:
dgriffin65 15:14382459c8b7 26 if (_state[id].n == 0) {
dgriffin65 15:14382459c8b7 27 // flag
dgriffin65 15:14382459c8b7 28 _state[id].websocket_opcode = c & 0x0f;
dgriffin65 15:14382459c8b7 29 _state[id].websocket_flg = c << 8;
dgriffin65 15:14382459c8b7 30 _state[id].n ++;
dgriffin65 15:14382459c8b7 31 } else
dgriffin65 15:14382459c8b7 32 if (_state[id].n == 1) {
dgriffin65 15:14382459c8b7 33 // length 7bit
dgriffin65 15:14382459c8b7 34 _state[id].websocket_flg |= c;
dgriffin65 15:14382459c8b7 35 _state[id].length = c & 0x7f;
dgriffin65 15:14382459c8b7 36 _state[id].n ++;
dgriffin65 15:14382459c8b7 37 if (_state[id].length < 126) {
dgriffin65 15:14382459c8b7 38 _state[id].n = 0;
dgriffin65 15:14382459c8b7 39 if (_state[id].length) {
dgriffin65 15:14382459c8b7 40 if (_state[id].websocket_flg & 0x0080) {
dgriffin65 15:14382459c8b7 41 _state[id].mode = MODE_WEBSOCKET_MASK;
dgriffin65 15:14382459c8b7 42 } else {
dgriffin65 15:14382459c8b7 43 _state[id].mode = MODE_WEBSOCKET_BODY;
dgriffin65 15:14382459c8b7 44 }
dgriffin65 15:14382459c8b7 45 } else {
dgriffin65 15:14382459c8b7 46 _state[id].mode = MODE_WEBSOCKET_ENTER;
dgriffin65 15:14382459c8b7 47 }
dgriffin65 15:14382459c8b7 48 DBG("ws length %d\r\n", _state[id].length);
dgriffin65 15:14382459c8b7 49 }
dgriffin65 15:14382459c8b7 50 } else {
dgriffin65 15:14382459c8b7 51 // length 16bit,64bit
dgriffin65 15:14382459c8b7 52 if (_state[id].n == 2) {
dgriffin65 15:14382459c8b7 53 _state[id].length = c;
dgriffin65 15:14382459c8b7 54 _state[id].n ++;
dgriffin65 15:14382459c8b7 55 } else
dgriffin65 15:14382459c8b7 56 if (_state[id].n < 9 && (_state[id].websocket_flg & 0x7f) == 127) {
dgriffin65 15:14382459c8b7 57 // 64bit
dgriffin65 15:14382459c8b7 58 _state[id].length = (_state[id].length << 8) | c;
dgriffin65 15:14382459c8b7 59 _state[id].n ++;
dgriffin65 15:14382459c8b7 60 } else {
dgriffin65 15:14382459c8b7 61 // end
dgriffin65 15:14382459c8b7 62 _state[id].length = (_state[id].length << 8) | c;
dgriffin65 15:14382459c8b7 63 _state[id].n = 0;
dgriffin65 15:14382459c8b7 64 if (_state[id].websocket_flg & 0x0080) {
dgriffin65 15:14382459c8b7 65 _state[id].mode = MODE_WEBSOCKET_MASK;
dgriffin65 15:14382459c8b7 66 } else {
dgriffin65 15:14382459c8b7 67 _state[id].mode = MODE_WEBSOCKET_BODY;
dgriffin65 15:14382459c8b7 68 }
dgriffin65 15:14382459c8b7 69 DBG("ws length2 %d\r\n", _state[id].length);
dgriffin65 15:14382459c8b7 70 }
dgriffin65 15:14382459c8b7 71 }
dgriffin65 15:14382459c8b7 72 break;
dgriffin65 15:14382459c8b7 73 case MODE_WEBSOCKET_MASK:
dgriffin65 15:14382459c8b7 74 // masking key
dgriffin65 15:14382459c8b7 75 _state[id].websocket_mask[_state[id].n] = c;
dgriffin65 15:14382459c8b7 76 _state[id].n ++;
dgriffin65 15:14382459c8b7 77 if (_state[id].n >= 4) {
dgriffin65 15:14382459c8b7 78 _state[id].n = 0;
dgriffin65 15:14382459c8b7 79 _state[id].mode = MODE_WEBSOCKET_BODY;
dgriffin65 15:14382459c8b7 80 DBG("ws mask\r\n");
dgriffin65 15:14382459c8b7 81 }
dgriffin65 15:14382459c8b7 82 break;
dgriffin65 15:14382459c8b7 83 case MODE_WEBSOCKET_BODY:
dgriffin65 15:14382459c8b7 84 // payload
dgriffin65 15:14382459c8b7 85 if (_state[id].websocket_flg & 0x0080) {
dgriffin65 15:14382459c8b7 86 // un-mask
dgriffin65 15:14382459c8b7 87 _state[id].buf->queue(c ^ _state[id].websocket_mask[_state[id].n & 0x03]);
dgriffin65 15:14382459c8b7 88 } else {
dgriffin65 15:14382459c8b7 89 _state[id].buf->queue(c);
dgriffin65 15:14382459c8b7 90 }
dgriffin65 15:14382459c8b7 91 _state[id].n ++;
dgriffin65 15:14382459c8b7 92 if (_state[id].n >= _state[id].length) {
dgriffin65 15:14382459c8b7 93 _state[id].mode = MODE_WEBSOCKET_ENTER;
dgriffin65 15:14382459c8b7 94 }
dgriffin65 15:14382459c8b7 95 break;
dgriffin65 15:14382459c8b7 96 }
dgriffin65 15:14382459c8b7 97 }
dgriffin65 15:14382459c8b7 98
dgriffin65 15:14382459c8b7 99 int HTTPD::parseWebsocket (int id) {
dgriffin65 15:14382459c8b7 100 int i;
dgriffin65 15:14382459c8b7 101
dgriffin65 15:14382459c8b7 102 DBG("ws opcode %d\r\n", _state[id].websocket_opcode);
dgriffin65 15:14382459c8b7 103 switch (_state[id].websocket_opcode) {
dgriffin65 15:14382459c8b7 104 case 0x00: // continuation
dgriffin65 15:14382459c8b7 105 break;
dgriffin65 15:14382459c8b7 106 case 0x01: // text
dgriffin65 15:14382459c8b7 107 case 0x02: // binary
dgriffin65 15:14382459c8b7 108 i = getHandler(_state[id].uri);
dgriffin65 15:14382459c8b7 109 if (i >= 0) {
dgriffin65 15:14382459c8b7 110 if (_handler[i].funcCgi) {
dgriffin65 15:14382459c8b7 111 // cgi
dgriffin65 15:14382459c8b7 112 _handler[i].funcCgi(id);
dgriffin65 15:14382459c8b7 113 }
dgriffin65 15:14382459c8b7 114 }
dgriffin65 15:14382459c8b7 115 break;
dgriffin65 15:14382459c8b7 116 case 0x08: // close
dgriffin65 15:14382459c8b7 117 _state[id].client->close();
dgriffin65 15:14382459c8b7 118 break;
dgriffin65 15:14382459c8b7 119 case 0x09: // ping
dgriffin65 15:14382459c8b7 120 {
dgriffin65 15:14382459c8b7 121 char pong[_state[id].n + 2];
dgriffin65 15:14382459c8b7 122 pong[0] = 0x8a;
dgriffin65 15:14382459c8b7 123 pong[1] = 0x04;
dgriffin65 15:14382459c8b7 124 for (i = 0; i < _state[id].length; i ++) {
dgriffin65 15:14382459c8b7 125 if (_state[id].buf->dequeue(&pong[i + 2]) == false) break;
dgriffin65 15:14382459c8b7 126 }
dgriffin65 15:14382459c8b7 127 _state[id].client->send(pong, _state[id].length + 2);
dgriffin65 15:14382459c8b7 128 }
dgriffin65 15:14382459c8b7 129 break;
dgriffin65 15:14382459c8b7 130 case 0x0a: // pong
dgriffin65 15:14382459c8b7 131 break;
dgriffin65 15:14382459c8b7 132 default:
dgriffin65 15:14382459c8b7 133 break;
dgriffin65 15:14382459c8b7 134 }
dgriffin65 15:14382459c8b7 135 _state[id].n = 0;
dgriffin65 15:14382459c8b7 136 _state[id].length = 0;
dgriffin65 15:14382459c8b7 137 return 0;
dgriffin65 15:14382459c8b7 138 }
dgriffin65 15:14382459c8b7 139
dgriffin65 15:14382459c8b7 140 int HTTPD::acceptWebsocket (int id) {
dgriffin65 15:14382459c8b7 141 char buf[HTTPD_CMD_SIZE], buf2[HTTPD_CMD_SIZE];
dgriffin65 15:14382459c8b7 142
dgriffin65 15:14382459c8b7 143 DBG("websocket accept: %d\r\n", id);
dgriffin65 15:14382459c8b7 144
dgriffin65 15:14382459c8b7 145 strcpy(buf, "HTTP/1.1 101 Switching Protocols\r\n");
dgriffin65 15:14382459c8b7 146 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 147 strcpy(buf, "Upgrade: websocket\r\n");
dgriffin65 15:14382459c8b7 148 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 149 strcpy(buf, "Connection: Upgrade\r\n");
dgriffin65 15:14382459c8b7 150 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 151
dgriffin65 15:14382459c8b7 152 strcpy(buf, "Sec-WebSocket-Accept: ");
dgriffin65 15:14382459c8b7 153 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 154 strcpy(buf, _state[id].websocket_key);
dgriffin65 15:14382459c8b7 155 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
dgriffin65 15:14382459c8b7 156 sha1(buf, strlen(buf), buf2);
dgriffin65 15:14382459c8b7 157 base64encode(buf2, 20, buf, sizeof(buf));
dgriffin65 15:14382459c8b7 158 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 159 strcpy(buf, "\r\n\r\n");
dgriffin65 15:14382459c8b7 160 _state[id].client->send(buf, strlen(buf));
dgriffin65 15:14382459c8b7 161 //_state[id].client->set_blocking(true, HTTPD_TIMEOUT * 100);
dgriffin65 15:14382459c8b7 162 return 0;
dgriffin65 15:14382459c8b7 163 }
dgriffin65 15:14382459c8b7 164
dgriffin65 15:14382459c8b7 165 int HTTPD::sendWebsocket (int id, const char *buf, int len, const char *mask) {
dgriffin65 15:14382459c8b7 166 HTTPD *httpd = HTTPD::getInstance();
dgriffin65 15:14382459c8b7 167 int i = 0, r;
dgriffin65 15:14382459c8b7 168 char tmp[10];
dgriffin65 15:14382459c8b7 169
dgriffin65 15:14382459c8b7 170 tmp[i++] = 0x81; // single, text frame
dgriffin65 15:14382459c8b7 171 if (len < 126) {
dgriffin65 15:14382459c8b7 172 tmp[i++] = (mask == NULL ? 0 : 0x80) | len;
dgriffin65 15:14382459c8b7 173 } else {
dgriffin65 15:14382459c8b7 174 tmp[i++] = (mask == NULL ? 0 : 0x80) | 126;
dgriffin65 15:14382459c8b7 175 tmp[i++] = (len >> 8) & 0xff;
dgriffin65 15:14382459c8b7 176 tmp[i++] = len & 0xff;
dgriffin65 15:14382459c8b7 177 }
dgriffin65 15:14382459c8b7 178 if (mask) {
dgriffin65 15:14382459c8b7 179 memcpy(&tmp[i], mask, 4);
dgriffin65 15:14382459c8b7 180 i += 4;
dgriffin65 15:14382459c8b7 181 }
dgriffin65 15:14382459c8b7 182 r = httpd->_state[id].client->send(tmp, i);
dgriffin65 15:14382459c8b7 183
dgriffin65 15:14382459c8b7 184 if (r >= 0) {
dgriffin65 15:14382459c8b7 185 if (mask) {
dgriffin65 15:14382459c8b7 186 char tmp2[len];
dgriffin65 15:14382459c8b7 187 for (i = 0; i < len; i ++) {
dgriffin65 15:14382459c8b7 188 tmp2[i] = buf[i] ^ mask[i & 0x03];
dgriffin65 15:14382459c8b7 189 }
dgriffin65 15:14382459c8b7 190 r = httpd->_state[id].client->send(tmp2, len);
dgriffin65 15:14382459c8b7 191 } else {
dgriffin65 15:14382459c8b7 192 r = httpd->_state[id].client->send((char*)buf, len);
dgriffin65 15:14382459c8b7 193 }
dgriffin65 15:14382459c8b7 194 }
dgriffin65 15:14382459c8b7 195 return r;
dgriffin65 15:14382459c8b7 196 }
dgriffin65 15:14382459c8b7 197
dgriffin65 15:14382459c8b7 198