HandshakeSession.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #ifndef GNUTELLA__HANDSHAKING__HANDSHAKE_SESSION_H
00024 #define GNUTELLA__HANDSHAKING__HANDSHAKE_SESSION_H
00025 
00026 #include "Imports.h"
00027 
00028 namespace Gnutella {
00029 namespace Handshaking {
00030 
00031 class Handshaker;
00032 
00033 // \todo Put in the class HandshakeSession
00034 enum RejectReason
00035 {
00036     NotRejecting,
00037     RejectNoSlots,
00038     RejectUnsupportedFeatures,
00039     RejectImUltrapeer,
00040     RejectImLeaf
00041 };
00042 
00043 enum HandshakeError
00044 {
00045     NoError,
00046     ErrorCannotEstablishConnection,
00047     ErrorRemoteClosedConnection,
00048     ErrorRemoteNodeRejected,
00049     ErrorRejectedByRemoteNode,
00050     ErrorInvalidHeadersRead,
00051     ErrorWriteDevice,
00052     ErrorReadDevice,
00053     ErrorTimeout
00054 };
00055 
00057 
00060 class HandshakeSession : public QObject
00061 {
00062     Q_OBJECT
00063 
00064 public:
00065             HandshakeSession (Connection *, const NodeAddress &,
00066                               Handshaker *, NodeCache *);
00067             ~HandshakeSession();
00068 
00069     void    request (const NodeInfo &myNodeInfo);
00070     void    waitRequest();
00071     void    respond (const NodeInfo &myNodeInfo);
00072     void    waitResponse();
00073     void    acknowledge (const NodeInfo &myNodeInfo);
00074     void    waitAcknowledgement();
00075     void    reject (RejectReason, const NodeInfo &myNodeInfo);
00076 
00077     NodeInfo        otherNodeInfo() const;
00078     NodeInfo        myNodeInfo() const;
00079     Connection *    connection() const;
00080     HandshakeError  error() const;
00081 
00082 signals:
00083     void    connectionEstablished (HandshakeSession *);
00084     void    receivedRequest (HandshakeSession *);
00085     void    receivedResponse (HandshakeSession *);
00086     void    handshakingCompleted (HandshakeSession *);
00087     void    handshakingFailed (HandshakeSession *);
00088 
00089 private slots:
00090     void    connectionEstablished();
00091     void    connectionFailed();
00092     void    connectionClosed(); 
00093     void    handshakeRead();        
00094     void    handshakeWritten(); 
00095     void    readError();            
00096     void    writeError();           
00097     void    timeout ();             
00098 
00099 private:
00100 
00101     enum State
00102     {
00103         UnknownState,
00104         WaitingPhase1Handshake,
00105         SendingPhase1Handshake,
00106         WaitingPhase2Handshake,
00107         SendingPhase2Handshake,
00108         WaitingPhase3Handshake,
00109         SendingPhase3Handshake,
00110         RejectingConnection,
00111         HandshakingTimedOut,
00112         HandshakingFailed,
00113         HandshakingCompleted
00114     };
00115 
00116     void    completed();
00117     void    failed (HandshakeError);
00118     void    sendResponse (RejectReason, const NodeInfo &); // \todo Maybe rename the type of the argument?
00119     void    setHandshakeHeaders (Header &handshakeHeaders, const NodeInfo &myNodeInfo);
00120     void    getHandshakeHeaders (const Header &handshakeHeaders);
00121 
00122     struct Data
00123     {
00124         Handshaker      *handshaker;
00125         NodeCache       *nodeCache;
00126         HeaderReader    *reader;
00127         HeaderWriter    *writer;
00128         Connection      *connection;
00129         State           state;
00130         HandshakeError  error;
00131         QTimer          timer;
00132         NodeInfo        myNodeInfo;
00133         NodeInfo        otherNodeInfo;
00134 
00135         Data() : handshaker (0), nodeCache (0), reader (0), writer (0),
00136                  connection (0), state (UnknownState), error (NoError),
00137                  timer(), myNodeInfo(), otherNodeInfo()
00138         {}
00139 
00140     private:
00141         REFERENCE_OBJECT (Data)
00142     };
00143 
00144     Data d;
00145 };
00146 
00147 inline NodeInfo HandshakeSession::myNodeInfo() const
00148 { return d.myNodeInfo; }
00149 
00150 inline NodeInfo HandshakeSession::otherNodeInfo() const
00151 { return d.otherNodeInfo; }
00152 
00153 inline Connection * HandshakeSession::connection() const
00154 { return d.connection; }
00155 
00156 inline HandshakeError HandshakeSession::error() const
00157 { return d.error; }
00158 
00159 } // namespace Handshaking
00160 } // namespace Gnutella
00161 
00162 #endif // GNUTELLA__HANDSHAKING__HANDSHAKE_SESSION_H