/* compressloop-slave, compression server for compressloop-distributed Copyright (C) 2004 James Cameron This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Derived from compressloop.c (c) 1999 by Paul `Rusty' Russell, GPL, with contributions in 2000 and 2001 by Klaus Knopper, and in 2002 by Valentijn Sessink. */ #include #include #include #include #include #include #define BLOCKSIZE 65536 #define UPSIZE BLOCKSIZE + (BLOCKSIZE/1000) + 12 #define PORT 8522 ssize_t readp(int fd, void *buf, size_t count) { ssize_t stat, bytes = 0; while (bytes < count) { stat = read(fd, buf+bytes, count-bytes); if (stat <= 0) { return stat; } bytes += stat; } return bytes; } ssize_t writep(int fd, void *buf, size_t count) { ssize_t stat, bytes = 0; while (bytes < count) { stat = write(fd, buf+bytes, count-bytes); if (stat <= 0) { return stat; } bytes += stat; } return bytes; } int main(int argc, char **argv) { int optionchar, lsock, ov, stat, asock, version, eof, port=PORT, verbose=0; struct sockaddr_in laddr; while ((optionchar = getopt(argc, argv, "l:v")) != -1) { switch (optionchar) { case 'l': port = atoi(optarg); break; case 'v': verbose++; break; default: fprintf(stderr, "usage: slave [-l port] [-v]\n"); exit(1); } } lsock = socket(AF_INET, SOCK_STREAM, 0); if (lsock == -1) { perror("socket"); exit(1); } if (verbose) fprintf(stderr, "socket\n"); ov = 1; stat = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *) &ov, sizeof(ov)); if (stat < 0) { perror("setsockopt"); exit(1); } ov = BLOCKSIZE * 4; stat = setsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *) &ov, sizeof(ov)); if (stat < 0) { perror("setsockopt (SO_RCVBUF)"); } ov = BLOCKSIZE * 4; stat = setsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *) &ov, sizeof(ov)); if (stat < 0) { perror("setsockopt (SO_RCVBUF)"); } laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = INADDR_ANY; laddr.sin_port = htons(port); stat = bind(lsock, (struct sockaddr *) &laddr, sizeof laddr); if (stat) { perror("bind"); exit(1); } if (verbose) fprintf(stderr, "bind\n"); stat = listen(lsock, 1); if (stat) { perror("listen"); exit(1); } if (verbose) fprintf(stderr, "listen\n"); while (1) { asock = accept(lsock, NULL, NULL); if (asock == -1) { perror("accept"); exit(1); } if (verbose) fprintf(stderr, "accept\n"); stat = readp(asock, &version, sizeof(version)); if (stat < 0) { perror("readp"); close(asock); continue; } if (stat == 0) { close(asock); continue; } version = ntohl(version); eof = 0; while (!eof) { int bytes = 0, size; unsigned long number, netlen, outlen = UPSIZE; char in[BLOCKSIZE], out[UPSIZE]; stat = readp(asock, &number, sizeof(number)); if (stat < 0) { perror("readp"); break; } if (stat == 0) { break; } number = ntohl(number); if (verbose > 1) fprintf(stderr, "block %lu ", number); stat = readp(asock, &size, sizeof(size)); if (stat < 0) { perror("readp"); break; } if (stat == 0) { break; } size = ntohl(size); if (verbose > 1) fprintf(stderr, "size %d ", size); if (size > BLOCKSIZE) { fprintf(stderr, "slave: size > blocksize\n"); break; } stat = readp(asock, in, size); if (stat < 0) { perror("readp"); break; } if (stat == 0) { break; } bytes = stat; stat = compress2(out, &outlen, in, bytes, Z_DEFAULT_COMPRESSION); if (stat != Z_OK) { fprintf(stderr, "slave: compress2: error %d\n", stat); break; } if (verbose > 1) fprintf(stderr, "gz %lu ", outlen); number = htonl(number); stat = writep(asock, &number, sizeof(number)); if (stat <= 0) { perror("write"); break; } netlen = htonl(outlen); stat = writep(asock, &netlen, sizeof(netlen)); if (stat <= 0) { perror("write"); break; } stat = writep(asock, out, outlen); if (stat <= 0) { perror("write"); break; } if (verbose > 1) fprintf(stderr, "\n"); } if (verbose) fprintf(stderr, "\n"); close(asock); } } /* obligatory comment */