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_client.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_Client::CL_NetSession_Client(
00036 int ip_addr,
00037 int port,
00038 const std::string &game_id,
00039 CL_ConnectionProvider *provider)
00040 : CL_NetSession_Generic(provider)
00041 {
00042 mutex = CL_Mutex::create();
00043
00044 tcp_connection = provider->create_tcp_connection(
00045 ip_addr,
00046 port);
00047
00048 if (tcp_connection == NULL)
00049 {
00050 throw CL_Error("Could not connect to host.");
00051 }
00052
00053 udp_connection = NULL;
00054
00055
00056 server = CL_NetComputer(new CL_NetComputer_Server(this));
00057 all.add(server);
00058
00059
00060 CL_ConnectionPacket p = tcp_connection->receive();
00061 while (p.size == 0)
00062 {
00063 provider->wait_for_connection_data(mutex);
00064 p = tcp_connection->receive();
00065 }
00066
00067 CL_InputSource_MemoryGeneric input(p.data, p.size, true);
00068 if (input.read_int32() != Packet_Hello)
00069 {
00070 throw CL_Error("Protocol error. Didn't get a Hello.");
00071 }
00072 our_id = input.read_int32();
00073
00074 int size = input.read_int32();
00075 if (size > 1000)
00076 throw CL_Error("Protocol error. Game ID size above 1000.");
00077
00078 char *str = new char[size+1];
00079 str[size] = 0;
00080 input.read(str, size);
00081
00082 if (game_id != str)
00083 {
00084 delete[] str;
00085 throw CL_Error("Wrong netsession id.");
00086 }
00087
00088 delete[] str;
00089
00090
00091 CL_OutputSource_MemoryGeneric output;
00092 output.write_int32(Packet_Hello_ToYouToo);
00093 tcp_connection->send(
00094 CL_ConnectionPacket(
00095 output.get_data(),
00096 output.size()));
00097
00098 exit_thread = false;
00099 thread = CL_Thread::create(this);
00100 thread->start();
00101 }
00102
00103 CL_NetSession_Client::~CL_NetSession_Client()
00104 {
00105 exit_thread = true;
00106 thread->wait();
00107 delete thread;
00108
00109 delete tcp_connection;
00110 delete udp_connection;
00111
00112
00113 for (
00114 std::list<CL_NetChannelQueue_Client*>::iterator it = netchannels.begin();
00115 it != netchannels.end();
00116 it++)
00117 {
00118 delete *it;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 delete mutex;
00130 }
00131
00132 CL_NetComputer &CL_NetSession_Client::get_server()
00133 {
00134 return server;
00135 }
00136
00137 CL_NetGroup &CL_NetSession_Client::get_all()
00138 {
00139 return all;
00140 }
00141
00142 bool CL_NetSession_Client::peek(int channel) const
00143 {
00144 CL_MutexSection mutex_section(mutex);
00145
00146 CL_NetChannelQueue_Client *queue = find_queue(channel);
00147 if (queue != NULL)
00148 {
00149 return !queue->empty();
00150 }
00151
00152 return false;
00153 }
00154
00155 CL_NetMessage CL_NetSession_Client::receive(int channel, int timeout)
00156 {
00157 CL_MutexSection mutex_section(mutex);
00158
00159 CL_NetChannelQueue_Client *queue = create_queue(channel);
00160
00161 while (queue->empty())
00162 {
00163 int s = timeout;
00164 if (timeout < 0 || timeout > 20) s = 20;
00165 mutex->leave();
00166 CL_System::sleep(s);
00167 mutex->enter();
00168
00169 if (timeout != -1)
00170 {
00171 timeout -= s;
00172 if (timeout <= 0) break;
00173 }
00174 }
00175
00176 if (queue->empty()) throw CL_Error("No message to receive!");
00177 CL_NetMessage msg = queue->front(); queue->pop();
00178 check_trigger();
00179 return msg;
00180 }
00181
00182 void CL_NetSession_Client::send(
00183 const int dest_channel,
00184 const CL_NetGroup &dest,
00185 const CL_NetMessage &message,
00186 bool reliable )
00187 {
00188 CL_MutexSection mutex_section(mutex);
00189
00190 static bool warning = true;
00191 if (warning && reliable == false)
00192 {
00193 cl_info(info_network, "cannot send data unreliable (udp): not implemented yet!");
00194 warning = false;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 CL_OutputSource_MemoryGeneric output;
00207 output.write_int32(Packet_NetChannel_Message_ToServer);
00208 output.write_int32(dest_channel);
00209
00210
00211
00212 output.write_int32(message.data.size());
00213 output.write(message.data.data(), message.data.size());
00214
00215 CL_ConnectionPacket packet;
00216 packet.size = output.size();
00217 packet.data = output.get_data();
00218
00219 tcp_connection->send(packet);
00220 }
00221
00222 CL_NetComputer CL_NetSession_Client::receive_computer_leave()
00223 {
00224 throw CL_Error("Computer leave queue empty.");
00225 }
00226
00227 CL_NetComputer CL_NetSession_Client::receive_computer_join()
00228 {
00229 throw CL_Error("Computer join queue empty.");
00230 }
00231
00232 CL_NetComputer CL_NetSession_Client::receive_computer_rejoin()
00233 {
00234 throw CL_Error("Computer rejoin queue empty.");
00235 }
00236
00237 bool CL_NetSession_Client::receive_session_closed()
00238 {
00239 CL_MutexSection mutex_section(mutex);
00240 return tcp_connection->connection_lost();
00241 }
00242
00243 int CL_NetSession_Client::access_status(int channel) const
00244 {
00245 CL_MutexSection mutex_section(mutex);
00246
00247 CL_NetChannelQueue_Client *queue = find_queue(channel);
00248 return (queue == NULL) ? 0 : queue->access;
00249 }
00250
00251 bool CL_NetSession_Client::is_writable(int channel) const
00252 {
00253 CL_MutexSection mutex_section(mutex);
00254
00255 CL_NetChannelQueue_Client *queue = find_queue(channel);
00256 if (queue == NULL) return false;
00257
00258 return (queue->access & ACCESS_CHANNEL_WRITE) == ACCESS_CHANNEL_WRITE;
00259 }
00260
00261 bool CL_NetSession_Client::is_readable(int channel) const
00262 {
00263 CL_MutexSection mutex_section(mutex);
00264
00265 CL_NetChannelQueue_Client *queue = find_queue(channel);
00266 if (queue == NULL) return false;
00267
00268 return (queue->access & ACCESS_CHANNEL_READ) == ACCESS_CHANNEL_READ;
00269 }
00270
00271
00272 int CL_NetSession_Client::receive_access_changed()
00273 {
00274 CL_MutexSection mutex_section(mutex);
00275
00276 if (access_queue.empty()) return -1;
00277 int id = access_queue.front()->channel_id;
00278 access_queue.pop();
00279 check_trigger();
00280 return id;
00281 }
00282
00283
00284 void CL_NetSession_Client::set_access(
00285 int channel,
00286 const CL_NetComputer &computer,
00287 int access_rights)
00288 {
00289 throw CL_Error("We are not the network server. Cannot change access.");
00290 }
00291
00292 void CL_NetSession_Client::set_access(
00293 int channel,
00294 const CL_NetGroup &group,
00295 int access_rights)
00296 {
00297 throw CL_Error("We are not the network server. Cannot change access.");
00298 }
00299
00300 void CL_NetSession_Client::keep_alive()
00301 {
00302 CL_MutexSection mutex_section(mutex);
00303
00304 if (tcp_connection->connection_lost())
00305 {
00306 provider->remove_connection(tcp_connection);
00307 return;
00308 }
00309
00310 while (tcp_connection->peek())
00311 {
00312 if (exit_thread) return;
00313
00314 CL_ConnectionPacket msg = tcp_connection->receive();
00315
00316 CL_InputSource_MemoryGeneric input(msg.data, msg.size, true);
00317 switch (input.read_int32())
00318 {
00319 case Packet_NetChannel_AccessChange:
00320 {
00321 CL_NetChannelQueue_Client *queue = create_queue(input.read_int32());
00322 queue->access = input.read_int32();
00323 access_queue.push(queue);
00324 trigger.set_flag();
00325 }
00326 break;
00327
00328 case Packet_NetChannel_Message_ToClient:
00329 {
00330 CL_NetChannelQueue_Client *queue = create_queue(input.read_int32());
00331 CL_NetMessage game_msg;
00332 int size = input.read_int32();
00333 char *data = new char[size];
00334 game_msg.from = server;
00335 input.read(data, size);
00336 game_msg.data.append(data, size);
00337 queue->push(game_msg);
00338 trigger.set_flag();
00339 }
00340 break;
00341
00342 default:
00343 cl_info(info_network, "Network Protocol error!");
00344 cl_assert(false);
00345 }
00346 }
00347 }
00348
00349 CL_NetChannelQueue_Client *CL_NetSession_Client::find_queue(int netchannel) const
00350 {
00351 CL_MutexSection mutex_section(mutex);
00352
00353
00354 for (
00355 std::list<CL_NetChannelQueue_Client*>::const_iterator it = netchannels.begin();
00356 it != netchannels.end();
00357 it++)
00358 {
00359 if ((*it)->channel_id == netchannel) return *it;
00360 }
00361
00362 return NULL;
00363 }
00364
00365 CL_NetChannelQueue_Client *CL_NetSession_Client::create_queue(int netchannel)
00366 {
00367 CL_MutexSection mutex_section(mutex);
00368
00369 CL_NetChannelQueue_Client *found = find_queue(netchannel);
00370 if (found != NULL) return found;
00371
00372 CL_NetChannelQueue_Client *c = new CL_NetChannelQueue_Client;
00373 c->channel_id = netchannel;
00374 c->access = 0;
00375
00376 netchannels.push_back(c);
00377
00378 return c;
00379 }
00380
00381 void CL_NetSession_Client::run()
00382 {
00383 while (exit_thread == false)
00384 {
00385 keep_alive();
00386 provider->wait_for_connection_data(mutex);
00387 }
00388 }
00389
00390 void CL_NetSession_Client::check_trigger()
00391 {
00392 bool queues_empty = access_queue.empty();
00393
00394 std::list<CL_NetChannelQueue_Client*>::iterator it;
00395 for (it = netchannels.begin(); it != netchannels.end(); it++)
00396 {
00397 if (!(*it)->empty()) queues_empty = false;
00398 }
00399
00400 if (queues_empty) trigger.reset();
00401 }
00402
00404
00405
00406 CL_NetComputer_Server::CL_NetComputer_Server(CL_NetSession_Client *session)
00407 : CL_NetComputer_Generic(session)
00408 {
00409 }
00410
00411 CL_NetComputer_Server::~CL_NetComputer_Server()
00412 {
00413 }
00414
00415 unsigned long CL_NetComputer_Server::get_address() const
00416 {
00417
00418 return 0;
00419 }
00420
00421 void CL_NetComputer_Server::disconnect()
00422 {
00423
00424 }
00425
00426 CL_NetSession_Client *CL_NetComputer_Server::get_session()
00427 {
00428 return static_cast<CL_NetSession_Client*>(CL_NetComputer_Generic::get_session());
00429 }