⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioudpmodule.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
字号:
// IOUDPModule.cc
/*/////////////////////////////////////////////////////////////////////////////

	李亦
	2006.06.
/*//////////////////////////////////////////////////////////////////////////////

//#include <platforms.h>


#include <winsock.h>
#include "server/strhandle.h"
#include "server/net/IOUDPModule.h"
#include "platform/platformAssert.h"

namespace CS
{


#pragma pack(push,1)

typedef struct __udpsocket 
{
	SOCKET		sock;
	SOCKADDR_IN sockAddr;
	DWORD			dwState;
	DWORD			dwTime;
	char			svConnectAddr[256];

	__udpsocket *pParent;
	__udpsocket **pChildSockets;
} UDPSOCKET;



typedef struct  _tagUDPHeader
{
	DWORD dwFlags;
} UDPHDR;

#pragma pack(pop)


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//CS_IOHANDLER IOUDPModule::m_ioHandler;
static IOUDPModule	gs_udpIOModule;

IOUDPModule::IOUDPModule()
{
	m_ioHandler.pGetError	= GetError;
	m_ioHandler.pClose	= Close;
	m_ioHandler.pConnect	= Connect;
	m_ioHandler.pFree		= Free;
	m_ioHandler.pListen	= Listen;
	m_ioHandler.pCheckAccept	= CheckAccept;
	m_ioHandler.pCheckSend	= CheckSend;
	m_ioHandler.pCheckRecv	= CheckRecv;
	m_ioHandler.pAccept	= Accept;
	m_ioHandler.pQuery	= Query;
	m_ioHandler.pRecv		= Recv;
	m_ioHandler.pInsert	= Insert;
	m_ioHandler.pRemove	= Remove;
	m_ioHandler.pSend		= Send;
	m_ioHandler.pRecvEx	= RecvEx;
	m_ioHandler.pSendEx	= SendEx;
	m_ioHandler.pGetConnectAddr = GetConnectAddr;
	m_ioHandler.pGetNetAddress	= GetNetAddress;
}

IOUDPModule::~IOUDPModule()
{
}


CS_IOHANDLER* IOUDPModule::GetIOHandler()
{
	return &gs_udpIOModule.m_ioHandler;
	//return &m_ioHandler;
}


INT	RPGAPI IOUDPModule::GetError(void *data)
{
	data;
	return WSAGetLastError();
}


int RPGAPI IOUDPModule::Insert()
{
	// Initialize Winsock 1.1
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0)
		return E_IOFAILED;
	if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return E_IOFAILED;
	}
	
	return E_IOOK;
}


int RPGAPI IOUDPModule::Remove()
{
	// Clean up Winsock 1.1
	WSACleanup();
	return E_IOOK;
}


