upgrade.c (12960B)
1 /* Feel free to use this example code in any way 2 you see fit (Public Domain) */ 3 4 /** 5 * @file upgrade.c 6 * @brief Minimal example for the HTTP "Upgrade" API of libmicrohttpd. 7 * A "GET /" carrying "Connection: Upgrade" and "Upgrade: echo" 8 * is answered with "101 Switching Protocols"; afterwards the 9 * raw socket speaks a trivial line-based echo protocol until 10 * the client sends the line "QUIT" or closes the connection. 11 * @author Christian Grothoff 12 */ 13 14 #include <sys/types.h> 15 #ifndef _WIN32 16 #include <sys/select.h> 17 #include <sys/socket.h> 18 #include <fcntl.h> 19 #else 20 #include <winsock2.h> 21 #endif 22 #include <microhttpd.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <errno.h> 27 28 #define PORT 8888 29 30 /** 31 * Name of the protocol we are willing to switch to. Any name would 32 * do; "echo" is not registered with IANA and is only used here to keep 33 * the example self-contained. 34 */ 35 #define PROTOCOL "echo" 36 37 /** 38 * Maximum length of a line of the echo protocol. Longer lines are 39 * truncated. 40 */ 41 #define LINE_SIZE 1024 42 43 #define PAGE_UPGRADE_REQUIRED \ 44 "This resource speaks the \"" PROTOCOL "\" protocol only.\n" 45 46 #define PAGE_NOT_FOUND \ 47 "Not found.\n" 48 49 50 /** 51 * State of the line-based echo protocol for one connection. 52 */ 53 struct EchoState 54 { 55 /** 56 * Bytes of the line received so far (without the line terminator). 57 */ 58 char line[LINE_SIZE]; 59 60 /** 61 * Number of valid bytes in @e line. 62 */ 63 size_t line_len; 64 }; 65 66 67 /** 68 * Compare the first @a len bytes of @a a and @a b, ignoring case. 69 * Only ASCII letters are folded, which is all HTTP tokens may contain. 70 * 71 * @param a first string 72 * @param b second string 73 * @param len number of bytes to compare 74 * @return 1 if the strings match, 0 if they do not 75 */ 76 static int 77 equal_caseless (const char *a, 78 const char *b, 79 size_t len) 80 { 81 size_t i; 82 83 for (i = 0; i < len; i++) 84 { 85 char ca = a[i]; 86 char cb = b[i]; 87 88 if (('A' <= ca) && ('Z' >= ca)) 89 ca = (char) (ca - 'A' + 'a'); 90 if (('A' <= cb) && ('Z' >= cb)) 91 cb = (char) (cb - 'A' + 'a'); 92 if (ca != cb) 93 return 0; 94 } 95 return 1; 96 } 97 98 99 /** 100 * Check whether the comma-separated list @a value contains the token 101 * @a token. Both the "Connection:" and the "Upgrade:" request header 102 * fields are lists, so a client may legitimately send 103 * "Connection: keep-alive, Upgrade"; a plain string comparison against 104 * the whole field value would reject such a request. 105 * 106 * @param value the header field value, may be NULL 107 * @param token the token to look for, compared case-insensitively 108 * @return 1 if @a token is one of the tokens in @a value, 0 if not 109 */ 110 static int 111 has_token (const char *value, 112 const char *token) 113 { 114 const size_t token_len = strlen (token); 115 const char *pos = value; 116 117 if (NULL == value) 118 return 0; 119 while ('\0' != *pos) 120 { 121 const char *end; 122 size_t len; 123 124 /* skip separators and optional whitespace before the token */ 125 while ((',' == *pos) || (' ' == *pos) || ('\t' == *pos)) 126 pos++; 127 end = pos; 128 while (('\0' != *end) && (',' != *end)) 129 end++; 130 len = (size_t) (end - pos); 131 /* strip optional whitespace after the token */ 132 while ((0 != len) && 133 ((' ' == pos[len - 1]) || ('\t' == pos[len - 1]))) 134 len--; 135 if ((len == token_len) && 136 (equal_caseless (pos, token, token_len))) 137 return 1; 138 pos = end; 139 if ('\0' != *pos) 140 pos++; /* skip the comma */ 141 } 142 return 0; 143 } 144 145 146 /** 147 * Send @a len bytes from @a buf over @a sock, retrying until either 148 * everything was sent or the connection broke. 149 * 150 * @param sock the socket to write to 151 * @param buf the data to send 152 * @param len number of bytes in @a buf 153 * @return 1 on success, 0 if the connection broke 154 */ 155 static int 156 send_all (MHD_socket sock, 157 const char *buf, 158 size_t len) 159 { 160 ssize_t ret; 161 size_t off; 162 163 for (off = 0; off < len; off += (size_t) ret) 164 { 165 ret = send (sock, 166 buf + off, 167 (int) (len - off), 168 0); 169 if (0 > ret) 170 { 171 if (EINTR == errno) 172 { 173 ret = 0; 174 continue; 175 } 176 return 0; 177 } 178 if (0 == ret) 179 return 0; 180 } 181 return 1; 182 } 183 184 185 /** 186 * Make @a sock blocking. MHD hands out the socket in non-blocking 187 * mode, see the tutorial chapter for the reason why. This function 188 * contains the only operating-system-dependent code of this example. 189 * 190 * @param sock the socket to modify 191 */ 192 static void 193 make_blocking (MHD_socket sock) 194 { 195 #ifndef _WIN32 196 int flags; 197 198 flags = fcntl (sock, F_GETFL); 199 if (-1 == flags) 200 abort (); 201 if ((flags & ~O_NONBLOCK) != flags) 202 if (-1 == fcntl (sock, F_SETFL, flags & ~O_NONBLOCK)) 203 abort (); 204 #else /* _WIN32 */ 205 unsigned long flags = 0; 206 207 if (0 != ioctlsocket (sock, (int) FIONBIO, &flags)) 208 abort (); 209 #endif /* _WIN32 */ 210 } 211 212 213 /** 214 * Feed @a size bytes of received data into the echo protocol state 215 * machine, echoing back every complete line. 216 * 217 * @param sock the socket to echo to 218 * @param es the protocol state of this connection 219 * @param data the received bytes 220 * @param size number of bytes in @a data 221 * @return 1 if the client asked us to stop or the connection broke, 222 * 0 if we should keep going 223 */ 224 static int 225 echo_feed (MHD_socket sock, 226 struct EchoState *es, 227 const char *data, 228 size_t size) 229 { 230 size_t i; 231 232 for (i = 0; i < size; i++) 233 { 234 if ('\n' != data[i]) 235 { 236 if (es->line_len < sizeof (es->line)) 237 es->line[es->line_len++] = data[i]; 238 /* else: line too long, drop the excess bytes */ 239 continue; 240 } 241 /* A complete line was received; drop the CR of a CRLF terminator */ 242 if ((0 != es->line_len) && 243 ('\r' == es->line[es->line_len - 1])) 244 es->line_len--; 245 if ((4 == es->line_len) && 246 (equal_caseless (es->line, "QUIT", 4))) 247 { 248 (void) send_all (sock, "BYE\r\n", 5); 249 es->line_len = 0; 250 return 1; 251 } 252 if ((! send_all (sock, es->line, es->line_len)) || 253 (! send_all (sock, "\r\n", 2))) 254 return 1; 255 es->line_len = 0; 256 } 257 return 0; 258 } 259 260 261 /** 262 * Called by MHD once the "101 Switching Protocols" response was sent. 263 * From here on MHD is out of the picture: @a sock is an ordinary 264 * socket and we are free to speak whatever protocol we like on it. 265 * 266 * As the daemon runs with #MHD_USE_THREAD_PER_CONNECTION, this 267 * function has a thread of its own and may block for as long as it 268 * wants. 269 * 270 * @param cls closure given to #MHD_create_response_for_upgrade() 271 * @param connection the original HTTP connection 272 * @param req_cls last value of @a req_cls of the access handler 273 * @param extra_in bytes the client sent after the request header and 274 * which MHD read together with the header 275 * @param extra_in_size number of bytes in @a extra_in 276 * @param sock the socket to talk to the client on 277 * @param urh handle to pass to #MHD_upgrade_action() 278 */ 279 static void 280 upgrade_handler (void *cls, 281 struct MHD_Connection *connection, 282 void *req_cls, 283 const char *extra_in, 284 size_t extra_in_size, 285 MHD_socket sock, 286 struct MHD_UpgradeResponseHandle *urh) 287 { 288 struct EchoState es; 289 char buf[256]; 290 ssize_t got; 291 int done; 292 293 (void) cls; /* Unused. Silent compiler warning. */ 294 (void) connection; /* Unused. Silent compiler warning. */ 295 (void) req_cls; /* Unused. Silent compiler warning. */ 296 297 /* MHD hands out a non-blocking socket; this example wants to use 298 plain blocking recv()/send() calls on it. */ 299 make_blocking (sock); 300 301 es.line_len = 0; 302 303 /* The client may have pipelined payload directly behind the request 304 header, in which case MHD has read it already. Those bytes are 305 gone from the socket, so they must be processed first. */ 306 done = echo_feed (sock, 307 &es, 308 extra_in, 309 extra_in_size); 310 311 while (0 == done) 312 { 313 got = recv (sock, 314 buf, 315 sizeof (buf), 316 0); 317 if (0 > got) 318 { 319 if (EINTR == errno) 320 continue; 321 break; /* read error */ 322 } 323 if (0 == got) 324 break; /* client closed the connection */ 325 done = echo_feed (sock, 326 &es, 327 buf, 328 (size_t) got); 329 } 330 331 /* Hand the socket back to MHD. This is the only legal way to get 332 rid of it; never call close() on it ourselves, and note that the 333 connection is not cleaned up before this call happens. */ 334 MHD_upgrade_action (urh, 335 MHD_UPGRADE_ACTION_CLOSE); 336 } 337 338 339 /** 340 * Answer an ordinary HTTP request from a static string. 341 * 342 * @param connection the connection to answer 343 * @param status_code the HTTP status code to use 344 * @param page the response body 345 * @param offer_upgrade if true, advertise our protocol in an 346 * "Upgrade:" header field 347 * @return #MHD_YES on success, #MHD_NO on error 348 */ 349 static enum MHD_Result 350 answer_plain (struct MHD_Connection *connection, 351 unsigned int status_code, 352 const char *page, 353 int offer_upgrade) 354 { 355 struct MHD_Response *response; 356 enum MHD_Result ret; 357 358 response = MHD_create_response_from_buffer_static (strlen (page), 359 page); 360 if (NULL == response) 361 return MHD_NO; 362 if (offer_upgrade) 363 (void) MHD_add_response_header (response, 364 MHD_HTTP_HEADER_UPGRADE, 365 PROTOCOL); 366 ret = MHD_queue_response (connection, 367 status_code, 368 response); 369 MHD_destroy_response (response); 370 return ret; 371 } 372 373 374 static enum MHD_Result 375 access_handler (void *cls, 376 struct MHD_Connection *connection, 377 const char *url, 378 const char *method, 379 const char *version, 380 const char *upload_data, 381 size_t *upload_data_size, 382 void **req_cls) 383 { 384 struct MHD_Response *response; 385 enum MHD_Result ret; 386 387 (void) cls; /* Unused. Silent compiler warning. */ 388 (void) upload_data; /* Unused. Silent compiler warning. */ 389 (void) upload_data_size; /* Unused. Silent compiler warning. */ 390 (void) req_cls; /* Unused. Silent compiler warning. */ 391 392 if (0 != strcmp (url, "/")) 393 return answer_plain (connection, 394 MHD_HTTP_NOT_FOUND, 395 PAGE_NOT_FOUND, 396 0); 397 /* Upgrading requires HTTP/1.1 and a request that actually asks for 398 our protocol. A client that does not ask gets a plain 426. */ 399 if ((0 != strcmp (method, MHD_HTTP_METHOD_GET)) || 400 (0 != strcmp (version, MHD_HTTP_VERSION_1_1)) || 401 (! has_token (MHD_lookup_connection_value (connection, 402 MHD_HEADER_KIND, 403 MHD_HTTP_HEADER_CONNECTION), 404 "Upgrade")) || 405 (! has_token (MHD_lookup_connection_value (connection, 406 MHD_HEADER_KIND, 407 MHD_HTTP_HEADER_UPGRADE), 408 PROTOCOL))) 409 return answer_plain (connection, 410 MHD_HTTP_UPGRADE_REQUIRED, 411 PAGE_UPGRADE_REQUIRED, 412 1); 413 414 /* The request is fine, switch protocols. MHD already put 415 "Connection: Upgrade" into the response for us, we only have to 416 name the protocol we switch to. */ 417 response = MHD_create_response_for_upgrade (&upgrade_handler, 418 NULL); 419 if (NULL == response) 420 return MHD_NO; 421 if (MHD_YES != 422 MHD_add_response_header (response, 423 MHD_HTTP_HEADER_UPGRADE, 424 PROTOCOL)) 425 { 426 MHD_destroy_response (response); 427 return MHD_NO; 428 } 429 ret = MHD_queue_response (connection, 430 MHD_HTTP_SWITCHING_PROTOCOLS, 431 response); 432 /* The response may be destroyed right away: MHD keeps its own 433 reference until the upgrade handler has been called. */ 434 MHD_destroy_response (response); 435 return ret; 436 } 437 438 439 int 440 main (void) 441 { 442 struct MHD_Daemon *daemon; 443 444 daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION 445 | MHD_USE_INTERNAL_POLLING_THREAD 446 | MHD_ALLOW_UPGRADE 447 | MHD_USE_ERROR_LOG, 448 PORT, NULL, NULL, 449 &access_handler, NULL, 450 MHD_OPTION_END); 451 if (NULL == daemon) 452 return 1; 453 454 (void) getchar (); 455 456 MHD_stop_daemon (daemon); 457 return 0; 458 }