diff --git a/sflphone-common/src/Makefile.am b/sflphone-common/src/Makefile.am index f41b7b87aeafd60e778948d7b5a6c8e4d07f6eb4..10950a290304ca4bfb9a69a28ae31562e9b453eb 100644 --- a/sflphone-common/src/Makefile.am +++ b/sflphone-common/src/Makefile.am @@ -65,7 +65,6 @@ libsflphone_la_LIBADD = \ $(src)/libs/dbus-c++/src/libdbus-c++-1.la \ $(IAX_LIB) \ ./sip/libsiplink.la \ - ./sip/im/libim.la \ ./audio/libaudio.la \ ./dbus/libdbus.la \ ./config/libconfig.la \ diff --git a/sflphone-common/src/sip/Makefile.am b/sflphone-common/src/sip/Makefile.am index 7a5477f525f7a930ff27a86f4d00f594375973cc..9043a15a5badd977412259d78ce0bcc3cf2e320e 100644 --- a/sflphone-common/src/sip/Makefile.am +++ b/sflphone-common/src/sip/Makefile.am @@ -13,6 +13,7 @@ libsiplink_la_SOURCES = \ sipcall.cpp \ sipvoiplink.cpp +libsiplink_la_LIBADD = im/libim.la noinst_HEADERS = \ Pattern.h \ diff --git a/sflphone-common/src/sip/im/InstantMessaging.cpp b/sflphone-common/src/sip/im/InstantMessaging.cpp index 691ef6e87727e147a08e98cca92d971ce4cc0b49..126f2e2735681a5cdf9cd9376398faca9a2d7910 100644 --- a/sflphone-common/src/sip/im/InstantMessaging.cpp +++ b/sflphone-common/src/sip/im/InstantMessaging.cpp @@ -3,38 +3,80 @@ namespace sfl { InstantMessaging::InstantMessaging() - {} + : imFiles () + {} - InstantMessaging::~InstantMessaging(){ + InstantMessaging::~InstantMessaging() + {} + + bool InstantMessaging::init () { + return true; } - pj_status_t InstantMessaging::init () { - return PJ_SUCCESS; + int InstantMessaging::openArchive (CallID& id) { + + // Create a new file stream + std::ofstream File (id.c_str (), std::ios::out | std::ios::app); + imFiles[id] = &File; + + // Attach it to the call ID + return (int)imFiles.size (); + } + + int InstantMessaging::closeArchive (CallID& id) { + + // Erase it from the map + imFiles.erase (id); + return (int)imFiles.size (); + } + + bool InstantMessaging::saveMessage (const std::string& message, const std::string& author, CallID& id, int mode) { + + // We need here to write the text message in the right file. + // We will use the Call ID + + std::ofstream File; + std::string filename = "sip:"; + + filename.append (id); + File.open (filename.c_str (), (std::_Ios_Openmode )mode); + + if (!File.good () || !File.is_open ()) + return false; + + File << "[" << author << "] " << message << '\n'; + File.close (); + + return true; } - std::string InstantMessaging::receive (std::string message, CallID& id) { + std::string InstantMessaging::receive (const std::string& message, const std::string& author, CallID& id) { // We just receive a TEXT message. Before sent it to the recipient, we must assure that the message is complete. // We should use a queue to push these messages in _debug ("New message : %s", message.c_str ()); - // TODO Archive the messages // TODO Security check // TODO String cleaning + // Archive the message + this->saveMessage (message, author, id); + + return message; } pj_status_t InstantMessaging::notify (CallID& id) { - + // Notify the clients through a D-Bus signal + return PJ_SUCCESS; } - pj_status_t InstantMessaging::send (pjsip_inv_session *session, const std::string& text) { + pj_status_t InstantMessaging::send (pjsip_inv_session *session, CallID& id, const std::string& text) { pjsip_method msg_method; @@ -70,6 +112,9 @@ namespace sfl { // Done pjsip_dlg_dec_lock( dialog ); + // Archive the message + this->saveMessage (text, "Me", id); + return PJ_SUCCESS; } diff --git a/sflphone-common/src/sip/im/InstantMessaging.h b/sflphone-common/src/sip/im/InstantMessaging.h index 3c9acecbfd4554364b4e197ec08f4e9e3e823a01..238ce1687fd375b4d2631b876293b9e717d6b93c 100644 --- a/sflphone-common/src/sip/im/InstantMessaging.h +++ b/sflphone-common/src/sip/im/InstantMessaging.h @@ -2,8 +2,8 @@ #define _INSTANT_MESSAGING_H #include <string> -#include <queue> #include <iostream> +#include <fstream> #include <pjsip.h> #include <pjlib.h> #include <pjsip_ua.h> @@ -17,6 +17,9 @@ #define STR_PLAIN pj_str((char*)"plain") #define METHOD_NAME pj_str((char*)"MESSAGE") +#define MODE_APPEND std::ios::out || std::ios::app +#define MODE_TEST std::ios::out + namespace sfl { class InstantMessaging @@ -35,7 +38,33 @@ namespace sfl { /* * Register and initialize instant messaging support */ - pj_status_t init (); + bool init (); + + /* + * Open an existing file if possible or create a new one. + * + * @param id The current call + * @return int The number of currently open file stream + */ + int openArchive (CallID& id); + + /* + * Close the file corresponding to the specified call + * + * @param id The current call + * @return int The number of remaining open file stream + */ + int closeArchive (CallID& id); + + /* + * Write the text message to the right file + * The call ID is associated to a file descriptor, so it is easy then to retrieve the right file + * + * @param message The text message + * @param id The current call + * @return True if the message could have been successfully saved, False otherwise + */ + bool saveMessage (const std::string& message, const std::string& author, CallID& id, int mode = MODE_APPEND); /* * Receive a string SIP message, for a specific call @@ -43,7 +72,7 @@ namespace sfl { * @param message The message contained in the TEXT message * @param id The call recipient of the message */ - std::string receive (std::string message, CallID& id); + std::string receive (const std::string& message, const std::string& author, CallID& id); /* * Send a SIP string message inside a call @@ -54,7 +83,7 @@ namespace sfl { * @return pj_status_t 0 on success * 1 otherwise */ - pj_status_t send (pjsip_inv_session*, const std::string&); + pj_status_t send (pjsip_inv_session*, CallID& id, const std::string&); /** * Notify the clients, through D-Bus, that a new message has arrived @@ -63,12 +92,30 @@ namespace sfl { */ pj_status_t notify (CallID& id); + /* + * Add a pair file stream / call ID to the private std::map + */ + inline int addFileStream (std::string key, std::ofstream &value) { + return (int)imFiles.size (); + } + + /* + * Remove a pair file stream / call ID from the private std::map + */ + inline int removeFileStream (std::string key) { imFiles.erase (key); return (int)imFiles.size (); } + private: /** * A queue to handle messages */ - std::queue<std::string> queuedMessages; + // std::queue<std::string> queuedMessages; + + /** + * A map to handle opened file descriptors + * A file descriptor is associated to a call ID + */ + std::map<std::string, std::ofstream*> imFiles; InstantMessaging(const InstantMessaging&); //No Copy Constructor InstantMessaging& operator=(const InstantMessaging&); //No Assignment Operator diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index 75da8298e7b3a0417d15def3ef782feba0f2fbbf..634a73152fb7b245936aeb654a4682a96b6da878 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -1101,7 +1101,7 @@ int SIPVoIPLink::inv_session_reinvite (SIPCall *call, std::string direction) status = pjsip_inv_send_msg (call->getInvSession(), tdata); // Test IM message - imModule->send (call->getInvSession (), "Salut! Click <a href='http://sflphone.org'>here</a>"); + imModule->send (call->getInvSession (), call->getCallId (), "Salut! Click <a href='http://sflphone.org'>here</a>"); if (status != PJ_SUCCESS) return 1; // !PJ_SUCCESS @@ -3413,7 +3413,7 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_ // Right now, it does do anything. // And notify the clients Manager::instance ().incomingMessage ( call->getCallId (), - imModule->receive (message, call->getCallId ())); + imModule->receive (message, call->getPeerNumber (), call->getCallId ())); } diff --git a/sflphone-common/test/instantmessagingtest.cpp b/sflphone-common/test/instantmessagingtest.cpp index 4557f06fd81d92c51a86b27259dd576a6872e18c..dc7ad4999f3ae443971c577998cdf4d9496d76dc 100644 --- a/sflphone-common/test/instantmessagingtest.cpp +++ b/sflphone-common/test/instantmessagingtest.cpp @@ -29,30 +29,68 @@ */ #include <stdio.h> -#include <sstream> -#include <dlfcn.h> +#include <iostream> +#include <fstream> #include "instantmessagingtest.h" using std::cout; using std::endl; -using namespace sfl; void InstantMessagingTest::setUp() { - _im = new InstantMessaging (); + _im = new sfl::InstantMessaging (); _im->init (); } -void InstantMessagingTest::testFunction() +void InstantMessagingTest::testSaveSingleMessage () { - _debug ("-------------------- InstantMessagingTest::testFunction --------------------\n"); + _debug ("-------------------- InstantMessagingTest::testSaveSingleMessage --------------------\n"); - CPPUNIT_ASSERT (1 == 1); + std::string input, tmp; + std::string callID = "testfile1.txt"; + + // Open a file stream and try to write in it + CPPUNIT_ASSERT (_im->saveMessage ("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out) == true); + + // Read it to check it has been successfully written + std::ifstream testfile (callID.c_str (), std::ios::in); + CPPUNIT_ASSERT (testfile.is_open () == true); + + while (!testfile.eof ()) { + std::getline (testfile, tmp); + input.append (tmp); + } + testfile.close (); + CPPUNIT_ASSERT (input == "[Manu] Bonjour, c'est un test d'archivage de message"); +} + +void InstantMessagingTest::testSaveMultipleMessage () +{ + _debug ("-------------------- InstantMessagingTest::testSaveMultipleMessage --------------------\n"); + + std::string input, tmp; + std::string callID = "testfile2.txt"; + + // Open a file stream and try to write in it + CPPUNIT_ASSERT (_im->saveMessage ("Bonjour, c'est un test d'archivage de message", "Manu", callID, std::ios::out) == true); + CPPUNIT_ASSERT (_im->saveMessage ("Cool", "Alex", callID, std::ios::out || std::ios::app) == true); + + // Read it to check it has been successfully written + std::ifstream testfile (callID.c_str (), std::ios::in); + CPPUNIT_ASSERT (testfile.is_open () == true); + + while (!testfile.eof ()) { + std::getline (testfile, tmp); + input.append (tmp); + } + testfile.close (); + printf ("%s\n", input.c_str()); + CPPUNIT_ASSERT (input == "[Manu] Bonjour, c'est un test d'archivage de message[Alex] Cool"); } void InstantMessagingTest::tearDown() { - delete _im; - _im = 0; + delete _im; + _im = 0; } diff --git a/sflphone-common/test/instantmessagingtest.h b/sflphone-common/test/instantmessagingtest.h index 40629374f316624a96f4eb5b1efea3b71656bcb1..dc97ba727c403a8f2fa4a083a6f6ef928557f788 100644 --- a/sflphone-common/test/instantmessagingtest.h +++ b/sflphone-common/test/instantmessagingtest.h @@ -53,7 +53,8 @@ class InstantMessagingTest : public CppUnit::TestCase { * Use cppunit library macros to add unit test the factory */ CPPUNIT_TEST_SUITE( InstantMessagingTest ); - CPPUNIT_TEST( testFunction ); + CPPUNIT_TEST (testSaveSingleMessage); + CPPUNIT_TEST (testSaveMultipleMessage); CPPUNIT_TEST_SUITE_END(); public: @@ -71,7 +72,9 @@ class InstantMessagingTest : public CppUnit::TestCase { */ inline void tearDown (); - void testFunction (); + void testSaveSingleMessage (); + + void testSaveMultipleMessage (); private: sfl::InstantMessaging *_im;