/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2004 Net Integration Technologies, Inc.
 *
 * WvTCPListener test.  Listens on a port, and bounces stdin and stdout 
 * between all connections established to it.  SSL-enabled for fun and
 * profit.
 */

#include "wvtcp.h"
#include "wvstreamlist.h"
#include "wvlog.h"
#include "wvsslstream.h"
#include "strutils.h"
#include "wvx509.h"

static WvX509Mgr * x509;

typedef WvBoundCallback<WvStreamCallback, WvStreamList &> MyCallback;

static void stream_bounce_to_list(WvStreamList &l, WvStream &s, void *)
{
    WvStreamList::Iter out(l);
    char *line;

    while ((line = s.getline(0)) != NULL)
    {
        for (out.rewind(); out.next(); )
        {
            if (&out() != &s && out().select(0, false, true))
            {
                out().print("%s> %s\n", 
                            s.src() ? (WvString)*s.src() : WvString("stdin"),
                            line);
            }
        }
    }
}

static void accept_connection(WvStreamList &l, WvStream &s, void *)
{
    WvTCPListener &listener = *(WvTCPListener *) &s;
    WvTCPConn *conn = listener.accept();

    if (conn)
    {
        WvSSLStream *ssl = new WvSSLStream(conn, x509, false, true);
        MyCallback bounce_cb(stream_bounce_to_list, l);
        ssl->setcallback(bounce_cb, NULL);
        l.append(ssl, true);
    }
}

int main(int argc, char **argv)
{
    WvString myname("peanut.internal.nit.ca");
    WvString dn("O=%s,OU=Weaver.%s",
        myname, encode_hostname_as_DN(myname));

    x509 = new WvX509Mgr(dn, 1024);

    WvLog log("irctest"), err = log.split(WvLog::Error);
    WvStreamList l;

    WvTCPListener listener(WvIPPortAddr(argc==2 ? argv[1] : "0.0.0.0:0"));
    
    MyCallback bounce_cb(stream_bounce_to_list, l);
    MyCallback accept_cb(accept_connection, l);

    wvcon->setcallback(bounce_cb, NULL);
    listener.setcallback(accept_cb, NULL);
    
    log("Listening on port %s\n", *listener.src());
    
    l.append(&listener, false);
    l.append(wvcon, false);
    
    while (listener.isok() && wvcon->isok())
    {
        if (l.select(-1))
            l.callback();
    }
    
    return 0;
}

