2009-04-22 20:04:28 +02:00

1269 lines
34 KiB
C

/*
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
http://www.zsnes.com
http://sourceforge.net/projects/zsnes
https://zsnes.bountysource.com
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**********************************************************\
* ZSNES TCP/IP MODULE FOR NETWORK PLAY *
* *
* Coded by the ZSNES team *
* TCP/IP drivers coded by _Demo_, revised by Pharos *
* UDP drivers coded by _Demo_, revised by zsKnight *
* Gameplay netplay implementation by zsKnight *
* UDP Packet loss/out of order algorithm/implementation *
* by zsKnight, assistance on normal packets by Pharos *
\**********************************************************/
// UDP Algorithm:
//
// UDP Header (1 byte): 1 = Normal Packet w/ reply req, 2 = Reply Packet,
// 3 = Gameplay Packet (single byte),
// 4 = Gameplay Packet (larger packet), 5 = Re-request gameplay
// packet
//
// Normal Packets:
// Note: The actual implementation turned out to be quite different
// than the below descriptions.
// First byte contains the packet counter, followed by packet contents.
// Remote will send a Reply Packet (just contains packet counter)
// Each packet buffer will have a timer counter which decreases after
// every 1/60 seconds (value set at start is 60). If this reaches 0
// that packet will be re-sent and reset the timer value back to 60.
// If the local side receives the reply packet, it will set the timer
// counter to -1.
//
// Gameplay Packets:
// Note: Gameplay counter is separate from normal packet counter.
// Note2: When referring to TCP/IP, it refers to the Normal Packets above.
// Each packet in TCP/IP will contain a byte counter when UDP is
// enabled.
// Each UDP packet will contain a byte counter, the number of packets,
// then each packet will contain a byte size only if there are > 1
// packets. If the packet is just one byte long and contains a value<2,
// it will follow by a byte containing info on how many packets its has
// been like that for (it will not go beyond 32). If the packet is
// more than one byte long, it will repeat that packet as the extra
// packets for the next 3 packets, with the first byte of those packets
// as the byte counter of that packet, then the second as the size.
// Also, the send data will be stored in a 256*32 byte buffer in case
// of packet loss.
// When receiving, since no UDP packets will exceed 32bytes in length,
// there will be a 256*32 byte buffer and a 256 byte flag buffer.
// The flag clearing pointer will move at an offset of 128 from the
// actual point of the receive buffer. When it receives data from
// the UDP (or TCP), if the byte count of the data matches the
// receive pointer, it will just send the data directly and increase the
// receive pointer. Else it will fill the buffer accordingly based on
// the send data (for a maximum of 32 bytes). Then if the bit on the
// flag buffer is set for the current receive pointer, return the
// appropriate buffer and increase receive pointer.
// In case of packet loss, if no data has been received for every 500ms, the
// local side would send a re-send package request. What this would
// do is let the remote side build up a package containing all the
// data from the requested send point to the current receive point.
// A resend request will start off with 0x00,0xFF, then the counter
// number. A resent packet will start off with 0x00,0xFE, the # of
// packets, then the packet data (size of packet, data). A resend will
// only be done if the requested packet is within the past 64 packets.
// In-game chat will be moved to a separate packet in TCP/IP
#ifdef __UNIXSDL__
#include "gblhdr.h"
#define closesocket(A) close(A)
#define CopyMemory(A,B,C) memcpy(A,B,C)
#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
#define UINT unsigned int
#define WORD unsigned short
#define SOCKET int
#define SOCKADDR_IN struct sockaddr_in
#define LPSOCKADDR struct sockaddr*
#define LPHOSTENT struct hostent*
#define HOSTENT struct hostent
#define LPINADDR struct in_addr*
#define LPIN_ADDR struct in_addr*
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#define ioctlsocket ioctl
#define FD_SET_VAR fd_set
#else
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <winsock.h>
#define FD_SET_VAR FD_SET
#endif
int RecvPtr;
int RecvPtr2;
unsigned char RecvFlags[256];
unsigned char RecvBuffer[256*32];
int RecvBufferSize[256];
int SendPtr;
int SendPtr2;
unsigned char SendBuffer[256*32];
int SendBufferSize[256];
int SendRepeated;
int PrevSPacket[16];
int PrevSData[16*32];
int PrevSSize[16];
int PrevSPtr[16];
int tcperr;
unsigned short portval;
int UDPEnable = 1;
int UDPConfig = 1;
int UDPBackTrace = 6;
int blahblahblah = 0;
int CounterA = -1;
int CounterB = -1;
int UDPMode2 = 0;
int packetnum,packetnumhead;
int packetrecvhead;
unsigned char packetdata[2048*16];
unsigned char packetrdata[2048*32];
int packetconfirm[256];
int packetreceived[256];
int packetreceivesize[256];
int packetsize[256];
unsigned char cpacketdata[2048+32];
UINT ConnectAddr;
int packettimeleft[256];
int packetresent[256];
int PacketCounter=0;
unsigned char CLatencyVal=0;
SOCKET gamesocket; /* tcp socket for the game */
SOCKET serversocket; /* tcp socket when the server is listening */
SOCKET ugamesocket; /* udp socket sending */
SOCKET userversocket; /* udp socket listening */
SOCKADDR_IN serveraddress; /* address of the server */
SOCKADDR_IN ugameaddress; /* address of the server */
SOCKADDR_IN userveraddress; /* address of the server */
char blah[256];
char remotehost[256];
char hostname[50] = "IP N/A";
// Function Prototypes
int SendData(int dsize,unsigned char *dptr);
int GetData(int dsize,unsigned char *dptr);
int GetLeftUDP();
/**********************************************************\
* Initialize the zsnes tcpip module *
* - no parameters *
* - return 0 on success other value on error *
* *
* - no known side effects *
\**********************************************************/
int InitTCP()
{
#ifndef __UNIXSDL__
WORD versionneeded = MAKEWORD(2,2);
WSADATA wsadata;
#endif
UDPEnable=0;
#ifndef __UNIXSDL__
/* Startup winsock */
WSAStartup(versionneeded, &wsadata);
/* Verify version number and exit on wrong version */
if (wsadata.wVersion != versionneeded)
{
return(-1);
}
serversocket=INVALID_SOCKET;
#endif
return(0);
}
/**********************************************************\
* Deinitialize the zsnes tcpip module *
* - no parameters *
* *
* - no known side effects *
\**********************************************************/
void DeInitTCP()
{
#ifndef __UNIXSDL__
WSACleanup();
#endif
}
/**********************************************************\
* Gets UDP Status through sending data *
* - no parameters *
* *
* - no known side effects *
\**********************************************************/
void GetUDPStatus() {
int retval;
UDPEnable=UDPConfig;
if (!UDPEnable){
blah[0]=0;
retval = send(gamesocket,blah,1,0);
gethostname(blah,255);
retval = send(gamesocket,blah,strlen(blah),0);
}
else {
blah[0]=1;
retval = send(gamesocket,blah,1,0);
gethostname(blah,255);
retval = send(gamesocket,blah,strlen(&blah[1])+1,0);
}
retval = recv(gamesocket,blah,256,0);
if (blah[0]==0) UDPEnable=0;
retval = recv(gamesocket,blah,256,0);
}
/**********************************************************\
* Connect to game server *
* - parameters *
* - pointer server name *
* - server port *
* - return 0 on success other value on error *
* *
* - no known side effects *
\**********************************************************/
int isipval(char *name){
int i=0;
while(name[i]!=0){
if (!((name[i]=='.') || ((name[i]>='0') && (name[i]<='9'))))
return(0);
i++;
}
return(1);
}
int ConnectServer(char *servername, unsigned int port)
{
char blah[255];
int retval,i;
LPHOSTENT host1=NULL;
int yesip;
packetnum = 0;
packetnumhead = 0;
packetrecvhead = 0;
RecvPtr = 0;
SendPtr = 0;
RecvPtr2 = 0;
SendPtr2 = 0;
ConnectAddr = 0;
SendRepeated = 0;
for (i=0;i<16;i++)
PrevSPacket[i]=0;
/* get host and verify if it is valid */
yesip = isipval(servername);
if (!yesip){
host1 = gethostbyname(servername);
if (host1 == NULL)
{
return(-1);
}
}
// return(-1);
if (UDPConfig) UDPEnable = 1;
if (UDPEnable)
{
PacketCounter=1;
for (i=0;i<256;i++) {packettimeleft[i]=-1; packetconfirm[i]=1; packetreceived[i]=0; RecvFlags[i]=0;}
userveraddress.sin_family = AF_INET;
ugameaddress.sin_family = AF_INET;
if (!yesip)
{
ugameaddress.sin_addr = *( (LPIN_ADDR) *host1->h_addr_list );
}
else
{
ugameaddress.sin_addr.s_addr = inet_addr(servername);
}
ConnectAddr = ugameaddress.sin_addr.s_addr;
userveraddress.sin_addr.s_addr = INADDR_ANY;
// port++;
ugameaddress.sin_port = htons((unsigned short) port);
userveraddress.sin_port = htons((unsigned short) port);
// port--;
userversocket = socket(AF_INET, SOCK_DGRAM,0);
ugamesocket = socket(AF_INET, SOCK_DGRAM,0);
if (ugamesocket == INVALID_SOCKET)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
tcperr=WSAGetLastError();
sprintf(blah,"Could not initialize UDP(2) : %d",tcperr);
MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
return(-2);
}
if (userversocket == INVALID_SOCKET)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
tcperr=WSAGetLastError();
sprintf(blah,"Could not initialize UDP(2.5) : %d",tcperr);
MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
return(-2);
}
if (bind(userversocket,(struct sockaddr*)&userveraddress,sizeof(userveraddress))==
SOCKET_ERROR)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
tcperr=WSAGetLastError();
sprintf(blah,"Could not initialize UDP(16) : %d",tcperr);
MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
return(-2);
}
// blah[0]=1;
// retval = sendto(ugamesocket,blah,1,0,(struct sockaddr*)&ugameaddress,sizeof(struct sockaddr));
// if (retval == SOCKET_ERROR) return(-1);
blah[0]=1;
SendData(1,blah);
// retval = sendto(ugamesocket,blah,5,0,(struct sockaddr*)&ugameaddress,sizeof(struct sockaddr));
// blah[0]=0;
// i = sizeof(struct sockaddr);
// retval = recvfrom(userversocket,blah,5,0,(struct sockaddr*)&userveraddress,&i);
// MessageBox(NULL,blah,
// "Error",
// MB_SYSTEMMODAL|MB_OK);
return(0);
// retval = send(gamesocket,blah,1,0);
// retval = recv(gamesocket,blah,1,0);
}
/* create the game socket and verify if it is valid */
gamesocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (gamesocket == INVALID_SOCKET)
{
return(-2);
}
/* initialize server address */
serveraddress.sin_family = AF_INET;
if (!yesip)
serveraddress.sin_addr = *( (LPIN_ADDR) *host1->h_addr_list );
else
serveraddress.sin_addr.s_addr = inet_addr(servername);
serveraddress.sin_port = htons((unsigned short)port);
/* try to connect to the server */
retval = connect( gamesocket,
(LPSOCKADDR)&serveraddress,
sizeof(struct sockaddr));
if (retval == SOCKET_ERROR)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
sprintf(blah,"Could not connect to other side");
MessageBox(NULL,blah,
"Error",
MB_SYSTEMMODAL|MB_OK);
#endif
closesocket(gamesocket);
return(-3);
}
// GetUDPStatus();
return(0);
}
int WaitForServer(){
int i;
if (UDPEnable){
if ((i=GetData(1,blah))){
if ((i==1) && (blah[0]==1))
return(1);
}
return(0);
}
return(1);
}
/**********************************************************\
* Disconnect from game server *
* - no parameters *
* *
* - no known side effects *
\**********************************************************/
void Disconnect()
{
if (UDPEnable)
{
closesocket(ugamesocket);
closesocket(userversocket);
return;
}
PacketCounter=0;
closesocket(gamesocket);
}
/**********************************************************\
* Start the game server *
* - parameters *
- port number
* - return 0 on success other value on error *
* *
* - no known side effects *
\**********************************************************/
int StartServerCycle(unsigned short port)
{
int retval,i;
portval = port;
packetnum = 0;
packetnumhead = 0;
packetrecvhead = 0;
ConnectAddr = 0;
SendRepeated = 0;
RecvPtr = 0;
SendPtr = 0;
RecvPtr2 = 0;
SendPtr2 = 0;
for (i=0;i<16;i++)
PrevSPacket[i]=0;
if (UDPConfig) UDPEnable = 1;
if (UDPEnable)
{
/* get host and verify if it is valid */
PacketCounter=1;
for (i=0;i<256;i++) {packettimeleft[i]=-1; packetconfirm[i]=1; packetreceived[i]=0; RecvFlags[i]=0;}
userveraddress.sin_family = AF_INET;
ugameaddress.sin_family = AF_INET;
userveraddress.sin_addr.s_addr = INADDR_ANY;
ugameaddress.sin_addr.s_addr = INADDR_ANY;
// portval++;
ugameaddress.sin_port = htons((unsigned short) portval);
userveraddress.sin_port = htons((unsigned short) portval);
// portval--;
userversocket = socket(AF_INET, SOCK_DGRAM,0);
ugamesocket = socket(AF_INET, SOCK_DGRAM,0);
if (userversocket == INVALID_SOCKET)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
tcperr=WSAGetLastError();
sprintf(blah,"Could not initialize UDP(5) : %d",tcperr);
MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
return(-2);
}
if (bind(userversocket,(struct sockaddr*)&userveraddress,sizeof(userveraddress))==
SOCKET_ERROR)
{
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
tcperr=WSAGetLastError();
sprintf(blah,"Could not initialize UDP(6) : %d",tcperr);
MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
return(-2);
}
blah[0]=2;
blah[1]='C';
blah[2]='B';
blah[3]='A';
blah[4]=0;
// retval = recvfrom(userversocket,blah,5,0,
// (struct sockaddr *)&userveraddress,&socklen);
ugameaddress.sin_addr.s_addr = userveraddress.sin_addr.s_addr;
ugamesocket = socket(AF_INET, SOCK_DGRAM,0);
return(0);
// retval = send(gamesocket,blah,1,0);
// retval = recv(gamesocket,blah,1,0);
}
/* Create the listen socket */
serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serversocket == INVALID_SOCKET)
{
#ifndef __UNIXSDL__
tcperr=WSAGetLastError();
#endif
return(-1);
}
serveraddress.sin_family = AF_INET;
serveraddress.sin_addr.s_addr = INADDR_ANY;
serveraddress.sin_port = htons(port);
/* bind name and socket */
retval = bind(serversocket,
(LPSOCKADDR)&serveraddress,
sizeof(struct sockaddr));
if (retval == SOCKET_ERROR)
{
#ifndef __UNIXSDL__
tcperr=WSAGetLastError();
#endif
closesocket(serversocket);
return(-2);
}
/* setup socket to listen */
retval = listen(serversocket, SOMAXCONN);
if (retval == SOCKET_ERROR)
{
#ifndef __UNIXSDL__
tcperr=WSAGetLastError();
#endif
closesocket(serversocket);
return(-3);
}
return 0;
}
int acceptzuser()
{
if (UDPEnable)
{
return(0);
}
/* wait for connection */
gamesocket = accept(serversocket, NULL, NULL);
if (gamesocket == INVALID_SOCKET)
{
#ifndef __UNIXSDL__
tcperr=WSAGetLastError();
#endif
closesocket(serversocket);
serversocket=-1;
return(-1);
}
// GetUDPStatus();
return(0);
}
int ServerCheckNewClient()
{
FD_SET_VAR zrf;
struct timeval nto;
int r;
if (UDPEnable)
{
r=GetData(256,blah);
if (r == -1) return(-1);
if (r > 0){
ugameaddress.sin_addr.s_addr=userveraddress.sin_addr.s_addr;
ConnectAddr = ugameaddress.sin_addr.s_addr;
blah[0]=1;
r=SendData(1,blah);
return(1);
}
return(0);
}
if(serversocket == INVALID_SOCKET)
{
return(-1);
}
nto.tv_sec=0;
nto.tv_usec=0; /* return immediately */
FD_ZERO(&zrf);
FD_SET(serversocket,&zrf);
r=select(serversocket+1,&zrf,0,0,&nto);
if(r == -1)
{
#ifndef __UNIXSDL__
tcperr=WSAGetLastError();
#endif
return(-2);
}
if(r == 0)
{
return(0);
}
if(FD_ISSET(serversocket,&zrf))
{
return 1;
}
return(0);
}
/**********************************************************\
* Stop the game server *
* - no parameters *
* *
* - no known side effects *
\**********************************************************/
void StopServer()
{
if (UDPEnable)
{
closesocket(ugamesocket);
closesocket(userversocket);
return;
}
PacketCounter=0;
closesocket(gamesocket);
closesocket(serversocket);
}
/**********************************************************\
* Send data *
* - parameters : *
* - size of data *
* - pointer to data *
* - return 0 on success other value on error *
* *
* - side effects : *
* - close the socket on error *
\**********************************************************/
int PacketReceive()
{
int dataleft,i,i2,i3,i4,i5,i6,i7,retval;
dataleft=GetLeftUDP();
if (dataleft<=0) return(dataleft);
i = sizeof(userveraddress);
retval = recvfrom(userversocket,cpacketdata,2048+32,0,(struct sockaddr *)&userveraddress,&i);
if ((ConnectAddr!=0) && (ConnectAddr != userveraddress.sin_addr.s_addr)) return(0);
if (retval == SOCKET_ERROR)
{
closesocket(ugamesocket);
return(-1);
}
if ((cpacketdata[0]==1) && (retval>0)) {
i=(unsigned char)cpacketdata[1];
blah[0]=2;
blah[1]=cpacketdata[1];
sendto(ugamesocket,blah,2,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
if (!packetreceived[i]){
packetreceived[i]=1;
packetreceivesize[i]=retval-2;
CopyMemory(&(packetrdata[2048*(i & 0x0F)]),&(cpacketdata[2]),retval-2);
}
}
if (cpacketdata[0]==2){
packetconfirm[cpacketdata[1]]=1;
while ((packetconfirm[packetnumhead]) && (packetnum!=packetnumhead))
packetnumhead=(packetnumhead+1) & 0xFF;
}
if ((cpacketdata[0]==16) && (cpacketdata[1]!=SendPtr)){
i=cpacketdata[1];
cpacketdata[0]=17;
cpacketdata[2]=SendPtr;
i3=3;
while (i!=SendPtr){
cpacketdata[i3]=SendBufferSize[i];
i3++;
for (i4=0;i4<SendBufferSize[i];i4++){
cpacketdata[i3]=SendBuffer[i4+(i << 5)];
i3++;
}
i=(i+1) & 0xFF;
}
sendto(ugamesocket,cpacketdata,i3,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
return(0);
}
if (cpacketdata[0]==17){
i2=cpacketdata[1];
i3=3;
while (i2!=cpacketdata[2]){
i4=cpacketdata[i3];
i3++;
RecvFlags[i2]=1;
RecvBufferSize[i2]=i4;
for (i5=0;i5<i4;i5++){
RecvBuffer[(i2 << 5)+i5]=cpacketdata[i3];
i3++;
}
i2=(i2+1) & 0xFF;
}
}
i2=RecvPtr+(RecvPtr2 << 8);
i3=(cpacketdata[2]+(cpacketdata[3] << 8))-i2;
if (i3<0) i3+=65536;
if ((((cpacketdata[0] & 0xF7)==4) || ((cpacketdata[0] & 0xF7)==5))
&& ((i3>=0) && (i3<=127))) {
CLatencyVal=cpacketdata[1];
i=cpacketdata[2];
i3=0;
if ((cpacketdata[0] & 0x07)==4){
for (i2=0;i2<cpacketdata[4];i2++){
RecvBuffer[((i-i2) & 0xFF) << 5] = 0;
RecvBuffer[(((i-i2) & 0xFF) << 5)+1] = CLatencyVal;
RecvFlags[((i-i2) & 0xFF)] = 1;
RecvBufferSize[((i-i2) & 0xFF)] = 2;
}
i3+=5;
} else {
for (i2=0;i2<cpacketdata[4];i2++){
RecvBuffer[(i << 5) + i2] = cpacketdata[i2+5];
}
RecvFlags[i] = 1;
RecvBufferSize[i] = cpacketdata[4];
i3+=cpacketdata[4]+5;
}
if (cpacketdata[0] & 0x08){
retval=cpacketdata[i3];
i3++;
for (i2=0;i2<retval;i2++){
i=cpacketdata[i3];
i5=cpacketdata[i3+1];
i3+=2;
RecvFlags[i] = 1;
RecvBufferSize[i] = i5;
if ((cpacketdata[i3]==0) && (i5==3)){
i7 = cpacketdata[i3+2];
for (i6=0;i6<i7;i6++){
RecvFlags[(i-i6) & 0xFF] = 1;
RecvBufferSize[(i-i6) & 0xFF] = 2;
}
for (i4=0;i4<i5;i4++){
for (i6=0;i6<i7;i6++)
RecvBuffer[(((i-i6) & 0xFF) << 5)+i4]=cpacketdata[i3];
i3++;
}
}
else
{
for (i4=0;i4<i5;i4++){
RecvBuffer[(i << 5)+i4]=cpacketdata[i3];
i3++;
}
}
}
}
}
return(0);
}
void PacketResend()
{
int i;
for (i=0;i<256;i++) {
if ((packettimeleft[i]==0) && (packetconfirm[i]==0)){
packettimeleft[i]=180;
if (packetresent[i]==1) packettimeleft[i]=60;
if (packetresent[i]==2) packettimeleft[i]=90;
if (packetsize[i]>512) packettimeleft[packetnum]=60*3;
packetresent[i]++;
CopyMemory(&(cpacketdata[2]),&(packetdata[2048*(i & 0x0F)]),packetsize[i]);
cpacketdata[0]=1;
cpacketdata[1]=(char)i;
sendto(ugamesocket,cpacketdata,packetsize[i]+2,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
}
}
}
extern void UpdateVFrame(void);
int SendData(int dsize,unsigned char *dptr)
{
int retval;
if (UDPEnable){
/* retval = sendto(ugamesocket,dptr,dsize,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
return(0); */
if (((packetnum-packetnumhead) & 0xFF) >= 15){
// sprintf(message1,"Packet Overflow.");
// MessageBox (NULL, message1, "Init Error" , MB_ICONERROR );
// wait for receive packet, call JoyRead while waiting
while (((packetnum-packetnumhead) & 0xFF) >= 15){
PacketResend();
PacketReceive();
UpdateVFrame();
while ((packetconfirm[packetnumhead]) && (packetnum!=packetnumhead))
packetnumhead=(packetnumhead+1) & 0xFF;
}
}
CopyMemory(&(cpacketdata[2]),dptr,dsize);
CopyMemory(&(packetdata[2048*(packetnum & 0x0F)]),dptr,dsize);
packetsize[packetnum]=dsize;
packetconfirm[packetnum]=0;
cpacketdata[0]=1;
cpacketdata[1]=(char)packetnum;
retval = sendto(ugamesocket,cpacketdata,dsize+2,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
packettimeleft[packetnum]=60;
if (dsize>512) packettimeleft[packetnum]=90;
packetresent[packetnum]=1;
packetnum=(packetnum+1) & 0xFF;
if (retval == SOCKET_ERROR)
{
closesocket(ugamesocket);
return(-1);
}
return(0);
}
/* send data with the socket */
retval = send(gamesocket,dptr,dsize,0);
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
return(0);
}
extern int PacketSendSize;
extern unsigned char PacketSendArray[2048+256];
int SendDataNop()
{
return (SendData(PacketSendSize,PacketSendArray));
}
/**********************************************************\
* Send data UDP *
* - parameters : *
* - size of data *
* - pointer to data *
* - return 0 on success other value on error *
* *
* - side effects : *
* - close the socket on error *
\**********************************************************/
int AttachEnd(int psb){
int i,i2,i3,ps;
//int PrevSPacket[4];
//int PrevSData[4*32];
//int PrevSSize[4];
ps=psb;
i2=0;
for (i=0;i<(UDPBackTrace-1);i++){
if (PrevSPacket[i]) i2++;
}
// if (PrevSPacket[0]) i2=0;
if (i2){
cpacketdata[0]+=8;
cpacketdata[ps]=(char)i2;
ps++;
for (i=0;i<(UDPBackTrace-1);i++){
if (PrevSPacket[i]){
cpacketdata[ps]=PrevSPtr[i];
cpacketdata[ps+1]=PrevSSize[i];
ps+=2;
for (i3=0;i3<PrevSSize[i];i3++){
cpacketdata[ps]=PrevSData[i*32+i3];
ps++;
}
}
}
for (i=0;i<(UDPBackTrace-2);i++){
PrevSPacket[i]=PrevSPacket[i+1];
PrevSSize[i]=PrevSSize[i+1];
PrevSPtr[i]=PrevSPtr[i+1];
CopyMemory(&(PrevSData[i*32]),&(PrevSData[i*32+32]),32);
}
}
return ps;
}
int SendDataUDP(int dsize,unsigned char *dptr)
{
int retval,i;
int packetsize;
// return (SendData(dsize,dptr));
if (UDPEnable){
/*int SendPtr;
char SendBuffer[256*32];
char SendBufferSize[256];*/
blahblahblah++;
packetsize = 0;
for (i=0;i<dsize;i++)
SendBuffer[SendPtr*32+i]=dptr[i];
SendBufferSize[SendPtr]=dsize;
if ((dsize == 2) && (dptr[0]<=1)){
if (SendRepeated < 32) SendRepeated++;
cpacketdata[0]=4;
cpacketdata[1]=dptr[1];
cpacketdata[2]=(char)SendPtr;
cpacketdata[3]=(char)SendPtr2;
cpacketdata[4]=(char)SendRepeated;
packetsize=5;
packetsize=AttachEnd(packetsize);
PrevSPacket[UDPBackTrace-2]=0;
SendPtr=(SendPtr+1) & 0xFF;
if (!SendPtr) SendPtr2=(SendPtr2+1) & 0xFF;
retval = sendto(ugamesocket,cpacketdata,packetsize,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
} else {
if (SendRepeated){
PrevSPacket[UDPBackTrace-2]=1;
PrevSSize[UDPBackTrace-2]=3;
PrevSData[(UDPBackTrace-2)*32]=0;
PrevSData[(UDPBackTrace-2)*32+1]=dptr[1];
PrevSData[(UDPBackTrace-2)*32+2]=SendRepeated;
PrevSPtr[UDPBackTrace-2]=(SendPtr-1) & 0xFF;
}
SendRepeated=0;
cpacketdata[0]=5;
cpacketdata[1]=dptr[1];
cpacketdata[2]=SendPtr;
cpacketdata[3]=SendPtr2;
cpacketdata[4]=dsize;
packetsize=5;
for (i=0;i<dsize;i++)
cpacketdata[i+5]=dptr[i];
packetsize+=dsize;
packetsize=AttachEnd(packetsize);
PrevSPacket[UDPBackTrace-2]=1;
PrevSSize[UDPBackTrace-2]=dsize;
for (i=0;i<dsize;i++)
PrevSData[(UDPBackTrace-2)*32+i]=dptr[i];
PrevSPtr[UDPBackTrace-2]=SendPtr;
SendPtr=(SendPtr+1) & 0xFF;
if (!SendPtr) SendPtr2=(SendPtr2+1) & 0xFF;
retval = sendto(ugamesocket,cpacketdata,packetsize,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
}
return(0);
}
/* send data with the socket */
retval = sendto(gamesocket,dptr,dsize,0,(struct sockaddr *) &ugameaddress,sizeof(struct sockaddr));
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
return(0);
}
int SendDataUDPNop()
{
return (SendDataUDP(PacketSendSize,PacketSendArray));
}
/**********************************************************\
* Get data left *
* - return size left on success negative value on error *
* *
* - side effects : *
* - close the socket on error *
\**********************************************************/
int GetLeft()
{
int retval;
int tempsize;
retval = ioctlsocket(gamesocket,FIONREAD,&tempsize);
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
return(tempsize);
}
int GetLeftUDP()
{
FD_SET_VAR zrf;
struct timeval nto;
int r;
nto.tv_sec=0;
nto.tv_usec=0; /* return immediately */
FD_ZERO(&zrf);
FD_SET(userversocket,&zrf);
r=select(userversocket+1,&zrf,0,0,&nto);
if (r == SOCKET_ERROR)
{
closesocket(userversocket);
return(-1);
}
return(r);
}
/**********************************************************\
* Receive data *
* - parameters : *
* - size of data *
* - pointer to data *
* - return size on success negative value on error *
* *
* - side effects : *
* - close the socket on error *
\**********************************************************/
int GetData(int dsize,unsigned char *dptr)
{
int retval,i;
int dataleft;
retval=0;
// Temporary UDP routines
if (UDPEnable) {
PacketResend();
PacketReceive();
i=packetrecvhead;
if (packetreceived[i]){
CopyMemory(dptr,&(packetrdata[2048*(i & 0x0F)]),packetreceivesize[i]);
retval = packetreceivesize[i];
packetreceived[(i+128) & 0xFF]=0;
packetrecvhead=(packetrecvhead+1) & 0xFF;
return(retval);
}
i=RecvPtr;
if ((RecvFlags[i]) && (UDPMode2)){
CopyMemory(dptr,&(RecvBuffer[32*i]),RecvBufferSize[i]);
retval = RecvBufferSize[i];
RecvFlags[(i+128) & 0xFF]=0;
RecvPtr=(RecvPtr+1) & 0xFF;
if (!RecvPtr) RecvPtr2=(RecvPtr2+1) & 0xFF;
CounterA=90;
return(retval);
}
if ((CounterA==0) & (UDPMode2)){
// Send 16+RecvPtr
cpacketdata[0]=16;
cpacketdata[1]=RecvPtr;
sendto(ugamesocket,cpacketdata,2,0,(struct sockaddr *)&ugameaddress,sizeof(ugameaddress));
CounterA=90;
return(0);
}
return(0);
}
dataleft=GetLeft();
if(dataleft==0) return(0);
if(dataleft<dsize)
{
dsize=dataleft;
}
/* get data with the socket */
retval = recv(gamesocket,dptr,dsize,0);
if (retval == SOCKET_ERROR)
{
closesocket(gamesocket);
return(-1);
}
return(retval);
}
extern unsigned char PacketRecvArray[2048+256];
int GetDataNop()
{
return (GetData(2048,PacketRecvArray));
}
void GetHostName()
{
HOSTENT* phe;
if (!InitTCP()){
strcpy(hostname,"YOUR IP: ");
gethostname(blah,255);
phe = gethostbyname(blah);
strcpy(blah, inet_ntoa(*(struct in_addr*)phe->h_addr));
strcat(hostname,blah);
}
}
void UDPWait1Sec(){
CounterB=60;
while (CounterB>0)
UpdateVFrame();
}
void UDPClearVars(){
int i;
CounterA=-1;
RecvPtr = 0;
SendPtr = 0;
for (i=0;i<16;i++)
PrevSPacket[i]=0;
for (i=0;i<256;i++)
RecvFlags[i]=0;
}
void UDPEnableMode(){
UDPMode2=1;
}
void UDPDisableMode(){
UDPMode2=0;
}
void WinErrorA2(void){
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
char message1[256];
sprintf(message1,"Failed waiting for checksum.");
MessageBox (NULL, message1, "Init Error" , MB_ICONERROR );
#endif
}
void WinErrorB2(void){
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
char message1[256];
sprintf(message1,"Failed waiting for confirmation.");
MessageBox (NULL, message1, "Init Error" , MB_ICONERROR );
#endif
}
void WinErrorC2(void){
#ifdef __UNIXSDL__
STUB_FUNCTION;
#else
char message1[256];
sprintf(message1,"Failed waiting for confirmation(B).");
MessageBox (NULL, message1, "Init Error" , MB_ICONERROR );
#endif
}