HTTP Server, WebSocket support

Fork of HTTPD by Suga koubou

Committer:
dgriffin65
Date:
Thu Jun 15 20:17:24 2017 +0000
Revision:
1:b724fdb741e7
Parent:
0:d18dff347122
Updated to mbed-os

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 #ifndef HTTPD_H
okini3939 0:d18dff347122 20 #define HTTPD_H
okini3939 0:d18dff347122 21
okini3939 0:d18dff347122 22 #include "mbed.h"
okini3939 0:d18dff347122 23 #include "rtos.h"
dgriffin65 1:b724fdb741e7 24 #include "NetworkStack.h"
dgriffin65 1:b724fdb741e7 25 #include "EthInterface.h"
okini3939 0:d18dff347122 26 #include "CBuffer.h"
okini3939 0:d18dff347122 27
dgriffin65 1:b724fdb741e7 28 #define DEBUG
okini3939 0:d18dff347122 29
okini3939 0:d18dff347122 30 #define HTTPD_PORT 80
dgriffin65 1:b724fdb741e7 31 #define HTTPD_MAX_CLIENTS 5
okini3939 0:d18dff347122 32 #define HTTPD_KEEPALIVE 10
okini3939 0:d18dff347122 33 #define HTTPD_TIMEOUT 15000
okini3939 0:d18dff347122 34 #define HTTPD_MAX_HANDLES 10
okini3939 0:d18dff347122 35
okini3939 0:d18dff347122 36 #define HTTPD_CMD_SIZE 100
okini3939 0:d18dff347122 37 #define HTTPD_BUF_SIZE 256
okini3939 0:d18dff347122 38 #define HTTPD_STACK_SIZE (1024 * 6)
okini3939 0:d18dff347122 39 //#define HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 40
okini3939 0:d18dff347122 41 //Debug is disabled by default
okini3939 0:d18dff347122 42 #if defined(DEBUG) and (!defined(TARGET_LPC11U24))
okini3939 0:d18dff347122 43 #define DBG(x, ...) std::printf("[DBG]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 44 #define WARN(x, ...) std::printf("[WARN]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 45 #define ERR(x, ...) std::printf("[ERR]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 46 #define INFO(x, ...) std::printf("[INFO]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 47 #else
okini3939 0:d18dff347122 48 #define DBG(x, ...)
okini3939 0:d18dff347122 49 #define WARN(x, ...)
okini3939 0:d18dff347122 50 #define ERR(x, ...)
okini3939 0:d18dff347122 51 #define INFO(x, ...)
okini3939 0:d18dff347122 52 #endif
okini3939 0:d18dff347122 53
okini3939 0:d18dff347122 54
okini3939 0:d18dff347122 55 class HTTPD {
okini3939 0:d18dff347122 56 public:
okini3939 0:d18dff347122 57
okini3939 0:d18dff347122 58 enum Request {
okini3939 0:d18dff347122 59 REQ_HTTPGET,
okini3939 0:d18dff347122 60 REQ_HTTPPOST,
okini3939 0:d18dff347122 61 REQ_PUT,
okini3939 0:d18dff347122 62 };
okini3939 0:d18dff347122 63
okini3939 0:d18dff347122 64 enum Mode {
okini3939 0:d18dff347122 65 MODE_REQUEST,
okini3939 0:d18dff347122 66 MODE_REQSTR,
okini3939 0:d18dff347122 67 MODE_HEADER,
okini3939 0:d18dff347122 68 MODE_BODY,
okini3939 0:d18dff347122 69 MODE_ENTER,
okini3939 0:d18dff347122 70 MODE_ERROR,
okini3939 0:d18dff347122 71 MODE_WEBSOCKET,
okini3939 0:d18dff347122 72 MODE_WEBSOCKET_MASK,
okini3939 0:d18dff347122 73 MODE_WEBSOCKET_BODY,
okini3939 0:d18dff347122 74 MODE_WEBSOCKET_ENTER,
okini3939 0:d18dff347122 75 };
okini3939 0:d18dff347122 76
okini3939 0:d18dff347122 77 struct STATE {
okini3939 0:d18dff347122 78 Thread *thread;
dgriffin65 1:b724fdb741e7 79 TCPSocket *client;
okini3939 0:d18dff347122 80 volatile Request req;
okini3939 0:d18dff347122 81 volatile Mode mode;
okini3939 0:d18dff347122 82 CircBuffer <char>*buf;
okini3939 0:d18dff347122 83 char uri[HTTPD_CMD_SIZE];
okini3939 0:d18dff347122 84 char *filename;
okini3939 0:d18dff347122 85 char *querystring;
okini3939 0:d18dff347122 86 int enter;
okini3939 0:d18dff347122 87 int length;
okini3939 0:d18dff347122 88 int n;
okini3939 0:d18dff347122 89 int keepalive;
okini3939 0:d18dff347122 90 int websocket;
okini3939 0:d18dff347122 91 char *websocket_key;
okini3939 0:d18dff347122 92 int websocket_opcode;
okini3939 0:d18dff347122 93 int websocket_flg;
okini3939 0:d18dff347122 94 char websocket_mask[4];
okini3939 0:d18dff347122 95 int websocket_payload;
okini3939 0:d18dff347122 96 int (*sendws)(int id, const char *buf, int len, const char *mask);
okini3939 0:d18dff347122 97 };
okini3939 0:d18dff347122 98
okini3939 0:d18dff347122 99 HTTPD ();
okini3939 0:d18dff347122 100
dgriffin65 1:b724fdb741e7 101 int start (NetworkStack *ns, int port = HTTPD_PORT);
okini3939 0:d18dff347122 102
okini3939 0:d18dff347122 103 // --- HTTPD_req.cpp ---
okini3939 0:d18dff347122 104 void httpdError (int id, int err);
okini3939 0:d18dff347122 105
okini3939 0:d18dff347122 106 // --- HTTPD_ws.cpp ---
okini3939 0:d18dff347122 107 static int sendWebsocket (int id, const char *buf, int len, const char *mask = NULL);
okini3939 0:d18dff347122 108
okini3939 0:d18dff347122 109 // --- HTTPD_util.cpp ---
okini3939 0:d18dff347122 110 char *getUri (int id);
okini3939 0:d18dff347122 111 char *getFilename (int id);
okini3939 0:d18dff347122 112 char *getQueryString (int id);
dgriffin65 1:b724fdb741e7 113
dgriffin65 1:b724fdb741e7 114 TCPSocket *getClientSocket(int id) {
dgriffin65 1:b724fdb741e7 115 if (id >= HTTPD_MAX_CLIENTS) return NULL;
dgriffin65 1:b724fdb741e7 116 return _state[id].client;
dgriffin65 1:b724fdb741e7 117 }
okini3939 0:d18dff347122 118 int send (int id, const char *body, int len, const char *header = NULL);
dgriffin65 1:b724fdb741e7 119 int sendstr (int id, const char *buf);
dgriffin65 1:b724fdb741e7 120 int hprintf(int id, const char* format, ...);
okini3939 0:d18dff347122 121 int receive (int id, char *buf, int len);
okini3939 0:d18dff347122 122 int attach (const char *uri, const char *dir);
okini3939 0:d18dff347122 123 int attach (const char *uri, void (*funcCgi)(int id));
okini3939 0:d18dff347122 124 int base64encode (const char *input, int length, char *output, int len);
okini3939 0:d18dff347122 125 int urlencode (const char *str, char *buf, int len);
okini3939 0:d18dff347122 126 int urldecode (const char *str, char *buf, int len);
okini3939 0:d18dff347122 127
okini3939 0:d18dff347122 128 static HTTPD * getInstance() {
okini3939 0:d18dff347122 129 return _inst;
okini3939 0:d18dff347122 130 };
okini3939 0:d18dff347122 131
okini3939 0:d18dff347122 132 private :
okini3939 0:d18dff347122 133 static HTTPD *_inst;
okini3939 0:d18dff347122 134 Thread *_daemon;
dgriffin65 1:b724fdb741e7 135 TCPServer _server;
dgriffin65 1:b724fdb741e7 136
dgriffin65 1:b724fdb741e7 137 NetworkStack *m_ns;
okini3939 0:d18dff347122 138
okini3939 0:d18dff347122 139 #ifdef HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 140 struct STATE _state[HTTPD_MAX_CLIENTS + 1];
okini3939 0:d18dff347122 141 #else
okini3939 0:d18dff347122 142 struct STATE _state[HTTPD_MAX_CLIENTS];
okini3939 0:d18dff347122 143 #endif
okini3939 0:d18dff347122 144
okini3939 0:d18dff347122 145 struct HANDLER {
okini3939 0:d18dff347122 146 char *uri;
okini3939 0:d18dff347122 147 char *dir;
okini3939 0:d18dff347122 148 void (*funcCgi)(int id);
okini3939 0:d18dff347122 149 } _handler[HTTPD_MAX_HANDLES];
okini3939 0:d18dff347122 150
okini3939 0:d18dff347122 151 int _handler_count;
okini3939 0:d18dff347122 152
dgriffin65 1:b724fdb741e7 153 static void daemon ();
okini3939 0:d18dff347122 154 static void child (void const *arg);
okini3939 0:d18dff347122 155 static void closer (void const *arg);
okini3939 0:d18dff347122 156
okini3939 0:d18dff347122 157 // --- HTTPD_req.cpp ---
okini3939 0:d18dff347122 158 int httpdFile (int id, char *dir);
okini3939 0:d18dff347122 159 void recvData (int id, char c);
okini3939 0:d18dff347122 160 int parseRequest (int id);
okini3939 0:d18dff347122 161 int parseHeader (int id);
okini3939 0:d18dff347122 162 void reqContentLength (int id, const char *buf);
okini3939 0:d18dff347122 163 void reqConnection (int id, const char *buf);
okini3939 0:d18dff347122 164 void reqUpgrade (int id, const char *buf);
okini3939 0:d18dff347122 165 void reqWebSocketVersion (int id, const char *buf);
okini3939 0:d18dff347122 166 void reqWebSocketKey (int id, const char *buf);
okini3939 0:d18dff347122 167
okini3939 0:d18dff347122 168 // --- HTTPD_ws.cpp ---
okini3939 0:d18dff347122 169 void recvWS (int id, char c);
okini3939 0:d18dff347122 170 int parseWebsocket (int id);
okini3939 0:d18dff347122 171 int acceptWebsocket (int id);
okini3939 0:d18dff347122 172
okini3939 0:d18dff347122 173 // --- HTTPD_util.cpp ---
okini3939 0:d18dff347122 174 int getHandler (const char *uri);
okini3939 0:d18dff347122 175 char *mimetype (char *file);
okini3939 0:d18dff347122 176 int strnicmp (const char *p1, const char *p2, int n);
okini3939 0:d18dff347122 177 int from_hex (int ch);
okini3939 0:d18dff347122 178 int to_hex (int code);
okini3939 0:d18dff347122 179 };
okini3939 0:d18dff347122 180
okini3939 0:d18dff347122 181 #endif