| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- #include <glibmm.h>
- #include <giomm.h>
- #include <list>
- #include <iostream>
- #include "SocketHandler.h"
- #include <cassert>
- /*
- 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<SocketHandler>& 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<SocketHandler>& 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<Gio::AsyncResult>& 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<char> 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;
- }
|