gm-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gm-devel] New ProtocolManager code and Contact code, please review


From: Jesse Lovelace
Subject: [Gm-devel] New ProtocolManager code and Contact code, please review
Date: Mon, 01 Jul 2002 18:07:57 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020513

Hi,

Attached is my work for today on the ProtocolManager class and Contact class, please review it because it does create a new idea in the style that we use. The big change is the support for mutliple protocols per contact and the ability to dynamically send a message using any available network.

jesse

p.s. - if there are no objections i would like to start merging this tomorrow, 1100 EST (GMT -5)

// -*- C++ -*-
/*
    $Id: contact.h,v 1.6 2002/06/30 21:45:48 mentat Exp $

    GNU Messenger - The secure instant messenger
    Copyright (C) 1999-2002  Henrik Abelsson <address@hidden>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef KIT_CONTACT_H
#define KIT_CONTACT_H

#include <string>
#include "cryptography.h"
#include "xml.h"
#include "boost/smart_ptr.hpp"
#include "boost/weak_ptr.hpp"

using namespace std;
using namespace boost;

/**
  All contacts (buddies) in the various protocols are represented by this

 Each contact has a status associated with it, and the client should display the
 user differently depending on the status here.
 \begin{itemize}
 \item Contact::Offline - User is offline
 \item Contact::Online - User is connected and available
 \item Contact::Away - User is connected but away
 \item Contact::Dnd - User is connected but doesnt want to be disturbed
 \item Contact::Na - User is connected but is not available
 \item Contact::Ffc - User is connected and free for chat
 \item Contact::Custom - A custom status. retrieve info()["customstatus"] to 
find out more.
 \end{itemize}
 */

class Contact
{
 public:

        Contact();
        Contact(const Contact& cont);
        Contact(XMLNode &config);

        ~Contact() {};

        // Contact status.
        //Custom is a string set and retrieved by info()["customstatus"]
        enum status { Offline, Online, Away, Occupied, Dnd, Na, Ffc, Custom };

        
        /* ----------------- mutators --------------- */
        /// Add a list of protocols and usernames.
        void    setProtocols(const map<string, string>& p);
        
        /// sets the current protocol that this contact is using
        void    setActiveProtocol(const string& proto);
        
        /// Add a protocol to the contact
        void    setProtocol(const string &p);
        
        /// sets the value "serverid"
        void    setServerId(const string &n) { m_user["serverid"]=n;}
        
        /// sets the "real name" of the contact: TODO make compatible with 
AuthLoad
        void    setNick(const string &n)     { m_user["nick"]=n;}
        
        /// sets the contact status, do not use, instead call with protocol 
identifier
        void    setStatus(const int status)  { m_status=status;}
        
        /// sets the status of the contact on a give network
        void    setStatus(const int status, const string& protocol);

        /* -------------- getors --------------------*/
        /// returns default protocol
        string protocol() const;
        
        /// returns active protocol if one exists
        string activeProtocol() const { if (m_status == Online) return 
m_activeProtocol; else return ""; }
        
        /// returns the server id for the contact, depreciated.
        string serverId() const { return m_user["serverid"];}
        
        /// returns the contacts "real name"
        string nick() const     { if (m_user.property("nick")=="") return 
m_user["serverid"]; return m_user["nick"]; }
        
        /// returns the status of the default protocol, depreciated     
        int    status() const   { return m_status; }
        
        /// returns the status of the user on the given protocol
        int        status(const string& proto) const;
        
        /// returns true if contact is available on any network
        bool available() const;
        
        /// returns true if there is an active session and if that session is 
encrypted
        bool isEncrypted() const { if ((m_status == Online) && (m_crypto.get() 
!= NULL)) return true; return false; }
                
        /// returns wether or not the client is GM
        bool isGM() const { return m_gm; }

        /* ---------------------- misc functions ---------------------------*/
        /// Get xml node (for extending)
        XMLNode &info()  { return m_user;}
        void operator=(const Contact &other);
        
        friend bool operator <(const Contact& c1, const Contact& c2);

private:

        /// a 'weak' pointer to the contact's encryption context
    weak_ptr<gmCrypto> m_crypto;
        
        /// the XML tree containing the current contact's information
        /// from authload
    mutable XMLNode m_user;
        
