/* Copyright (C) 2005-2009 Michel de Boer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /** * @file * Instant message session. * SIP does not have a concept of message sessions. It's up to the * user interface to create the illusion of a session by grouping * messages between 2 users. */ #ifndef _MSG_SESSION_H #define _MSG_SESSION_H #include #include #include "id_object.h" #include "exceptions.h" #include "user.h" #include "sockets/url.h" #include "parser/media_type.h" #include "patterns/observer.h" using namespace std; namespace im { /** * Maximum length for inline text messages. Longer texts are shown * as attachments. */ const size_t MAX_INLINE_TEXT_LEN = 10240; /** Message direction. */ enum t_direction { MSG_DIR_IN, /**< Incoming. */ MSG_DIR_OUT /**< Outgoing. */ }; /** Text format. */ enum t_text_format { TXT_PLAIN, /**< Plain */ TXT_HTML, /**< HTML */ }; /** Message composing state. */ enum t_composing_state { COMPOSING_STATE_IDLE, COMPOSING_STATE_ACTIVE }; /** * Convert a state name a conveyed in an im_iscomposing body to a state. * @param state_name [in] The state name to convert. * @return The composing state. If the state name is unknown, then * COMPOSING_STATE_IDE is returned. */ t_composing_state string2composing_state(const string &state_name); /** * Convert a composing state to a string for an im_iscomposing body. * @param state [in] The composing state to convert. * @return The string. */ string composing_state2string(t_composing_state state); /** * Single message with meta information. * In the current implementation a message either contains a text message * or an attachment. * TODO: use multipart MIME to send a text message with an attachment. */ class t_msg : public t_id_object { public: string subject; /**< Subject of the message. */ string message; /**< The message text. */ t_direction direction; /**< Direction of the message. */ time_t timestamp; /**< Timestamp of the message. */ t_text_format format; /**< Text format. */ bool has_attachment; /**< Indicates if an attachment is present. */ string attachment_filename; /**< File name of stored attachment. */ t_media attachment_media; /**< Media type of attachment */ string attachment_save_as_name; /**< Suggested 'save as' filename */ /** Constructor. */ t_msg(); /** * Constructor. * Sets the timestamp to the current time. * @param msg [in] The message. * @param dir [in] Direction of the message. * @param fmt [in] Text format of the message. */ t_msg(const string &msg, t_direction dir, t_text_format fmt); /** * Add an attachment to the message. * @param filename [in] File name (full path) of the attachment. * @param media [in] Media type of the attachment. * @param save_as [in] Suggested file name for saving. */ void set_attachment(const string &filename, const t_media &media, const string &save_as); }; /** * Message session. * It's up to the user interface to create a message session and store * all messages in it. The session is just a container to store a * collection of page-mode messages. */ class t_msg_session : public patterns::t_subject { private: t_user *user_config; /**< User profile of the local user. */ t_display_url remote_party; /**< Remote party. */ list messages; /**< Messages sent/received. */ /** Indicates if a new message has been added to the list of message. */ bool new_message_added; bool error_recvd; /**< Indicates that an error has been received. */ string error_msg; /**< Received error message. */ /** Indicates that a delivery notification has been received. */ bool delivery_notification_recvd; /** Received delivery notification. */ string delivery_notification; bool msg_in_flight; /**< Indicates if an outgoing message is in flight. */ /** Indicates if a composing state indication must be sent to the remote party. */ bool send_composing_state; /** Message composing state of the local party. */ t_composing_state local_composing_state; /** Timeout in seconds till the active state of the local party expires. */ time_t local_idle_timeout; /** Timeout in seconds till a refresh of the active state indication must be sent. */ time_t local_refresh_timeout; /** Message composing state of the remote party. */ t_composing_state remote_composing_state; /** Timeout in seconds till the active state of the remote party expires. */ time_t remote_idle_timeout; public: /** * Constructor. * @param u [in] User profile of the local user. */ t_msg_session(t_user *u); /** * Constructor. * @param u [in] User profile of the local user. * @param _remote_party [in] URL of remote party. */ t_msg_session(t_user *u, t_display_url _remote_party); /** Destructor. */ ~t_msg_session(); /** @name getters */ //@{ t_user *get_user(void) const; t_display_url get_remote_party(void) const; const list &get_messages(void) const; t_composing_state get_remote_composing_state(void) const; //@} /** @name setters */ //@{ void set_user(t_user *u); void set_remote_party(const t_display_url &du); void set_send_composing_state(bool enable); //@} /** * Get the last message of the session. * @return The last message. * @throws empty_list_exception There are no messages. */ t_msg get_last_message(void); /** Check if a new message has been added. */ bool is_new_message_added(void) const; /** * Set the display name of the remote party if it is not yet set. * @param display [in] The display name to set. */ void set_display_if_empty(const string &display); /** * Add a received message to the session. * @param msg [in] The message to add. */ void recv_msg(const t_msg &msg); /** * Send a message to the remote party. * The message will be added to the list of messages. * @param message [in] Message to be sent. * @param format [in] Text format of the message. */ void send_msg(const string &message, t_text_format format); /** * Send a message with file attachment to the remote party. * The message will be added to the list of messages. * @param filename [in] Name of file to be sent. * @param media [in] Mime type of the file. * @param subject [in] Subject of message. */ void send_file(const string &filename, const t_media &media, const string &subject); /** * Set the error message of the session. * @param message [in] Error message. * @post @ref error_msg == message * @post @ref error_recvd == true */ void set_error(const string &message); /** * Check if an error has been received. * @return true, if an error has been received. * @return false, otherwise */ bool error_received(void) const; /** * Take the error message from the session. * @return Error message. * @pre @ref error_received() == true * @post @ref error_received() == false */ string take_error(void); /** * Set the delivery notification of the session. * @param notification [in] Delivery notification. * @post @ref delivery_notification == notification * @post @ref delivery_notification_recvd == true */ void set_delivery_notification(const string ¬ification); /** * Check if a delivery notification has been received. * @return true, if an error has been received. * @return false, otherwise */ bool delivery_notification_received(void) const; /** * Take the delivery notification from the session. * @return Delivery notification. * @pre @ref delivery_notification_received() == true * @post @ref delivery_notification_received() == false */ string take_delivery_notification(void); /** * Check if the session matches with a particular user and * remote party. * @param user [in] The user * @param remote_party [in] URL of the remote party * @return true, if there is a match * @return false, otherwise */ bool match(t_user *user, t_url _remote_party); /** * Set the message in flight indicator. * @param in_flight [in] Indicator value to set. */ void set_msg_in_flight(bool in_flight); /** * Check if a message is in flight. * @return true, message is in flight. * @return false, no message is in flight. */ bool is_msg_in_flight(void) const; /** * Set the local composing state. * If the state transitions to a new state, then a composing indication * is sent to the remote party. * The local idle timeout and refresh timeout timers are updated depending * on the current state. * @param state [in] The new local composing state. */ void set_local_composing_state(t_composing_state state); /** * Set the remote composing state. * The remote idle timeout timer is updated depending on the state. * @param state [in] The new remote composing state. * @param idle_timeout [in] The idle timeout value when state == active. * @note When state == idle, then the idle_timout argument has no meaning. */ void set_remote_composing_state(t_composing_state state, time_t idle_timeout = 120); /** * Decrement the timeout values for the local composing state if * the current state is active. * If the idle timeout reaches zero, then the state transitions * to idle, and an idle indication is sent to the remote party. * If the refresh timeout reaches zero, then an active indication * is sent to the remote party. * If the current state is idle, then nothing is done. */ void dec_local_composing_timeout(void); /** Decrement the timeout values for the remote composing state if * the current state is active. * If the idle timeout reaches zero, then the state transitions * to idle. * If the current state is idle, then nothing is done. */ void dec_remote_composing_timeout(void); }; }; // end namespace #endif