Index: trunk/src/lib/network/synchronizeable.cc
===================================================================
--- trunk/src/lib/network/synchronizeable.cc	(revision 9110)
+++ trunk/src/lib/network/synchronizeable.cc	(revision 9406)
@@ -11,6 +11,6 @@
 
 ### File Specific:
-   main-programmer: Silvan Nellen
-   co-programmer: Benjamin Wuest
+   main-programmer: Christoph Renner (rennerc@ee.ethz.ch)
+   co-programmer: Patrick Boenzli (patrick@orxonox.ethz.ch)
 */
 
@@ -29,4 +29,6 @@
 #include "synchronizeable.h"
 
+#include "converter.h"
+
 
 
@@ -38,9 +40,9 @@
   this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
   this->owner = 0;
-  this->setIsServer(SharedNetworkData::getInstance()->getHostID() == 0);
+//   this->setIsServer(SharedNetworkData::getInstance()->getHostID() == 0);
   this->uniqueID = NET_UID_UNASSIGNED;
   this->networkStream = NULL;
   this->bSynchronize = false;
-  
+
   if( State::isOnline())
   {
@@ -54,5 +56,5 @@
   assert( syncVarList.size() == 0 );
   mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId" ) );
-    
+
   this->registerVar( new SynchronizeableInt( &this->owner, &this->owner, "owner" ) );
   this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName" ) );
@@ -69,9 +71,10 @@
   {
     this->networkStream->disconnectSynchronizeable(*this);
-  
-    if ( this->isServer() && this->beSynchronized() && this->getUniqueID() > 0 && !this->isA( CL_MESSAGE_MANAGER ) )
+
+    if ( (SharedNetworkData::getInstance()->isMasterServer() || SharedNetworkData::getInstance()->isProxyServer() )
+           && this->beSynchronized() && this->getUniqueID() > 0 && !this->isA( CL_MESSAGE_MANAGER ) )
       NetworkGameManager::getInstance()->removeSynchronizeable( this->getUniqueID() );
   }
-    
+
   for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
   {
@@ -79,5 +82,5 @@
   }
   syncVarList.clear();
-  
+
   for ( UserStateHistory::iterator it = recvStates.begin(); it != recvStates.end(); it++ )
   {
@@ -93,5 +96,5 @@
 
   }
-  
+
   for ( UserStateHistory::iterator it = sentStates.begin(); it != sentStates.end(); it++ )
   {
@@ -105,32 +108,19 @@
       delete *it2;
     }
-
-  }
-}
-
-/**
- * Sets the server flag to a given value
- * @param isServer: the boolean value which the server flag is to set to
- */
-void Synchronizeable::setIsServer(bool isServer)
-{
-  if( isServer )
-    this->state = this->state | STATE_SERVER;
-  else
-    this->state = this->state & (~STATE_SERVER);
-}
-
-
-/**
- * Determines if the server flag is set
- * @return true, if the server flag is true, false else
- */
-bool Synchronizeable::isServer()
-{
-  return (this->state & STATE_SERVER) >0;
-}
-
-
-
+  }
+}
+
+
+
+/**
+ * creates a diff image from two states
+ * @param userId: the userid of the user where the image will be sent to
+ * @param data: the binary data array to write to
+ * @param maxLength: maximal length of the data written (length of available space in the array)
+ * @param stateId: the state id that this diff will represent
+ * @param priorityTH: the priority threshold: all syncs below this threshold won't be synchronized
+ *
+ * @todo check for permissions
+ */
 int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
 {
@@ -169,5 +159,5 @@
         (*it2)->data = NULL;
       }
-      
+
       delete *it2;
     }
@@ -181,9 +171,4 @@
   while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId )
     it++;
-  
-//  if ( getLeafClassID() == CL_SPACE_SHIP )
-//  {
-//    PRINTF(0)("getStateDiff:SpaceShip from: %d stateId: %d\n", (it == sentStates[userId].end())?-1:fromStateId, stateId);
-//  }
 
   if ( it == sentStates[userId].end() )
@@ -196,5 +181,5 @@
 
     stateFrom = initialEntry;
-    
+
     sentStates[userId].push_back( stateFrom );
   }
@@ -205,5 +190,5 @@
 
   sentStates[userId].push_back( stateTo );
-  
+
   stateTo->stateId = stateId;
   stateTo->dataLength = neededSize;
@@ -214,6 +199,6 @@
   int i = 0;
   int n;
