--- /dev/null
+/*
+ * Copyright 2008, Tollef Fog Heen <tfheen@err.no>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <librsync.h>
+
+int server = 0;
+
+ssize_t write_chunked(int fd, const char *buf, size_t count)
+{
+ char csize[11];
+ int i;
+ i = snprintf(csize, 11, "%x\r\n",count);
+ return write(fd, csize, i) + write(fd, buf, count) +
+ write(fd, "\r\n", 2);
+}
+
+ssize_t read_chunked(int fd, void *buf, size_t count)
+{
+ char b[1024];
+ size_t bu = 0;
+ ssize_t r;
+ long chunksize;
+
+ b[0] = b[1] = 0;
+ memset(b, 0, sizeof(b));
+
+ r = read(fd, b, 1);
+ while (r > 0 && strstr(b, "\r\n") == NULL) {
+ bu += r;
+ r = read(fd, b+bu, 1);
+ }
+ if (r <= 0) {
+ return r;
+ }
+ chunksize = strtol(b, NULL, 16);
+ if (count < chunksize) {
+ /* Ooops. */
+ fprintf(stderr, "count too small\n");
+ exit(1);
+ }
+ r = read(fd, buf, chunksize);
+ read(fd, b, 2); /* \r\n */
+ return r;
+
+}
+
+int do_server()
+{
+ char inbuf[2048], outbuf[2048];
+ ssize_t inused, outused;
+ ssize_t r;
+ rs_job_t *rs_job;
+ rs_signature_t *sigsum;
+ rs_buffers_t rs_buf;
+ rs_result rs_status;
+ char filename[1024];
+
+ /* Check that we get a SIG, try to load it. */
+ r = read(0, inbuf, 5); /* SIG\r\n */
+ if (r != 5) {
+ perror("read");
+ exit(1);
+ }
+
+ if (memcmp(inbuf, "SIG\r\n", 5) != 0) {
+ fprintf(stderr, "Protocol error, expected SIG");
+ exit(1);
+ }
+
+ rs_job = rs_loadsig_begin(&sigsum);
+
+ read_chunked(0, filename, 1024);
+ write(1, "", 0);
+
+ rs_buf.next_out = outbuf;
+ rs_buf.avail_out = sizeof(outbuf);
+ rs_status = RS_RUNNING;
+ inused = 1;
+ while (inused >= 0 && rs_buf.eof_in != 1) {
+ inused = read_chunked(0, inbuf, sizeof(inbuf));
+
+ if (inused == 0)
+ rs_buf.eof_in = 1;
+ rs_buf.avail_in = inused;
+ rs_buf.next_in = inbuf;
+ rs_status = rs_job_iter(rs_job, &rs_buf);
+ fprintf(stderr, "%s\n", rs_strerror(rs_status));
+ }
+
+}
+
+int do_client(char *filename)
+{
+ int f;
+ char inbuf[2048], outbuf[2048];
+ ssize_t inused, outused;
+ rs_job_t *rs_job;
+ rs_buffers_t rs_buf;
+ rs_result rs_status;
+
+ f = open(filename, O_RDONLY);
+ if (f < 0) {
+ perror("open");
+ exit(1);
+ }
+ write(1, "SIG\r\n", 5);
+ write_chunked(1, filename, strlen(filename));
+
+ rs_job = rs_sig_begin(RS_DEFAULT_BLOCK_LEN,
+ RS_DEFAULT_STRONG_LEN);
+ inused = read(f, inbuf, sizeof(inbuf));
+ while (inused >= 0 && rs_buf.eof_in != 1) {
+ if (inused < sizeof(inbuf))
+ rs_buf.eof_in = 1;
+ rs_buf.avail_in = inused;
+ rs_buf.next_in = inbuf;
+ rs_buf.next_out = outbuf;
+ rs_buf.avail_out = sizeof(outbuf);
+ rs_status = rs_job_iter(rs_job, &rs_buf);
+ fprintf(stderr, "%s\n", rs_strerror(rs_status));
+ write_chunked(1, outbuf, rs_buf.next_out - outbuf);
+ if (rs_buf.avail_in > 0) {
+ memmove(inbuf, rs_buf.next_in, rs_buf.avail_in);
+ rs_buf.next_in = inbuf + rs_buf.avail_in;
+ inused = rs_buf.avail_in;
+ } else {
+ inused = 0;
+ }
+ inused += read(f, inbuf + inused, sizeof(inbuf) - inused);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ /* FIXME Help */
+ exit(1);
+ }
+
+ if (strcmp(argv[1], "--server") == 0)
+ return do_server();
+ else
+ return do_client(argv[1]);
+}
+