/
ServerComm.cpp
executable file
·167 lines (151 loc) · 5.28 KB
/
ServerComm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//
// File: ServerComm.cpp
//
// Copyright (c) 2009, 2010 University of Toronto and Steve Harvey
//
#include <QtGui>
#include <QtDebug>
#include <QBuffer>
#include <QUrl>
#include <cstring>
#include "ServerComm.h"
#include "HttpGet.h"
#include "TrHttp.h"
#include <QHttp>
ServerComm::ServerComm(QWidget* owner) {
this->owner = owner;
}
/** Do an HTTP GET of the directory on the server that has the
* available traceroute sets. The directory listing is parsed
* for links, and these are appended to the trsets vector.
*/
bool ServerComm::getTrSets(QStringList& trsets, bool popupOnError) {
static bool in_progress = false;
if ( in_progress )
return false;
//in theory, a race condition is here.
in_progress = true;
trsets.clear();
QBuffer buf;
buf.open(QBuffer::WriteOnly);
QUrl url("http://trgen.ixmaps.ca/trsets/");
HttpGet hget(url, &buf);
qDebug() << "HttpGet error " << hget.error();
QHttp::Error err = hget.error();
if ( err != QHttp::NoError ) {
msgConnFailure(err, popupOnError);
in_progress = false;
return false;
}
// scan the Apache directory listing. This makes it easy to change deployment
// of batch trace files.
// To see what this is parsing, fetch the link in a browser and view source.
char prefix_str[] = "<a href=\"";
qDebug() << "prefix_str len is " << sizeof(prefix_str);
QByteArray ba = buf.buffer();
char *s = ba.data();
qDebug() << "from server got: " << s;
char *e = s + ba.count() - (sizeof(prefix_str)+2); // guard against read past buffer end
while ( s < e ) {
// look for <a href="something.trset"
if ( strncmp(s, prefix_str, sizeof(prefix_str)-1) == 0 ) {
// found a likely URL
char *token = s+sizeof(prefix_str)-1;
char *p;
for ( p = token; *p != '"'; p++ ) {
if ( p >= e )
goto end_buffer;
}
*p = '\0'; // stomp the closing quote -> string terminator
if ( token[0] == '.' && token[1] == '/' )
token += 2; // ignore superfluous ./ in ./something.trset
// Apache directory listing contains a few unwanted URLs beginning with ? or /
// restrict filenames to those ending with ".trset"
if ( token[0] != '?' && token[0] != '/' && strcmp(p-6, ".trset") == 0 ) {
QString qstr(token);
trsets << qstr;
qDebug() << "getTrSets got " << qstr.toAscii().data();
}
s = p+1;
} else
s++;
}
end_buffer:
in_progress = false;
return true;
}
int ServerComm::msgConnFailure(QHttp::Error err, bool popupOnError) {
int rc;
switch ( err ) {
case QHttp::HostNotFound: rc = TrStatus::ERR_HOST_NOT_FOUND; break;
case QHttp::ConnectionRefused: rc = TrStatus::ERR_CONNECTION_REFUSED; break;
case QHttp::UnexpectedClose: rc = TrStatus::ERR_UNEXPECTED_CLOSE; break;
case QHttp::InvalidResponseHeader: rc = TrStatus::ERR_INVALID_RESPONSE_HEADER; break;
case QHttp::WrongContentLength: rc = TrStatus::ERR_WRONG_CONTENT_LENGTH; break;
case QHttp::Aborted: rc = TrStatus::ERR_REQUEST_ABORTED; break;
case QHttp::ProxyAuthenticationRequiredError: rc = TrStatus::ERR_PROXY_AUTH_REQ; break;
case QHttp::AuthenticationRequiredError: rc = TrStatus::ERR_AUTH_REQ; break;
default: rc = TrStatus::ERR_UNKNOWN_CONNECT_ERR; break;
}
QString why = TrStatus::getErrorTextByCode(rc);
if ( popupOnError ) {
QMessageBox::critical(owner, tr("Connection failure"),
tr("The connection to the central database is not working.")+" ("+why+")", QMessageBox::Ok);
}
return rc;
}
/** Submit a traceroute formatted as HTTP POST data to the server.
*/
bool ServerComm::submitTraceroute(const char *post_data, TrStatus *tstat, bool popupOnError) {
bool submitted_ok = true;
qDebug() << post_data;
TrHttp th("trgen.ixmaps.ca", post_data, tstat);
subm_waiting_completion = true;
connect(&th, SIGNAL(done(bool)), this, SLOT(trResultsSubmitted(bool)));
QTime dieTime = QTime::currentTime().addSecs(5);
while( QTime::currentTime() < dieTime ) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
if ( !subm_waiting_completion ) {
break;
}
}
if ( subm_waiting_completion ) {
if ( popupOnError ) {
QMessageBox::critical(owner, tr("Connection failure"),
tr("The connection to the central database is not working."),
QMessageBox::Ok);
}
tstat->setError(TrStatus::ERR_SUBMIT_TIMEOUT);
submitted_ok = false;
} else {
//qDebug() << "TrHttp error " << th.error();
QHttp::Error err = th.error();
if ( err != QHttp::NoError ) {
tstat->setError(msgConnFailure(err, popupOnError));
submitted_ok = false;
}
}
qDebug() << "posting, state " << th.state() << ", error " << th.error();
qDebug() << "TID=" << tstat->traceroute_id << ", errorMsg=" << tstat->errorMsg;
return submitted_ok;
}
void ServerComm::trResultsSubmitted(bool error) {
subm_error_status = error; // not used, submitTraceroute() queries the TrHttp object for this
subm_waiting_completion = false;
}
/** Fetch a trset batch file from the server.
*/
bool ServerComm::fetchBatch(const QString& filename, QBuffer& buf, bool popupOnError) {
buf.open(QBuffer::WriteOnly);
QString str_url("http://trgen.ixmaps.ca/trsets/");
str_url += filename;
QUrl url(str_url);
HttpGet hget(url, &buf);
qDebug() << "HttpGet error " << hget.error();
QHttp::Error err = hget.error();
if ( err != QHttp::NoError ) {
msgConnFailure(err, popupOnError);
return false;
}
return true;
}