/* * WAConnection.h * * Created on: 26/06/2012 * Author: Antonio */ #ifndef WACONNECTION_H_ #define WACONNECTION_H_ #include #include #include #include "WAException.h" #include "FMessage.h" #include "WALogin.h" #include "utilities.h" #include "BinTreeNodeReader.h" #include "BinTreeNodeWriter.h" #include "MediaUploader.h" #pragma warning(disable : 4290) class WALogin; class WASocketConnection; class KeyStream; class BinTreeNodeReader; class WAListener { public: virtual void onMessageForMe(const FMessage ¶mFMessage) throw (WAException) = 0; virtual void onMessageStatusUpdate(const FMessage ¶mFMessage) = 0; virtual void onMessageError(const FMessage &message, int paramInt) = 0; virtual void onPing(const std::string ¶mString) throw (WAException) = 0; virtual void onPingResponseReceived() = 0; virtual void onAvailable(const std::string ¶mString, bool paramBoolean, DWORD lastSeenTime = 0) = 0; virtual void onClientConfigReceived(const std::string ¶mString) = 0; virtual void onIsTyping(const std::string ¶mString, bool paramBoolean) = 0; virtual void onAccountChange(int paramInt, time_t paramLong) = 0; virtual void onPrivacyBlockListAdd(const std::string ¶mString) = 0; virtual void onPrivacyBlockListClear() = 0; virtual void onDirty(const std::map& paramHashtable) = 0; virtual void onDirtyResponse(int paramHashtable) = 0; virtual void onRelayRequest(const std::string ¶mString1, int paramInt, const std::string ¶mString2) = 0; virtual void onSendGetPicture(const std::string &jid, const std::vector& data, const std::string &id) = 0; virtual void onContactChanged(const std::string &jid, bool added) = 0; virtual void onPictureChanged(const std::string &jid, const std::string &id, bool set) = 0; virtual void onDeleteAccount(bool result) = 0; }; class WAGroupListener { public: virtual void onGroupAddUser(const std::string &gjid, const std::string &ujid, int ts) = 0; virtual void onGroupRemoveUser(const std::string &gjid, const std::string &ujid, int ts) = 0; virtual void onGroupNewSubject(const std::string &from, const std::string &author, const std::string &newSubject, int paramInt) = 0; virtual void onGroupMessage(const FMessage ¶mFMessage) = 0; virtual void onServerProperties(std::map* nameValueMap) = 0; virtual void onGroupCreated(const std::string &gjid, const std::string &nick) = 0; virtual void onGroupInfo(const std::string &jid, const std::string &owner, const std::string &subject, const std::string &subject_owner, int time_subject, int time_created) = 0; virtual void onSetSubject(const std::string ¶mString) = 0; virtual void onAddGroupParticipants(const std::string ¶mString, const std::vector ¶mVector, int paramHashtable) = 0; virtual void onRemoveGroupParticipants(const std::string ¶mString, const std::vector ¶mVector, int paramHashtable) = 0; virtual void onGetParticipants(const std::string &gjid, const std::vector &participants) = 0; virtual void onLeaveGroup(const std::string ¶mString) = 0; }; class GroupSetting { public: std::string jid; bool enabled; time_t muteExpiry; GroupSetting() { enabled = true; jid = ""; muteExpiry = 0; } }; class WAConnection { class IqResultHandler { protected: WAConnection* con; public: IqResultHandler(WAConnection* con) {this->con = con;} virtual void parse(ProtocolTreeNode* paramProtocolTreeNode, const std::string ¶mString) throw (WAException)=0; void error(ProtocolTreeNode* node, int code) { con->logData("WAConnection: error node %s: code = %d", node->getAttributeValue("id").c_str(), code); } void error(ProtocolTreeNode* node) throw (WAException) { std::vector nodes(node->getAllChildren("error")); for (size_t i = 0; i < nodes.size(); i++) { ProtocolTreeNode* errorNode = nodes[i]; if (errorNode != NULL) { const string &errorCodeString = errorNode->getAttributeValue("code"); if (!errorCodeString.empty()) { int errorCode = atoi(errorCodeString.c_str()); error(node, errorCode); } } } } virtual ~IqResultHandler() {} }; class IqResultPingHandler: public IqResultHandler { public: IqResultPingHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode*, const std::string&) throw (WAException) { if (this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onPingResponseReceived(); } void error(ProtocolTreeNode*) throw (WAException) { if (this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onPingResponseReceived(); } }; class IqResultGetGroupsHandler: public IqResultHandler { private: std::string type; public: IqResultGetGroupsHandler(WAConnection* con, const std::string &type ):IqResultHandler(con) {this->type = type;} virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { std::vector groups; this->con->readGroupList(node, groups); } }; class IqResultServerPropertiesHandler: public IqResultHandler { public: IqResultServerPropertiesHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { std::vector nodes(node->getAllChildren("prop")); std::map nameValueMap; for (size_t i = 0; i < nodes.size();i++) { ProtocolTreeNode* propNode = nodes[i]; const string &nameAttr = propNode->getAttributeValue("name"); const string &valueAttr = propNode->getAttributeValue("value"); nameValueMap[nameAttr] = valueAttr; } if (this->con->m_pGroupEventHandler != NULL) this->con->m_pGroupEventHandler->onServerProperties(&nameValueMap); } }; class IqResultPrivayListHandler: public IqResultHandler { public: IqResultPrivayListHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { ProtocolTreeNode* queryNode = node->getChild(0); ProtocolTreeNode::require(queryNode, "query"); ProtocolTreeNode* listNode = queryNode->getChild(0); ProtocolTreeNode::require(listNode, "list"); if (this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onPrivacyBlockListClear(); if (listNode->children != NULL) { for (size_t i = 0; i < listNode->children->size(); i++) { ProtocolTreeNode* itemNode = (*listNode->children)[i]; ProtocolTreeNode::require(itemNode, "item"); if (itemNode->getAttributeValue("type").compare("jid") == 0) { const string &jid = itemNode->getAttributeValue("value"); if (!jid.empty() && this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onPrivacyBlockListAdd(jid); } } } } }; class IqResultGetGroupInfoHandler: public IqResultHandler { public: IqResultGetGroupInfoHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) { ProtocolTreeNode* groupNode = node->getChild(0); ProtocolTreeNode::require(groupNode, "group"); const string &owner = groupNode->getAttributeValue("owner"); const string &subject = groupNode->getAttributeValue("subject"); const string &subject_t = groupNode->getAttributeValue("s_t"); const string &subject_owner = groupNode->getAttributeValue("s_o"); const string &creation = groupNode->getAttributeValue("creation"); if (this->con->m_pGroupEventHandler != NULL) this->con->m_pGroupEventHandler->onGroupInfo(from, owner, subject, subject_owner, atoi(subject_t.c_str()), atoi(creation.c_str())); } }; class IqResultGetGroupParticipantsHandler: public IqResultHandler { public: IqResultGetGroupParticipantsHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) { if (this->con->m_pGroupEventHandler != NULL) { std::vector participants; this->con->readAttributeList(node, participants, "participant", "jid"); this->con->m_pGroupEventHandler->onGetParticipants(from, participants); } } }; class IqResultCreateGroupChatHandler: public IqResultHandler { std::string subject; public: IqResultCreateGroupChatHandler(WAConnection* con, const std::string &_subject) : IqResultHandler(con), subject(_subject) {} virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) { ProtocolTreeNode* groupNode = node->getChild(0); ProtocolTreeNode::require(groupNode, "group"); const string &groupId = groupNode->getAttributeValue("id"); if (!groupId.empty() && con->m_pGroupEventHandler != NULL) this->con->m_pGroupEventHandler->onGroupCreated(groupId + "@" + from, subject); } }; class IqResultGetPhotoHandler: public IqResultHandler { private: std::string jid; std::string oldId; std::string newId; public: IqResultGetPhotoHandler(WAConnection* con, const std::string &jid):IqResultHandler(con) { this->jid = jid; } virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { const string &attributeValue = node->getAttributeValue("type"); if (!attributeValue.empty() && attributeValue == "result" && this->con->m_pEventHandler != NULL) { std::vector children(node->getAllChildren("picture")); for (size_t i = 0; i < children.size(); i++) { ProtocolTreeNode* current = children[i]; const string &id = current->getAttributeValue("id"); if (!id.empty() && current->data != NULL && current->data->size() > 0) { if (current->data != NULL) this->con->m_pEventHandler->onSendGetPicture(this->jid, *current->data, id); break; } } } } void error(ProtocolTreeNode*) throw (WAException) { if (this->con->m_pEventHandler != NULL) { std::vector v; this->con->m_pEventHandler->onSendGetPicture("error", v, ""); } } }; class IqResultSetPhotoHandler: public IqResultHandler { private: std::string jid; public: IqResultSetPhotoHandler(WAConnection* con, const std::string &jid):IqResultHandler(con) {this->jid = jid;} virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { if (this->con->m_pEventHandler != NULL) { ProtocolTreeNode* child = node->getChild("picture"); if (child != NULL) this->con->m_pEventHandler->onPictureChanged(this->jid, "", true); else this->con->m_pEventHandler->onPictureChanged(this->jid, "", false); } } }; class IqResultSendDeleteAccount: public IqResultHandler { public: IqResultSendDeleteAccount(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode*, const std::string&) throw (WAException) { if (this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onDeleteAccount(true); } void error(ProtocolTreeNode*) throw (WAException) { if (this->con->m_pEventHandler != NULL) this->con->m_pEventHandler->onDeleteAccount(false); } }; class IqResultClearDirtyHandler: public IqResultHandler { public: IqResultClearDirtyHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode*, const std::string&) throw (WAException) { } }; class IqSendClientConfigHandler: public IqResultHandler { public: IqSendClientConfigHandler(WAConnection* con):IqResultHandler(con) {} virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { con->logData("Clientconfig response %s", node->toString().c_str()); } void error(ProtocolTreeNode* node) throw (WAException) { con->logData("Clientconfig response error %s", node->toString().c_str()); } }; class MediaUploadResponseHandler : public IqResultHandler { private: FMessage message; public: MediaUploadResponseHandler(WAConnection* con, const FMessage &message) :IqResultHandler(con) { this->message = message; } virtual void parse(ProtocolTreeNode* node, const std::string&) throw (WAException) { this->con->processUploadResponse(node, &message); } void error(ProtocolTreeNode* node) throw (WAException) { con->logData("Error on Media Upload Request: %s", node->toString().c_str()); } }; friend class WALogin; private: ISocketConnection *rawConn; BinTreeNodeReader in; BinTreeNodeWriter out; WAListener *m_pEventHandler; WAGroupListener *m_pGroupEventHandler; int iqid; std::map pending_server_requests; IMutex *m_pMutex; void parseAck(ProtocolTreeNode *node) throw (WAException); void parseChatStates(ProtocolTreeNode *node) throw (WAException); void parseIq(ProtocolTreeNode *node) throw(WAException); void parseMessage(ProtocolTreeNode* node) throw(WAException); void parseNotification(ProtocolTreeNode *node) throw(WAException); void parsePresense(ProtocolTreeNode*) throw(WAException); void parseReceipt(ProtocolTreeNode *node) throw (WAException); std::map parseCategories(ProtocolTreeNode* node) throw(WAException); void processUploadResponse(ProtocolTreeNode *node, FMessage *message); void sendMessageWithMedia(FMessage* message) throw(WAException); void sendMessageWithBody(FMessage* message) throw(WAException); ProtocolTreeNode* getReceiptAck(const std::string &to, const std::string &id, const std::string &receiptType) throw(WAException); std::string makeId(const std::string &prefix); void readGroupList(ProtocolTreeNode* node, std::vector& groups) throw (WAException); std::string gidToGjid(const std::string &gid); void readAttributeList(ProtocolTreeNode* node, std::vector &vector, const std::string &tag, const std::string &attribute) throw (WAException); void sendVerbParticipants(const std::string &gjid, const std::vector &participants, const std::string &inner_tag) throw (WAException); bool supportsReceiptAcks(); static ProtocolTreeNode* getMessageNode(FMessage* message, ProtocolTreeNode* node); std::vector* processGroupSettings(const std::vector& gruops); public: WAConnection(const std::string &user, const std::string &resource, IMutex* mutex, IMutex *write_mutex, ISocketConnection *conn, WAListener* m_pEventHandler, WAGroupListener* m_pGroupEventHandler); virtual ~WAConnection(); std::string user; std::string domain; std::string resource; std::string jid; std::string nick; KeyStream inputKey, outputKey; bool retry; bool supports_receipt_acks; time_t expire_date; int account_kind; time_t lastTreeRead; static void globalInit(void); static int tokenLookup(const std::string&); void logData(const char *format, ...); void flush() { out.flushBuffer(true); } static std::string removeResourceFromJid(const std::string &jid); void setFlush(bool _flush) { if (out.bFlush = _flush) out.flushBuffer(true); } void setLogin(WALogin *login); void sendMessage(FMessage* message) throw(WAException); void sendAvailableForChat() throw(WAException); bool read() throw(WAException); void sendAck(ProtocolTreeNode * node, const char *classType); void sendPing() throw(WAException); void sendPong(const std::string &id) throw(WAException); void sendComposing(const std::string &to) throw(WAException); void sendActive() throw(WAException); void sendInactive() throw(WAException); void sendPaused(const std::string &to) throw(WAException); void sendMessageReceived(const FMessage &message) throw(WAException); void sendPresenceSubscriptionRequest(const std::string &to) throw (WAException); void sendClientConfig(const std::string &sound, const std::string &pushID, bool preview, const std::string &platform) throw(WAException); void sendClientConfig(const std::string &pushID, bool preview, const std::string &platform, bool defaultSettings, bool groupSettings, const std::vector& groups) throw(WAException); void sendClose() throw (WAException); void sendAvailable() throw (WAException); // U.H. void sendGetPrivacyList() throw (WAException); void sendGetServerProperties() throw (WAException); void sendGetGroups() throw (WAException); void sendCreateGroupChat(const std::string &subject) throw (WAException); void sendGetGroupInfo(const std::string &gjid) throw (WAException); void sendGetParticipants(const std::string &gjid) throw (WAException); void sendClearDirty(const std::string &category) throw (WAException); void sendJoinLeaveGroup(const char *gjid, bool bJoin) throw (WAException); void sendAddParticipants(const std::string &gjid, const std::vector &participants) throw (WAException); void sendRemoveParticipants(const std::string &gjid, const std::vector &participant) throw (WAException); void sendSetNewSubject(const std::string &gjid, const std::string &subject) throw (WAException); void sendStatusUpdate(std::string& status) throw (WAException); void sendGetPicture(const char *jid, const char *type) throw (WAException); void sendSetPicture(const char *jid, std::vector* data, std::vector* preview) throw (WAException); void sendDeleteAccount() throw(WAException); }; #endif /* WACONNECTION_H_ */