Index: fg_server.cpp
===================================================================
RCS file: /home/cvs/anders/FlightGear/fgmp/fg_server/src/fg_server.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.5
diff -u -8 -r1.1.1.1 -r1.5
--- fg_server.cpp	29 Apr 2007 17:01:22 -0000	1.1.1.1
+++ fg_server.cpp	29 Apr 2007 20:43:38 -0000	1.5
@@ -309,16 +309,17 @@
         NewPlayer.ModelName     = "* unknown *";
         NewPlayer.Timestamp     = time(0);
         NewPlayer.Origin        = Sender.getHost ();
         NewPlayer.Address       = Sender;
         NewPlayer.IsLocal       = IsLocal;
         NewPlayer.HasErrors     = true;
         NewPlayer.Error         = ErrorMsg;
         NewPlayer.ClientID      = m_MaxClientID;
+	NewPlayer.LastRelayedToInactive = 0;
         AlreadyThere            = false;
         CurrentPlayer           = m_PlayerList.begin();
         //////////////////////////////////////////////////
         //      see, if we already know the client
         //////////////////////////////////////////////////
         while (CurrentPlayer != m_PlayerList.end())
         {
                 if (CurrentPlayer->Address.getIP() == Sender.getIP())
@@ -371,16 +372,17 @@
         NewPlayer.ModelName     = "* unknown *";
         NewPlayer.Timestamp     = Timestamp;
         NewPlayer.Origin        = Sender.getHost ();
         NewPlayer.HasErrors     = false;
         NewPlayer.Address       = Sender;
         NewPlayer.IsLocal       = IsLocal;
         NewPlayer.LastPos.clear();
         NewPlayer.LastOrientation.clear();
+	NewPlayer.LastRelayedToInactive = 0;
         if (MsgId == CHAT_MSG_ID)
         {       // don't add to local list
                 return;
         }
         if (MsgId == POS_DATA_ID) 
         {
                 NewPlayer.LastPos.Set (
                   XDR_decode_double (PosMsg->position[X]),
@@ -406,16 +408,17 @@
                 m_Log.log (L_HIGH) << "New REMOTE Client: ";
         m_Log.setflags (LOGOBJECT::NODATE);
         if (IsLocal)
         {
                 Message  = "Welcome to ";
                 Message += m_ServerName;
                 CreateChatMessage (NewPlayer.ClientID , Message);
                 Message = "this is version v" + string(VERSION);
+		Message += " (Experimental features: LazyRelay)";
                 CreateChatMessage (NewPlayer.ClientID , Message);
                 Message  ="using protocol version v";
                 Message += NumToStr (m_ProtoMajorVersion, 0);
                 Message += "." + NumToStr (m_ProtoMinorVersion, 0);
                 CreateChatMessage (NewPlayer.ClientID , Message);
         }
         Message  = NewPlayer.Callsign;
         Message += " is now online, using ";
@@ -438,31 +441,34 @@
 //////////////////////////////////////////////////////////////////////
 void
 FG_SERVER::AddRelay ( const string & Server, int Port )
 {
         mT_Relay        NewRelay;
 
         NewRelay.Name = Server;
         NewRelay.Address.set ((char*) Server.c_str(), Port);
+	NewRelay.Timestamp = time(0);
+	NewRelay.Active = false;
         m_RelayList.push_back (NewRelay);
 } // FG_SERVER::AddRelay()
 //////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////////////////
 //
 //      clean up player list
 //      check for expired players
 //
 //////////////////////////////////////////////////////////////////////
 void
 FG_SERVER::CleanUp ()
 {
         time_t          Timestamp;
         mT_PlayerListIt CurrentPlayer;
+	mT_RelayListIt  CurrentRelay;
 
         Timestamp = time(0);
         CurrentPlayer = m_PlayerList.begin();
         while (CurrentPlayer != m_PlayerList.end())
         {
                 if ((Timestamp-CurrentPlayer->Timestamp) > PLAYER_TTL)
                 {
                         m_Log.log (L_HIGH)
@@ -481,16 +487,27 @@
                         }
                         mT_PlayerListIt P;
                         P = CurrentPlayer;
                         CurrentPlayer = m_PlayerList.erase (P);
                         continue;
                 }
                 CurrentPlayer++;
         }
+        CurrentRelay = m_RelayList.begin();
+        while (CurrentRelay != m_RelayList.end())
+        {
+               if (((Timestamp-CurrentRelay->Timestamp) > RELAY_TTL) && CurrentRelay->Active)
+                {
+                       CurrentRelay->Active = false;
+                       m_Log.log (L_HIGH) << "Deactivating relay " << CurrentRelay->Name << endl;
+               }
+               CurrentRelay++;
+       }
+        
 } // FG_SERVER::CleanUp ()
 //////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////////////////
 //
 //  create a chat message and put it into the internal message queue
 //
 //////////////////////////////////////////////////////////////////////
@@ -543,18 +560,20 @@
         uint32_t                MsgMagic;
         time_t                  Timestamp;
         bool                    PlayerInList;
         bool                    PacketFromLocalClient;
         string                  ErrorMsg;
         Point3D                 SenderPosition;
         Point3D                 SenderOrientation;
         mT_PlayerListIt         CurrentPlayer;
+        mT_PlayerListIt         SendingPlayer;
         mT_RelayListIt          CurrentRelay;
         mT_MessageIt            CurrentMessage;
+	bool                    HasLocalClients;
 
         MsgHdr = (T_MsgHdr *) Msg;
         Timestamp = time(0);
         PacketFromLocalClient = true;  // assume client to be local
         //////////////////////////////////////////////////
         //
         //      check if the received packet is valid
         //
@@ -620,19 +639,23 @@
         //
         //      check for senders position
         //      we have to walk through to list until
         //      we find the sender, so we walk to list
         //      twice. FIXME: can be done better?
         //
         //////////////////////////////////////////////////
         PlayerInList = false;
+	HasLocalClients = false;
         CurrentPlayer = m_PlayerList.begin();
         while ((CurrentPlayer != m_PlayerList.end()) && (PlayerInList == false))
         {
+               if (CurrentPlayer->IsLocal) {
+                       HasLocalClients = true;
+               }
                 if ((CurrentPlayer->Callsign == MsgHdr->Callsign)
                 && (CurrentPlayer->Address.getIP() == SenderAddress.getIP()))
                 {
                         PlayerInList = true;
                         CurrentPlayer->Timestamp = Timestamp;
                         if (MsgId == POS_DATA_ID)
                         {
                                 PosMsg =
@@ -655,17 +678,29 @@
                                 SenderOrientation = 
                                   CurrentPlayer->LastOrientation;
                         }
                 }
                 CurrentPlayer++;
         }
         if (PlayerInList == false)
         {
-                AddClient (SenderAddress, Msg, PacketFromLocalClient);
+		AddClient (SenderAddress, Msg, PacketFromLocalClient);
+		if (!HasLocalClients && PacketFromLocalClient) {
+                        // Optimisticall activate all relays to make sure
+			// that the system does not become partitioned.
+                        mT_RelayListIt CurrentRelay = m_RelayList.begin();
+                        while (CurrentRelay != m_RelayList.end())
+                        {
+                               	CurrentRelay->Active = true;
+                               	CurrentRelay->Timestamp = Timestamp;    
+                               	m_Log.log (L_HIGH) << "Optimistically activating relay " << CurrentRelay->Name  << endl;
+                               	CurrentRelay++;
+                        }
+                }
         }
         //////////////////////////////////////////
         //
         //      send the packet back to all clients.
         //      since we are walking through the list,
         //      we look for the sending client, too. if it
         //      is not already there, add it to the list
         //
@@ -711,16 +746,17 @@
                 //////////////////////////////////////////////////
                 //  FIXME: if Sender is an Relay,
                 //               CurrentPlayer->lRealAddress will be
                 //               address of Relay and not the client's!
                 //               so use a clientID instead
                 if ((CurrentPlayer->Callsign == MsgHdr->Callsign)
                 && (CurrentPlayer->Address.getIP() == SenderAddress.getIP()))
                 {
+			SendingPlayer = CurrentPlayer;
                         CurrentPlayer++;
                         continue; // don't send packet back to sender
                 }
                 //////////////////////////////////////////////////
                 //        Drop CurrentPlayer if last sign of
                 //        life is older then TTL
                 //////////////////////////////////////////////////
                 if ((Timestamp-CurrentPlayer->Timestamp) > PLAYER_TTL)
@@ -805,66 +841,90 @@
         //        send packet to all Relays,
         //        change Magic to RELAY_MAGIC, so the
         //        receiving Relay will not resend
         //        packets back for this client.
         //        do not send to oberserver, if origin is
         //        a Relay
         //
         //////////////////////////////////////////////////
+	bool UpdateInactive = Timestamp-SendingPlayer->LastRelayedToInactive > UPDATE_INACTIVE_PERIOD;
+	if (UpdateInactive) {
+		SendingPlayer->LastRelayedToInactive = Timestamp;
+	}
         if (PacketFromLocalClient)
         {
                 MsgHdr->Magic = XDR_encode_uint32 (RELAY_MAGIC);
                 CurrentRelay = m_RelayList.begin();
                 while (CurrentRelay != m_RelayList.end())
                 {
-                        m_DataSocket->sendto(Msg, Bytes, 0,
-                          &CurrentRelay->Address);
-                        CurrentRelay++;
-                }
+                       	if (CurrentRelay->Active || UpdateInactive) {   
+                               	m_DataSocket->sendto(Msg, Bytes, 0, &CurrentRelay->Address);
+                       	}
+                	CurrentRelay++;
+               }
+        } else {
+               // Renew timestamp of sending relay.
+               mT_RelayListIt CurrentRelay = m_RelayList.begin();
+               while (CurrentRelay != m_RelayList.end())
+               {
+                       if (CurrentRelay->Address.getIP() == SenderAddress.getIP()) {
+                               if (!CurrentRelay->Active) {
+                                       m_Log.log (L_HIGH) << "Activating relay " << CurrentRelay->Name  << endl;
+                                       CurrentRelay->Active = true;
+                               }
+                               CurrentRelay->Timestamp = Timestamp;
+                               break;
+                       }
+                       CurrentRelay++;
+           	}
         }
 } // FG_SERVER::HandlePacket ( char* sMsg[MAX_PACKET_SIZE] )
 //////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////////////////
 //
 //      main loop of the server
 //
 //////////////////////////////////////////////////////////////////////
 int
 FG_SERVER::Loop ()
 {
         int             Bytes;
         char            Msg[MAX_PACKET_SIZE];
         netAddress      SenderAddress;
         netSocket*      ListenSockets[3 + MAX_TELNETS];
+	time_t          CurrentTime, LastCleanUp;
 
         m_IsParent = true;
         if (m_Listening == false)
         {
                 m_Log.log (L_ERROR) << "FG_SERVER::Loop() - "
                   << "not listening on any socket!" << endl;
                 return (ERROR_NOT_LISTENING);
         }
         //////////////////////////////////////////////////
         //
         //      infinite listening loop
         //
         //////////////////////////////////////////////////
         CreateChatMessage (0, string("server ")+m_ServerName+string(" is online"));
+	LastCleanUp = time(0);
         for (;;)
         {
+		CurrentTime = time(0);
                 errno = 0;
                 ListenSockets[0] = m_DataSocket;
                 ListenSockets[1] = m_TelnetSocket;
                 ListenSockets[2] = 0;
                 Bytes = m_DataSocket->select (ListenSockets,0,m_PlayerExpires);
                 if (Bytes == -2)
                 {       // timeout, no packets received
                         CleanUp ();
+			LastCleanUp = CurrentTime;
                         continue;
                 }
                 if (! Bytes)
                 {
                         m_Log.log (L_ERROR) << "FG_SERVER::Loop() - "
                           << "Bytes <= 0!" << endl;
                         continue;
                 }
@@ -881,18 +941,25 @@
                                 // FIXME: reason to quit?
                                 continue;
                         }
                         HandlePacket ((char*)&Msg,Bytes,SenderAddress);
                 } // DataSocket
                 else if (ListenSockets[1] != 0)
                 {       // something on the wire (telnet)
                         HandleTelnet (m_TelnetSocket);
+			LastCleanUp = CurrentTime;
                         CleanUp ();
                 } // TelnetSocket
