mirror of
https://github.com/thug1src/thug.git
synced 2024-12-02 21:07:12 +00:00
334 lines
11 KiB
C++
334 lines
11 KiB
C++
/*****************************************************************************
|
|
** **
|
|
** Neversoft Entertainment **
|
|
** **
|
|
** Copyright (C) 1999 - All Rights Reserved **
|
|
** **
|
|
******************************************************************************
|
|
** **
|
|
** Project: GEL (Game Engine Library) **
|
|
** **
|
|
** Module: Net (OBJ) **
|
|
** **
|
|
** File name: netdsptch.cpp **
|
|
** **
|
|
** Created: 01/29/01 - spg **
|
|
** **
|
|
** Description: Network Dispatching code **
|
|
** **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Includes **
|
|
*****************************************************************************/
|
|
|
|
#include <core/defines.h>
|
|
#include <string.h>
|
|
#include <gel/net/net.h>
|
|
|
|
/*****************************************************************************
|
|
** Externals **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Defines **
|
|
*****************************************************************************/
|
|
|
|
//#define NET_PRINT_MESSAGES 1
|
|
/*****************************************************************************
|
|
** DBG Defines **
|
|
*****************************************************************************/
|
|
|
|
namespace Net
|
|
{
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Types **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Private Data **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Public Data **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Prototypes **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Functions **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Private Functions **
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
** Public Functions **
|
|
*****************************************************************************/
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
MsgHandler::MsgHandler( MsgHandlerCode *code, int flags, void *data, int pri )
|
|
: Lst::Node< MsgHandler >( this, pri ), m_code( code ), m_data( data ), m_flags( flags )
|
|
{
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* Register a handler for a net msg */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
MsgHandler* Dispatcher::AddHandler( unsigned char net_msg_id, MsgHandlerCode *code, int flags,
|
|
void *data, int pri )
|
|
{
|
|
MsgHandler* handler;
|
|
|
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap());
|
|
|
|
handler = new MsgHandler( code, flags, data, pri );
|
|
|
|
m_handler_list[net_msg_id].AddNode( handler );
|
|
|
|
Mem::Manager::sHandle().PopContext();
|
|
|
|
return handler;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
void Dispatcher::Init( void )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < MAX_NET_MSG_ID; i++ )
|
|
{
|
|
m_handler_list[i].DestroyAllNodes();
|
|
}
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
void Dispatcher::Deinit( void )
|
|
{
|
|
int i;
|
|
|
|
|
|
|
|
for( i = 0; i < MAX_NET_MSG_ID; i++ )
|
|
{
|
|
Lst::Search< MsgHandler > sh;
|
|
MsgHandler* handler, *next;
|
|
|
|
for( handler = sh.FirstItem( m_handler_list[i] ); handler;
|
|
handler = next )
|
|
{
|
|
next = sh.NextItem();
|
|
|
|
delete handler;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* Dispatch messages to their appropriate handlers */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
int Dispatcher::DispatchMsgHandlers( Conn *conn, int flags )
|
|
{
|
|
MsgHandlerContext msg_context;
|
|
char msg_data[MAX_STREAM_LENGTH];
|
|
int result;
|
|
char *data;
|
|
|
|
Dbg_Assert( conn != NULL );
|
|
|
|
msg_context.m_Conn = conn;
|
|
msg_context.m_App = conn->m_app;
|
|
msg_context.m_PacketFlags = flags;
|
|
msg_context.m_Msg = msg_data;
|
|
msg_context.m_MsgLength = 0;
|
|
|
|
data = conn->m_read_buffer;
|
|
|
|
// loop through received data and handle messages
|
|
while( data < conn->m_read_ptr )
|
|
{
|
|
bool size_known;
|
|
|
|
// *** IMPORTANT. Because of alignment issues, I now copy the data from the byte stream
|
|
// into an aligned message buffer. Indexing into the buffer and casting to Msg's caused
|
|
// load errors
|
|
memcpy( &msg_context.m_MsgId, data, sizeof( unsigned char ));
|
|
data += sizeof( unsigned char );
|
|
|
|
// Check to see if the size of this message type is stored after the msg id
|
|
size_known = (( conn->m_app->GetManager()->GetMessageFlags( msg_context.m_MsgId ) & mMSG_SIZE_UNKNOWN ) == 0 );
|
|
//if( conn->IsRemote())
|
|
//{
|
|
//Dbg_Printf( "Got message %s with size_known of %d\n", conn->m_app->GetManager()->GetMessageName(msg_context.m_MsgId ), size_known);
|
|
//}
|
|
|
|
if( size_known )
|
|
{
|
|
unsigned short temp;
|
|
memcpy( &temp, data, sizeof( unsigned short ));
|
|
msg_context.m_MsgLength = (unsigned long)temp;
|
|
|
|
data += sizeof( unsigned short );
|
|
}
|
|
|
|
if( msg_context.m_MsgId == MSG_ID_SEQUENCED )
|
|
{
|
|
unsigned char embedded_msg_id;
|
|
unsigned short embedded_msg_length;
|
|
|
|
Dbg_Assert( size_known );
|
|
|
|
memcpy( &embedded_msg_id, data + 5, sizeof( unsigned char ));
|
|
embedded_msg_length = msg_context.m_MsgLength - Manager::vMSG_SEQ_HEADER_LENGTH;
|
|
|
|
conn->GetInboundMetrics()->AddMessage( embedded_msg_id, msg_context.m_MsgLength );
|
|
#ifdef NET_PRINT_MESSAGES
|
|
if( conn->IsRemote())
|
|
{
|
|
unsigned char group_id;
|
|
unsigned int seq_id;
|
|
|
|
memcpy( &group_id, data, sizeof( unsigned char ));
|
|
memcpy( &seq_id, data + 1, sizeof( unsigned int ));
|
|
Dbg_Printf( "(%d) Dispatching Sequenced Message (%d) Length (%d) Emb. Length (%d) : %s. Seq: %d Group: %d\n",
|
|
conn->m_app->m_FrameCounter,
|
|
embedded_msg_id,
|
|
msg_context.m_MsgLength,
|
|
embedded_msg_length,
|
|
conn->m_app->GetManager()->GetMessageName( embedded_msg_id ),
|
|
seq_id,
|
|
group_id );
|
|
}
|
|
#endif NET_PRINT_MESSAGES
|
|
}
|
|
|
|
// If we know the size, just copy the message into the aligned buffer
|
|
// otherwise, copy the maximum size of a message into the buffer and have the
|
|
// handler tell us the size of the message by changint the context's m_MsgLength member
|
|
if( size_known )
|
|
{
|
|
if( msg_context.m_MsgLength > 0 )
|
|
{
|
|
memcpy( msg_context.m_Msg, data, msg_context.m_MsgLength );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy( msg_context.m_Msg, data, Manager::vMAX_PACKET_SIZE );
|
|
}
|
|
|
|
if( conn->IsForeign())
|
|
{
|
|
msg_context.m_PacketFlags |= mHANDLE_FOREIGN;
|
|
}
|
|
result = DispatchMessage( &msg_context );
|
|
if( ( result == HANDLER_ERROR ) ||
|
|
( result == HANDLER_HALT ))
|
|
{
|
|
// output error indicating mal-formmated data
|
|
Dbg_Printf( "Stream processing halted on message %d\n", msg_context.m_MsgId );
|
|
conn->m_read_ptr = conn->m_read_buffer;
|
|
return HANDLER_HALT;
|
|
}
|
|
|
|
// By this time we know the message size, whether it was explicit or implicit
|
|
// so we can do the metrics calculation and the debug printout
|
|
if( msg_context.m_MsgId != MSG_ID_SEQUENCED )
|
|
{
|
|
conn->GetInboundMetrics()->AddMessage( msg_context.m_MsgId, msg_context.m_MsgLength );
|
|
#ifdef NET_PRINT_MESSAGES
|
|
/*if( conn->IsRemote())
|
|
{
|
|
Dbg_Printf( "(%d) Dispatching Message (%d) Length (%d) : %s\n",
|
|
conn->m_app->m_FrameCounter,
|
|
msg_context.m_MsgId,
|
|
msg_context.m_MsgLength,
|
|
conn->m_app->GetManager()->GetMessageName( msg_context.m_MsgId ));
|
|
}*/
|
|
#endif
|
|
}
|
|
|
|
data += msg_context.m_MsgLength;
|
|
}
|
|
|
|
conn->m_read_ptr = conn->m_read_buffer;
|
|
return HANDLER_CONTINUE;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* Dispatch a message to its appropriate handler. Stop if higher */
|
|
/* priority handlers say to */
|
|
/******************************************************************/
|
|
|
|
int Dispatcher::DispatchMessage( MsgHandlerContext *context )
|
|
{
|
|
Lst::Search< MsgHandler > sh;
|
|
MsgHandler *handler, *next;
|
|
int result;
|
|
|
|
|
|
|
|
Dbg_Assert( context );
|
|
|
|
// If this is a message we want to handle, call the handler
|
|
for( handler = sh.FirstItem( m_handler_list[context->m_MsgId] );
|
|
handler; handler = next )
|
|
{
|
|
next = sh.NextItem();
|
|
|
|
if(( handler->m_flags & context->m_PacketFlags ) != context->m_PacketFlags )
|
|
{
|
|
Dbg_Printf( "*** Conn %d packetflag mismatch on id %d : 0x%x 0x%x\n", context->m_Conn->GetHandle(), context->m_MsgId, handler->m_flags, context->m_PacketFlags );
|
|
continue;
|
|
}
|
|
|
|
context->m_Data = handler->m_data;
|
|
result = handler->m_code( context );
|
|
// Check the result from the handler
|
|
if( ( result == HANDLER_ERROR ) ||
|
|
( result == HANDLER_HALT ) ||
|
|
( result == HANDLER_MSG_DESTROYED ))
|
|
{
|
|
// Stop processing the buffer
|
|
return result;
|
|
}
|
|
// A higher int handler has chosen to mask this message from the rest
|
|
if( ( result == HANDLER_MSG_DONE ))
|
|
{
|
|
return HANDLER_CONTINUE;
|
|
}
|
|
}
|
|
|
|
return HANDLER_CONTINUE;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
} // namespace Net
|