00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifdef WIN32
00016 #pragma warning (disable:4786)
00017 #endif
00018
00019 #include <API/Core/System/error.h>
00020 #include <API/Core/System/mutex.h>
00021 #include <API/Network/netcomputer.h>
00022 #include <API/Network/netgroup.h>
00023 #include <API/Network/netmessage.h>
00024 #include <API/Core/System/error.h>
00025 #include <API/Core/System/thread.h>
00026 #include <API/Core/System/cl_assert.h>
00027 #include <API/Core/System/system.h>
00028 #include <Network/Generic/network_delivery_impl.h>
00029 #include <Network/Generic/netsession_server.h>
00030 #include <Network/Generic/netsession_generic.h>
00031 #include <Network/Generic/network_generic.h>
00032 #include <Core/IOData/Generic/outputsource_memory_generic.h>
00033 #include <Core/IOData/Generic/inputsource_memory_generic.h>
00034
00035 CL_NetSession_Server::CL_NetSession_Server(
00036 CL_ConnectionProvider *provider,
00037 const char *game_id,
00038 int port)
00039 : CL_NetSession_Generic(provider)
00040 {
00041 mutex = CL_Mutex::create();
00042
00043 this->game_id = game_id;
00044 this->port = port;
00045
00046 id_counter = 1;
00047
00048 udp_connection = provider->create_udp_connection(port);
00049
00050 provider->start_accept_on_port(port);
00051
00052 exit_thread = false;
00053 thread = CL_Thread::create(this);
00054 thread->start();
00055 }
00056
00057 CL_NetSession_Server::~CL_NetSession_Server()
00058 {
00059 exit_thread = true;
00060 thread->wait();
00061 delete thread;
00062
00063 provider->stop_accept_on_port(port);
00064
00065
00066 {
00067 for (
00068 std::list<CL_NetComputer_Host*>::iterator it = prejoin.begin();
00069 it != prejoin.end();
00070 it++)
00071 {
00072 delete *it;
00073 }
00074 }
00075 {
00076 for (
00077 std::list<CL_NetComputer_Host*>::iterator it = computers.begin();
00078 it != computers.end();
00079 it++)
00080 {
00081 delete *it;
00082 }
00083 }
00084
00085 while (leave_queue.empty() == false)
00086 {
00087 delete leave_queue.front();
00088 leave_queue.pop();
00089 }
00090
00091 delete mutex;
00092 }
00093
00094 CL_NetComputer &CL_NetSession_Server::get_server()
00095 {
00096 static CL_NetComputer null_server;
00097 return null_server;
00098 }
00099
00100 CL_NetGroup &CL_NetSession_Server::get_all()
00101 {
00102 return all;
00103 }
00104
00105 bool CL_NetSession_Server::peek(int channel) const
00106 {
00107 CL_MutexSection mutex_section(mutex);
00108
00109 CL_NetChannelQueue *queue = find_queue(channel);
00110 if (queue != NULL) return !queue->empty();
00111
00112 return false;
00113 }
00114
00115 CL_NetMessage CL_NetSession_Server::receive(int channel, int timeout)
00116 {
00117 CL_MutexSection mutex_section(mutex);
00118
00119 CL_NetChannelQueue *queue = create_queue(channel);
00120
00121 while (queue->empty())
00122 {
00123 int s = timeout;
00124 if (timeout < 0 || timeout > 20) s = 20;
00125 mutex->leave();
00126 CL_System::sleep(s);
00127 mutex->enter();
00128
00129 if (timeout != -1)
00130 {
00131 timeout -= s;
00132 if (timeout <= 0) break;
00133 }
00134 }
00135
00136 if (queue->empty()) throw CL_Error("No message to receive.");
00137 CL_NetMessage msg = queue->front(); queue->pop();
00138 check_trigger();
00139 return msg;
00140 }
00141
00142 void CL_NetSession_Server::send(
00143 const int dest_channel,
00144 const CL_NetComputer &dest,
00145 const CL_NetMessage &message,
00146 bool reliable )
00147 {
00148 CL_MutexSection mutex_section(mutex);
00149
00150 static bool warning = true;
00151 if (warning && reliable == false)
00152 {
00153 cl_info(info_network, "cannot send data unreliable (udp): not implemented yet!");
00154 warning = false;
00155 }
00156
00157 CL_NetComputer_Host *dest_host = get_computer_host(dest);
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 CL_OutputSource_MemoryGeneric output;
00169 output.write_int32(Packet_NetChannel_Message_ToClient);
00170 output.write_int32(dest_channel);
00171 output.write_int32(message.data.size());
00172 output.write(message.data.data(), message.data.size());
00173
00174 CL_ConnectionPacket packet;
00175 packet.size = output.size();
00176 packet.data = output.get_data();
00177
00178 dest_host->connection->send(packet);
00179 }
00180
00181 void CL_NetSession_Server::send(
00182 const int dest_channel,
00183 const CL_NetGroup &dest,
00184 const CL_NetMessage &message,
00185 bool reliable )
00186 {
00187 CL_MutexSection mutex_section(mutex);
00188
00189 const std::list<CL_NetComputer> &computers = dest.get_computers();
00190 std::list<CL_NetComputer>::const_iterator it;
00191
00192 for (
00193 it = computers.begin();
00194 it != computers.end();
00195 it++)
00196 {
00197 send(
00198 dest_channel,
00199 *it,
00200 message,
00201 reliable);
00202 }
00203 }
00204
00205 CL_NetComputer CL_NetSession_Server::receive_computer_leave()
00206 {
00207 CL_MutexSection mutex_section(mutex);
00208
00209 if (leave_queue.empty()) return NULL;
00210
00211 CL_NetComputer ret = leave_queue.front();
00212 leave_queue.pop();
00213 check_trigger();
00214
00215
00216 for (
00217 std::map<int, CL_NetChannelQueue>::iterator it = netchannels.begin();
00218 it != netchannels.end();
00219 it++)
00220 {
00221 CL_NetChannelQueue &queue = (*it).second;
00222 queue.access.erase(get_computer_host(ret)->id);
00223 }
00224
00225 return ret;
00226 }
00227
00228 CL_NetComputer CL_NetSession_Server::receive_computer_join()
00229 {
00230 CL_MutexSection mutex_section(mutex);
00231
00232 if (join_queue.empty()) throw CL_Error("Computer join queue is empty.");
00233 CL_NetComputer ret(join_queue.front());
00234 join_queue.pop();
00235 check_trigger();
00236
00237 return ret;
00238 }
00239
00240 CL_NetComputer CL_NetSession_Server::receive_computer_rejoin()
00241 {
00242 CL_MutexSection mutex_section(mutex);
00243
00244 if (rejoin_queue.empty()) return NULL;
00245 CL_NetComputer ret(rejoin_queue.front());
00246 rejoin_queue.pop();
00247 check_trigger();
00248
00249 return ret;
00250 }
00251
00252 bool CL_NetSession_Server::receive_session_closed()
00253 {
00254 return false;
00255 }
00256
00257 int CL_NetSession_Server::access_status(int ) const
00258 {
00259
00260 return ACCESS_CHANNEL_READ|ACCESS_CHANNEL_WRITE;
00261 }
00262
00263 bool CL_NetSession_Server::is_writable(int ) const
00264 {
00265 return true;
00266 }
00267
00268 bool CL_NetSession_Server::is_readable(int ) const
00269 {
00270 return true;
00271 }
00272
00273
00274 int CL_NetSession_Server::receive_access_changed()
00275 {
00276 return -1;
00277 }
00278
00279
00280 void CL_NetSession_Server::set_access(
00281 int channel,
00282 const CL_NetComputer &computer,
00283 int access_rights)
00284 {
00285 CL_MutexSection mutex_section(mutex);
00286
00287 CL_NetComputer_Host *computer_host = get_computer_host(computer);
00288 CL_NetChannelQueue *queue = create_queue(channel);
00289
00290 int cur_access = 0;
00291 std::map<int,int>::iterator access_it = queue->access.find(computer_host->id);
00292 if (access_it != queue->access.end())
00293 {
00294 cur_access = (*access_it).second;
00295 (*access_it).second = access_rights;
00296 }
00297 else
00298 {
00299 queue->access.insert(std::pair<int,int>(computer_host->id, access_rights));
00300 }
00301
00302 if (cur_access != access_rights)
00303 {
00304 CL_OutputSource_MemoryGeneric output;
00305 output.write_int32(Packet_NetChannel_AccessChange);
00306 output.write_int32(channel);
00307 output.write_int32(access_rights);
00308
00309 CL_ConnectionPacket packet;
00310 packet.size = output.size();
00311 packet.data = output.get_data();
00312
00313 computer_host->connection->send(packet);
00314 }
00315 }
00316
00317 void CL_NetSession_Server::set_access(
00318 int channel,
00319 const CL_NetGroup &group,
00320 int access_rights)
00321 {
00322 CL_MutexSection mutex_section(mutex);
00323
00324 for (
00325 std::list<CL_NetComputer>::const_iterator it = group.get_computers().begin();
00326 it != group.get_computers().end();
00327 it++)
00328 {
00329 set_access(
00330 channel,
00331 *it,
00332 access_rights);
00333 }
00334 }
00335
00336 void CL_NetSession_Server::keep_alive()
00337 {
00338 CL_MutexSection mutex_section(mutex);
00339
00340 if (exit_thread) return;
00341
00342
00343 std::list<CL_NetComputer_Host*>::iterator it_computers = computers.begin();
00344 while (it_computers != computers.end())
00345 {
00346 while ((*it_computers)->connection->peek())
00347 {
00348 CL_ConnectionPacket msg = (*it_computers)->connection->receive();
00349
00350 CL_InputSource_MemoryGeneric input(msg.data, msg.size, true);
00351 switch (input.read_int32())
00352 {
00353 case Packet_NetChannel_AccessChange:
00354 cl_info(info_network, "Network Protocol error!");
00355 cl_assert(false);
00356 break;
00357
00358 case Packet_NetChannel_Message_ToServer:
00359 {
00360 static bool warning = true;
00361 if (warning)
00362 {
00363 cl_info(info_network, "permissions not checked: Not implemented yet.");
00364 warning = false;
00365 }
00366 CL_NetChannelQueue *queue = create_queue(input.read_int32());
00367 CL_NetMessage game_msg;
00368 int size = input.read_int32();
00369 char *data = new char[size];
00370 game_msg.from = *it_computers;
00371 input.read(data, size);
00372 game_msg.data.append(data, size);
00373 queue->push(game_msg);
00374 trigger.set_flag();
00375 }
00376 break;
00377
00378 default:
00379 cl_info(info_network, "Network Protocol error!");
00380 cl_assert(false);
00381 }
00382 }
00383
00384 if ((*it_computers)->connection->connection_lost())
00385 {
00386 leave_queue.push(*it_computers);
00387 all.remove(CL_NetComputer(*it_computers));
00388 provider->remove_connection((*it_computers)->connection);
00389 it_computers = computers.erase(it_computers);
00390
00391 trigger.set_flag();
00392 }
00393 else
00394 {
00395 it_computers++;
00396 }
00397 }
00398
00399
00400
00401 std::list<CL_NetComputer_Host*>::iterator it_prejoin = prejoin.begin();
00402 while (it_prejoin != prejoin.end())
00403 {
00404 if ((*it_prejoin)->connection->connection_lost())
00405 {
00406 delete *it_prejoin;
00407 it_prejoin = prejoin.erase(it_prejoin);
00408
00409 continue;
00410 }
00411
00412 if ((*it_prejoin)->connection->peek())
00413 {
00414 CL_ConnectionPacket msg = (*it_prejoin)->connection->receive();
00415
00416 CL_InputSource_MemoryGeneric input(msg.data, msg.size);
00417 if (msg.size >= (int) sizeof(int))
00418 {
00419 switch (input.read_int32())
00420 {
00421 case Packet_Hello_ToYouToo:
00422 computers.push_back(*it_prejoin);
00423 all.add(CL_NetComputer(*it_prejoin));
00424 join_queue.push(*it_prejoin);
00425 it_prejoin = prejoin.erase(it_prejoin);
00426 trigger.set_flag();
00427 continue;
00428
00429 default:
00430 cl_info(info_network, "Network Protocol error!");
00431 cl_assert(false);
00432 }
00433 }
00434
00435 delete[] ((char*) msg.data);
00436 }
00437
00438 it_prejoin++;
00439 }
00440
00441
00442 while (true)
00443 {
00444 CL_Connection *new_client = provider->accept();
00445 if (new_client == NULL) break;
00446
00447 CL_OutputSource_MemoryGeneric msg;
00448 msg.write_int32(Packet_Hello);
00449 msg.write_int32(id_counter);
00450 msg.write_int32(game_id.length());
00451 msg.write(game_id.c_str(), game_id.length());
00452
00453 CL_ConnectionPacket packet(msg.get_data(), msg.size());
00454 new_client->send(packet);
00455
00456 prejoin.push_back(new CL_NetComputer_Host(this, new_client, id_counter++));
00457 }
00458
00459
00460 while (udp_connection->peek())
00461 {
00462 CL_UDPConnectionPacket netmsg = udp_connection->receive();
00463
00464 try
00465 {
00466 CL_InputSource_MemoryGeneric message(netmsg.data, netmsg.size);
00467
00468 int msgtype = message.read_int32();
00469 switch (msgtype)
00470 {
00471 case 0:
00472 {
00473 std::string req_game_id = message.read_string();
00474 if (req_game_id == game_id)
00475 {
00476 CL_OutputSource_MemoryGeneric msg;
00477 msg.write_int32(1);
00478 msg.write_string(game_id.c_str());
00479
00480 CL_UDPConnectionPacket reply;
00481 reply.data = msg.get_data();
00482 reply.size = msg.size();
00483 reply.ip_addr = netmsg.ip_addr;
00484 reply.port = netmsg.port;
00485 udp_connection->send(reply);
00486 }
00487 }
00488 break;
00489
00490 case 1:
00491
00492 break;
00493
00494 case 2:
00495
00496 break;
00497 }
00498 }
00499 catch (CL_Error err)
00500 {
00501
00502 }
00503 }
00504 }
00505
00506 void CL_NetSession_Server::run()
00507 {
00508 while (exit_thread == false)
00509 {
00510 keep_alive();
00511 provider->wait_for_connection_data(mutex);
00512 }
00513 }
00514
00515 CL_NetChannelQueue *CL_NetSession_Server::find_queue(int netchannel) const
00516 {
00517 std::map<int, CL_NetChannelQueue>::const_iterator it = netchannels.find(netchannel);
00518 if (it == netchannels.end()) return NULL;
00519
00520 return (CL_NetChannelQueue *) (&(*it).second);
00521 }
00522
00523 CL_NetChannelQueue *CL_NetSession_Server::create_queue(int netchannel)
00524 {
00525 CL_NetChannelQueue *found = find_queue(netchannel);
00526 if (found != NULL) return found;
00527
00528 CL_NetChannelQueue c;
00529 netchannels.insert(std::pair<int, CL_NetChannelQueue>(netchannel, c));
00530
00531 return &netchannels[netchannel];
00532 }
00533
00534 bool CL_NetSession_Server::has_read_access(
00535 CL_NetChannelQueue *channel,
00536 CL_NetComputer_Host *host)
00537 {
00538 std::map<int, int>::iterator it = channel->access.find(host->id);
00539 if (it == channel->access.end()) return false;
00540
00541 return ((*it).second & ACCESS_CHANNEL_READ) == ACCESS_CHANNEL_READ;
00542 }
00543
00544 void CL_NetSession_Server::check_trigger()
00545 {
00546 bool queues_empty =
00547 join_queue.empty() &&
00548 rejoin_queue.empty() &&
00549 leave_queue.empty();
00550
00551 std::map<int,CL_NetChannelQueue>::iterator it;
00552 for (it = netchannels.begin(); it != netchannels.end(); it++)
00553 {
00554 if (!it->second.empty()) queues_empty = false;
00555 }
00556
00557 if (queues_empty) trigger.reset();
00558 }
00559
00560
00561
00562 CL_NetComputer_Host::CL_NetComputer_Host(
00563 CL_NetSession_Server *session,
00564 CL_Connection *connection,
00565 int id)
00566 :
00567 CL_NetComputer_Generic(session)
00568 {
00569 this->connection = connection;
00570 this->id = id;
00571 }
00572
00573 CL_NetComputer_Host::~CL_NetComputer_Host()
00574 {
00575 delete connection;
00576 }
00577
00578 unsigned long CL_NetComputer_Host::get_address() const
00579 {
00580
00581 return 0;
00582 }
00583
00584 void CL_NetComputer_Host::disconnect()
00585 {
00586
00587 }