#include <windows.h>
#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/ns.h>
#include <9pm/devip.h>
#undef listen
#undef accept
#undef bind
#pragma comment(lib, "wsock32.lib")
static long
netread(Conv *c, void *a, long n)
{
long r;
r = recv(c->sfd, a, n, 0);
if(r < 0){
pm_oserror();
nexterror();
}
return r;
}
static long
netwrite(Conv *c, void *a, long n)
{
long r;
r = send(c->sfd, a, n, 0);
if(r < 0){
pm_oserror();
nexterror();
}
return r;
}
static void
netclone(Conv *c)
{
int fd, one, type;
if(c->p->name[0] == 't')
type = SOCK_STREAM;
else
type = SOCK_DGRAM;
fd = socket(AF_INET, type, 0);
if(fd < 0){
pm_oserror();
werrstr("devip clone (socket): %r");
nexterror();
}
if(type == SOCK_STREAM){
one = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one));
}
c->sfd = fd;
}
static void
netconnect(Conv *c)
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
hnputs(&sin.sin_port, c->rport);
hnputl(&sin.sin_addr.s_addr, c->raddr);
if(connect(c->sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){
pm_oserror();
werrstr("devip connect: %r");
nexterror();
}
}
/*
* I don't know if this is right. -rsc
*/
static void
netannounce(Conv *c)
{
if(listen(c->sfd, 5) < 0){
pm_oserror();
werrstr("devip announce (listen): %r");
nexterror();
}
}
/*
* I don't know if this is right. -rsc
*/
static void
netlisten(Conv *cv, Conv *lcv)
{
int nfd, len;
struct sockaddr_in sin;
len = sizeof(sin);
nfd = accept(lcv->sfd, (struct sockaddr*)&sin, &len);
if(nfd < 0){
pm_oserror();
werrstr("devip listen (accept): %r");
nexterror();
}
if(sin.sin_family != AF_INET || len != sizeof(sin)){
closesocket(nfd);
error("accepted socket not AF_INET");
}
cv->raddr = nhgetl(&sin.sin_addr.s_addr);
cv->rport = nhgets(&sin.sin_port);
cv->sfd = nfd;
}
static void
netclose(Conv *c)
{
closesocket(c->sfd);
}
Proto udpproto = {
"udp",
netread,
netwrite,
netclone,
netconnect,
netannounce,
netlisten,
netclose,
30,
};
Proto tcpproto = {
"tcp",
netread,
netwrite,
netclone,
netconnect,
netannounce,
netlisten,
netclose,
30,
};
void
ipinit(void (*inst)(Proto*))
{
WSADATA wasdat;
if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0)
sysfatal("no winsock.dll");
inst(&tcpproto);
inst(&udpproto);
}
syntax highlighted by Code2HTML, v. 0.9.1