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

📄 net_ipx.c

📁 quake1 dos源代码最新版本
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	if (regs.h.al == 0xff)
	{
		Con_DPrintf("IPX_OpenSocket: socket already open\n");
		return -1;
	}
	if (regs.h.al != 0)
	{
		Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al);
		return -1;
	}
	socket = regs.x.dx;

// grab a handle; fill in the ECBs, and get them listening
	for (handle = 0; handle < IPXSOCKETS; handle++)
	{
		if (ipxsocket[handle] == 0)
		{
			ipxsocket[handle] = socket;
			readlist[handle] = NULL;
			sequence[handle] = 0;
			for (n = 0; n < IPXSOCKBUFFERS; n ++)
			{
				lma->socketbuffer[handle][n].ecb.socket = socket;
				lma->socketbuffer[handle][n].ecb.inUse = 0;
				if (n)
					IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb);
			}
			handlesInUse++;
			return handle;
		}
	}

	// "this will NEVER happen"
	Sys_Error("IPX_OpenSocket: handle allocation failed\n");
	return -1;
}

//=============================================================================

int IPX_CloseSocket(int handle)
{
	// if there's a send in progress, give it one last chance
	if (lma->socketbuffer[handle][0].ecb.inUse != 0)
		IPX_RelinquishControl();

	// close the socket (all pending sends/received are cancelled)
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_CLOSE;
	regs.x.dx = ipxsocket[handle];
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);

	ipxsocket[handle] = 0;
	handlesInUse--;

	return 0;
}

//=============================================================================

int IPX_Connect (int handle, struct qsockaddr *addr)
{
	IPXaddr ipxaddr;

	Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
	if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
	{
		Con_Printf("Get Local Target failed\n");
		return -1;
	}

	return 0;
}

//=============================================================================

int IPX_CheckNewConnections (void)
{
	int n;

	if (net_acceptsocket == -1)
		return -1;

	for (n = 1; n < IPXSOCKBUFFERS; n ++)
		if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
			return net_acceptsocket;
	return -1;
}

//=============================================================================

int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
{
	ECB		*ecb;
	ipx_lowmem_buffer_t *rcvbuf;
	int		copylen;

	ProcessReadyList(handle);
tryagain:
	if (readlist[handle] == NULL)
		return 0;
	ecb = readlist[handle];
	readlist[handle] = ecb->link;

	if (ecb->completionCode != 0)
	{
		Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode);
		ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
		IPX_ListenForPacket(ecb);
		goto tryagain;
	}

	rcvbuf = (ipx_lowmem_buffer_t *)ecb;

	// copy the data up to the buffer
	copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader));
	if (len < copylen)
		Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen);
	Q_memcpy(buf, rcvbuf->data, copylen);

	// fill in the addr if they want it
	if (addr)
	{
		((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE;
		Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr));
		((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0;
		((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0;
	}

	// update the send ecb's immediate address
	Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6);

	// get this ecb listening again
	rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
	IPX_ListenForPacket(&rcvbuf->ecb);
	return copylen;
}

//=============================================================================

int IPX_Broadcast (int handle, byte *buf, int len)
{
	struct sockaddr_ipx addr;
	int ret;

	Q_memset(addr.sipx_addr.network, 0x00, 4);
	Q_memset(addr.sipx_addr.node, 0xff, 6);
	addr.sipx_port = htons(net_hostport);
	Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
	ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr);
	return ret;
}

//=============================================================================

int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
{
	// has the previous send completed?
	while (lma->socketbuffer[handle][0].ecb.inUse != 0)
		IPX_RelinquishControl();

	switch (lma->socketbuffer[handle][0].ecb.completionCode)
	{
		case 0x00: // success
		case 0xfc: // request cancelled
			break;

		case 0xfd: // malformed packet
		default:
			Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode);
			break;

		case 0xfe: // packet undeliverable
		case 0xff: // unable to send packet
			Con_Printf("IPX lost route, trying to re-establish\n");

			// look for a new route
			if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
				return -1;

			// re-send the one that failed
			regs.x.cs = ipx_cs;
			regs.x.ip = ipx_ip;
			regs.x.bx = IPX_SEND;
			regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
			regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
			__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);

			// report that we did not send the current one
			return 0;
	}

	// ecb : length
	lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len;

	// ipx header : type
	lma->socketbuffer[handle][0].header.type = PTYPE_IPX;

	// ipx header : destination
	Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));

	// sequence number
	lma->socketbuffer[handle][0].sequence = sequence[handle];
	sequence[handle]++;

	// copy down the data
	Q_memcpy(lma->socketbuffer[handle][0].data, buf, len);

	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_SEND;
	regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
	regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);

	return len;
}

