00001 #include "MercuryNetServer.h"
00002 #include "MercuryLog.h"
00003 #include "MercuryObject.h"
00004 #include "MercuryODE.h"
00005
00006 MercuryNetServerConnection::~MercuryNetServerConnection()
00007 {
00008 delete m_pConnection;
00009 m_thdMain.Halt();
00010 m_thdMain.Close();
00011 }
00012
00013 MercuryNetServerConnection::MercuryNetServerConnection( ezSockets * pAccepted )
00014 {
00015 m_pNetClass = NULL;
00016 m_bIsActive = false;
00017 m_pConnection = pAccepted;
00018
00019
00020 if( pAccepted->GetAddress() == "88.55.123.44" )
00021 return;
00022
00023 m_bIsActive = true;
00024 m_thdMain.Create( CoreThreadCaller, this );
00025 }
00026
00027 void MercuryNetServerConnection::SendCommand( const MString & sCommandName, const PStack & kParameters )
00028 {
00029 ezSocketsPacket p;
00030 p.ClearPacket();
00031 p.Write1( 3 );
00032 p.WriteNT( sCommandName );
00033 NetEncodePStack( p, kParameters );
00034 m_pConnection->SendPack( p );
00035 }
00036
00037 void MercuryNetServerConnection::BroadcastToClient( const MString & sMessage, const PStack & pParameters )
00038 {
00039 ezSocketsPacket pack;
00040 pack.ClearPacket();
00041 pack.Write4( 2 );
00042 pack.WriteNT( sMessage );
00043 NetEncodePStack( pack, pParameters );
00044 m_pConnection->SendPack( pack );
00045 }
00046
00047 void * MercuryNetServerConnection::CoreThreadCaller( void * NetClient)
00048 {
00049 ((MercuryNetServerConnection *)NetClient)->CoreThread();
00050 return 0;
00051 }
00052
00053 void MercuryNetServerConnection::CoreThread( void)
00054 {
00055 ezSocketsPacket tmp;
00056 m_pConnection->bBlocking = true;
00057 m_pConnection->mode = ezSockets::skPackets;
00058 while( !m_pConnection->IsError() )
00059 {
00060 if( !m_pConnection->ReadPack( tmp ) )
00061 break;
00062 unsigned char cCode = tmp.Read4();
00063 switch( cCode )
00064 {
00065 case 0:
00066 break;
00067 case 1:
00068 break;
00069 case 2:
00070 break;
00071 case 3:
00072 {
00073 MString sName = tmp.ReadNT();
00074 PStack t;
00075 NetDecodePStack( tmp, t );
00076 if( m_pNetClass )
00077 {
00078 PStack ret;
00079 m_pNetClass->Command( ret, sName.c_str(), t );
00080 }
00081 }
00082 break;
00083 case 4:
00084 {
00085 double dCurTime = m_pParent->m_tmrSync.Age();
00086 double dClientTime;
00087 long delTimeID;
00088 delTimeID = tmp.Read4();
00089
00090 tmp.ReadData( 8, (char*)&dClientTime );
00091
00092
00093 ezSocketsPacket p;
00094 p.ClearPacket();
00095 p.Write4( 4 );
00096 p.Write4( delTimeID );
00097 p.WriteData( (char*)&dClientTime, 8 );
00098 p.WriteData( (char*)&dCurTime, 8 );
00099
00100 m_pConnection->SendPack( p );
00101 break;
00102 }
00103 }
00104 }
00105 m_pConnection->Close();
00106 m_bIsActive = false;
00107 }
00108
00109
00110
00111
00112 MercuryNetServer::MercuryNetServer()
00113 {
00114 m_pListener = new ezSockets;
00115 m_fTimeSinceLastODE = 0;
00116 }
00117
00118 MercuryNetServer::~MercuryNetServer()
00119 {
00120 m_thdMain.Halt( true );
00121 m_thdMain.Close();
00122 m_thdUDPMain.Halt( true );
00123 m_thdUDPMain.Close();
00124 for( MDequeIterator< MercuryNetServerConnection * > i = m_vClients.begin(); i != m_vClients.end(); ++i )
00125 {
00126 i.Data()->m_thdMain.Close();
00127 SAFE_DELETE( i.Data()->m_pConnection );
00128 SAFE_DELETE( i.Data() );
00129 }
00130 SAFE_DELETE( m_pListener );
00131 SAFE_DELETE( m_pUDPListener );
00132 }
00133
00134 void MercuryNetServer::BroadcastToAllClients( const MString & sMessage, const PStack & pParameters )
00135 {
00136 for( MDequeIterator< MercuryNetServerConnection * > i = m_vClients.begin(); i != m_vClients.end(); ++i )
00137 i.Data()->BroadcastToClient( sMessage, pParameters );
00138 }
00139
00140 bool MercuryNetServer::BindAndListen( int iPort, GenClientFunction cbFunction )
00141 {
00142 m_tmrSync.Touch();
00143 m_cbGenFunction = cbFunction;
00144 if( !m_pListener->Create() )
00145 return false;
00146 m_pListener->bBlocking = true;
00147 if( !m_pListener->Bind( iPort ) )
00148 return false;
00149 if( !m_pListener->Listen() )
00150 return false;
00151
00152 m_pUDPListener = new ezSockets;
00153 m_pUDPListener->mode = ezSockets::skUDP;
00154 m_pUDPListener->bBlocking = true;
00155 m_pUDPListener->Create( IPPROTO_UDP, SOCK_DGRAM );
00156 if( !m_pUDPListener->Bind( iPort ) )
00157 return false;
00158
00159 m_thdUDPMain.Close();
00160 m_thdUDPMain.Create( CoreUDPThreadCaller, this );
00161
00162 m_thdMain.Close();
00163 m_thdMain.Create( CoreThreadCaller, this );
00164 return true;
00165 }
00166
00167 void MercuryNetServer::Update( const float dTime )
00168 {
00169 m_fTimeSinceLastODE += dTime;
00170
00171 if( m_fTimeSinceLastODE > .5f )
00172 {
00173 UpdateODE();
00174 m_fTimeSinceLastODE=0;
00175 }
00176 }
00177
00178 void MercuryNetServer::UpdateODE( const MString & sNameOfObject )
00179 {
00180 if( m_pWorld == NULL )
00181 return;
00182
00183 unsigned i;
00184 double dCurTime = m_tmrSync.Age();
00185 ezSocketsPacket p;
00186 p.ClearPacket();
00187
00188
00189 p.Write4( 5 );
00190
00191
00192 p.WriteData( (char*)&dCurTime, 8 );
00193
00194
00195 MHash<MercuryODEObject *> & pAllObjects = m_pWorld->GetAllObjectMap();
00196
00197 if( sNameOfObject != "" )
00198 {
00199 p.Write4( 1 );
00200 MercuryODEObject * g = pAllObjects[sNameOfObject];
00201 ODEUnitInfo inf;
00202 if( g->m_oBody )
00203 {
00204 p.WriteNT( sNameOfObject );
00205 inf.pos = dBodyGetPosition( g->m_oBody );
00206 const float * f = dBodyGetQuaternion( g->m_oBody );
00207 inf.rot.w = f[0]; inf.rot.x = f[1]; inf.rot.y = f[2]; inf.rot.z = f[3];
00208 inf.linvel = dBodyGetLinearVel( g->m_oBody );
00209 inf.angvel = dBodyGetAngularVel( g->m_oBody );
00210 p.WriteData( (const char*) &inf, sizeof( ODEUnitInfo ) );
00211 }
00212 }
00213 else
00214 {
00215 MVector< MString > pAllIndicies;
00216 pAllObjects.VectorIndicies( pAllIndicies );
00217
00218
00219 p.Write4( pAllIndicies.size() );
00220
00221 for( i = 0; i < pAllIndicies.size(); i++ )
00222 {
00223 MercuryODEObject * g = pAllObjects[pAllIndicies[i]];
00224 ODEUnitInfo inf;
00225 if( g->m_oBody )
00226 {
00227 p.WriteNT( pAllIndicies[i] );
00228
00229 inf.pos = dBodyGetPosition( g->m_oBody );
00230 const float * f = dBodyGetQuaternion( g->m_oBody );
00231 inf.rot.w = f[0]; inf.rot.x = f[1]; inf.rot.y = f[2]; inf.rot.z = f[3];
00232 inf.linvel = dBodyGetLinearVel( g->m_oBody );
00233 inf.angvel = dBodyGetAngularVel( g->m_oBody );
00234 p.WriteData( (const char*) &inf, sizeof( ODEUnitInfo ) );
00235 }
00236 }
00237 }
00238
00239 for( MDequeIterator< MercuryNetServerConnection * > j = m_vClients.begin(); j != m_vClients.end(); ++j )
00240 (*j)->m_pConnection->SendPack( p );
00241 }
00242
00243 void * MercuryNetServer::CoreThreadCaller( void * NetClient)
00244 {
00245 ((MercuryNetServer *)NetClient)->CoreThread();
00246 return 0;
00247 }
00248
00249 void MercuryNetServer::CoreThread()
00250 {
00251 while( !m_pListener->IsError() )
00252 {
00253 ezSockets * s = m_pListener->Accept();
00254 if( s )
00255 {
00256 m_vClients.push_back( m_cbGenFunction( s ) );
00257 m_vClients.back()->AttachParent( this );
00258 }
00259 }
00260 }
00261
00262 void * MercuryNetServer::CoreUDPThreadCaller( void * NetClient )
00263 {
00264 ((MercuryNetServer *)NetClient)->CoreUDPThread();
00265 return NULL;
00266 }
00267
00268 void MercuryNetServer::CoreUDPThread()
00269 {
00270 ezSocketsPacket g;
00271 while( !m_pUDPListener->IsError() )
00272 {
00273 g.ClearPacket();
00274 m_pUDPListener->ReadPack( g );
00275
00276 Sleep( 1000.0f );
00277 ezSocketsPacket j;
00278 j.ClearPacket();
00279 j.Write4( 5 );
00280 j.Port = g.Port;
00281 j.PositionTAG = g.PositionTAG;
00282 j.Write4( 5 );
00283 m_pUDPListener->SendPack( j );
00284 }
00285 }
00286
00287 MercuryNetServerConnection * DefaultSocketConnection(ezSockets * pAccepted)
00288 {
00289 return new MercuryNetServerConnection( pAccepted );
00290 }
00291
00292
00293
00294 void NetEncodePStack( ezSocketsPacket & pPacket, const PStack & pParameters )
00295 {
00296 pPacket.Write1( pParameters.GetSize() );
00297 for( unsigned i = 0; i < pParameters.GetSize(); i++ )
00298 {
00299 pPacket.Write1( pParameters.PeekItem( i ).GetType() );
00300 switch( pParameters.PeekItem( i ).GetType() )
00301 {
00302 case PSElement::BOOL:
00303 pPacket.Write1( pParameters.PeekItem( i ).GetValueB() );
00304 break;
00305 case PSElement::INTEGER:
00306 pPacket.Write4( pParameters.PeekItem( i ).GetValueI() );
00307 break;
00308 case PSElement::FLOAT:
00309 {
00310 float f = pParameters.PeekItem( i ).GetValueF();
00311 pPacket.Write4( *((unsigned long*)((float*)&f)) );
00312 break;
00313 }
00314 case PSElement::STRING:
00315 pPacket.WriteNT( pParameters.PeekItem( i ).GetValueS() );
00316 break;
00317 default:
00318 break;
00319 }
00320 }
00321 }
00322
00323 void NetDecodePStack( ezSocketsPacket & pPacket, PStack & pParameters )
00324 {
00325 unsigned long iParameters = pPacket.Read1();
00326 for( unsigned i = 0; i < iParameters; i++ )
00327 {
00328 switch( pPacket.Read1() )
00329 {
00330 case PSElement::BOOL:
00331 pParameters.PushItemBack( PSElement( (bool)(pPacket.Read1() != 0) ) );
00332 break;
00333 case PSElement::INTEGER:
00334 pParameters.PushItemBack( PSElement( (int)pPacket.Read4() ) );
00335 break;
00336 case PSElement::FLOAT:
00337 {
00338 unsigned long l = pPacket.Read4();
00339 pParameters.PushItemBack( PSElement( *((float*)((unsigned long*)&l))));
00340 break;
00341 }
00342 case PSElement::STRING:
00343 pParameters.PushItemBack( PSElement( pPacket.ReadNT() ) );
00344 break;
00345 default:
00346 break;
00347 }
00348 }
00349 }