Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
jami-daemon
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
savoirfairelinux
jami-daemon
Commits
d81435fa
Project 'savoirfairelinux/ring-daemon' was moved to 'savoirfairelinux/jami-daemon'. Please update any links and bookmarks that may still have the old path.
Commit
d81435fa
authored
13 years ago
by
Rafaël Carré
Browse files
Options
Downloads
Patches
Plain Diff
IM : simplify
parent
d6a2bb56
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
daemon/src/im/InstantMessaging.cpp
+56
-255
56 additions, 255 deletions
daemon/src/im/InstantMessaging.cpp
daemon/src/im/InstantMessaging.h
+5
-48
5 additions, 48 deletions
daemon/src/im/InstantMessaging.h
daemon/test/instantmessagingtest.cpp
+0
-1
0 additions, 1 deletion
daemon/test/instantmessagingtest.cpp
with
61 additions
and
304 deletions
daemon/src/im/InstantMessaging.cpp
+
56
−
255
View file @
d81435fa
...
...
@@ -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);
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*/
)
void
InstantMessaging
::
sip_send
(
pjsip_inv_session
*
session
,
const
std
::
string
&
id
,
const
std
::
string
&
text
)
{
// 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
)
{
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
;
pjsip_dialog
*
dialog
=
session
->
dlg
;
// 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
());
// 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
(
c
type
);
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
);
...
...
This diff is collapsed.
Click to expand it.
daemon/src/im/InstantMessaging.h
+
5
−
48
View file @
d81435fa
...
...
@@ -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
);
/**
...
...
This diff is collapsed.
Click to expand it.
daemon/test/instantmessagingtest.cpp
+
0
−
1
View file @
d81435fa
...
...
@@ -47,7 +47,6 @@ using std::endl;
void
InstantMessagingTest
::
setUp
()
{
_im
=
new
sfl
::
InstantMessaging
();
_im
->
init
();
}
void
InstantMessagingTest
::
testSaveSingleMessage
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment