reman3/Rayman_X/cpa/tempgrp/NET/l0GSUbi.c

640 lines
22 KiB
C
Raw Blame History

/*
* universal multiplayer library level 0 implementation file
* transport layer: Game Service UBI Soft PC-windows 95
*/
/*
* Author: David Fournier
*
* Creation Date: 2/1/97
*
*/
#include "warnings.h"
#include <stdlib.h>
/*
* we need this one to fill the interface structure
* with pointers to the correct functions
*/
#include "PrivL0GSUBI.h"
#include "PrivL0TCP.h"
#include "PrivNetDef.h"
#include "L0GlDef.h"
#include "NetMemCo.h"
#include "NetSock.h"
#include "NetEnd.h"
#include "PrivNetSer.h"
#include <stdio.h>
#include <gameserv.h>
#include <NET\Netdebug.h>
#define GSUBI_MAXBUF 250
typedef short tdPlayerId; /* Id for the game service. */
static char gs_bL0PCWin95GSUBIInitState; /* State of the level 0 game service module. */
#pragma pack(1)
typedef struct
{
NetLib_tduxPlayerId pid; /* ID of the player. */
NetLib_tduwJoinType joinType; /* Create, Join or Watch. */
}NetLib_tdstInfoPlayer;
static NetLib_tdstInfoPlayer gs_InfoLocal; /* Informations of the local player. */
static NetLib_tduxPlayerId gs_IdMaster; /* Master Id. */
typedef struct stFIFO
{
struct stFIFO *next; /* Next message of FIFO. */
unsigned long size; /* Size of message. */
NetLib_tduxPlayerId id; /* ID of sender. */
}FIFO;
static FIFO *FIFObegin; /* First message of file. */
static FIFO **FIFOend; /* Last pointer of the file. */
static long SendBufSize; /* Virtual buffer size. */
static unsigned long LastTime; /* Time for the last eL0PCWin95TENEngine. */
static unsigned long SendMaxRate; /* Maximum rate. */
typedef struct
{
NetLib_uxReadReceiptId m_uxReadReceiptId;
unsigned long uxPriority:7;
unsigned long uxReplaceType:7;
unsigned long uxReplace:1;
unsigned long eMessageType:5;
unsigned long uxHeadBigEndian:1;
unsigned long uxBodyBigEndian:1;
}GSUBIHead;
#pragma pack()
/*****************************************************************************
* Description: vL0PCWin95GSUBICloseChannel
* Not use for this protocol.
*****************************************************************************
* Input: identifier of the channel
* Output: none
*****************************************************************************/
void vL0PCWin95GSUBICloseChannel(tduwNetChannel uwChannel)
{
}
/*****************************************************************************
* Description: uwL0PCWin95GSUBIStartChannelScan
* returns the identification number of the first channel for the protocol
*****************************************************************************
* Input: none
* Output: 0
*****************************************************************************/
tduwNetChannel uwL0PCWin95GSUBIStartChannelScan(void)
{
if(!(gs_bL0PCWin95GSUBIInitState&0x02))
return C_uwNetInvalidChannel;
return 0;
}
/*****************************************************************************
* Description: uwL0PCWin95GSUBINextChannel
* returns the identification number of the channel following the last
* return always C_uwNetInvalidChannel because there is one channel.
*****************************************************************************
* Input: uwLastScannedChannel, index returned by the previous call
* Output: C_uwNetInvalidChannel
*****************************************************************************/
tduwNetChannel uwL0PCWin95GSUBINextChannel(tduwNetChannel uwLastScannedChannel)
{
return C_uwNetInvalidChannel;
}
/*****************************************************************************
* Description: uwL0PCWin95GSUBIStartBroadcastChannelScan
* returns the identification number of the first broadcast channel
* for the protocol
*****************************************************************************
* Input: none
* Output: 0
*****************************************************************************/
tduwNetChannel uwL0PCWin95GSUBIStartBroadcastChannelScan(void)
{
if(!(gs_bL0PCWin95GSUBIInitState&0x02))
return C_uwNetInvalidChannel;
return 1;
}
/*****************************************************************************
* Description: uwL0PCWin95GSUBINextBroadcastChannel
* returns the identification number of the broadcast channel following
* the specified one
* return always C_uwNetInvalidChannel because there is one channel broadcast.
*****************************************************************************
* Input: uwLastScannedChannel, index returned by the previous call
* Output: identification of the channel following the specified one
*****************************************************************************/
tduwNetChannel uwL0PCWin95GSUBINextBroadcastChannel(tduwNetChannel uwLastScannedChannel)
{
return C_uwNetInvalidChannel;
}
/*****************************************************************************
* Description: L0PCWin95GSUBIReadCallBack
* This function is call by the game service API when a message arrived.
* The message is store in the incoming message list until the level one read it.
*****************************************************************************
* Input: fromPid, id of the sender.
* buf, adress of the buffer message.
* size, size of the message.
* Output: none.
*****************************************************************************/
static void GS_FUNCTIONCALL L0PCWin95GSUBIReadCallBack(tdPlayerId fromPid, char *buf, short size)
{
FIFO *cour;
#if defined(NET_USE_DEBUG)
GSUBIHead *pSend=(GSUBIHead *)buf;
vDebugSISISI(Net_C_Debug_GSUbi,"Receive Type",pSend->eMessageType,"Size",size-sizeof(GSUBIHead),"Source",fromPid);
#endif
cour=(FIFO *)pMalloc(sizeof(FIFO)+size);
if (cour)
{
*FIFOend=cour;
cour->next=NULL;
cour->size=size;
cour->id=fromPid;
memcpy(cour+1,buf,size);
FIFOend=&(cour->next);
}
}
/*****************************************************************************
* Description: wL0PCWin95GSUBIGetMessage
* Get a message if it's possible.
*****************************************************************************/
short wL0PCWin95GSUBIGetMessage(tdstNetMessage **ppMes)
{
FIFO *cour;
tdstNetMessage *pMes;
GSUBIHead *pSend;
if (FIFObegin==NULL)
{
*ppMes=NULL;
return 0;
}
else
{
pMes=(tdstNetMessage *)pMalloc(FIFObegin->size+sizeof(tdstNetMessage)-sizeof(GSUBIHead));
if (pMes==NULL)
{
*ppMes=NULL;
return -1;
}
pSend=(GSUBIHead *)(FIFObegin+1);
memcpy(pMes+1,pSend+1,FIFObegin->size-sizeof(GSUBIHead));
pMes->m_uxReadReceiptId=pSend->m_uxReadReceiptId;
pMes->uxPriority=pSend->uxPriority;
pMes->uxReplace=pSend->uxReplace;
pMes->uxReplaceType=pSend->uxReplaceType;
pMes->eMessageType=pSend->eMessageType;
pMes->uxHeadBigEndian=pSend->uxHeadBigEndian;
pMes->uxBodyBigEndian=pSend->uxBodyBigEndian;
pMes->uxSessionId=0;
pMes->uxSenderId=FIFObegin->id;
pMes->uxRecipientId=gs_InfoLocal.pid;
pMes->uwMessageSizeInBytes=(unsigned short)(FIFObegin->size-sizeof(GSUBIHead));
pMes->ulReserved=M_ulMakeReserved(M_uwProcessCheckSum(pMes),
M_uwProcessCheckSumBody(pMes));
cour=FIFObegin->next;
vFree((char *)FIFObegin);
FIFObegin=cour;
if (cour==NULL) FIFOend=&FIFObegin;
*ppMes=pMes;
return 1;
}
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIReadData
*****************************************************************************
* Input: p_uwChannel, pointer on a field to store the identification of
* a new channel in case of access to a newly created broacast channel
* (irrelevant for the serial layer)
* ppData, address of the pointer to retrieve a full message if
* necessary.
* Output: an error condition.
*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95GSUBIReadData(tduwNetChannel *p_uwChannel, tdpPointer *ppData)
{
short r;
/* no : try to get a message from the FIFO */
r=wL0PCWin95GSUBIGetMessage((tdstNetMessage **)ppData);
if (r>0) return NetLib_E_es_NoError;
else if (r==0) return NetLib_E_es_FIFOIsEmpty;
else return NetLib_E_es_NotEnoughMemory;
}
/*****************************************************************************
* Description: eL0PCWin95GSUBISendData
*****************************************************************************
* Input: uwChannel, channel to send the message into.
* pData, pointer on the block to send
* Output: an error condition.
*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95GSUBISendData(tduwNetChannel uwChannel, tdpPointer pData)
{
unsigned long ulBytestoSend;
tdstNetMessage *pMes=(tdstNetMessage *)pData;
int NumErr=0;
short RepFlag;
GSUBIHead *pSend;
unsigned long NewTime;
NetLib_tduxPlayerId uxRecipient;
if(!(gs_bL0PCWin95GSUBIInitState&0x02))
return NetLib_E_es_InvalidChannel;
uxRecipient=pMes->uxRecipientId;
/* verify the validity of the Channel */
if(uwChannel>1)
{
uxRecipient=uwChannel-2;
uwChannel=0;
}
else if (uxRecipient==C_uxNetBroadcastId) uwChannel=1;
ulBytestoSend= pMes->uwMessageSizeInBytes + sizeof(GSUBIHead);
NewTime=GetTickCount();
SendBufSize-=((NewTime-LastTime)*(float)SendMaxRate)/1000;
LastTime=NewTime;
if (SendBufSize<0) SendBufSize=0;
if (SendBufSize>=GSUBI_MAXBUF)
{
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_GSUbi,"Controle de flot.");
#endif
return NetLib_E_es_BufferIsFull;
}
SendBufSize+=ulBytestoSend;
pSend=(GSUBIHead *)pMalloc(ulBytestoSend);
if (!pSend)
{
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_GSUbi,"Manque de m<>moire.");
#endif
return NetLib_E_es_NotEnoughMemory;
}
pSend->m_uxReadReceiptId=pMes->m_uxReadReceiptId;
pSend->uxPriority=pMes->uxPriority;
pSend->uxReplace=pMes->uxReplace;
pSend->uxReplaceType=pMes->uxReplaceType;
pSend->eMessageType=pMes->eMessageType;
pSend->uxHeadBigEndian=pMes->uxHeadBigEndian;
pSend->uxBodyBigEndian=pMes->uxBodyBigEndian;
memcpy(pSend+1,pMes+1,pMes->uwMessageSizeInBytes);
if (pMes->uxReplace) RepFlag=0x80 | pMes->uxPriority;
else RepFlag=0;
if (uwChannel!=1)
{
#if defined(NET_USE_DEBUG)
vDebugSISISI(Net_C_Debug_GSUbi,"Send to one player. Type",pMes->eMessageType,"Size",pMes->uwMessageSizeInBytes,"Recipient",uxRecipient);
#endif
NumErr=GS_vSendToOnePlayer((short)(uxRecipient),(char *)pSend,(short)ulBytestoSend,RepFlag);
}
else
{
#if defined(NET_USE_DEBUG)
vDebugSISISI(Net_C_Debug_GSUbi,"Send to all players. Type",pMes->eMessageType,"Size",pMes->uwMessageSizeInBytes,"Recipient",uxRecipient);
#endif
NumErr=GS_vSendToAllPlayers((char *)pSend,(short)ulBytestoSend,0,RepFlag);
}
vFree((char *)pSend);
if (NumErr)
{
#if defined(NET_USE_DEBUG)
vDebugSI(Net_C_Debug_GSUbi,"Emission en attente",NumErr);
#endif
return NetLib_E_es_BufferIsFull;
}
/* free the message buffer */
vFree(pData);
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIQueryChannelStatus
* returns the current status of the channel
*****************************************************************************
* Input: uwChannel, channel to query
* Output: an error condition.
*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95GSUBIQueryChannelStatus(tduwNetChannel uwChannel)
{
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIEngine
*****************************************************************************
* Input: none
* Output: none
*****************************************************************************/
void eL0PCWin95GSUBIEngine(void)
{
char szBuffer[128];
if(gs_bL0PCWin95GSUBIInitState&0x02) GS_lEngine(szBuffer);
}
/*****************************************************************************
* Description : vL0PCWin95GSUBICloseProtocol(void)
* GSUBI-Level 0 closing function
*****************************************************************************
* Input : none
* Output : none
*****************************************************************************/
void vL0PCWin95GSUBICloseProtocol(void)
{
FIFO *p;
while (FIFObegin)
{
p=FIFObegin->next;
vFree((char*)FIFObegin);
FIFObegin=p;
}
FIFObegin=NULL;
FIFOend=&FIFObegin;
vLevel1RemoveProtocol(E_Net_pr_Windows95GSUBIProtocol);
}
/*****************************************************************************
* Description: L0PCWin95GSUBINewPlayerCallBack
* This function is call by the game service API when a new player join the session.
*****************************************************************************
* Input: pid = id of the player.
* name = name of the player for the game service.
* options = options player for the game service.
* size = size of the options.
* isYou = true if the player is the local player.
* isMaster = true if the player is the master.
* Output: none
*****************************************************************************/
void GS_FUNCTIONCALL L0PCWin95GSUBINewPlayerCallBack(tdPlayerId pid,char *name,char *options,short size,int isYou,int isMaster)
{
NetLib_tdstAddPlayerDesc PlDesc;
short j=NetLib_Join_Join;
char nameopt[500];
#if defined(NET_USE_DEBUG)
vDebugSIS(Net_C_Debug_GSUbi,"NewPlayerCallBack Pid",pid,name);
#endif
if (isYou)
{
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_GSUbi,"Is me");
#endif
gs_InfoLocal.pid = pid;
gs_InfoLocal.joinType = j;
}
if (isMaster)
{
gs_IdMaster=pid;
}
PlDesc.m_tduxPlayerId=pid;
/* PlDesc.m_pPlayerDescriptionData=options;*/
/* PlDesc.m_ucPlayerDesciptionLength=size;*/
PlDesc.m_pPlayerDescriptionData=NULL;
PlDesc.m_uxPlayerDesciptionLength=0;
PlDesc.m_stL1AddPlayerDesc.m_eProtocol=E_Net_pr_Windows95GSUBIProtocol;
PlDesc.m_stL1AddPlayerDesc.m_vL0Param=NULL;
PlDesc.IsYou=isYou;
PlDesc.JoinType=j;
sprintf(nameopt,"name '%s'",name);
PlDesc.Options=nameopt;
NetLib_eAddNewPlayer(&PlDesc);
}
/*****************************************************************************
* Description: L0PCWin95GSUBIDoPlayerLeft
* A user has left the game. This function is call by the game service API.
*****************************************************************************
* Input: pid : ID of player who left the game.
* Output: none
*****************************************************************************/
static void GS_FUNCTIONCALL L0PCWin95GSUBIDoPlayerLeft(tdPlayerId pid, int isme)
{
#if defined(NET_USE_DEBUG)
vDebugSI(Net_C_Debug_GSUbi,"DoPlayerLeft Pid",pid);
#endif
if (!isme) eNetDisconnectPlayer((NetLib_tduxPlayerId)(pid),1);
}
/*****************************************************************************
* Description: vL0PCWin95GSUBIAddNewPlayer
*****************************************************************************
* Input: pChanel : adress of returned chanel.
* par : extern parameter.
* Output: error code.
*****************************************************************************/
NetLib_tdeErrorStatus vL0PCWin95GSUBIAddNewPlayer(tduwNetChannel *pChanel,void *par)
{
*pChanel=0;
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIConnectionResult
* Return connection result from tcp to game service.
* Level 0 TCP call this function when the result of connection is know.
*****************************************************************************
* Input: Result
* Output: none
*****************************************************************************/
void vL0PCWin95GSUBIConnectionResult(int iRes)
{
GS_vNetLibConnectionResult(iRes);
}
/*****************************************************************************
* Description: L0PCWin95GSUBIRateCallBack
* This callback is call by the game service API for control the sending rate.
*****************************************************************************
* Input: ulRate, maximum rate of emission.
*****************************************************************************/
static void GS_FUNCTIONCALL L0PCWin95GSUBIRateCallBack(unsigned long ulRate)
{
#if defined(GSUBI_TRACE)
DebugSI("Maximum rate",ulRate);
#endif
SendMaxRate=ulRate;
}
/*****************************************************************************
* Description: vL0PCWin95GSUBIOpenProtocol
* initialize the specified interface structure with the correct function
* pointers to enable a protocol-independent data transmission process.
*****************************************************************************
* Input: p_stProtocolInterface, pointer to the interface structure
* uwPortNumber, port number to bind the socket to
* Output: none
*****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95GSUBIOpenProtocol(void)
{
tdstNetProtocolInterface *p_stProtocolInterface;
p_stProtocolInterface=pstLevel1AddProtocol();
FIFObegin=NULL;
FIFOend=&FIFObegin;
/* logical identification of the protocol */
p_stProtocolInterface->eProtocol = E_Net_pr_Windows95GSUBIProtocol;
/* setup the function pointers */
p_stProtocolInterface->fn_uwStartChannelScan = uwL0PCWin95GSUBIStartChannelScan;
p_stProtocolInterface->fn_uwStartBroadcastChannelScan= uwL0PCWin95GSUBIStartBroadcastChannelScan;
p_stProtocolInterface->fn_uwNextChannel= uwL0PCWin95GSUBINextChannel;
p_stProtocolInterface->fn_uwNextBroadcastChannel= uwL0PCWin95GSUBINextBroadcastChannel;
p_stProtocolInterface->fn_eReadData= eL0PCWin95GSUBIReadData;
p_stProtocolInterface->fn_eSendData= eL0PCWin95GSUBISendData;
p_stProtocolInterface->fn_eQueryChannelStatus= eL0PCWin95GSUBIQueryChannelStatus;
p_stProtocolInterface->fn_vLevel0NetEngine = eL0PCWin95GSUBIEngine;
p_stProtocolInterface->fn_vCloseChannel = vL0PCWin95GSUBICloseChannel;
p_stProtocolInterface->fn_vLevel0CloseProtocol = vL0PCWin95GSUBICloseProtocol;
p_stProtocolInterface->fn_eAddNewPlayer = vL0PCWin95GSUBIAddNewPlayer;
gs_bL0PCWin95GSUBIInitState = 0x01;
#if defined(NET_USE_DEBUG)
vDebugClear(Net_C_Debug_GSUbi);
vDebugS(Net_C_Debug_GSUbi,"SetupInterface");
#endif
vL0PCWin95TCPGSSetCallBackResult(vL0PCWin95GSUBIConnectionResult);
GS_vSetRmPlayerCallBack(L0PCWin95GSUBIDoPlayerLeft);
GS_vSetNewPlayerCallBack(L0PCWin95GSUBINewPlayerCallBack);
GS_vSetMsgReceivedCallBack(L0PCWin95GSUBIReadCallBack);
GS_vSetRateCtrlCallBack(L0PCWin95GSUBIRateCallBack);
GS_vSetSetPlayerCallBack(vL0PCWin95TCPGSSetPLayer);
GS_vSetSetChannelCallBack(vL0PCWin95TCPGSSetChannel);
GS_vSetInitiateConnectionCallBack(vL0PCWin95TCPGSInitiateConnection);
SendBufSize=0;
LastTime=GetTickCount();
SendMaxRate=1000000L;
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIStart
* Start a game with GSUBI.
* Initialise the incoming message list. State flag are set for call to GS_lEngine.
*****************************************************************************
* Input: none
* Output: none
*****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95GSUBIStart(void)
{
FIFO *p;
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_GSUbi,"Start");
#endif
while (FIFObegin)
{
p=FIFObegin->next;
vFree((char*)FIFObegin);
FIFObegin=p;
}
FIFObegin=NULL;
FIFOend=&FIFObegin;
gs_bL0PCWin95GSUBIInitState|=0x02;
SendBufSize=0;
LastTime=GetTickCount();
SendMaxRate=1000000L;
}
/*****************************************************************************
* Description: vL0PCWin95GSUBIFinish
* Finish a game with GSUBI.
* This function erase the list of incoming message, disconnect all remote players,
* close all TCP port, and send message to game service for quit the game mode.
*****************************************************************************
* Input: none
* Output: none
*****************************************************************************/
void _NET_CALLING_CONV_ vL0PCWin95GSUBIFinish(void)
{
FIFO *p;
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_GSUbi,"Finish");
#endif
while (FIFObegin)
{
p=FIFObegin->next;
vFree((char*)FIFObegin);
FIFObegin=p;
}
FIFObegin=NULL;
FIFOend=&FIFObegin;
GS_vQuitSession();
gs_bL0PCWin95GSUBIInitState&=~0x02;
SendBufSize=0;
LastTime=GetTickCount();
SendMaxRate=1000000L;
NetLib_vDisconnectAllRemotePlayers();
vL0PCWin95TCPCloseListenPort();
}
/*****************************************************************************
* Description: eL0PCWin95GSUBIMasterId
* Return the master Id. Master is the player who created the session for the
* game service.
*****************************************************************************/
NetLib_tduxPlayerId _NET_CALLING_CONV_ eL0PCWin95GSUBIMasterId(void)
{
return gs_IdMaster;
}
/*****************************************************************************
* Description : eL0PCWin95GSUBIIsProtocolSet
* Check if the protocol is correctly initialize or not
*****************************************************************************
* Input : none
* Output :
* NetLib_E_es_ProtocolNotInitialized : the vLevel0SetupWin95PCGSUBIInterface has not
* been called yet or it has failed, the application should call the level 2
* eInitializeGlobalData function.
*****************************************************************************/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95GSUBIIsProtocolSet(void)
{
if(!(gs_bL0PCWin95GSUBIInitState&0x01)) return NetLib_E_es_ProtocolNotInitialized;
return NetLib_E_es_True;
}
/*****************************************************************************
* Description : eL0PCWin95GSUBIIsProtocolAvailable
* Not use for this protocol.
*****************************************************************************
* Output : NetLib_E_es_True if the port is avaible
* An error code otherwise
*****************************************************************************/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95GSUBIIsProtocolAvailable(void)
{
return NetLib_E_es_True;
}