- #include <boost/asio/deadline_timer.hpp>
- #include <boost/asio/io_service.hpp>
- #include <boost/asio/ip/tcp.hpp>
- #include <boost/asio/read_until.hpp>
- #include <boost/asio/streambuf.hpp>
- #include <boost/asio/write.hpp>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/enable_shared_from_this.hpp>
- #include <iostream>
- #include <set>
- #include <map>
- #include "Message.hpp"
- #include "SQLite.hpp"
-
- using boost::asio::deadline_timer;
- using boost::asio::ip::tcp;
- using boost::asio::ip::udp;
-
- using namespace std;
- using namespace PWRD;
- using namespace PWRD::SQL;
- using namespace PWRD::Protocol;
-
- typedef map<string, int> Peers;
- typedef map<string, int> Stats;
- typedef map<string, string> Files;
- typedef map<string, tcp::socket* > Sockets;
- #define DEADLINE 10
- #define MAXLEN 1024
- #define SECONDS 5
-
- namespace PWRD{
- namespace Network{
- class Session{
- public:
- Session(boost::asio::ip::tcp::socket &_socket, boost::asio::io_service &io_service, const char *path);
- ~Session();
- void start();
-
- void stop();
- void delivery(string &ip);
-
- private:
- void handle_connect(const boost::system::error_code& ec,
- tcp::resolver::iterator endpoint_iter);
-
- void start_read();
-
- void handle_read_header(const boost::system::error_code& ec);
-
- void start_delivery();
-
- void handle_read_body(const boost::system::error_code& ec);
-
- void start_write_heartbeat();
-
- void handle_write_heartbeat(const boost::system::error_code& ec);
- void handle_wait(const boost::system::error_code& ec);
- void handle_write_config(const boost::system::error_code& ec, Configure &conf);
-
- private:
- bool stopped_;
- tcp::socket &socket_;
- Header header_;
- HeartbeatMessage heartbeat_message_;
- DataMessage packet_message_;
- ConfigMessage conf_message_;
- deadline_timer heartbeat_timer_;
- Callback *callback_;
- char *input_stream_;
-
- };
-
- class SessionPool{
- public:
- SessionPool();
- ~SessionPool();
- void join(string&, Session *);
- void delivery(string&);
- void leave(string &ip);
-
- private:
- std::map<string, Session *> session_pool_;
- };
- /************************************************************
- * Usage: Client will connect to every server and it's never
- * stopped until you shutdown it. Connect action will
- * start in every DEADLINE seconds
- ************************************************************/
- class Client{
- public:
- void stop();
- void start();
- Client(boost::asio::io_service &_io_service, boost::asio::io_service &_io_service_data, const char *_sqlite);
- protected:
- void handle_wait_update();
- void handle_update();
- void start_connect();
- void handle_connect(const boost::system::error_code& ec,Peers::iterator it);
- void handle_deadline();
- void check_all();
- private:
-
- Peers peers_;
- Sockets sockets_;
- Stats status_;
- Files files_;
-
- deadline_timer deadline_;
- boost::asio::io_service &io_service_;
- const char * sqlite_;
- bool all_;
-
- SessionPool session_pool_;
-
- boost::asio::io_service &io_service_data_;
-
- };
- };
- };
ATC.cpp
- #include "ATC.hpp"
- namespace PWRD{
- namespace Network{
- //-------------------------------------------------------------------------
-
- //Session
-
- //-------------------------------------------------------------------------
-
- Session::Session(boost::asio::ip::tcp::socket &_socket, boost::asio::io_service &io_service, const char *path)
- :socket_(_socket),
- heartbeat_timer_(io_service),
- stopped_(false)
- {
- callback_ = new Callback(path);
- input_stream_ = new char[MAXLEN];
- }
-
- Session::~Session(){
- delete callback_;
- delete input_stream_;
- }
- void Session::start(){
- start_read();
- start_write_heartbeat();
- }
-
- void Session::stop(){
- stopped_ = true;
- socket_.close();
- heartbeat_timer_.cancel();
- }
-
- void Session::start_read(){
- socket_.async_receive(
- boost::asio::buffer(&header_, HEADERLEN),
- boost::bind(&Session::handle_read_header, this,
- boost::asio::placeholders::error)
- );
- }
-
- void Session::handle_read_header(const boost::system::error_code& ec){
- if(stopped_)
- return;
- if(!ec){
- if(HEARTBEAT == header_.type){
- logs.write_log(NORMAL, "info:Receive heartbeat message");
- //heartbeat_timer_.expires_from_now(boost::posix_time::seconds(SECONDS));
-
- start_read();
- }
- else if(PACKET == header_.type){
- socket_.async_receive(
- boost::asio::buffer(input_stream_, header_.length),
- boost::bind(&Session::handle_read_body, this,
- boost::asio::placeholders::error)
- );
- logs.write_log(NORMAL, "info:Receive Packet message: %d bytes", header_.length);
- }
- }
- else{
- logs.write_log(NORMAL, "Error on receive: %s", (ec.message()).c_str());
- stop();
- }
- }
-
- void Session::handle_read_body(const boost::system::error_code& ec){
- if(stopped_)
- return;
- if(!ec){
- if(packet_message_.Parse(input_stream_, header_.length)){
- Packet * packet = packet_message_.pack();
- logs.write_log(NORMAL, "info:Receive data: %s", (packet->data()).c_str());
- callback_->Write(packet);
- }
-
- start_read();
- }
- else{
- logs.write_log(NORMAL, "Error on receive: %s", (ec.message()).c_str());
- stop();
- }
- }
- void Session::start_write_heartbeat(){
- if(stopped_)
- return ;
- Header header;
- header.length = 0;
- header.type = HEARTBEAT;
- boost::asio::async_write(socket_, boost::asio::buffer(&header, HEADERLEN),
- boost::bind(&Session::handle_write_heartbeat, this,
- boost::asio::placeholders::error ));
- logs.write_log(NORMAL, "info:Send heartbeat message--->");
- }
- void Session::handle_write_heartbeat(const boost::system::error_code& ec){
- if(stopped_)
- return ;
-
- if(!ec){
- heartbeat_timer_.expires_from_now(boost::posix_time::seconds(SECONDS));
- heartbeat_timer_.async_wait(boost::bind(&Session::start_write_heartbeat, this));
-
- }
- else{
- logs.write_log(NORMAL, "info:Error on heartbeat: %s ", (ec.message()).c_str());
- stop();
-
- }
- }
- void Session::start_delivery(){
- if(stopped_)
- return ;
- /* *
- * SQLite append
- * */
- Configure conf;
- conf_message_.set_conf(conf);
- conf_message_.Serialize();
- header_.length = conf_message_.length();
- header_.type = CONFIG;
- socket_.async_send(
- boost::asio::buffer(&header_, HEADERLEN),
- boost::bind(&Session::handle_write_config, this, _1, conf)
- //boost::asio::placeholders::error, conf)
-
- );
- }
-
- void Session::delivery(string &ip){
- if(stopped_)
- return ;
- /* *
- * SQLite append
- * */
- Configure conf;
- conf_message_.set_conf(conf);
- conf_message_.Serialize();
- header_.length = conf_message_.length();
- header_.type = CONFIG;
- socket_.async_send(
- boost::asio::buffer(&header_, HEADERLEN),
- boost::bind(&Session::handle_write_config, this, _1, conf)
- //boost::asio::placeholders::error, conf)
-
- );
- }
-
- void Session::handle_write_config(const boost::system::error_code& ec, Configure &conf){
- if(stopped_)
- return ;
-
- if(!ec){
- socket_.async_send(
- boost::asio::buffer(conf_message_.data(),
- conf_message_.length()),
- boost::bind(&Session::handle_wait, this, _1)
-
- );
- }
- }
-
- void Session::handle_wait(const boost::system::error_code &ec){
- return;
- }
-
- //-------------------------------------------------------------------------
-
- //SessionPool
-
- //-------------------------------------------------------------------------
-
- SessionPool::SessionPool(){
- }
-
- SessionPool::~SessionPool(){
-
- }
-
- void SessionPool::join(string &ip, Session *sess){
- session_pool_[ip] = sess;
- }
-
- void SessionPool::delivery(string &ip){
- session_pool_[ip]->delivery(ip);
- }
-
- void SessionPool::leave(string &ip){
- if(NULL == session_pool_[ip]){
- delete session_pool_[ip];
- }
- session_pool_[ip] = NULL;
- }
-
- //-------------------------------------------------------------------------
-
- //Client
-
- //-------------------------------------------------------------------------
-
- Client::Client(boost::asio::io_service &_io_service, boost::asio::io_service &_io_service_data, const char *_sqlite)
- :io_service_(_io_service),
- io_service_data_(_io_service_data),
- deadline_(_io_service),
- sqlite_(_sqlite), all_(false){
-
- }
- void Client::start()
- {
- //IP Table
-
- if(NULL == sqlite_){
- logs.write_log(NORMAL, "Sqlite dbname is invalid");
- return;
- }
- SQLite::get_instance(sqlite_);
- AddrMap &map_ = SQLite::lookup();
- logs.write_log(NORMAL, "Get %d records", map_.size());
- AddrMap::iterator iter = map_.begin();
- for(; iter != map_.end(); iter++){
- Vector vect = iter->second;
- string ip = vect[1], port = vect[2];
- status_[ip] = -1;
- peers_[ip] = std::atoi(port.c_str());
- sockets_[ip] = new boost::asio::ip::tcp::socket(io_service_);
- files_[ip] = "/tmp/file";
- //times_[ip] = boost::asio::deadline_timer(io_service_);
-
- }
-
- //start to connect
-
- start_connect();
- deadline_.async_wait(boost::bind(&Client::handle_deadline, this));
-
- }
- void Client::stop(){
- deadline_.cancel();
- }
-
- void Client::handle_wait_update(){
-
- }
- void Client::handle_update(){
-
- }
- void Client::start_connect(){
- if(peers_.size() > 0){
- deadline_.expires_from_now(boost::posix_time::seconds(DEADLINE));
- for(Peers::iterator it = peers_.begin();
- it != peers_.end(); it++){
-
- if( status_[it->first] < 0){
- logs.write_log(NORMAL, "Start to connect: %s:%d", (it->first).c_str(), it->second);
-
- sockets_[it->first]->async_connect(
- boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(it->first), it->second),
- boost::bind(&Client::handle_connect,
- this, _1, it));
-
- }
- }
- }
- else{
- stop();
- }
-
- }
-
-
- void Client::handle_connect(const boost::system::error_code& ec,
- Peers::iterator it){
- if(!sockets_[it->first]->is_open()){
- logs.write_log(NORMAL, "Connect time out");
- return;
- }
- else if(ec){
- logs.write_log(NORMAL, "Connect error:%s", (ec.message()).c_str());
- //sockets_[it->first]->close();
-
- return;
- }
- else{
- logs.write_log(NORMAL, "Connect ok! it was conected with %s:%d", (it->first).c_str(), it->second);
- status_[it->first] = 1;
- Session * ss = new Session(*(sockets_[it->first]), io_service_data_, (files_[it->first]).c_str());
- session_pool_.join(it->first, ss);
- ss->start();
- }
- }
-
- void Client::handle_deadline(){
-
- check_all();
- if(!all_){
- logs.write_log(NORMAL, "Timers out, begin to connect other server");
- start_connect();
- }
- deadline_.expires_from_now(boost::posix_time::seconds(DEADLINE));
- deadline_.async_wait(boost::bind(&Client::handle_deadline, this));
- }
-
- void Client::check_all(){
- for(Stats::iterator it = status_.begin(); it != status_.end(); it++){
- if(it->second < 0){
- all_ = false;
- return;
- }
- }
- all_ = true;
- return;
-
- }
-
- };
- };