|  | @@ -0,0 +1,245 @@
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// 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 <boost/asio.hpp>
 | 
	
		
			
				|  |  | +#include <boost/asio/ip/basic_resolver.hpp>
 | 
	
		
			
				|  |  | +#include <boost/bind.hpp>
 | 
	
		
			
				|  |  | +#include <cstdlib>
 | 
	
		
			
				|  |  | +#include <iostream>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// #include <boost/json.hpp>
 | 
	
		
			
				|  |  | +// #include <boost/json/src.hpp>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// <boost/json.hpp>
 | 
	
		
			
				|  |  | +#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<session> {
 | 
	
		
			
				|  |  | +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<session>(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 <filename>" << 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;
 | 
	
		
			
				|  |  | +}
 |