PageRenderTime 60ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/warmux-11.04/tools/servers/index_server/sync_slave.cpp

#
C++ | 252 lines | 199 code | 33 blank | 20 comment | 47 complexity | 9970cd6ac7c2c3e5617ec5769d7239e7 MD5 | raw file
Possible License(s): BSD-3-Clause, 0BSD, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. /******************************************************************************
  2. * Warmux is a convivial mass murder game.
  3. * Copyright (C) 2001-2011 Warmux Team.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  18. ******************************************************************************/
  19. #include <list>
  20. #include <fstream>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <sys/ioctl.h>
  24. #include <WSERVER_debug.h>
  25. #include <WSERVER_index_msg.h>
  26. #include "sync_slave.h"
  27. #include "config.h"
  28. #include "client.h"
  29. #include "net_data.h"
  30. #include "download.h"
  31. #include "stat.h"
  32. SyncSlave sync_slave;
  33. // map < version, ip >
  34. std::multimap<std::string, FakeClient> fake_clients;
  35. SyncSlave::SyncSlave()
  36. {
  37. }
  38. SyncSlave::~SyncSlave()
  39. {
  40. for(iterator it = begin();
  41. it != end();
  42. ++it)
  43. {
  44. delete (it->second);
  45. }
  46. }
  47. static ssize_t getline(std::string& line, std::ifstream& file)
  48. {
  49. line.clear();
  50. std::getline(file, line);
  51. if(file.eof())
  52. return -1;
  53. return line.size();
  54. }
  55. bool SyncSlave::Start()
  56. {
  57. const std::string server_fn = "./server_list";
  58. DPRINT(TRAFFIC, "Contacting other servers ...");
  59. std::ifstream fin;
  60. fin.open(server_fn.c_str(), std::ios::in);
  61. if (!fin)
  62. return false;
  63. ssize_t read;
  64. std::string line;
  65. std::string my_hostname;
  66. config.Get( "my_hostname", my_hostname);
  67. // GNU getline isn't available on *BSD and Win32, so we use a new function, see getline above
  68. while ((read = getline(line, fin)) >= 0)
  69. {
  70. if (line.size() == 0 || line.at(0) == '#')
  71. continue;
  72. std::string::size_type port_pos = line.find(':', 0);
  73. if (port_pos == std::string::npos)
  74. continue;
  75. std::string hostname = line.substr(0, port_pos);
  76. std::string portstr = line.substr(port_pos+1);
  77. int port = atoi(portstr.c_str());
  78. if (hostname != my_hostname && find(hostname) == end())
  79. {
  80. IndexServerConn* c = new IndexServerConn(hostname, port);
  81. if (c->connected)
  82. insert(make_pair(hostname, c));
  83. else
  84. delete c;
  85. }
  86. }
  87. fin.close();
  88. return true;
  89. }
  90. void SyncSlave::CheckGames()
  91. {
  92. iterator it = begin();
  93. while (it != end())
  94. {
  95. int received;
  96. bool result = false;
  97. if (ioctl( it->second->GetFD(), FIONREAD, &received) == -1)
  98. {
  99. PRINT_ERROR;
  100. result = false;
  101. }
  102. if (received == 0 || it->second->Receive())
  103. result = true;
  104. if (!result || ! it->second->connected)
  105. {
  106. DPRINT(INFO, "Index server at %s disconnected", it->first.c_str());
  107. delete it->second;
  108. erase(it);
  109. it = begin();
  110. }
  111. else
  112. {
  113. it->second->CheckState();
  114. ++it;
  115. }
  116. }
  117. }
  118. IndexServerConn::IndexServerConn(const std::string &addr, int port)
  119. {
  120. DPRINT(INFO, "Contacting index server at %s ...",addr.c_str());
  121. if(!ConnectTo( addr, port))
  122. return;
  123. SendInt((int)TS_MSG_VERSION);
  124. SendStr("WIS");
  125. }
  126. IndexServerConn::~IndexServerConn()
  127. {
  128. close(GetFD());
  129. }
  130. bool IndexServerConn::HandShake()
  131. {
  132. std::string key;
  133. if (!ReceiveStr(key))
  134. return false;
  135. if (key != "MassMurder!")
  136. {
  137. DPRINT(INFO,"Doesn't seem do be a valid server...");
  138. return false;
  139. }
  140. DPRINT(INFO,"Server identified...");
  141. return true;
  142. }
  143. bool IndexServerConn::HandleMsg(enum IndexServerMsg msg_id)
  144. {
  145. switch(msg_id)
  146. {
  147. case TS_MSG_VERSION:
  148. return HandShake();
  149. break;
  150. case TS_MSG_WIS_VERSION:
  151. {
  152. int version;
  153. if (BytesReceived() < sizeof(uint32_t)) // The message is not completely received
  154. return true;
  155. if (!ReceiveInt(version)) // Receive the version number of the server index
  156. return false;
  157. if (version > VERSION)
  158. {
  159. DPRINT(INFO,"The server at %i have a version %i, while we are only running a %i version",
  160. GetIP(), version, VERSION);
  161. exit(EXIT_FAILURE);
  162. }
  163. else if(version < VERSION)
  164. {
  165. DPRINT(INFO,"This server is running an old version (v%i) !", version);
  166. return false;
  167. }
  168. DPRINT(INFO,"We are running the same version..");
  169. }
  170. break;
  171. case TS_MSG_JOIN_LEAVE:
  172. {
  173. int ip;
  174. int port;
  175. std::string version;
  176. if (!ReceiveStr(version))
  177. return false;
  178. if (BytesReceived() < 2*sizeof(uint32_t)) // The message is not completely received
  179. return true;
  180. if (!ReceiveInt(ip)) // Receive the IP of the warmux server
  181. return false;
  182. if (!ReceiveInt(port)) // Receive the port of the warmux server
  183. return false;
  184. if (port < 0) // means it disconnected
  185. {
  186. for (std::multimap<std::string, FakeClient>::iterator serv = fake_clients.lower_bound(version);
  187. serv != fake_clients.upper_bound(version);
  188. serv++) {
  189. if( serv->second.ip == ip
  190. && serv->second.port == -port )
  191. {
  192. fake_clients.erase(serv);
  193. DPRINT(MSG, "A fake server disconnected");
  194. break;
  195. }
  196. }
  197. }
  198. else
  199. {
  200. HostOptions options;
  201. std::string game_name;
  202. if (!ReceiveStr(game_name))
  203. return false;
  204. int passwd;
  205. if (!ReceiveInt(passwd))
  206. return false;
  207. options.Set(game_name, passwd);
  208. fake_clients.insert(std::make_pair(version, FakeClient(ip, port, options)));
  209. stats.NewFakeServer(version);
  210. }
  211. }
  212. break;
  213. default:
  214. DPRINT(INFO,"Bad message!");
  215. return false;
  216. }
  217. msg_id = TS_NO_MSG;
  218. return true;
  219. }