/* Terminal Mixer - multi-point multi-user access to terminal applications Copyright (C) 2007 LluĂ­s Batlle i Rossell Please find the license in the provided COPYING file. */ #include #include #include #include #include #include #include #include #include "main.h" #include "handlers.h" static int served_sockets = 0; static int listen_socket = -1; /* not listening */ static int connected_sockets = 0; static int *conn_sockets = 0; static void start_listening(int new) { int ls; struct sockaddr_in addr; int res; assert(new > 0); ls = socket(AF_INET, SOCK_STREAM, 0); if (ls == -1) error("Cannot create the tcp listen socket in the server"); { int on = 1; res = setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (res == -1) error("Cannot set SO_REUSEADDR"); } addr.sin_family = AF_INET; addr.sin_port = htons(command_line.tcp_port); addr.sin_addr.s_addr = htonl(INADDR_ANY); res = bind(ls, (struct sockaddr *) & addr, sizeof(addr)); if (res == -1) error("Error binding tcp to port %i", command_line.tcp_port); /* NUANCE: 0 backlog. Why should we assure future connections? */ res = listen(ls, 0); if (res == -1) error("Error listening on the binded tcp socket"); listen_socket = ls; } void s_tcp_update_served(int new) { if (new > served_sockets && new > 0 ) { conn_sockets = realloc(conn_sockets, sizeof(*conn_sockets) * new); if (listen_socket == -1) /* not listening */ { start_listening(new); } served_sockets = new; } else if (new < served_sockets) { not_implemented("new < served_sockets at s_tcp_update_served"); } } void s_tcp_shutdown() { int i; if (listen_socket != -1) { close(listen_socket); } for (i=0; i < connected_sockets; ++i) { close(conn_sockets[i]); } connected_sockets = 0; served_sockets = 0; } void s_tcp_prepare_read_fdset(fd_set *read_set, int *maxfd) { int i; FD_SET(listen_socket, read_set); *maxfd = max(*maxfd, listen_socket); for (i=0; i < connected_sockets; ++i) { /* We only accept if we don't have any * connetion opened. */ FD_SET(conn_sockets[i], read_set); *maxfd = max(*maxfd, conn_sockets[i]); } } static void remove_conn_socket(int n) { int i; assert(n >= 0); for(i=n+1; i connected_sockets) { int s; s = accept_connection(listen_socket); conn_sockets[connected_sockets++] = s; welcome_new_client_socket(s); } else { int s; s = accept_connection(listen_socket); close(s); } } } void s_tcp_send_to_connected(const char *buffer, size_t size) { int i; for (i=0; i < connected_sockets; ++i) { write(conn_sockets[i], buffer, size); } }