mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
10 KiB
296 lines
10 KiB
/*
|
|
* $Id: AmSIPEventDaemon.h,v 1.3.2.1 2005/09/02 13:47:46 rco Exp $
|
|
*
|
|
* Copyright (C) 2002-2003 Fhg Fokus
|
|
*
|
|
* This file is part of sems, a free SIP media server.
|
|
*
|
|
* sems 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
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* sems 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
|
|
*/
|
|
|
|
#ifndef AM_SIP_EVENT_DAEMON_H_
|
|
#define AM_SIP_EVENT_DAEMON_H_
|
|
|
|
#include "sys/time.h"
|
|
|
|
#include "AmThread.h"
|
|
#include "AmEventQueue.h"
|
|
#include "AmRequest.h"
|
|
#include "AmSession.h"
|
|
#include <string>
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <utility>
|
|
|
|
struct AmSubscription {
|
|
|
|
enum SubstateValue { Active, Pending, Terminated };
|
|
enum EventReasonValue { NoReason, Deactivated, Probation,
|
|
Rejected, Timeout, Giveup, Noresource };
|
|
|
|
const std::string getReasonString(const EventReasonValue& r) const;
|
|
|
|
AmRequestUAS req; // the request that triggered this
|
|
std::string ID; // the subscription ID
|
|
time_t created;
|
|
int expires;
|
|
SubstateValue subscriptionState;
|
|
EventReasonValue reason;
|
|
int retry_after;
|
|
|
|
std::string hash_str;
|
|
std::string sess_key;
|
|
|
|
AmSubscription(const AmRequestUAS& req_, const std::string& hash_str_,
|
|
const std::string& sess_key_, std::string subID,
|
|
int sipExpires, const SubstateValue& subState,
|
|
const EventReasonValue& subReason, int retry_after)
|
|
: req(req_), hash_str(hash_str_), sess_key(sess_key_),
|
|
ID(subID), expires(sipExpires), subscriptionState(subState),
|
|
reason(subReason), retry_after(retry_after)
|
|
{ created = time(NULL); }
|
|
|
|
bool timeout() {
|
|
return (!expires) || ((int)time(NULL) >= expires + (int) created);
|
|
}
|
|
|
|
void checkTimeout() {
|
|
if (timeout()) {
|
|
subscriptionState = Terminated;
|
|
reason = Timeout;
|
|
}
|
|
}
|
|
|
|
int getExpires() {
|
|
int ret = expires + (int) created - (int)time(NULL);
|
|
if (ret<0)
|
|
return 0;
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
void refresh(int sipExpires, const SubstateValue& subState,
|
|
const EventReasonValue& subReason, int retry_after_) {
|
|
expires = sipExpires;
|
|
subscriptionState = subState;
|
|
reason = subReason;
|
|
retry_after = retry_after_;
|
|
created = (int) time(NULL);
|
|
}
|
|
};
|
|
|
|
|
|
class AmResourceState {
|
|
std::string r_state;
|
|
std::string default_content_type;
|
|
public:
|
|
|
|
AmResourceState()
|
|
: default_content_type("text/plain") { }
|
|
|
|
virtual ~AmResourceState() { }
|
|
|
|
AmResourceState(std::string initial_state)
|
|
: r_state(initial_state),
|
|
default_content_type("text/plain") { }
|
|
|
|
/**
|
|
* change the state for a registered resource.
|
|
* @param new_state [in] the new state to be changed
|
|
* @return true if state has changed so notifications should be sent
|
|
*/
|
|
virtual bool setState(AmResourceState* new_state);
|
|
|
|
/**
|
|
* set Authorization for Request (SUBSCRIBE)
|
|
* for subscriptionState == [Pending, Terminated]
|
|
* set EventReasonValue (see RFC3256 3.2.4. )
|
|
*
|
|
* @param req [in] request (subscribe or implicit refer)
|
|
* @param retry_after [out] < 0 (or no change) means:
|
|
* do not include retry-after information
|
|
* @param expires [in, out] expires value, in: requested, out: granted
|
|
*/
|
|
virtual void getAuthorization(const AmRequestUAS& req, AmSubscription::SubstateValue& subscriptionState,
|
|
AmSubscription::EventReasonValue& ReasonValue, int& expires, int& retry_after);
|
|
|
|
virtual void refreshAuthorization(AmSubscription* existingSubscription, const AmRequestUAS& req,
|
|
AmSubscription::SubstateValue& subscriptionState,
|
|
AmSubscription::EventReasonValue& ReasonValue, int& expires, int& retry_after);
|
|
|
|
/**
|
|
* get the state, to be sent to subscription subs
|
|
* @param subs [in] the subscription
|
|
* @param content_type [out] content type for NOTIFY
|
|
*/
|
|
virtual std::string getState(const AmSubscription* subs, std::string& content_type);
|
|
};
|
|
|
|
|
|
class AmSIPEvent : public AmEvent {
|
|
public:
|
|
AmRequestUAS request;
|
|
std::string hash_str;
|
|
std::string sess_key;
|
|
|
|
enum EventType { Subscribe };
|
|
AmSIPEvent(EventType event_type, const AmRequestUAS& request,
|
|
const std::string& hash_str, const std::string& sess_key);
|
|
std::string getEventPackage();
|
|
std::string getEventPackageParameter(const std::string parameterName);
|
|
std::string getResourceID() { return request.cmd.user; }
|
|
void dbgEvent();
|
|
};
|
|
|
|
class AmResourceEvent : public AmEvent {
|
|
public:
|
|
enum EventType { RegisterResource, ChangeResourceState, RemoveResource };
|
|
|
|
EventType type;
|
|
std::string eventPackage;
|
|
std::string resourceID;
|
|
AmResourceState* resourceState;
|
|
|
|
AmResourceEvent(EventType type, std::string eventPackage,
|
|
std::string resourceID, AmResourceState* resourceState);
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* RFC3265 SIP Event Notifiation Deamon.
|
|
* It is designed as a singleton using a queue to get his work.
|
|
* It wakes up only if there is anything to do.
|
|
*/
|
|
|
|
class AmSIPEventDaemon : public AmThread,
|
|
public AmEventQueue, AmEventHandler
|
|
{
|
|
static AmSIPEventDaemon* _instance;
|
|
|
|
void run();
|
|
void on_stop();
|
|
|
|
// some typedefs for the resource states
|
|
typedef std::map<std::string, AmResourceState* > ResourceStateMap; // resourceID and state
|
|
typedef std::map<std::string, ResourceStateMap > EventPackageMap; // package name and resourcemap
|
|
typedef ResourceStateMap::iterator ResourceStateMapIter;
|
|
typedef EventPackageMap::iterator EventPackageMapIter;
|
|
|
|
|
|
// some typedefs for the subscription table
|
|
typedef std::vector<AmSubscription* > SubscriptionTable; // the subscriptions
|
|
typedef std::map<std::string, SubscriptionTable > SubscriptionIDMap; // resourceID and subscriptions
|
|
typedef std::map<std::string, SubscriptionIDMap > PackageSubscriptionMap; // package name and subscription map
|
|
|
|
typedef SubscriptionTable::iterator SubscriptionTableIter;
|
|
typedef std::map<std::string, std::vector<AmSubscription* > >::iterator SubscriptionIDMapIter;
|
|
typedef std::map<std::string, SubscriptionIDMap >::iterator PackageSubscriptionMapIter;
|
|
|
|
/** container for active subscriptions */
|
|
PackageSubscriptionMap a_subscriptions;
|
|
|
|
/** the resource states */
|
|
EventPackageMap res_states;
|
|
|
|
/** the daemon only runs if this is true */
|
|
AmCondition<bool> _run_cond;
|
|
|
|
/** add a subscription to the container */
|
|
void addSubscription(const std::string& eventPackage,const std::string& resourceID,
|
|
AmSubscription* subs);
|
|
|
|
/** get a subscription by the dialog identifiers and the subscription ID */
|
|
AmSubscription* getSubscription(const std::string& hash_str, const std::string& sess_key,
|
|
const std::string& subscriptionID);
|
|
|
|
/** get a list of subscriptions to a resource and dialog package */
|
|
bool filterSubscriptions(const std::string& eventPackage, const std::string& resourceID,
|
|
std::vector<AmSubscription*>& result);
|
|
|
|
/** remove a subscription from the container */
|
|
bool removeSubscription(const std::string& resourceID, const std::string& eventPackage,
|
|
const std::string& subscriptionID);
|
|
|
|
AmResourceState* getResourceState(std::string eventPackage, std::string resourceID);
|
|
|
|
void onSubscribe(AmSIPEvent* event);
|
|
void onRegisterResource(AmResourceEvent* event);
|
|
void onChangeResourceState(AmResourceEvent* event);
|
|
void onUACRequestStatus(AmRequestUACStatusEvent* event);
|
|
void onRemoveResource(AmResourceEvent* event);
|
|
|
|
std::string getNewId();
|
|
AmCmd sendNotify(std::string eventPackage, AmSubscription* subs, AmResourceState* r_state);
|
|
|
|
std::string getEventPackageParameter(AmCmd& cmd, const std::string parameterName);
|
|
std::string getEventPackage(AmCmd& cmd);
|
|
|
|
public:
|
|
AmSIPEventDaemon();
|
|
~AmSIPEventDaemon();
|
|
|
|
static AmSIPEventDaemon* instance();
|
|
|
|
/** process the events from eventqueue */
|
|
void process(AmEvent* event);
|
|
|
|
/**
|
|
* register a resource
|
|
*
|
|
* @param eventPackage [in] event package name
|
|
* @param resourceID [in] resource to be registered
|
|
* @param resourceState [in] (initial) state of the resource
|
|
* eventd takes ownership of resource state!
|
|
*/
|
|
void registerResource(const std::string& eventPackage, const std::string& resourceID,
|
|
AmResourceState* resourceState);
|
|
|
|
/**
|
|
* change the state of a resource
|
|
* will send notifies if a subscription exists
|
|
* @param eventPackage [in] event package name
|
|
* @param resourceID [in] resource
|
|
* @param resourceState [in] state of the resource
|
|
* eventd takes ownership of resource state!
|
|
*/
|
|
void changeResourceState(const std::string& eventPackage, const std::string& resourceID,
|
|
AmResourceState* resourceState);
|
|
|
|
/**
|
|
* remove a resource
|
|
* will send notifies if a subscription exists
|
|
* @param eventPackage [in] event package name
|
|
* @param resourceID [in] resource to be removed
|
|
*/
|
|
void removeResource(const std::string& eventPackage, const std::string& resourceID);
|
|
|
|
/**
|
|
* post a SIP request (SUBSCRIBE, REFER not yet implemented))
|
|
* @return true if subscription found
|
|
* @return false if subscription not found
|
|
*/
|
|
bool postRequest(const std::string& hash_str,std::string& sess_key,
|
|
AmRequestUAS* req);
|
|
};
|
|
#endif
|