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