📄 net_ipx.c
字号:
}
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 *)®s);
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 *)®s);
// 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 *)®s);
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 + -