1 /*
2  * Copyright (C) 2002-2003 Fhg Fokus
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. This program is released under
10  * the GPL with the additional exemption that compiling, linking,
11  * and/or using OpenSSL is allowed.
12  *
13  * For a license to use the SEMS software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 /** @file AmSessionContainer.h */
28 #ifndef AmSessionContainer_h
29 #define AmSessionContainer_h
30 
31 #include "AmThread.h"
32 #include "AmSession.h"
33 
34 #include "ampi/MonitoringAPI.h"
35 
36 #include <string>
37 #include <queue>
38 #include <map>
39 
40 using std::string;
41 
42 /**
43  * \brief Centralized session container.
44  *
45  * This is the register for all active and dead sessions.
46  * If has a deamon which wakes up only if it has work.
47  * Then, it kills all dead sessions and try to go to bed
48  * (it cannot sleep if one or more sessions are still alive).
49  */
50 class AmSessionContainer : public AmThread
51 {
52   static AmSessionContainer* _instance;
53 
54   typedef std::queue<AmSession*>      SessionQueue;
55 
56   /** Container for dead sessions */
57   SessionQueue d_sessions;
58   /** Mutex to protect the dead session container */
59   AmMutex      ds_mut;
60 
61   /** is container closed for new sessions? */
62   AmCondition<bool> _container_closed;
63 
64   /** the daemon only runs if this is true */
65   AmCondition<bool> _run_cond;
66 
67   /** We are a Singleton ! Avoid people to have their own instance. */
68   AmSessionContainer();
69 
70 
71   bool enable_unclean_shutdown;
72 
73   /**
74    * Tries to stop the session and queue it destruction.
75    */
76   void stopAndQueue(AmSession* s);
77 
78   /** @see AmThread::run() */
79   void run();
80   /** @see AmThread::on_stop() */
81   void on_stop();
82 
83   bool clean_sessions();
84 
85   typedef std::queue<struct timeval> TimevalQueue;
86 
87   /** Container for cps timevals*/
88   TimevalQueue cps_queue;
89   /** Maximum cps since the lasd getMaxCPS()*/
90   unsigned int max_cps;
91   /** Mutex to protect the cps container */
92   AmMutex      cps_mut;
93 
94   enum { CPS_SAMPLERATE = 5 };
95 
96   unsigned int CPSLimit;
97   unsigned int CPSHardLimit;
98 
99   bool check_and_add_cps();
100 
101  public:
102   static AmSessionContainer* instance();
103 
104   static void dispose();
105 
106   enum AddSessionStatus {
107     ShutDown,
108     Inserted,
109     AlreadyExist
110   };
111 
112   /**
113    * Creates a new session.
114    * @param req local request
115    * @return a new session or NULL on error.
116    */
117   AmSession* createSession(const AmSipRequest& req,
118 			   string& app_name,
119 			   AmArg* session_params = NULL);
120 
121   /**
122    * Adds a session to the container (UAS only).
123    * @return true if the session is new within the container.
124    */
125   AddSessionStatus addSession(const string& callid,
126 			      const string& remote_tag,
127 			      const string& local_tag,
128 			      const string& via_branch,
129 			      AmSession* session);
130 
131   /**
132    * Adds a session to the container.
133    * @return true if the session is new within the container.
134    */
135   AddSessionStatus addSession(const string& local_tag,
136 			      AmSession* session);
137 
138   /**
139    * Constructs a new session and adds it to the active session container.
140    * @param req client's request
141    */
142   void startSessionUAS(AmSipRequest& req);
143 
144   /**
145    * Constructs a new session and adds it to the active session container.
146    * @param req client's request
147    */
148   string startSessionUAC(const AmSipRequest& req,
149 			 string& app_name,
150 			 AmArg* session_params = NULL);
151 
152   /**
153    * Detroys a session.
154    */
155   void destroySession(AmSession* s);
156 
157   /**
158    * post an event into the event queue of the identified dialog.
159    * @return false if session doesn't exist
160    */
161   bool postEvent(const string& callid,
162 		 const string& remote_tag,
163 		 const string& via_branch,
164 		 AmEvent* event);
165 
166   /**
167    * post a generic event into the event queue of the identified dialog.
168    * sess_key is local_tag (to_tag)
169    * note: if hash_str is known, use
170    *          postGenericEvent(hash_str,sess_key,event);
171    *       for better performance.
172    * @return false if session doesn't exist
173    */
174   bool postEvent(const string& local_tag, AmEvent* event);
175 
176   /**
177    * broadcasts a server shutdown system event to all sessions
178    */
179   void  broadcastShutdown();
180 
181   /** enable unclean shutdown (will not broadcastShutdown event) */
182   void enableUncleanShutdown();
183 
184   /** Set the maximum number of calls per second to be accepted */
185   void setCPSLimit(unsigned int limit);
186 
187   /** Set the maximum number of calls per second to be accepted as a percent
188    * of the current CPS. Intented to be used by the components. 0 means turning off
189    * the soft limit.
190    */
191   void setCPSSoftLimit(unsigned int percent);
192 
193   /** Return the maximum number of calls per second to be accepted */
194   pair<unsigned int, unsigned int> getCPSLimit();
195 
196   /**
197    * Gets the timeaverage of calls per second in the last CPS_SAMPLERATE sec window
198    */
199   unsigned int getAvgCPS();
200   /**
201    * Gets the maximum of calls per second since last query
202    */
203   unsigned int getMaxCPS();
204 
205   void initMonitoring();
206 
207   _MONITORING_DEFINE_INTERFACE;
208 
209 };
210 
211 #endif
212