session.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include <boost/bind.hpp>
  2. #include <iostream>
  3. #include "session.h"
  4. session::session(boost::asio::ip::tcp::socket socket,
  5. boost::asio::io_service &io_service, std::string hostname,
  6. std::string port)
  7. : socket_(std::move(socket)),
  8. io_service_{io_service}, resolver_{io_service}, server_{io_service},
  9. timer_{io_service}, host{hostname}, port{port} {}
  10. void session::start(void) {
  11. std::cout << "session" << std::endl;
  12. auto self(shared_from_this());
  13. // read_buffer.reserve(1024);
  14. // do_write("Welcome!\n");
  15. do_read();
  16. }
  17. session::~session() { std::cout << "~session destructed" << std::endl; }
  18. void session::parse_auth(void) {
  19. // how many nulls should I be seeing?
  20. // \0user\0pass\0terminal/SPEED\0
  21. // Maybe in the future I'll care about parsing this out. I don't right now.
  22. // Ok, yes I do! If I don't have a proper rlogin value here, it isn't going
  23. // to work when I try to connect to the rlogin server.
  24. if (rlogin_auth.size() > 10)
  25. rlogin_name = rlogin_auth.c_str() + 1;
  26. else
  27. rlogin_name = "?";
  28. }
  29. void session::on_connect(const boost::system::error_code error) {
  30. // We've connected to the server! WOOT WOOT!
  31. if (!error) {
  32. std::cout << "Connected to server!" << std::endl;
  33. do_write("Connected...\n\r");
  34. connected = true;
  35. if (rlogin_auth[0] != 0) {
  36. // Ok, the rlogin information was junk --
  37. do_write("Let me make up some rlogin for you...\n\r");
  38. char temp[] = "\0test\0test\0terminal/9600\0";
  39. std::string tmp(temp, sizeof(temp));
  40. server_write(tmp);
  41. } else {
  42. server_write(rlogin_auth);
  43. }
  44. server_read();
  45. } else {
  46. // TODO:
  47. std::string output = "Failed to connect : ";
  48. output += host;
  49. output += " : ";
  50. output += port;
  51. output += "\n\r";
  52. do_write(output);
  53. std::cout << "Failed to connect to server." << std::endl;
  54. std::cout << "SHUTDOWN..." << std::endl;
  55. socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  56. }
  57. }
  58. void session::server_read(void) {
  59. auto self(shared_from_this());
  60. boost::asio::async_read(
  61. server_, boost::asio::buffer(server_buffer, sizeof(server_buffer) - 1),
  62. boost::asio::transfer_at_least(1),
  63. [this, self](boost::system::error_code ec, std::size_t length) {
  64. if (!ec) {
  65. server_buffer[length] = 0;
  66. if (length) {
  67. // std::cout << length << std::endl;
  68. std::cout << "S: " << server_buffer << std::endl;
  69. do_write(server_buffer);
  70. }
  71. server_read();
  72. } else {
  73. std::cout << "S: read_failed: connection closed" << std::endl;
  74. socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  75. // socket_.async_shutdown(boost::bind(&session::on_shutdown, this,
  76. // boost::asio::placeholders::error));
  77. }
  78. });
  79. }
  80. void session::on_resolve(
  81. const boost::system::error_code error,
  82. const boost::asio::ip::tcp::resolver::results_type results) {
  83. //
  84. auto self(shared_from_this());
  85. if (!error) {
  86. // Take the first endpoint.
  87. boost::asio::ip::tcp::endpoint const &endpoint = *results;
  88. server_.async_connect(endpoint,
  89. boost::bind(&session::on_connect, this,
  90. boost::asio::placeholders::error));
  91. } else {
  92. // TO DO:
  93. std::string output = "Unable to resolve: ";
  94. output += host;
  95. output += "\n\r";
  96. do_write(output);
  97. std::cout << "Unable to resolve?" << std::endl;
  98. std::cout << "SHUTDOWN ..." << std::endl;
  99. socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  100. }
  101. }
  102. void session::do_read(void) {
  103. auto self(shared_from_this());
  104. boost::asio::async_read( // why can't I async_read_some here?
  105. socket_, boost::asio::buffer(read_buffer, sizeof(read_buffer) - 1),
  106. boost::asio::transfer_at_least(1),
  107. [this, self](boost::system::error_code ec, std::size_t length) {
  108. if (!ec) {
  109. read_buffer[length] = 0;
  110. if (rlogin_auth.empty()) {
  111. // first read should be rlogin information
  112. rlogin_auth.assign(read_buffer, length);
  113. // parse authentication information
  114. parse_auth();
  115. do_write(std::string(1, 0));
  116. do_write("Welcome, ");
  117. do_write(rlogin_name);
  118. do_write("\n\r");
  119. // Activate the connection to the server
  120. /* // this fails, and I'm not sure why. I've used code like this
  121. before. resolver_.async_resolve( host, port, std::bind(
  122. &session::on_resolve, this, _1, _2)); */
  123. // This example shows using boost::bind, which WORKS.
  124. // https://stackoverflow.com/questions/6025471/bind-resolve-handler-to-resolver-async-resolve-using-boostasio
  125. resolver_.async_resolve(
  126. host, port,
  127. boost::bind(&session::on_resolve, this,
  128. boost::asio::placeholders::error,
  129. boost::asio::placeholders::iterator));
  130. } else if (length) {
  131. // std::cout << length << std::endl;
  132. server_write(read_buffer);
  133. std::cout << "C: " << read_buffer << std::endl;
  134. // do_write(output);
  135. }
  136. do_read();
  137. } else {
  138. std::cout << "C: read_failed: connection closed" << std::endl;
  139. if (connected)
  140. server_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  141. // server_.async_shutdown(boost::bind(&session::on_shutdown, this,
  142. // boost::asio::placeholders::error));
  143. }
  144. });
  145. }
  146. void session::do_write(std::string message) {
  147. auto self(shared_from_this());
  148. boost::asio::async_write(
  149. socket_, boost::asio::buffer(message),
  150. [this, self](boost::system::error_code ec, std::size_t /*length*/) {
  151. if (!ec) {
  152. } else {
  153. std::cout << "write failed? closed?" << std::endl;
  154. server_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  155. // server_.async_shutdown(boost::bind(&session::on_shutdown, this,
  156. // boost::asio::placeholders::error));
  157. }
  158. });
  159. }
  160. void session::server_write(std::string message) {
  161. auto self(shared_from_this());
  162. boost::asio::async_write(
  163. server_, boost::asio::buffer(message),
  164. [this, self](boost::system::error_code ec, std::size_t /*length*/) {
  165. if (!ec) {
  166. } else {
  167. std::cout << "write failed? closed?" << std::endl;
  168. socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  169. // socket_.async_shutdown(boost::bind(&session::on_shutdown, this,
  170. // boost::asio::placeholders::error));
  171. }
  172. });
  173. }
  174. void session::on_shutdown(boost::system::error_code ec) {
  175. std::cout << "shutdown." << std::endl;
  176. }