+ while (--n >= 0) {
+ srsd_t *srsd = evts[n].data.ptr;
+
+ if (srsd->listener) {
+ struct epoll_event evt = { .events = EPOLLIN };
+ srsd_t *tmp;
+ int sock;
+
+ sock = accept_nonblock(srsd->fd);
+ if (sock < 0) {
+ UNIXERR("accept");
+ continue;
+ }
+
+ evt.data.ptr = tmp = srsd_new();
+ tmp->decoder = srsd->decoder;
+ tmp->fd = sock;
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &evt) < 0) {
+ UNIXERR("epoll_ctl");
+ srsd_delete(&tmp);
+ close(sock);
+ }
+ continue;
+ }
+
+ if (evts[n].events & EPOLLIN) {
+ int res = buffer_read(&srsd->ibuf, srsd->fd, -1);
+
+ if ((res < 0 && errno != EINTR && errno != EAGAIN)
+ || res == 0)
+ {
+ srsd_delete(&srsd);
+ continue;
+ }
+
+ if (process_srs(srs, domain, srsd) < 0) {
+ srsd_delete(&srsd);
+ continue;
+ }
+ }
+
+ if ((evts[n].events & EPOLLOUT) && srsd->obuf.len) {
+ int res = write(srsd->fd, srsd->obuf.data, srsd->obuf.len);
+
+ if (res < 0 && errno != EINTR && errno != EAGAIN) {
+ srsd_delete(&srsd);
+ continue;
+ }
+
+ if (res > 0) {
+ buffer_consume(&srsd->obuf, res);
+ }
+ }
+
+ if (srsd->watchwr == !srsd->obuf.len) {
+ struct epoll_event evt = {
+ .events = EPOLLIN | (srsd->obuf.len ? EPOLLOUT : 0),
+ .data.ptr = srsd,
+ };
+ if (epoll_ctl(epollfd, EPOLL_CTL_MOD, srsd->fd, &evt) < 0) {
+ UNIXERR("epoll_ctl");
+ srsd_delete(&srsd);
+ continue;
+ }
+ srsd->watchwr = srsd->obuf.len != 0;
+ }
+ }