Commit d7be3df1 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

[#3654] Ability to save history in files

parent 07314c70
......@@ -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 \
......
......@@ -13,6 +13,7 @@ libsiplink_la_SOURCES = \
sipcall.cpp \
sipvoiplink.cpp
libsiplink_la_LIBADD = im/libim.la
noinst_HEADERS = \
Pattern.h \
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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 ()));
}
......
......@@ -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;
}
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment