00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QHostAddress>
00029 #include <util/string.h>
00030 #include <vidalia.h>
00031
00032 #include "controlsocket.h"
00033
00034
00035
00036
00037 #define CONN_TIMEOUT 5000
00038
00039
00040
00041 #define READ_TIMEOUT 250
00042
00043
00044
00045 ControlSocket::ControlSocket()
00046 {
00047 }
00048
00049
00050
00051
00052
00053 bool
00054 ControlSocket::connect(QHostAddress addr, quint16 port, QString *errmsg)
00055 {
00056
00057 vNotice("Connecting to Tor's control port on %1:%2").arg(addr.toString())
00058 .arg(port);
00059 connectToHost(addr, port);
00060 if (!waitForConnected(CONN_TIMEOUT)) {
00061 vWarn("Failed to connect to Tor's control port: %1").arg(errorString());
00062 return err(errmsg, tr("Error connecting to %1:%2 [%3]")
00063 .arg(addr.toString())
00064 .arg(port)
00065 .arg(errorString()));
00066 }
00067 return true;
00068 }
00069
00070
00071 bool
00072 ControlSocket::disconnect(QString *errmsg)
00073 {
00074 disconnectFromHost();
00075 if (isConnected()) {
00076 if (!waitForDisconnected(CONN_TIMEOUT)) {
00077 vWarn("Failed to disconnect from Tor: %1").arg(errorString());
00078 return err(errmsg, tr("Error disconnecting socket. [%1]")
00079 .arg(errorString()));
00080 }
00081 }
00082 return true;
00083 }
00084
00085
00086
00087 bool
00088 ControlSocket::isConnected()
00089 {
00090 return (isValid() && state() == QAbstractSocket::ConnectedState);
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100 bool
00101 ControlSocket::sendCommand(ControlCommand cmd, QString *errmsg)
00102 {
00103 if (!isConnected()) {
00104 return err(errmsg, tr("Control socket is not connected."));
00105 }
00106
00107
00108 QString strCmd = cmd.toString();
00109 vInfo("Control Command: %1").arg(strCmd.trimmed());
00110
00111
00112 if (write(strCmd.toAscii()) != strCmd.length()) {
00113 return err(errmsg, tr("Error sending control command. [%1]")
00114 .arg(errorString()));
00115 }
00116 flush();
00117 return true;
00118 }
00119
00120
00121
00122 bool
00123 ControlSocket::readLineData(QString &line, QString *errmsg)
00124 {
00125 char buffer[1024];
00126 int bytesRecv = QAbstractSocket::readLine(buffer, 1024);
00127 while (bytesRecv != -1) {
00128 line.append(buffer);
00129 if (buffer[bytesRecv-1] == '\n') {
00130 break;
00131 }
00132 bytesRecv = QAbstractSocket::readLine(buffer, 1024);
00133 }
00134 if (bytesRecv == -1) {
00135 return err(errmsg, errorString());
00136 }
00137 return true;
00138 }
00139
00140
00141
00142
00143 bool
00144 ControlSocket::readLine(QString &line, QString *errmsg)
00145 {
00146
00147
00148 while (!canReadLine()) {
00149 if (!isConnected()) {
00150 return err(errmsg, tr("Socket disconnected while attempting "
00151 "to read a line of data."));
00152 }
00153 waitForReadyRead(READ_TIMEOUT);
00154 }
00155 line.clear();
00156 return readLineData(line, errmsg);
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 bool
00172 ControlSocket::readReply(ControlReply &reply, QString *errmsg)
00173 {
00174 QChar c;
00175 QString line;
00176
00177 if (!isConnected()) {
00178 return false;
00179 }
00180
00181
00182 do {
00183
00184 if (!readLine(line, errmsg)) {
00185 return false;
00186 }
00187
00188 if (line.length() < 4) {
00189 return err(errmsg, tr("Invalid control reply. [%1]").arg(line));
00190 }
00191
00192
00193 ReplyLine replyLine(line.mid(0, 3), line.mid(4));
00194 c = line.at(3);
00195
00196
00197
00198 if (c == QChar('+') &&
00199 !line.startsWith("250+PROTOCOLINFO")) {
00200
00201
00202
00203 while (true) {
00204 if (!readLine(line, errmsg)) {
00205 return false;
00206 }
00207 if (line.trimmed() == ".") {
00208 break;
00209 }
00210 replyLine.appendData(line);
00211 }
00212 }
00213 reply.appendLine(replyLine);
00214 } while (c != QChar(' '));
00215 return true;
00216 }
00217