#include "dat.h" #include "fn.h" static char adir[40]; static Channel *clientc; typedef struct Client Client; struct Client { int fd; uvlong owner; }; int srvreadkey(int fd, Keyreq *kr) { uchar req[Ipcreqsz]; u32int ks, mod; int want; if(ipcreadn(fd, req, sizeof req) < 0) return -1; ipcunpackreq(req, &want, &mod, &ks); kr->op = ipcreqreset(req) ? Keyreset : Keypress; kr->ks = ks; kr->mod = mod; kr->want = want; return 0; } static void clientthread(void *arg) { Client *client; Channel *reply; int fd; Keyreq kr; Keyres res; uchar out[Ipcmaxresp]; char commit[Maxutf], preedit[Maxutf]; int n, ncommit, npreedit; uchar token; client = arg; fd = client->fd; threadsetname("client %d", fd); reply = chancreate(sizeof(Keyres), 0); kr.reply = reply; kr.owner = client->owner; while(srvreadkey(fd, &kr) == 0){ chansend(keyc, &kr); chanrecv(reply, &res); ncommit = stoutf(&res.commit, commit, sizeof commit); npreedit = stoutf(&res.preedit, preedit, sizeof preedit); n = ipcpackresp(out, sizeof out, res.eaten, commit, ncommit, preedit, npreedit, kr.want); if(n < 0 || ipcsend(fd, out, n) < 0) break; } kr.op = Keyrelease; kr.want = 0; chansend(keyc, &kr); chanrecv(reply, &res); chanfree(reply); close(fd); free(client); chanrecv(clientc, &token); } static void srvinit(void) { char addr[64]; snprint(addr, sizeof(addr), "unix!" IPCPATH, getuid()); remove(addr + 5); if(announce(addr, adir) < 0) die("announce: %r"); } void srvthread(void*) { Client *client; char ldir[40]; int fd; uchar token; threadsetname("srv"); srvinit(); token = 0; clientc = chancreate(sizeof token, Maxclients); for(;;){ fd = listen(adir, ldir); if(fd < 0) continue; if(channbsend(clientc, &token) <= 0){ close(fd); continue; } client = emalloc(sizeof *client); client->fd = fd; client->owner = ownernew(); if(proccreate(clientthread, client, 8192) < 0){ chanrecv(clientc, &token); close(fd); free(client); } } }