+static int send_sb(struct client_task *ct, void *buf, size_t numbytes,
+ enum sb_designator band, bool dont_free)
+{
+ int ret, fd = ct->scc.fd;
+ struct iovec iov[2];
+
+ if (!ct->sbc) {
+ struct sb_buffer sbb;
+ sb_transformation trafo = ct->status < CL_RECEIVED_PROCEED?
+ NULL : sc_trafo;
+ sbb = (typeof(sbb))SBB_INIT(band, buf, numbytes);
+ ct->sbc = sb_new_send(&sbb, dont_free, trafo, ct->scc.send);
+ }
+ ret = sb_get_send_buffers(ct->sbc, iov);
+ ret = xwritev(fd, iov, ret);
+ if (ret < 0) {
+ sb_free(ct->sbc);
+ ct->sbc = NULL;
+ return ret;
+ }
+ if (sb_sent(ct->sbc, ret)) {
+ ct->sbc = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+static int recv_sb(struct client_task *ct, fd_set *rfds,
+ struct sb_buffer *result)
+{
+ int ret;
+ size_t n;
+ sb_transformation trafo;
+ void *trafo_context;
+ struct iovec iov;
+
+ if (!FD_ISSET(ct->scc.fd, rfds))
+ return 0;
+ if (ct->status < CL_SENT_CH_RESPONSE)
+ trafo = trafo_context = NULL;
+ else {
+ trafo = sc_trafo;
+ trafo_context = ct->scc.recv;
+ }
+ if (!ct->sbc)
+ ct->sbc = sb_new_recv(0, trafo, trafo_context);
+again:
+ sb_get_recv_buffer(ct->sbc, &iov);
+ ret = read_nonblock(ct->scc.fd, iov.iov_base, iov.iov_len, rfds, &n);
+ if (ret < 0) {
+ sb_free(ct->sbc);
+ ct->sbc = NULL;
+ return ret;
+ }
+ if (n == 0)
+ return 0;
+ if (!sb_received(ct->sbc, n, result))
+ goto again;
+ ct->sbc = NULL;
+ return 1;
+}
+
+