void * RPGAPI IOUDPModule::Listen(char *svTarget)
{
	UDPSOCKET	*pUDPSock;

	// Get listen port
	int			nPort = 0;
	in_addr		bindAddr;

	bindAddr.S_un.S_addr	= INADDR_ANY;

	if(svTarget == NULL) 
	{
		//nPort=CConfig::GetCfgNum(CConfig::m_szUDPIOConfig,"Default Port");	
	}
	else if(lstrcmpi(svTarget,"RANDOM") != 0) 
	{
		char	svAdr[ADDR_MAX],
				*svPort;
		lstrcpyn(svAdr,svTarget,ADDR_MAX);
		svPort=BreakString(svAdr,":");
		if(svPort == NULL) 
		{
			nPort = atoi(svAdr);
		}
		else
		{
			bindAddr.S_un.S_addr	= inet_addr(svAdr);
			nPort	= atoi(svPort);
		}
	}
	

	// Create listener socket
	SOCKET sock;
	sock	= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(sock == INVALID_SOCKET) 
		return NULL;

	// Bind socket
	SOCKADDR_IN saddr;
	dMemset(&saddr,0,sizeof(SOCKADDR_IN));

	saddr.sin_addr.S_un.S_addr = INADDR_ANY;
	saddr.sin_family	= AF_INET;
	saddr.sin_port		= htons((WORD)nPort);
	
	if(bind(sock,(SOCKADDR*) &saddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) 
	{
		closesocket(sock);
		return NULL;
	}

	int namelen	= sizeof(SOCKADDR_IN);
	getsockname(sock, (SOCKADDR*)&saddr, &namelen);

	// Allocate state structure
	pUDPSock	= (UDPSOCKET *)dMalloc(sizeof(UDPSOCKET));
	if(pUDPSock == NULL)
	{
		closesocket(sock);
		return NULL;
	}

	// Fill in state structure
	dMemset(&(pUDPSock->sockAddr), 0, sizeof(SOCKADDR_IN));
	pUDPSock->sock		= sock;
	pUDPSock->dwState	= US_LISTEN;
	pUDPSock->dwTime	= 0; // No timeout on listening sockets
	pUDPSock->pParent	= NULL;

	pUDPSock->pChildSockets	= (UDPSOCKET **)dMalloc(MAX_UDP_CHILDREN * sizeof(UDPSOCKET *));
	if(pUDPSock->pChildSockets == NULL) 
	{
		dFree(pUDPSock);
		closesocket(sock);
		return NULL;
	}


	int i;
	for(i = 0; i < MAX_UDP_CHILDREN; i++) 
	{
		pUDPSock->pChildSockets[i] = NULL;
	}


	// Fill in connect address
	if(bindAddr.S_un.S_addr == INADDR_ANY) 
	{
		char		svHostName[ADDR_MAX];
		hostent	*he;
		in_addr	*pAddr;

		gethostname(svHostName,ADDR_MAX);
		he = gethostbyname(svHostName);
		if(he)
		{
			pAddr = (in_addr *)he->h_addr_list[0];
			wsprintf(pUDPSock->svConnectAddr,"%u.%u.%u.%u:%u",pAddr->S_un.S_un_b.s_b1,pAddr->S_un.S_un_b.s_b2,pAddr->S_un.S_un_b.s_b3,pAddr->S_un.S_un_b.s_b4,ntohs(saddr.sin_port));
		} 
		else 
		{
			lstrcpyn(pUDPSock->svConnectAddr,"No Connect Addr",ADDR_MAX);
		}
	} 
	else 
	{
		lstrcpyn(pUDPSock->svConnectAddr,svTarget,ADDR_MAX);
	}
	
	return pUDPSock;
}




BOOL RPGAPI IOUDPModule::CheckAccept(void *data)
{
	// Check to see if this is a listening socket

	return TRUE;
}


void * RPGAPI IOUDPModule::Accept(void *data, char *svAddr, int nMaxLen)
{
	// Check for incoming data WSAENOTCONN Net
	int nLen(0); 
	UDPSOCKET	*pUDPSock = (UDPSOCKET*)data;

	if(pUDPSock->dwState != US_LISTEN)
		return NULL;

	if(ioctlsocket(pUDPSock->sock, FIONREAD, (DWORD*)&nLen) < 0)
		return NULL;

	if(nLen > 0)
	{
		// Allocate memory for packet
		SOCKADDR_IN		sockAddrFrom;
		int				nFromLen	= sizeof(SOCKADDR_IN);
		BYTE				*buf		= (BYTE *)dMalloc(nLen);

		if(buf == NULL) 
			return NULL;

		// Peek the message
		nLen	= recvfrom(pUDPSock->sock, (char*)buf, nLen, MSG_PEEK, (SOCKADDR *)&sockAddrFrom, &nFromLen);
		if(nLen < 0)
		{
			dFree(buf);
			return NULL;
		}
				
		// Check to see if this is a new connection
		int i;
		for(i = 0;i < MAX_UDP_CHILDREN; i++) 
		{
			if(pUDPSock->pChildSockets[i]) 
			{
				if(memcmp(&(pUDPSock->pChildSockets[i]->sockAddr), &sockAddrFrom, sizeof(SOCKADDR_IN)) == 0) 
				{
					// Woops, it'sock for another child socket
					dFree(buf);
					return NULL;
				}
			}
		}
		
		// Check to make sure it isn't a 'close' message
		if( (((UDPHDR *)buf)->dwFlags & UF_RST) == UF_RST ) 
		{
			// If so, it isn't for a child connection, so we throw it away.
			nLen = recvfrom(pUDPSock->sock, (char *)buf,nLen,0,(SOCKADDR *)&sockAddrFrom,&nFromLen);		
			dFree(buf);
			return NULL;
		}
		dFree(buf);

		// Find connections table slot
		int		nTimeout = -1;
		DWORD		dwTimeDiff,
					dwLastTimeDiff = 0;

		for(i = 0;i < MAX_UDP_CHILDREN; i++)
		{
			if(pUDPSock->pChildSockets[i] == NULL)
				break;			
			dwTimeDiff = (GetTickCount() - pUDPSock->pChildSockets[i]->dwTime);
			if(dwTimeDiff > dwLastTimeDiff) 
			{
				nTimeout			= i;
				dwLastTimeDiff	= dwTimeDiff;
			}
		}

		// Clean out connections table if things are full
		if(i == MAX_UDP_CHILDREN) 
		{
			if(dwLastTimeDiff >= UDP_TIMEOUT) 
			{
				UDPSOCKET *pios = pUDPSock->pChildSockets[nTimeout];
				pUDPSock->pChildSockets[nTimeout]	= NULL;								
				closesocket(pios->sock);
				pios->dwState	= 0;
				i	= nTimeout;
			} 
			else 
			{
				// Reject accept if things don't work
				return NULL;
			}
		}
	
		// Create accepted socket
		UDPSOCKET	*pIOSockNew;
		pIOSockNew	= (UDPSOCKET *)dMalloc(sizeof(UDPSOCKET));
		if(pIOSockNew == NULL) 
			return NULL;
		
		// Add to connections table
		pUDPSock->pChildSockets[i]	= pIOSockNew;

		// Fill in accepted socket
		DuplicateHandle(GetCurrentProcess(), (HANDLE)(pUDPSock->sock), GetCurrentProcess(), (HANDLE *)&(pIOSockNew->sock),0,FALSE,DUPLICATE_SAME_ACCESS);
		pIOSockNew->sockAddr	= sockAddrFrom;
		pIOSockNew->dwState	= US_CONNECTED;
		pIOSockNew->dwTime	= GetTickCount();
		pIOSockNew->pParent	= pUDPSock;
		pIOSockNew->pChildSockets	= NULL; // No child sockets for accepted sockets

		if(nMaxLen > 16) 
		{
			wsprintf(svAddr,"%3u.%3u.%3u.%3u",
				sockAddrFrom.sin_addr.S_un.S_un_b.s_b1,
				sockAddrFrom.sin_addr.S_un.S_un_b.s_b2,
				sockAddrFrom.sin_addr.S_un.S_un_b.s_b3,
				sockAddrFrom.sin_addr.S_un.S_un_b.s_b4);
		}
		
		return pIOSockNew;
	}

	return NULL;
}



void * RPGAPI IOUDPModule::Connect(char *svTarget)
{
	// Create socket
	SOCKET sock;
	sock	= socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if(sock == INVALID_SOCKET) 
		return NULL;

	// Get target port
	int	nPort;
	char	svHost[256],
			*ptr;

	lstrcpyn(svHost,svTarget,256);
	for(ptr = svHost; ((*ptr)!=':') && ((*ptr)!=NULL); ptr++);
	if((*ptr)==':') 
	{
		*ptr = '\0';
		ptr++;
		nPort = atoi(ptr);
	}
	else 
		return NULL;//nPort=CConfig::GetCfgNum(CConfig::m_szUDPIOConfig,"Default Port");

	// Resolve hostname
	DWORD		addr;
	addr = inet_addr(svHost);

	if(addr == INADDR_NONE) 
	{
		hostent *he = gethostbyname(svHost);
		if(he == NULL) 
		{
			closesocket(sock);
			return NULL;
		}
		addr = *(DWORD *)(he->h_addr_list[0]);
	}

	// Create socket address
	SOCKADDR_IN saddr;
	dMemset(&saddr,0,sizeof(SOCKADDR_IN));

	saddr.sin_addr.S_un.S_addr	= addr;
	saddr.sin_family				= AF_INET;
	saddr.sin_port					= htons((WORD)nPort);
	
	// Allocate internal state structure
	UDPSOCKET *pUDPSock	= (UDPSOCKET *)dMalloc(sizeof(UDPSOCKET));
	if(pUDPSock == NULL) 
	{
		closesocket(sock);
		return NULL;
	}
	
	// Always 'connected' since there is no handshake

	pUDPSock->sock		= sock;
	pUDPSock->sockAddr= saddr;
	pUDPSock->dwState	= US_CONNECTED;
	pUDPSock->dwTime	= GetTickCount();
	pUDPSock->pParent	= NULL;
	pUDPSock->pChildSockets	= NULL; // No child sockets for source socket

	return pUDPSock;
}


int RPGAPI IOUDPModule::Close(void *ios)
{
	int i;
	UDPSOCKET *pUDPSock = (UDPSOCKET *)ios;
	if(pUDPSock == NULL) 
		return E_IOFAILED;

	if((pUDPSock->dwState & US_CONNECTED) || (pUDPSock->dwState & US_LISTEN)) 
	{
		if(pUDPSock->dwState & US_CONNECTED) 
		{
			// Send close packet (don't care if it makes it over though)
			UDPHDR		hdr;
			hdr.dwFlags	= UF_RST;

			sendto(pUDPSock->sock,
					(char *)&hdr,
					sizeof(UDPHDR),
					0,
					(SOCKADDR *)&(pUDPSock->sockAddr),
					sizeof(SOCKADDR_IN));
			if(pUDPSock->pParent != NULL) 
			{
				for(i = 0; i < MAX_UDP_CHILDREN; i++) 
				{
					if(pUDPSock->pParent->pChildSockets[i] == pUDPSock) 
					{
						pUDPSock->pParent->pChildSockets[i]=NULL;
					}
				}
			}
		}

		if(pUDPSock->dwState & US_LISTEN) 
		{
			for(i = 0;i < MAX_UDP_CHILDREN; i++) 
			{
				if(pUDPSock->pChildSockets[i] != NULL) 
				{
					pUDPSock->pChildSockets[i]->pParent = NULL;
				}
			}
			dFree(pUDPSock->pChildSockets);
		}
		closesocket(pUDPSock->sock);
	}
	
	dFree(pUDPSock);
	return E_IOOK;
}



char * RPGAPI IOUDPModule::Query()
{
	return "UDPIO: Back Orifice UDP IO Module v1.0";
}


BOOL RPGAPI IOUDPModule::CheckRecv(void *data)
{
	return TRUE;
}


int RPGAPI IOUDPModule::Recv(void *data, BYTE *pInData, int *pnInDataLen)
{
	AssertWarn(0,"RecvEx调整此处逻辑");
	return RecvEx(data,&pInData, pnInDataLen);
}

int RPGAPI IOUDPModule::RecvEx(void *data, BYTE **pInData, int *pnInDataLen)
{
	UDPSOCKET *pUDPSock = (UDPSOCKET *)data;
	
	// Ensure socket is connected
	if(pUDPSock->dwState != US_CONNECTED) 
		return E_IOFAILED;
	
	// Check for incoming data
	int nLen(0);
	ioctlsocket(pUDPSock->sock, FIONREAD, (DWORD*)&nLen);

	if(nLen >= sizeof(UDPHDR))
	{
		// Allocate buffer for data
		BYTE	*buf=(BYTE *)dMalloc(nLen);
		if(buf == NULL) 
		{
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}

		// Peek at data
		SOCKADDR_IN sockAddrFrom;
		int			nFromLen = sizeof(SOCKADDR_IN);
		INT			lenret;

		lenret = recvfrom(pUDPSock->sock,(char *)buf,nLen,MSG_PEEK,(sockaddr *)&sockAddrFrom,&nFromLen);
		if(lenret < nLen) 
		{
			dFree(buf);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}

		// Ensure that it'sock for this socket
		if(memcmp(&(pUDPSock->sockAddr), &sockAddrFrom, sizeof(SOCKADDR_IN)) != 0) 
		{
			dFree(buf);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOINVALID;
		}
		
		// Get real packet
		nFromLen=sizeof(SOCKADDR_IN);
		lenret=recvfrom(pUDPSock->sock,(char *)buf,nLen,0,(sockaddr *)&sockAddrFrom,&nFromLen);
		if(lenret < nLen) 
		{
			dFree(buf);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}


		// Check for connection reset
		if(((UDPHDR *)buf)->dwFlags & UF_RST) 
		{
			dFree(buf);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}
		
		// Pass data back to application
		*pInData		= (buf+sizeof(UDPHDR));
		*pnInDataLen= (nLen-sizeof(UDPHDR));
		return E_IOOK;
	}
	*pInData		= NULL;
	*pnInDataLen= 0;	
	return E_IOINVALID;

}


BOOL RPGAPI IOUDPModule::CheckSend(void *data)
{
	data;
	return TRUE;
}

int RPGAPI IOUDPModule::Send(void *data, BYTE *pData, int nDataLen)
{
	return SendEx(data, pData, nDataLen);
}

int RPGAPI IOUDPModule::SendEx(void *data, BYTE *pData, int nDataLen)
{
	UDPSOCKET *pUDPSock	= (UDPSOCKET *)data;
	
	// Ensure socket is connected
	if(pUDPSock->dwState != US_CONNECTED) 
		return E_IOFAILED;
	
	// Allocate buffer for header and data
	BYTE *buf	= (BYTE *)dMalloc(nDataLen+sizeof(UDPHDR));
	if(buf == NULL) 
		return E_IOFAILED;

	// Create packet
	((UDPHDR *)buf)->dwFlags	= 0;
	dMemcpy(buf+sizeof(UDPHDR), pData, nDataLen);
	

	// Send packet
	int lenret;
	lenret	= sendto(pUDPSock->sock,(char *)buf,nDataLen+sizeof(UDPHDR),0,(SOCKADDR *)&(pUDPSock->sockAddr),sizeof(SOCKADDR_IN));
	dFree(buf);

	if(lenret == SOCKET_ERROR) 
		return E_IOFAILED;

	if(lenret < nDataLen) 
		return E_IOINVALID;

	return E_IOOK;
}

void RPGAPI IOUDPModule::Free(void *data, BYTE *pBuffer)
{
	if(pBuffer == NULL) 
		return;
	dFree(pBuffer-sizeof(UDPHDR));

}

void*	RPGAPI	IOUDPModule::GetNetAddress(void *data)
{
	UDPSOCKET *pUDPSock = (UDPSOCKET *)data;
	return &pUDPSock->sockAddr;
}


int RPGAPI IOUDPModule::GetConnectAddr(void *data, char *svAddr, int nMaxLen)
{
	UDPSOCKET *pUDPSock = (UDPSOCKET *)data;

	if(nMaxLen < 0)
		return E_IOFAILED;
	if(nMaxLen > ADDR_MAX) 
		nMaxLen = ADDR_MAX;

	lstrcpyn(svAddr, pUDPSock->svConnectAddr, nMaxLen);
	return E_IOOK;
}


};//namespace CS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -