/********************************************************************************/ /* */ /* NetSynch.c */ /* */ /* This file defines the synchronisation API */ /* */ /********************************************************************************/ /* Author: David Fournier * * Creation Date: 10/04/97 */ #include "warnings.h" #include "NetMemCo.h" #include #include #include "Privnetser.h" #include "PrivNetSynch.h" typedef struct { NetLib_uxSynchroId uxSyncId; /* Synchro Id. */ unsigned long ulSizeMes; /* Size of message. */ }NetLib_tdstMesSynchro; typedef struct _stRecSynchro { NetLib_tduxPlayerId PId; /* Player Id. */ struct _stRecSynchro *pNext; /* Next synchro message receipt. */ NetLib_uxSynchroId uxSyncId; /* Synchro Id. */ unsigned long ulSizeMes; /* Size of message. */ }NetLib_tdstRecSynchro; typedef struct { NetLib_uxSynchroId uxSyncId; /* Synchro Id. */ NetLib_tduxPlayerId *pMarkPlayer; /* Array of players mark. */ NetLib_tduxPlayerId NbrPlayer; /* Number of remote player. */ NetLib_tdstRecSynchro *pRecSync; /* Array of synchro receipt. */ NetLib_tdulTimeInfo ulTimeEnd; /* Time of end process (begin + time out). */ NetLib_tdfnvSynchroCallback tdfnvCallback; /* CallBack for remote sync message. */ }NetLib_tdstInfoSynchro; static NetLib_tdstInfoSynchro gs_tdstInfoSynchro; /* Informations of the current synchro. */ /***************************************************************************** * Description: vNetLibInitSynchro * Initialyze synchro module. ***************************************************************************** * Input: none * Output: none *****************************************************************************/ void _NET_CALLING_CONV_ vNetLibInitSynchro(void) { gs_tdstInfoSynchro.uxSyncId=NetLib_C_InvalidSynchroId; gs_tdstInfoSynchro.pMarkPlayer=NULL; gs_tdstInfoSynchro.ulTimeEnd=0; gs_tdstInfoSynchro.pRecSync=NULL; gs_tdstInfoSynchro.tdfnvCallback=NULL; } /***************************************************************************** * Description: eNetLibFreeSynchro * Free synchro module. ***************************************************************************** * Input: none * Output: none *****************************************************************************/ void _NET_CALLING_CONV_ vNetLibFreeSynchro(void) { NetLib_tdstRecSynchro *pRecSync,*pNext; vFree(gs_tdstInfoSynchro.pMarkPlayer); gs_tdstInfoSynchro.pMarkPlayer=NULL; pRecSync=gs_tdstInfoSynchro.pRecSync; while (pRecSync) { pNext=pRecSync->pNext; vFree(pRecSync); pRecSync=pNext; } gs_tdstInfoSynchro.pRecSync=NULL; gs_tdstInfoSynchro.tdfnvCallback=NULL; gs_tdstInfoSynchro.uxSyncId=NetLib_C_InvalidSynchroId; } /***************************************************************************** * Description: eNetLibTestSynchro * Return the synchro state. *****************************************************************************/ NetLib_tdeErrorStatus eNetLibTestSynchro(int bWithoutAck,NetLib_tduxPlayerId ucMaster) { NetLib_tduxPlayerId i; NetLib_tdstRecSynchro *pRecSync; if (!bWithoutAck) { for (i=0;iuxSyncId==gs_tdstInfoSynchro.uxSyncId) && (pRecSync->PId==gs_tdstInfoSynchro.pMarkPlayer[i])) break; pRecSync=pRecSync->pNext; } if (!pRecSync) return NetLib_E_es_SynchroNoSync; } } else { pRecSync=gs_tdstInfoSynchro.pRecSync; while (pRecSync) { if ((pRecSync->uxSyncId==gs_tdstInfoSynchro.uxSyncId) && (pRecSync->PId==ucMaster)) break; pRecSync=pRecSync->pNext; } if (!pRecSync) return NetLib_E_es_SynchroNoSync; } return NetLib_E_es_SynchroOk; } /***************************************************************************** * Description: vNetLib_AckSynchro * Aknowledgment of a synchro message. *****************************************************************************/ static void _NET_CALLING_CONV_ vNetLib_AckSynchro(NetLib_tduxPlayerId PId, NetLib_uxReadReceiptId AId,NetLib_ucReadReceiptFlag Flag,long Param) { NetLib_tduxPlayerId i; if ((Flag==NetLib_C_ucReadReceiptSuccess) && (AId==gs_tdstInfoSynchro.uxSyncId)) { for (i=0;iulSizeMes),sizeof(unsigned long)); return NetLib_E_es_NoError; } /***************************************************************************** * Description: eHandleNetSysMsgSynchro * Receive a synchro message. *****************************************************************************/ NetLib_tdeErrorStatus _NET_CALLING_CONV_ eHandleNetSysMsgSynchro(tdstNetMessage *pstMes,tdeNetProtocol eProt,tduwNetChannel uwChannel) { NetLib_tdstMesSynchro *pMessage; NetLib_tdstRecSynchro **ppRecSync,*pRecSync,*pF; if(pstMes->m_uxReadReceiptId!=C_uxNetInvalidId) eNetSendReadReceiptMessage(pstMes); pMessage=(NetLib_tdstMesSynchro *)(pstMes+1); ppRecSync=&(gs_tdstInfoSynchro.pRecSync); while (*ppRecSync) { pRecSync=*ppRecSync; if ((pRecSync->uxSyncId==pMessage->uxSyncId) && (pRecSync->PId==pstMes->uxSenderId)) { /* If an old synchro with same Id and same player */ pF=*ppRecSync; /* is already in the file, delete it. */ *ppRecSync=(*ppRecSync)->pNext; vFree(pF); } else ppRecSync=&((*ppRecSync)->pNext); } pRecSync=(NetLib_tdstRecSynchro *)pMalloc(sizeof(NetLib_tdstRecSynchro)+pMessage->ulSizeMes); pRecSync->PId=pstMes->uxSenderId; pRecSync->pNext=NULL; pRecSync->uxSyncId=pMessage->uxSyncId; pRecSync->ulSizeMes=pMessage->ulSizeMes; memcpy(pRecSync+1,pMessage+1,pMessage->ulSizeMes); *ppRecSync=pRecSync; vFree(pstMes); return NetLib_E_es_NoError; } /***************************************************************************** * Description: eNetLibWaitSynchro * Send a synchro message and wait synchro messages from all other players or from master. ***************************************************************************** * Input: uxSyncId = Synchro id * ulTimeOut = when time elapsed, function return NetLib_E_es_SynchroNoAck or NetLib_E_es_SynchroNoSync. * pBufMes = Adress of the send message. * ulSizeMes = Size of the send message. * tdfnvCallback = CallBack for receipt remote player message. * bWithoutAck = true (!=0) if send without acknoledment. * ucMaster = Id of master if the synchro is master/slave. * C_uxNetInvalidId if no master. * Output: An error code. * NetLib_E_es_SynchroWait : Synchro not finish. * NetLib_E_es_SynchroOk : Synchro ok. All synchro messages players receipt * and all player receive our message. * NetLib_E_es_SynchroNoAck : Time out, acknoledgment missing for one or many players, * NetLib_E_es_SynchroNoSync : or one or many synchro message missing. * NetLib_E_es_NotEnoughMemory : Not enough memory for perform synchro. *****************************************************************************/ NetLib_tdeErrorStatus _NET_CALLING_CONV_ eNetLibWaitSynchro(NetLib_uxSynchroId uxSyncId, NetLib_tdulTimeInfo ulTimeOut,void *pBufMes,unsigned long ulSizeMes, NetLib_tdfnvSynchroCallback tdfnvCallback,int bWithoutAck, NetLib_tduxPlayerId ucMaster) { NetLib_tduxPlayerId PId,OwnId; NetLib_tdstSendDesc tdstSendDesc; NetLib_tdstMesSynchro *pMessage; NetLib_tdeErrorStatus eStatus; NetLib_tdstRecSynchro *pRecSync; if (gs_tdstInfoSynchro.uxSyncId!=uxSyncId) { gs_tdstInfoSynchro.uxSyncId=NetLib_C_InvalidSynchroId; vFree(gs_tdstInfoSynchro.pMarkPlayer); gs_tdstInfoSynchro.NbrPlayer=NetLib_uwGetTotalNumberPlayer()-1; OwnId=NetLib_uxGetOwnPlayerId(); if (gs_tdstInfoSynchro.NbrPlayer==0) return NetLib_E_es_SynchroOk; gs_tdstInfoSynchro.pMarkPlayer=pMalloc(sizeof(NetLib_tduxPlayerId)*gs_tdstInfoSynchro.NbrPlayer); if (!gs_tdstInfoSynchro.pMarkPlayer) return NetLib_E_es_NotEnoughMemory; pMessage=(NetLib_tdstMesSynchro *)pMalloc(ulSizeMes+sizeof(NetLib_tdstMesSynchro)); if (!pMessage) { vFree(gs_tdstInfoSynchro.pMarkPlayer); gs_tdstInfoSynchro.pMarkPlayer=NULL; return NetLib_E_es_NotEnoughMemory; } if (OwnId==ucMaster) ucMaster=C_uxNetInvalidId; for (PId=0;PIduxSyncId=uxSyncId; pMessage->ulSizeMes=ulSizeMes; memcpy(pMessage+1,pBufMes,ulSizeMes); gs_tdstInfoSynchro.uxSyncId=uxSyncId; gs_tdstInfoSynchro.ulTimeEnd=GetTickCount()+ulTimeOut; gs_tdstInfoSynchro.tdfnvCallback=tdfnvCallback; if (ucMaster==C_uxNetInvalidId) tdstSendDesc.m_tduxRecipientId=C_uxNetBroadcastId; else tdstSendDesc.m_tduxRecipientId=ucMaster; tdstSendDesc.m_ulMaxWaitingTime=0; tdstSendDesc.m_pMessageData=(char*)pMessage; tdstSendDesc.m_uwMessageLength=ulSizeMes+sizeof(NetLib_tdstMesSynchro); tdstSendDesc.m_uxPriority=0; tdstSendDesc.m_uxReplaceType=0; tdstSendDesc.m_uxReplaceFlag=NetLib_C_uxNoReplace; if (!bWithoutAck) { tdstSendDesc.m_ucReadReceiptFlag=NetLib_C_ucReadReceiptRequired; tdstSendDesc.m_stReadReceiptDesc.m_ulMaxWaitingTime=ulTimeOut; tdstSendDesc.m_stReadReceiptDesc.m_ulReemitFreq=250; tdstSendDesc.m_stReadReceiptDesc.m_uxReadReceiptId=uxSyncId; tdstSendDesc.m_stReadReceiptDesc.m_lCallbackParam=uxSyncId; tdstSendDesc.m_stReadReceiptDesc.p_fnv_ReadReceiptCallback=vNetLib_AckSynchro; } else { tdstSendDesc.m_ucReadReceiptFlag=NetLib_C_ucNoReadReceipt; } eNetInternalSendMessage(&tdstSendDesc,E_Net_mt_SysSynchro); vFree(pMessage); } NetLib_vEngine(); eStatus=eNetLibTestSynchro(bWithoutAck,ucMaster); if ((eStatus!=NetLib_E_es_SynchroOk) && (GetTickCount()uxSyncId==uxSyncId) { tdfnvCallback(pRecSync->PId,pRecSync->uxSyncId,pRecSync+1,pRecSync->ulSizeMes); } pRecSync=pRecSync->pNext; } } vNetLibFreeSynchro(); } return eStatus; }