websocket.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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 *callback(enum mg_event event, struct mg_connection *conn) {
  7. if (event == MG_WEBSOCKET_READY) {
  8. unsigned char buf[40];
  9. buf[0] = 0x81;
  10. buf[1] = snprintf((char *) buf + 2, sizeof(buf) - 2, "%s", "server ready");
  11. mg_write(conn, buf, 2 + buf[1]);
  12. return ""; // MG_WEBSOCKET_READY return value is ignored
  13. } else if (event == MG_WEBSOCKET_MESSAGE) {
  14. unsigned char buf[200], reply[200];
  15. int n, i, mask_len, xor, msg_len, len;
  16. // Read message from the client.
  17. // Accept only small (<126 bytes) messages.
  18. len = 0;
  19. msg_len = mask_len = 0;
  20. for (;;) {
  21. if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
  22. return ""; // Read error, close websocket
  23. }
  24. len += n;
  25. if (len >= 2) {
  26. msg_len = buf[1] & 127;
  27. mask_len = (buf[1] & 128) ? 4 : 0;
  28. if (msg_len > 125) {
  29. return ""; // Message is too long, close websocket
  30. }
  31. // If we've buffered the whole message, exit the loop
  32. if (len >= 2 + mask_len + msg_len) {
  33. break;
  34. }
  35. }
  36. }
  37. // Prepare frame
  38. reply[0] = 0x81; // text, FIN set
  39. reply[1] = msg_len;
  40. // Copy message from request to reply, applying the mask if required.
  41. for (i = 0; i < msg_len; i++) {
  42. xor = mask_len == 0 ? 0 : buf[2 + (i % 4)];
  43. reply[i + 2] = buf[i + 2 + mask_len] ^ xor;
  44. }
  45. // Echo the message back to the client
  46. mg_write(conn, reply, 2 + msg_len);
  47. // Return non-NULL means stoping websocket conversation.
  48. // Close the conversation if client has sent us "exit" string.
  49. return memcmp(reply + 2, "exit", 4) == 0 ? "" : NULL;
  50. } else {
  51. return NULL;
  52. }
  53. }
  54. int main(void) {
  55. struct mg_context *ctx;
  56. const char *options[] = {
  57. "listening_ports", "8080",
  58. "document_root", "websocket_html_root",
  59. NULL
  60. };
  61. ctx = mg_start(&callback, NULL, options);
  62. getchar(); // Wait until user hits "enter"
  63. mg_stop(ctx);
  64. return 0;
  65. }