| 69 | } |
| 70 | |
| 71 | bool PlayToolsClient::open() |
| 72 | { |
| 73 | if (socket_.is_open()) { |
| 74 | return true; |
| 75 | } |
| 76 | |
| 77 | std::string host, port; |
| 78 | std::stringstream ss(address_); |
| 79 | std::getline(ss, host, ':'); |
| 80 | std::getline(ss, port); |
| 81 | |
| 82 | if (host.empty() || port.empty()) { |
| 83 | LogError << "Invalid address format:" << address_; |
| 84 | return false; |
| 85 | } |
| 86 | |
| 87 | tcp::resolver resolver(context_); |
| 88 | |
| 89 | std::array<uint8_t, 4> buffer; |
| 90 | constexpr char handshake[4] = { 'M', 'A', 'A', 0 }; |
| 91 | constexpr char signature[4] = { 'O', 'K', 'A', 'Y' }; |
| 92 | |
| 93 | boost::system::error_code ec; |
| 94 | auto endpoints = resolver.resolve(host, port, ec); |
| 95 | if (ec) { |
| 96 | LogError << "Cannot resolve address" << address_ << ec.message(); |
| 97 | return false; |
| 98 | } |
| 99 | boost::asio::connect(socket_, endpoints, ec); |
| 100 | if (ec) { |
| 101 | LogError << "Cannot connect to" << address_ << ec.message(); |
| 102 | return false; |
| 103 | } |
| 104 | boost::asio::write(socket_, boost::asio::buffer(handshake), ec); |
| 105 | if (ec) { |
| 106 | LogError << "Cannot send handshake:" << ec.message(); |
| 107 | return false; |
| 108 | } |
| 109 | boost::asio::read(socket_, boost::asio::buffer(buffer, 4), ec); |
| 110 | if (ec) { |
| 111 | LogError << "Cannot read handshake response:" << ec.message(); |
| 112 | return false; |
| 113 | } |
| 114 | |
| 115 | if (std::memcmp(buffer.data(), signature, 4) != 0) { |
| 116 | LogError << "Got invalid response from PlayTools"; |
| 117 | close(); |
| 118 | return false; |
| 119 | } |
| 120 | |
| 121 | if (!check_version() || !fetch_screen_size(screen_size_.first, screen_size_.second)) { |
| 122 | close(); |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | return true; |
| 127 | } |
| 128 | |