Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

o_net.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/13 12:29:26 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: o_net.cpp,v 1.2 2002/12/13 12:29:26 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: o_net.cpp,v $
00030   Revision 1.2  2002/12/13 12:29:26  kolrabi
00031   fixed some bugs
00032 
00033   Revision 1.1.1.1  2002/12/07 19:02:06  kolrabi
00034   initial release
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  * CLIENT ******************************************************************* 
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 //    udpsock     = INVALID_SOCKET;
00062 
00063     queue       = new list_c<char>;
00064     queuelen    = 0;
00065 }
00066 
00067 net_client_c::~net_client_c()
00068 {
00069     AssertThis;
00070 
00071     // clear queue
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     // close socket
00083     shutdown(sock, 0);
00084     closesocket(sock);
00085 }
00086 
00087 void net_client_c::send_message(net_message_header_t *msg, bool /* reliable */)
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)) // clear to send?
00106     {
00107         // first send queue..
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         // then message
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    // no.. add to queue
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     // receive and process messages
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)) // is there data?
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 //                    net_message_pong_t *msg = (net_message_pong_t*)buf;
00194                     latency = gv.netman->sv_gametime - header.time;
00195                 }
00196                 break;
00197 
00198                         default:
00199 
00200                                 // TODO: gv.iface->sv_clientmessage(msg);
00201                                 break;
00202         }
00203 
00204         SafeArrayDelete(buf);
00205         FD_ZERO(&fd);
00206         FD_SET(sock, &fd);
00207     }
00208 }
00209 
00210 /**************************************************************************** 
00211  **************************************************************************** 
00212  * NET MANAGER ************************************************************** 
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 //    cl_udpsocket        = INVALID_SOCKET;
00235 
00236     sv_socket           = INVALID_SOCKET;
00237 //    sv_udpsocket        = INVALID_SOCKET;
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     // clear queue
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     // set local address and port
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     //  SERVER **************************************************
00336 
00337     // new server frame
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             // accept new connections **********************************
00362         if (select(1, &fd, NULL, NULL, &tv)) // is there data?
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                         // TODO:
00381                         // gv.iface->sv_clientconnect(cl)
00382         }
00383 
00384             // receive messages from clients ***************************
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     // clear disconnected clients + read incoming messages ******
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                                 // TODO:
00404                                 // gv.iface->sv_clientdisconnect(cl)
00405 
00406                 clients->remove_ptr(cl);
00407                 SafeDelete(cl);
00408                         }
00409         }
00410     }
00411 
00412     // **********************************************************
00413     //  CLIENT **************************************************
00414 
00415     // receive and process messages
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)) // is there data?
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     //  COMMON **************************************************
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     // set local address and port
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)) // clear to send?
00567     {
00568         // first send queue..
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         // then message
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    // no.. add to queue
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: // assume userdefined
00631             // gv.iface->cl_servermessage( ... ) 
00632             ;
00633     }
00634 }

Generated on Wed Dec 18 15:48:47 2002 for omicron engine by doxygen1.2.18