+               
+               // Do periodic CleanUp.
+               if ((CurrentTime-LastCleanUp > PLAYER_TTL) || (CurrentTime-LastCleanUp > RELAY_TTL)) {
+                       CleanUp ();
+                       LastCleanUp = CurrentTime;
+               }
         }
 } // FG_SERVER::Loop()
 //////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////////////////
 //
 //      set listening port for incoming clients
 //
Index: fg_server.hpp
===================================================================
RCS file: /home/cvs/anders/FlightGear/fgmp/fg_server/src/fg_server.hpp,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -8 -r1.1.1.1 -r1.3
--- fg_server.hpp	29 Apr 2007 17:01:22 -0000	1.1.1.1
+++ fg_server.hpp	29 Apr 2007 20:11:55 -0000	1.3
@@ -14,17 +14,21 @@
 
 #include <iostream>
 #include <fstream>
 #include <list>
 #include <string>
 #include <string.h>
 #include <errno.h>
 #include <time.h>
+#ifdef __sparc
+#include <sys/int_types.h>
+#else
 #include <stdint.h>
+#endif
 #include <unistd.h>
 #include "netSocket.h"
 #include "logobject.hpp"
 #include "daemon.hpp"
 #include "fg_geometry.hpp"
 #include "mpmessages.hxx"
 #include "tiny_xdr.hxx"
 
