00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <SDL_net.h>
00024 #include <fstream>
00025 #include "download.h"
00026 #include "index_server.h"
00027 #include "index_svr_msg.h"
00028 #include "network.h"
00029 #include "gui/question.h"
00030 #include "include/app.h"
00031 #include "include/constant.h"
00032 #include "tool/debug.h"
00033 #include "tool/i18n.h"
00034 #include "tool/random.h"
00035
00036 IndexServer index_server;
00037
00038 IndexServer::IndexServer()
00039 {
00040 hidden_server = false;
00041 connected = false;
00042 server_lst.clear();
00043 first_server = server_lst.end();
00044 current_server = server_lst.end();
00045 }
00046
00047 IndexServer::~IndexServer()
00048 {
00049 server_lst.clear();
00050 if(connected)
00051 Disconnect();
00052 }
00053
00054
00055 bool IndexServer::Connect()
00056 {
00057 MSG_DEBUG("index_server", "Connecting..");
00058 assert(!connected);
00059
00060 if( hidden_server )
00061 return true;
00062
00063 if( !GetServerList() )
00064 return false;
00065
00066 std::string addr;
00067 int port;
00068
00069
00070
00071 while( GetServerAddress( addr, port) )
00072 {
00073 if( ConnectTo( addr, port) )
00074 return true;
00075 }
00076
00077 Question question;
00078 question.Set(_("Unable to contact an index server!"),1,0);
00079 question.Ask();
00080
00081 return false;
00082 }
00083
00084 bool IndexServer::ConnectTo(const std::string & address, const int & port)
00085 {
00086 MSG_DEBUG("index_server", "Connecting to %s %i", address.c_str(), port);
00087 Question question;
00088 question.Set(_("Contacting main server..."),1,0);
00089 question.Draw();
00090 AppWormux::GetInstance()->video.Flip();
00091
00092 network.Init();
00093
00094 MSG_DEBUG("index_server", "Opening connection");
00095
00096
00097 if( SDLNet_ResolveHost(&ip, address.c_str() , port) == -1 )
00098 {
00099 question.Set(_("Invalid index server adress!"),1,0);
00100 question.Ask();
00101 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00102 return false;
00103 }
00104
00105 socket = SDLNet_TCP_Open(&ip);
00106
00107 if(!socket)
00108 {
00109 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00110 return false;
00111 }
00112
00113 connected = true;
00114
00115 return HandShake();
00116 }
00117
00118 void IndexServer::Disconnect()
00119 {
00120 if( hidden_server )
00121 {
00122 hidden_server = false;
00123 return;
00124 }
00125
00126 if( !connected )
00127 return;
00128
00129 MSG_DEBUG("index_server", "Closing connection");
00130 first_server = server_lst.end();
00131 current_server = server_lst.end();
00132
00133 SDLNet_TCP_Close(socket);
00134 connected = false;
00135 }
00136
00137 static ssize_t getline(std::string& line, std::ifstream& file)
00138 {
00139 line.clear();
00140 std::getline(file, line);
00141 if(file.eof())
00142 return -1;
00143 return line.size();
00144 }
00145
00146 bool IndexServer::GetServerList()
00147 {
00148 MSG_DEBUG("index_server", "Retrieving server list");
00149
00150 if(server_lst.size() != 0)
00151 return true;
00152
00153
00154 const std::string server_file = Config::GetInstance()->GetPersonalDir() + "server_list";
00155
00156 if( !downloader.Get(server_list_url.c_str(), server_file.c_str()) )
00157 return false;
00158
00159
00160 std::ifstream fin;
00161 fin.open(server_file.c_str(), std::ios::in);
00162 if(!fin)
00163 return false;
00164
00165
00166
00167 ssize_t read;
00168 std::string line;
00169
00170
00171 while ((read = getline(line, fin)) >= 0)
00172 {
00173 if(line.at(0) == '#' || line.at(0) == '\n' || line.at(0) == '\0')
00174 continue;
00175
00176 std::string::size_type port_pos = line.find(':', 0);
00177 if(port_pos == std::string::npos)
00178 continue;
00179
00180 std::string hostname = line.substr(0, port_pos);
00181 std::string portstr = line.substr(port_pos+1);
00182 int port = atoi(portstr.c_str());
00183
00184 server_lst[ hostname ] = port;
00185 }
00186
00187 fin.close();
00188
00189 first_server = server_lst.end();
00190 current_server = server_lst.end();
00191 MSG_DEBUG("index_server", "Server list retrieved. %i servers are running", server_lst.size());
00192
00193 return (server_lst.size() != 0);
00194 }
00195
00196 bool IndexServer::GetServerAddress( std::string & address, int & port)
00197 {
00198 MSG_DEBUG("index_server", "Trying a new server");
00199
00200
00201 if( first_server == server_lst.end() )
00202 {
00203
00204
00205 int nbr = randomObj.GetLong( 0, server_lst.size()-1 );
00206 first_server = server_lst.begin();
00207 while(nbr--)
00208 ++first_server;
00209
00210 assert(first_server != server_lst.end());
00211
00212 current_server = first_server;
00213
00214 address = current_server->first;
00215 port = current_server->second;
00216 return true;
00217 }
00218
00219 ++current_server;
00220 if( current_server == server_lst.end() )
00221 current_server = server_lst.begin();
00222
00223 address = current_server->first;
00224 port = current_server->second;
00225
00226 return (current_server != first_server);
00227 }
00228
00229
00230 void IndexServer::Send(const int& nbr)
00231 {
00232 char packet[4];
00233
00234 Uint32 u_nbr = *((Uint32*)&nbr);
00235
00236 SDLNet_Write32(u_nbr, packet);
00237 SDLNet_TCP_Send(socket, packet, sizeof(packet));
00238 }
00239
00240 void IndexServer::Send(const std::string &str)
00241 {
00242 Send(str.size());
00243 SDLNet_TCP_Send(socket, (void*)str.c_str(), str.size());
00244 }
00245
00246 int IndexServer::ReceiveInt()
00247 {
00248 char packet[4];
00249 if( SDLNet_TCP_Recv(socket, packet, sizeof(packet)) < 1 )
00250 {
00251 Disconnect();
00252 return 0;
00253 }
00254
00255 Uint32 u_nbr = SDLNet_Read32(packet);
00256 int nbr = *((int*)&u_nbr);
00257 return nbr;
00258 }
00259
00260 std::string IndexServer::ReceiveStr()
00261 {
00262 int size = ReceiveInt();
00263
00264 if(!connected)
00265 return "";
00266
00267 assert(size > 0);
00268 char* str = new char[size+1];
00269
00270 if( SDLNet_TCP_Recv(socket, str, size) < 1 )
00271 {
00272 Disconnect();
00273 return "";
00274 }
00275
00276 str[size] = '\0';
00277
00278 std::string st(str);
00279 delete []str;
00280 return st;
00281 }
00282
00283 bool IndexServer::HandShake()
00284 {
00285 Send(TS_MSG_VERSION);
00286 Send(Constants::VERSION);
00287
00288 int msg = ReceiveInt();
00289 std::string sign;
00290
00291 if(msg == TS_MSG_VERSION)
00292 sign = ReceiveStr();
00293
00294 if(msg != TS_MSG_VERSION || sign != "MassMurder!")
00295 {
00296 Question question;
00297 question.Set(_("It doesn't seem to be a valid Wormux server..."),1,0);
00298 question.Ask();
00299 Disconnect();
00300 return false;
00301 }
00302 return true;
00303 }
00304
00305 void IndexServer::SendServerStatus()
00306 {
00307 assert(network.IsServer());
00308
00309 if(hidden_server)
00310 return;
00311 Send(TS_MSG_HOSTING);
00312 Send(network.GetPort());
00313 }
00314
00315 std::list<address_pair> IndexServer::GetHostList()
00316 {
00317 Send(TS_MSG_GET_LIST);
00318 int lst_size = ReceiveInt();
00319 std::list<address_pair> lst;
00320 while(lst_size--)
00321 {
00322 IPaddress ip;
00323 ip.host = ReceiveInt();
00324 ip.port = ReceiveInt();
00325 const char* addr = SDLNet_ResolveIP(&ip);
00326 char port[10];
00327 sprintf(port, "%d", ip.port);
00328
00329 address_pair addr_pair;
00330 addr_pair.second = std::string(port);
00331
00332 if(addr == NULL)
00333 {
00334
00335 unsigned char* str_ip = (unsigned char*)&ip.host;
00336 char formated_ip[16];
00337 snprintf(formated_ip, 16, "%i.%i.%i.%i", (int)str_ip[0],
00338 (int)str_ip[1],
00339 (int)str_ip[2],
00340 (int)str_ip[3]);
00341 addr_pair.first = std::string(formated_ip);
00342 }
00343 else
00344 addr_pair.first = std::string(addr);
00345 lst.push_back(addr_pair);
00346 }
00347 return lst;
00348 }