ref: ae40b3ece15d77a2255281de17a5882107b1a744
dir: /plan9/net_udp.c/
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <ctype.h>
#include <bio.h>
#include <ndb.h>
#include "../q_shared.h"
/* FIXME: only loopback works, the rest is complete bullshit */
typedef struct Loopmsg Loopmsg;
typedef struct Loopback Loopback;
enum{
LOOPBACK = 0x7f000001,
MAX_LOOPBACK = 4
};
struct Loopmsg{
byte data[MAX_MSGLEN];
int datalen;
};
struct Loopback{
Loopmsg msgs[MAX_LOOPBACK];
int get;
int send;
};
Loopback loopbacks[2];
int ipfd[2], ipxfd[2];
netadr_t laddr;
qboolean NET_CompareAdr (netadr_t a, netadr_t b)
{
return (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port);
}
/* compares without the port */
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
{
if(a.type != b.type)
return false;
switch(a.type){
case NA_LOOPBACK:
return true;
case NA_IP:
return (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3]);
case NA_IPX:
return !memcmp(a.ipx, b.ipx, 10);
default:
return false;
}
}
char *NET_AdrToString (netadr_t a)
{
static char s[64];
Com_sprintf(s, sizeof(s), "%i.%i.%i.%i:%hi", a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port << 8 | a.port >> 8);
return s;
}
char *NET_BaseAdrToString (netadr_t a)
{
static char s[64];
Com_sprintf(s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
return s;
}
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
qboolean NET_StringToAdr (char *s, netadr_t *a)
{
int i;
char *e, *p, *ss;
Ndb *db;
Ndbtuple *nt;
if(!strcmp(s, "localhost")){
memset(a, 0, sizeof(*a));
a->type = NA_LOOPBACK;
return true;
}
/* FIXMEGASHIT */
if((ss = smprint("%s", s)) == nil) /* don't fuck with someone else's s */
sysfatal("NET_StringToAdr:smprint: %r");
p = ss;
if((e = strchr(p, ':')) != nil){
*e++ = '\0';
a->port = atoi(e);
}
db = ndbopen(nil);
if((nt = ndbgetipaddr(db, ss)) == nil){
ndbclose(db);
return false;
}
if((ss = smprint("%s", nt->val)) == nil) /* get copy of first value found */
sysfatal("NET_StringToAdr:smprint: %r");
p = ss;
for(i = 0; i < 4; i++){
if((e = strchr(p, '.')) != nil)
*e++ = '\0';
a->ip[i] = atoi(p);
p = e;
}
a->type = NA_IP;
free(ss);
ndbfree(nt);
ndbclose(db);
return true;
}
qboolean NET_IsLocalAddress (netadr_t adr)
{
return NET_CompareAdr (adr, laddr);
}
qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
{
int i;
Loopback *loop;
loop = &loopbacks[sock];
if(loop->send - loop->get > MAX_LOOPBACK)
loop->get = loop->send - MAX_LOOPBACK;
if (loop->get >= loop->send)
return false;
i = loop->get & (MAX_LOOPBACK-1);
loop->get++;
memcpy(net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
net_message->cursize = loop->msgs[i].datalen;
*net_from = laddr;
return true;
}
void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t /*to*/)
{
Loopback *loop;
int i;
loop = &loopbacks[sock^1];
i = loop->send & (MAX_LOOPBACK-1);
loop->send++;
memcpy(loop->msgs[i].data, data, length);
loop->msgs[i].datalen = length;
}
qboolean NET_GetPacket (netsrc_t src, netadr_t *from, sizebuf_t *d)
{
int n, protocol, fd;
NetConnInfo *nci;
char addr[21];
if(NET_GetLoopPacket(src, from, d))
return true;
for(protocol = 0 ; protocol < 2 ; protocol++){
if(protocol == 0)
fd = ipfd[src];
else
fd = ipxfd[src];
if(!fd)
continue;
if((n = read(fd, d->data, d->maxsize)) < 0){
fprint(2, "NET_GetPacket:read: %r\n");
Com_Printf("NET_GetPacket: error reading packet\n");
continue;
}
if(n == d->maxsize){
Com_Printf("Oversize packet from %s\n", NET_AdrToString(*from));
continue;
}
d->cursize = n;
/* FIXME */
if((nci = getnetconninfo(nil, fd)) == nil){
fprint(2, "NET_GetPacket:getnetconninfo: %r\n");
return true;
}
seprint(addr, addr+sizeof(addr), "%s:%s", nci->rsys, nci->rserv);
NET_StringToAdr(addr, from);
return true;
}
return false;
}
void NET_SendPacket (netsrc_t src, int length, void *data, netadr_t to)
{
int fd = 0;
switch(to.type){
case NA_LOOPBACK:
NET_SendLoopPacket(src, length, data, to);
return;
case NA_BROADCAST:
case NA_IP:
fd = ipfd[src];
if(!fd)
return;
break;
case NA_IPX:
case NA_BROADCAST_IPX:
fd = ipxfd[src];
if(!fd)
return;
break;
default:
Com_Error(ERR_FATAL, "NET_SendPacket: bad address type");
}
if(write(fd, data, length) != length){
fprint(2, "NET_SendPacket:write: %r\n");
Com_Printf("NET_SendPacket: bad write\n");
}
}
int NET_Socket (char *ifc, int port)
{
int fd;
char addr[21], dir[40], *p;
/* FIXMEGAFUCKEDUPSHIT */
p = seprint(addr, addr+sizeof(addr), "udp!*");
if(ifc != nil || Q_strcasecmp(ifc, "localhost"))
p = seprint(p-1, addr+sizeof(addr), "%s", ifc);
if(port == PORT_ANY)
seprint(p, addr+sizeof(addr), "!%hud", (ushort)port);
if((fd = announce(addr, dir)) < 0){
fprint(2, "NET_Socket:announce: %r\n");
Com_Printf("Net_Socket: announce failed!\n");
return false;
}
return fd; /* FIXME: NO! */
}
void NET_OpenIP (void)
{
cvar_t *port, *ip;
port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET);
ip = Cvar_Get("ip", "localhost", CVAR_NOSET);
/* FIXME: those are ctl fd's! */
if(!ipfd[NS_SERVER])
ipfd[NS_SERVER] = NET_Socket(ip->string, port->value);
if(!ipfd[NS_CLIENT])
ipfd[NS_CLIENT] = NET_Socket(ip->string, PORT_ANY);
}
void NET_OpenIPX (void)
{
}
/* a single player game will only use the loopback code */
void NET_Config (qboolean multiplayer)
{
int i;
if(!multiplayer){ /* shut down any existing sockets */
for(i=0 ; i<2 ; i++){
if(ipfd[i]){
close(ipfd[i]);
ipfd[i] = 0;
}
if(ipxfd[i]){
close(ipxfd[i]);
ipxfd[i] = 0;
}
}
}
else{ /* open sockets */
NET_OpenIP();
NET_OpenIPX();
}
}
void NET_Init (void)
{
}
void NET_Shutdown (void)
{
NET_Config(false); // close sockets
}
/* sleeps msec or until net socket is ready */
void NET_Sleep(int /*msec*/)
{
/* PORTME */
/*
struct timeval timeout;
fd_set fdset;
extern cvar_t *dedicated;
extern qboolean stdin_active;
*/
if(!ipfd[NS_SERVER] || dedicated && !dedicated->value)
return; // we're not a server, just run full speed
/*
FD_ZERO(&fdset);
if (stdin_active)
FD_SET(0, &fdset); // stdin is processed too
FD_SET(ipfd[NS_SERVER], &fdset); // network socket
timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000;
select(ipfd[NS_SERVER]+1, &fdset, NULL, NULL, &timeout);
*/
}