// Copyright (c) 2014 Cesanta Software Limited
// All rights reserved
//
// This software is dual-licensed: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation. For the terms of this
// license, see .
//
// You are free to use this software under the terms of the GNU General
// Public License, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// Alternatively, you can license this software under a commercial
// license, as set out in .
//
// $Date: 2014-09-28 05:04:41 UTC $
#include "mongoose.h"
static void *stdin_thread(void *param) {
int ch, sock = *(int *) param;
// Forward all types characters to the socketpair
while ((ch = getchar()) != EOF) {
unsigned char c = (unsigned char) ch;
send(sock, (const char *) &c, 1, 0);
}
return NULL;
}
static void server_handler(struct mg_connection *nc, int ev, void *p) {
(void) p;
if (ev == MG_EV_RECV) {
// Push received message to all ncections
struct mbuf *io = &nc->recv_mbuf;
struct mg_connection *c;
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
if (!(c->flags & MG_F_USER_2)) continue; // Skip non-client connections
mg_send(c, io->buf, io->len);
}
mbuf_remove(io, io->len);
} else if (ev == MG_EV_ACCEPT) {
char addr[32];
mg_sock_addr_to_str(p, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("New client connected from %s\n", addr);
}
}
static void client_handler(struct mg_connection *conn, int ev, void *p) {
struct mbuf *io = &conn->recv_mbuf;
(void) p;
if (ev == MG_EV_CONNECT) {
if (conn->flags & MG_F_CLOSE_IMMEDIATELY) {
printf("%s\n", "Error connecting to server!");
exit(EXIT_FAILURE);
}
printf("%s\n", "Connected to server. Type a message and press enter.");
} else if (ev == MG_EV_RECV) {
if (conn->flags & MG_F_USER_1) {
// Received data from the stdin, forward it to the server
struct mg_connection *c = (struct mg_connection *) conn->user_data;
mg_send(c, io->buf, io->len);
mbuf_remove(io, io->len);
} else {
// Received data from server connection, print it
fwrite(io->buf, io->len, 1, stdout);
mbuf_remove(io, io->len);
}
} else if (ev == MG_EV_CLOSE) {
// Connection has closed, most probably cause server has stopped
exit(EXIT_SUCCESS);
}
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
exit(EXIT_FAILURE);
} else if (strcmp(argv[2], "client") == 0) {
sock_t fds[2];
struct mg_connection *ioconn, *server_conn;
mg_mgr_init(&mgr, NULL);
// Connect to the pubsub server
server_conn = mg_connect(&mgr, argv[1], client_handler);
if (server_conn == NULL) {
fprintf(stderr, "Cannot connect to port %s\n", argv[1]);
exit(EXIT_FAILURE);
}
server_conn->flags |= MG_F_USER_2; // Mark this as a client connection
// Create a socketpair and give one end to the thread that reads stdin
mg_socketpair(fds, SOCK_STREAM);
mg_start_thread(stdin_thread, &fds[1]);
// The other end of a pair goes inside the server
ioconn = mg_add_sock(&mgr, fds[0], client_handler);
ioconn->flags |= MG_F_USER_1; // Mark this so we know this is a stdin
ioconn->user_data = server_conn;
} else {
// Server code path
mg_mgr_init(&mgr, NULL);
mg_bind(&mgr, argv[1], server_handler);
printf("Starting pubsub server on port %s\n", argv[1]);
}
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return EXIT_SUCCESS;
}