#include #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); }