diff --git a/sflphone-common/src/Makefile.am b/sflphone-common/src/Makefile.am index 09ce81355ddddb126ca478e8cd91f42fd59ce1e9..7bc3ca62da0b8558c3cc3c0ea9db6787f219c242 100644 --- a/sflphone-common/src/Makefile.am +++ b/sflphone-common/src/Makefile.am @@ -81,6 +81,7 @@ libsflphone_la_LIBADD = \ $(src)/libs/dbus-c++/src/libdbus-c++-1.la \ $(IAX_LIB) \ ./sip/libsiplink.la \ + ./sip/im/libim.la \ ./audio/libaudio.la \ ./audio/audiortp/libaudiortp.la \ ./audio/sound/libsound.la \ diff --git a/sflphone-common/src/sip/Makefile.am b/sflphone-common/src/sip/Makefile.am index 8cb4829edc3797aa8e107d2a2b8af0cdf87393ec..7a5477f525f7a930ff27a86f4d00f594375973cc 100644 --- a/sflphone-common/src/sip/Makefile.am +++ b/sflphone-common/src/sip/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS=im + include $(top_srcdir)/globals.mak noinst_LTLIBRARIES = libsiplink.la @@ -22,4 +24,4 @@ noinst_HEADERS = \ sipvoiplink.h libsiplink_la_CXXFLAGS = \ - @PCRE_LIBS@ \ No newline at end of file + @PCRE_LIBS@ diff --git a/sflphone-common/src/sip/im/InstantMessaging.cpp b/sflphone-common/src/sip/im/InstantMessaging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3d75d8c9667a9d0e9f6f8657bcc1789a76281c4 --- /dev/null +++ b/sflphone-common/src/sip/im/InstantMessaging.cpp @@ -0,0 +1,75 @@ +#include "InstantMessaging.h" + +namespace sfl { + + InstantMessaging::InstantMessaging() + : _current_dlg( NULL ), _message(EMPTY_MESSAGE), _response(EMPTY_MESSAGE){} + + + InstantMessaging::~InstantMessaging(){ + delete _current_dlg; _current_dlg = 0; + } + + + void InstantMessaging::set_text( std::string message ){ + _message = pj_str((char*)message.c_str()); + } + + void InstantMessaging::set_response( std::string resp ){ + _response = pj_str((char*)resp.c_str()); + } + + std::string InstantMessaging::get_text_message( void ){ + std::string text; + + text = _response.ptr; + return text; + } + + + pj_status_t InstantMessaging::receive (std::string message, 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 + + } + + + pj_status_t InstantMessaging::send (CallID& id, std::string message) { + + /* + 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; + + msg_method.id = PJSIP_OTHER_METHOD; + msg_method.name = METHOD_NAME ; + + // Must lock dialog + pjsip_dlg_inc_lock( _current_dlg ); + + // Create the message request + status = pjsip_dlg_create_request( _current_dlg, &msg_method, -1, &tdata ); + PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 ); + + // Attach "text/plain" body + tdata->msg->body = pjsip_msg_body_create( tdata->pool, &type, &subtype, &_message ); + + // Send the request + status = pjsip_dlg_send_request( _current_dlg, tdata, -1, NULL); + PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 ); + + // Done + pjsip_dlg_dec_lock( _current_dlg ); + */ + return PJ_SUCCESS; + } + + + void InstantMessaging::display (void){ + std::cout << "<IM> " << _response.ptr << std::endl; + } + +} diff --git a/sflphone-common/src/sip/im/InstantMessaging.h b/sflphone-common/src/sip/im/InstantMessaging.h new file mode 100644 index 0000000000000000000000000000000000000000..9266dc588cca3c5f3ae8aea609ba589322d1d63c --- /dev/null +++ b/sflphone-common/src/sip/im/InstantMessaging.h @@ -0,0 +1,115 @@ +#ifndef _INSTANT_MESSAGING_H +#define _INSTANT_MESSAGING_H + +#include <string> +#include <queue> +#include <iostream> +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> + +#include "call.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") + +namespace sfl { + + class InstantMessaging + { + public: + /* + * Class constructor + */ + InstantMessaging(); + + /* + * Class destructor + */ + ~InstantMessaging(); + + /* + * Attach the instant messaging module to an existing SIP dialog + * + * @param dlg A pointer on the current pjsip_dialog structure + */ + void set_dialog (pjsip_dialog *dlg) { _current_dlg = dlg; } + + /* + * Prepare a string to be sent. This method have to be called + * before sending each message + * + * @param message The text message + */ + void set_text( std::string message ); + + std::string get_text_message(void) ; + + /* + * 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 + */ + pj_status_t receive (std::string message, CallID& 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 send (CallID& id, const std::string message); + + /** + * Notify the clients, through D-Bus, that a new message has arrived + * + * @param id The callID to notify (TODO: accountID?) + */ + pj_status_t notify (CallID& id); + + /* + * Set the response. + * + * @param resp The last string message received + */ + void set_response( std::string resp ); + + /* + * Display the response + */ + void display (void); + + private: + + /* + * The pjsip_dialog instance through which the instant messaging module exists + */ + pjsip_dialog *_current_dlg; + + /* + * The message to be sent + */ + pj_str_t _message; + + /** + * A queue to handle messages + */ + std::queue<std::string> queuedMessages; + + /* + * The last response + */ + pj_str_t _response; + + InstantMessaging(const InstantMessaging&); //No Copy Constructor + InstantMessaging& operator=(const InstantMessaging&); //No Assignment Operator + }; +} +#endif // _INSTANT_MESSAGING_H diff --git a/sflphone-common/src/sip/im/Makefile.am b/sflphone-common/src/sip/im/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..a59fdac64525c2115e8ecc5ea0c9e03222439068 --- /dev/null +++ b/sflphone-common/src/sip/im/Makefile.am @@ -0,0 +1,8 @@ +SUBDIRS = + +include $(top_srcdir)/globals.mak + +noinst_LTLIBRARIES = libim.la + +libim_la_SOURCES = \ + InstantMessaging.cpp InstantMessaging.h diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index a005ab44408ff388ebe41076eb77fd0ee2de9444..6629447a0f085d9292667c46ffabb304b420528f 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -65,6 +65,8 @@ #define CAN_REINVITE 1 +using namespace sfl; + static char * invitationStateMap[] = { (char*) "PJSIP_INV_STATE_NULL", (char*) "PJSIP_INV_STATE_CALLING", @@ -163,6 +165,11 @@ pj_thread_desc desc; */ UrlHook *urlhook; +/* + * Instant Messaging module + */ +InstantMessaging *imModule; + /** * Get the number of voicemail waiting in a SIP message */ @@ -270,6 +277,7 @@ SIPVoIPLink::SIPVoIPLink (const AccountID& accountID) srand (time (NULL)); urlhook = new UrlHook (); + imModule = new InstantMessaging (); /* Start pjsip initialization step */ init(); @@ -3331,18 +3339,21 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_ _debug("UserAgent: Transaction changed to state %s", transactionStateMap[tsx->state]); + pjsip_rx_data* r_data; + pjsip_tx_data* t_data; + if (tsx->role==PJSIP_ROLE_UAS && tsx->state==PJSIP_TSX_STATE_TRYING && pjsip_method_cmp (&tsx->method, &pjsip_refer_method) ==0) { /** Handle the refer method **/ onCallTransfered (inv, e->body.tsx_state.src.rdata); + } else if (tsx->role==PJSIP_ROLE_UAS && tsx->state==PJSIP_TSX_STATE_TRYING) { if (e && e->body.rx_msg.rdata) { _debug("Event"); - pjsip_tx_data* t_data; - pjsip_rx_data* r_data = e->body.rx_msg.rdata; + r_data = e->body.rx_msg.rdata; if (r_data && r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { @@ -3360,13 +3371,38 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_ } // Must reply 200 OK on SIP INFO request else if (request.find (method_info) != (size_t)-1) { - pjsip_dlg_create_response (inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data); - pjsip_dlg_send_response (inv->dlg, tsx, t_data); } } } + + // Incoming TEXT message + if (e && e->body.tsx_state.src.rdata) { + + std::string message; + SIPCall * call; + + // Get the message inside the transaction + r_data = e->body.tsx_state.src.rdata; + message = (char*) r_data->msg_info.msg->body->data; + + // Try to determine who is the recipient of the message + call = reinterpret_cast<SIPCall *> (inv->mod_data[getModId() ]); + if (!call) { + _debug ("Incoming TEXT message: Can't find the recipient of the message"); + return; + } + + // Respond with a 200/OK + pjsip_dlg_create_response (inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data); + pjsip_dlg_send_response (inv->dlg, tsx, t_data); + + imModule->receive (message, call->getCallId ()); + + } + + } } diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h index 20da9443255c77f55bd5016321acb2aa29cc1f16..6aacc197b14941217483eed21f27eed8dd00339a 100644 --- a/sflphone-common/src/sip/sipvoiplink.h +++ b/sflphone-common/src/sip/sipvoiplink.h @@ -37,7 +37,7 @@ #include "voiplink.h" #include "hooks/urlhook.h" - +#include "im/InstantMessaging.h" ////////////////////////////// /* PJSIP imports */