Quassel IRC  Pre-Release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
network.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2015 by the Quassel Project *
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) version 3. *
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  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19  ***************************************************************************/
20 
21 #include <QTextCodec>
22 
23 #include "network.h"
24 
25 QTextCodec *Network::_defaultCodecForServer = 0;
26 QTextCodec *Network::_defaultCodecForEncoding = 0;
27 QTextCodec *Network::_defaultCodecForDecoding = 0;
28 
29 // ====================
30 // Public:
31 // ====================
33 Network::Network(const NetworkId &networkid, QObject *parent)
34  : SyncableObject(parent),
35  _proxy(0),
36  _networkId(networkid),
37  _identity(0),
38  _myNick(QString()),
39  _latency(0),
40  _networkName(QString("<not initialized>")),
41  _currentServer(QString()),
42  _connected(false),
43  _connectionState(Disconnected),
44  _prefixes(QString()),
45  _prefixModes(QString()),
46  _useRandomServer(false),
47  _useAutoIdentify(false),
48  _useSasl(false),
49  _useAutoReconnect(false),
50  _autoReconnectInterval(60),
51  _autoReconnectRetries(10),
52  _unlimitedReconnectRetries(false),
53  _codecForServer(0),
54  _codecForEncoding(0),
55  _codecForDecoding(0),
56  _autoAwayActive(false)
57 {
58  setObjectName(QString::number(networkid.toInt()));
59 }
60 
61 
63 {
64  emit aboutToBeDestroyed();
65 }
66 
67 
68 bool Network::isChannelName(const QString &channelname) const
69 {
70  if (channelname.isEmpty())
71  return false;
72 
73  if (supports("CHANTYPES"))
74  return support("CHANTYPES").contains(channelname[0]);
75  else
76  return QString("#&!+").contains(channelname[0]);
77 }
78 
79 
81 {
82  NetworkInfo info;
83  info.networkName = networkName();
84  info.networkId = networkId();
85  info.identity = identity();
89  info.serverList = serverList();
91  info.perform = perform();
95  info.useSasl = useSasl();
96  info.saslAccount = saslAccount();
97  info.saslPassword = saslPassword();
103  return info;
104 }
105 
106 
108 {
109  // we don't set our ID!
110  if (!info.networkName.isEmpty() && info.networkName != networkName()) setNetworkName(info.networkName);
111  if (info.identity > 0 && info.identity != identity()) setIdentity(info.identity);
112  if (info.codecForServer != codecForServer()) setCodecForServer(QTextCodec::codecForName(info.codecForServer));
113  if (info.codecForEncoding != codecForEncoding()) setCodecForEncoding(QTextCodec::codecForName(info.codecForEncoding));
114  if (info.codecForDecoding != codecForDecoding()) setCodecForDecoding(QTextCodec::codecForName(info.codecForDecoding));
115  if (info.serverList.count()) setServerList(toVariantList(info.serverList)); // FIXME compare components
117  if (info.perform != perform()) setPerform(info.perform);
121  if (info.useSasl != useSasl()) setUseSasl(info.useSasl);
122  if (info.saslAccount != saslAccount()) setSaslAccount(info.saslAccount);
129 }
130 
131 
132 QString Network::prefixToMode(const QString &prefix) const
133 {
134  if (prefixes().contains(prefix))
135  return QString(prefixModes()[prefixes().indexOf(prefix)]);
136  else
137  return QString();
138 }
139 
140 
141 QString Network::modeToPrefix(const QString &mode) const
142 {
143  if (prefixModes().contains(mode))
144  return QString(prefixes()[prefixModes().indexOf(mode)]);
145  else
146  return QString();
147 }
148 
149 
150 QStringList Network::nicks() const
151 {
152  // we don't use _ircUsers.keys() since the keys may be
153  // not up to date after a nick change
154  QStringList nicks;
155  foreach(IrcUser *ircuser, _ircUsers.values()) {
156  nicks << ircuser->nick();
157  }
158  return nicks;
159 }
160 
161 
162 QString Network::prefixes() const
163 {
164  if (_prefixes.isNull())
166 
167  return _prefixes;
168 }
169 
170 
171 QString Network::prefixModes() const
172 {
173  if (_prefixModes.isNull())
175 
176  return _prefixModes;
177 }
178 
179 
180 // example Unreal IRCD: CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG
182 {
183  if (mode.isEmpty())
184  return NOT_A_CHANMODE;
185 
186  QString chanmodes = support("CHANMODES");
187  if (chanmodes.isEmpty())
188  return NOT_A_CHANMODE;
189 
190  ChannelModeType modeType = A_CHANMODE;
191  for (int i = 0; i < chanmodes.count(); i++) {
192  if (chanmodes[i] == mode[0])
193  break;
194  else if (chanmodes[i] == ',')
195  modeType = (ChannelModeType)(modeType << 1);
196  }
197  if (modeType > D_CHANMODE) {
198  qWarning() << "Network" << networkId() << "supplied invalid CHANMODES:" << chanmodes;
199  modeType = NOT_A_CHANMODE;
200  }
201  return modeType;
202 }
203 
204 
205 QString Network::support(const QString &param) const
206 {
207  QString support_ = param.toUpper();
208  if (_supports.contains(support_))
209  return _supports[support_];
210  else
211  return QString();
212 }
213 
214 
215 IrcUser *Network::newIrcUser(const QString &hostmask, const QVariantMap &initData)
216 {
217  QString nick(nickFromMask(hostmask).toLower());
218  if (!_ircUsers.contains(nick)) {
219  IrcUser *ircuser = ircUserFactory(hostmask);
220  if (!initData.isEmpty()) {
221  ircuser->fromVariantMap(initData);
222  ircuser->setInitialized();
223  }
224 
225  if (proxy())
226  proxy()->synchronize(ircuser);
227  else
228  qWarning() << "unable to synchronize new IrcUser" << hostmask << "forgot to call Network::setProxy(SignalProxy *)?";
229 
230  connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString)));
231 
232  _ircUsers[nick] = ircuser;
233 
234  // This method will be called with a nick instead of hostmask by setInitIrcUsersAndChannels().
235  // Not a problem because initData contains all we need; however, making sure here to get the real
236  // hostmask out of the IrcUser afterwards.
237  QString mask = ircuser->hostmask();
238  SYNC_OTHER(addIrcUser, ARG(mask));
239  // emit ircUserAdded(mask);
240  emit ircUserAdded(ircuser);
241  }
242 
243  return _ircUsers[nick];
244 }
245 
246 
247 IrcUser *Network::ircUser(QString nickname) const
248 {
249  nickname = nickname.toLower();
250  if (_ircUsers.contains(nickname))
251  return _ircUsers[nickname];
252  else
253  return 0;
254 }
255 
256 
258 {
259  QString nick = _ircUsers.key(ircuser);
260  if (nick.isNull())
261  return;
262 
263  _ircUsers.remove(nick);
264  disconnect(ircuser, 0, this, 0);
265  ircuser->deleteLater();
266 }
267 
268 
270 {
271  QString chanName = _ircChannels.key(channel);
272  if (chanName.isNull())
273  return;
274 
275  _ircChannels.remove(chanName);
276  disconnect(channel, 0, this, 0);
277  channel->deleteLater();
278 }
279 
280 
282 {
283  QList<IrcUser *> users = ircUsers();
284  _ircUsers.clear();
285  QList<IrcChannel *> channels = ircChannels();
286  _ircChannels.clear();
287 
288  qDeleteAll(users);
289  qDeleteAll(channels);
290 }
291 
292 
293 IrcChannel *Network::newIrcChannel(const QString &channelname, const QVariantMap &initData)
294 {
295  if (!_ircChannels.contains(channelname.toLower())) {
296  IrcChannel *channel = ircChannelFactory(channelname);
297  if (!initData.isEmpty()) {
298  channel->fromVariantMap(initData);
299  channel->setInitialized();
300  }
301 
302  if (proxy())
303  proxy()->synchronize(channel);
304  else
305  qWarning() << "unable to synchronize new IrcChannel" << channelname << "forgot to call Network::setProxy(SignalProxy *)?";
306 
307  _ircChannels[channelname.toLower()] = channel;
308 
309  SYNC_OTHER(addIrcChannel, ARG(channelname))
310  // emit ircChannelAdded(channelname);
311  emit ircChannelAdded(channel);
312  }
313  return _ircChannels[channelname.toLower()];
314 }
315 
316 
317 IrcChannel *Network::ircChannel(QString channelname) const
318 {
319  channelname = channelname.toLower();
320  if (_ircChannels.contains(channelname))
321  return _ircChannels[channelname];
322  else
323  return 0;
324 }
325 
326 
328 {
330  return _defaultCodecForServer->name();
331  return QByteArray();
332 }
333 
334 
335 void Network::setDefaultCodecForServer(const QByteArray &name)
336 {
337  _defaultCodecForServer = QTextCodec::codecForName(name);
338 }
339 
340 
342 {
344  return _defaultCodecForEncoding->name();
345  return QByteArray();
346 }
347 
348 
349 void Network::setDefaultCodecForEncoding(const QByteArray &name)
350 {
351  _defaultCodecForEncoding = QTextCodec::codecForName(name);
352 }
353 
354 
356 {
358  return _defaultCodecForDecoding->name();
359  return QByteArray();
360 }
361 
362 
363 void Network::setDefaultCodecForDecoding(const QByteArray &name)
364 {
365  _defaultCodecForDecoding = QTextCodec::codecForName(name);
366 }
367 
368 
369 QByteArray Network::codecForServer() const
370 {
371  if (_codecForServer)
372  return _codecForServer->name();
373  return QByteArray();
374 }
375 
376 
377 void Network::setCodecForServer(const QByteArray &name)
378 {
379  setCodecForServer(QTextCodec::codecForName(name));
380 }
381 
382 
383 void Network::setCodecForServer(QTextCodec *codec)
384 {
385  _codecForServer = codec;
386  QByteArray codecName = codecForServer();
387  SYNC_OTHER(setCodecForServer, ARG(codecName))
388  emit configChanged();
389 }
390 
391 
392 QByteArray Network::codecForEncoding() const
393 {
394  if (_codecForEncoding)
395  return _codecForEncoding->name();
396  return QByteArray();
397 }
398 
399 
400 void Network::setCodecForEncoding(const QByteArray &name)
401 {
402  setCodecForEncoding(QTextCodec::codecForName(name));
403 }
404 
405 
406 void Network::setCodecForEncoding(QTextCodec *codec)
407 {
408  _codecForEncoding = codec;
409  QByteArray codecName = codecForEncoding();
410  SYNC_OTHER(setCodecForEncoding, ARG(codecName))
411  emit configChanged();
412 }
413 
414 
415 QByteArray Network::codecForDecoding() const
416 {
417  if (_codecForDecoding)
418  return _codecForDecoding->name();
419  else return QByteArray();
420 }
421 
422 
423 void Network::setCodecForDecoding(const QByteArray &name)
424 {
425  setCodecForDecoding(QTextCodec::codecForName(name));
426 }
427 
428 
429 void Network::setCodecForDecoding(QTextCodec *codec)
430 {
431  _codecForDecoding = codec;
432  QByteArray codecName = codecForDecoding();
433  SYNC_OTHER(setCodecForDecoding, ARG(codecName))
434  emit configChanged();
435 }
436 
437 
438 // FIXME use server encoding if appropriate
439 QString Network::decodeString(const QByteArray &text) const
440 {
441  if (_codecForDecoding)
444 }
445 
446 
447 QByteArray Network::encodeString(const QString &string) const
448 {
449  if (_codecForEncoding) {
450  return _codecForEncoding->fromUnicode(string);
451  }
453  return _defaultCodecForEncoding->fromUnicode(string);
454  }
455  return string.toLatin1();
456 }
457 
458 
459 QString Network::decodeServerString(const QByteArray &text) const
460 {
461  if (_codecForServer)
463  else
465 }
466 
467 
468 QByteArray Network::encodeServerString(const QString &string) const
469 {
470  if (_codecForServer) {
471  return _codecForServer->fromUnicode(string);
472  }
474  return _defaultCodecForServer->fromUnicode(string);
475  }
476  return string.toLatin1();
477 }
478 
479 
480 // ====================
481 // Public Slots:
482 // ====================
483 void Network::setNetworkName(const QString &networkName)
484 {
486  SYNC(ARG(networkName))
487  emit networkNameSet(networkName);
488  emit configChanged();
489 }
490 
491 
492 void Network::setCurrentServer(const QString &currentServer)
493 {
495  SYNC(ARG(currentServer))
496  emit currentServerSet(currentServer);
497 }
498 
499 
500 void Network::setConnected(bool connected)
501 {
502  if (_connected == connected)
503  return;
504 
505  _connected = connected;
506  if (!connected) {
507  setMyNick(QString());
508  setCurrentServer(QString());
510  }
511  SYNC(ARG(connected))
512  emit connectedSet(connected);
513 }
514 
515 
516 //void Network::setConnectionState(ConnectionState state) {
518 {
519  _connectionState = (ConnectionState)state;
520  //qDebug() << "netstate" << networkId() << networkName() << state;
521  SYNC(ARG(state))
523 }
524 
525 
526 void Network::setMyNick(const QString &nickname)
527 {
528  _myNick = nickname;
529  if (!_myNick.isEmpty() && !ircUser(myNick())) {
530  newIrcUser(myNick());
531  }
532  SYNC(ARG(nickname))
533  emit myNickSet(nickname);
534 }
535 
536 
537 void Network::setLatency(int latency)
538 {
539  if (_latency == latency)
540  return;
541  _latency = latency;
542  SYNC(ARG(latency))
543 }
544 
545 
547 {
548  _identity = id;
549  SYNC(ARG(id))
550  emit identitySet(id);
551  emit configChanged();
552 }
553 
554 
555 void Network::setServerList(const QVariantList &serverList)
556 {
557  _serverList = fromVariantList<Server>(serverList);
558  SYNC(ARG(serverList))
559  emit configChanged();
560 }
561 
562 
564 {
565  _useRandomServer = use;
566  SYNC(ARG(use))
567  emit configChanged();
568 }
569 
570 
571 void Network::setPerform(const QStringList &perform)
572 {
573  _perform = perform;
574  SYNC(ARG(perform))
575  emit configChanged();
576 }
577 
578 
580 {
581  _useAutoIdentify = use;
582  SYNC(ARG(use))
583  emit configChanged();
584 }
585 
586 
587 void Network::setAutoIdentifyService(const QString &service)
588 {
589  _autoIdentifyService = service;
590  SYNC(ARG(service))
591  emit configChanged();
592 }
593 
594 
595 void Network::setAutoIdentifyPassword(const QString &password)
596 {
597  _autoIdentifyPassword = password;
598  SYNC(ARG(password))
599  emit configChanged();
600 }
601 
602 
603 void Network::setUseSasl(bool use)
604 {
605  _useSasl = use;
606  SYNC(ARG(use))
607  emit configChanged();
608 }
609 
610 
611 void Network::setSaslAccount(const QString &account)
612 {
613  _saslAccount = account;
614  SYNC(ARG(account))
615  emit configChanged();
616 }
617 
618 
619 void Network::setSaslPassword(const QString &password)
620 {
621  _saslPassword = password;
622  SYNC(ARG(password))
623  emit configChanged();
624 }
625 
626 
628 {
629  _useAutoReconnect = use;
630  SYNC(ARG(use))
631  emit configChanged();
632 }
633 
634 
635 void Network::setAutoReconnectInterval(quint32 interval)
636 {
637  _autoReconnectInterval = interval;
638  SYNC(ARG(interval))
639  emit configChanged();
640 }
641 
642 
643 void Network::setAutoReconnectRetries(quint16 retries)
644 {
645  _autoReconnectRetries = retries;
646  SYNC(ARG(retries))
647  emit configChanged();
648 }
649 
650 
652 {
653  _unlimitedReconnectRetries = unlimited;
654  SYNC(ARG(unlimited))
655  emit configChanged();
656 }
657 
658 
659 void Network::setRejoinChannels(bool rejoin)
660 {
661  _rejoinChannels = rejoin;
662  SYNC(ARG(rejoin))
663  emit configChanged();
664 }
665 
666 
667 void Network::addSupport(const QString &param, const QString &value)
668 {
669  if (!_supports.contains(param)) {
670  _supports[param] = value;
671  SYNC(ARG(param), ARG(value))
672  }
673 }
674 
675 
676 void Network::removeSupport(const QString &param)
677 {
678  if (_supports.contains(param)) {
679  _supports.remove(param);
680  SYNC(ARG(param))
681  }
682 }
683 
684 
685 QVariantMap Network::initSupports() const
686 {
687  QVariantMap supports;
688  QHashIterator<QString, QString> iter(_supports);
689  while (iter.hasNext()) {
690  iter.next();
691  supports[iter.key()] = iter.value();
692  }
693  return supports;
694 }
695 
696 
697 // There's potentially a lot of users and channels, so it makes sense to optimize the format of this.
698 // Rather than sending a thousand maps with identical keys, we convert this into one map containing lists
699 // where each list index corresponds to a particular IrcUser. This saves sending the key names a thousand times.
700 // Benchmarks have shown space savings of around 56%, resulting in saving several MBs worth of data on sync
701 // (without compression) with a decent amount of IrcUsers.
703 {
704  QVariantMap usersAndChannels;
705 
706  if (_ircUsers.count()) {
707  QHash<QString, QVariantList> users;
708  QHash<QString, IrcUser *>::const_iterator it = _ircUsers.begin();
709  QHash<QString, IrcUser *>::const_iterator end = _ircUsers.end();
710  while (it != end) {
711  const QVariantMap &map = it.value()->toVariantMap();
712  QVariantMap::const_iterator mapiter = map.begin();
713  while (mapiter != map.end()) {
714  users[mapiter.key()] << mapiter.value();
715  ++mapiter;
716  }
717  ++it;
718  }
719  // Can't have a container with a value type != QVariant in a QVariant :(
720  // However, working directly on a QVariantMap is awkward for appending, thus the detour via the hash above.
721  QVariantMap userMap;
722  foreach(const QString &key, users.keys())
723  userMap[key] = users[key];
724  usersAndChannels["Users"] = userMap;
725  }
726 
727  if (_ircChannels.count()) {
728  QHash<QString, QVariantList> channels;
729  QHash<QString, IrcChannel *>::const_iterator it = _ircChannels.begin();
730  QHash<QString, IrcChannel *>::const_iterator end = _ircChannels.end();
731  while (it != end) {
732  const QVariantMap &map = it.value()->toVariantMap();
733  QVariantMap::const_iterator mapiter = map.begin();
734  while (mapiter != map.end()) {
735  channels[mapiter.key()] << mapiter.value();
736  ++mapiter;
737  }
738  ++it;
739  }
740  QVariantMap channelMap;
741  foreach(const QString &key, channels.keys())
742  channelMap[key] = channels[key];
743  usersAndChannels["Channels"] = channelMap;
744  }
745 
746  return usersAndChannels;
747 }
748 
749 
750 void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels)
751 {
752  Q_ASSERT(proxy());
753  if (isInitialized()) {
754  qWarning() << "Network" << networkId() << "received init data for users and channels although there already are known users or channels!";
755  return;
756  }
757 
758  // toMap() and toList() are cheap, so we can avoid copying to lists...
759  // However, we really have to make sure to never accidentally detach from the shared data!
760 
761  const QVariantMap &users = usersAndChannels["Users"].toMap();
762 
763  // sanity check
764  int count = users["nick"].toList().count();
765  foreach(const QString &key, users.keys()) {
766  if (users[key].toList().count() != count) {
767  qWarning() << "Received invalid usersAndChannels init data, sizes of attribute lists don't match!";
768  return;
769  }
770  }
771 
772  // now create the individual IrcUsers
773  for(int i = 0; i < count; i++) {
774  QVariantMap map;
775  foreach(const QString &key, users.keys())
776  map[key] = users[key].toList().at(i);
777  newIrcUser(map["nick"].toString(), map); // newIrcUser() properly handles the hostmask being just the nick
778  }
779 
780  // same thing for IrcChannels
781  const QVariantMap &channels = usersAndChannels["Channels"].toMap();
782 
783  // sanity check
784  count = channels["name"].toList().count();
785  foreach(const QString &key, channels.keys()) {
786  if (channels[key].toList().count() != count) {
787  qWarning() << "Received invalid usersAndChannels init data, sizes of attribute lists don't match!";
788  return;
789  }
790  }
791  // now create the individual IrcChannels
792  for(int i = 0; i < count; i++) {
793  QVariantMap map;
794  foreach(const QString &key, channels.keys())
795  map[key] = channels[key].toList().at(i);
796  newIrcChannel(map["name"].toString(), map);
797  }
798 }
799 
800 
801 void Network::initSetSupports(const QVariantMap &supports)
802 {
803  QMapIterator<QString, QVariant> iter(supports);
804  while (iter.hasNext()) {
805  iter.next();
806  addSupport(iter.key(), iter.value().toString());
807  }
808 }
809 
810 
812 {
813  QString nick(nickFromMask(mask).toLower());
814  IrcUser *ircuser;
815 
816  if (_ircUsers.contains(nick)) {
817  ircuser = _ircUsers[nick];
818  ircuser->updateHostmask(mask);
819  }
820  else {
821  ircuser = newIrcUser(mask);
822  }
823  return ircuser;
824 }
825 
826 
827 void Network::ircUserNickChanged(QString newnick)
828 {
829  QString oldnick = _ircUsers.key(qobject_cast<IrcUser *>(sender()));
830 
831  if (oldnick.isNull())
832  return;
833 
834  if (newnick.toLower() != oldnick) _ircUsers[newnick.toLower()] = _ircUsers.take(oldnick);
835 
836  if (myNick().toLower() == oldnick)
837  setMyNick(newnick);
838 }
839 
840 
841 void Network::emitConnectionError(const QString &errorMsg)
842 {
843  emit connectionError(errorMsg);
844 }
845 
846 
847 // ====================
848 // Private:
849 // ====================
851 {
852  // seems like we have to construct them first
853  QString prefix = support("PREFIX");
854 
855  if (prefix.startsWith("(") && prefix.contains(")")) {
856  _prefixes = prefix.section(")", 1);
857  _prefixModes = prefix.mid(1).section(")", 0, 0);
858  }
859  else {
860  QString defaultPrefixes("~&@%+");
861  QString defaultPrefixModes("qaohv");
862 
863  if (prefix.isEmpty()) {
864  _prefixes = defaultPrefixes;
865  _prefixModes = defaultPrefixModes;
866  return;
867  }
868  // clear the existing modes, just in case we're run multiple times
869  _prefixes = QString();
870  _prefixModes = QString();
871 
872  // we just assume that in PREFIX are only prefix chars stored
873  for (int i = 0; i < defaultPrefixes.size(); i++) {
874  if (prefix.contains(defaultPrefixes[i])) {
875  _prefixes += defaultPrefixes[i];
876  _prefixModes += defaultPrefixModes[i];
877  }
878  }
879  // check for success
880  if (!_prefixes.isNull())
881  return;
882 
883  // well... our assumption was obviously wrong...
884  // check if it's only prefix modes
885  for (int i = 0; i < defaultPrefixes.size(); i++) {
886  if (prefix.contains(defaultPrefixModes[i])) {
887  _prefixes += defaultPrefixes[i];
888  _prefixModes += defaultPrefixModes[i];
889  }
890  }
891  // now we've done all we've could...
892  }
893 }
894 
895 
896 /************************************************************************
897  * NetworkInfo
898  ************************************************************************/
899 
901  : networkId(0),
902  identity(1),
903  useRandomServer(false),
904  useAutoIdentify(false),
905  autoIdentifyService("NickServ"),
906  useSasl(false),
907  useAutoReconnect(true),
908  autoReconnectInterval(60),
909  autoReconnectRetries(20),
910  unlimitedReconnectRetries(false),
911  rejoinChannels(true)
912 {
913 }
914 
915 
916 bool NetworkInfo::operator==(const NetworkInfo &other) const
917 {
918  if (networkId != other.networkId) return false;
919  if (networkName != other.networkName) return false;
920  if (identity != other.identity) return false;
921  if (codecForServer != other.codecForServer) return false;
922  if (codecForEncoding != other.codecForEncoding) return false;
923  if (codecForDecoding != other.codecForDecoding) return false;
924  if (serverList != other.serverList) return false;
925  if (useRandomServer != other.useRandomServer) return false;
926  if (perform != other.perform) return false;
927  if (useAutoIdentify != other.useAutoIdentify) return false;
928  if (autoIdentifyService != other.autoIdentifyService) return false;
929  if (autoIdentifyPassword != other.autoIdentifyPassword) return false;
930  if (useSasl != other.useSasl) return false;
931  if (saslAccount != other.saslAccount) return false;
932  if (saslPassword != other.saslPassword) return false;
933  if (useAutoReconnect != other.useAutoReconnect) return false;
934  if (autoReconnectInterval != other.autoReconnectInterval) return false;
935  if (autoReconnectRetries != other.autoReconnectRetries) return false;
936  if (unlimitedReconnectRetries != other.unlimitedReconnectRetries) return false;
937  if (rejoinChannels != other.rejoinChannels) return false;
938  return true;
939 }
940 
941 
942 bool NetworkInfo::operator!=(const NetworkInfo &other) const
943 {
944  return !(*this == other);
945 }
946 
947 
948 QDataStream &operator<<(QDataStream &out, const NetworkInfo &info)
949 {
950  QVariantMap i;
951  i["NetworkId"] = QVariant::fromValue<NetworkId>(info.networkId);
952  i["NetworkName"] = info.networkName;
953  i["Identity"] = QVariant::fromValue<IdentityId>(info.identity);
954  i["CodecForServer"] = info.codecForServer;
955  i["CodecForEncoding"] = info.codecForEncoding;
956  i["CodecForDecoding"] = info.codecForDecoding;
957  i["ServerList"] = toVariantList(info.serverList);
958  i["UseRandomServer"] = info.useRandomServer;
959  i["Perform"] = info.perform;
960  i["UseAutoIdentify"] = info.useAutoIdentify;
961  i["AutoIdentifyService"] = info.autoIdentifyService;
962  i["AutoIdentifyPassword"] = info.autoIdentifyPassword;
963  i["UseSasl"] = info.useSasl;
964  i["SaslAccount"] = info.saslAccount;
965  i["SaslPassword"] = info.saslPassword;
966  i["UseAutoReconnect"] = info.useAutoReconnect;
967  i["AutoReconnectInterval"] = info.autoReconnectInterval;
968  i["AutoReconnectRetries"] = info.autoReconnectRetries;
969  i["UnlimitedReconnectRetries"] = info.unlimitedReconnectRetries;
970  i["RejoinChannels"] = info.rejoinChannels;
971  out << i;
972  return out;
973 }
974 
975 
976 QDataStream &operator>>(QDataStream &in, NetworkInfo &info)
977 {
978  QVariantMap i;
979  in >> i;
980  info.networkId = i["NetworkId"].value<NetworkId>();
981  info.networkName = i["NetworkName"].toString();
982  info.identity = i["Identity"].value<IdentityId>();
983  info.codecForServer = i["CodecForServer"].toByteArray();
984  info.codecForEncoding = i["CodecForEncoding"].toByteArray();
985  info.codecForDecoding = i["CodecForDecoding"].toByteArray();
986  info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
987  info.useRandomServer = i["UseRandomServer"].toBool();
988  info.perform = i["Perform"].toStringList();
989  info.useAutoIdentify = i["UseAutoIdentify"].toBool();
990  info.autoIdentifyService = i["AutoIdentifyService"].toString();
991  info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
992  info.useSasl = i["UseSasl"].toBool();
993  info.saslAccount = i["SaslAccount"].toString();
994  info.saslPassword = i["SaslPassword"].toString();
995  info.useAutoReconnect = i["UseAutoReconnect"].toBool();
996  info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
997  info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
998  info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
999  info.rejoinChannels = i["RejoinChannels"].toBool();
1000  return in;
1001 }
1002 
1003 
1004 QDebug operator<<(QDebug dbg, const NetworkInfo &i)
1005 {
1006  dbg.nospace() << "(id = " << i.networkId << " name = " << i.networkName << " identity = " << i.identity
1007  << " codecForServer = " << i.codecForServer << " codecForEncoding = " << i.codecForEncoding << " codecForDecoding = " << i.codecForDecoding
1008  << " serverList = " << i.serverList << " useRandomServer = " << i.useRandomServer << " perform = " << i.perform
1009  << " useAutoIdentify = " << i.useAutoIdentify << " autoIdentifyService = " << i.autoIdentifyService << " autoIdentifyPassword = " << i.autoIdentifyPassword
1010  << " useSasl = " << i.useSasl << " saslAccount = " << i.saslAccount << " saslPassword = " << i.saslPassword
1011  << " useAutoReconnect = " << i.useAutoReconnect << " autoReconnectInterval = " << i.autoReconnectInterval
1012  << " autoReconnectRetries = " << i.autoReconnectRetries << " unlimitedReconnectRetries = " << i.unlimitedReconnectRetries
1013  << " rejoinChannels = " << i.rejoinChannels << ")";
1014  return dbg.space();
1015 }
1016 
1017 
1018 QDataStream &operator<<(QDataStream &out, const Network::Server &server)
1019 {
1020  QVariantMap serverMap;
1021  serverMap["Host"] = server.host;
1022  serverMap["Port"] = server.port;
1023  serverMap["Password"] = server.password;
1024  serverMap["UseSSL"] = server.useSsl;
1025  serverMap["sslVersion"] = server.sslVersion;
1026  serverMap["UseProxy"] = server.useProxy;
1027  serverMap["ProxyType"] = server.proxyType;
1028  serverMap["ProxyHost"] = server.proxyHost;
1029  serverMap["ProxyPort"] = server.proxyPort;
1030  serverMap["ProxyUser"] = server.proxyUser;
1031  serverMap["ProxyPass"] = server.proxyPass;
1032  out << serverMap;
1033  return out;
1034 }
1035 
1036 
1037 QDataStream &operator>>(QDataStream &in, Network::Server &server)
1038 {
1039  QVariantMap serverMap;
1040  in >> serverMap;
1041  server.host = serverMap["Host"].toString();
1042  server.port = serverMap["Port"].toUInt();
1043  server.password = serverMap["Password"].toString();
1044  server.useSsl = serverMap["UseSSL"].toBool();
1045  server.sslVersion = serverMap["sslVersion"].toInt();
1046  server.useProxy = serverMap["UseProxy"].toBool();
1047  server.proxyType = serverMap["ProxyType"].toInt();
1048  server.proxyHost = serverMap["ProxyHost"].toString();
1049  server.proxyPort = serverMap["ProxyPort"].toUInt();
1050  server.proxyUser = serverMap["ProxyUser"].toString();
1051  server.proxyPass = serverMap["ProxyPass"].toString();
1052  return in;
1053 }
1054 
1055 
1056 bool Network::Server::operator==(const Server &other) const
1057 {
1058  if (host != other.host) return false;
1059  if (port != other.port) return false;
1060  if (password != other.password) return false;
1061  if (useSsl != other.useSsl) return false;
1062  if (sslVersion != other.sslVersion) return false;
1063  if (useProxy != other.useProxy) return false;
1064  if (proxyType != other.proxyType) return false;
1065  if (proxyHost != other.proxyHost) return false;
1066  if (proxyPort != other.proxyPort) return false;
1067  if (proxyUser != other.proxyUser) return false;
1068  if (proxyPass != other.proxyPass) return false;
1069  return true;
1070 }
1071 
1072 
1073 bool Network::Server::operator!=(const Server &other) const
1074 {
1075  return !(*this == other);
1076 }
1077 
1078 
1079 QDebug operator<<(QDebug dbg, const Network::Server &server)
1080 {
1081  dbg.nospace() << "Server(host = " << server.host << ":" << server.port << ", useSsl = " << server.useSsl << ")";
1082  return dbg.space();
1083 }