#include "stdlib.h" #include "../shared/Messages.h" #include "../shared/MiscSupport.h" #include "../shared/CommandDispatcher.h" #include "../shared/ReplyToClient.h" #include "../shared/LogFile.h" #include "../shared/GlobalConfigFile.h" #include "P64.h" #include "ProxyMainLoop.h" ///////////////////////////////////////////////////////////////////// // Connection ///////////////////////////////////////////////////////////////////// class Connection { private: static std::map< SocketInfo *, Connection * > _bySocket; static std::map< std::string, Connection * > _byCookie; SocketInfo *_client; SocketInfo *_server; std::string _lastId; std::string _cookie; bool _valid; void clientToServerImpl(ExternalRequest *request); public: static Connection *find(SocketInfo *socket); static Connection *find(std::string cookie); static void deleteAll(); Connection(ExternalRequest *request, InputListener &serverListener); ~Connection(); static void clientToServer(ExternalRequest *request); void internalToServer(std::string data); void serverToClient(std::string data); bool getValid() const; }; std::map< SocketInfo *, Connection * > Connection::_bySocket; std::map< std::string, Connection * > Connection::_byCookie; bool Connection::getValid() const { return _valid; } bool verboseDebugging() { static bool value = getConfigItem("verbose_debugging") == "1"; return value; } void Connection::clientToServer(ExternalRequest *request) { Connection *c = find(request->getProperty("cookie")); if (c) { c->clientToServerImpl(request); } else if (verboseDebugging()) { TclList logMsg; logMsg<getProperty("cookie"); LogFile::primary().sendString(logMsg, 0); } } void Connection::clientToServerImpl(ExternalRequest *request) { std::string currentId = request->getProperty("sequence"); if (!currentId.empty()) { // If the id is blank we assume that the client is not using ids. if (currentId == _lastId) { // If the id is a duplicate, then we've already received this // message. if (verboseDebugging()) { TclList logMsg; logMsg<getProperty("body"); static P64Decoder decoder; std::string decoded; if (!decoder.decode(encoded, decoded)) { if (verboseDebugging()) { TclList logMsg; logMsg<second; } } Connection::~Connection() { DeleteSocketThread::deleteSocket(_client); _bySocket.erase(_client); if (_server) { DeleteSocketThread::deleteSocket(_server); _bySocket.erase(_server); } if (!_cookie.empty()) { _byCookie.erase(_cookie); } } Connection::Connection(ExternalRequest *request, InputListener &serverListener) : _client(request->getSocketInfo()), _server(NULL), _valid(false) { // We should never be called twice on the same socket like this. If we // are, then the simplest thing is to break the old connection. delete find(request->getSocketInfo()); _bySocket[_client] = this; std::string destination = request->getProperty("destination"); std::string host = getConfigItem("destination_" + destination + "_host"); std::string port = getConfigItem("destination_" + destination + "_port"); if (host.empty() || port.empty()) { TclList logMsg; logMsg<getValid() != SocketInfo::valid) { TclList logMsg; logMsg<getProperty("write", "http://proxy.trade-ideas.com/Write.php"); addToOutputQueue(_client, writeUrl + "?cookie=" + _cookie + "\r\n"); serverListener.listenToNewSocket(_server); } ///////////////////////////////////////////////////////////////////// // ProxyMainLoop ///////////////////////////////////////////////////////////////////// ProxyMainLoop::ProxyMainLoop() : ThreadClass("ProxyMainLoop"), _incoming("ProxyMainLoop"), _serverListener(&_incoming, mtServerInput) { CommandDispatcher *disp = CommandDispatcher::getInstance(); disp->listenForCommand("listen", &_incoming, mtNewClientConnection); disp->listenForCommand("write", &_incoming, mtNewClientData); startThread(); } ProxyMainLoop::~ProxyMainLoop() { Request *r = new Request(NULL); r->callbackId = mtQuit; _incoming.newRequest(r); waitForThread(); Connection::deleteAll(); } void ProxyMainLoop::threadFunction() { while (true) { while (Request *current = _incoming.getRequest()) { switch (current->callbackId) { case mtServerInput: { Connection *c = Connection::find(current->getSocketInfo()); if (c) { NewInputRequest *request = dynamic_cast(current); if (request->newSocket()) { // Meaningless for a client socket. We created this // socket ourselves, not another thread. } else if (request->atEOF()) { delete c; } else { c->serverToClient(request->getNewInput()); } } break; } case mtNewClientConnection: { ExternalRequest *request = dynamic_cast(current); Connection *c = new Connection(request, _serverListener); if (c->getValid()) { CommandDispatcher::getInstance() ->getDeadManTimer() .grantImmunity(request->getSocketInfo()); std::string remote = request->getProperty("remote", "unknown"); c->internalToServer ("command=proxy_info&auth=auth&remote=" + urlEncode(remote) + "\r\n"); } else { delete c; } break; } case mtNewClientData: { ExternalRequest *request = dynamic_cast(current); Connection::clientToServer(request); DeleteSocketThread::deleteSocket(request->getSocketInfo()); break; } case mtQuit : { delete current; return; } case DeleteSocketThread::callbackId: { Connection *c = Connection::find(current->getSocketInfo()); if (c) { delete c; } break; } } delete current; } _incoming.waitForRequest(); } }