src/network/nNetObject.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028 
00029 #include "tMemManager.h"
00030 #include "nNetObject.h"
00031 #include "tLocale.h"
00032 //#include "nNet.h"
00033 #include "nSimulatePing.h"
00034 #include "tSysTime.h"
00035 #include "tToDo.h"
00036 #include "nObserver.h"
00037 #include "nConfig.h"
00038 #include "tRecorder.h"
00039 
00040 #include <deque>
00041 #include <set>
00042 #include <map>
00043 
00044 // debug watchs
00045 #ifdef DEBUG
00046 int sn_WatchNetID = 0;
00047 extern nMessage* sn_WatchMessage;
00048 #endif
00049 
00050 tDEFINE_REFOBJ( nNetObject )
00051 
00052 // max ping to equalize;
00053 int sn_pingCharityServer=0;
00054 
00055 // first, we need a mechanism to distribute the nNetObject id's
00056 // among the clients and the server.
00057 
00058 // only used on the server: the next free id.
00059 static unsigned short net_current_id=1;
00060 
00061 
00062 // the maximal value of net_max_current_id
00063 static const unsigned short net_max_current_id_max = 32000;
00064 // the minimal value of net_max_current_id
00065 //#ifdef DEBUG
00066 //static const unsigned short net_max_current_id_min = 1000;
00067 //#else
00068 static const unsigned short net_max_current_id_min = 16000;
00069 //#endif
00070 
00071 // the maximal ID we currently want to assign
00072 static unsigned short net_max_current_id = net_max_current_id_min;
00073 
00074 #ifdef DEBUG
00075 static void sn_BreakOnObjectID( unsigned int id )
00076 {
00077 #ifdef DEBUG_X
00078     static unsigned int breakOnID = sn_WatchNetID;
00079     static REAL minTime = 0;
00080     if ( id == breakOnID  && tSysTimeFloat() > minTime )
00081         st_Breakpoint();
00082 #endif
00083 }
00084 
00085 static void sn_BreakOnObject( nNetObject * object )
00086 {
00087     if ( object )
00088         sn_BreakOnObjectID( object->ID() );
00089 }
00090 #endif
00091 
00092 static unsigned short inc_id(){
00093     unsigned short ret=net_current_id++;
00094 
00095     if ( net_current_id > net_max_current_id )
00096     {
00097         net_current_id = 1;
00098     }
00099 
00100     if (net_current_id==0)
00101         net_current_id++;
00102     return ret;
00103 }
00104 // the number of ID's that is to be requested from the server
00105 #define ID_PREFETCH 50
00106 
00107 // the requested id FIFO
00108 unsigned short net_reserved_id[ID_PREFETCH];
00109 unsigned short distribute=0,request=0;
00110 
00111 
00112 // the reserved id's are stored here
00113 tArray<unsigned short> sn_netObjectsOwner;
00114 // so the server knows who owns wich id
00115 
00116 // queue of recently freed IDs ready for reuse
00117 static std::deque<nNetObjectID> sn_freedIDs;
00118 
00119 // stored information needed when the objects are destroeyed
00120 static tArray<bool> sn_netObjects_AcceptClientSync;
00121 // and the function AcceptClientSync() is no longer valid (bummer.)
00122 
00123 tArray<tJUST_CONTROLLED_PTR<nNetObject> > sn_netObjects(1024);
00124 
00125 static const REAL nDeletedTimeout = 60.0f;
00126 
00127 struct nDeletedInfo
00128 {
00129     tJUST_CONTROLLED_PTR<nNetObject> object_;   // deleted object
00130     nTimeAbsolute time_;                                                // time it was deleted
00131 
00132     nDeletedInfo()
00133     {
00134         this->UnSet();
00135     }
00136 
00137     void Set( nNetObject* object )
00138     {
00139 #ifdef DEBUG
00140         sn_BreakOnObject( object );
00141 #endif
00142         time_ = tSysTimeFloat();
00143         object_ = object;
00144     }
00145 
00146     void UnSet( )
00147     {
00148         time_ = - nDeletedTimeout * 2.0f;
00149         object_ = NULL;
00150     }
00151 };
00152 
00153 // info about deleted objects, sorted by their former ID
00154 typedef std::map< nNetObjectID, nDeletedInfo > nDeletedInfos;
00155 static nDeletedInfos sn_netObjectsDeleted;
00156 
00157 static bool free_server( nNetObjectID id )
00158 {
00159     if ( bool(sn_netObjectsOwner[id]) || bool(sn_netObjects[id]) )
00160     {
00161         return false;
00162     }
00163 
00164     nDeletedInfos::iterator found = sn_netObjectsDeleted.find( id );
00165     if ( found != sn_netObjectsDeleted.end() )
00166     {
00167         nDeletedInfo  & deleted = (*found).second;
00168         if ( deleted.time_ > tSysTimeFloat() - nDeletedTimeout )
00169         {
00170             return false;
00171         }
00172 
00173         if ( deleted.object_ )
00174         {
00175 #ifdef DEBUG
00176             sn_BreakOnObjectID( id );
00177 #endif
00178             // clear the deletion info, but don't reuse the ID just yet
00179             deleted.UnSet();
00180             return false;
00181         }
00182     }
00183 
00184     return true;
00185 }
00186 
00187 static unsigned short next_free_server_nokill(){
00188     // slowly decrease max user ID
00189     if ( net_max_current_id > net_max_current_id_min )
00190     {
00191         net_max_current_id--;
00192         if ( net_current_id > net_max_current_id )
00193             net_current_id = 1;
00194     }
00195 
00196     // recycle old used IDs
00197     while ( sn_freedIDs.size() > 1000 && sn_freedIDs.size() * 20 > net_max_current_id )
00198     {
00199         nNetObjectID freedID = sn_freedIDs.front();
00200         sn_freedIDs.pop_front();
00201 #ifdef DEBUG
00202         sn_BreakOnObjectID( freedID );
00203 #endif
00204         sn_netObjectsOwner[freedID] = 0;
00205     }
00206 
00207     nNetObjectID start_id = net_current_id;
00208     if (sn_GetNetState()==nSERVER || sn_GetNetState()==nSTANDALONE)
00209     {
00210         do
00211         {
00212             inc_id();
00213         }
00214         while ( !free_server( net_current_id ) && net_current_id != start_id );
00215 
00216         if ( net_current_id != start_id )
00217         {
00218             // no problem!
00219 #ifdef DEBUG
00220             sn_BreakOnObjectID( net_current_id );
00221 #endif
00222             return net_current_id;
00223         }
00224         else
00225         {
00226             // we ran out of IDs.
00227             return 0;
00228         }
00229     }
00230 
00231     else
00232     {
00233         tERR_ERROR("next_free_server is not available for clients.");
00234         return 0;
00235     }
00236 }
00237 
00238 // kills the guy with the most registered IDs
00239 static int kill_id_hog()
00240 {
00241     int i;
00242     int grabbedIDs[MAXCLIENTS+2];
00243     int usedIDs[MAXCLIENTS+2];
00244 
00245     for ( i = MAXCLIENTS+1; i>=0; --i )
00246     {
00247         grabbedIDs[i] = 0;
00248         usedIDs[i] = 0;
00249     }
00250 
00251     // find out how many IDs a user has reserved with or without using them
00252     for ( i = sn_netObjectsOwner.Len()-1; i>=0; --i )
00253     {
00254         int owner = sn_netObjectsOwner( i );
00255         if ( owner >= 0 && owner <= MAXCLIENTS )
00256         {
00257             if ( sn_netObjects[i] )
00258             {
00259                 usedIDs[ owner ] ++;
00260             }
00261             else if ( owner > 0 )
00262             {
00263                 grabbedIDs[ owner ] ++;
00264             }
00265         }
00266     }
00267 
00268     // find the user with most used/grabbed IDs
00269     int maxGrabbed = 2 * ID_PREFETCH + 1;
00270     int maxUsed = 0;
00271     int maxGrabbedUser = -1;
00272     int maxUsedUser = -1;
00273 
00274     for ( i = MAXCLIENTS+1; i > 0; --i )
00275     {
00276         if ( grabbedIDs[i] > maxGrabbed )
00277         {
00278             maxGrabbedUser = i;
00279             maxGrabbed = grabbedIDs[i];
00280         }
00281 
00282         if ( usedIDs[i] > maxUsed )
00283         {
00284             maxUsedUser = i;
00285             maxUsed = usedIDs[i];
00286         }
00287     }
00288 
00289     // kick the top grabber
00290     if ( maxGrabbedUser > 0 )
00291     {
00292         con << "Killing top ID grabber.\n";
00293         st_Breakpoint();
00294         sn_DisconnectUser( maxGrabbedUser, "$network_kill_maxidgrabber" );
00295         return maxGrabbedUser;
00296     }
00297 
00298     // kick the top user
00299     else if ( maxUsedUser > 0 )
00300     {
00301         con << "Killing top ID user.\n";
00302         st_Breakpoint();
00303         sn_DisconnectUser( maxUsedUser, "$network_kill_maxiduser" );
00304         return maxUsedUser;
00305     }
00306 
00307     return -1;
00308 }
00309 
00310 // wrapper for toto tools
00311 static bool sg_todoKillHog=false;
00312 static void kill_id_hog_todo()
00313 {
00314     if ( sg_todoKillHog )
00315         kill_id_hog();
00316     sg_todoKillHog=false;
00317 }
00318 
00319 static unsigned short next_free_server( bool kill ){
00320     nNetObjectID id = next_free_server_nokill();
00321     if ( id > 0 )
00322     {
00323         return id;
00324     }
00325     else
00326     {
00327         // plan to kill the worst ID user
00328         sg_todoKillHog=true;
00329         st_ToDo( kill_id_hog_todo );
00330 
00331         // increase ID limit
00332         int increase = 1000;
00333         if ( net_max_current_id + 2 * increase < net_max_current_id_max )
00334             net_max_current_id += increase;
00335         else
00336             net_max_current_id = net_max_current_id + ( net_max_current_id_max - net_max_current_id );
00337 
00338         id = next_free_server_nokill();
00339         if ( id > 0 )
00340         {
00341             return id;
00342         }
00343         else
00344         {
00345             // throw an error
00346             if ( kill )
00347                 throw nKillHim();
00348 
00349             // or just exit silently
00350             con << "Emergency exit: desperately ran out of IDs.\n";
00351             exit(-1);
00352         }
00353     }
00354 }
00355 
00356 void req_id_handler(nMessage &m){
00357     unsigned short stop = distribute;
00358     if (distribute == 0)
00359         stop = ID_PREFETCH;
00360 
00361     if (sn_GetNetState()==nSERVER)
00362         Cheater(m.SenderID());
00363     else{
00364         while (!m.End())
00365         {
00366             unsigned short id, count=1;
00367             m.Read(id);
00368             if (!m.End())
00369                 m.Read(count);
00370 
00371             for (unsigned short i=id + count - 1; i>= id && request+1 != stop; i--)
00372             {
00373                 if (sn_netObjects[i])
00374                 {
00375                     con << "Warning! Network id receive error on ID " << i << " belonging to client " << sn_netObjects[i]->Owner() << "\n";
00376                     con << "while recieving ID block " << id << "-" << id+count-1 << " from netmessage " << m.MessageID() << ".\n";
00377 
00378                 }
00379                 else
00380                 {
00381                     net_reserved_id[request] = i;
00382 #ifdef DEBUG
00383                     // con << "got id " << net_reserved_id[request] << '\n';
00384 #endif
00385                     request++;
00386                     if (request>=ID_PREFETCH)
00387                         request=0;
00388                 }
00389             }
00390         }
00391     }
00392 }
00393 
00394 nDescriptor req_id(20,req_id_handler,"req_id");
00395 
00396 void id_req_handler(nMessage &m){
00397     // Add security: keep clients from fetching too many ids
00398 
00399     if (sn_GetNetState()==nSERVER && m.SenderID()<=MAXCLIENTS)
00400     {
00401         if (m.End())
00402         { // old style request; send only one ID back.
00403             tJUST_CONTROLLED_PTR< nMessage > rep=new nMessage(req_id);
00404             unsigned short id=next_free_server(true);
00405             sn_netObjectsOwner[id]=m.SenderID();
00406             //    con << "Assigning ID " << id << "\n";
00407             rep->Write(id);
00408             rep->Send(m.SenderID());
00409 
00410 #ifdef DEBUG
00411             //con << "distributed id " << net_current_id-1 << " to user " << m.SenderID() << '\n';
00412 #endif
00413         }
00414         else
00415         {
00416             // new style request: many IDs
00417             unsigned short num;
00418             m.Read(num);
00419 
00420             // but not too many. kick violators.
00421             if ( num > ID_PREFETCH*4 )
00422             {
00423                 throw nKillHim();
00424             }
00425 
00426             tJUST_CONTROLLED_PTR< nMessage > rep=new nMessage(req_id);
00427 
00428             unsigned short begin_block=0;       // begin of the block of currently assigned IDs
00429             unsigned short block_len=0;         // and it's length
00430 
00431             for (int i = num-1; i>=0; i--)
00432             {
00433                 nNetObjectID id = next_free_server(true);
00434 
00435                 sn_netObjectsOwner[id]=m.SenderID();
00436 
00437                 if (begin_block + block_len == id)      // RLE for allocated IDs
00438                     block_len++;
00439                 else
00440                 {
00441                     if (block_len > 0)
00442                     {
00443                         //                    con << "Assigning block " << begin_block << " - " << begin_block + block_len - 1 << "\n";
00444                         rep->Write(begin_block);
00445                         rep->Write(block_len);
00446                     }
00447                     begin_block = id;
00448                     block_len = 1;
00449                 }
00450             }
00451             if (block_len > 0)
00452             {
00453                 //            con << "Assigning block " << begin_block << " - " << begin_block + block_len - 1 << "\n";
00454                 rep->Write(begin_block);
00455                 rep->Write(block_len);
00456             }
00457 
00458             rep->Send(m.SenderID());
00459         }
00460     }
00461 }
00462 
00463 nDescriptor id_req(21,id_req_handler,"id_req_handler");
00464 
00465 unsigned short next_free(){
00466     unsigned short ret=0;
00467 
00468     do{
00469         if (sn_GetNetState()==nCLIENT){
00470             unsigned short need_soon = request + ID_PREFETCH - distribute;
00471             if (need_soon > ID_PREFETCH)
00472                 need_soon -= ID_PREFETCH;
00473             if (need_soon < (ID_PREFETCH >> 1))
00474             {
00475                 tJUST_CONTROLLED_PTR< nMessage > m = new nMessage(id_req);
00476                 m->Write(ID_PREFETCH >> 2);
00477                 m->Send(0);
00478             }
00479 
00480             double timeout=tSysTimeFloat()+60;
00481             while (sn_Connections[0].socket && distribute==request && tSysTimeFloat()<timeout){
00482                 // wait for new ids from the server
00483 #ifdef DEBUG
00484                 // con << distribute << ":" << request << '\n';
00485 #endif
00486                 sn_Receive();
00487                 nNetObject::SyncAll();
00488                 sn_SendPlanned();
00489                 //      st_Breakpoint();
00490                 tAdvanceFrame(1000000);
00491             }
00492             if (tSysTimeFloat()>=timeout)
00493                 tERR_ERROR_INT("Not enough nNetObject IDs to distribute. Sorry!\n");
00494 
00495             ret=net_reserved_id[distribute];
00496 
00497             distribute++;
00498             if (distribute>=ID_PREFETCH)
00499                 distribute=0;
00500             //      con << "used id " << ret << '\n';
00501             net_current_id=ret+1;
00502         }
00503         else
00504         {
00505             ret=next_free_server(false);
00506         }
00507 
00508         if (sn_netObjects[ret]){
00509             con << "Warning! Network id assignment error on ID " << ret << " belonging to client " << sn_netObjects[ret]->Owner() << "\n";
00510             ret=0;
00511         }
00512 
00513     }while (ret==0 && sn_Connections[0].socket);
00514 
00515     return ret;
00516 }
00517 
00518 void first_fill_ids(){
00519     if (sn_GetNetState()!=nCLIENT)
00520         tERR_ERROR("first_fill_ids is only for clients!");
00521 
00522     distribute=request=0;
00523 
00524     tJUST_CONTROLLED_PTR< nMessage > m = new nMessage(id_req);
00525     m->Write(ID_PREFETCH - 10);
00526     m->Send(0);
00527 }
00528 
00529 
00530 void Cheater(int i)
00531 {
00532     // anything to do at all?
00533     if (i != 0 && !sn_Connections[i].socket)
00534     {
00535         return;
00536     }
00537 
00538     con << "User " << i << " tried to cheat.\n";
00539     //  st_Breakpoint();
00540 
00541     if ( i == 0 )
00542         // terminate connection to server
00543         throw tGenericException("There was a network error, the connection to the server had to be terminated.", "Network Error");
00544     else
00545         sn_DisconnectUser(i, "$network_kill_cheater" );
00546 }
00547 
00548 
00549 /*
00550 nDescriptor& nNetObject::CreatorDescriptor() const{
00551   return nNetObject_initialisator.desc;
00552 }
00553 */
00554 
00555 void nNetObject::AddRef(){
00556     tASSERT ( this );
00557 
00558     if ( this )
00559     {
00560         tASSERT( refCtr_ >= 0 );
00561         refCtr_++;
00562         tASSERT( refCtr_ >= 0 );
00563     }
00564 }
00565 
00566 void nNetObject::ReleaseOwnership(){
00567     if ( this->createdLocally )
00568     {
00569         this->createdLocally = false;
00570         Release();
00571     }
00572 }
00573 
00574 void nNetObject::TakeOwnership(){
00575     if ( !this->createdLocally )
00576     {
00577         this->createdLocally = true;
00578         //              AddRef();
00579     }
00580 }
00581 
00582 void nNetObject::Release(){
00583     tASSERT( this );
00584 
00585     if (this){
00586         if (refCtr_>0)
00587             refCtr_--;
00588         else
00589         {
00590 #ifdef DEBUG
00591             tERR_ERROR("Negative recfcount!");
00592 #else
00593             return;
00594 #endif
00595         }
00596         int extra=0;
00597 
00598         // account for the reference held by the creator of the object
00599 
00600         // only if the object is validly entered in our object-array
00601         if (id > 0 && static_cast<nNetObject*>(sn_netObjects[id])==this)
00602         {
00603             if ( createdLocally )
00604                 extra = -1;
00605         }
00606         //    else
00607         //      extra = -1;
00608 
00609         if ( refCtr_ + extra <= 0 )
00610         {
00611             refCtr_ = -100;
00612             delete this;
00613         }
00614     }
00615 }
00616 
00617 // get refcount. Use only for Debgging purposes, never base any decisions on it.
00618 int nNetObject::GetRefcount() const
00619 {
00620     int extra=0;
00621 
00622     // account for the reference held by the creator of the object
00623 
00624     // only if the object is validly entered in our object-array
00625     if (id > 0 && static_cast<nNetObject*>(sn_netObjects[id])==this)
00626     {
00627         if ( createdLocally )
00628             extra = -1;
00629     }
00630     //    else
00631     //      extra = -1;
00632 
00633     return this->refCtr_ + extra;
00634 }
00635 
00636 nObserver& nNetObject::GetObserver() const
00637 {
00638     if ( !this->observer_ )
00639     {
00640         this->observer_ = tNEW( nObserver );
00641         this->observer_->SetObject( this );
00642     }
00643 
00644     return *this->observer_;
00645 }
00646 
00647 
00648 // dumps object stats
00649 void nNetObject::Dump( tConsole& con )
00650 {
00651     tString str;
00652     this->PrintName( str );
00653     con << str;
00654 }
00655 
00656 // checks whether n is newer than old (exploits integer overflow)
00657 bool sn_Update(unsigned short &old,unsigned short n){
00658     if ( 0 == old )
00659     {
00660         old = n;
00661         return true;
00662     }
00663 
00664     short diff=old-n;
00665     if (diff<0){
00666         old=n;
00667         return true;
00668     }
00669     else
00670         return false;
00671 }
00672 
00673 // same for longs
00674 bool sn_Update(unsigned long &old,unsigned long n){
00675     if ( 0 == old )
00676     {
00677         old = n;
00678         return true;
00679     }
00680 
00681     long diff=old-n;
00682     if (diff<0){
00683         old=n;
00684         return true;
00685     }
00686     else
00687         return false;
00688 }
00689 
00690 // static unsigned long int global_lastSync=0;
00691 
00692 bool nNetObject::SyncIsNew(nMessage &m){
00693     unsigned long int bigID =  m.MessageIDBig();
00694     //    sn_Update(global_lastSync,bigID);
00695     return sn_Update(lastSyncID_,bigID);
00696 }
00697 
00698 /*
00699 static unsigned short global_lastSync=0;
00700 
00701 bool nNetObject::SyncIsNew(nMessage &m){
00702     sn_Update(global_lastSync,m.MessageID());
00703     return sn_Update(lastSyncID,m.MessageID());
00704 }
00705 */
00706 
00707 nNetObject::nNetObject(int own):lastSyncID_(0),
00708 id(0),refCtr_(0),owner(own){
00709 #ifdef DEBUG
00710     //con << "Netobject " << id  << " created.\n";
00711     //  if (id == 383)
00712     //   st_Breakpoint();
00713 #endif
00714     syncListID_ = -1;
00715 
00716     createdLocally = true;
00717 
00718     if (own<0) owner=::sn_myNetID;
00719 }
00720 
00721 static nNetObjectRegistrar* sn_Registrar = NULL;
00722 
00723 nNetObjectRegistrar::nNetObjectRegistrar()
00724 {
00725     sender = 100;
00726     id = 0;
00727     oldRegistrar = sn_Registrar;
00728     sn_Registrar = this;
00729 }
00730 
00731 nNetObjectRegistrar::~nNetObjectRegistrar()
00732 {
00733     tASSERT( sn_Registrar == this );
00734     sn_Registrar = oldRegistrar;
00735 }
00736 
00737 // gegister with the object database
00738 void nNetObject::Register( const nNetObjectRegistrar& registrar )
00739 {
00740     tASSERT( this == registrar.object );
00741     tASSERT( id == 0 || id == registrar.id );
00742 
00743     if ( this->id == registrar.id )
00744     {
00745         return;
00746     }
00747 
00748     id = registrar.id;
00749 
00750     if (sn_netObjectsOwner[id]!= registrar.sender || sn_netObjects[id]){
00751 #ifdef DEBUG
00752         con << "Netobject " << id << " is already reserved!\n";
00753 #endif
00754         if (sn_netObjectsOwner[id]!=registrar.sender){
00755             Cheater( registrar.sender );
00756             nReadError();
00757         }
00758     }
00759     else
00760     {
00761 #ifdef DEBUG
00762         sn_BreakOnObjectID( id );
00763 #endif
00764         sn_netObjects[id]=this;
00765     }
00766 
00767     if (sn_GetNetState()!=nCLIENT)
00768         owner=registrar.sender; // to make sure noone is given a nNetObject from
00769     // someone else.
00770 
00771     sn_netObjectsOwner[id]=owner;
00772     sn_netObjects_AcceptClientSync[id]=false;
00773 }
00774 
00775 nNetObject::nNetObject(nMessage &m):lastSyncID_(m.MessageIDBig()),refCtr_(0){
00776     // sn_Update(global_lastSync,lastSyncID_);
00777 
00778     id = 0;
00779     owner = 0;
00780 
00781     syncListID_ = -1;
00782 
00783     tASSERT( sn_Registrar );
00784     nNetObjectRegistrar& registrar = *sn_Registrar;
00785 
00786     createdLocally = false;
00787 
00788     m.Read( registrar.id );
00789 #ifdef DEBUG
00790     //con << "Netobject " << id << " created on remote order.\n";
00791     //  if (id == 383)
00792     //  st_Breakpoint();
00793 #endif
00794     m.Read( owner );
00795 
00796     // clients are only allowed to create self-owned objects
00797     if ( sn_GetNetState() == nSERVER )
00798     {
00799         if ( owner != m.SenderID() )
00800         {
00801             throw nKillHim();
00802         }
00803     }
00804 
00805     registrar.object = this;
00806     registrar.sender = m.SenderID();
00807 
00808     knowsAbout[m.SenderID()].knowsAboutExistence=true;
00809 #ifdef DEBUG
00810     // con << "Netobject " << id  << " created (remote order).\n";
00811 #endif
00812 }
00813 
00814 void nNetObject::DoBroadcastExistence(){
00815     if (BroadcastExistence() &&
00816             ( sn_GetNetState()!=nCLIENT ||
00817               ( owner == ::sn_myNetID && AcceptClientSync() )
00818             )
00819        )
00820     {
00821         int maxUser = (sn_GetNetState() == nSERVER) ? MAXCLIENTS : 0;
00822         int minUser  = (sn_GetNetState() == nSERVER) ? 1 : 0;
00823         for (int user = maxUser; user >= minUser; --user)
00824         {
00825             // sync the object only to users that don't know about it yet
00826             if ( !knowsAbout[user].knowsAboutExistence && sn_Connections[user].socket ) // && !knowsAbout[user].syncReq )
00827                 RequestSync( user, true );
00828         }
00829     }
00830 }
00831 
00832 
00833 struct nDestroyInfo
00834 {
00835     unsigned short id;
00836     unsigned short sender;
00837     bool actionOnDeleteExecuted;
00838     nTimeAbsolute timeout;
00839 };
00840 
00841 static tArray< nDestroyInfo > sn_Destroyed; // accepted destroy messages to be executed later
00842 static std::set< unsigned short > sn_LocallyDestroyedIDs; // IDs of locally destroyed objects
00843 
00844 // returns whether the given ID belongs to a locally deleted object and deletes the entry
00845 bool sn_WasDeletedLocally( unsigned short id )
00846 {
00847     // delete local destruction log, if there was any
00848     std::set< unsigned short >::iterator found = sn_LocallyDestroyedIDs.find(id);
00849     if ( found != sn_LocallyDestroyedIDs.end() )
00850     {
00851         // yes. Ignore the message and remove the local destroy thing.
00852         sn_LocallyDestroyedIDs.erase( found );
00853         return true;
00854     }
00855 
00856     return false;
00857 }
00858 
00859 void nNetObject::InitAfterCreation(){
00860     DoBroadcastExistence();
00861     // con << "InitAfterCreation\n";
00862 
00863 #ifdef DEBUG
00864     sn_BreakOnObjectID( id );
00865 #endif
00866 
00867     // it just got created, all local deletions must be fakes
00868     sn_WasDeletedLocally( id );
00869 } // after remote creation,
00870 
00871 
00872 static void net_destroy_handler(nMessage &m){
00873     //con << "destroy begin\n";
00874     unsigned short id;
00875     //int count=0;
00876     while (!m.End()){
00877         m.Read(id);
00878 #ifdef DEBUG
00879         sn_BreakOnObjectID( id );
00880 #endif
00881         // see if there was a local destruction; if yes, ignore.
00882         if (sn_WasDeletedLocally( id ))
00883             continue;
00884 
00885         nDestroyInfo& info = sn_Destroyed[ sn_Destroyed.Len() ];
00886         info.id = id;
00887         info.sender = m.SenderID();
00888         info.actionOnDeleteExecuted=false;
00889         info.timeout=tSysTimeFloat()+nDeletedTimeout;
00890 
00891         // notify object of pending deletion
00892         if (nNetObject *no=sn_netObjects[id])
00893         {
00894             tASSERT( !no->Owned() );
00895 
00896             no->ActionOnDelete();
00897             info.actionOnDeleteExecuted=true;
00898 
00899             // if the object is now suddenly owned by this machine, there must be a reason.
00900             // undo the deletion. Whoever did this has now the responsibility for the object.
00901             if ( no->Owned() )
00902                 sn_Destroyed.SetLen( sn_Destroyed.Len() - 1 );
00903         }
00904 
00905 #ifdef DEBUG
00906         //count ++;
00907         //con << count;
00908         //con << " destroying object " << id << " by remote order.\n";
00909 #endif
00910 
00911     }
00912     //con << "destroy end.\n";
00913 }
00914 
00915 static void sn_DoDestroy()
00916 {
00917 #ifdef DEBUG
00918     static bool recursion = false;
00919     tASSERT( !recursion );
00920     recursion = true;
00921 #endif
00922 
00923     for ( int i = sn_Destroyed.Len()-1 ; i>=0; --i )
00924     {
00925         nDestroyInfo& info = sn_Destroyed( i );
00926         unsigned short id = info.id;
00927 
00928         // check if the message timed out
00929         bool timedOut = ( info.timeout < tSysTimeFloat() );
00930 
00931         // get object
00932         nNetObject *no=sn_netObjects[id];
00933 
00934         // destroy it!
00935         if (bool(no) || timedOut){
00936 #ifdef DEBUG
00937             sn_BreakOnObjectID( id );
00938 #endif
00939             // see if there was a local destruction; if yes, ignore.
00940             if (!sn_WasDeletedLocally( id ) && !timedOut )
00941             {
00942                 if (no->Owner()==info.sender || info.sender==0){
00943                     sn_netObjectsDeleted [ id ].Set( no );
00944 
00945                     if (!info.actionOnDeleteExecuted)
00946                         no->ActionOnDelete();
00947 
00948                     sn_netObjects(id)=NULL;
00949                     sn_netObjectsOwner(id)=0;
00950                 }
00951                 else
00952                     Cheater(info.sender);
00953             }
00954 
00955             // delete message by overwriting it with the last message in the array
00956             int last = sn_Destroyed.Len()-1;
00957             info = sn_Destroyed( last );
00958             sn_Destroyed.SetLen( last );
00959         }
00960     }
00961 #ifdef DEBUG
00962     recursion = false;
00963 #endif
00964 }
00965 
00966 static nCallbackReceivedComplete sn_ReceivedComplete( sn_DoDestroy );
00967 
00968 /*
00969 // tell the basic nNetObject constructor where to store itself
00970 void nNetObject::RegisterRegistrar( nNetObjectRegistrar& r )
00971 {
00972         sn_Registrar = &r;
00973 }
00974 */
00975 
00976 static nDescriptor net_destroy(22,net_destroy_handler,"net_destroy");
00977 
00978 static tJUST_CONTROLLED_PTR< nMessage > destroyers[MAXCLIENTS+2];
00979 static REAL                             destroyersTime[MAXCLIENTS+2];
00980 
00981 // list of netobjects that have a sync request running
00982 static tList< nNetObject > sn_SyncRequestedObject;
00983 
00984 nNetObject::~nNetObject(){
00985     // remove from sync list
00986     if ( syncListID_ >= 0 )
00987         sn_SyncRequestedObject.Remove( this, syncListID_ );
00988 
00989     // release observer
00990     if ( this->observer_ )
00991     {
00992         this->observer_->SetObject( NULL );
00993     }
00994 
00995 #ifdef DEBUG
00996     int extra=0;
00997 
00998     // account for the reference held by the creator of the object
00999 
01000     // only if the object is validly entered in our object-array
01001     if (id > 0 && static_cast<nNetObject*>(sn_netObjects[id])==this)
01002     {
01003         if ( createdLocally )
01004             extra = -1;
01005     }
01006 
01007     if (refCtr_ + extra > 0)
01008         tERR_ERROR("Hey! There is stil someone interested in this nNetObject!\n");
01009     //con << "Netobject " << id  << " deleted.\n";
01010 #endif
01011 
01012     // mark id as soon-to-be free
01013     if (id)
01014     {
01015 #ifdef DEBUG
01016         sn_BreakOnObjectID( id );
01017 #endif
01018         if ( sn_GetNetState() == nSERVER )
01019         {
01020             sn_netObjectsOwner[id]=0xFFFF;
01021             sn_freedIDs.push_back( id );
01022         }
01023         else
01024         {
01025             sn_netObjectsOwner[id]=0;
01026         }
01027     }
01028 
01029     // determine whether a destroy message should be sent: the server definitely should...
01030     bool sendDestroyMessage = (sn_GetNetState()==nSERVER);
01031     if (!sendDestroyMessage && id && sn_netObjects_AcceptClientSync[id] && owner==sn_myNetID)
01032     {
01033         // ... but also the client if the object belongs to it.
01034         sendDestroyMessage = true;
01035 
01036         // the server will send a response destroy message later. We need to ignore it.
01037         sn_LocallyDestroyedIDs.insert(id);
01038     }
01039 
01040     // send it
01041     if ( sendDestroyMessage )
01042     {
01043         int idsync=id;
01044         tRecorderSync< int >::Archive( "_NETOBJECT_DESTROYED", 3, idsync );
01045 
01046         // con << "Destroying object " << id << '\n';
01047         for (int user=MAXCLIENTS;user>=0;user--){
01048             if (user!=sn_myNetID && knowsAbout[user].knowsAboutExistence ||
01049                     knowsAbout[user].acksPending){
01050                 if (destroyers[user]==NULL)
01051                 {
01052                     destroyers[user]=new nMessage(net_destroy);
01053                     destroyersTime[user]=tSysTimeFloat();
01054                 }
01055                 destroyers[user]->Write(id);
01056 
01057                 if (destroyers[user]->DataLen()>100){
01058                     destroyers[user]->Send(user);
01059                     destroyers[user]=NULL;
01060                 }
01061 
01062 #ifdef DEBUG
01063                 //con << "remotely destroying object " << id << '\n';
01064 #endif
01065             }
01066         }
01067     }
01068     refCtr_=100;
01069     if (id)
01070     {
01071         if (this == sn_netObjects[id])
01072         {
01073 #ifdef DEBUG
01074             sn_BreakOnObjectID( id );
01075 #endif
01076             sn_netObjects[id] = NULL;
01077         }
01078 
01079         // clear object from info arrays
01080         nDeletedInfos::iterator found = sn_netObjectsDeleted.find( id );
01081         if ( found != sn_netObjectsDeleted.end() )
01082         {
01083             nDeletedInfo  & deleted = (*found).second;
01084             deleted.Set( NULL );
01085             sn_netObjectsDeleted.erase(found);
01086         }
01087     }
01088 
01089     refCtr_=-100;
01090     tCHECK_DEST;
01091 }
01092 
01093 
01094 
01095 nNetObject *nNetObject::Object(int i){
01096     if (i==0) // the NULL nNetObject
01097         return NULL;
01098 
01099     // the last deleted object with specified ID
01100     nNetObject* deleted = NULL;
01101     nDeletedInfos::const_iterator found = sn_netObjectsDeleted.find( id );
01102     if ( found != sn_netObjectsDeleted.end() )
01103     {
01104         deleted = (*found).second.object_;
01105     }
01106 
01107     // return immediately if the object is there
01108     nNetObject *ret=ObjectDangerous( i );
01109     if ( ret )
01110     {
01111         return ret;
01112     }
01113 
01114     // set new timeout value
01115     const REAL totalTimeout=10;
01116     const REAL printMessageTimeout=.5;
01117 
01118     double newTimeout=tSysTimeFloat()+totalTimeout;
01119     static double timeout=-1;
01120     if ( tSysTimeFloat() > timeout )
01121         timeout = newTimeout;
01122 
01123     bool printMessage=true;
01124     while (sn_Connections[0].socket &&
01125             NULL==(ret=sn_netObjects[i]) && timeout >tSysTimeFloat()){ // wait until it is spawned
01126         if (tSysTimeFloat()>timeout-(totalTimeout + printMessageTimeout))
01127         {
01128             if (printMessage)
01129             {
01130                 con << "Waiting for NetObject with ID " << i << " to spawn...\n";
01131                 printMessage=false;
01132             }
01133             if (sn_GetNetState()==nSERVER){
01134                 // in server mode, we cannot wait.
01135 
01136                 // the deleted object with the same ID must have been meant
01137                 if ( deleted )
01138                 {
01139                     return deleted;
01140                 }
01141 
01142                 nReadError();
01143 
01144                 con << "Now we need to leave the\n"
01145                 << "system in an undefined state. I hope this works...\n";
01146 
01147                 Cheater(owner); // kill this bastard
01148                 return NULL; // pray that noone references this pointer
01149             }
01150         }
01151         tAdvanceFrame(10000);
01152         sn_Receive();
01153         sn_SendPlanned();
01154     }
01155 
01156     if (!ret)
01157         ret = deleted;
01158 
01159     if (!ret)
01160         tERR_WARN("Netobject " << i << " requested, but was never spawned.");
01161 
01162     return ret;
01163 }
01164 
01165 
01166 nNetObject *nNetObject::ObjectDangerous(int i ){
01167     if (i==0) // the NULL nNetObject
01168     {
01169         return NULL;
01170     }
01171     else
01172     {
01173         nNetObject* ret = sn_netObjects[i];
01174         if ( ret )
01175         {
01176             return ret;
01177         }
01178         else
01179         {
01180             nDeletedInfos::const_iterator found = sn_netObjectsDeleted.find( i );
01181             if ( found != sn_netObjectsDeleted.end() )
01182             {
01183                 nDeletedInfo const & deleted = (*found).second;
01184                 if ( deleted.time_ > tSysTimeFloat() - nDeletedTimeout )
01185                 {
01186                     return deleted.object_;
01187                 }
01188             }
01189         }
01190     }
01191 
01192     return NULL;
01193 }
01194 
01195 void nNetObject::PrintName(tString &s) const
01196 {
01197     s << "Nameless NetObject nr. " << id;
01198 }
01199 
01200 bool nNetObject::HasBeenTransmitted(int user) const{
01201     return (knowsAbout[user].knowsAboutExistence);
01202 }
01203 
01204 // we must not transmit an object that contains pointers
01205 // to non-transmitted objects. this function is supposed to check that.
01206 bool nNetObject::ClearToTransmit(int user) const{
01207     return true;
01208 }
01209 
01210 void nNetObject::WriteSync(nMessage &m, int run )
01211 {
01212     if ( run == 0 )
01213     {
01214         WriteSync( m );
01215     }
01216 }
01217 
01218 void nNetObject::ReadSync(nMessage &m, int run )
01219 {
01220     if ( run == 0 )
01221     {
01222         ReadSync( m );
01223     }
01224 }
01225 
01226 void nNetObject::WriteCreate(nMessage &m, int run )
01227 {
01228     if ( run == 0 )
01229     {
01230         WriteCreate( m );
01231     }
01232 }
01233 
01234 void nNetObject::ReadCreate(nMessage &m, int run )
01235 {
01236     // run == 0 would call the constructor, but run == 0 never happens.
01237     tASSERT( run > 0 );
01238 }
01239 
01240 void nNetObject::WriteAll( nMessage & m, bool create )
01241 {
01242     int lastLen = -1;
01243     int run = 0;
01244 
01245     // write as long as the read functions do something
01246     while ( m.DataLen() > lastLen )
01247     {
01248         lastLen = m.DataLen();
01249         if ( create )
01250         {
01251             WriteCreate(m,run);
01252         }
01253 
01254         WriteSync(m,run);
01255         ++run;
01256     }
01257 }
01258 
01259 void nNetObject::ReadAll ( nMessage & m, bool create )
01260 {
01261     int lastRead = -1;
01262     int run = 0;
01263 
01264     // read as long as the read functions do something
01265     while ( m.ReadSoFar() > lastRead )
01266     {
01267         lastRead = m.ReadSoFar();
01268         if ( create && run > 0 )
01269         {
01270             ReadCreate(m,run);
01271         }
01272 
01273         ReadSync(m,run);
01274         ++run;
01275     }
01276 }
01277 
01278 void nNetObject::WriteSync(nMessage &m){
01279 #ifdef DEBUG
01280     if (sn_GetNetState()!=nSERVER && !AcceptClientSync())
01281         tERR_ERROR("WriteSync should only be called server-side!");
01282 #endif
01283 } // nothing to do yet
01284 
01285 
01286 
01287 void nNetObject::ReadSync(nMessage &m){
01288     if (sn_GetNetState()==nSERVER){
01289         bool back=knowsAbout[m.SenderID()].syncReq;
01290         RequestSync(); // tell the others about it
01291         knowsAbout[m.SenderID()].syncReq=back;
01292         // but not the sender of the message; he
01293         // knows already.
01294     }
01295 }
01296 
01297 extern bool deb_net;
01298 
01299 // read and write id and owner
01300 void nNetObject::WriteCreate(nMessage &m){
01301     m.Write(id);
01302     m.Write(owner);
01303 
01304     // store the info needed in the destructor
01305     sn_netObjects_AcceptClientSync[id]=this->AcceptClientSync();
01306 
01307     if (deb_net)
01308         con << "Sending creation message for nNetObject " << id << "\n";
01309 }
01310 
01311 void nNetObject::GetID()
01312 {
01313     if ( !id && GetRefcount() >= 0 )
01314     {
01315         if ( bool( sn_Registrar ) && this == sn_Registrar->object )
01316         {
01317             id = sn_Registrar->id;
01318         }
01319         else
01320         {
01321             id = next_free();
01322         }
01323 
01324         if (sn_netObjects[id])
01325             tERR_ERROR("Dublicate nNetObject id " << id);
01326 
01327         sn_netObjectsOwner[id]=owner;
01328         sn_netObjects_AcceptClientSync[id]=false;
01329 
01330         sn_netObjects[id]=this;
01331     }
01332 }
01333 
01334 // request a sync
01335 void nNetObject::RequestSync(int user,bool ack){ // only for a single user
01336 #ifdef nSIMULATE_PING
01337     ack=true;
01338 #endif
01339     this->GetID();
01340 
01341     if (sn_GetNetState()==nSERVER || (AcceptClientSync() && owner==::sn_myNetID)){
01342         knowsAbout[user].syncReq=true;
01343         knowsAbout[user].nextSyncAck |=ack;
01344     }
01345 #ifdef DEBUG
01346     else
01347         tERR_ERROR("RequestSync should only be called server-side!");
01348 #endif
01349 
01350     if ( syncListID_ < 0 )
01351         sn_SyncRequestedObject.Add( this, syncListID_ );
01352 }
01353 
01354 void nNetObject::RequestSync(bool ack){
01355     this->GetID();
01356 
01357 #ifdef nSIMULATE_PING
01358     ack=true;
01359 #endif
01360 
01361 #ifdef DEBUG
01362     if (sn_GetNetState()==nCLIENT && (!AcceptClientSync() || owner!=::sn_myNetID))
01363         tERR_ERROR("RequestSync should only be called server-side!");
01364 #endif
01365 
01366     for (int i=MAXCLIENTS;i>=0;i--){
01367         knowsAbout[i].syncReq=true;
01368         knowsAbout[i].nextSyncAck |=ack;
01369     }
01370 
01371     if ( syncListID_ < 0 )
01372         sn_SyncRequestedObject.Add( this, syncListID_ );
01373 }
01374 
01375 
01376 static void net_control_handler(nMessage &m){
01377     //con << "control\n";
01378     if (sn_GetNetState()==nSERVER){
01379         unsigned short id;
01380         m.Read(id);
01381         nNetObject *o = sn_netObjects[id];
01382         if ( o ){
01383             if (m.SenderID()==o->Owner()) // only the owner is
01384                 // allowed to control the object
01385                 o->ReceiveControlNet(m);
01386             else
01387                 Cheater(m.SenderID()); // another lame cheater.
01388         }
01389     }
01390 }
01391 
01392 static nDescriptor net_control(23,net_control_handler,"net_control");
01393 
01394 void nNetObject::ReceiveControlNet(nMessage &){
01395 #ifdef DEBUG
01396     if (sn_GetNetState()==nCLIENT)
01397         tERR_ERROR("rec_cont should not be called client-side!");
01398 #endif
01399 
01400     // after control is received, we better sync this object with
01401     // the clients:
01402 
01403     RequestSync();
01404 }
01405 
01406 // control functions:
01407 nMessage * nNetObject::NewControlMessage(){
01408     nMessage *m=new nMessage(net_control);
01409     m->Write(id);
01410     return m;
01411 }
01412 
01413 
01414 
01415 class nWaitForAckSync: public nWaitForAck{
01416     unsigned short netobj;
01417 public:
01418     nWaitForAckSync(nMessage* m,int rec,unsigned short obj)
01419             :nWaitForAck(m,rec),netobj(obj){
01420         if (sn_netObjects(obj)->knowsAbout[rec].acksPending<15)
01421         {
01422             sn_netObjects(obj)->knowsAbout[rec].acksPending++;
01423         }
01424         else
01425         {
01426             st_Breakpoint();
01427         }
01428     }
01429     virtual ~nWaitForAckSync(){
01430         tCHECK_DEST;
01431     }
01432 
01433     virtual void AckExtraAction()
01434     {
01435         nNetObject* obj = sn_netObjects[netobj];
01436         if ( obj )
01437         {
01438             if ( obj->knowsAbout[receiver].acksPending)
01439             {
01440                 obj->knowsAbout[receiver].acksPending--;
01441             }
01442             else
01443             {
01444                 //                      st_Breakpoint();
01445             }
01446 
01447 #ifdef DEBUG
01448             /*
01449             if ( !obj->knowsAbout[receiver].knowsAboutExistence )
01450               {
01451                 tString str;
01452                 obj->PrintName( str );
01453                 con << "Received ack for object " << str << "\n";
01454               }
01455             */
01456 #endif
01457 
01458             obj->knowsAbout[receiver].knowsAboutExistence=true;
01459         }
01460         else
01461         {
01462             //          st_Breakpoint();
01463         }
01464     }
01465 };
01466 
01467 
01468 
01469 
01470 static void net_sync_handler(nMessage &m){
01471     unsigned short id;
01472     m.Read(id);
01473 #ifdef DEBUG
01474     // sn_BreakOnObjectID( id );
01475 #endif
01476     nNetObject * obj = nNetObject::ObjectDangerous(id);
01477     if (obj){
01478         if (sn_GetNetState()!=nCLIENT &&
01479                 (!obj->AcceptClientSync()
01480                  || obj->Owner()!=m.SenderID())
01481            ){
01482             Cheater(m.SenderID());
01483 #ifdef DEBUG
01484             tERR_ERROR("sync should only be called client-side!");
01485 #endif
01486         }
01487         else if (obj->SyncIsNew(m)){
01488             m.Reset();
01489             m.Read(id);
01490             obj->ReadAll(m, false);
01491         }
01492     }
01493 }
01494 
01495 static nDescriptor net_sync(24,net_sync_handler,"net_sync");
01496 
01497 bool nNetObject::AcceptClientSync() const{
01498     return false;
01499 }
01500 
01501 
01502 // global functions:
01503 
01504 
01505 //static int current_sync[MAXCLIENTS+2];
01506 static bool is_ready_to_get_objects[MAXCLIENTS+2];
01507 
01508 // from nNetwork.C
01509 //extern REAL planned_rate_control[MAXCLIENTS+2];
01510 
01511 static bool s_DoPrintDebug = false;
01512 bool nNetObject::DoDebugPrint()
01513 {
01514     return s_DoPrintDebug;
01515 }
01516 
01517 static int sn_syncedUser = -1;
01518 
01520 int nNetObject::SyncedUser()
01521 {
01522     return sn_syncedUser;
01523 }
01524 
01525 void nNetObject::SyncAll(){
01526 #ifdef DEBUG
01527     s_DoPrintDebug = false;
01528 
01529     static nTimeRolling debugtime = 0;
01530     nTimeRolling time = tSysTimeFloat();
01531     if (time > debugtime && sn_GetNetState() == nSERVER)
01532     {
01533         debugtime = time+5;
01534         //      s_DoPrintDebug = true;
01535     }
01536 #endif
01537 
01538     for (int user=MAXCLIENTS;user>=0;user--)
01539         if (is_ready_to_get_objects[user] &&
01540                 sn_Connections[user].socket && sn_netObjects.Len()>0 && user!=sn_myNetID){
01541 
01542             sn_syncedUser = user;
01543 
01544             // send the destroy messages
01545             if (destroyers[user])
01546             {
01547                 // but check whether the opportunity is good (big destroyers message, or a sync packet in the pipe) first
01548                 if ( destroyers[user]->DataLen() > 75 ||
01549                         sn_Connections[user].sendBuffer_.Len() > 0 ||
01550                         destroyersTime[user] < tSysTimeFloat()-.5 )
01551                 {
01552                     destroyers[user]->Send(user);
01553                     destroyers[user]=NULL;
01554                 }
01555             }
01556 
01557             // con << sn_SyncRequestedObject.Len() << "/" << sn_netObjects.Len() << "\n";
01558 
01559             int currentSync = sn_SyncRequestedObject.Len()-1;
01560             while (sn_Connections[user].socket>0 &&
01561                     sn_Connections[user].bandwidthControl_.CanSend() &&
01562                     sn_Connections[user].ackPending<sn_maxNoAck &&
01563                     currentSync >= 0){
01564                 nNetObject *nos = sn_SyncRequestedObject( currentSync );
01565 
01566                 if (nos && nos->ClearToTransmit(user) && ( nos == sn_netObjects( nos->id ) )
01567                         && (sn_GetNetState()!=nCLIENT ||
01568                             nos->AcceptClientSync()))
01569                 {
01570                     short s = nos->id;
01571 
01572                     if (// nos->knowsAbout[user].syncReq &&
01573                         !nos->knowsAbout[user].knowsAboutExistence)
01574                     {
01575                         if (!nos->knowsAbout[user].acksPending){
01576 #ifdef DEBUG
01577                             //con << "remotely creating object " << s << '\n';
01578 #endif
01579                             /*
01580                               con << "creating object " << s << " at user " << user
01581                               << " owned by " << sn_netObjects(s)->owner << '\n';
01582                             */
01583                             // send a creation message
01584 
01585                             tJUST_CONTROLLED_PTR< nMessage > m=new nMessage
01586                                                                (nos->CreatorDescriptor());
01587 
01588 #ifdef DEBUG
01589                             if (s == sn_WatchNetID)
01590                                 sn_WatchMessage = m;
01591 #endif
01592 
01593                             nos->WriteAll(*m,true);
01594                             new nWaitForAckSync(m,user,s);
01595                             unsigned long id = m->MessageIDBig();
01596                             m->SendImmediately(user, false);
01597                             m->messageIDBig_ = id;
01598 
01599                             nos->knowsAbout[user].syncReq = false;
01600                         }
01601 #ifdef DEBUG
01602                         else if (DoDebugPrint())
01603                         {
01604                             tString s;
01605                             s << "Not remotely creating object ";
01606                             nos->PrintName(s);
01607                             s << " on user " << user << " again because there is an Ack pending.\n";
01608                             con << s;
01609                         }
01610 #endif
01611                     }
01612                     else if (nos->knowsAbout[user].syncReq
01613                              && sn_Connections[user].bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) >50
01614                              && nos->knowsAbout[user].acksPending<=1){
01615                         // send a sync
01616                         tJUST_CONTROLLED_PTR< nMessage > m = new nMessage(net_sync);
01617 
01618                         m->Write(s);
01619                         nos->WriteAll(*m,false);
01620                         nos->knowsAbout[user].syncReq=false;
01621 
01622                         if (nos->knowsAbout[user].nextSyncAck){
01623                             new nWaitForAckSync(m,user,s);
01624                             nos->knowsAbout[user].nextSyncAck=false;
01625                         }
01626 #ifndef nSIMULATE_PING
01627                         unsigned long id = m->MessageIDBig();
01628                         //m->Send(user,0,false);
01629                         m->SendImmediately(user,false);
01630                         m->messageIDBig_ = id;
01631 #endif
01632                     }
01633 
01634                 }
01635 
01636                 currentSync--;
01637             }
01638 
01639             sn_syncedUser = -1;
01640 
01641 #ifdef DEBUG
01642             bool inc=false;
01643             static int warn=0;
01644             static int nextWarnOverflow=0;
01645             static int nextWarnAck=0;
01646             if (sn_Connections[user].bandwidthControl_.Control( nBandwidthControl::Usage_Planning )<-100){
01647                 if (warn>=nextWarnOverflow)
01648                 {
01649                     nextWarnOverflow = 2+(warn*17)/16;
01650                     con << "Warning! Network overflow: "
01651                     << -100-sn_Connections[user].bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) << "\n";
01652                 }
01653                 inc=true;
01654             }
01655             if (sn_Connections[user].ackPending>=sn_maxNoAck){
01656                 if (warn>=nextWarnAck)
01657                 {
01658                     nextWarnAck = 2+(warn*17)/16;
01659                     std::cerr << "Warning! Too many acks pending: "
01660                     << sn_Connections[user].ackPending << "\n";
01661                 }
01662                 inc=true;
01663             }
01664             if (inc)
01665                 warn++;
01666 #endif
01667         }
01668 
01669 
01670     // clear out objects that no longer need to be in the list because
01671     // all requested syncs have been sent
01672     {
01673         for ( int currentSync = sn_SyncRequestedObject.Len()-1; currentSync >= 0; --currentSync ){
01674             nNetObject *nos = sn_SyncRequestedObject( currentSync );
01675 
01676             if ( nos )
01677             {
01678                 // check if nos can be removed from sync request list
01679                 bool canRemove = true;
01680 
01681                 // check if there is anything preventing the removal
01682                 if ( nos == sn_netObjects( nos->id ) )
01683                 {
01684                     int start = ( sn_GetNetState() == nSERVER ) ? MAXCLIENTS : 0;
01685                     int stop  = ( sn_GetNetState() == nSERVER ) ? 1 : 0;
01686                     for ( int i = start; i>=stop && canRemove; --i )
01687                     {
01688                         const nKnowsAboutInfo& knows = nos->knowsAbout[i];
01689                         if ( sn_Connections[i].socket && knows.syncReq )
01690                             canRemove = false;
01691                     }
01692                 }
01693                 if ( canRemove )
01694                     sn_SyncRequestedObject.Remove( nos, nos->syncListID_ );
01695             }
01696         }
01697     }
01698 }
01699 
01700 
01701 static void ready_handler(nMessage &m)
01702 {
01703     is_ready_to_get_objects[m.SenderID()]=true;
01704 
01705     // reset peer's ping, it's probably unreliable
01706     sn_Connections[m.SenderID()].ping.Timestep(100);
01707 }
01708 
01709 static nDescriptor ready(25,ready_handler,"ready to get objects");
01710 
01711 
01712 static void net_clear_handler(nMessage &m){
01713     if (sn_GetNetState()!=nSERVER){
01714         nNetObject::ClearAll();
01715         first_fill_ids();
01716     }
01717 }
01718 
01719 static nDescriptor net_clear(26,net_clear_handler,"net_clear");
01720 
01721 
01722 void nNetObject::ClearAllDeleted()
01723 {
01724     // forget about objects that were deleted in the past. The swap trick is to
01725     // avoid that the objects try to remove themselves from the list while it is cleared.
01726     nDeletedInfos swap;
01727     swap.swap( sn_netObjectsDeleted );
01728     swap.clear();
01729 
01730     // send out object deletion messages
01731     for ( int i = MAXCLIENTS;i>=0;i--)
01732     {
01733         if ( sn_Connections[i].socket && destroyers[i] )
01734         {
01735             destroyers[i]->Send(i);
01736             destroyers[i] = NULL;
01737         }
01738     }
01739 }
01740 
01741 void nNetObject::ClearAll(){
01742     ClearAllDeleted();
01743     sn_freedIDs.clear();
01744 
01745     //con << "WARNING! BAD DESIGN. nNetObject::clear all() called.\n";
01746     int i;
01747     for (i=sn_netObjects.Len()-1;i>=0;i--)
01748         if (tJUST_CONTROLLED_PTR< nNetObject > no=sn_netObjects(i)){
01749             sn_netObjects(i)=NULL;
01750             sn_netObjectsOwner(i)=0;
01751             no->id = 0;
01752         }
01753     sn_netObjects.SetLen(0);
01754     sn_netObjectsOwner.SetLen(0);
01755 
01756     for (i=sn_SyncRequestedObject.Len()-1;i>=0;i--)
01757     {
01758         nNetObject * n = sn_SyncRequestedObject[i];
01759         tASSERT(n);
01760         sn_SyncRequestedObject.Remove( n, n->syncListID_ );
01761     }
01762 
01763     (tNEW(nMessage)(net_clear))->BroadCast(); // just to make sure..
01764 }
01765 
01766 
01767 void nNetObject::ClearKnows(int user, bool clear){
01768     if (0<=user && user <=MAXCLIENTS){
01769         is_ready_to_get_objects[user]=false;
01770         for (int i=sn_netObjects.Len()-1;i>=0;i--){
01771             nNetObject *no=sn_netObjects(i);
01772             if (no){
01773                 no->knowsAbout[user].Reset();
01774 
01775                 no->DoBroadcastExistence();  // immediately transfer the thing
01776 
01777                 if (clear){
01778                     if (no->owner==user && user!=sn_myNetID){
01779                         if (no->ActionOnQuit())
01780                             sn_netObjects(i)=NULL; // destroy it
01781                         else{
01782                             no->owner=::sn_myNetID; // or make it mine.
01783                             sn_netObjectsOwner(i)=::sn_myNetID;
01784                             if (no->AcceptClientSync()){
01785                                 tControlledPTR< nNetObject > bounce( no ); // destroy it, if noone wants it
01786                             }
01787                         }
01788                     }
01789                 }
01790             }
01791         }
01792     }
01793 }
01794 
01795 void ClearKnows(int user, bool clear){
01796     nNetObject::ClearKnows(user, clear);
01797 
01798     if (clear)
01799         for (int i=sn_netObjectsOwner.Len()-1;i>=0;i--){
01800             if (sn_netObjectsOwner(i)==user)
01801                 sn_netObjectsOwner(i)=0;
01802         }
01803 }
01804 
01805 
01806 /* If we switch from standalone to client mode, all the sn_netObjects
01807  * need new id's.
01808  */
01809 
01810 
01811 void nNetObject::RelabelOnConnect(){
01812     if (sn_GetNetState()==nCLIENT){
01813         tArray<tJUST_CONTROLLED_PTR<nNetObject> > sn_netObjects_old;
01814 
01815         // transfer the sn_netObjects to sn_netObjects_old:
01816         int i;
01817         for (i=sn_netObjects.Len()-1;i>=0;i--){
01818             sn_netObjects_old[i]=sn_netObjects(i);
01819             sn_netObjects(i)=NULL;
01820             sn_netObjectsOwner[i]=0;
01821         }
01822 
01823         // assign new id's and transfer them back to sn_netObjects:
01824         for (i=sn_netObjects_old.Len()-1;i>=0;i--){
01825             nNetObject *no = sn_netObjects_old(i);
01826             if (no){
01827                 unsigned short id=next_free();
01828 
01829 #ifdef DEBUG
01830                 sn_BreakOnObjectID( id );
01831 #endif
01832 
01833 #ifdef DEBUG
01834                 //con << "object " <<i << " gets new id " << id << '\n';
01835 #endif
01836                 no->id=id;
01837                 no->owner=::sn_myNetID;
01838                 sn_netObjectsOwner[id]=::sn_myNetID;
01839                 for (int j=MAXCLIENTS;j>=0;j--){
01840                     no->knowsAbout[j].Reset();
01841                     no->DoBroadcastExistence();
01842                 }
01843 
01844                 if (sn_netObjects[id])
01845                     st_Breakpoint();
01846 
01847                 sn_netObjects[id]=no;
01848                 sn_netObjects_old(i)=NULL;
01849             }
01850         }
01851     }
01852     (new nMessage(ready))->Send(0);
01853     is_ready_to_get_objects[0]=true;
01854 }
01855 
01856 
01857 static void login_callback(){
01858     int user = nCallbackLoginLogout::User();
01859     ClearKnows( user, !nCallbackLoginLogout::Login() );
01860 
01861     if ( user == 0 )
01862     {
01863         if (nCallbackLoginLogout::Login())
01864             nNetObject::RelabelOnConnect();
01865         else
01866         {
01867             sn_Destroyed.SetLen(0);
01868             sn_LocallyDestroyedIDs.clear();
01869         }
01870     }
01871 
01872     // send and delete the  remaining destroyer message
01873     if ( destroyers[user] )
01874     {
01875         destroyers[user]->Send(user);
01876         destroyers[user]=NULL;
01877     }
01878 }
01879 
01880 static nCallbackLoginLogout nlc(&login_callback);
01881 
01882 
01883 static bool sync_ack[MAXCLIENTS+2];
01884 static unsigned short c_sync=0;
01885 
01886 static void sync_ack_handler(nMessage &m){
01887     unsigned short id;
01888     m.Read(id);
01889     if (id==c_sync)
01890         sync_ack[m.SenderID()]=true;
01891 }
01892 
01893 static nDescriptor sync_ack_nd(27,sync_ack_handler,"sync_ack");
01894 
01895 
01896 static void sync_msg_handler(nMessage &m);
01897 static nDescriptor sync_nd(28,sync_msg_handler,"sync_msg");
01898 
01899 // from nNetwork.C
01900 
01901 void sn_Sync(REAL timeout,bool sync_sn_netObjects, bool otherEnd){
01902     nTimeAbsolute endTime=timeout+tSysTimeFloat();
01903 
01904 #ifdef DEBUG
01905     //con << "Start sync...\n";
01906 #endif
01907 
01908     if (sn_GetNetState()==nCLIENT){
01909         // repeat as often as packet loss suggests: of 100 packets, we want a single lost packet left probability of 1%.
01910         REAL failureProbability = 1;
01911         while ( failureProbability > .0001 && timeout > .01 )
01912         {
01913             failureProbability *= sn_Connections[0].PacketLoss();
01914             // con << failureProbability << "\n";
01915 
01916             // server responding to sync request message
01917             static nVersionFeature sg_ServerSync( 10 );
01918 
01919             // ask server when we're fully synced from his side
01920             sync_ack[0]=true;
01921             if ( sg_ServerSync.Supported( 0 ) && otherEnd )
01922             {
01923                 tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(sync_nd);
01924                 *m << timeout;
01925                 m->Write(sync_sn_netObjects);
01926                 m->Write(c_sync);
01927                 m->Send(0);
01928                 sync_ack[0]=false;
01929             }
01930             else
01931             {
01932                 // repeating the procedure is useless anyway
01933                 failureProbability = 0;
01934             }
01935 
01936             // wait for all packets to be sent and the sync ack packet to be received
01937             while ( sn_Connections[0].socket && ( sync_ack[0] == false || sn_Connections[0].ackPending>0 || sn_QueueLen(0)) &&
01938                     tSysTimeFloat()<endTime){
01939                 sn_Delay();
01940                 sn_Receive();
01941                 if (sync_sn_netObjects)
01942                     nNetObject::SyncAll();
01943                 sn_SendPlanned();
01944             }
01945 
01946             // decrease timeout for next try
01947             timeout *= .5;
01948             endTime=timeout+tSysTimeFloat();
01949         }
01950     }
01951     else if (sn_GetNetState()==nSERVER){
01952         for (int user=MAXCLIENTS;user>0;user--){
01953             sync_ack[user]=false;
01954             if (sn_Connections[user].socket){
01955                 tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(sync_nd);
01956                 *m << timeout;
01957                 m->Write(sync_sn_netObjects);
01958                 m->Write(c_sync);
01959                 m->Send(user);
01960             }
01961         }
01962 
01963         bool goon=true;
01964         while (goon){
01965             sn_Delay();
01966             sn_Receive();
01967             if (sync_sn_netObjects)
01968                 nNetObject::SyncAll();
01969             sn_SendPlanned();
01970 
01971             goon=false;
01972             for (int user=MAXCLIENTS;user>0;user--)
01973             {
01974                 if (sn_Connections[user].socket &&
01975                         (!sync_ack[user] || sn_Connections[user].ackPending>0 || sn_QueueLen(user)))
01976                 {
01977                     goon=true;
01978                 }
01979             }
01980 
01981             if (tSysTimeFloat()>endTime)
01982             {
01983                 goon=false;
01984             }
01985         }
01986     }
01987 
01988 #ifdef DEBUG
01989     //con << "Stop sync.\n";
01990 #endif
01991 }
01992 
01993 static void sync_msg_handler(nMessage &m){
01994     static bool recursion=false;
01995     if (!recursion){
01996         recursion=true;
01997 
01998         REAL timeout;
01999         unsigned short sync_sn_netObjects;
02000 
02001         // sync and write sync response
02002         m >> timeout;
02003         m.Read(sync_sn_netObjects);
02004         unsigned short c_sync;
02005         m.Read(c_sync);
02006 
02007         if (sn_GetNetState()!=nSERVER){
02008             sn_Sync(timeout+4,sync_sn_netObjects!=0,false);
02009             tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(sync_ack_nd);
02010             m->Write(c_sync);
02011             m->Send(0);
02012         }
02013         else
02014         {
02015             // no time for syncing! write sync response immediately with low priority so the client
02016             // gets it as soon as all other things are sent
02017             tJUST_CONTROLLED_PTR< nMessage > response=new nMessage(sync_ack_nd);
02018             response->Write(c_sync);
02019             response->Send(m.SenderID(),10000000);
02020         }
02021         recursion=false;
02022     }
02023 }
02024 
02025 void clear_owners(){
02026     sn_freedIDs.clear();
02027     for (int i=sn_netObjectsOwner.Len()-1;i>=0;i--)
02028         sn_netObjectsOwner(i)=0;
02029 }
02030 
02031 
02032 #include "nPriorizing.h"
02033 
02034 // *********************************************************
02035 // nBandwidthTaskSync/Create: object syncing bandwidth tasks
02036 // *********************************************************
02037 
02038 nBandwidthTaskObject::nBandwidthTaskObject( nType type, nNetObject& object )
02039         :nBandwidthTask( type ), object_( &object )
02040 {
02041 }
02042 
02043 nBandwidthTaskObject::~nBandwidthTaskObject()
02044 {
02045 
02046 }
02047 
02048 // estimate bandwidth usage
02049 int  nBandwidthTaskObject::DoEstimateSize() const
02050 {
02051     return 16;
02052 }
02053 
02054 // executes whatever it has to do
02055 void nBandwidthTaskSync::DoExecute( nSendBuffer& buffer, nBandwidthControl& control )
02056 {
02057     tJUST_CONTROLLED_PTR< nMessage > message = tNEW( nMessage )( net_sync );
02058     Object().WriteAll( *message, false );
02059     buffer.AddMessage( *message, &control );
02060 }
02061 
02062 // executes whatever it has to do
02063 void nBandwidthTaskCreate::DoExecute( nSendBuffer& buffer, nBandwidthControl& control )
02064 {
02065     tJUST_CONTROLLED_PTR< nMessage > message = tNEW( nMessage )( Object().CreatorDescriptor() );
02066     Object().WriteAll( *message, true );
02067 
02068     buffer.AddMessage( *message, &control );
02069 }
02070 
02071 
02072 // *******************************************************************************
02073 // *
02074 // *    DoGetMachine
02075 // *
02076 // *******************************************************************************
02080 // *******************************************************************************
02081 
02082 nMachine & nNetObject::DoGetMachine( void ) const
02083 {
02084     return nMachine::GetMachine( Owner() );
02085 }
02086 
02087 

Generated on Sat Mar 15 22:55:50 2008 for Armagetron Advanced by  doxygen 1.5.4