websocket_chat.c 2.07 KB
Newer Older
1 2 3 4
/*
 * Copyright (c) 2014 Cesanta Software Limited
 * All rights reserved
 */
Sergey Lyubka's avatar
Sergey Lyubka committed
5

Sergey Lyubka's avatar
Sergey Lyubka committed
6 7
#include "mongoose.h"

8 9 10
static sig_atomic_t s_signal_received = 0;
static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
Sergey Lyubka's avatar
Sergey Lyubka committed
11 12 13 14 15 16

static void signal_handler(int sig_num) {
  signal(sig_num, signal_handler);  // Reinstantiate signal handler
  s_signal_received = sig_num;
}

17 18 19 20 21
static int is_websocket(const struct mg_connection *nc) {
  return nc->flags & NSF_IS_WEBSOCKET;
}

static void broadcast(struct mg_connection *nc, const char *msg, size_t len) {
Sergey Lyubka's avatar
Sergey Lyubka committed
22
  struct mg_connection *c;
23
  char buf[500];
Sergey Lyubka's avatar
Sergey Lyubka committed
24

25 26 27
  snprintf(buf, sizeof(buf), "%p %.*s", nc, (int) len, msg);
  for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, strlen(buf));
Sergey Lyubka's avatar
Sergey Lyubka committed
28 29 30
  }
}

31 32 33 34
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  struct http_message *hm = (struct http_message *) ev_data;
  struct websocket_message *wm = (struct websocket_message *) ev_data;

Sergey Lyubka's avatar
Sergey Lyubka committed
35
  switch (ev) {
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    case NS_HTTP_REQUEST:
      /* Usual HTTP request - serve static files */
      mg_serve_http(nc, hm, s_http_server_opts);
      nc->flags |= NSF_SEND_AND_CLOSE;
      break;
    case NS_WEBSOCKET_HANDSHAKE_DONE:
      /* New websocket connection. Tell everybody. */
      broadcast(nc, "joined", 6);
      break;
    case NS_WEBSOCKET_FRAME:
      /* New websocket message. Tell everybody. */
      broadcast(nc, (char *) wm->data, wm->size);
      break;
    case NS_CLOSE:
      /* Disconnect. Tell everybody. */
      if (is_websocket(nc)) {
        broadcast(nc, "left", 4);
Sergey Lyubka's avatar
Sergey Lyubka committed
53
      }
54
      break;
Sergey Lyubka's avatar
Sergey Lyubka committed
55
    default:
56
      break;
Sergey Lyubka's avatar
Sergey Lyubka committed
57 58 59 60
  }
}

int main(void) {
61 62
  struct mg_mgr mgr;
  struct mg_connection *nc;
63

Sergey Lyubka's avatar
Sergey Lyubka committed
64 65
  signal(SIGTERM, signal_handler);
  signal(SIGINT, signal_handler);
66

67 68 69 70 71 72 73
  mg_mgr_init(&mgr, NULL);

  nc = mg_bind(&mgr, s_http_port, ev_handler);
  s_http_server_opts.document_root = ".";
  mg_set_protocol_http_websocket(nc);

  printf("Started on port %s\n", s_http_port);
Sergey Lyubka's avatar
Sergey Lyubka committed
74
  while (s_signal_received == 0) {
75
    mg_mgr_poll(&mgr, 200);
Sergey Lyubka's avatar
Sergey Lyubka committed
76
  }
77 78
  mg_mgr_free(&mgr);

Sergey Lyubka's avatar
Sergey Lyubka committed
79 80
  return 0;
}