//=============================================================================

char *IPX_AddrToString (struct qsockaddr *addr)
{
	static char buf[28];

	sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
		((struct sockaddr_ipx *)addr)->sipx_addr.network[0],
		((struct sockaddr_ipx *)addr)->sipx_addr.network[1],
		((struct sockaddr_ipx *)addr)->sipx_addr.network[2],
		((struct sockaddr_ipx *)addr)->sipx_addr.network[3],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[0],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[1],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[2],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[3],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[4],
		((struct sockaddr_ipx *)addr)->sipx_addr.node[5],
		ntohs(((struct sockaddr_ipx *)addr)->sipx_port)
		);
	return buf;
}

//=============================================================================

int IPX_StringToAddr (char *string, struct qsockaddr *addr)
{
	int  val;
	char buf[3];

	buf[2] = 0;
	Q_memset(addr, 0, sizeof(struct qsockaddr));
	addr->sa_family = AF_NETWARE;

#define DO(src,dest)	\
	buf[0] = string[src];	\
	buf[1] = string[src + 1];	\
	if (sscanf (buf, "%x", &val) != 1)	\
		return -1;	\
	((struct sockaddr_ipx *)addr)->sipx_addr.dest = val

	DO(0, network[0]);
	DO(2, network[1]);
	DO(4, network[2]);
	DO(6, network[3]);
	DO(9, node[0]);
	DO(11, node[1]);
	DO(13, node[2]);
	DO(15, node[3]);
	DO(17, node[4]);
	DO(19, node[5]);
#undef DO

	sscanf (&string[22], "%u", &val);
	((struct sockaddr_ipx *)addr)->sipx_port = htons(val);

	return 0;
}

//=============================================================================

int IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
{
	Q_memset(addr, 0, sizeof(struct qsockaddr));
	addr->sa_family = AF_NETWARE;
	IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr);
	((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle];
	return 0;
}

//=============================================================================

int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
	strcpy(name, IPX_AddrToString(addr));
	return 0;
}

//=============================================================================

int IPX_GetAddrFromName (char *name, struct qsockaddr *addr)
{
	int n;
	char buf[32];

	n = strlen(name);

	if (n == 12)
	{
		sprintf(buf, "00000000:%s:%u", name, net_hostport);
		return IPX_StringToAddr (buf, addr);
	}
	if (n == 21)
	{
		sprintf(buf, "%s:%u", name, net_hostport);
		return IPX_StringToAddr (buf, addr);
	}
	if (n > 21 && n <= 27)
		return IPX_StringToAddr (name, addr);

	return -1;
}

//=============================================================================

int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
	if (addr1->sa_family != addr2->sa_family)
		return -1;

	if(memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10))
		return -1;

	if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port)
		return 1;

	return 0;
}

//=============================================================================

int IPX_GetSocketPort (struct qsockaddr *addr)
{
	return ntohs(((struct sockaddr_ipx *)addr)->sipx_port);
}


int IPX_SetSocketPort (struct qsockaddr *addr, int port)
{
	((struct sockaddr_ipx *)addr)->sipx_port = htons(port);
	return 0;
}

//=============================================================================

⌨️ 快捷键说明

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