@@ -48,16 +52,18 @@
 		ERROR_COMMANDLINE	= 1,
 		ERROR_CREATE_SOCKET	= 2,
 		ERROR_COULDNT_BIND	= 3,
 		ERROR_NOT_LISTENING	= 4,
 		ERROR_COULDNT_LISTEN	= 5,
 		// other constants
 		MAX_PACKET_SIZE		= 1024,
 		PLAYER_TTL		= 10,
+		RELAY_TTL               = 10,
+		UPDATE_INACTIVE_PERIOD  = 1,
 		MAX_TELNETS		= 5,
 		RELAY_MAGIC		= 0x53464746    // GSGF
 	};
 	//////////////////////////////////////////////////
 	//
 	//	constructors
 	//
 	//////////////////////////////////////////////////
@@ -98,28 +104,31 @@
 		string		ModelName;
 		time_t		Timestamp;
 		Point3D		LastPos;
 		Point3D		LastOrientation;
 		bool		IsLocal;
 		string		Error;		// in case of errors
 		bool		HasErrors;
 		int		ClientID;
+		time_t		LastRelayedToInactive;
 	}; // mT_Player
 
 	//////////////////////////////////////////////////
 	//
 	//  type of list of relays
 	//  
 	//////////////////////////////////////////////////
 	class mT_Relay
 	{
 	public:
 		string		Name;
 		netAddress	Address;
+		time_t          Timestamp;
+		bool            Active;
 	};
 	//////////////////////////////////////////////////
 	//
 	//	chat messages from server to clients
 	//	
 	//////////////////////////////////////////////////
 	class mT_ChatMsg
 	{
Index: main.cpp
===================================================================
RCS file: /home/cvs/anders/FlightGear/fgmp/fg_server/src/main.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -8 -r1.1.1.1 -r1.2
--- main.cpp	29 Apr 2007 17:01:22 -0000	1.1.1.1
+++ main.cpp	29 Apr 2007 17:41:28 -0000	1.2
@@ -1,11 +1,14 @@
 using namespace std;
 
 #include <cstdlib>
+#ifdef __sparc
+#include <signal.h>
+#endif
 #include "fg_server.hpp"
 #include "fg_config.hpp"
 #include "daemon.hpp"
 #include "typcnvt.hpp"
 
 FG_SERVER       Servant;
 extern	bool    RunAsDaemon;
 extern	cDaemon Myself;
Index: tiny_xdr.hxx
===================================================================
RCS file: /home/cvs/anders/FlightGear/fgmp/fg_server/src/tiny_xdr.hxx,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -8 -r1.1.1.1 -r1.2
--- tiny_xdr.hxx	29 Apr 2007 17:01:22 -0000	1.1.1.1
+++ tiny_xdr.hxx	29 Apr 2007 17:41:28 -0000	1.2
@@ -14,25 +14,27 @@
 #ifndef TINY_XDR_HEADER
 #define TINY_XDR_HEADER
 
 #ifdef HAVE_CONFIG_H
 #   include <config.h>
 #endif
 #ifdef HAVE_STDINT_H
 #   include <stdint.h>
-#elif defined( _MSC_VER ) || defined(__MINGW32__) || defined(sun)
+#elif defined( _MSC_VER ) || defined(__MINGW32__)
 typedef signed char        int8_t;
 typedef signed short       int16_t;
 typedef signed int         int32_t;
 typedef __int64            int64_t;
 typedef unsigned char      uint8_t;
 typedef unsigned short     uint16_t;
 typedef unsigned int       uint32_t;
 typedef unsigned __int64   uint64_t;
+#elif defined(__sparc)
+#include <sys/int_types.h>
 #else
 #   error
 #   error "Port me! Platforms that don't have <stdint.h> need to define int8_t, et. al."
 #   error
 #endif
 
 // Establish __BYTE_ORDER
 #ifdef __linux__
@@ -47,16 +49,21 @@
 #       define __BYTE_ORDER __LITTLE_ENDIAN
 #   endif
 
 #elif defined __sgi
 #   ifndef __BYTE_ORDER
 #           define __BYTE_ORDER __BIG_ENDIAN
 #   endif
 
+#elif defined __sparc
+#   ifndef __BYTE_ORDER
+#           define __BYTE_ORDER __BIG_ENDIAN
+#   endif
+
 #elif defined(__CYGWIN__) || defined(_WIN32)
 #   ifndef __BYTE_ORDER
 #           define __BYTE_ORDER __LITTLE_ENDIAN
 #   endif
 
 #endif
 
 #if ((__BYTE_ORDER != __LITTLE_ENDIAN) && (__BYTE_ORDER != __BIG_ENDIAN))
@@ -84,17 +91,17 @@
     return ((b&0xff00)>>8)|((b&0x00ff)>>8);
 }
 
 inline uint32_t bswap_32(unsigned int b) {
     return ((b&0xff000000)>>24)|((b&0x00ff0000)>>8)|
             ((b&0x0000ff00)<<8)|((b&0x000000ff)<<24);
 }
 
