Advertisement
Guest User

Untitled

a guest
Apr 9th, 2020
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.60 KB | None | 0 0
  1. #include "socket.hpp"
  2. #include "awaiter.hpp"
  3.  
  4. namespace tinyfiber {
  5. namespace tcp {
  6.  
  7. using namespace make_result;
  8.  
  9. Result<Socket> Socket::ConnectTo(const std::string& host, uint16_t port) {
  10.   Socket conn;
  11.   // connect
  12.   auto endpoints = conn.resolver_.resolve(host, std::to_string(port));
  13.   asio::error_code error_code;
  14.   Fiber* fiber = GetCurrentFiber();
  15.  
  16.   asio::async_connect(
  17.       conn.socket_,
  18.       endpoints,
  19.       [fiber, &error_code](
  20.           const asio::error_code& connect_error_code,
  21.           const asio::ip::tcp::endpoint& endpoint) {
  22.  
  23.         error_code = connect_error_code;
  24.         GetCurrentScheduler()->Add(fiber);
  25.   });
  26.  
  27.   GetCurrentScheduler()->Suspend();
  28.  
  29.   if (!error_code) {
  30.     return Result<Socket>::Ok(std::move(conn));
  31.   } else {
  32.     return Result<Socket>::Fail(error_code);
  33.   }
  34. }
  35.  
  36. Result<Socket> Socket::ConnectToLocal(uint16_t port) {
  37.   return ConnectTo("localhost", port);
  38. }
  39.  
  40. Result<size_t> Socket::ReadSome(MutableBuffer buffer) {
  41.   asio::error_code error_code;
  42.   size_t bytes_transferred = 0;
  43.   Fiber* fiber = GetCurrentFiber();
  44.  
  45.   socket_.async_read_some(buffer, [fiber, &error_code, &bytes_transferred](
  46.       const asio::error_code& read_some_error_code,
  47.       size_t bytes_transferred_) {
  48.  
  49.     error_code = read_some_error_code;
  50.     bytes_transferred = bytes_transferred_;
  51.     GetCurrentScheduler()->Add(fiber);
  52.   });
  53.  
  54.   GetCurrentScheduler()->Suspend();
  55.   if (!error_code) {  // some bytes read
  56.     return Result<size_t>::Ok(bytes_transferred);
  57.   } else if (error_code == asio::error::eof) {  // eof reached
  58.     return Result<size_t>::Ok(0);
  59.   } else {  // error occurred
  60.     return Result<size_t>::Fail(error_code);
  61.   }
  62. }
  63.  
  64. Result<size_t> Socket::Read(MutableBuffer buffer) {
  65.   size_t read = 0;
  66.   while (read < buffer.size()) {
  67.     auto bytes_read = ReadSome(asio::buffer(buffer + read, buffer.size() - read));
  68.     if (!bytes_read.IsOk()) {
  69.       return make_result::Fail(bytes_read.Error());
  70.     }
  71.     read += bytes_read.Value();
  72.     if (bytes_read.Value() == 0) {
  73.       break;
  74.     }
  75.   }
  76.   return make_result::Ok(read);
  77. }
  78.  
  79. Status Socket::Write(ConstBuffer buffer) {
  80.   asio::error_code error_code;
  81.   Fiber* fiber = GetCurrentFiber();
  82.  
  83.   asio::async_write(socket_, buffer, [fiber, &error_code](
  84.       const asio::error_code& write_error_code,
  85.       size_t bytes_transferred_) {
  86.  
  87.     error_code = write_error_code;
  88.     GetCurrentScheduler()->Add(fiber);
  89.   });
  90.  
  91.   GetCurrentScheduler()->Suspend();
  92.  
  93.   if (!error_code) {
  94.     return Ok();
  95.   } else {
  96.     return Fail(error_code);
  97.   }
  98. }
  99.  
  100. Status Socket::ShutdownWrite() {
  101.   // Not implemented
  102.   // Use `shutdown` method of ip::tcp::socket
  103.   asio::error_code error_code;
  104.   socket_.shutdown(asio::ip::tcp::socket::shutdown_send, error_code);
  105.   if (!error_code) {
  106.     return Ok();
  107.   } else {
  108.     return Fail(error_code);
  109.   }
  110. }
  111.  
  112. Socket::Socket(): socket_(GetCurrentScheduler()->GetIOContext()), resolver_(GetCurrentScheduler()->GetIOContext()) {
  113.  
  114. }
  115.  
  116. Socket::Socket(asio::ip::tcp::socket&& socket): socket_(std::move(socket)), resolver_(GetCurrentScheduler()->GetIOContext()) {
  117.  
  118. }
  119.  
  120. Acceptor::Acceptor(): acceptor_(GetCurrentScheduler()->GetIOContext()) {
  121.  
  122. }
  123.  
  124. Status Acceptor::Listen(uint16_t port) {
  125.   asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), port);
  126.   asio::error_code error_code;
  127.  
  128.   acceptor_.open(ep.protocol(), error_code);
  129.   if (error_code) {
  130.     return Fail(error_code);
  131.   }
  132.  
  133.   acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true), error_code);
  134.   if (error_code) {
  135.     return Fail(error_code);
  136.   }
  137.  
  138.   acceptor_.bind(ep, error_code);
  139.   if (error_code) {
  140.     return Fail(error_code);
  141.   }
  142.  
  143.   acceptor_.listen();
  144.   return Ok();
  145. }
  146.  
  147. Result<uint16_t> Acceptor::ListenAvailablePort() {
  148.   auto is_listening = Listen(0);
  149.   if (is_listening.IsOk()) {
  150.     return make_result::Ok(GetPort());
  151.   } else {
  152.     return make_result::Fail(is_listening.Error());
  153.   }
  154. }
  155.  
  156. Result<Socket> Acceptor::Accept() {
  157.   asio::error_code error_code;
  158.   asio::ip::tcp::socket socket(GetCurrentScheduler()->GetIOContext());
  159.   Fiber* current_fiber = GetCurrentFiber();
  160.  
  161.   acceptor_.async_accept(socket, [current_fiber, &error_code](
  162.       std::error_code accept_error_code) {
  163.  
  164.     error_code = accept_error_code;
  165.     GetCurrentScheduler()->Add(current_fiber);
  166.   });
  167.  
  168.   GetCurrentScheduler()->Suspend();
  169.   if (!error_code) {
  170.     return Result<Socket>::Ok(std::move(socket));
  171.   } else {
  172.     return make_result::Fail(error_code);
  173.   }
  174. }
  175.  
  176. uint16_t Acceptor::GetPort() const {
  177.   return acceptor_.local_endpoint().port();
  178. }
  179.  
  180. }  // namespace tcp
  181. }  // namespace tinyfiber
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement