/* ask for a key */ int convneedkey(Conv *c, Attr *a) { /* * Piggyback key requests in the usual RPC channel. * Wait for the next RPC and then send a key request * in response. The keys get added out-of-band (via the * ctl file), so assume the key has been added when the * next request comes in. * * The convgetrpc seems dodgy, because we might be in * the middle of an rpc, and what about the one that comes * in later? It's all actually okay: convgetrpc is idempotent * until rpcrespond is called, so if we're in the middle of an rpc, * the first convgetrpc is a no-op, the rpcrespond sends back * the needkey, and then the client repeats the rpc we're in * the middle of. Otherwise, if we're not in the middle of an * rpc, the first convgetrpc waits for one, we respond needkey, * and then the second convgetrpc waits for another. Because * there is no second response, eventually the caller will get * around to asking for an rpc itself, at which point the already * gotten rpc will be returned again. */ if(convgetrpc(c, -1) == nil) return -1; if(conv->proto!=nil && c->proto->keyprompt!=nil) a = addattrs(parseattr(c->proto->keyprompt), a); flog("convneedkey %A", a); rpcrespond(c, "needkey %A", a); if(convgetrpc(c, -1) == nil) return -1; flog("convneedkey returning"); return 0; }
/* info ::= num | num '=' attr* defn */ static Type* parseinfo(char *desc, char **pp) { int n1, n2; Type *t; char *attr; n1 = n2 = 0; parsenum(desc, &n1, &n2, &desc); t = typebynum(n1, n2); if(*desc != '='){ *pp = desc; return t; } desc++; if(fstack) fstack->list = mktl(t, fstack->list); while(parseattr(desc, &attr, &desc) >= 0){ if(*attr == 's') t->xsizeof = atoi(attr+1)/8; } return parsedefn(desc, t, pp); }