#include"adconn.h" #include #include"bconsole.h" #include"bsocket.h" #include"httpconnect.h" #include"socks.h" #include"httppoll.h" #include class App::Private { public: Private() {} ByteStream *bs; BConsole *c; int mode; }; App::App(int mode, const QString &host, int port, const QString &serv, const QString &proxy_host, int proxy_port, const QString &proxy_user, const QString &proxy_pass) :QObject(0) { d = new Private; d->c = new BConsole; connect(d->c, SIGNAL(connectionClosed()), SLOT(con_connectionClosed())); connect(d->c, SIGNAL(readyRead()), SLOT(con_readyRead())); d->bs = 0; d->mode = mode; if(mode == 0 || mode == 1) { BSocket *s = new BSocket; d->bs = s; connect(s, SIGNAL(connected()), SLOT(st_connected())); connect(s, SIGNAL(error(int)), SLOT(st_error(int))); if(mode == 0) { fprintf(stderr, "adconn: Connecting to %s:%d ...\n", host.latin1(), port); s->connectToHost(host, port); } else { fprintf(stderr, "adconn: Connecting to '%s' server at %s ...\n", serv.latin1(), host.latin1()); s->connectToServer(host, serv); } } else if(mode == 2) { HttpConnect *s = new HttpConnect; d->bs = s; connect(s, SIGNAL(connected()), SLOT(st_connected())); connect(s, SIGNAL(error(int)), SLOT(st_error(int))); fprintf(stderr, "adconn: Connecting to %s:%d via %s:%d (https)\n", host.latin1(), port, proxy_host.latin1(), proxy_port); if(!proxy_user.isEmpty()) s->setAuth(proxy_user, proxy_pass); s->connectToHost(proxy_host, proxy_port, host, port); } else if(mode == 3) { SocksClient *s = new SocksClient; d->bs = s; connect(s, SIGNAL(connected()), SLOT(st_connected())); connect(s, SIGNAL(error(int)), SLOT(st_error(int))); fprintf(stderr, "adconn: Connecting to %s:%d via %s:%d (socks)\n", host.latin1(), port, proxy_host.latin1(), proxy_port); if(!proxy_user.isEmpty()) s->setAuth(proxy_user, proxy_pass); s->connectToHost(proxy_host, proxy_port, host, port); } else if(mode == 4) { HttpPoll *s = new HttpPoll; d->bs = s; connect(s, SIGNAL(connected()), SLOT(st_connected())); connect(s, SIGNAL(error(int)), SLOT(st_error(int))); fprintf(stderr, "adconn: Connecting to %s via %s:%d (poll)\n", host.latin1(), proxy_host.latin1(), proxy_port); if(!proxy_user.isEmpty()) s->setAuth(proxy_user, proxy_pass); s->connectToHost(proxy_host, proxy_port, host); } } App::~App() { delete d->bs; delete d->c; delete d; } void App::st_connected() { fprintf(stderr, "adconn: Connected\n"); // map the signals connect(d->bs, SIGNAL(connectionClosed()), SLOT(st_connectionClosed())); connect(d->bs, SIGNAL(delayedCloseFinished()), SLOT(st_delayedCloseFinished())); connect(d->bs, SIGNAL(readyRead()), SLOT(st_readyRead())); } void App::st_connectionClosed() { fprintf(stderr, "adconn: Connection closed by foreign host.\n"); quit(); } void App::st_delayedCloseFinished() { quit(); } void App::st_readyRead() { QByteArray a = d->bs->read(); d->c->write(a); } void App::st_error(int x) { fprintf(stderr, "adconn: Stream error [%d].\n", x); quit(); } void App::con_connectionClosed() { fprintf(stderr, "adconn: Closing.\n"); d->bs->close(); if(d->bs->bytesToWrite() == 0) quit(); } void App::con_readyRead() { QByteArray a = d->c->read(); d->bs->write(a); } int main(int argc, char **argv) { QApplication app(argc, argv, false); if(argc < 2) { printf("usage: adconn [options] [host]\n"); printf(" [host] must be in the form 'host:port' or 'domain#server'\n"); printf(" When using proxy 'poll', [host] must be a URL\n"); printf(" Options:\n"); printf(" --proxy=[https|poll|socks],host:port\n"); printf(" --proxy-auth=user,pass\n"); printf("\n"); return 0; } int mode = 0; QString proxy_host; int proxy_port=0; QString proxy_user, proxy_pass; for(int at = 1; at < argc; ++at) { QString s = argv[at]; // is it an option? if(s.left(2) == "--") { QString name; QStringList args; int n = s.find('=', 2); if(n != -1) { name = s.mid(2, n-2); ++n; args = QStringList::split(',', s.mid(n), true); } else { name = s.mid(2); args.clear(); } // eat the arg --argc; for(int x = at; x < argc; ++x) argv[x] = argv[x+1]; --at; // don't advance // process option if(name == "proxy") { QString type = args[0]; QString s = args[1]; int n = s.find(':'); if(n == -1) { printf("invalid host:port for proxy\n"); return 0; } proxy_host = s.mid(0, n); ++n; proxy_port = s.mid(n).toInt(); if(type == "https") { mode = 2; } else if(type == "poll") { mode = 4; } else if(type == "socks") { mode = 3; } else { printf("no such proxy type '%s'\n", type.latin1()); return 0; } } else if(name == "proxy-auth") { proxy_user = args[0]; proxy_pass = args[1]; } else { printf("Unknown option '%s'\n", name.latin1()); return 0; } } } if(argc < 2) { if(mode == 4) printf("No URL specified\n"); else printf("No host specified!\n"); return 0; } QString host, serv; int port=0; if(mode == 4) { host = argv[1]; } else { QString s = argv[1]; int n = s.find(':'); if(n == -1) { n = s.find('#'); if(n == -1) { printf("No port or server specified!\n"); return 0; } if(mode >= 2) { printf("Can't use domain#server with proxy!\n"); return 0; } host = s.mid(0, n); ++n; serv = s.mid(n); mode = 1; } else { host = s.mid(0, n); ++n; port = s.mid(n).toInt(); } } App *a = new App(mode, host, port, serv, proxy_host, proxy_port, proxy_user, proxy_pass); QObject::connect(a, SIGNAL(quit()), &app, SLOT(quit())); app.exec(); delete a; return 0; }