|
|
@@ -0,0 +1,228 @@
|
|
|
+#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;
|
|
|
+}
|
|
|
+
|