-inline uint64_t bswap_64(unsignedlonglong b) {
+inline uint64_t bswap_64(uint64_t b) {
     return ( ((b&0xff00000000000000LL) >> 56) |
              ((b&0x00ff000000000000LL) >> 40) |
              ((b&0x0000ff0000000000LL) >> 24) |
              ((b&0x000000ff00000000LL) >> 8) |
              ((b&0x00000000ff000000LL) << 8) |
              ((b&0x0000000000ff0000LL) << 24) |
              ((b&0x000000000000ff00LL) << 40) |
              ((b&0x00000000000000ffLL) << 56) );
Index: typcnvt.hpp
===================================================================
RCS file: /home/cvs/anders/FlightGear/fgmp/fg_server/src/typcnvt.hpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -8 -r1.1.1.1 -r1.2
--- typcnvt.hpp	29 Apr 2007 17:01:22 -0000	1.1.1.1
+++ typcnvt.hpp	29 Apr 2007 17:41:28 -0000	1.2
@@ -1,11 +1,11 @@
 //////////////////////////////////////////////////////////////////////
 //
-// $Id: typcnvt.hpp,v 1.1.1.1 2007-04-29 17:01:22 anders Exp $
+// $Id: typcnvt.hpp,v 1.2 2007-04-29 17:41:28 anders Exp $
 //
 //////////////////////////////////////////////////////////////////////
 #ifndef TYPCNVTHDR
 #define TYPCNVTHDR 1
 
 using namespace std;
 
 #ifdef HAVE_CONFIG_H
@@ -193,17 +193,17 @@
         n_WorkNumber = (t_longlong) n_WorkNumber;
         if ((n_WorkNumber == 0) && (tmp != 0))
         {
             str_Return = "0" + str_Return;
         }
         else
         {
             n = n_Factor;
-            n_WorkNumber = abs(n_WorkNumber);
+            n_WorkNumber = abs((long int)n_WorkNumber);
             while (n_WorkNumber >= 0 && n > 1)
             {
                 str_Return = Numbers[n_WorkNumber % n_Base] + str_Return;
                 n_WorkNumber /= n_Base;
                 n /= n_Base;
             }
         }
 //        if (tmp != 0.0)
