more handlers

Dependents:   bandwidth-meter-net mbedRail24v

Fork of Tiny-HTTPD by ban4jp -

Committer:
Jasper
Date:
Fri May 30 03:55:43 2014 +0000
Revision:
3:145c65ab9805
Parent:
0:d18dff347122
NULL isn't always 0, we need more handlers

Who changed what in which revision?

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