SocketHandler.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include <glibmm.h>
  2. #include <giomm.h>
  3. #include <list>
  4. #include <iostream>
  5. #include "SocketHandler.h"
  6. #include <cassert>
  7. /*
  8. Connections factory
  9. */
  10. SocketHandlerFactory* SocketHandlerFactory::m_instance=nullptr;
  11. /*
  12. Creation process
  13. */
  14. SocketHandlerFactory* SocketHandlerFactory::get()
  15. {
  16. if (nullptr==m_instance){
  17. m_instance = new SocketHandlerFactory();
  18. }
  19. return m_instance;
  20. }
  21. /*
  22. fuel
  23. */
  24. void SocketHandlerFactory::push(std::unique_ptr<SocketHandler>& source)
  25. {
  26. if(m_queue.empty()){
  27. Glib::signal_timeout().connect_seconds(sigc::mem_fun(this,&SocketHandlerFactory::patrol),1);
  28. }
  29. m_queue.push_back(std::move(source));
  30. }
  31. /*
  32. remove_if function
  33. remote connection to be destroyed
  34. */
  35. bool on_shut (const std::unique_ptr<SocketHandler>& value)
  36. {
  37. return value->toBeDestroyed();
  38. }
  39. /*
  40. cleanup closed connections
  41. */
  42. void SocketHandlerFactory::clean()
  43. {
  44. m_queue.remove_if(on_shut);
  45. if(m_queue.empty()){
  46. std::cout << "no open connection left." << std::endl;
  47. }
  48. }
  49. bool SocketHandlerFactory::patrol()
  50. {
  51. for(auto &it:m_queue){
  52. it->patrol();
  53. }
  54. return !m_queue.empty();
  55. }
  56. /*
  57. straight connection
  58. */
  59. SocketHandler::SocketHandler(const Glib::ustring& host,int port)
  60. :m_status(CONNECTING),m_garbage(false),m_patrol(-1)
  61. {
  62. connect_to_host_async(host,port,sigc::mem_fun(this,&SocketHandler::on_connect_async_ready));
  63. }
  64. SocketHandler::~SocketHandler()
  65. {
  66. std::cout << "bye." << std::endl;
  67. }
  68. SocketHandler::states SocketHandler::status() const
  69. {
  70. return m_status;
  71. }
  72. /*
  73. patrol counter before
  74. on patrol
  75. -1: disable
  76. */
  77. void SocketHandler::setPatrolCounter(ssize_t counter)
  78. {
  79. m_patrol=counter;
  80. }
  81. void SocketHandler::patrol()
  82. {
  83. if(m_patrol>0){
  84. --m_patrol;
  85. }
  86. if(m_patrol==0){
  87. onPatrol();
  88. }
  89. }
  90. bool SocketHandler::toBeDestroyed() const
  91. {
  92. return m_garbage;
  93. }
  94. void SocketHandler::onPatrol()
  95. {
  96. }
  97. void SocketHandler::selfDestroy()
  98. {
  99. std::cout << "kill me quick, before I died." << std::endl;
  100. m_garbage=true;
  101. Glib::signal_idle().connect_once(sigc::mem_fun(SocketHandlerFactory::get(),&SocketHandlerFactory::clean));
  102. }
  103. bool SocketHandler::error_handler(
  104. Glib::IOCondition /*io_condition*/)
  105. {
  106. m_status=ERROR;
  107. selfDestroy();
  108. /* detach signal */
  109. return false;
  110. }
  111. void SocketHandler::on_connect_async_ready(Glib::RefPtr<Gio::AsyncResult>& result)
  112. {
  113. try{
  114. m_socketclient=connect_to_host_finish(result);
  115. std::cout << "we r in" << std::endl;
  116. m_status=READY;
  117. }
  118. catch(Glib::Error& e){
  119. m_status=ERROR;
  120. std::cout << e.what() << std::endl;
  121. }
  122. /*
  123. callback
  124. */
  125. on_connect();
  126. }
  127. SingleRequestSocket::SingleRequestSocket(const Glib::ustring& host,int port)
  128. :SocketHandler(host,port)
  129. {}
  130. /*
  131. connection callback
  132. override
  133. */
  134. void SingleRequestSocket::on_connect()
  135. {
  136. if(m_status==SocketHandler::READY){
  137. Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::write_handler), m_socketclient->get_socket(), Glib::IO_OUT);
  138. Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::error_handler), m_socketclient->get_socket(), Glib::IO_HUP | Glib::IO_ERR | Glib::IO_NVAL);
  139. }
  140. else{
  141. error_handler(Glib::IOCondition::IO_ERR);
  142. }
  143. }
  144. void SingleRequestSocket::onPatrol()
  145. {
  146. selfDestroy();
  147. }
  148. /*
  149. Sending ready
  150. */
  151. bool SingleRequestSocket::write_handler(
  152. Glib::IOCondition /*io_condition*/)
  153. {
  154. /*
  155. send something to remote
  156. */
  157. Glib::ustring message = "GET / HTTP/1.1\r\nHost: kikoolaule\r\n\r\n";
  158. m_socketclient->get_output_stream()->write (message);
  159. /*
  160. received bytes notifications
  161. */
  162. Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::read_handler), m_socketclient->get_socket(), Glib::IO_IN);
  163. /* one shot write:
  164. detach signal
  165. */
  166. return false;
  167. }
  168. bool SingleRequestSocket::read_handler(Glib::IOCondition io_condition)
  169. {
  170. assert(io_condition==Glib::IO_IN);
  171. try
  172. {
  173. auto idata=m_socketclient->get_input_stream();
  174. gsize total=m_socketclient->get_socket()->get_available_bytes();
  175. if(total>0)
  176. {
  177. do
  178. {
  179. std::vector<char> buf(total);
  180. gsize r=idata->read(buf.data(),total);
  181. std::string answer(buf.begin(),buf.begin()+r);
  182. std::cout << answer << std::flush;
  183. total=m_socketclient->get_socket()->get_available_bytes();
  184. }while( total<0);
  185. }
  186. else
  187. {
  188. m_status=SHUTDOWN;
  189. }
  190. }
  191. catch(Glib::Error& e)
  192. {
  193. m_status=ERROR;
  194. error_handler(io_condition);
  195. }
  196. if(m_status!=READY){
  197. selfDestroy();
  198. }
  199. return m_status==READY;
  200. }