soc.2009.transport: fcf47c38: Support for more resources (more clients...
hanzz at soc.pidgin.im
hanzz at soc.pidgin.im
Tue Jun 30 02:50:41 EDT 2009
-----------------------------------------------------------------
Revision: fcf47c38bdb9ead72d80bebb8d437fcff97d1fd6
Ancestor: 4e09b6757ced5bf78b757d78eac947ad72268701
Author: hanzz at soc.pidgin.im
Date: 2009-06-30T06:45:23
Branch: im.pidgin.soc.2009.transport
URL: http://d.pidgin.im/viewmtn/revision/info/fcf47c38bdb9ead72d80bebb8d437fcff97d1fd6
Modified files:
caps.cpp main.cpp user.cpp user.h
ChangeLog:
Support for more resources (more clients connected to one PurpleAccount from the same JID)
-------------- next part --------------
============================================================
--- caps.cpp c04a1bc5d73e0f91b21d5604d2a6ecd6f5831952
+++ caps.cpp 0107eb249451a3048b26f8c3d796099b433d4654
@@ -84,13 +84,15 @@ void GlooxDiscoHandler::handleDiscoInfo(
std::cout << "no user?! wtf...";
}
else{
- std::cout << "1" << "\n";
- if (user->capsVersion().empty()){
- std::cout << "2" << "\n";
- user->setCapsVersion(versions[context]);
- if (user->readyForConnect()) {
- std::cout << "3" << "\n";
- user->connect();
+ if (user->hasResource(jid.resource())) {
+ std::cout << "1" << "\n";
+ if (user->getResource(jid.resource()).capsVersion.empty()){
+ std::cout << "2" << "\n";
+ user->setResource(jid.resource(), -256, versions[context]);
+ if (user->readyForConnect()) {
+ std::cout << "3" << "\n";
+ user->connect();
+ }
}
}
}
============================================================
--- main.cpp f5b5e5764f40765b8feef2deb05074448df99975
+++ main.cpp 7c68f1161604e0f9abb3ae475d383a030392fb3c
@@ -1229,10 +1229,10 @@ void GlooxMessageHandler::handlePresence
}
Log().Get(stanza.from().full()) << "Creating new User instance";
- user = new User(this, stanza.from().bare(), res.uin, res.password);
+ user = new User(this, stanza.from(), res.uin, res.password);
if (c!=NULL)
if(hasCaps(c->findAttribute("ver")))
- user->setCapsVersion(c->findAttribute("ver"));
+ user->setResource(stanza.from().resource(), stanza.priority(), c->findAttribute("ver"));
// if (!isVip)
// user->features=features0;
// else
============================================================
--- user.cpp 1bc78f76914b829a10162d3ebe1dee37bef950a1
+++ user.cpp a0fdf613b7246e97fdfe441aecc25a6fd42f7610
@@ -48,9 +48,12 @@ static void sendXhtmlTag(Tag *tag, Tag *
GlooxMessageHandler::instance()->j->send(stanzaTag);
}
-User::User(GlooxMessageHandler *parent, const std::string &jid, const std::string &username, const std::string &password){
+User::User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password){
p = parent;
- m_jid = jid;
+ m_jid = jid.bare();
+ Resource r;
+ m_resources[jid.resource()] = r;
+ m_resource = jid.resource();
m_username = username;
m_password = password;
m_connected = false;
@@ -114,10 +117,13 @@ bool User::syncCallback() {
* Returns true if main JID for this User has feature `feature`,
* otherwise returns false.
*/
-bool User::hasFeature(int feature){
- if (m_capsVersion.empty())
+bool User::hasFeature(int feature, std::string resource){
+ if (resource.empty())
+ resource = m_resource;
+ std::string caps = m_resources[resource].capsVersion;
+ if (caps.empty())
return false;
- if (p->capsCache[m_capsVersion]&feature)
+ if (p->capsCache[caps]&feature)
return true;
return false;
}
@@ -167,7 +173,7 @@ bool User::isOpenedConversation(const st
* Returns true if exists opened conversation with user with uin `name`.
*/
bool User::isOpenedConversation(const std::string &name){
- std::map<std::string,PurpleConversation *>::iterator iter = m_conversations.begin();
+ std::map<std::string, Conversation>::iterator iter = m_conversations.begin();
iter = m_conversations.find(name);
if(iter != m_conversations.end())
return true;
@@ -514,7 +520,7 @@ void User::purpleMessageReceived(PurpleA
if (conv==NULL){
// make conversation if it doesn't exist
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,account,name);
- m_conversations[(std::string)name]=conv;
+ m_conversations[(std::string)name].conv = conv;
}
}
@@ -525,7 +531,7 @@ void User::purpleConversationWriteChat(P
std::string name(who);
MUCHandler *muc = (MUCHandler*) g_hash_table_lookup(m_mucs, purple_conversation_get_name(conv));
if (!isOpenedConversation(name)) {
- m_conversations[name] = conv;
+ m_conversations[name].conv = conv;
if (muc)
muc->setConversation(conv);
}
@@ -554,7 +560,7 @@ void User::purpleConversationWriteIM(Pur
std::for_each( name.begin(), name.end(), replaceBadJidCharacters() );
// new message from legacy network has been received
if (!isOpenedConversation(name)) {
- m_conversations[name] = conv;
+ m_conversations[name].conv = conv;
}
Log().Get(m_jid) << "purpleConversationWriteIM:" << name << msg;
@@ -564,7 +570,12 @@ void User::purpleConversationWriteIM(Pur
char *strip = purple_markup_strip_html(newline);
std::string message(strip);
- Message s(Message::Chat, m_jid, message);
+ std::string to;
+ if (m_conversations[name].resource.empty())
+ to = m_jid;
+ else
+ to = m_jid + "/" + m_conversations[name].resource;
+ Message s(Message::Chat, to, message);
std::string from;
from.append(name);
from.append("@");
@@ -623,7 +634,7 @@ void User::purpleChatAddUsers(PurpleConv
if (!muc)
return;
if (!isOpenedConversation(name)) {
- m_conversations[name] = conv;
+ m_conversations[name].conv = conv;
muc->setConversation(conv);
}
muc->addUsers(cbuddies);
@@ -745,10 +756,12 @@ void User::receivedMessage(const Message
// open new conversation or get the opened one
if (!isOpenedConversation(username)){
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,m_account,username.c_str());
- m_conversations[username]=conv;
+ m_conversations[username].conv = conv;
+ m_conversations[username].resource = msg.from().resource();
}
else{
- conv = m_conversations[username];
+ conv = m_conversations[username].conv;
+ m_conversations[username].resource = msg.from().resource();
}
std::string body = msg.body();
@@ -837,8 +850,7 @@ void User::connect(){
if (m_account) {
Log().Get(m_jid) << "connect() has been called before";
return;
- }
- Log().Get(m_jid) << "Connecting with caps: " << m_capsVersion;
+ };
if (purple_accounts_find(m_username.c_str(), this->p->protocol()->protocol().c_str()) != NULL){
Log().Get(m_jid) << "this account already exists";
m_account = purple_accounts_find(m_username.c_str(), this->p->protocol()->protocol().c_str());
@@ -1075,13 +1087,11 @@ void User::receivedPresence(const Presen
}
}
+ Tag *stanzaTag = stanza.tag();
+ if (!stanzaTag)
+ return;
if (m_lang == NULL) {
- Tag *tag = stanza.tag();
- if (!tag)
- return;
- std::string lang = tag->findAttribute("xml:lang");
- Log().Get("LANG") << tag->xml();
- delete tag;
+ std::string lang = stanzaTag->findAttribute("xml:lang");
if (lang == "")
lang = "en";
setLang(lang.c_str());
@@ -1093,11 +1103,16 @@ void User::receivedPresence(const Presen
if(stanza.to().username() == ""){
if(stanza.presence() == Presence::Unavailable) {
// disconnect from legacy network if we are connected
- std::map<std::string,int> ::iterator iter = m_resources.begin();
+ std::map<std::string,Resource> ::iterator iter = m_resources.begin();
if ((m_connected==false && int(time(NULL))>int(m_connectionStart)+10) || m_connected==true){
iter = m_resources.find(stanza.from().resource());
if(iter != m_resources.end()){
m_resources.erase(stanza.from().resource());
+ for(std::map<std::string, Conversation>::iterator u = m_conversations.begin(); u != m_conversations.end() ; u++){
+ if ((*u).second.resource == stanza.from().resource()){
+ m_conversations[(*u).first].resource = "";
+ }
+ }
}
}
if (m_connected){
@@ -1123,20 +1138,29 @@ void User::receivedPresence(const Presen
}
}
} else {
- m_resource=stanza.from().resource();
- std::map<std::string,int> ::iterator iter = m_resources.begin();
- iter = m_resources.find(m_resource);
+ std::string resource=stanza.from().resource();
+ std::map<std::string,Resource> ::iterator iter = m_resources.begin();
+ iter = m_resources.find(resource);
if(iter == m_resources.end()){
- m_resources[m_resource]=stanza.priority();
+ m_resources[resource].priority = stanza.priority();
+ Tag *c = stanzaTag->findChildWithAttrib("xmlns","http://jabber.org/protocol/caps");
+ // presence has caps
+ if (c!=NULL){
+ if (p->hasCaps(c->findAttribute("ver"))){
+ m_resources[resource].capsVersion = c->findAttribute("ver");
+ }
+ }
+ if (m_resources[resource].priority > m_resources[m_resource].priority)
+ m_resource = resource;
}
Log().Get(m_jid) << "resource: " << m_resource;
if (!m_connected){
// we are not connected to legacy network, so we should do it when disco#info arrive :)
- Log().Get(m_jid) << "connecting: capsVersion=" << m_capsVersion;
+ Log().Get(m_jid) << "connecting: resource=" << m_resource;
if (m_readyForConnect==false){
m_readyForConnect=true;
- if (m_capsVersion.empty()){
+ if (m_resources[m_resource].capsVersion.empty()){
// caps not arrived yet, so we can't connect just now and we have to wait for caps
}
else{
@@ -1193,7 +1217,6 @@ void User::receivedPresence(const Presen
}
}
-
// send presence about tranport status to user
if(m_connected || m_readyForConnect) {
Presence tag(stanza.presence(), m_jid, stanza.status());
@@ -1208,6 +1231,7 @@ void User::receivedPresence(const Presen
p->j->send( tag );
}
}
+ delete stanzaTag;
}
}
============================================================
--- user.h 778fae39a0d134a39feac04c54b723826b10d9f6
+++ user.h f503f466694a21d92372913b62b677da498fca60
@@ -63,9 +63,19 @@ struct subscribeContact {
std::string group;
};
+struct Resource {
+ int priority;
+ std::string capsVersion;
+};
+
+struct Conversation {
+ PurpleConversation *conv;
+ std::string resource;
+};
+
class User {
public:
- User(GlooxMessageHandler *parent, const std::string &jid, const std::string &username, const std::string &password);
+ User(GlooxMessageHandler *parent, JID jid, const std::string &username, const std::string &password);
~User();
void connect();
@@ -77,7 +87,7 @@ class User {
bool syncCallback();
bool isInRoster(const std::string &name,const std::string &subscription);
bool isOpenedConversation(const std::string &name);
- bool hasFeature(int feature);
+ bool hasFeature(int feature, std::string resource = "");
// XMPP stuff
Tag *generatePresenceStanza(PurpleBuddy *buddy);
@@ -118,10 +128,6 @@ class User {
PurpleValue *getSetting(const char *key);
void updateSetting(const std::string &key, PurpleValue *value);
- // Entity Capabilities
- std::string & capsVersion() { return m_capsVersion; }
- void setCapsVersion(const std::string &capsVersion) { m_capsVersion = capsVersion; }
-
// Authorization requests
bool hasAuthRequest(const std::string &name);
void removeAuthRequest(const std::string &name);
@@ -132,8 +138,15 @@ class User {
// connection start
time_t connectionStart() { return m_connectionStart; }
+ void setResource(const std::string resource, int priority = -256, const std::string caps = "") {
+ if (priority != -256) m_resources[resource].priority = priority;
+ if (!caps.empty()) m_resources[resource].capsVersion = caps;
+ }
+ bool hasResource(const std::string r) {return m_resources.find(r) == m_resources.end(); }
+ Resource & getResource(const std::string r) { return m_resources[r];}
+
PurpleAccount *account() { return m_account; }
- std::map<std::string,int> & resources() { return m_resources; }
+ std::map<std::string,Resource> & resources() { return m_resources; }
int reconnectCount() { return m_reconnectCount; }
bool isVIP() { return m_vip; }
bool readyForConnect() { return m_readyForConnect; }
@@ -163,14 +176,13 @@ class User {
std::string m_username; // legacy network user name
std::string m_jid; // Jabber ID of this user
std::string m_resource; // active resource
- std::string m_capsVersion; // caps version of client which connected as first (TODO: this should be changed with active resource)
const char *m_lang; // xml:lang
time_t m_connectionStart; // connection start timestamp
GHashTable *m_mucs; // MUCs
std::map<std::string,RosterRow> m_roster; // jabber roster of this user
- std::map<std::string,int> m_resources; // list of all resources which are connected to the transport
+ std::map<std::string,Resource> m_resources; // list of all resources which are connected to the transport
std::map<std::string,authRequest> m_authRequests; // list of authorization requests (holds callbacks and user data)
- std::map<std::string,PurpleConversation *> m_conversations; // list of opened conversations
+ std::map<std::string,Conversation> m_conversations; // list of opened conversations
std::map<std::string,PurpleBuddy *> m_subscribeCache; // cache for contacts for roster X
GHashTable *m_settings; // user settings
};
More information about the Commits
mailing list