diff options
Diffstat (limited to 'src/subscription.h')
-rw-r--r-- | src/subscription.h | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/subscription.h b/src/subscription.h new file mode 100644 index 0000000..67359a0 --- /dev/null +++ b/src/subscription.h @@ -0,0 +1,319 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file + * Subscription (RFC 3265) + */ + +#ifndef _SUBSCRIPTION_H +#define _SUBSCRIPTION_H + +#include <queue> +#include <string> +#include "abstract_dialog.h" + +/** Subscription role */ +enum t_subscription_role { + SR_SUBSCRIBER, /**< Subscriber */ + SR_NOTIFIER /**< Notifier */ +}; + +/** Subscription state */ +enum t_subscription_state { + SS_NULL, /**< Initial state */ + SS_ESTABLISHED, /**< Subscription is in place */ + SS_UNSUBSCRIBING, /**< A request to unsubscribe has been sent */ + SS_UNSUBSCRIBED, /**< An outoging unsubscribe was succesful. Waiting for the final NOTIFY. */ + SS_TERMINATED, /**< Subscription ended */ +}; + +/** + * Convert a subscription state to string. + * @param state [in] Subscription state. + * @return String representation of state. + */ +string t_subscription_state2str(t_subscription_state state); + +/** + * RFC 3265 + * Generic subscription state for subscribers and notifiers + * For each event type this class should be subclassed. + */ +class t_subscription { +protected: + t_subscription_role role; + t_subscription_state state; + + /** + * When a subscriber subscription is terminated, this reason indicates + * the reason conveyed in the NOTIFY, if any. + */ + string reason_termination; + + /** + * If the NOTIFY indicated that the subscriber may retry subscription at + * a later time, then resubscribe_after indicates the number of seconds to wait. + */ + unsigned long resubscribe_after; + + /** Indicates if a re-subscribe may be done after a failure. */ + bool may_resubscribe; + + t_abstract_dialog *dialog; /**< Dialog owning the subscription */ + string event_type; + string event_id; + + /** + * User profile of user using the line + * This is a pointer to the user_config owned by a phone user. + * So this pointer should never be deleted. + */ + t_user *user_config; + + bool pending; /**< Indicates if not active yet. */ + + /** @name Timers */ + //@{ + /** + * For a subscriber the subscription_timeout timer indicates when + * the subscription must be refreshed. + * For a notifier it indicates when the subscription expires. + */ + unsigned short id_subscription_timeout; + + /** + * Indicates if a subscriber automatically refreshes the subscritption + * when the subscription timer expires. If not, then the subscription + * terminates at expiry. + */ + bool auto_refresh; + + /** Subcription expiry for a SUBSCRIBE request */ + unsigned long subscription_expiry; + + /** Default duration for a subscription */ + unsigned long default_duration; + //@} + + /** Protect constructor from being used */ + t_subscription() {}; + + /** Write event type and id to log file */ + void log_event() const; + + /** + * Remove a pending request. Pass one of the client request pointers. + * @param cr [in] Client request to remove. + */ + void remove_client_request(t_client_request **cr); + + /** @name Create requests based on the event type */ + //@{ + /** + * Create a SUBSCRIBE request. + * Creating a SUBSCRIBE is for subscription refreshment/unsubscribe. + * @param expires [in] Expiry time in seconds. + */ + virtual t_request *create_subscribe(unsigned long expires) const; + + /** + * Create a NOTIFY request. + * @param sub_state [in] Subscription state to be put in the Subscription-State header. + * @param reason [in] The reason parameter of the Subscription-State header. + */ + virtual t_request *create_notify(const string &sub_state, + const string &reason = "") const; + //@} + + /** + * Send request. + * @param user_config [in] User profile of user sending the request. + * @param r [in] Request to send. + * @param tuid [in] Transaction user id. + */ + void send_request(t_user *user_config, t_request *r, t_tuid tuid) const; + + /** + * Send response. + * @param user_config [in] User profile of user sending the response. + * @param r [in] Response to send. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + */ + void send_response(t_user *user_config, t_response *r, t_tuid tuid, t_tid tid) const; + + /** + * Start a subscription timer. + * @param timer [in] Type of subscription timer. + * @param duration [in] Duration of timer in ms + */ + void start_timer(t_subscribe_timer timer, long duration); + + /** + * Stop a subscription timer. + * @param timer [in] Type of subscription timer. + */ + void stop_timer(t_subscribe_timer timer); + +public: + /** Pending request */ + t_client_request *req_out; + + /** + * Queue of pending outgoing NOTIFY requests. A next NOTIFY + * will only be sent after the previous NOTIFY has been + * answered. + */ + queue<t_request *> queue_notify; + + /** + * Constructor + * @param _dialog [in] Dialog owning this subscription. SUBSCRIBE and NOTIFY + * requests are sent within this dialog. + * @param _role [in] Role + * @param _event_type [in] Event type of the subscription. + */ + t_subscription(t_abstract_dialog *_dialog, t_subscription_role _role, + const string &_event_type); + + /** + * Constructor + * @param _dialog [in] Dialog owning this subscription. SUBSCRIBE and NOTIFY + * requests are sent within this dialog. + * @param _role [in] Role + * @param _event_type [in] Event type of the subscription. + * @param _event_id [in] Event id. + */ + t_subscription(t_abstract_dialog *_dialog, t_subscription_role _role, + const string &_event_type, const string &_event_id); + + /** Destructor */ + virtual ~t_subscription(); + + /** @name Getters */ + //@{ + t_subscription_role get_role(void) const; + t_subscription_state get_state(void) const; + string get_reason_termination(void) const; + unsigned long get_resubscribe_after(void) const; + bool get_may_resubscribe(void) const; + string get_event_type(void) const; + string get_event_id(void) const; + unsigned long get_expiry(void) const; + //@} + + /** @name Receive requests */ + //@{ + /** + * Reveive SUBSCRIBE request + * @param r [in] Received request. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + * @return The return value indicates if processing is finished. + * This way a subclass can first call the parent class method. + * If the parent indicates that process is finished, then the child + * does not need to further process. + * Note that recv_subscribe returns false if the SUBSCRIBE is valid. The + * subscription timer will be started, but no response is sent. The subclass + * MUST further handle the SUBSCRIBE, i.e. send a response and a NOTIFY. + */ + virtual bool recv_subscribe(t_request *r, t_tuid tuid, t_tid tid); + + /** + * Receive NOTIFY request. + * @param r [in] Received request. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + * @return When the NOTIFY is valid, false is returned. The subclass MUST further + * handle the NOTIFY, i.e. send a response. + */ + virtual bool recv_notify(t_request *r, t_tuid tuid, t_tid tid); + //@} + + /** @name Receive responses */ + //@{ + /** + * Receive NOTIFY/SUBSCRIBE response. + * @param r [in] Received response. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + * @return The return value indicates if processing is finished. + */ + virtual bool recv_response(t_response *r, t_tuid tuid, t_tid tid); + + /** + * Receive NOTIFY response. + * @param r [in] Received response. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + * @return The return value indicates if processing is finished. + */ + virtual bool recv_notify_response(t_response *r, t_tuid tuid, t_tid tid); + + /** + * Receive SUBSCRIBE response. + * @param r [in] Received response. + * @param tuid [in] Transaction user id. + * @param tid [in] Transaction id. + * @return The return value indicates if processing is finished. + */ + virtual bool recv_subscribe_response(t_response *r, t_tuid tuid, t_tid tid); + //@} + + /** + * Process timeouts + * @param timer [in] Type of subscription timer. + * @return The return value indicates if processing is finished. + */ + virtual bool timeout(t_subscribe_timer timer); + + /** + * Match timer id with a running timer. + * @param timer [in] Type of subscription timer. + * @return True, if id matches, otherwise false. + */ + virtual bool match_timer(t_subscribe_timer timer, t_object_id id_timer) const; + + /** + * Does incoming request match with event type and id? + * @param r [in] Request to match. + * @return True if request matches, otherwise false. + */ + virtual bool match(t_request *r) const; + + /** + * Check if subscription is pending. + * @return True if subscription is pending, otherwise false. + */ + bool is_pending(void) const; + + /** + * Subscribe to an event. + * @param expires [in] Expiry in seconds. If expires == 0, then the default duration is used. + */ + virtual void subscribe(unsigned long expires); + + /** Unsubscribe from an event. */ + virtual void unsubscribe(void); + + /** Refresh subscription. */ + virtual void refresh_subscribe(void); +}; + +#endif |