Another big update today.
[quassel.git] / network / server.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005/06 by The Quassel Team                             *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "global.h"
22 #include "server.h"
23 #include "cmdcodes.h"
24
25 #include <QMetaObject>
26
27 Server::Server(QString net) : network(net) {
28
29 }
30
31 Server::~Server() {
32
33 }
34
35 void Server::run() {
36   connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
37   connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
38   connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
39   connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
40   connect(&socket, SIGNAL(readyRead()), this, SLOT(socketHasData()));
41
42   exec();
43 }
44
45 void Server::connectToIrc(QString net) {
46   if(net != network) return; // not me!
47   QList<QVariant> servers = global->getData("Networks").toMap()[net].toMap()["Servers"].toList();
48   qDebug() << "Connecting to"<< servers[0].toMap();
49   QString host = servers[0].toMap()["Address"].toString();
50   quint16 port = servers[0].toMap()["Port"].toUInt();
51   sendStatusMsg(QString("Connecting to %1:%2...").arg(host).arg(port));
52   socket.connectToHost(host, port);
53 }
54
55 void Server::disconnectFromIrc(QString net) {
56   if(net != network) return; // not me!
57   socket.disconnectFromHost();
58 }
59
60 void Server::socketHasData() {
61   while(socket.canReadLine()) {
62     QString s = socket.readLine().trimmed();
63     //qDebug() << "Read: " << s;
64     emit recvRawServerMsg(s);
65     //Message *msg = Message::createFromServerString(this, s);
66     handleServerMsg(s);
67   }
68 }
69
70 void Server::socketError( QAbstractSocket::SocketError err ) {
71   qDebug() << "Socket Error!";
72   //emit error(err);
73 }
74
75 void Server::socketConnected( ) {
76   qDebug() << "Socket connected!";
77   putRawLine("NICK :QuasselDev");
78   putRawLine("USER Sputnick 8 * :Using Quassel IRC (WiP Version)");
79 }
80
81 void Server::socketDisconnected( ) {
82   qDebug() << "Socket disconnected!";
83   //emit disconnected();
84 }
85
86 void Server::socketStateChanged(QAbstractSocket::SocketState state) {
87   qDebug() << "Socket state changed: " << state;
88 }
89
90 void Server::userInput(QString net, QString buf, QString msg) {
91   putRawLine(msg);
92 }
93
94 void Server::putRawLine(QString s) {
95   qDebug() << "SentRaw: " << s;
96   s += "\r\n";
97   socket.write(s.toAscii());
98 }
99
100 void Server::putCmd(QString cmd, QStringList params, QString prefix) {
101   QString m;
102   if(!prefix.isEmpty()) m += ":" + prefix + " ";
103   m += cmd.toUpper();
104   for(int i = 0; i < params.size() - 1; i++) {
105     m += " " + params[i];
106   }
107   if(!params.isEmpty()) m += " :" + params.last();
108   qDebug() << "SentCmd: " << m;
109   m += "\r\n";
110   socket.write(m.toAscii());
111 }
112
113 /** Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
114 void Server::handleServerMsg(QString msg) {
115   try {
116     if(msg.isEmpty()) {
117       qWarning() << "Received empty string from server!";
118       return;
119     }
120     // OK, first we split the raw message into its various parts...
121     QString prefix;
122     QString cmd;
123     QStringList params;
124     if(msg[0] == ':') {
125       msg.remove(0,1);
126       prefix = msg.section(' ', 0, 0);
127       msg = msg.section(' ', 1);
128     }
129     cmd = msg.section(' ', 0, 0).toUpper();
130     msg = msg.section(' ', 1);
131     QString left = msg.section(':', 0, 0);
132     QString trailing = msg.section(':', 1);
133     if(!left.isEmpty()) {
134       params << left.split(' ', QString::SkipEmptyParts);
135     }
136     if(!trailing.isEmpty()) {
137       params << trailing;
138     }
139     // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-)
140     QString hname = cmd.toLower();
141     hname[0] = hname[0].toUpper();
142     hname = "handle" + hname + "FromServer";
143     if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, prefix), Q_ARG(QStringList, params))) {
144       // Ok. Default handler it is.
145       defaultHandlerForServer(cmd, prefix, params);
146     }
147   } catch(Exception e) {
148     emit sendStatusMsg(e.msg());
149   }
150 }
151
152 void Server::defaultHandlerForServer(QString cmd, QString prefix, QStringList params) {
153   uint num = cmd.toUInt();
154   if(num) {
155     emit sendMessage("", cmd + " " + params.join(" "));
156   } else {
157     emit sendMessage("", QString("Unknown: ") + cmd + " " + params.join(" "));
158   }
159 }
160
161 void Server::handleUserMsg(QString usrMsg) {
162
163 }
164
165 void Server::handleNoticeFromServer(QString prefix, QStringList params) {
166   sendMessage("", params.join(" "));
167
168
169 }
170
171 void Server::handlePingFromServer(QString prefix, QStringList params) {
172   putCmd("PONG", params);
173 }
174
175 /* Exception classes for message handling */
176 Server::ParseError::ParseError(QString cmd, QString prefix, QStringList params) {
177   _msg = QString("Command Parse Error: ") + cmd + params.join(" ");
178
179 }
180
181 Server::UnknownCmdError::UnknownCmdError(QString cmd, QString prefix, QStringList params) {
182   _msg = QString("Unknown Command: ") + cmd;
183
184 }