static void serve_file(int nfd, const char *fn) { struct stat sb; knc_ctx ctx; int fd; int ret; fd = open(fn, O_RDONLY, 0); if (fd == -1) { fprintf(stderr, "open(\"%s\"): %s\n", fn, strerror(errno)); exit(1); } ret = fstat(fd, &sb); if (ret == -1) { fprintf(stderr, "stat: %s\n", strerror(errno)); exit(1); } ctx = knc_ctx_init(); if (!ctx) { fprintf(stderr, "out of memory\n"); exit(1); } knc_set_debug(ctx, debug); knc_set_net_fd(ctx, nfd); knc_accept(ctx); knc_authenticate(ctx); /* XXXrcd: st_size is an off_t, but we take a size_t there. punt. */ knc_put_mmapbuf(ctx, KNC_DIR_SEND, sb.st_size, MAP_PRIVATE, fd, 0); close(fd); knc_flush(ctx, KNC_DIR_SEND, -1); if (knc_error(ctx)) fprintf(stderr, "KNC ERROR: %s\n", knc_errstr(ctx)); else knc_close(ctx); knc_ctx_destroy(ctx); return; }
int knc_loop(struct knc_ctx *ctx) { fd_set rd, wr; int fd; int i; int ret; int valrecv = 0; int valsend = 0; char *buf; fd = knc_get_net_fd(ctx); /* XXXrcd: Set non-blocking? */ ret = fcntl(fd, F_SETFL, O_NONBLOCK); if (ret == -1) fprintf(stderr, "%d: set nonblocking, %s\n", getpid(), strerror(errno)); for (;;) { fprintf(stderr, "%d: loop start, recv'd = %d sent = %d.\n", getpid(), valrecv, valsend); if (knc_error(ctx)) break; if (knc_get_net_fd(ctx) == -1) break; /* * The data that we are sending and receiving is a simple * steam of incrementing single byte integers modulo 11. * Both sides send the same data, so it can be validated. */ if (knc_avail_buf(ctx, KNC_DIR_SEND) < UNIT_BUFSIZ) { ret = knc_get_ibuf(ctx, KNC_DIR_SEND, (void **)&buf, 8192); if (ret == -1) fprintf(stderr, "%d: ret == -1 for sending\n", getpid()); for (i=0; i < ret; i++) buf[i] = valsend++ % 11; if (ret > 0) knc_fill_buf(ctx, KNC_DIR_SEND, ret); } if (knc_avail_buf(ctx, KNC_DIR_RECV) > 0) { ret = knc_get_obuf(ctx, KNC_DIR_RECV, (void **)&buf, 8192); if (ret < 0) fprintf(stderr, "%d: ret == %d for receiving\n", getpid(), ret); for (i=0; i < ret; i++) { if (buf[i] != valrecv++ % 11) { fprintf(stderr, "Malformed input\n"); return -1; } } if (ret > 0) knc_drain_buf(ctx, KNC_DIR_RECV, ret); } FD_ZERO(&rd); FD_ZERO(&wr); if (knc_avail_buf(ctx, KNC_DIR_RECV) < UNIT_BUFSIZ) FD_SET(fd, &rd); if (knc_avail_buf(ctx, KNC_DIR_SEND) > 0) FD_SET(fd, &wr); ret = select(fd+1, &rd, &wr, NULL, NULL); if (ret < 0) { fprintf(stderr, "select: %s\n", strerror(errno)); break; } if (FD_ISSET(fd, &rd)) knc_fill(ctx, KNC_DIR_RECV); if (FD_ISSET(fd, &wr)) knc_flush(ctx, KNC_DIR_SEND); knc_garbage_collect(ctx); } ret = 0; if (knc_error(ctx)) { fprintf(stderr, "KNC UNIT TEST ERROR: %s\n", knc_errstr(ctx)); ret = 1; } knc_ctx_close(ctx); close(fd); return ret; }