-  
-  bool hasPermission;
+
+  bool hasPermission = false;
   bool sizeChanged = false;
 
@@ -221,20 +206,40 @@
   for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
   {
-    hasPermission = (
-            this->isServer() && (*it)->checkPermission( PERMISSION_SERVER ) ||
-        this->owner == SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ) ||
-            this->isServer() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ) ||
-            (*it)->checkPermission( PERMISSION_ALL ) 
-                    );
-    
-    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() ) 
+    // DATA PERMISSIONS
+    // check if this synchronizeable has the permissions to write the data
+
+    // first check MASTER_SERVER permissions
+    if( SharedNetworkData::getInstance()->isMasterServer() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
+      hasPermission = true;
+    // now check PROXY_SERVER permissions
+    else if( SharedNetworkData::getInstance()->isProxyServer() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
+      hasPermission = true;
+    // now check OWNER permissions
+    else if( this->owner == SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    // now check ALL permissions
+    else if( (*it)->checkPermission( PERMISSION_ALL ))
+      hasPermission = true;
+    // SPECIAL: get write permissions if i am master server and i am able to overwrite the client stuff
+    else if( SharedNetworkData::getInstance()->isMasterServer() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    // SPECIAL: get write permissions if i am proxy server and i am able to overwrite the client stuff
+    else if( SharedNetworkData::getInstance()->isProxyServer()  && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    else
+      hasPermission = false;
+
+
+    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() )
       sizeChanged = true;
-    
+
     if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeChanged )
     {
       n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
       //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
+      //PRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
       stateTo->sizeList.push_back( n );
-      //(*it)->debug();
+      // this is only for very hardcore debug sessions
+      // (*it)->debug();
       i += n;
     }
@@ -257,5 +262,5 @@
   if ( i != neededSize )
   {
-    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassName(), i, neededSize);
+    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassCName(), i, neededSize);
     assert(false);
   }
@@ -281,4 +286,5 @@
  * @param fromStateId id of the base state id
  * @return number bytes read
+ *
  * @todo check for permissions
  */
@@ -299,14 +305,10 @@
   StateHistoryEntry * stateFrom = NULL;
 
+  // search the state from wich the diff is made of
   StateHistory::iterator it = recvStates[userId].begin();
   while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
     it++;
 
-  
-//  if ( getLeafClassID() == CL_SPACE_SHIP )
-//  {
-//    PRINTF(0)("setStateDiff:SpaceShip from: %d stateId: %d\n", (it == recvStates[userId].end())?-1:fromStateId, stateId);
-//  }
-
+  // if this is the first state to receive
   if ( it == recvStates[userId].end() )
   {
@@ -318,11 +320,12 @@
 
     stateFrom = initialEntry;
-    
+
     recvStates[userId].push_back( stateFrom );
   }
   else
     stateFrom = (*it);
-  
-  //apply diff
+
+
+  // apply diff
   for ( int i = 0; i<length; i++ )
   {
@@ -331,26 +334,50 @@
     else
       stateTo->data[i] = data[i];
-    
-  }
-  
+  }
+
   //add state to state history
   recvStates[userId].push_back( stateTo );
-  
+
   int i = 0;
   int n = 0;
   std::list<int> changes;
