static void proc_event_cb(unused int fd, short events, void *arg) { struct tmuxpeer *peer = arg; ssize_t n; struct imsg imsg; int v; if (!(peer->flags & PEER_BAD) && (events & EV_READ)) { if ((n = imsg_read(&peer->ibuf)) == -1 || n == 0) { peer->dispatchcb(NULL, peer->arg); return; } for (;;) { if ((n = imsg_get(&peer->ibuf, &imsg)) == -1) { peer->dispatchcb(NULL, peer->arg); return; } if (n == 0) break; log_debug("peer %p message %d", peer, imsg.hdr.type); v = imsg.hdr.peerid; if (imsg.hdr.type != MSG_VERSION && v != PROTOCOL_VERSION) { log_debug("peer %p bad version %d", peer, v); proc_send(peer, MSG_VERSION, -1, NULL, 0); peer->flags |= PEER_BAD; if (imsg.fd != -1) close(imsg.fd); imsg_free(&imsg); break; } peer->dispatchcb(&imsg, peer->arg); imsg_free(&imsg); } } if (events & EV_WRITE) { if (msgbuf_write(&peer->ibuf.w) <= 0 && errno != EAGAIN) { peer->dispatchcb(NULL, peer->arg); return; } } if ((peer->flags & PEER_BAD) && peer->ibuf.w.queued == 0) { peer->dispatchcb(NULL, peer->arg); return; } proc_update_event(peer); }
static void proc_event_cb(__unused int fd, short events, void *arg) { struct tmuxpeer *peer = arg; ssize_t n; struct imsg imsg; if (!(peer->flags & PEER_BAD) && (events & EV_READ)) { if (((n = imsg_read(&peer->ibuf)) == -1 && errno != EAGAIN) || n == 0) { peer->dispatchcb(NULL, peer->arg); return; } for (;;) { if ((n = imsg_get(&peer->ibuf, &imsg)) == -1) { peer->dispatchcb(NULL, peer->arg); return; } if (n == 0) break; log_debug("peer %p message %d", peer, imsg.hdr.type); if (peer_check_version(peer, &imsg) != 0) { if (imsg.fd != -1) close(imsg.fd); imsg_free(&imsg); break; } peer->dispatchcb(&imsg, peer->arg); imsg_free(&imsg); } } if (events & EV_WRITE) { if (msgbuf_write(&peer->ibuf.w) <= 0 && errno != EAGAIN) { peer->dispatchcb(NULL, peer->arg); return; } } if ((peer->flags & PEER_BAD) && peer->ibuf.w.queued == 0) { peer->dispatchcb(NULL, peer->arg); return; } proc_update_event(peer); }
int proc_send(struct tmuxpeer *peer, enum msgtype type, int fd, const void *buf, size_t len) { struct imsgbuf *ibuf = &peer->ibuf; void *vp = (void *)buf; int retval; if (peer->flags & PEER_BAD) return (-1); log_debug("sending message %d to peer %p (%zu bytes)", type, peer, len); retval = imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, fd, vp, len); if (retval != 1) return (-1); proc_update_event(peer); return (0); }
struct tmuxpeer * proc_add_peer(struct tmuxproc *tp, int fd, void (*dispatchcb)(struct imsg *, void *), void *arg) { struct tmuxpeer *peer; peer = xcalloc(1, sizeof *peer); peer->parent = tp; peer->dispatchcb = dispatchcb; peer->arg = arg; imsg_init(&peer->ibuf, fd); event_set(&peer->event, fd, EV_READ, proc_event_cb, peer); log_debug("add peer %p: %d (%p)", peer, fd, arg); proc_update_event(peer); return (peer); }