websocket.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright (c) 2004-2012 Sergey Lyubka
  2. // This file is a part of mongoose project, http://github.com/valenok/mongoose
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "mongoose.h"
  6. static void websocket_ready_handler(struct mg_connection *conn) {
  7. unsigned char buf[40];
  8. buf[0] = 0x81;
  9. buf[1] = snprintf((char *) buf + 2, sizeof(buf) - 2, "%s", "server ready");
  10. mg_write(conn, buf, 2 + buf[1]);
  11. }
  12. static int websocket_data_handler(struct mg_connection *conn) {
  13. unsigned char buf[200], reply[200];
  14. int n, i, mask_len, xor, msg_len, len;
  15. // Read message from the client.
  16. // Accept only small (<126 bytes) messages.
  17. len = 0;
  18. msg_len = mask_len = 0;
  19. for (;;) {
  20. if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
  21. return 0; // Read error, close websocket
  22. }
  23. len += n;
  24. if (len >= 2) {
  25. msg_len = buf[1] & 127;
  26. mask_len = (buf[1] & 128) ? 4 : 0;
  27. if (msg_len > 125) {
  28. return 0; // Message is too long, close websocket
  29. }
  30. // If we've buffered the whole message, exit the loop
  31. if (len >= 2 + mask_len + msg_len) {
  32. break;
  33. }
  34. }
  35. }
  36. // Prepare frame
  37. reply[0] = 0x81; // text, FIN set
  38. reply[1] = msg_len;
  39. // Copy message from request to reply, applying the mask if required.
  40. for (i = 0; i < msg_len; i++) {
  41. xor = mask_len == 0 ? 0 : buf[2 + (i % 4)];
  42. reply[i + 2] = buf[i + 2 + mask_len] ^ xor;
  43. }
  44. // Echo the message back to the client
  45. mg_write(conn, reply, 2 + msg_len);
  46. // Returnint zero means stoping websocket conversation.
  47. // Close the conversation if client has sent us "exit" string.
  48. return memcmp(reply + 2, "exit", 4);
  49. }
  50. int main(void) {
  51. struct mg_context *ctx;
  52. struct mg_callbacks callbacks;
  53. const char *options[] = {
  54. "listening_ports", "8080",
  55. "document_root", "websocket_html_root",
  56. NULL
  57. };
  58. memset(&callbacks, 0, sizeof(callbacks));
  59. callbacks.websocket_ready = websocket_ready_handler;
  60. callbacks.websocket_data = websocket_data_handler;
  61. ctx = mg_start(&callbacks, NULL, options);
  62. getchar(); // Wait until user hits "enter"
  63. mg_stop(ctx);
  64. return 0;
  65. }