/Projects/LightningPrototypes/Client/Source/client.cpp

https://github.com/pxf/pxf-tech2 · C++ · 231 lines · 178 code · 44 blank · 9 comment · 32 complexity · 5cc4bc4571ebc36361a0c2fbe20c10ea MD5 · raw file

  1. #include "client.h"
  2. #define INITIAL_QUEUE 6
  3. #define PING_INTERVAL 10000 // Ping interval in milliseconds
  4. #define PING_TIMEOUT 5000 // Ping timeout in milliseconds
  5. Client::Client(const char *_tracker_address, int _tracker_port, const char *_local_address, int _local_port, int _client_port)
  6. {
  7. GOOGLE_PROTOBUF_VERIFY_VERSION;
  8. m_tracker_address = Pxf::StringDuplicate(_tracker_address);
  9. m_tracker_port = _tracker_port;
  10. m_local_address = Pxf::StringDuplicate(_local_address);
  11. m_local_port = _local_port;
  12. m_client_port = _client_port;
  13. m_TaskQueue.reserve(INITIAL_QUEUE);
  14. m_ConnMan = ConnectionManager((Pxf::Util::Array<Packet*>*)(new Pxf::Util::Array<LiPacket*>));
  15. m_Kernel = Pxf::Kernel::GetInstance();
  16. m_log_tag = m_Kernel->CreateTag("cli");
  17. m_net_tag = m_ConnMan.m_log_tag;
  18. }
  19. Client::~Client()
  20. {
  21. Pxf::MemoryFree(m_tracker_address);
  22. Pxf::MemoryFree(m_local_address);
  23. }
  24. int Client::run()
  25. {
  26. time_t last_ping, ping_timestamp;
  27. Pxf::Util::Array<LiPacket*> *packets;
  28. // Setting up socket for clients to connect to
  29. Connection *client_c = m_ConnMan.new_connection(CLIENT);
  30. if(!m_ConnMan.bind_connection(client_c, m_local_address, m_client_port))
  31. {
  32. m_Kernel->Log(m_net_tag, "Could not bind to %s:%d", m_local_address, m_client_port);
  33. return false;
  34. }
  35. printf("bound client socket has sockid:%d\n", client_c->socket);
  36. m_Kernel->Log(m_log_tag, "Connecting to tracker at %s.", m_tracker_address);
  37. bool exit = false;
  38. if (!connect_tracker())
  39. {
  40. m_Kernel->Log(m_log_tag, "Connection failed, quitting");
  41. exit = true;
  42. }
  43. ping_timestamp = time(NULL);
  44. // This is our main fail
  45. while(!exit)
  46. {
  47. packets = (Pxf::Util::Array<LiPacket*>*)m_ConnMan.recv_packets(PING_INTERVAL);
  48. if (difftime(time(NULL), ping_timestamp) > PING_INTERVAL/1000.0f)
  49. {
  50. // Ping all connections
  51. Pxf::Util::Array<struct Connection*>::iterator i_conn;
  52. for (i_conn = m_ConnMan.m_Connections.begin(); i_conn != m_ConnMan.m_Connections.end(); i_conn++)
  53. {
  54. if ((*i_conn)->bound)
  55. continue;
  56. if (difftime(ping_timestamp, (*i_conn)->timestamp) > PING_TIMEOUT/1000.0f)
  57. {
  58. m_Kernel->Log(m_log_tag, "Connection to %s timed out...", (*i_conn)->target_address);
  59. m_ConnMan.remove_connection(*i_conn);
  60. if (i_conn == m_ConnMan.m_Connections.end())
  61. break;
  62. continue;
  63. }
  64. ping(*i_conn, (int)time(NULL));
  65. }
  66. ping_timestamp = time(NULL);
  67. continue;
  68. }
  69. // If there are no packets available, try to get some more
  70. if (packets->empty()) continue;
  71. // Packet loop
  72. Pxf::Util::Array<LiPacket*>::iterator p;
  73. p = packets->begin();
  74. while (p != packets->end())
  75. {
  76. (*p)->get_type();
  77. if ((*p)->connection->type == CLIENT)
  78. {
  79. m_Kernel->Log(m_log_tag, "Packet from a client");
  80. switch((*p)->message_type)
  81. {
  82. case 1:
  83. break;
  84. default:
  85. m_Kernel->Log(m_log_tag, "Unknown packet type: %d", (*p)->message_type);
  86. p = packets->erase(p);
  87. continue;
  88. }
  89. }
  90. else if ((*p)->connection->type == TRACKER)
  91. {
  92. m_Kernel->Log(m_log_tag, "Packet from tracker");
  93. switch((*p)->message_type)
  94. {
  95. case PONG: //PONG
  96. {
  97. trackerclient::Pong *pong = (trackerclient::Pong*)((*p)->unpack());
  98. (*p)->connection->timestamp = time(NULL);
  99. p = packets->erase(p);
  100. continue;
  101. }
  102. default:
  103. m_Kernel->Log(m_log_tag, "Unknown packet type: %d", (*p)->message_type);
  104. p = packets->erase(p);
  105. continue;
  106. }
  107. }
  108. else if ((*p)->connection->type == INTERNAL)
  109. {
  110. 1+1;
  111. }
  112. else
  113. {
  114. m_Kernel->Log(m_log_tag, "Packet from unknown connection type, dropping");
  115. p = packets->erase(p);
  116. continue;
  117. }
  118. p++;
  119. }
  120. }
  121. return 0;
  122. }
  123. void Client::ping(Connection *_c, int _timestamp)
  124. {
  125. trackerclient::Ping *ping_tracker = new trackerclient::Ping();
  126. ping_tracker->set_ping_data(_timestamp);
  127. LiPacket *pkg = new LiPacket(_c, ping_tracker, PING);
  128. m_ConnMan.send(_c, pkg->data, pkg->length);
  129. delete pkg;
  130. }
  131. /* Connects to the tracker at the specified endpoint */
  132. bool Client::connect_tracker()
  133. {
  134. Connection *bound_c = m_ConnMan.new_connection(CLIENT);
  135. if(!m_ConnMan.bind_connection(bound_c, m_local_address, m_local_port))
  136. {
  137. m_Kernel->Log(m_net_tag, "Could not bind to %s:%d", m_local_address, m_local_port);
  138. return false;
  139. }
  140. bound_c->type = TRACKER;
  141. Connection *c = m_ConnMan.new_connection(TRACKER);
  142. if (!m_ConnMan.connect_connection(c, m_tracker_address, m_tracker_port))
  143. {
  144. m_Kernel->Log(m_net_tag, "Could not connect to tracker.");
  145. return false;
  146. }
  147. int type = INIT_HELLO;
  148. m_ConnMan.send(c, (char*)&type, 4);
  149. // Wait for tracker to respond. Timeout after 5 seconds.
  150. Pxf::Util::Array<LiPacket*> *packets = (Pxf::Util::Array<LiPacket*>*)m_ConnMan.recv_packets(5000);
  151. if (packets->size() == 0)
  152. {
  153. m_Kernel->Log(m_net_tag, "Connection to tracker at %s timed out.", c->target_address);
  154. return false;
  155. }
  156. trackerclient::HelloToClient *hello_client = (trackerclient::HelloToClient*)(packets->front()->unpack());
  157. m_session_id = hello_client->session_id();
  158. // delete packets->front();
  159. packets->clear();
  160. m_Kernel->Log(m_log_tag, "Connected to tracker. Got session_id %d, using socket %d", m_session_id, c->socket);
  161. trackerclient::HelloToTracker *hello_tracker = new trackerclient::HelloToTracker();
  162. hello_tracker->set_session_id(m_session_id);
  163. hello_tracker->set_address(m_local_address);
  164. hello_tracker->set_port(m_local_port);
  165. hello_tracker->set_client_port(m_client_port);
  166. hello_tracker->set_available(m_TaskQueue.capacity()-m_TaskQueue.size());
  167. LiPacket *pkg = new LiPacket(c, hello_tracker, HELLO_TO_TRACKER);
  168. m_ConnMan.send(c, pkg->data, pkg->length);
  169. m_Kernel->Log(m_log_tag, "Connection to tracker on socket %d terminated.", c->socket);
  170. m_ConnMan.remove_connection(c);
  171. delete pkg;
  172. packets = (Pxf::Util::Array<LiPacket*>*)m_ConnMan.recv_packets(5000);
  173. if (packets->empty())
  174. {
  175. // Check that the tracker connected...
  176. Pxf::Util::Array<Connection*>::iterator c;
  177. for (c = m_ConnMan.m_Connections.begin(); c != m_ConnMan.m_Connections.end(); c++)
  178. if ((*c)->type == TRACKER) return true;
  179. m_Kernel->Log(m_net_tag, "Tracker could not connect to client. Are the ports open?");
  180. return false;
  181. }
  182. else
  183. {
  184. m_Kernel->Log(m_net_tag, "Got unknown packet when expecting connection from tracker.");
  185. return false;
  186. }
  187. }