[Top][All Lists]
[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...
*/
- [Gm-devel] New ProtocolManager code and Contact code, please review,
Jesse Lovelace <=