HTTP Server, WebSocket support

Dependents:   HTTPD_sample ch5_mbed_lightweight_Web_server_dust_sensor ch8_mbed_websocket_client Renesas_GR-Peach_LCD

Committer:
okini3939
Date:
Wed Nov 13 01:58:04 2013 +0000
Revision:
0:d18dff347122
1st build;

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