NetworkServices with NUCLEO-L476RG and W5500 by SeeedStudio stack.

Dependents:   coap-example Borsch coap-example

Fork of NetworkServices by AMETEK Powervar

Committer:
sgnezdov
Date:
Wed Jul 05 18:34:39 2017 +0000
Revision:
17:c976088bf39d
Parent:
15:14382459c8b7
Changed setup interface to take MAC address, because W5500 may use software defined MAC when obtaining IP.

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