ipc: strip machinery no peer uses; keep client state in one Keyreq
ipc.c: an AF_UNIX nonblocking connect completes at once or fails with EAGAIN, so the EINPROGRESS/poll/SO_ERROR path and the fcntl juggling were dead; the deadline plumbing checked a clock that cannot fail and re-tested the deadline before every transfer although only waitfd blocks; readfield's truncation and discard loop served the unit test, since every caller owns char[Ipcfieldmax+1]; NULL-argument checks on in-tree encoders are gone (peer validation stays). The primary key frame is Ipckey, not 'legacy'; ipckeysym names the keysym mapping. srv.c: the per-connection capability and caret already lived in the persistent Keyreq; the mirror locals and 'negotiated' flag guarded a protocol rule no client relied on. proccreate never fails in libthread. gtk: focus-out no longer round-trips a reset before closing the socket that releases the engine; the caret dedup compares the packed frame; srvconnect's preedit no-ops and the insimple flag are gone.
This commit is contained in:
85
srv.c
85
srv.c
@@ -11,98 +11,78 @@ static int
|
||||
srvreadreq(int fd, Keyreq *kr, int *want)
|
||||
{
|
||||
uchar req[Ipccaretsz];
|
||||
int type, valid;
|
||||
int valid;
|
||||
int32_t x, y, h;
|
||||
u32int ks, mod;
|
||||
|
||||
if(ipcreadn(fd, req, Ipcreqsz) < 0)
|
||||
return -1;
|
||||
type = ipcreqtype(req);
|
||||
switch(type){
|
||||
case Ipclegacy:
|
||||
ipcunpackreq(req, want, &mod, &ks);
|
||||
*want = 0;
|
||||
kr->ks = 0;
|
||||
kr->mod = 0;
|
||||
switch(ipcreqtype(req)){
|
||||
case Ipckey:
|
||||
ipcunpackreq(req, want, &kr->mod, &kr->ks);
|
||||
kr->op = ipcreqreset(req) ? Keyreset : Keypress;
|
||||
kr->ks = ks;
|
||||
kr->mod = mod;
|
||||
break;
|
||||
return 0;
|
||||
case Ipccap:
|
||||
*want = (req[0] & Ipcreqwant) != 0;
|
||||
kr->op = Keycap;
|
||||
kr->ks = 0;
|
||||
kr->mod = 0;
|
||||
break;
|
||||
return 0;
|
||||
case Ipccaret:
|
||||
if(ipcreadn(fd, req + Ipcreqsz, Ipccaretsz - Ipcreqsz) < 0 ||
|
||||
ipcunpackcaret(req, &valid, &x, &y, &h) < 0)
|
||||
return -1;
|
||||
*want = 0;
|
||||
kr->op = Keycaret;
|
||||
kr->ks = 0;
|
||||
kr->mod = 0;
|
||||
kr->caret.valid = valid;
|
||||
kr->caret.x = x;
|
||||
kr->caret.y = y;
|
||||
kr->caret.h = h;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
return type;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* One Keyreq persists for the connection: the negotiated capability and
|
||||
* the last caret ride along with every request, and the socket closing
|
||||
* releases the engine.
|
||||
*/
|
||||
static void
|
||||
clientthread(void *arg)
|
||||
{
|
||||
Channel *reply;
|
||||
int fd;
|
||||
Keyreq kr;
|
||||
Keyres res;
|
||||
Caret caret;
|
||||
uchar out[Ipcmaxresp];
|
||||
uchar out[Ipcmaxresp], token;
|
||||
char commit[Maxutf], preedit[Maxutf];
|
||||
int cap, n, ncommit, negotiated, npreedit, type, want;
|
||||
uchar token;
|
||||
int fd, n, ncommit, npreedit, want;
|
||||
|
||||
fd = (int)(uintptr)arg;
|
||||
threadsetname("client %d", fd);
|
||||
reply = chancreate(sizeof(Keyres), 0);
|
||||
kr.reply = reply;
|
||||
memset(&kr, 0, sizeof kr);
|
||||
kr.reply = chancreate(sizeof(Keyres), 0);
|
||||
kr.owner = &fd;
|
||||
cap = Cclientpreedit;
|
||||
negotiated = 0;
|
||||
memset(&caret, 0, sizeof caret);
|
||||
kr.cap = cap;
|
||||
kr.caret = caret;
|
||||
while((type = srvreadreq(fd, &kr, &want)) >= 0){
|
||||
if(type == Ipccap){
|
||||
cap = want ? Cclientpreedit : 0;
|
||||
negotiated = 1;
|
||||
}else if(type == Ipclegacy && !negotiated)
|
||||
cap = want ? Cclientpreedit : 0;
|
||||
else if(type == Ipccaret)
|
||||
caret = kr.caret;
|
||||
kr.cap = cap;
|
||||
kr.caret = caret;
|
||||
kr.cap = Cclientpreedit;
|
||||
while(srvreadreq(fd, &kr, &want) >= 0){
|
||||
if(kr.op != Keycaret)
|
||||
kr.cap = want ? Cclientpreedit : 0;
|
||||
chansend(keyc, &kr);
|
||||
chanrecv(reply, &res);
|
||||
if(type == Ipccaret)
|
||||
chanrecv(kr.reply, &res);
|
||||
if(kr.op == Keycaret)
|
||||
continue;
|
||||
ncommit = stoutf(&res.commit, commit, sizeof commit);
|
||||
npreedit = stoutf(&res.preedit, preedit, sizeof preedit);
|
||||
n = ipcpackresp(out, sizeof out,
|
||||
type == Ipccap ? 1 : res.eaten,
|
||||
/* A capability reply is always eaten: it marks the extension. */
|
||||
n = ipcpackresp(out, sizeof out, kr.op == Keycap || res.eaten,
|
||||
commit, ncommit, preedit, npreedit, want);
|
||||
if(n < 0 || ipcsend(fd, out, n) < 0)
|
||||
break;
|
||||
}
|
||||
kr.op = Keyrelease;
|
||||
kr.cap = cap;
|
||||
kr.caret = caret;
|
||||
kr.ks = 0;
|
||||
kr.mod = 0;
|
||||
chansend(keyc, &kr);
|
||||
chanrecv(reply, &res);
|
||||
chanfree(reply);
|
||||
chanrecv(kr.reply, &res);
|
||||
chanfree(kr.reply);
|
||||
close(fd);
|
||||
chanrecv(clientc, &token);
|
||||
}
|
||||
@@ -142,9 +122,6 @@ srvthread(void*)
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if(proccreate(clientthread, (void*)(uintptr)fd, 8192) < 0){
|
||||
chanrecv(clientc, &token);
|
||||
close(fd);
|
||||
}
|
||||
proccreate(clientthread, (void*)(uintptr)fd, 8192);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user