static void _message(const char *from, const char *msg) { int i; for (i = 0; i != MAX_USERS; ++i) { if (users[i].sock != -1) { telnet_printf(users[i].telnet, "%s: %s\n", from, msg); } } }
/* send a line to the server */ static void send_line (const char* line, size_t len) { telnet_printf(telnet, "%.*s\n", (int)len, line); /* echo output */ if (terminal.flags & TERM_FLAG_ECHO) { wattron(win_main, COLOR_PAIR(COLOR_YELLOW)); on_text_plain(line, len); on_text_plain("\n", 1); wattron(win_main, COLOR_PAIR(terminal.color)); } }
/* process input line */ static void _online(const char *line, int overflow, void *ud) { struct user_t *user = (struct user_t*)ud; int i; /* if the user has no name, this is his "login" */ if (user->name == 0) { /* must not be empty, must be at least 32 chars */ if (strlen(line) == 0 || strlen(line) > 32) { telnet_printf(user->telnet, "Invalid name.\nEnter name: "); return; } /* must not already be in use */ for (i = 0; i != MAX_USERS; ++i) { if (users[i].name != 0 && strcmp(users[i].name, line) == 0) { telnet_printf(user->telnet, "Name in use.\nEnter name: "); return; } } /* keep name */ user->name = strdup(line); telnet_printf(user->telnet, "Welcome, %s!\n", line); return; } /* if line is "quit" then, well, quit */ if (strcmp(line, "quit") == 0) { close(user->sock); user->sock = -1; _message(user->name, "** HAS QUIT **"); free(user->name); user->name = 0; return; } /* just a message -- send to all users */ _message(user->name, line); }
static void _event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data) { struct user_t *user = (struct user_t*)user_data; switch(ev->type) { case TELNET_EV_DATA: printf("TELNET_EV_DATA\n"); break; case TELNET_EV_SEND: printf("TELNET_EV_SEND\n"); _send(user->sock, ev->data.buffer, ev->data.size); break; case TELNET_EV_SUBNEGOTIATION: printf("TELNET_EV_SUBNEGOTIANTION\n"); if(ev->sub.telopt == TELNET_TELOPT_NAWS) { user->width = (ev->sub.buffer[0] * 256) + (unsigned char)ev->sub.buffer[1]; user->height = (ev->sub.buffer[2] * 256) + (unsigned char)ev->sub.buffer[3]; telnet_printf(telnet, "client width is x: %d and y: %d\n", user->width, user->height); printf("client width is x: %d and y: %d\n", user->width, user->height); _draw(user->width, user->height, telnet); } break; case TELNET_EV_WILL: printf("client will\n"); break; case TELNET_EV_WONT: printf("client wont\n"); break; case TELNET_EV_ERROR: close(user->sock); user->sock = -1; telnet_free(user->telnet); printf("TELNET_EV_ERROR\n"); break; default: break; } }
static void _event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data) { struct user_t *user = (struct user_t*)user_data; switch(ev->type) { case TELNET_EV_DATA: printf("TELNET_EV_DATA\n"); break; case TELNET_EV_SEND: printf("TELNET_EV_SEND\n"); _send(user->sock, ev->data.buffer, ev->data.size); break; case TELNET_EV_SUBNEGOTIATION: printf("TELNET_EV_SUBNEGOTIANTION\n"); if(ev->sub.telopt == TELNET_TELOPT_NAWS) printf("NAWS subnegotiation has %d bytes\n", ev->data.size); telnet_printf(telnet, "NAWS subnegotiation has %d bytes\n", ev->data.size); break; case TELNET_EV_WILL: printf("client will\n"); break; case TELNET_EV_WONT: printf("client wont\n"); break; case TELNET_EV_ERROR: close(user->sock); user->sock = -1; telnet_free(user->telnet); printf("TELNET_EV_ERROR\n"); break; default: break; } }
int main(int argc, char **argv) { char buffer[512]; short listen_port; int listen_sock; int rs; int i; struct sockaddr_in addr; socklen_t addrlen; struct pollfd pfd[MAX_USERS + 1]; /* initialize Winsock */ #if defined(_WIN32) WSADATA wsd; WSAStartup(MAKEWORD(2, 2), &wsd); #endif /* check usage */ if (argc != 2) { fprintf(stderr, "Usage:\n ./telnet-chatd <port>\n"); return 1; } /* initialize data structures */ memset(&pfd, 0, sizeof(pfd)); memset(users, 0, sizeof(users)); for (i = 0; i != MAX_USERS; ++i) users[i].sock = -1; /* parse listening port */ listen_port = (short)strtol(argv[1], 0, 10); /* create listening socket */ if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "socket() failed: %s\n", strerror(errno)); return 1; } /* reuse address option */ rs = 1; setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&rs, sizeof(rs)); /* bind to listening addr/port */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(listen_port); if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "bind() failed: %s\n", strerror(errno)); return 1; } /* listen for clients */ if (listen(listen_sock, 5) == -1) { fprintf(stderr, "listen() failed: %s\n", strerror(errno)); return 1; } printf("LISTENING ON PORT %d\n", listen_port); /* initialize listening descriptors */ pfd[MAX_USERS].fd = listen_sock; pfd[MAX_USERS].events = POLLIN; /* loop for ever */ for (;;) { /* prepare for poll */ for (i = 0; i != MAX_USERS; ++i) { if (users[i].sock != -1) { pfd[i].fd = users[i].sock; pfd[i].events = POLLIN; } else { pfd[i].fd = -1; pfd[i].events = 0; } } /* poll */ rs = poll(pfd, MAX_USERS + 1, -1); if (rs == -1 && errno != EINTR) { fprintf(stderr, "poll() failed: %s\n", strerror(errno)); return 1; } /* new connection */ if (pfd[MAX_USERS].revents & POLLIN) { /* acept the sock */ addrlen = sizeof(addr); if ((rs = accept(listen_sock, (struct sockaddr *)&addr, &addrlen)) == -1) { fprintf(stderr, "accept() failed: %s\n", strerror(errno)); return 1; } printf("Connection received.\n"); /* find a free user */ for (i = 0; i != MAX_USERS; ++i) if (users[i].sock == -1) break; if (i == MAX_USERS) { printf(" rejected (too many users)\n"); _send(rs, "Too many users.\r\n", 14); close(rs); } /* init, welcome */ users[i].sock = rs; users[i].telnet = telnet_init(telopts, _event_handler, 0, &users[i]); telnet_negotiate(users[i].telnet, TELNET_WILL, TELNET_TELOPT_COMPRESS2); telnet_printf(users[i].telnet, "Enter name: "); } /* read from client */ for (i = 0; i != MAX_USERS; ++i) { /* skip users that aren't actually connected */ if (users[i].sock == -1) continue; if (pfd[i].revents & POLLIN) { if ((rs = recv(users[i].sock, buffer, sizeof(buffer), 0)) > 0) { telnet_recv(users[i].telnet, buffer, rs); } else if (rs == 0) { printf("Connection closed.\n"); close(users[i].sock); if (users[i].name != 0) { _message(users[i].name, "** HAS DISCONNECTED **"); free(users[i].name); users[i].name = 0; } telnet_free(users[i].telnet); users[i].sock = -1; break; } else if (errno != EINTR) { fprintf(stderr, "recv(client) failed: %s\n", strerror(errno)); exit(1); } } } } /* not that we can reach this, but GCC will cry if it's not here */ return 0; }