ref: 2feac9be1d1bebe1a05a47c0adf0254228ca558d
dir: /net_udp_plan9.c/
#include "quakedef.h"
#include <ip.h>
#include <thread.h>
Addr myip;
static int lpid = -1, afd;
static Channel *lchan;
int
UDP_Init(void)
{
char *s;
byte ip[IPaddrlen];
fmtinstall('I', eipfmt);
if(strcmp(hostname.string, "UNNAMED") == 0)
if((s = getenv("sysname")) != nil){
setcvar("hostname", s);
free(s);
}
myipaddr(ip, nil);
snprint(myip.ip, sizeof myip.ip, "%I", ip);
snprint(myip.srv, sizeof myip.srv, "%hud", Udpport);
return 0;
}
void
UDP_Shutdown(void)
{
UDP_Listen(false);
}
static void
lproc(void *)
{
int fd, lfd;
char adir[40], ldir[40], data[100];
snprint(data, sizeof data, "%s/udp!*!%s", netmtpt, myip.srv);
if((afd = announce(data, adir)) < 0)
sysfatal("announce: %r");
for(;;){
if((lfd = listen(adir, ldir)) < 0
|| (fd = accept(lfd, ldir)) < 0
|| close(lfd) < 0
|| send(lchan, &fd) < 0)
break;
}
}
static void
udpname(void)
{
if((lchan = chancreate(sizeof(int), 0)) == nil)
sysfatal("chancreate: %r");
if((lpid = proccreate(lproc, nil, 8192)) < 0)
sysfatal("proccreate lproc: %r");
}
void
UDP_Listen(bool on)
{
if(lpid < 0){
if(on)
udpname();
return;
}
if(on)
return;
close(afd);
chanclose(lchan);
threadint(lpid);
chanfree(lchan);
lpid = -1;
}
void
udpinfo(Addr *a)
{
NetConnInfo *nc;
if((nc = getnetconninfo(nil, a->fd)) == nil){
Con_DPrintf("getnetconninfo: %r\n");
return;
}
strncpy(a->ip, nc->raddr, sizeof(a->ip)-1);
strncpy(a->srv, nc->rserv, sizeof(a->srv)-1);
strncpy(a->sys, nc->rsys, sizeof(a->sys)-1);
free(nc);
}
int
UDP_Connect(Addr *a)
{
if((a->fd = dial(netmkaddr(a->ip, "udp", a->srv), myip.srv, nil, nil)) < 0){
Con_DPrintf("dial: %r\n");
return -1;
}
return 0;
}
int
getnewcon(Addr *a)
{
if(lpid < 0)
return 0;
if(nbrecv(lchan, &a->fd) == 0)
return 0;
udpinfo(a);
return 1;
}
int
udpread(byte *buf, int len, Addr *a)
{
int n;
if(flen(a->fd) < 1)
return 0;
if((n = read(a->fd, buf, len)) <= 0){
Con_DPrintf("udpread: %r\n");
return -1;
}
return n;
}
int
udpwrite(byte *buf, int len, Addr *a)
{
if(write(a->fd, buf, len) != len){
Con_DPrintf("udpwrite: %r\n");
return -1;
}
return len;
}
char *
UDP_AddrToString(Addr *a)
{
char *p;
static char buf[52];
strncpy(buf, a->sys, sizeof(buf)-1);
if((p = strrchr(buf, '!')) != nil)
*p = ':';
return buf;
}
int
UDP_Broadcast(byte *buf, int len)
{
int fd;
char ip[46];
snprint(ip, sizeof ip, "%I", IPv4bcast);
if((fd = dial(netmkaddr(ip, "udp", myip.srv), myip.srv, nil, nil)) < 0){
Con_DPrintf("UDP_Broadcast: %r\n");
return -1;
}
if(write(fd, buf, len) != len)
Con_DPrintf("write: %r\n");
close(fd);
return 0;
}
int
getip(char *s, Addr *a)
{
int fd, n;
char buf[128], *f[4], *p;
snprint(buf, sizeof buf, "%s/cs", netmtpt);
if((fd = open(buf, ORDWR)) < 0)
sysfatal("open: %r");
if((p = strrchr(s, '!')) == nil)
p = myip.srv;
else
p++;
snprint(buf, sizeof buf, "udp!%s!%s", s, p);
n = strlen(buf);
if(write(fd, buf, n) != n){
Con_DPrintf("translating %s: %r\n", s);
return -1;
}
seek(fd, 0, 0);
if((n = read(fd, buf, sizeof(buf)-1)) <= 0){
Con_DPrintf("reading cs tables: %r");
return -1;
}
buf[n] = 0;
close(fd);
if(getfields(buf, f, 4, 0, " !") < 2)
goto err;
strncpy(a->ip, f[1], sizeof(a->ip)-1);
a->ip[sizeof(a->ip)-1] = 0;
strncpy(a->srv, f[2], sizeof(a->srv)-1);
a->srv[sizeof(a->srv)-1] = 0;
snprint(a->sys, sizeof a->sys, "%s!%s", a->ip, a->srv);
return 0;
err:
Con_DPrintf("bad cs entry %s", buf);
return -1;
}
int
UDP_AddrCompare(Addr *a1, Addr *a2)
{
if(strcmp(a1->ip, a2->ip) != 0)
return -1;
if(strcmp(a1->srv, a2->srv) != 0)
return 1;
return 0;
}
u16int
UDP_GetSocketPort(Addr *a)
{
return atoi(a->srv);
}
void
UDP_SetSocketPort(Addr *a, u16int port)
{
snprint(a->srv, sizeof a->srv, "%hud", port); /* was htons'ed */
}