// // client.cpp // ~~~~~~~~~~ // // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include // #include // #include // #ifdef WORKING_JSON json::value parse_file(char const *filename) { file f(filename, "r"); json::stream_parser p; json::error_code ec; do { char buf[4096]; auto const nread = f.read(buf, sizeof(buf)); p.write(buf, nread, ec); } while (!f.eof()); if (ec) return nullptr; p.finish(ec); if (ec) return nullptr; return p.release(); } #endif class session : public std::enable_shared_from_this { public: session(boost::asio::ip::tcp::socket socket, boost::asio::io_service &io_service, std::string hostname, std::string port) : socket_(std::move(socket)), io_service_{io_service}, resolver_{io_service}, host{hostname}, port{port} {} void start(void) { std::cout << "session" << std::endl; auto self(shared_from_this()); // read_buffer.reserve(1024); // do_write("Welcome!\n"); do_read(); } ~session() { std::cout << "~session" << std::endl; } void parse_auth(void) { // how many nulls should I be seeing? // \0user\0pass\0terminal/SPEED\0 // Maybe in the future I'll care about parsing this out. I don't right now. if (rlogin_auth.size() > 10) rlogin_name = rlogin_auth.c_str() + 1; else rlogin_name = "?"; } void on_resolve(const boost::system::error_code error, const boost::asio::ip::tcp::resolver::results_type results) { // auto self(shared_from_this()); if (!error) { for (boost::asio::ip::tcp::endpoint const &endpoint : results) { std::cout << "GOT: " << endpoint << "\n"; } } else { std::cout << "Unable to resolve?" << std::endl; } } void do_read(void) { auto self(shared_from_this()); boost::asio::async_read( // why can't I async_read_some here? socket_, boost::asio::buffer(read_buffer, sizeof(read_buffer) - 1), boost::asio::transfer_at_least(1), [this, self](boost::system::error_code ec, std::size_t length) { if (!ec) { read_buffer[length] = 0; if (rlogin_auth.empty()) { // first read should be rlogin information rlogin_auth.assign(read_buffer, length); // parse authentication information parse_auth(); do_write(std::string(1, 0)); do_write("Welcome, "); do_write(rlogin_name); do_write("\n\r"); // Activate the connection to the server // this works! /* boost::system::error_code ec; boost::asio::ip::tcp::resolver::results_type results = self->resolver_.resolve("google.com", "80", ec); for (boost::asio::ip::tcp::endpoint const &endpoint : results) { std::cout << endpoint << "\n"; } */ // resolver_.async_resolve(host, port, on_resolve); // This works, but I can't std::bind to a callback? /* resolver_.async_resolve( host, port, [&](boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type results) { if (!ec) { for (const boost::asio::ip::tcp::endpoint &endpoint : results) { std::cout << endpoint << "\n"; } } else { std::cerr << "Something went wrong"; } }); */ /* resolver_.async_resolve( host, port, std::bind( &session::on_resolve, this, _1, _2)); */ // This example shows using boost::bind, which WORKS. // https://stackoverflow.com/questions/6025471/bind-resolve-handler-to-resolver-async-resolve-using-boostasio resolver_.async_resolve( host, port, boost::bind(&session::on_resolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } else if (length) { // std::cout << length << std::endl; std::cout << read_buffer << std::endl; std::string output = "Got ["; output += read_buffer; output += "]\n"; do_write(output); } do_read(); } else { std::cout << "read_failed: connection closed" << std::endl; } }); } void do_write(std::string message) { auto self(shared_from_this()); boost::asio::async_write( socket_, boost::asio::buffer(message), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { } else { std::cout << "write failed? closed?" << std::endl; } }); } private: boost::asio::ip::tcp::socket socket_; boost::asio::io_service &io_service_; boost::asio::ip::tcp::resolver resolver_; // std::string read_buffer; char read_buffer[1024]; std::string rlogin_auth; std::string rlogin_name; std::string host; std::string port; }; class server { public: server(boost::asio::io_service &io_service, const boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::string port) : io_service_{io_service}, acceptor_{io_service_, endpoint}, host_{host}, port_{port} { do_accept(); } private: void do_accept() { acceptor_.async_accept([this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket) { if (!ec) { std::make_shared(std::move(socket), io_service_, host_, port_) ->start(); } do_accept(); }); } boost::asio::io_service &io_service_; boost::asio::ip::tcp::acceptor acceptor_; std::string host_; std::string port_; }; int main(int argc, char *argv[]) { // boost::json::json_value config; if (argc != 2) { std::cerr << "Usage: twproxy " << std::endl; return EXIT_FAILURE; } try { // Parse the file as JSON // config = parse_file( argv[1] ); } catch (std::exception const &e) { std::cerr << "Caught exception: " << e.what() << std::endl; return EXIT_FAILURE; } int port = 9999; // 2002; try { boost::asio::io_service io_service; boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); // std::atoi(argv[i])); // connect to the BBS server s(io_service, endpoint, "127.0.0.1", "2023"); io_service.run(); } catch (std::exception &e) { std::cerr << "Exception: " << e.what() << "\n"; } return EXIT_SUCCESS; }