00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "network.h"
00023
00024 #include <SDL_net.h>
00025 #include <SDL_thread.h>
00026 #include <netinet/in.h>
00027 #include "../game/game_mode.h"
00028 #include "../game/game.h"
00029 #include "../gui/question.h"
00030 #include "../include/action_handler.h"
00031 #include "../tool/debug.h"
00032 #include "../tool/i18n.h"
00033 #include "distant_cpu.h"
00034
00035 #if defined(DEBUG) && not defined(WIN32)
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #endif
00040
00041 Network network;
00042
00043
00044
00045 Network::Network()
00046 {
00047 max_player_number = 0;
00048 m_is_connected = false;
00049 m_is_server = false;
00050 m_is_client = false;
00051 state = NETWORK_NOT_CONNECTED;
00052 inited = false;
00053 sync_lock = false;
00054 network_menu = NULL;
00055
00056
00057 #ifdef WIN32
00058 nickname = getenv("USERNAME");
00059 #else
00060 nickname = getenv("USER");
00061 #endif
00062 }
00063
00064
00065 int net_thread_func(void* no_param)
00066 {
00067 network.ReceiveActions();
00068 network.Disconnect();
00069 return 1;
00070 }
00071
00072
00073
00074 void Network::Init()
00075 {
00076 if(inited) return;
00077 if (SDLNet_Init()) {
00078 Error(_("Failed to initialize network library!"));
00079 }
00080 inited = true;
00081 max_player_number = GameMode::GetInstance()->max_teams;
00082 connected_player = 0;
00083
00084 #if defined(DEBUG) && not defined(WIN32)
00085 fin = open("./network.in", O_RDWR | O_CREAT | O_SYNC, S_IRWXU | S_IRWXG);
00086 fout = open("./network.out", O_RDWR | O_CREAT | O_SYNC, S_IRWXU | S_IRWXG);
00087 #endif
00088 }
00089
00090
00091
00092 Network::~Network()
00093 {
00094 Disconnect();
00095 if(inited)
00096 {
00097 SDLNet_Quit();
00098 #if defined(DEBUG) && not defined(WIN32)
00099 close(fin);
00100 close(fout);
00101 #endif
00102 }
00103 }
00104
00105
00106
00107 void Network::Disconnect()
00108 {
00109 if(!m_is_connected) return;
00110
00111 m_is_connected = false;
00112
00113 SDL_WaitThread(thread,NULL);
00114 printf("Network thread finished\n");
00115 for(std::list<DistantComputer*>::iterator client = cpu.begin();
00116 client != cpu.end();
00117 client++)
00118 {
00119 delete *client;
00120 }
00121 cpu.clear();
00122 SDLNet_FreeSocketSet(socket_set);
00123
00124 if(m_is_server)
00125 SDLNet_TCP_Close(server_socket);
00126
00127 m_is_server = false;
00128 m_is_client = false;
00129 }
00130
00131
00132
00133
00134 void Network::ClientConnect(const std::string &host, const std::string& port)
00135 {
00136 MSG_DEBUG("network", "Client connect to %s:%s", host.c_str(), port.c_str());
00137
00138 int prt=0;
00139 sscanf(port.c_str(),"%i",&prt);
00140 prt = htons(prt);
00141
00142 if(SDLNet_ResolveHost(&ip,host.c_str(),prt)==-1)
00143 {
00144 Question question;
00145 question.Set(_("Invalid server adress!"),1,0);
00146 question.Ask();
00147 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00148 return;
00149 }
00150
00151 ip.port = prt;
00152
00153 TCPsocket socket = SDLNet_TCP_Open(&ip);
00154
00155 if(!socket)
00156 {
00157 Question question;
00158 question.Set(_("Unable to contact server!"),1,0);
00159 question.Ask();
00160 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00161 return;
00162 }
00163
00164 m_is_client = true;
00165 m_is_server = false;
00166 state = NETWORK_OPTION_SCREEN;
00167 m_is_connected = true;
00168
00169 socket_set = SDLNet_AllocSocketSet(1);
00170 connected_player = 1;
00171 cpu.push_back(new DistantComputer(socket));
00172
00173 Action a(Action::ACTION_NICKNAME, nickname);
00174 network.SendAction(&a);
00175
00176
00177 thread = SDL_CreateThread(net_thread_func,NULL);
00178 }
00179
00180
00181
00182
00183
00184 void Network::ServerStart(const std::string &port)
00185 {
00186
00187 MSG_DEBUG("network", "Start server on port %s", port.c_str());
00188
00189 cpu.clear();
00190
00191 int prt;
00192 sscanf(port.c_str(),"%i",&prt);
00193 prt = htons(prt);
00194
00195 if(SDLNet_ResolveHost(&ip,NULL,prt)==-1)
00196 {
00197 Question question;
00198 question.Set(_("Invalid port!"),1,0);
00199 question.Ask();
00200 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00201 return;
00202 }
00203 ip.port = prt;
00204
00205 m_is_server = true;
00206 m_is_client = false;
00207 m_is_connected = true;
00208
00209
00210 state = NETWORK_OPTION_SCREEN;
00211 AcceptIncoming();
00212 connected_player = 1;
00213 printf("\nConnected\n");
00214 socket_set = SDLNet_AllocSocketSet(GameMode::GetInstance()->max_teams);
00215 thread = SDL_CreateThread(net_thread_func,NULL);
00216 }
00217
00218 std::list<DistantComputer*>::iterator Network::CloseConnection(std::list<DistantComputer*>::iterator closed)
00219 {
00220 printf("Client disconnected\n");
00221 delete *closed;
00222 if(m_is_server && connected_player == max_player_number)
00223 {
00224
00225
00226 printf("Allowing new connections\n");
00227 AcceptIncoming();
00228 }
00229
00230 connected_player--;
00231 return cpu.erase(closed);
00232 }
00233
00234 void Network::AcceptIncoming()
00235 {
00236 assert(m_is_server);
00237 if(state != NETWORK_OPTION_SCREEN) return;
00238
00239 server_socket = SDLNet_TCP_Open(&ip);
00240 if(!server_socket)
00241 {
00242 Question question;
00243 question.Set(_("Unable to listen for client!"),1,0);
00244 question.Ask();
00245 printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
00246 return;
00247 }
00248 printf("\nStart listening");
00249 }
00250
00251 void Network::RejectIncoming()
00252 {
00253 assert(m_is_server);
00254 if(!server_socket) return;
00255 SDLNet_TCP_Close(server_socket);
00256 server_socket = NULL;
00257 printf("\nStop listening");
00258 }
00259
00260
00261
00262
00263 void Network::ReceiveActions()
00264 {
00265 char* packet;
00266
00267 while(m_is_connected && (cpu.size()==1 || m_is_server))
00268 {
00269 if(state == NETWORK_PLAYING && cpu.size() == 0)
00270 {
00271
00272 break;
00273 }
00274
00275 while(SDLNet_CheckSockets(socket_set, 100) == 0 && m_is_connected)
00276 if(m_is_server && server_socket)
00277 {
00278
00279 TCPsocket incoming;
00280 incoming = SDLNet_TCP_Accept(server_socket);
00281 if(incoming)
00282 {
00283 cpu.push_back(new DistantComputer(incoming));
00284 connected_player++;
00285 printf("New client connected\n");
00286 if(connected_player >= max_player_number)
00287 RejectIncoming();
00288 ActionHandler::GetInstance()->NewAction(new Action(Action::ACTION_ASK_VERSION));
00289 }
00290 }
00291
00292 std::list<DistantComputer*>::iterator dst_cpu = cpu.begin();
00293 while(dst_cpu != cpu.end() && m_is_connected)
00294 {
00295 if((*dst_cpu)->SocketReady())
00296 {
00297
00298 int packet_size = (*dst_cpu)->ReceiveDatas(packet);
00299 if( packet_size <= 0)
00300 {
00301 dst_cpu = CloseConnection(dst_cpu);
00302 continue;
00303 }
00304
00305 #if defined(DEBUG) && not defined(WIN32)
00306 int tmp = 0xFFFFFFFF;
00307 write(fin, &packet_size, 4);
00308 write(fin, packet, packet_size);
00309 write(fin, &tmp, 4);
00310 #endif
00311
00312 Action* a = new Action(packet);
00313 MSG_DEBUG("network.traffic","Received action %s",
00314 ActionHandler::GetInstance()->GetActionName(a->GetType()).c_str());
00315
00316
00317 if( a->GetType() == Action::ACTION_NICKNAME){
00318 std::string nickname = a->PopString();
00319 std::cout<<"New nickname: " + nickname<< std::endl;
00320 (*dst_cpu)->nickname = nickname;
00321 delete a;
00322 break;
00323 }
00324
00325 if( a->GetType() == Action::ACTION_NEW_TEAM
00326 || a->GetType() == Action::ACTION_DEL_TEAM)
00327 {
00328 (*dst_cpu)->ManageTeam(a);
00329 delete a;
00330 }
00331 else
00332 if(a->GetType() == Action::ACTION_CHAT_MESSAGE)
00333 {
00334 (*dst_cpu)->SendChatMessage(a);
00335 delete a;
00336 }
00337 else
00338 {
00339 ActionHandler::GetInstance()->NewAction(a, false);
00340 }
00341
00342
00343 if(a->GetType() != Action::ACTION_SEND_VERSION
00344 && a->GetType() != Action::ACTION_CHANGE_STATE
00345 && a->GetType() != Action::ACTION_CHAT_MESSAGE)
00346 for(std::list<DistantComputer*>::iterator client = cpu.begin();
00347 client != cpu.end();
00348 client++)
00349 if(client != dst_cpu)
00350 {
00351 (*client)->SendDatas(packet, packet_size);
00352 }
00353 free(packet);
00354 }
00355 dst_cpu++;
00356 }
00357 }
00358 Game::GetInstance()->SetEndOfGameStatus( true );
00359 }
00360
00361
00362 void Network::SendAction(Action* a)
00363 {
00364 if (!m_is_connected) return;
00365
00366 MSG_DEBUG("network.traffic","Send action %s",
00367 ActionHandler::GetInstance()->GetActionName(a->GetType()).c_str());
00368
00369 int size;
00370 char* packet;
00371 a->WritePacket(packet, size);
00372
00373 assert(*((int*)packet) != 0 );
00374 SendPacket(packet, size);
00375
00376 free(packet);
00377 }
00378
00379 void Network::SendPacket(char* packet, int size)
00380 {
00381 #if defined(DEBUG) && not defined(WIN32)
00382 int tmp = 0xFFFFFFFF;
00383 write(fout, &size, 4);
00384 write(fout, packet, size);
00385 write(fout, &tmp, 4);
00386 #endif
00387 for(std::list<DistantComputer*>::iterator client = cpu.begin();
00388 client != cpu.end();
00389 client++)
00390 {
00391 (*client)->SendDatas(packet, size);
00392 }
00393 }
00394
00395 void Network::SendChatMessage(std::string txt)
00396 {
00397 if(IsServer())
00398 {
00399 ActionHandler::GetInstance()->NewAction(new Action(Action::ACTION_CHAT_MESSAGE, nickname + std::string("> ") + txt));
00400 }
00401 else
00402 {
00403 Action a(Action::ACTION_CHAT_MESSAGE, txt);
00404 network.SendAction(&a);
00405 }
00406 }
00407
00408
00409
00410 const bool Network::IsConnected() const { return m_is_connected; }
00411 const bool Network::IsLocal() const { return !m_is_server && !m_is_client; }
00412 const bool Network::IsServer() const { return m_is_server; }
00413 const bool Network::IsClient() const { return m_is_client; }
00414 const uint Network::GetPort() const { return ntohs(ip.port); }
00415
00416