        /// the status of the contact, not really used
    int m_status;
        
        /// the protocol currently used for a session
        string m_activeProtocol;
        
        bool m_gm;
};

/// Comparation operators
bool operator==(Contact lhs,Contact rhs);

bool operator!=(Contact lhs,Contact rhs);

#endif
// -*- C++ -*-
/*
    $Id: manager.h,v 1.5 2002/06/28 18:37:33 mentat Exp $

    GNU Messenger - The secure instant messenger

        Copyright (C) 1999-2002  Henrik Abelsson <address@hidden>
        parts Copyright (C) 2002 Jesse Lovelace <address@hidden>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef KIM_PROTOCOL_MANAGER_H
#define KIM_PROTOCOL_MANAGER_H

#include <string>
#include <vector>

#include "authload.h"
#include "protocol.h"
#include "boost/weak_ptr.hpp"

using namespace std;
using namespace boost;

/**
   ProtocolManager - Manages a number of different protocols

   In order to make it easier to write clients this class in the only one that 
is needed to
   interace with multiple protocols. You create a stand alone protocol as 
usual, then add it
   to the manager which will then take care of routing requests and callbacks 
to the right
   protocol.

   Just change the protocol string depending on which protocol you're 
interested in

 */
class Network;
class NetworkServer;

class ProtocolManager
{
public:
    ProtocolManager(weak_ptr<AuthLoad> auth) { m_auth = auth; }
        ProtocolManager() {}
    virtual ~ProtocolManager();

          /**
     Add a new protocol
        (don't call directly.. will be called internally by the protocols)
           */
        void addProtocol(Protocol *);

        void removeProtocol(const string& proto);

        int getState(const string &proto);
        const vector<string> protocols();
        Protocol *protocol(const string &proto);

        const string screenName(const string &proto);

        /* call periodically */
        void update(const string &proto);
        void updateAll();
                
        /// returns wether or not the session for that contact is a GM session
        /// and would support cryptography
        bool IsGM(const Contact& c);
                
        /// if the session is encrypted, will initiate a new Key Exchange, 
never throws
        void ForceKeyX(const Contact& c);
        
        /// if the session is encrypted, will change the local cipher type, 
never throws
        /// keysize and blocksize are in bytes
        void ChangeCipher(const Contact& c, int cipherType, int keysize = -1, 
int blocksize = -1);

  /* actions */

  /**
     This should create a new system dependant Network pointer and return it. 
It's called when a protocol
     needs a new socket.

     Also should add the Network to any event monitoring it may do.
   */
        virtual Network *createNet(Protocol *n)=0;
        virtual NetworkServer * createServer(Protocol *proto)=0;

         /** Should ONLY remove the socket from event handling! DON'T delete it!
        */

    virtual void removeNet(const Network *n)=0;
        /**
     Returns all Network* associated with a given protocol.
        */
        list<Network*> getNets(const string &proto);

        /**
     Returns all Network*s currently in use.
        */
        list<Network*> getNetsAll();

        void login(const string &proto);

        void setAway(const string& proto, const string& msg);
        void setAllAway(const string& msg);
        void setInfo(const string& proto, const string& info);
        void setAllInfo(const string& info);

        void logout(const string &proto);
        void sendMessage(const string &proto,const Contact &recipient, const 
string &message);
        void sendMessage(const string& proto, const Contact & recipient, const 
vbuf& data);
        
        void sendMessage(const Contact& c, const string& message);
        void sendMessage(const Contact& c, const vbuf& data);
        void addBuddy(const string &proto,const Contact &c);

        void delBuddy(const string &proto,const Contact &c);
        void getPubkey(const string &proto);
        void newUser(const string &proto);
        void customRequest(const string &proto,const XMLNode &n);
        void wipeBuddies(const string& proto);
        
        /**
         The login process has succeded and the client is connected
         */
        virtual void c_loggedIn(const string &proto);

         /**
     The client has been logged out
         */
        virtual void c_loggedOut(const string &proto);

         /**
     A message has come! Someone is interested in talking to our user
         */
        virtual void c_recvdMessage(const string &proto,const Contact &c, const 
string &message) = 0;
        virtual void c_recvdMessageAnony(const string& protocol, const Contact& 
c, const string& message) = 0;
         /**
         The status for a contact has changed (May have gone offline, or gone 
away)
         @see Contact
         */
        virtual void c_statusChange(const string &proto,const Contact &c);

