void TelnetConnection::handleRead(const boost::system::error_code &err, size_t bytesTransfered) { if (!err) { std::vector<std::string> input; {boost::lock_guard<boost::mutex> guard(mTelnetMutex); telnet_recv(mTelnet, mInputBuffer.begin(), bytesTransfered); if (mIncompleteMessage && mInputQueue.size() == 1) { startReceive(); return; } input = std::move(mInputQueue); mInputQueue.clear(); if (mIncompleteMessage) { mInputQueue.emplace_back(std::move(input.back())); input.erase(input.end() - 1); } } for (const std::string &str : input) { mMessageHandler(shared_from_this(), str); } } else { std::cerr << "handleRead: " << err.message() << std::endl; /*if (err == boost::asio::error::connection_reset || err == boost::asio::error::eof) { }*/ mDisconnectHandler(shared_from_this()); return; } startReceive(); }
int main(int argc, char** argv) { FILE *fh; telnet_t *telnet; char buffer[4096]; size_t len; /* check for a requested input file */ if (argc != 2) { fprintf(stderr, "Usage: telnet-test [test file]\n"); return 1; } /* open requested file */ if ((fh = fopen(argv[1], "rt")) == NULL) { fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); return 2; } /* create telnet parser instance */ if ((telnet = telnet_init(telopts, event_print, 0, NULL)) == 0) { fprintf(stderr, "Failed to initialize libtelnet: %s\n", strerror(errno)); return 3; } /* read input until we hit EOF or marker */ while (fgets(buffer, sizeof(buffer), fh) != NULL && strcmp(buffer, "%%\n") != 0) { if (buffer[0] != '#') { len = strlen(buffer); decode(buffer, &len); telnet_recv(telnet, buffer, len); } } /* clean up */ telnet_free(telnet); fclose(fh); return 0; }
static void _process(telnet_t *telnet, const char *buffer, size_t size) { telnet_event_t ev; unsigned char byte; size_t i, start; for (i = start = 0; i != size; ++i) { byte = buffer[i]; switch (telnet->state) { /* regular data */ case TELNET_STATE_DATA: /* on an IAC byte, pass through all pending bytes and * switch states */ if (byte == TELNET_IAC) { if (i != start) { ev.type = TELNET_EV_DATA; ev.data.buffer = buffer + start; ev.data.size = i - start; telnet->eh(telnet, &ev, telnet->ud); } telnet->state = TELNET_STATE_IAC; } break; /* IAC command */ case TELNET_STATE_IAC: switch (byte) { /* subnegotiation */ case TELNET_SB: telnet->state = TELNET_STATE_SB; break; /* negotiation commands */ case TELNET_WILL: telnet->state = TELNET_STATE_WILL; break; case TELNET_WONT: telnet->state = TELNET_STATE_WONT; break; case TELNET_DO: telnet->state = TELNET_STATE_DO; break; case TELNET_DONT: telnet->state = TELNET_STATE_DONT; break; /* IAC escaping */ case TELNET_IAC: /* event */ ev.type = TELNET_EV_DATA; ev.data.buffer = (char*)&byte; ev.data.size = 1; telnet->eh(telnet, &ev, telnet->ud); /* state update */ start = i + 1; telnet->state = TELNET_STATE_DATA; break; /* some other command */ default: /* event */ ev.type = TELNET_EV_IAC; ev.iac.cmd = byte; telnet->eh(telnet, &ev, telnet->ud); /* state update */ start = i + 1; telnet->state = TELNET_STATE_DATA; } break; /* negotiation commands */ case TELNET_STATE_WILL: case TELNET_STATE_WONT: case TELNET_STATE_DO: case TELNET_STATE_DONT: _negotiate(telnet, byte); start = i + 1; telnet->state = TELNET_STATE_DATA; break; /* subnegotiation -- determine subnegotiation telopt */ case TELNET_STATE_SB: telnet->sb_telopt = byte; telnet->buffer_pos = 0; telnet->state = TELNET_STATE_SB_DATA; break; /* subnegotiation -- buffer bytes until end request */ case TELNET_STATE_SB_DATA: /* IAC command in subnegotiation -- either IAC SE or IAC IAC */ if (byte == TELNET_IAC) { telnet->state = TELNET_STATE_SB_DATA_IAC; } else if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS && byte == TELNET_WILL) { /* In 1998 MCCP used TELOPT 85 and the protocol defined an invalid * subnegotiation sequence (IAC SB 85 WILL SE) to start compression. * Subsequently MCCP version 2 was created in 2000 using TELOPT 86 * and a valid subnegotiation (IAC SB 86 IAC SE). libtelnet for now * just captures and discards MCCPv1 sequences. */ start = i + 2; telnet->state = TELNET_STATE_DATA; /* buffer the byte, or bail if we can't */ } else if (_buffer_byte(telnet, byte) != TELNET_EOK) { start = i + 1; telnet->state = TELNET_STATE_DATA; } break; /* IAC escaping inside a subnegotiation */ case TELNET_STATE_SB_DATA_IAC: switch (byte) { /* end subnegotiation */ case TELNET_SE: /* return to default state */ start = i + 1; telnet->state = TELNET_STATE_DATA; /* process subnegotiation */ if (_subnegotiate(telnet) != 0) { /* any remaining bytes in the buffer are compressed. * we have to re-invoke telnet_recv to get those * bytes inflated and abort trying to process the * remaining compressed bytes in the current _process * buffer argument */ telnet_recv(telnet, &buffer[start], size - start); return; } break; /* escaped IAC byte */ case TELNET_IAC: /* push IAC into buffer */ if (_buffer_byte(telnet, TELNET_IAC) != TELNET_EOK) { start = i + 1; telnet->state = TELNET_STATE_DATA; } else { telnet->state = TELNET_STATE_SB_DATA; } break; /* something else -- protocol error. attempt to process * content in subnegotiation buffer, then evaluate the * given command as an IAC code. */ default: _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, "unexpected byte after IAC inside SB: %d", byte); /* enter IAC state */ start = i + 1; telnet->state = TELNET_STATE_IAC; /* process subnegotiation; see comment in * TELNET_STATE_SB_DATA_IAC about invoking telnet_recv() */ if (_subnegotiate(telnet) != 0) { telnet_recv(telnet, &buffer[start], size - start); return; } else { /* recursive call to get the current input byte processed * as a regular IAC command. we could use a goto, but * that would be gross. */ _process(telnet, (char *)&byte, 1); } break; } break; } } /* pass through any remaining bytes */ if (telnet->state == TELNET_STATE_DATA && i != start) { ev.type = TELNET_EV_DATA; ev.data.buffer = buffer + start; ev.data.size = i - start; telnet->eh(telnet, &ev, telnet->ud); } }
int main (int argc, char** argv) { const char* default_port = "23"; struct sigaction sa; int i; /* process command line args */ for (i = 1; i < argc; ++i) { /* help */ if (strcmp(argv[i], "-h") == 0) { printf( "CLC %s by Sean Middleditch <*****@*****.**>\n" "This program has been released into the PUBLIC DOMAIN.\n\n" "Usage:\n" " clc [-h] <host> [<port>]\n\n" "Options:\n" " -h display help\n", CLC_VERSION ); return 0; } /* other unknown option */ if (argv[i][0] == '-') { fprintf(stderr, "Unknown option %s.\nUse -h to see available options.\n", argv[i]); exit(1); } /* if host is unset, this is the host */ if (host == NULL) { host = argv[i]; /* otherwise, it's a port */ } else { port = argv[i]; } } /* ensure we have a host */ if (host == NULL) { fprintf(stderr, "No host was given.\nUse -h to see command format.\n"); exit(1); } /* set default port if none was given */ if (port == NULL) port = default_port; /* cleanup on any failure */ atexit(cleanup); /* set terminal defaults */ memset(&terminal, 0, sizeof(struct TERMINAL)); terminal.state = TERM_ASCII; terminal.flags = TERM_FLAGS_DEFAULT; terminal.color = TERM_COLOR_DEFAULT; /* initial telnet handler */ telnet = telnet_init(telnet_telopts, telnet_event, 0, 0); /* connect to server */ sock = do_connect(host, port); if (sock == -1) { fprintf(stderr, "Failed to connect to %s:%s\n", host, port); exit(1); } printf("Connected to %s:%s\n", host, port); /* set initial banner */ snprintf(banner, sizeof(banner), "CLC - %s:%s (connected)", host, port); /* configure curses */ initscr(); start_color(); nonl(); cbreak(); noecho(); win_main = newwin(LINES-2, COLS, 0, 0); win_banner = newwin(1, COLS, LINES-2, 0); win_input = newwin(1, COLS, LINES-1, 0); idlok(win_main, TRUE); scrollok(win_main, TRUE); nodelay(win_input, FALSE); keypad(win_input, TRUE); use_default_colors(); init_pair(COLOR_RED, COLOR_RED, -1); init_pair(COLOR_BLUE, COLOR_BLUE, -1); init_pair(COLOR_GREEN, COLOR_GREEN, -1); init_pair(COLOR_CYAN, COLOR_CYAN, -1); init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1); init_pair(COLOR_YELLOW, COLOR_YELLOW, -1); init_pair(COLOR_WHITE, COLOR_WHITE, -1); init_pair(TERM_COLOR_DEFAULT, -1, -1); wbkgd(win_main, COLOR_PAIR(TERM_COLOR_DEFAULT)); wclear(win_main); init_pair(10, COLOR_WHITE, COLOR_BLUE); wbkgd(win_banner, COLOR_PAIR(10)); wclear(win_banner); init_pair(11, -1, -1); wbkgd(win_input, COLOR_PAIR(11)); wclear(win_input); redraw_display(); /* set signal handlers */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = handle_signal; sigaction(SIGINT, &sa, NULL); sigaction(SIGWINCH, &sa, NULL); /* initial edit buffer */ memset(&editbuf, 0, sizeof(struct EDITBUF)); /* setup poll info */ struct pollfd fds[2]; fds[0].fd = 1; fds[0].events = POLLIN; fds[1].fd = sock; fds[1].events = POLLIN; /* main loop */ while (running) { /* poll sockets */ if (poll(fds, 2, -1) == -1) { if (errno != EAGAIN && errno != EINTR) { endwin(); fprintf(stderr, "poll() failed: %s\n", strerror(errno)); return 1; } } /* resize event? */ if (have_sigwinch) { have_sigwinch = 0; redraw_display(); } /* escape? */ if (have_sigint) { exit(0); } /* input? */ if (fds[0].revents & POLLIN) { int key = wgetch(win_input); if (key != ERR) on_key(key); } /* process input data */ if (fds[1].revents & POLLIN) { char buffer[2048]; int ret = recv(sock, buffer, sizeof(buffer), 0); if (ret == -1) { if (errno != EAGAIN && errno != EINTR) { endwin(); fprintf(stderr, "recv() failed: %s\n", strerror(errno)); return 1; } } else if (ret == 0) { running = 0; } else { recv_bytes += ret; telnet_recv(telnet, buffer, ret); } } /* flush output */ paint_banner(); wnoutrefresh(win_main); wnoutrefresh(win_banner); wnoutrefresh(win_input); doupdate(); } /* final display, pause */ sock = -1; autobanner = 1; paint_banner(); wnoutrefresh(win_banner); doupdate(); wgetch(win_input); /* clean up */ endwin(); printf("Disconnected.\n"); /* free memory (so Valgrind leak detection is useful) */ telnet_free(telnet); return 0; }
int main(int argc, char *argv[]) { int listen_sock; struct sockaddr_in addr; //telnet_t *telnet; //struct sockaddr_in client_addr; socklen_t addrlen; int rs; struct pollfd pfd[2]; char buffer[512]; memset(&pfd, 0, sizeof(pfd)); if((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("cant open socket\n"); exit(errno); } setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&rs, sizeof(rs)); rs = 1; //bzero(&self, sizeof(self)); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(MY_PORT); addr.sin_addr.s_addr = INADDR_ANY; if( bind(listen_sock, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) { perror("cant bind"); exit(errno); } if( listen(listen_sock, 20) != 0 ) { perror("cant listen"); exit(errno); } pfd[1].fd = listen_sock; pfd[1].events = POLLIN; while(1) { if(user.sock != -1) { pfd[0].fd = user.sock; pfd[0].events = POLLIN; } else { pfd[0].fd = -1; pfd[0].events = 0; } rs = poll(pfd, 2, -1); if(rs == -1 && errno == EINTR) { printf("Poll failed\n"); return 1; } if(pfd[1].revents & POLLIN) { addrlen = sizeof(addr); if((rs = accept(listen_sock, (struct sockaddr*)&addr, &addrlen)) == -1) { fprintf(stderr, "accept() failed %d.\n", errno); return 1; } printf("Connected client: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); user.sock = rs; user.telnet = telnet_init(telopts, _event_handler, 0, &user); telnet_negotiate(user.telnet, TELNET_DO, TELNET_TELOPT_NAWS); } if(pfd[0].revents & POLLIN) { if( (rs = recv(user.sock, buffer, sizeof(buffer), 0)) > 0) { telnet_recv(user.telnet, buffer, sizeof(buffer)); } else if(rs == 0) { printf("connection closed\n"); close(user.sock); telnet_free(user.telnet); user.sock = -1; break; } else if(errno != EINTR) { fprintf(stderr, "recv() failed\n"); exit(1); } } //send(clientfd, "Hello, world!", sizeof("Hello, world!"), 0); } close(listen_sock); return 0; }
int main(int argc, char **argv) { char buffer[512]; int rs; int sock; struct sockaddr_in addr; struct pollfd pfd[2]; struct addrinfo *ai; struct addrinfo hints; struct termios tios; /* check usage */ if (argc != 3) { fprintf(stderr, "Usage:\n ./telnet-client <host> <port>\n"); return 1; } /* look up server host */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rs = getaddrinfo(argv[1], argv[2], &hints, &ai)) != 0) { fprintf(stderr, "getaddrinfo() failed for %s: %s\n", argv[1], gai_strerror(rs)); return 1; } /* create server socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "socket() failed: %s\n", strerror(errno)); return 1; } /* bind server socket */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "bind() failed: %s\n", strerror(errno)); return 1; } /* connect */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { fprintf(stderr, "connect() failed: %s\n", strerror(errno)); return 1; } /* free address lookup info */ freeaddrinfo(ai); /* get current terminal settings, set raw mode, make sure we * register atexit handler to restore terminal settings */ tcgetattr(STDOUT_FILENO, &orig_tios); atexit(_cleanup); tios = orig_tios; cfmakeraw(&tios); tcsetattr(STDOUT_FILENO, TCSADRAIN, &tios); /* set input echoing on by default */ do_echo = 1; /* initialize telnet box */ telnet = telnet_init(telopts, _event_handler, 0, &sock); /* initialize poll descriptors */ memset(pfd, 0, sizeof(pfd)); pfd[0].fd = STDIN_FILENO; pfd[0].events = POLLIN; pfd[1].fd = sock; pfd[1].events = POLLIN; /* loop while both connections are open */ while (poll(pfd, 2, -1) != -1) { /* read from stdin */ if (pfd[0].revents & POLLIN) { if ((rs = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) { _input(buffer, rs); } else if (rs == 0) { break; } else { fprintf(stderr, "recv(server) failed: %s\n", strerror(errno)); exit(1); } } /* read from client */ if (pfd[1].revents & POLLIN) { if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { telnet_recv(telnet, buffer, rs); } else if (rs == 0) { break; } else { fprintf(stderr, "recv(client) failed: %s\n", strerror(errno)); exit(1); } } } /* clean up */ telnet_free(telnet); close(sock); return 0; }
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; }