2012-08-16 21:07:56 +00:00
|
|
|
/*
|
|
|
|
* ET: Legacy
|
|
|
|
* Copyright (C) 2012 Jan Simek <mail@etlegacy.com>
|
|
|
|
*
|
|
|
|
* This file is part of ET: Legacy - http://www.etlegacy.com
|
|
|
|
*
|
|
|
|
* ET: Legacy is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* ET: Legacy is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with ET: Legacy. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "connection.h"
|
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
Connection::Connection(boost::asio::io_service& io_service,
|
2012-10-14 00:21:36 +00:00
|
|
|
std::string server_address /*=etlegacy.com*/,
|
|
|
|
unsigned short server_port /*=27960*/,
|
2012-09-02 22:11:28 +00:00
|
|
|
std::string message /*=getstatus*/,
|
|
|
|
float timeout /*=1.5*/)
|
|
|
|
: io_service_(io_service), socket_(io_service, udp::v4()), timer_(io_service)
|
2012-08-16 21:07:56 +00:00
|
|
|
{
|
2012-10-14 00:21:36 +00:00
|
|
|
// Allow ip:port address format
|
|
|
|
if (server_address.find(":") != std::string::npos)
|
|
|
|
{
|
|
|
|
server_port = boost::lexical_cast<unsigned short>
|
|
|
|
(server_address.substr(server_address.find(":") + 1));
|
|
|
|
server_address = server_address.substr(0, server_address.find(":"));
|
|
|
|
}
|
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
udp::resolver resolver(io_service_);
|
2012-10-14 00:21:36 +00:00
|
|
|
udp::resolver::query query(udp::v4(), server_address,
|
2012-08-16 21:07:56 +00:00
|
|
|
boost::lexical_cast<std::string>(server_port));
|
2012-09-02 22:11:28 +00:00
|
|
|
receiver_endpoint_ = *resolver.resolve(query);
|
2012-08-16 21:07:56 +00:00
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
socket_.async_send_to(boost::asio::buffer(wrap_message(message)),
|
|
|
|
receiver_endpoint_,
|
|
|
|
boost::bind(&Connection::HandleSend, this));
|
2012-08-16 21:07:56 +00:00
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
// How long should we wait for the server to respond
|
|
|
|
timer_.expires_from_now(boost::posix_time::seconds(timeout));
|
|
|
|
timer_.async_wait(boost::bind(&Connection::close, this));
|
|
|
|
}
|
2012-08-16 21:07:56 +00:00
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
void Connection::close()
|
|
|
|
{
|
|
|
|
socket_.close();
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
/**
|
2012-08-16 21:07:56 +00:00
|
|
|
* @brief Wraps messages into the Quake III protocol format
|
|
|
|
*/
|
|
|
|
std::string Connection::wrap_message(std::string message)
|
|
|
|
{
|
|
|
|
// NOTE: master server doesn't react to a message terminated with 0xfa
|
2012-09-02 22:11:28 +00:00
|
|
|
return std::string(4, 0xff) + message;
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
|
|
|
|
2012-09-14 11:18:17 +00:00
|
|
|
std::vector<std::string> Connection::get_response()
|
2012-08-16 21:07:56 +00:00
|
|
|
{
|
2012-09-02 22:11:28 +00:00
|
|
|
return response_;
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
|
|
|
|
2012-09-02 22:11:28 +00:00
|
|
|
/**
|
|
|
|
* @brief Calls itself after every received packet.
|
|
|
|
* @note It hangs after the last received packet until it is stopped.
|
|
|
|
*/
|
|
|
|
void Connection::HandleReceive(const boost::system::error_code& error,
|
|
|
|
size_t bytes_recvd)
|
2012-08-16 21:07:56 +00:00
|
|
|
{
|
2012-09-02 22:11:28 +00:00
|
|
|
if (!error && bytes_recvd > 0)
|
2012-08-16 21:07:56 +00:00
|
|
|
{
|
2012-09-02 22:11:28 +00:00
|
|
|
socket_.async_receive_from(
|
|
|
|
boost::asio::buffer(data_, max_length), receiver_endpoint_,
|
|
|
|
boost::bind(&Connection::HandleReceive, this,
|
|
|
|
boost::asio::placeholders::error,
|
|
|
|
boost::asio::placeholders::bytes_transferred));
|
|
|
|
|
|
|
|
// std::cout.write(data_, bytes_recvd) << std::endl;
|
2012-10-13 15:17:37 +00:00
|
|
|
response_.push_back(std::string(data_, bytes_recvd));
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
2012-09-14 11:18:17 +00:00
|
|
|
#if 0
|
2012-09-02 22:11:28 +00:00
|
|
|
else if (error)
|
2012-08-16 21:07:56 +00:00
|
|
|
{
|
2012-09-14 11:18:17 +00:00
|
|
|
std::cout << "Receive error: [" << error.category().name() << "] " << error.message() << std::endl;
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
2012-09-14 11:18:17 +00:00
|
|
|
#endif
|
2012-09-02 22:11:28 +00:00
|
|
|
// io_service will quit when it has no more work to do
|
2012-08-16 21:07:56 +00:00
|
|
|
}
|
2012-09-02 22:11:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Calls HandleReceive for the first packet.
|
|
|
|
*
|
|
|
|
* Separate from the HandleReceive method to avoid adding whitespace to response_
|
|
|
|
*/
|
|
|
|
void Connection::HandleSend()
|
|
|
|
{
|
|
|
|
socket_.async_receive_from(
|
|
|
|
boost::asio::buffer(data_, max_length), receiver_endpoint_,
|
|
|
|
boost::bind(&Connection::HandleReceive, this,
|
|
|
|
boost::asio::placeholders::error,
|
|
|
|
boost::asio::placeholders::bytes_transferred));
|
2012-10-13 15:17:37 +00:00
|
|
|
}
|