-  
+  bool hasPermission = false;
+
+  // extract the new state for every client
   for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
   {
-    if (
-        (*it)->checkPermission( PERMISSION_SERVER ) && networkStream->isUserServer( userId ) ||
-        (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId ||
-        networkStream->isUserServer( userId ) && this->owner != SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ) ||
-        (*it)->checkPermission( PERMISSION_ALL ) 
-       )
+    // DATA PERMISSIONS
+    // check if this synchronizeable has the permissions to write the data
+
+    // first check MASTER_SERVER permissions
+    if(  this->networkStream->isUserMasterServer( userId ) && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
+      hasPermission = true;
+    // now check PROXY_SERVER permissions
+    else if( this->networkStream->isUserProxyServer( userId )  && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
+      hasPermission = true;
+    // now check OWNER permissions
+    else if( this->owner == userId && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    // now check ALL permissions
+    else if( (*it)->checkPermission( PERMISSION_ALL ))
+      hasPermission = true;
+    // SPECIAL: get write permissions if im sending to a master server that does not own this sync
+    else if( this->networkStream->isUserMasterServer( userId ) && this->owner != SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    // SPECIAL: get write permissions if im sending to a proxy server that does not own this sync
+    else if( this->networkStream->isUserProxyServer( userId )  && this->owner != SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
+      hasPermission = true;
+    else
+      hasPermission = false;
+
+
+
+    // if it has the permission to write do it
+    if( hasPermission)
     {
       n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
       i += n;
-      //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n);
+      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
+      //PRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
       //(*it)->debug();
       if ( (*it)->getHasChanged() )
@@ -361,7 +388,7 @@
     else
     {
-//      PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s %d %d %d %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserServer( userId ), this->owner, userId );
+//      PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s %d %d %d %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_MASTER_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserServer( userId ), this->owner, userId );
       n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
-      //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n);
+      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
       //(*it)->debug();
       i += n;
@@ -370,5 +397,5 @@
 
   this->varChangeHandler( changes );
-  
+
   return i;
 }
@@ -423,13 +450,13 @@
         (*it)->data = NULL;
       }
-    
+
       delete *it;
     }
     recvStates[userId].clear();
   }
- 
+
   if ( sentStates.size() > userId )
   {
-    
+
     for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
     {
@@ -439,5 +466,5 @@
         (*it)->data = NULL;
       }
-    
+
       delete *it;
     }
@@ -448,7 +475,7 @@
 /**
  * this function is called after recieving a state.
- * @param userId 
- * @param stateId 
- * @param fromStateId 
+ * @param userId
+ * @param stateId
+ * @param fromStateId
  */
 void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
@@ -457,5 +484,5 @@
   if ( recvStates.size() <= userId )
     recvStates.resize( userId+1 );
-  
+
   //remove old states
   StateHistory::iterator it = recvStates[userId].begin();
@@ -485,5 +512,5 @@
       StateHistory::iterator delIt = it;
       it ++;
-      
+
       if ( (*delIt)->data )
       {
@@ -493,13 +520,13 @@
       delete *delIt;
       recvStates[userId].erase( delIt );
-      
+
       continue;
     }
     it++;
   }
-  
+
   StateHistory::iterator fromState = recvStates[userId].end();
   StateHistory::iterator toState = recvStates[userId].end();
-  
+
   for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
   {
@@ -508,19 +535,19 @@
     if ( (*it)->stateId == fromStateId )
       fromState = it;
-    
+
     if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
       break;
   }
-  
+
   // setStateDiff was not called and i know fromStateId
   if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
   {
     StateHistoryEntry * entry = new StateHistoryEntry;
-    
+
     entry->dataLength = (*fromState)->dataLength;
     if ( entry->dataLength > 0 )
     {
       entry->data = new byte[entry->dataLength];
-          
+
       assert( (*fromState)->data );
       memcpy( entry->data, (*fromState)->data, entry->dataLength );
@@ -528,8 +555,8 @@
     else
       entry->data = NULL;
-    
+
     entry->sizeList = (*fromState)->sizeList;
     entry->stateId = stateId;
-    
+
     recvStates[userId].push_back(entry);
   }
@@ -538,7 +565,7 @@
 /**
  * this function is called after sending a state
- * @param userId 
- * @param stateId 
- * @param fromStateId 
+ * @param userId
+ * @param stateId
+ * @param fromStateId
  */
 void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
@@ -557,5 +584,5 @@
       StateHistory::iterator delIt = it;
       it ++;
-      
+
       if ( (*delIt)->data )
       {
@@ -565,5 +592,5 @@
       delete *delIt;
       sentStates[userId].erase( delIt );
-      
+
       continue;
     }
@@ -571,8 +598,8 @@
   }
 
-  
+
   StateHistory::iterator fromState = sentStates[userId].end();
   StateHistory::iterator toState = sentStates[userId].end();
-  
+
   for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
   {
@@ -581,20 +608,20 @@
     if ( (*it)->stateId == fromStateId )
       fromState = it;
-    
+
     if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
       break;
   }
 
-  
+
   // getStateDiff was not called and i know fromStateId
   if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
   {
     StateHistoryEntry * entry = new StateHistoryEntry;
-    
+
     entry->dataLength = (*fromState)->dataLength;
     if ( entry->dataLength > 0 )
     {
       entry->data = new byte[entry->dataLength];
-      
+
       assert( (*fromState)->data );
       memcpy( entry->data, (*fromState)->data, entry->dataLength );
@@ -602,13 +629,13 @@
     else
       entry->data = NULL;
-    
+
     entry->sizeList = (*fromState)->sizeList;
     entry->stateId = stateId;
-    
+
     sentStates[userId].push_back(entry);
   }
-  
-}
-
-
-
+
+}
+
+
+
