Handshaker.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
00018
00019
00020
00021
00022
00023 #include "Qt.h"
00024 #include "Handshaker.h"
00025 #include "HandshakeSession.h"
00026 #include "RequestHeader.h"
00027 #include "ResponseHeader.h"
00028 #include "SlotAllocator.h"
00029 #include "Imports.cpp"
00030
00031 using namespace Gnutella::Handshaking;
00032
00033 namespace Gnutella {
00034 namespace Handshaking {
00035
00036 class HandshakerPrivate
00037 {
00038 REFERENCE_OBJECT (HandshakerPrivate)
00039
00040 public:
00041 typedef QSet <HandshakeSession *> HandshakeSessions;
00042
00043 NodeInfo nodeInfo;
00044 LocalPeer *localPeer;
00045 NodeCache *nodeCache;
00046 SlotAllocator *slotAllocator;
00047 HandshakeSessions sessions;
00048
00049 HandshakerPrivate() : nodeInfo(), localPeer (0), nodeCache (0),
00050 slotAllocator (0), sessions()
00051 {}
00052 };
00053
00054 }
00055 }
00056
00057 Handshaker::Handshaker (LocalPeer *localPeer,
00058 NodeCache *nodeCache,
00059 SlotAllocator *slotAllocator)
00060 : p (new HandshakerPrivate)
00061 {
00062 p->localPeer = localPeer;
00063 p->nodeCache = nodeCache;
00064 p->slotAllocator = slotAllocator;
00065
00066
00067
00068 p->nodeInfo.address.setHostPort (localPeer->serverPort());
00069 p->nodeInfo.type = localPeer->nodeInfo().type;
00070 p->nodeInfo.identification = "Calitko/0.6.1";
00071
00072 p->nodeInfo.pongCaching = Version (0, 1);
00073 p->nodeInfo.ggep = Version (0, 5);
00074 p->nodeInfo.queryRouting = Version (0, 1);
00075 p->nodeInfo.ultrapeerQueryRouting = Version (0, 1);
00076 p->nodeInfo.dynamicQuerying = Version (0, 1);
00077
00078 p->nodeInfo.vendorMessage = Version (0, 1);
00079
00080 p->nodeInfo.byePacket = Version (0, 1);
00081 p->nodeInfo.degree = 32;
00082 p->nodeInfo.maxTtl = 3;
00083
00084 }
00085
00086 Handshaker::~Handshaker()
00087 {
00088 delete p;
00089 }
00090
00091 HandshakeSession * Handshaker::newSession (Connection *connection,
00092 const NodeAddress &nodeAddress)
00093 {
00094
00095 p->nodeInfo.address.setHostPort (p->localPeer->serverPort());
00096 p->nodeInfo.ultrapeerNeeded = p->slotAllocator->hasFreePeerSlots();
00097 p->nodeInfo.type = p->localPeer->nodeInfo().type;
00098
00099
00100 HandshakeSession *session = 0;
00101 session = new HandshakeSession (connection, nodeAddress,
00102 this, p->nodeCache);
00103 p->sessions.insert (session);
00104
00105 connect (session, SIGNAL (connectionEstablished (HandshakeSession *)),
00106 this, SLOT (connectionEstablished (HandshakeSession *)));
00107 connect (session, SIGNAL (receivedRequest (HandshakeSession *)),
00108 this, SLOT (receivedRequest (HandshakeSession *)));
00109 connect (session, SIGNAL (receivedResponse (HandshakeSession *)),
00110 this, SLOT (receivedResponse (HandshakeSession *)));
00111 connect (session, SIGNAL (handshakingCompleted (HandshakeSession *)),
00112 this, SLOT (handshakingCompleted (HandshakeSession *)));
00113 connect (session, SIGNAL (handshakingFailed (HandshakeSession *)),
00114 this, SLOT (handshakingFailed (HandshakeSession *)));
00115
00116 return session;
00117 }
00118
00119 void Handshaker::deleteSession (HandshakeSession *session)
00120 {
00121 Q_ASSERT (p->sessions.contains (session));
00122 p->sessions.remove (session);
00123 session->disconnect (this);
00124 session->deleteLater();
00125 }
00126
00127 void Handshaker::requestConnection (Connection *connection,
00128 const NodeAddress & nodeAddress)
00129 {
00130 qDebug() << "Handshaker::requestConnection()";
00131
00132 HandshakeSession *session = newSession (connection, nodeAddress);
00133 p->slotAllocator->allocateSlot (session);
00134
00135
00136
00137
00138
00139
00140 connection->connectToNode (nodeAddress);
00141
00142 qDebug() << "Handshaker::requestConnection() done";
00143 }
00144
00145 void Handshaker::acceptConnection (Connection *connection)
00146 {
00147 HandshakeSession *session = newSession (connection, NodeAddress::Null);
00148 p->slotAllocator->allocateSlot (session);
00149 session->waitRequest();
00150 }
00151
00152 void Handshaker::connectionEstablished (HandshakeSession *session)
00153 {
00154 Connection *connection = session->connection();
00155 emit handshakingStarted (connection);
00156 session->request (p->nodeInfo);
00157 }
00158
00159 void Handshaker::handshakingCompleted (HandshakeSession *session)
00160 {
00161 Connection *connection = session->connection();
00162 NodeInfo nodeInfo = session->otherNodeInfo();
00163 connection->disconnect (session);
00164 deleteSession (session);
00165 emit handshakingCompleted (connection, nodeInfo);
00166 }
00167
00168 void Handshaker::handshakingFailed (HandshakeSession *session)
00169 {
00170 qDebug() << "Handshaker::failedHandshaking" << session;
00171
00172 Connection *connection = session->connection();
00173 HandshakeError error = session->error();
00174 NodeInfo nodeInfo = session->otherNodeInfo();
00175 connection->disconnect (session);
00176 deleteSession (session);
00177 connection->deleteLater();
00178
00179 emit handshakingFailed (connection, error);
00180 }
00181
00182 bool Handshaker::hasRequiredFeatures (const NodeInfo &nodeInfo)
00183 {
00184
00185
00186 if (nodeInfo.type == TypeUnknown)
00187 return false;
00188 if (nodeInfo.type == TypeLeaf
00189 && nodeInfo.queryRouting.minorVersion() < 1)
00190 return false;
00191 if (nodeInfo.type == TypePeer
00192 && nodeInfo.ultrapeerQueryRouting.minorVersion() < 1)
00193 return false;
00194 return true;
00195 }
00196
00197 bool Handshaker::compatibleNodeTypes (const NodeInfo &otherNodeInfo)
00198 {
00200 if (p->nodeInfo.type == TypeLeaf) {
00201 return otherNodeInfo.type == TypeUltrapeer;
00202 }
00203 if (p->nodeInfo.type == TypeUltrapeer || p->nodeInfo.type == TypePeer) {
00204 if (otherNodeInfo.type == TypePeer)
00205 return otherNodeInfo.ultrapeerNeeded == true;
00206 else
00207 return true;
00208 }
00209 Q_ASSERT (false);
00210 return false;
00211 }
00212
00213 int Handshaker::getRejectReason (HandshakeSession *session)
00214 {
00215 NodeInfo otherNodeInfo = session->otherNodeInfo();
00216 if (!hasRequiredFeatures (otherNodeInfo))
00217 return RejectUnsupportedFeatures;
00218 if (!compatibleNodeTypes (otherNodeInfo)) {
00219 if (p->nodeInfo.type == TypeLeaf)
00220 return RejectImLeaf;
00221 else
00222 return RejectImUltrapeer;
00223 } else if (!p->slotAllocator->hasSlotFor (otherNodeInfo))
00224 return RejectNoSlots;
00225 else
00226 return NotRejecting;
00227 }
00228
00229 void Handshaker::receivedRequest (HandshakeSession *session)
00230 {
00231 p->nodeInfo.address.setHostAddress (session->myNodeInfo().address.hostAddress());
00232 RejectReason reason = static_cast <RejectReason> (getRejectReason (session));
00233 if (reason != NotRejecting)
00234 session->reject (reason, p->nodeInfo);
00235 else {
00236 session->respond (p->nodeInfo);
00237 }
00238 }
00239
00240 void Handshaker::receivedResponse (HandshakeSession *session)
00241 {
00242 p->nodeInfo.address.setHostAddress (session->myNodeInfo().address.hostAddress());
00243 RejectReason reason = static_cast <RejectReason> (getRejectReason (session));
00244 if (reason != NotRejecting)
00245 session->reject (reason, p->nodeInfo);
00246 else {
00247 session->acknowledge (p->nodeInfo);
00248 }
00249 }
00250
00251 void Handshaker::setVisibleIp (const QHostAddress &address)
00252 {
00253 p->localPeer->setServerIpAddress (address);
00254 }