00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <torsocket.h>
00018 #include <vidalia.h>
00019 #include "geoipresolver.h"
00020 #include "config.h"
00021
00022 #if defined(USE_QSSLSOCKET)
00023 #include <torsslsocket.h>
00024 #endif
00025
00026
00027 #define GEOIP_HOST "geoip.vidalia-project.net"
00028
00029 #define GEOIP_PORT 80
00030
00031 #define GEOIP_SSL_PORT 1443
00032
00033 #define GEOIP_PAGE "/cgi-bin/geoip"
00034
00035
00036
00037 GeoIpResolver::GeoIpResolver()
00038 {
00039 _socksAddr = QHostAddress::LocalHost;
00040 _socksPort = 9050;
00041
00042 #if defined(USE_QSSLSOCKET)
00043 if (! QSslSocket::addDefaultCaCertificates(":/geoip/cacert_root.crt"))
00044 vWarn("Failed to add the GeoIP CA certificate to the default CA "
00045 "certificate database.");
00046 #endif
00047 }
00048
00049
00050
00051 void
00052 GeoIpResolver::setSocksHost(QHostAddress addr, quint16 port)
00053 {
00054 _socksAddr = addr;
00055 _socksPort = port;
00056 }
00057
00058
00059
00060
00061 bool
00062 GeoIpResolver::resolveFromCache(QHostAddress ip)
00063 {
00064 if (_cache.contains(ip)) {
00065 emit resolved(-1, QList<GeoIp>() << _cache.geoip(ip));
00066 return true;
00067 }
00068 return false;
00069 }
00070
00071
00072
00073 QList<QHostAddress>
00074 GeoIpResolver::resolveFromCache(QList<QHostAddress> ips)
00075 {
00076 QList<GeoIp> cached;
00077
00078
00079 foreach (QHostAddress ip, ips) {
00080 if (_cache.contains(ip)) {
00081 ips.removeAt(ips.indexOf(ip));
00082 cached << _cache.geoip(ip);
00083 }
00084 }
00085
00086
00087 if (cached.size() > 0) {
00088 vInfo("Resolved %1 GeoIP entries from cache.").arg(ips.size());
00089 emit resolved(-1, cached);
00090 }
00091 return ips;
00092 }
00093
00094
00095 int
00096 GeoIpResolver::resolve(QHostAddress ip)
00097 {
00098 return resolve(QList<QHostAddress>() << ip);
00099 }
00100
00101
00102 void
00103 GeoIpResolver::connected()
00104 {
00105
00106 QAbstractSocket *socket = dynamic_cast<QAbstractSocket *>(sender());
00107 if (!_requestList.contains(socket)) {
00108 return;
00109 }
00110 GeoIpRequest *req = (GeoIpRequest *)_requestList.value(socket);
00111 vInfo("Connected to the GeoIP host. Sending request for %1 uncached "
00112 "GeoIP entries. (request id %2)").arg(req->size()).arg(req->id());
00113
00114
00115 socket->write(req->request());
00116 }
00117
00118
00119 void
00120 GeoIpResolver::disconnected()
00121 {
00122
00123 QAbstractSocket *socket = dynamic_cast<QAbstractSocket *>(sender());
00124 if (!_requestList.contains(socket)) {
00125 return;
00126 }
00127 GeoIpRequest *request = (GeoIpRequest *)_requestList.take(socket);
00128
00129
00130 GeoIpResponse response = GeoIpResponse(socket->readAll());
00131
00132
00133 if (response.statusCode() == 200) {
00134
00135 int numCached = 0, i = 0;
00136 QList<GeoIp> geoips = response.geoIps();
00137 foreach (GeoIp geoip, geoips) {
00138 QHostAddress ip = geoip.ip();
00139
00140 if (request->contains(ip)) {
00141
00142
00143 if (!_cache.contains(ip)) {
00144 _cache.cache(geoip);
00145 numCached++;
00146 }
00147 i++;
00148 } else {
00149
00150
00151
00152
00153
00154 vWarn("Received a GeoIP entry for IP address %1 that was not included "
00155 "in the initial request. (request id %2)").arg(ip)
00156 .arg(request->id());
00157 geoips.removeAt(i);
00158 }
00159 }
00160
00161 if (numCached > 0) {
00162 _cache.saveToDisk();
00163 }
00164
00165 vInfo("Parsed %1 entries from the GeoIP response. (request id %2)")
00166 .arg(geoips.size()).arg(request->id());
00167 emit resolved(request->id(), geoips);
00168 } else {
00169
00170
00171 vWarn("GeoIP resolution failed (request id %1): %2").arg(request->id())
00172 .arg(response.statusMessage());
00173 emit resolveFailed(request->id(), response.statusMessage());
00174 }
00175
00176 socket->close();
00177 delete socket;
00178 delete request;
00179 }
00180
00181
00182 void
00183 GeoIpResolver::socketError(QString errorString)
00184 {
00185
00186 QAbstractSocket *socket = dynamic_cast<QAbstractSocket *>(sender());
00187 if (!_requestList.contains(socket)) {
00188 return;
00189 }
00190
00191
00192
00193 if (socket->error() != QAbstractSocket::RemoteHostClosedError) {
00194
00195 GeoIpRequest *request = (GeoIpRequest *)_requestList.take(socket);
00196 emit resolveFailed(request->id(), errorString);
00197 socket->abort();
00198 vWarn("GeoIP request socket error (request id %1): %2").arg(request->id())
00199 .arg(errorString);
00200 delete socket;
00201 delete request;
00202 }
00203 }
00204
00205
00206 GeoIpRequest*
00207 GeoIpResolver::createRequest(QList<QHostAddress> ips)
00208 {
00209 static int id = -1;
00210 GeoIpRequest *request = new GeoIpRequest(++id);
00211 request->setHost(GEOIP_HOST);
00212 request->setPage(GEOIP_PAGE);
00213 request->setRequest(ips);
00214 return request;
00215 }
00216
00217
00218 int
00219 GeoIpResolver::resolve(QList<QHostAddress> ips)
00220 {
00221
00222
00223 QList<QHostAddress> uncached = resolveFromCache(ips);
00224 if (!uncached.size()) {
00225 return -1;
00226 }
00227
00228
00229 #if defined(USE_QSSLSOCKET)
00230 TorSslSocket *socket = new TorSslSocket(_socksAddr, _socksPort);
00231 #else
00232 TorSocket *socket = new TorSocket(_socksAddr, _socksPort);
00233 #endif
00234
00235 connect(socket, SIGNAL(connectedToRemoteHost()), this, SLOT(connected()),
00236 Qt::QueuedConnection);
00237 connect(socket, SIGNAL(socketError(QString)),
00238 this, SLOT(socketError(QString)),
00239 Qt::QueuedConnection);
00240 connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()),
00241 Qt::QueuedConnection);
00242 GeoIpRequest *request = createRequest(ips);
00243 _requestList.insert(socket, request);
00244
00245
00246 #if defined(USE_QSSLSOCKET)
00247 if (TorSslSocket::supportsSsl()) {
00248 vInfo("Opening an SSL connection to the GeoIP host at %1:%2 (request id %3)")
00249 .arg(GEOIP_HOST).arg(GEOIP_SSL_PORT).arg(request->id());
00250 socket->connectToRemoteHost(GEOIP_HOST, GEOIP_SSL_PORT, true);
00251 } else {
00252 vInfo("Opening an unencrypted connection to the GeoIP host at %1:%2 "
00253 "(request id %3)").arg(GEOIP_HOST).arg(GEOIP_PORT).arg(request->id());
00254 socket->connectToRemoteHost(GEOIP_HOST, GEOIP_PORT, false);
00255 }
00256 #else
00257 vInfo("Opening an unencrypted connection to the GeoIP host at %1:%2 "
00258 "(request id %3)").arg(GEOIP_HOST).arg(GEOIP_PORT).arg(request->id());
00259 socket->connectToRemoteHost(GEOIP_HOST, GEOIP_PORT);
00260 #endif
00261 return request->id();
00262 }
00263