         /**
     An error has occured.
     @param errno The error code
     @param error Human readable error description
         */
        virtual void c_error(const string &proto,int err_no,const string 
&error);

         /**
     Our own state (as opposed to c_statusChange for buddy states) has changed.
         */
        virtual void c_stateChange(const string &proto,int state);
        /**
         We've gotten the servers public key (only kitprotocol)
         */
        virtual void c_gotPubkey(const Contact& c,const string &key);

        /**
    We've gotten a buddy of the server
         */
        virtual void c_gotBuddy(const string &proto,const Contact &c);

        virtual void c_custom(const string &proto,const XMLNode &n);

        //typedef map<string,Contact > buddy_t;
private:

        void sendEncryptedMessage(const string& proto, const Contact& c, const 
string& mess) {}
        void sendEncryptedMessage(const string& proto, const Contact& c, const 
vbuf& data) {}
        

        typedef map<string,Protocol *> provider_t;
        provider_t m_provider;
        weak_ptr<AuthLoad> m_auth;
        map<Contact, shared_ptr<gmCrypto> > m_activeContacts;
        /// this would be were we had the SSH2 manager
        //map<string, > m_activeCrypto;
};
#endif
// -*- C++ -*-
/*
    $Id: contact.cpp,v 1.4 2002/06/30 21:45:48 mentat Exp $

    GNU Messenger - The secure instant messenger
    Copyright (C) 1999-2002  Henrik Abelsson <address@hidden>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#pragma warning(disable:4786)
#include <xmlnode.h>
#include <contact.h>

#include "contact.h"

Contact::Contact(const Contact& c)
{
        // this smart pointer is weak
        m_crypto = c.m_crypto;
        m_user=c.m_user;
        m_status=c.m_status;
}

Contact::Contact():
        m_user(),m_status(Contact::Offline), m_gm(false)
{
        m_user.setName("contact");
}
Contact::Contact(XMLNode &config):
       m_user(config),m_status(Contact::Offline)
{
}
int Contact::status(const string& proto)
{
        if (m_user.child("protocols").hasChild(proto))
                return 
m_user.child("protocols").child(proto).intProperty("status");
        return Contact::Offline;
        
}
void Contact::operator=(const Contact &other)
{
        // this smart pointer is weak
        m_crypto = other.m_crypto;
        m_user=other.m_user;
        m_status=other.m_status;
}

bool Contact::available()
{
        vector<XMLNode> nets = m_user.child("protocols").children();
        for (unsigned int i = 0; i < nets.size(); i++)
                if (nets[i].intProperty("status") != Offline)
                        return true;
        return false;
}

void Contact::setProtocol(const string& proto)
{
    if (!m_user.child("protocols").hasChild(proto))
        m_user.child("protocols").addChild(proto);
}

void Contact::setProtocols(const map<string, string> & p)
{
    for (map<string,string>::const_iterator it = p.begin(); it != p.end(); it++)
        if (!m_user.child("protocols").hasChild(it->first))
                {
            m_user.child("protocols").addChild(it->first).setProperty("login", 
it->second).setProperty("status", Contact::Offline);
                }
}

string Contact::protocol() const
{
    if (m_user.child("protocols").const_children().size() == 0)
        return "";
    else
        return m_user.child("protocols").const_children()[0];
}

void Contact::setStatus(const int status, const string& protocol)
{
        if (m_user.child("protocols").hasChild(protocol))
                m_user.child("protocols").child(protocol).setProperty("status", 
status);
}

void Contact::setActiveProtocol(const string& proto)
{
        if (m_user.child("protocols").hasChild(proto))
                m_activeProtocol = proto;
}

bool operator < (const Contact& c1, const Contact& c2)
{
        return (c1.nick() < c2.nick());
}

bool operator==(Contact lhs,Contact rhs)
{
  return lhs.protocol() == rhs.protocol() && lhs.serverId() == rhs.serverId();
};

bool operator!=(Contact lhs,Contact rhs)
{
  return lhs.protocol() != rhs.protocol() || lhs.serverId() != rhs.serverId();
};

/*
    $Id: manager.cpp,v 1.11 2002/06/28 18:34:50 mentat Exp $

    GNU Messenger - The secure instant messenger
    Copyright (C) 1999-2001  Henrik Abelsson <address@hidden>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#pragma warning(disable:4786)

#include <log.h>

#include "manager.h"
#include "contact.h"
#include <iostream>

using namespace std;

ProtocolManager::~ProtocolManager()
{
}

void ProtocolManager::removeProtocol(const string &proto)
{
        logout(proto);
        Protocol * myProto = protocol(proto);
        if (!myProto)
                return;
        m_provider.erase(proto);
        delete myProto;
}

void ProtocolManager::addProtocol(Protocol *proto)
{
        if (proto)
        {
                debug() << "adding " << proto->protocol() << " to protocol 
manager" << endl;
                m_provider[proto->protocol()]=proto;
        }
}

int ProtocolManager::getState(const string &proto)
{
  if (m_provider.count(proto))
    return m_provider[proto]->getState(); // needs to return
  return Protocol::S_offline; 
}

const vector<string> ProtocolManager::protocols()
{
        vector<string> tmp;
        for  (provider_t::iterator i=m_provider.begin();i!=m_provider.end();i++)
                tmp.push_back(i->first);
        return tmp;
}

Protocol *ProtocolManager::protocol(const string &proto)
{
        if (m_provider.count(proto))
                return m_provider[proto];
        else return NULL;
}

const string ProtocolManager::screenName(const string &proto)
{
        if (m_provider.count(proto))
                return m_provider[proto]->screenName();
        return "";
}

void ProtocolManager::update(const string &proto)
{
        if (m_provider.count(proto))
                m_provider[proto]->update();
}

void ProtocolManager::updateAll()
{
        for  (provider_t::iterator i=m_provider.begin();i!=m_provider.end();i++)
                i->second->update();
}

void ProtocolManager::setAway(const string& proto, const string& msg)
{
        if (m_provider.count(proto))
                m_provider[proto]->setAway(msg);
}

void ProtocolManager::setAllAway(const string& msg)
{
        for (provider_t::iterator i=m_provider.begin();i!=m_provider.end();i++)
                i->second->setAway(msg);
}

void ProtocolManager::setInfo(const string& proto, const string& info)
{
        if (m_provider.count(proto))
                m_provider[proto]->setInfo(info);
}

void ProtocolManager::setAllInfo(const string& info)
{
        for (provider_t::iterator i=m_provider.begin();i!=m_provider.end();i++)
                i->second->setInfo(info);
}

void ProtocolManager::login(const string &proto)
{
        if (m_provider.count(proto))
                m_provider[proto]->login();
}

void ProtocolManager::logout(const string &proto)
{
        if (proto != "" && m_provider.count(proto))
                m_provider[proto]->logout();
}

void ProtocolManager::sendMessage(const string &proto,const Contact &recipient, 
const string &message)
{
        if (m_provider.count(proto))
                m_provider[proto]->sendMessage(recipient,message);
}
void ProtocolManager::sendMessage(const string &proto,const Contact &recipient, 
const vbuf& data)
{
        if (m_provider.count(proto))
                m_provider[proto]->sendMessage(recipient, data);
}

void ProtocolManager::sendMessage(const Contact& c, const string& message)
{       
        map<Contact, shared_ptr<gmCrypto> >::iterator it = 
m_activeContacts.find(c);
        if (it != m_activeContacts.end()) // is this contact real?
                if ((it->first).available()) // are they available?
                        if ((it->first).isEncrypted()) // are they encrypted?
                                
sendEncryptedMessage((it->first).activeProtocol(), c, message);
                        else
                                sendMessage((it->first).activeProtocol(), c, 
message);
}

void ProtocolManager::sendMessage(const Contact& c, const vbuf& data)
{
        
}

void ProtocolManager::addBuddy(const string &proto,const Contact &c)
{
        if (m_provider.count(proto))
                m_provider[proto]->addBuddy(c);
}

void ProtocolManager::delBuddy(const string &proto,const Contact &c)
{
        if (m_provider.count(proto))
                m_provider[proto]->delBuddy(c);
}

void ProtocolManager::getPubkey(const string &proto)
{
        if (m_provider.count(proto))
                m_provider[proto]->getPubkey();
}

void ProtocolManager::newUser(const string &proto)
{
        if (m_provider.count(proto))
                m_provider[proto]->newUser();
}

void ProtocolManager::wipeBuddies(const string& proto)
{
        if (m_provider.count(proto))
                m_provider[proto]->clearBuddies();
}

void ProtocolManager::customRequest(const string &proto,const XMLNode &n)
{
        if (m_provider.count(proto))
                m_provider[proto]->customRequest(n);
}

void ProtocolManager::c_loggedIn(const string &proto)
{

}

void ProtocolManager::c_loggedOut(const string &proto)
{

}

void ProtocolManager::c_recvdMessage(const string &proto,const Contact &c, 
const string &message)
{

}

void ProtocolManager::c_recvdMessageAnony(const string& protocol, const 
Contact& c, const string& message)
{

}

void ProtocolManager::c_statusChange(const string &proto,const Contact &c)
{
        // here we should update the status of a contact
        map<Contact, shared_ptr<gmCrypto> >::iterator it = 
m_activeContacts.find(c);
        if (it != m_activeContacts.end())
        {
                
                (it->fi
        
        
}

void ProtocolManager::c_error(const string &proto,int err_no,const string 
&error)
{

}

void ProtocolManager::c_stateChange(const string &proto,int state)
{

}

void ProtocolManager::c_gotPubkey(const Contact &c,const string &key)
{
}

void ProtocolManager::c_custom(const string &proto,const XMLNode &n)
{
}

void ProtocolManager::c_gotBuddy(const string &proto,const Contact &c)
{
  //if (m_provider.count(c.protocol()))
    //m_provider[c.protocol()]->addBuddy(c);
  //c_statusChange(c.protocol(),c);
}

list<Network*> ProtocolManager::getNets(const string &proto)
{
  if (m_provider.count(proto))
    return m_provider[proto]->getNetworks();

  // temp fix for "not all paths return a value
  list<Network *> dummy;
  return dummy;
}

list<Network*> ProtocolManager::getNetsAll()
{
  list<Network *> tmp;
  for  (provider_t::const_iterator i=m_provider.begin();i!=m_provider.end();i++)
  {
    list<Network *> nets=i->second->getNetworks();
    for (list<Network*>::const_iterator j=nets.begin();j!=nets.end();j++)
    {
      tmp.push_back(*j);
    }
  }
  return tmp;
}

        /// returns wether or not the session for that contact is a GM session
        /// and would support cryptography
bool ProtocolManager::IsGM(const Contact& c)
{
        map<Contact, shared_ptr<gmCrypto> >::iterator it = 
m_activeContacts.find(c);
        if (it != m_activeContacts.end())
                return (it->first).isGM();
        else
                return false;
}
                
        /// if the session is encrypted, will initiate a new Key Exchange, 
never throws
void ProtocolManager::ForceKeyX(const Contact& c)
{
        // this must interface ssh2 code
}
        
        /// if the session is encrypted, will change the local cipher type, 
never throws
        /// keysize and blocksize are in bytes
void ProtocolManager::ChangeCipher(const Contact& c, int cipherType, int 
keysize = -1, int blocksize = -1)
{
        // this must interface ssh2 code
}
/*
    -----
    $Log: manager.cpp,v $
    Revision 1.11  2002/06/28 18:34:50  mentat
    SF CVS merge.

    Revision 1.2  2002/06/26 17:40:12  thementat
    Added the Open-Source ssh2 lib from Bitvise.

    Revision 1.1.1.1  2002/06/06 17:21:48  thementat
    Checkin of new sources BETA 2

    Revision 1.9  2001/12/16 19:46:50  mentat
    Updates to TOC protocol and authload class.

    Revision 1.8  2001/12/13 17:24:54  mentat
    Manager now returns Protocol::s_Offline if the protocol isnt loaded.

    Revision 1.7  2001/12/06 04:46:40  mentat
    Added setAway() and setAllAway(...) to manager class and to toc protocol, 
also added changes to toc so that will log in with wx client.

    Revision 1.6  2001/11/24 00:32:44  henrik
    Addcontact dialog restructuring, chat improvements, login/logout 
improvements.

    Revision 1.5  2001/10/05 14:11:00  abelsson
    Added debug() macro for debug output.

    Revision 1.4  2001/10/02 22:51:57  estyrke
    Added some more boilerplates...

*/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]