/* * Worldvisions Weaver Software: * Copyright (C) 1997-2002 Net Integration Technologies, Inc. * * simpleconn is a very simple program that forwards data between an * arbitrary set of given files (which are usually devices, named pipes, * etc). If a file is named '-', it refers to stdin/stdout. */ #include "wvfile.h" #include "wvistreamlist.h" #include "wvtcplistener.h" #include "wvtcp.h" #include "wvlog.h" #include static void bouncer(WvStream *input, WvIStreamList *list) { WvIStreamList::Iter i(*list); char buf[1024]; size_t len; if (!input->select(0, true, false, false)) return; len = input->read(buf, sizeof(buf)); if (!len) return; for (i.rewind(); i.next(); ) { IWvStream &out = i(); if (input == &out) continue; if (!out.isok()) continue; //delay_output wasn't really useful, and isn't in IWvStream //out.delay_output(true); out.write(buf, len); } } static void accept_callback(WvIStreamList *list, IWvStream *_conn) { WvStreamClone *conn = new WvStreamClone(_conn); conn->setcallback(wv::bind(bouncer, conn, list)); list->append(conn, true, "WvTCPConn"); } int main(int argc, char **argv) { WvIStreamList biglist, l; int count; char *cptr; WvLog log("simpleconn", WvLog::Info); signal( SIGPIPE, SIG_IGN ); if (argc < 2) { fprintf(stderr, "Usage: %s file [file...]\n" " Passes data between the given files/devices/etc. " "If a filename is\n" " '-', it refers to stdin/stdout.\n", argv[0]); return 1; } biglist.append(&l, false, "list"); for (count = 1; count < argc; count++) { WvStream *f; if (!strcmp(argv[count], "-")) { log("File %s is stdin/stdout\n", count); f = wvcon; l.append(f, false, "wvcon"); f->setcallback(wv::bind(bouncer, f, &l)); } else if (!strncasecmp(argv[count], "tcp:", 4)) { // TCP connection of some kind cptr = argv[count] + 4; if (strchr(cptr, ':')) // an additional colon? client mode. { log("File %s is a TCP client\n", count); f = new WvTCPConn(WvIPPortAddr(cptr)); l.append(f, true, "TCP client"); f->setcallback(wv::bind(bouncer, f, &l)); } else // server mode { log("File %s is a TCP server\n", count); WvTCPListener *listen = new WvTCPListener(WvIPPortAddr("", atoi(cptr))); listen->onaccept(wv::bind(accept_callback, &l, _1)); biglist.append(listen, true, "TCP server"); } } else { log("File %s is a file (%s)\n", count, argv[count]); f = new WvFile(argv[count], O_RDWR); if (!f->isok()) { WVRELEASE(f); f = new WvFile(argv[count], O_RDONLY); if (!f->isok()) { fprintf(stderr, "%s: %s\n", argv[count], f->errstr().cstr()); return 1; } } l.append(f, true, "file"); f->setcallback(wv::bind(bouncer, f, &l)); } } // continue as long as there is more than one open client, or a server while (l.count() >= 2 || (biglist.count() - 1 >= 1 && l.count() >= 1)) { if (biglist.select(1000)) biglist.callback(); } return 0; }