X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=command.c;h=9cf1967faa4bdb4a3f12d313e2a322881f787d1f;hp=cdc42fa1a220662ac7413b52fc40aba0f56e14d8;hb=2830b9f8;hpb=e151dbb79eac16326585ec0a33cf48029f5f22f4 diff --git a/command.c b/command.c index cdc42fa1..9cf1967f 100644 --- a/command.c +++ b/command.c @@ -15,6 +15,7 @@ #include "para.h" #include "error.h" #include "crypt.h" +#include "sideband.h" #include "command.h" #include "server.cmdline.h" #include "string.h" @@ -191,6 +192,118 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman return 1; } +/** + * Send a sideband packet through a blocking file descriptor. + * + * \param scc fd and crypto keys. + * \param buf The buffer to send. + * \param numbytes The size of \a buf. + * \param band The sideband designator of this packet. + * \param dont_free If true, never deallocate \a buf. + * + * The nonblock flag must be disabled for the file descriptor given by \a scc. + * + * Stream cipher encryption is automatically activated if neccessary via the + * sideband transformation, depending on the value of \a band. + * + * \return Standard. + * + * \sa \ref send_sb_va(). + */ +int send_sb(struct stream_cipher_context *scc, void *buf, size_t numbytes, + int band, bool dont_free) +{ + int ret; + struct sb_context *sbc; + struct iovec iov[2]; + struct sb_buffer sbb = SBB_INIT(band, buf, numbytes); + sb_transformation trafo = band < SBD_PROCEED? NULL : sc_trafo; + + sbc = sb_new_send(&sbb, dont_free, trafo, scc->send); + do { + ret = sb_get_send_buffers(sbc, iov); + ret = xwritev(scc->fd, iov, ret); + if (ret < 0) + goto fail; + } while (sb_sent(sbc, ret) == false); + return 1; +fail: + sb_free(sbc); + return ret; +} + +/** + * Create a variable sized buffer and send it as a sideband packet. + * + * \param scc Passed to \ref send_sb. + * \param band See \ref send_sb. + * \param fmt The format string. + * + * \return The return value of the underlying call to \ref send_sb. + */ +__printf_3_4 int send_sb_va(struct stream_cipher_context *scc, int band, + const char *fmt, ...) +{ + va_list ap; + char *msg; + int ret; + + va_start(ap, fmt); + ret = xvasprintf(&msg, fmt, ap); + va_end(ap); + return send_sb(scc, msg, ret, band, false); +} + +/** + * Send a sideband packet through a blocking file descriptor. + * + * \param scc fd and crypto keys. + * \param expected_band The expected band designator. + * \param max_size Passed to \ref sb_new_recv(). + * \param result Body of the sideband packet is returned here. + * + * If \a expected_band is not \p SBD_ANY, the band designator of the received + * sideband packet is compared to \a expected_band and a mismatch is considered + * an error. + * + * \return Standard. + */ +int recv_sb(struct stream_cipher_context *scc, + enum sb_designator expected_band, + size_t max_size, struct iovec *result) +{ + int ret; + struct sb_context *sbc; + struct iovec iov; + struct sb_buffer sbb; + sb_transformation trafo; + + trafo = expected_band != SBD_ANY && expected_band < SBD_PROCEED? + NULL : sc_trafo; + sbc = sb_new_recv(max_size, trafo, scc->recv); + for (;;) { + sb_get_recv_buffer(sbc, &iov); + ret = recv_bin_buffer(scc->fd, iov.iov_base, iov.iov_len); + if (ret == 0) + ret = -E_EOF; + if (ret < 0) + goto fail; + ret = sb_received(sbc, ret, &sbb); + if (ret < 0) + goto fail; + if (ret > 0) + break; + } + ret = -E_BAD_BAND; + if (expected_band != SBD_ANY && sbb.band != expected_band) + goto fail; + *result = sbb.iov; + return 1; +fail: + sb_free(sbc); + return ret; +} + int com_sender(struct command_context *cc) { int i, ret;