00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00043 #include "omicron/internal.h"
00044
00045
00046 #include "omicron/net.h"
00047 #include "omicron/array.h"
00048 #include "omicron/list.h"
00049
00050
00051
00052
00053
00054
00055
00056 net_client_c::net_client_c()
00057 {
00058 _log_printf(MSG_DEBUG, "net_client_c()");
00059
00060 sock = INVALID_SOCKET;
00061
00062
00063 queue = new list_c<char>;
00064 queuelen = 0;
00065 }
00066
00067 net_client_c::~net_client_c()
00068 {
00069 AssertThis;
00070
00071
00072 char *buf = (char*)queue->get_first();
00073
00074 while(buf)
00075 {
00076 SafeDelete(buf);
00077 buf = (char*)queue->get_next();
00078 }
00079
00080 SafeDelete(queue);
00081
00082
00083 shutdown(sock, 0);
00084 closesocket(sock);
00085 }
00086
00087 void net_client_c::send_message(net_message_header_t *msg, bool )
00088 {
00089 AssertThis;
00090 AssertReturn3(gv.netman, msg, queue);
00091
00092 if (sock == INVALID_SOCKET)
00093 return;
00094
00095 _log_printf(MSG_DEBUG, "SV: send_message: %u %u", msg->type, msg->len);
00096
00097 fd_set fd;
00098 TIMEVAL tv;
00099
00100 tv.tv_sec = 0;
00101 tv.tv_usec = 0;
00102
00103 FD_ZERO(&fd);
00104 FD_SET(sock, &fd);
00105 if (select(1, NULL, &fd, NULL, &tv))
00106 {
00107
00108
00109 char *buf = (char*)queue->get_first();
00110
00111 while(buf)
00112 {
00113 _log_printf(MSG_DEBUG, "SV: sending queued message");
00114
00115 int res = send(sock, buf, ((net_message_header_t*)buf)->len, 0);
00116
00117 if (res == SOCKET_ERROR)
00118 {
00119 status = NETSTAT_DISCONNECTED;
00120 _log_printf(MSG_DEBUG, "SV: network error");
00121 return;
00122 }
00123
00124 queuelen --;
00125 queue->remove(buf);
00126 SafeArrayDelete(buf);
00127 buf = (char*)queue->get_first();
00128 }
00129
00130
00131 int res = send(sock, (char*)msg, msg->len, 0);
00132 if (res == SOCKET_ERROR)
00133 {
00134 status = NETSTAT_DISCONNECTED;
00135 _log_printf(MSG_DEBUG, "SV: network error");
00136 return;
00137 }
00138 _log_printf(MSG_DEBUG, "SV: message sent");
00139 }
00140 else
00141 {
00142 _log_printf(MSG_DEBUG, "SV: message added to queue");
00143
00144 char *buf = new char[msg->len];
00145
00146 memcpy(buf, msg, msg->len);
00147 queue->append(buf);
00148 queuelen++;
00149 }
00150 }
00151
00152 void net_client_c::receive_message()
00153 {
00154 AssertThis;
00155 AssertReturn1(gv.netman);
00156
00157 if (sock == INVALID_SOCKET)
00158 return;
00159
00160
00161
00162 fd_set fd;
00163 TIMEVAL tv;
00164
00165 tv.tv_sec = 0;
00166 tv.tv_usec = 0;
00167
00168 FD_ZERO(&fd);
00169 FD_SET(sock, &fd);
00170 while(select(1, &fd, NULL, NULL, &tv))
00171 {
00172 net_message_header_t header;
00173
00174 int res = recv(sock, (char*)&header, sizeof(header), 0);
00175
00176 if (res == SOCKET_ERROR || !res)
00177 {
00178 status = NETSTAT_DISCONNECTED;
00179 return;
00180 }
00181
00182 char *buf = new char[header.len];
00183 memcpy(buf, &header, sizeof(header));
00184
00185 recv(sock, buf+sizeof(header), header.len-sizeof(header), 0);
00186
00187 _log_printf(MSG_DEBUG, "SV: message received from client: %u %u", header.type, header.len);
00188
00189 switch(header.type)
00190 {
00191 case NETMSG_PONG:
00192 {
00193
00194 latency = gv.netman->sv_gametime - header.time;
00195 }
00196 break;
00197
00198 default:
00199
00200
00201 break;
00202 }
00203
00204 SafeArrayDelete(buf);
00205 FD_ZERO(&fd);
00206 FD_SET(sock, &fd);
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 net_manager_c::net_manager_c()
00217 {
00218 _log_printf(MSG_DEBUG, "net_manager_c()");
00219
00220 SafeDelete(gv.netman);
00221
00222 gv.netman = this;
00223
00224 sv_lastupdate = _time_get();
00225 sv_gametime =
00226 cl_lastupdate = sv_lastupdate;
00227
00228 clients = new array_c<net_client_c>;
00229
00230 isserver = false;
00231 isclient = false;
00232
00233 cl_socket = INVALID_SOCKET;
00234
00235
00236 sv_socket = INVALID_SOCKET;
00237
00238
00239 cl_queue = new list_c<char>;
00240 cl_queuelen = 0;
00241
00242 #if defined(WIN32)
00243 WSAStartup(MAKEWORD(2,0), &wsadata);
00244 #endif
00245 }
00246
00247 net_manager_c::~net_manager_c()
00248 {
00249 AssertThis;
00250
00251 _log_printf(MSG_DEBUG, "~net_manager_c()");
00252
00253 for (slong i=0; i<clients->get_count(); i++)
00254 {
00255 net_client_c *cl = clients->get(i);
00256 SafeDelete(cl);
00257 }
00258 SafeDelete(clients);
00259
00260
00261 char *buf = cl_queue->get_first();
00262
00263 while(buf)
00264 {
00265 SafeArrayDelete(buf);
00266 buf = cl_queue->get_next();
00267 }
00268 SafeDelete(cl_queue);
00269
00270 gv.netman = NULL;
00271
00272 #if defined(WIN32)
00273 WSACleanup();
00274 #endif
00275 }
00276
00277
00278
00279 void net_manager_c::start_listen(ushort port, bool local)
00280 {
00281 SOCKADDR_IN laddress;
00282 int addrsize = sizeof(SOCKADDR_IN);
00283
00284 stop_listen();
00285
00286 sv_socket = socket( PF_INET, SOCK_STREAM, 0 );
00287
00288
00289 laddress.sin_family = AF_INET;
00290 laddress.sin_port = htons( port );
00291 laddress.sin_addr.s_addr = local?inet_addr("127.0.0.1"):INADDR_ANY;
00292
00293 if (bind(sv_socket, (struct sockaddr*)&laddress, addrsize))
00294 {
00295 _log_printf(MSG_DEBUG, "SV: failed to bind tcp socket");
00296 return;
00297 }
00298
00299 if (listen(sv_socket, 1))
00300 {
00301 _log_printf(MSG_DEBUG, "SV: failed to listen on port %u", port);
00302 return;
00303 }
00304
00305 _log_printf(MSG_DEBUG, "SV: tcp now listening on port %u", port);
00306
00307 isserver = true;
00308 }
00309
00310 void net_manager_c::stop_listen()
00311 {
00312 AssertThis;
00313
00314 if (sv_socket != INVALID_SOCKET)
00315 {
00316 _log_printf(MSG_DEBUG, "SV: no longer listening");
00317
00318 shutdown(sv_socket, 0);
00319 closesocket(sv_socket);
00320 }
00321 sv_socket = INVALID_SOCKET;
00322
00323 isserver = false;
00324 }
00325
00326
00327
00328 void net_manager_c::update()
00329 {
00330 AssertThis;
00331
00332 sv_gametime = _time_get();
00333
00334
00335
00336
00337
00338 if (isserver && sv_gametime>=sv_lastupdate+frametime)
00339 {
00340 net_message_ping_t pingmsg;
00341 pingmsg.header.type = NETMSG_PING;
00342 pingmsg.header.len = sizeof(net_message_ping_t);
00343 pingmsg.header.time = sv_gametime;
00344
00345 broadcast(&pingmsg.header);
00346
00347 sv_lastupdate = sv_gametime;
00348 }
00349
00350 if (isserver)
00351 {
00352 fd_set fd;
00353 TIMEVAL tv;
00354
00355 tv.tv_sec = 0;
00356 tv.tv_usec = 0;
00357
00358 FD_ZERO(&fd);
00359 FD_SET(sv_socket, &fd);
00360
00361
00362 if (select(1, &fd, NULL, NULL, &tv))
00363 {
00364 socklen_t addrsize = sizeof(SOCKADDR_IN);
00365 SOCKADDR_IN laddress;
00366
00367 SOCKET sock =
00368 accept(sv_socket, (struct sockaddr*)&laddress, &addrsize);
00369
00370 net_client_c *cl = new net_client_c;
00371
00372 cl->laddress = laddress;
00373 cl->sock = sock;
00374 cl->status = NETSTAT_CONNECTED;
00375
00376 cl->id = clients->add(cl);
00377
00378 _log_printf(MSG_DEBUG, "server: new connection");
00379
00380
00381
00382 }
00383
00384
00385 for (slong i=0; i<clients->get_count(); i++)
00386 {
00387 net_client_c *cl = clients->get(i);
00388 if (cl)
00389 cl->receive_message();
00390 }
00391 }
00392
00393
00394
00395 for (slong i=0; i<clients->get_count(); i++)
00396 {
00397 net_client_c *cl = clients->get(i);
00398
00399 if (cl)
00400 {
00401 if (cl->status == NETSTAT_DISCONNECTED)
00402 {
00403
00404
00405
00406 clients->remove_ptr(cl);
00407 SafeDelete(cl);
00408 }
00409 }
00410 }
00411
00412
00413
00414
00415
00416 if (isclient)
00417 {
00418 fd_set fd;
00419 TIMEVAL tv;
00420
00421 tv.tv_sec = 0;
00422 tv.tv_usec = 0;
00423
00424 FD_ZERO(&fd);
00425 FD_SET(cl_socket, &fd);
00426 while(select(1, &fd, NULL, NULL, &tv))
00427 {
00428 net_message_header_t header;
00429
00430 int res = recv(cl_socket, (char*)&header, sizeof(header), 0);
00431
00432 if (res == SOCKET_ERROR || !res)
00433 {
00434 disconnect_from_server();
00435 return;
00436 }
00437
00438 char *buf = new char[header.len];
00439 memcpy(buf, &header, sizeof(header));
00440
00441 recv(cl_socket, buf+sizeof(header), header.len-sizeof(header), 0);
00442
00443 cl_receivemessage(&header);
00444
00445 SafeArrayDelete(buf);
00446 FD_ZERO(&fd);
00447 FD_SET(cl_socket, &fd);
00448 }
00449
00450 }
00451
00452
00453
00454 }
00455
00456
00457
00458 void net_manager_c::broadcast(net_message_header_t *msg)
00459 {
00460 AssertThis;
00461
00462 AssertReturn1(msg);
00463
00464 for (slong i=0; i<clients->get_count(); i++)
00465 {
00466 net_client_c *cl = clients->get(i);
00467
00468 if (cl)
00469 {
00470 cl->send_message(msg);
00471 }
00472 }
00473 }
00474
00475 void net_manager_c::unicast(ulong clnum, net_message_header_t *msg)
00476 {
00477 AssertThis;
00478 AssertReturn1(msg);
00479
00480 net_client_c *cl = clients->get(clnum);
00481
00482 AssertReturn1(cl);
00483
00484 cl->send_message(msg);
00485 }
00486
00487
00488
00489 bool net_manager_c::connect_to_server(char *name, ushort port)
00490 {
00491 AssertThisV;
00492 AssertReturnValue1(name, false);
00493
00494 disconnect_from_server();
00495
00496 SOCKADDR_IN laddress;
00497 int addrsize = sizeof(SOCKADDR_IN);
00498 HOSTENT *he;
00499
00500 he = gethostbyname( name );
00501
00502 AssertReturnValue1(he, false);
00503
00504 _log_printf(MSG_DEBUG, "client: connecting to server %s:%u", name, port);
00505
00506 cl_socket = socket( PF_INET, SOCK_STREAM, 0 );
00507
00508
00509 laddress.sin_family = AF_INET;
00510 laddress.sin_port = htons( port );
00511
00512 memcpy( &laddress.sin_addr.s_addr,
00513 he->h_addr_list[0], 4 );
00514
00515 int res = connect(cl_socket, (sockaddr*)&laddress, addrsize);
00516
00517 if (res)
00518 {
00519 _log_printf(MSG_DEBUG, "client: could not connect to server");
00520 disconnect_from_server();
00521 return false;
00522 }
00523
00524 cl_connecttime = _time_get();
00525
00526 isclient = true;
00527
00528 return true;
00529 }
00530
00531 void net_manager_c::disconnect_from_server()
00532 {
00533 AssertThis;
00534
00535 _log_printf(MSG_DEBUG, "CL: disconnecting from server");
00536
00537 isclient = false;
00538
00539 if (cl_socket!=INVALID_SOCKET)
00540 {
00541 shutdown(cl_socket, 0);
00542 closesocket(cl_socket);
00543 cl_socket = INVALID_SOCKET;
00544 }
00545 }
00546
00547 void net_manager_c::cl_sendmessage(net_message_header_t *msg)
00548 {
00549 AssertThis;
00550
00551 AssertReturn1(msg);
00552
00553 if (cl_socket == INVALID_SOCKET)
00554 return;
00555
00556 _log_printf(MSG_DEBUG, "CL: send_message: %u %u", msg->type, msg->len);
00557
00558 fd_set fd;
00559 TIMEVAL tv;
00560
00561 tv.tv_sec = 0;
00562 tv.tv_usec = 0;
00563
00564 FD_ZERO(&fd);
00565 FD_SET(cl_socket, &fd);
00566 if (select(1, NULL, &fd, NULL, &tv))
00567 {
00568
00569
00570 char *buf = (char*)cl_queue->get_first();
00571
00572 while(buf)
00573 {
00574 _log_printf(MSG_DEBUG, "CL: sending queued message");
00575
00576 int res = send(cl_socket, buf, ((net_message_header_t*)buf)->len, 0);
00577
00578 if (res == SOCKET_ERROR)
00579 {
00580 _log_printf(MSG_DEBUG, "CL: network error");
00581 disconnect_from_server();
00582 return;
00583 }
00584
00585 cl_queue->remove(buf);
00586 SafeArrayDelete(buf);
00587 buf = (char*)cl_queue->get_first();
00588
00589 cl_queuelen--;
00590 }
00591
00592
00593 int res = send(cl_socket, (char*)msg, msg->len, 0);
00594 if (res == SOCKET_ERROR)
00595 {
00596 _log_printf(MSG_DEBUG, "CL: network error");
00597 disconnect_from_server();
00598 return;
00599 }
00600 _log_printf(MSG_DEBUG, "CL: message sent");
00601 }
00602 else
00603 {
00604 _log_printf(MSG_DEBUG, "CL: message added to queue");
00605
00606 char *buf = new char[msg->len];
00607
00608 memcpy(buf, msg, msg->len);
00609 cl_queue->append(buf);
00610 cl_queuelen++;
00611 }
00612 }
00613
00614 void net_manager_c::cl_receivemessage(net_message_header_t *msg)
00615 {
00616 AssertThis;
00617 AssertReturn1(msg);
00618
00619 _log_printf(MSG_DEBUG, "client: message received from server: %u %u", msg->type, msg->len);
00620
00621 switch(msg->type)
00622 {
00623 case NETMSG_PING:
00624 {
00625 msg->type = NETMSG_PONG;
00626 cl_sendmessage(msg);
00627 }
00628 break;
00629
00630 default:
00631
00632 ;
00633 }
00634 }