#include #include #include #include #include "SocketHandler.h" #include /* Connections factory */ SocketHandlerFactory* SocketHandlerFactory::m_instance=nullptr; /* Creation process */ SocketHandlerFactory* SocketHandlerFactory::get() { if (nullptr==m_instance){ m_instance = new SocketHandlerFactory(); } return m_instance; } /* fuel */ void SocketHandlerFactory::push(std::unique_ptr& source) { if(m_queue.empty()){ Glib::signal_timeout().connect_seconds(sigc::mem_fun(this,&SocketHandlerFactory::patrol),1); } m_queue.push_back(std::move(source)); } /* remove_if function remote connection to be destroyed */ bool on_shut (const std::unique_ptr& value) { return value->toBeDestroyed(); } /* cleanup closed connections */ void SocketHandlerFactory::clean() { m_queue.remove_if(on_shut); if(m_queue.empty()){ std::cout << "no open connection left." << std::endl; } } bool SocketHandlerFactory::patrol() { for(auto &it:m_queue){ it->patrol(); } return !m_queue.empty(); } /* straight connection */ SocketHandler::SocketHandler(const Glib::ustring& host,int port) :m_status(CONNECTING),m_garbage(false),m_patrol(-1) { connect_to_host_async(host,port,sigc::mem_fun(this,&SocketHandler::on_connect_async_ready)); } SocketHandler::~SocketHandler() { std::cout << "bye." << std::endl; } SocketHandler::states SocketHandler::status() const { return m_status; } /* patrol counter before on patrol -1: disable */ void SocketHandler::setPatrolCounter(ssize_t counter) { m_patrol=counter; } void SocketHandler::patrol() { if(m_patrol>0){ --m_patrol; } if(m_patrol==0){ onPatrol(); } } bool SocketHandler::toBeDestroyed() const { return m_garbage; } void SocketHandler::onPatrol() { } void SocketHandler::selfDestroy() { std::cout << "kill me quick, before I died." << std::endl; m_garbage=true; Glib::signal_idle().connect_once(sigc::mem_fun(SocketHandlerFactory::get(),&SocketHandlerFactory::clean)); } bool SocketHandler::error_handler( Glib::IOCondition /*io_condition*/) { m_status=ERROR; selfDestroy(); /* detach signal */ return false; } void SocketHandler::on_connect_async_ready(Glib::RefPtr& result) { try{ m_socketclient=connect_to_host_finish(result); std::cout << "we r in" << std::endl; m_status=READY; } catch(Glib::Error& e){ m_status=ERROR; std::cout << e.what() << std::endl; } /* callback */ on_connect(); } SingleRequestSocket::SingleRequestSocket(const Glib::ustring& host,int port) :SocketHandler(host,port) {} /* connection callback override */ void SingleRequestSocket::on_connect() { if(m_status==SocketHandler::READY){ Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::write_handler), m_socketclient->get_socket(), Glib::IO_OUT); Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::error_handler), m_socketclient->get_socket(), Glib::IO_HUP | Glib::IO_ERR | Glib::IO_NVAL); } else{ error_handler(Glib::IOCondition::IO_ERR); } } void SingleRequestSocket::onPatrol() { selfDestroy(); } /* Sending ready */ bool SingleRequestSocket::write_handler( Glib::IOCondition /*io_condition*/) { /* send something to remote */ Glib::ustring message = "GET / HTTP/1.1\r\nHost: kikoolaule\r\n\r\n"; m_socketclient->get_output_stream()->write (message); /* received bytes notifications */ Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::read_handler), m_socketclient->get_socket(), Glib::IO_IN); /* one shot write: detach signal */ return false; } bool SingleRequestSocket::read_handler(Glib::IOCondition io_condition) { assert(io_condition==Glib::IO_IN); try { auto idata=m_socketclient->get_input_stream(); gsize total=m_socketclient->get_socket()->get_available_bytes(); if(total>0) { do { std::vector buf(total); gsize r=idata->read(buf.data(),total); std::string answer(buf.begin(),buf.begin()+r); std::cout << answer << std::flush; total=m_socketclient->get_socket()->get_available_bytes(); }while( total<0); } else { m_status=SHUTDOWN; } } catch(Glib::Error& e) { m_status=ERROR; error_handler(io_condition); } if(m_status!=READY){ selfDestroy(); } return m_status==READY; }