websocket_chat.c 2.2 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
static int is_websocket(const struct mg_connection *nc) {
18
  return nc->flags & MG_F_IS_WEBSOCKET;
19 20
}

21
static void broadcast(struct mg_connection *nc, const struct mg_str msg) {
Sergey Lyubka's avatar
Sergey Lyubka committed
22
  struct mg_connection *c;
23
  char buf[500];
24 25 26
  char addr[32];
  mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
                      MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
Sergey Lyubka's avatar
Sergey Lyubka committed
27

28 29
  snprintf(buf, sizeof(buf), "%s %.*s", addr, (int) msg.len, msg.p);
  printf("%s\n", buf); /* Local echo. */
30
  for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
31
    if (c == nc) continue; /* Don't send to the sender. */
32
    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, strlen(buf));
Sergey Lyubka's avatar
Sergey Lyubka committed
33 34 35
  }
}

36
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
Sergey Lyubka's avatar
Sergey Lyubka committed
37
  switch (ev) {
38
    case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
39
      /* New websocket connection. Tell everybody. */
40
      broadcast(nc, mg_mk_str("++ joined"));
41
      break;
42 43 44
    }
    case MG_EV_WEBSOCKET_FRAME: {
      struct websocket_message *wm = (struct websocket_message *) ev_data;
45
      /* New websocket message. Tell everybody. */
46 47
      struct mg_str d = {(char *) wm->data, wm->size};
      broadcast(nc, d);
48
      break;
49 50
    }
    case MG_EV_CLOSE: {
51 52
      /* Disconnect. Tell everybody. */
      if (is_websocket(nc)) {
53
        broadcast(nc, mg_mk_str("-- left"));
Sergey Lyubka's avatar
Sergey Lyubka committed
54
      }
55
      break;
56
    }
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
  setvbuf(stdout, NULL, _IOLBF, 0);
  setvbuf(stderr, NULL, _IOLBF, 0);
68

69 70 71 72 73 74 75
  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
76
  while (s_signal_received == 0) {
77
    mg_mgr_poll(&mgr, 200);
Sergey Lyubka's avatar
Sergey Lyubka committed
78
  }
79 80
  mg_mgr_free(&mgr);

Sergey Lyubka's avatar
Sergey Lyubka committed
81 82
  return 0;
}