diff --git a/daemon/src/im/InstantMessaging.cpp b/daemon/src/im/InstantMessaging.cpp
index 1284012ad39f7fa737933b1bea89457746adfe41..f2662a4863a38ff5a3686ec27f38734b8062a6a7 100644
--- a/daemon/src/im/InstantMessaging.cpp
+++ b/daemon/src/im/InstantMessaging.cpp
@@ -36,43 +36,17 @@
namespace sfl
{
-static inline char* duplicateString (char dst[], const char src[], size_t len)
-{
- memcpy (dst, src, len);
- dst[len] = 0;
- return dst;
-}
-
static void XMLCALL startElementCallback (void *userData, const char *name, const char **atts)
{
+ if (strcmp (name, "entry"))
+ return;
- char attribute[100];
- char value[100];
-
- const char **att;
-
- // _debug ("InstantMessaging: StartElement Callback: %s", name);
-
- if (strcmp (name, "entry") == 0) {
-
- sfl::InstantMessaging::UriList *list = static_cast<sfl::InstantMessaging::UriList *> (userData);
- sfl::InstantMessaging::UriEntry entry = sfl::InstantMessaging::UriEntry();
-
- for (att = atts; *att; att += 2) {
-
- const char **val = att+1;
-
- duplicateString (attribute, *att, strlen (*att));
- duplicateString (value, *val, strlen (*val));
-
- // _debug ("InstantMessaging: attribute: %s, value: %s", attribute, value);
+ sfl::InstantMessaging::UriEntry entry = sfl::InstantMessaging::UriEntry();
- entry.insert (std::pair<std::string, std::string> (std::string (attribute), std::string (value)));
- }
-
- list->push_back (entry);
- }
+ for (const char **att = atts; *att; att += 2)
+ entry.insert (std::pair<std::string, std::string> (*att, *(att+1)));
+ (static_cast<sfl::InstantMessaging::UriList *> (userData))->push_back(entry);
}
static void XMLCALL endElementCallback (void * /*userData*/, const char * /*name*/)
@@ -87,40 +61,10 @@ InstantMessaging::InstantMessaging()
InstantMessaging::~InstantMessaging() {}
-bool InstantMessaging::init ()
-{
- return true;
-}
-
-int InstantMessaging::openArchive (std::string& 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 (std::string& id)
-{
-
- // Erase it from the map
- imFiles.erase (id);
- return (int) imFiles.size ();
-}
-
bool InstantMessaging::saveMessage (const std::string& message, const std::string& author, const std::string& 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 = "im:";
-
- filename.append (id);
+ std::string filename = "im:" + id;
File.open (filename.c_str (), (std::_Ios_Openmode) mode);
if (!File.good () || !File.is_open ())
@@ -132,209 +76,79 @@ bool InstantMessaging::saveMessage (const std::string& message, const std::strin
return true;
}
-std::string InstantMessaging::receive (const std::string& message, const std::string& /*author*/, const std::string& /*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 Security check
- // TODO String cleaning
-
- // Archive the message
- // TODO Deactivate this for the momment, this is an extra feature.
- // this->saveMessage (message, author, id);
-
-
- return message;
-
-}
-
-pj_status_t InstantMessaging::notify (const std::string& /*id*/)
-{
- // Notify the clients through a D-Bus signal
- return PJ_SUCCESS;
-}
-
-pj_status_t InstantMessaging::sip_send (pjsip_inv_session *session, const std::string& id, const std::string& text)
+void InstantMessaging::sip_send (pjsip_inv_session *session, const std::string& id, const std::string& text)
{
-
- pjsip_method msg_method;
- const pj_str_t type = STR_TEXT;
- const pj_str_t subtype = STR_PLAIN;
pjsip_tx_data *tdata;
- pj_status_t status;
- pjsip_dialog* dialog;
- pj_str_t message;
-
- msg_method.id = PJSIP_OTHER_METHOD;
- msg_method.name = METHOD_NAME;
-
- // Get the dialog associated to the call
- dialog = session->dlg;
- // Convert the text into a format readable by pjsip
- message = pj_str ( (char*) text.c_str ());
+ pjsip_dialog* dialog = session->dlg;
- // Must lock dialog
pjsip_dlg_inc_lock (dialog);
- // Create the message request
- status = pjsip_dlg_create_request (dialog, &msg_method, -1, &tdata);
- PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
+ pjsip_method msg_method = { PJSIP_OTHER_METHOD, pj_str((char*)"MESSAGE") };
+ if (pjsip_dlg_create_request (dialog, &msg_method, -1, &tdata) != PJ_SUCCESS) {
+ pjsip_dlg_dec_lock (dialog);
+ return;
+ }
- // Attach "text/plain" body
+ const pj_str_t type = pj_str((char*)"text");
+ const pj_str_t subtype = pj_str((char*)"plain");
+ pj_str_t message = pj_str ( (char*) text.c_str ());
tdata->msg->body = pjsip_msg_body_create (tdata->pool, &type, &subtype, &message);
- // Create the Require header to handle recipient-list Content-Disposition type
- // pjsip_generic_string_hdr reqhdr;
- // pj_str_t reqhname = pj_str ("Require");
- // pj_str_t reqhvalue = pj_str ("recipient-list");
-
- // Create the Content-Type header to handle multipart/mixed and boundary MIME types
- // pj_str_t ctype = pj_str ("Content-Type");
- // pj_str_t sctype = pj_str ("ctype"); // small version of the header name
- // ctypehdr = pjsip_msg_find_hdr_by_names (tdata->msg, &ctype, &sctype, NULL);
- // pjsip_generic_string_hdr ctypehdr;
- // pj_str_t ctypehname = pj_str ("Content-Type");
- // pj_str_t ctypehvalue = pj_str ("multipart/mixed;boundary=\"boundary\"");
-
- // Add headers to the message
- // pjsip_generic_string_hdr_init2 (&reqhdr, &reqhname, &reqhvalue);
- // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&reqhdr));
- // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&ctypehdr));
-
- // Send the request
- status = pjsip_dlg_send_request (dialog, tdata, -1, NULL);
- // PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-
- // Done
+ pjsip_dlg_send_request (dialog, tdata, -1, NULL);
pjsip_dlg_dec_lock (dialog);
- // Archive the message
- this->saveMessage (text, "Me", id);
-
- return PJ_SUCCESS;
+ saveMessage (text, "Me", id);
}
-pj_status_t InstantMessaging::send_sip_message (pjsip_inv_session *session, const std::string& id, const std::string& message)
+void InstantMessaging::send_sip_message (pjsip_inv_session *session, const std::string& id, const std::string& message)
{
-
- /* Check the length of the message */
- if (message.length() < getMessageMaximumSize()) {
- /* No problem here */
- sip_send (session, id, message);
- }
-
- else {
- /* It exceeds the size limit of a SIP MESSAGE (1300 bytes), o plit it and send multiple messages */
- std::vector<std::string> multiple_messages = split_message (message);
- /* Send multiple messages */
- // int size = multiple_messages.size();
- int i = 0;
-
- // Maximum is above 1500 character
- // TODO: Send every messages
- sip_send (session, id, multiple_messages[i]);
- }
-
- return PJ_SUCCESS;
+ std::vector<std::string> msgs = split_message (message);
+ std::vector<std::string>::const_iterator iter;
+ for (iter = msgs.begin(); iter != msgs.end(); ++iter)
+ sip_send (session, id, *iter);
}
-bool InstantMessaging::iax_send (iax_session* session, const std::string& /*id*/, const std::string& message)
+void InstantMessaging::iax_send (iax_session* session, const std::string& /*id*/, const std::string& message)
{
- if (iax_send_text (session, message.c_str()) != -1)
- return true;
- else
- return false;
-
-
+ iax_send_text(session, message.c_str()) != -1;
}
-bool InstantMessaging::send_iax_message (iax_session* session, const std::string& id, const std::string& message)
+void InstantMessaging::send_iax_message (iax_session* session, const std::string& id, const std::string& message)
{
-
- bool ret;
-
- /* Check the length of the message */
- if (message.length() < getMessageMaximumSize()) {
- /* No problem here */
- ret = iax_send (session, id, message);
- }
-
- else {
- /* It exceeds the size limit of a SIP MESSAGE (1300 bytes), o plit it and send multiple messages */
- std::vector<std::string> multiple_messages = split_message (message);
- /* Send multiple messages */
- // int size = multiple_messages.size();
- int i = 0;
-
- // Maximum is above 1500 character
- // TODO: Send every messages
- ret = iax_send (session, id, multiple_messages[i]);
- }
-
- return ret;
+ std::vector<std::string> msgs = split_message (message);
+ std::vector<std::string>::const_iterator iter;
+ for (iter = msgs.begin(); iter != msgs.end(); ++iter)
+ iax_send(session, id, *iter);
}
-std::vector<std::string> InstantMessaging::split_message (const std::string& text)
+std::vector<std::string> InstantMessaging::split_message(std::string text)
{
-
std::vector<std::string> messages;
- std::string text_to_split = text;
-
- /* Iterate over the message length */
- while (text_to_split.length() > getMessageMaximumSize()) {
- /* The remaining string is still too long */
-
- /* Compute the substring */
- std::string split_message = text_to_split.substr (0, (size_t) getMessageMaximumSize());
- /* Append our split character \n\n */
- split_message.append (DELIMITER_CHAR);
- /* Append in the vector */
- messages.push_back (split_message);
- /* Use the remaining string to not loop forever */
- text_to_split = text_to_split.substr ( (size_t) getMessageMaximumSize());
+ size_t len = getMessageMaximumSize();
+
+ while (text.length() > len - 2) {
+ messages.push_back (text.substr(len - 2) + "\n\n");
+ text = text.substr(len - 2);
}
- /* Push the last message */
- /* If the message length does not exceed the maximum size of a SIP MESSAGE, we go directly here */
- messages.push_back (text_to_split);
+ messages.push_back (text);
return messages;
}
std::string InstantMessaging::generateXmlUriList (UriList& list)
{
+ std::string xmlbuffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">"
+ "<list>";
- std::string xmlbuffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
- xmlbuffer.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
- xmlbuffer.append ("<list>");
-
- // An iterator over xml attribute
- UriEntry::iterator iterAttr;
+ for (UriList::iterator iter = list.begin(); iter != list.end(); ++iter)
+ xmlbuffer += "<entry uri=" + (*iter)[sfl::IM_XML_URI] + " cp:copyControl=\"to\" />";
- // An iterator over list entries
- UriList::iterator iterEntry = list.begin();
-
- while (iterEntry != list.end()) {
- xmlbuffer.append ("<entry uri=");
- UriEntry entry = static_cast<UriEntry> (*iterEntry);
- iterAttr = entry.find (sfl::IM_XML_URI);
- xmlbuffer.append (iterAttr->second);
- xmlbuffer.append (" cp:copyControl=\"to\" />");
-
- iterEntry++;
- }
-
- xmlbuffer.append ("</list>");
- xmlbuffer.append ("</resource-lists>");
-
- return xmlbuffer;
+ return xmlbuffer + "</list></resource-lists>";
}
@@ -357,20 +171,13 @@ InstantMessaging::UriList InstantMessaging::parseXmlUriList (std::string& urilis
std::string InstantMessaging::appendUriList (std::string text, UriList& list)
{
-
- std::string formatedText = "--boundary Content-Type: text/plain";
-
- formatedText.append (text);
- formatedText.append ("--boundary Content-Type: application/resource-lists+xml");
- formatedText.append ("Content-Disposition: recipient-list");
-
- std::string recipientlist = generateXmlUriList (list);
-
- formatedText.append (recipientlist);
-
- formatedText.append ("--boundary--");
-
- return formatedText;
+ return
+ "--boundary Content-Type: text/plain" +
+ text +
+ "--boundary Content-Type: application/resource-lists+xml" +
+ "Content-Disposition: recipient-list" +
+ generateXmlUriList (list) +
+ "--boundary--";
}
std::string InstantMessaging::findTextUriList (std::string& text)
@@ -405,21 +212,15 @@ std::string InstantMessaging::findTextUriList (std::string& text)
std::string InstantMessaging::findTextMessage (std::string& text)
{
std::string ctype = "Content-Type: text/plain";
- std::string boundary = "--boundary";
-
- size_t pos = 0;
- size_t begin = 0;
- size_t end = 0;
- // find the content type
- if ( (pos = text.find (ctype)) == std::string::npos)
+ size_t pos = text.find (ctype);
+ if (pos == std::string::npos)
throw InstantMessageException ("Could not find Content-Type tag while parsing sip message for text");
- // plain text content start after content type tag (plus \n\n)
- begin = pos+ctype.size();
+ size_t begin = pos+ctype.size();
- // retrive end of the text content
- if ( (end = text.find (boundary, begin)) == std::string::npos)
+ size_t end = text.find ("--boundary", begin);
+ if (end == std::string::npos)
throw InstantMessageException ("Could not find end of text \"boundary\" while parsing sip message for text");
return text.substr (begin, end-begin);
diff --git a/daemon/src/im/InstantMessaging.h b/daemon/src/im/InstantMessaging.h
index 90a0ee8040bd0f63215311feaa1025b23a2c6032..0175af3a36bf4aa5bd8ca453a4593f330ad33047 100644
--- a/daemon/src/im/InstantMessaging.h
+++ b/daemon/src/im/InstantMessaging.h
@@ -50,11 +50,7 @@
#include <iax-client.h>
#define EMPTY_MESSAGE pj_str((char*)"")
-#define STR_TEXT pj_str((char*)"text")
-#define STR_PLAIN pj_str((char*)"plain")
-#define METHOD_NAME pj_str((char*)"MESSAGE")
#define MAXIMUM_MESSAGE_LENGTH 1560 /* PJSIP's sip message limit */
-#define DELIMITER_CHAR "\n\n"
#define MODE_APPEND std::ios::out || std::ios::app
#define MODE_TEST std::ios::out
@@ -90,11 +86,6 @@ class InstantMessaging
*/
~InstantMessaging();
- /*
- * Register and initialize instant messaging support
- */
- bool init ();
-
/**
* Set maximum size fo this module.
*/
@@ -110,21 +101,6 @@ class InstantMessaging
return messageMaxSize;
}
- /*
- * 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 (std::string& 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 (std::string& 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
@@ -135,40 +111,21 @@ class InstantMessaging
*/
bool saveMessage (const std::string& message, const std::string& author, const std::string& id, int mode = MODE_APPEND);
- /*
- * Receive a string SIP message, for a specific call
- *
- * @param message The message contained in the TEXT message
- * @param id The call recipient of the message
- */
- std::string receive (const std::string& message, const std::string& author, const std::string& id);
-
/*
* Send a SIP string message inside a call
*
* @param id The call ID we will retrieve the invite session from
* @param message The string message, as sent by the client
- *
- * @return pj_status_t 0 on success
- * 1 otherwise
*/
- pj_status_t sip_send (pjsip_inv_session*, const std::string& id, const std::string&);
+ void sip_send (pjsip_inv_session*, const std::string& id, const std::string&);
- pj_status_t send_sip_message (pjsip_inv_session*, const std::string& id, const std::string&);
+ void send_sip_message (pjsip_inv_session*, const std::string& id, const std::string&);
- bool iax_send (iax_session* session, const std::string& id, const std::string& message);
+ void iax_send (iax_session* session, const std::string& id, const std::string& message);
- bool send_iax_message (iax_session *session, const std::string& id, const std::string&);
+ void send_iax_message (iax_session *session, const std::string& id, const std::string&);
- std::vector<std::string> split_message (const std::string&);
-
-
- /**
- * Notify the clients, through D-Bus, that a new message has arrived
- *
- * @param id The callID to notify (TODO: accountID?)
- */
- pj_status_t notify (const std::string& /*id*/);
+ std::vector<std::string> split_message(std::string);
/**
diff --git a/daemon/test/instantmessagingtest.cpp b/daemon/test/instantmessagingtest.cpp
index 18ad7cc3ee440a368ce68578314ad0e5f01e9318..47ca3ae7616f3fce6b820bf71b7ad59f2b59c0b8 100644
--- a/daemon/test/instantmessagingtest.cpp
+++ b/daemon/test/instantmessagingtest.cpp
@@ -47,7 +47,6 @@ using std::endl;
void InstantMessagingTest::setUp()
{
_im = new sfl::InstantMessaging ();
- _im->init ();
}
void InstantMessagingTest::testSaveSingleMessage ()