blob: a808ad553b7fba5ccaccb552d67a0718df70854a [file] [log] [blame]
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <sunrpc.h>
enum
{
MaxRead = 17000
};
typedef struct SunMsgFd SunMsgFd;
struct SunMsgFd
{
SunMsg msg;
int fd;
};
typedef struct Arg Arg;
struct Arg
{
SunSrv *srv;
Channel *creply;
Channel *csync;
int fd;
};
static void
sunfdread(void *v)
{
uint n, tot;
int done;
uchar buf[4], *p;
Arg arg = *(Arg*)v;
SunMsgFd *msg;
sendp(arg.csync, 0);
p = nil;
tot = 0;
for(;;){
n = readn(arg.fd, buf, 4);
if(n != 4)
break;
n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
if(arg.srv->chatty) fprint(2, "%.8ux...", n);
done = n&0x80000000;
n &= ~0x80000000;
p = erealloc(p, tot+n);
if(readn(arg.fd, p+tot, n) != n)
break;
tot += n;
if(done){
msg = emalloc(sizeof(SunMsgFd));
msg->msg.data = p;
msg->msg.count = tot;
msg->msg.creply = arg.creply;
sendp(arg.srv->crequest, msg);
p = nil;
tot = 0;
}
}
}
static void
sunfdwrite(void *v)
{
uchar buf[4];
u32int n;
Arg arg = *(Arg*)v;
SunMsgFd *msg;
sendp(arg.csync, 0);
while((msg = recvp(arg.creply)) != nil){
n = msg->msg.count;
buf[0] = (n>>24)|0x80;
buf[1] = n>>16;
buf[2] = n>>8;
buf[3] = n;
if(write(arg.fd, buf, 4) != 4
|| write(arg.fd, msg->msg.data, msg->msg.count) != msg->msg.count)
fprint(2, "sunfdwrite: %r\n");
free(msg->msg.data);
free(msg);
}
}
int
sunsrvfd(SunSrv *srv, int fd)
{
Arg *arg;
arg = emalloc(sizeof(Arg));
arg->fd = fd;
arg->srv = srv;
arg->csync = chancreate(sizeof(void*), 0);
arg->creply = chancreate(sizeof(SunMsg*), 10);
proccreate(sunfdread, arg, SunStackSize);
proccreate(sunfdwrite, arg, SunStackSize);
recvp(arg->csync);
recvp(arg->csync);
chanfree(arg->csync);
free(arg);
return 0;
}