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 
28 #ifndef _AmSession_h_
29 #define _AmSession_h_
30 
31 #include "AmRtpStream.h"
32 #include "AmThread.h"
33 #include "AmEventQueue.h"
34 #include "AmRtpAudio.h"
35 #include "AmDtmfDetector.h"
36 #include "AmSipMsg.h"
37 #include "AmSipHeaders.h"
38 #include "AmSipDialog.h"
39 #include "AmSipEvent.h"
40 #include "AmApi.h"
41 #include "AmSessionEventHandler.h"
42 #include "AmMediaProcessor.h"
43 
44 #include "AmZRTP.h"
45 
46 #include <string>
47 #include <vector>
48 #include <queue>
49 #include <map>
50 using std::string;
51 using std::vector;
52 
53 class AmSessionFactory;
54 class AmDtmfEvent;
55 
56 /** @file AmSession.h */
57 
58 /* definition imported from Ser parser/msg_parser.h */
59 #define FL_FORCE_ACTIVE 2
60 
61 
62 /**
63  * \brief Implements the default behavior of one session
64  *
65  * The session is identified by Call-ID, From-Tag and To-Tag.
66  */
67 class AmSession :
68   public virtual AmObject,
69 #ifndef SESSION_THREADPOOL
70   public AmThread,
71 #endif
72   public AmEventQueue,
73   public AmEventHandler,
74   public AmSipDialogEventHandler,
75   public AmMediaSession,
76   public AmDtmfSink
77 {
78   AmMutex      audio_mut;
79 
80 protected:
81   vector<SdpPayload *>  m_payloads;
82   //bool         negotiate_onreply;
83 
84   friend class AmRtpAudio;
85 
86   /** get new RTP format for the session */
87   //virtual AmAudioRtpFormat* getNewRtpFormat();
88 
89 private:
90   AmDtmfDetector   m_dtmfDetector;
91   AmDtmfEventQueue m_dtmfEventQueue;
92   bool m_dtmfDetectionEnabled;
93 
94   enum ProcessingStatus {
95     SESSION_PROCESSING_EVENTS = 0,
96     SESSION_WAITING_DISCONNECTED,
97     SESSION_ENDED_DISCONNECTED
98   };
99   ProcessingStatus processing_status;
100 
101 #ifndef SESSION_THREADPOOL
102   /** @see AmThread::run() */
103   void run();
104   void on_stop();
105 #else
106 public:
107   void start();
108   bool is_stopped();
109 
110 private:
111   void stop();
112   void* _pid;
113 #endif
114 
115   static void session_started();
116   static void session_stopped();
117 
118   static volatile unsigned int session_num;
119   static volatile unsigned int session_count;
120   static volatile unsigned int max_session_num;
121   static volatile unsigned long long avg_session_num;
122   static AmMutex session_num_mut;
123 
124   friend class AmMediaProcessor;
125   friend class AmMediaProcessorThread;
126   friend class AmSessionContainer;
127   friend class AmSessionFactory;
128   friend class AmSessionProcessorThread;
129 
130   std::unique_ptr<AmRtpAudio> _rtp_str;
131 
132   /** Application parameters passed through P-App-Param HF */
133   map<string,string> app_params;
134 
135   /** Sets the application parameters from the original request */
136   void setAppParams(const AmSipRequest& req);
137 
138 protected:
139 
140   AmCondition<bool> sess_stopped;
141 
142   /** this is the group the media is processed with
143       - by default local tag */
144   string callgroup;
145 
146   /** do accept early session? */
147   bool accept_early_session;
148 
149   /** Local IP interface to be used for RTP streams */
150   int rtp_interface;
151 
152   /** Session event handlers (ex: session timer, UAC auth, etc...) */
153   vector<AmSessionEventHandler*> ev_handlers;
154 
155   AmAudio *input, *output;
156 
157   virtual AmSipDialog* createSipDialog();
158 
159   /** process pending events,
160       @return whether everything went smoothly */
161   virtual bool processEventsCatchExceptions();
162 
163   /** @return whether startup was successful */
164   bool startup();
165 
166   /** @return whether session continues running */
167   virtual bool processingCycle();
168 
169   /** clean up session */
170   void finalize();
171 
172 public:
173 
174   enum SessionRefreshMethod {
175     REFRESH_REINVITE = 0,      // use reinvite
176     REFRESH_UPDATE,            // use update
177     REFRESH_UPDATE_FB_REINV    // use update or fallback to reinvite
178   };
179   /** currently selected session refresh method */
180   SessionRefreshMethod refresh_method;
181 
182   /** update selected session refresh method from remote capabilities */
183   void updateRefreshMethod(const string& headers);
184 
185   AmRtpAudio* RTPStream();
hasRtpStream()186   bool hasRtpStream() { return _rtp_str.get() != NULL; }
187 
188   string       remote_rtp_mux_ip;
189   unsigned short remote_rtp_mux_port;
190 
getRtpMuxRemoteIP()191   string getRtpMuxRemoteIP() { return remote_rtp_mux_ip; }
getRtpMuxRemotePort()192   unsigned short getRtpMuxRemotePort() { return remote_rtp_mux_port; }
193 
194 #ifdef WITH_ZRTP
195   AmZRTPSessionState zrtp_session_state;
196 
197   /** must be set before session is started! i.e. in constructor */
198   bool enable_zrtp;
199 
200 #endif
201 
202   AmSipDialog* dlg;
203 
204   /**
205    * \brief Exception occured in a Session
206    *
207    * Session (creation) should be aborted and replied with code/reason.
208    */
209   struct Exception {
210     int code;
211     string reason;
212     string hdrs;
codeException213     Exception(int c, string r, string h="") : code(c), reason(r), hdrs(h) {}
214   };
215 
216   /**
217    * Session constructor.
218    */
219   AmSession(AmSipDialog* dlg=NULL);
220 
221   virtual ~AmSession();
222 
223   /**
224    * @see AmEventHandler
225    */
226   virtual void process(AmEvent*);
227 
228   /**
229    * add a handler which will be called
230    * for all events in session
231    *
232    * @see AmSessionEventHandler
233    */
234   void addHandler(AmSessionEventHandler*);
235 
236   /* ----         media processing                    ---- */
237 
238   /** start processing media - add to media processor */
239   void startMediaProcessing();
240 
241   /** stop processing media - remove from media processor */
242   void stopMediaProcessing();
243 
244   /**
245    * Set the call group for this call; calls in the same
246    * group are processed by the same media processor thread.
247    *
248    * Note: this must be set before inserting
249    * the session to the MediaProcessor!
250    */
251   void setCallgroup(const string& cg);
252 
253   /** get the callgroup @return callgroup */
254   string getCallgroup();
255 
256   /**
257    * change the callgroup
258    *
259    * This function removes the session from
260    * the media processor and adds it again.
261    */
262   void changeCallgroup(const string& cg);
263 
264   /* ----         audio input and output        ---- */
265 
266   /**
267    * Lock audio input & output
268    * (inclusive RTP stream)
269    */
270   void lockAudio();
271 
272   /**
273    * Unlock audio input & output
274    * (inclusive RTP stream)
275    */
276   void unlockAudio();
277 
278   /**
279    * Audio input getter .
280    * Note: audio must be locked!
281    */
getInput()282   AmAudio* getInput() { return input; }
283   /**
284    * Audio output getter.
285    * Note: audio must be locked!
286    */
getOutput()287   AmAudio* getOutput() { return output; }
288 
289   /**
290    * Audio input & output set methods.
291    * Note: audio will be locked by the methods.
292    */
293   void setInput(AmAudio* in);
294   void setOutput(AmAudio* out);
295   void setInOut(AmAudio* in, AmAudio* out);
296 
297   /** checks if input/output is set, might be overidden! */
298   virtual bool isAudioSet();
299 
300   /**
301    * Clears input & ouput (no need to lock)
302    */
303   virtual void clearAudio();
304 
305   /** setter for rtp_str->mute */
setMute(bool mute)306   void setMute(bool mute) { RTPStream()->mute = mute; }
307 
308   /** setter for rtp_str->receiving */
setReceiving(bool receive)309   void setReceiving(bool receive) { RTPStream()->setReceiving(receive); }
310 
311   /** setter for rtp_str->force_receive_dtmf*/
setForceDtmfReceiving(bool receive)312   void setForceDtmfReceiving(bool receive) { RTPStream()->force_receive_dtmf = receive; }
313 
314   /* ----         SIP dialog attributes                  ---- */
315 
316   /** Gets the Session's call ID */
317   const string& getCallID() const;
318 
319   /** Gets the Session's remote tag */
320   const string& getRemoteTag()const ;
321 
322   /** Gets the Session's local tag */
323   const string& getLocalTag() const;
324 
325   /** Gets the branch param of the first via in the original INVITE*/
326   const string& getFirstBranch() const;
327 
328   /** Sets the Session's local tag if not set already */
329   void setLocalTag();
330 
331   /** Sets the Session's local tag */
332   void setLocalTag(const string& tag);
333 
334   /** Sets the URI for the session */
335   void setUri(const string& uri);
336 
337   /* ----         RTP stream attributes                  ---- */
338 
339   /** Gets the current RTP payload */
340   const vector<SdpPayload*>& getPayloads();
341 
342   /** Gets the port number of the remote part of the session */
343   int getRPort();
344 
345   /* ----         Call control                         ---- */
346 
347   /** refresh the session - re-INVITE or UPDATE*/
348   virtual bool refresh(int flags = 0);
349 
350   /** send an UPDATE in the session */
351   virtual int sendUpdate(const AmMimeBody* body, const string &hdrs);
352 
353   /** send a Re-INVITE (if connected) */
354   virtual int sendReinvite(bool updateSDP = true, const string& headers = "",
355 			   int flags = 0);
356 
357   /** send an INVITE */
358   virtual int sendInvite(const string& headers = "");
359 
360   /** set the session on/off hold */
361   virtual void setOnHold(bool hold);
362 
363   /** request the remote end to set the session on/off hold */
364   virtual void setRemoteHold(bool remote_hold);
365 
366   /** update UAC trans state reference from old_cseq to new_cseq
367       e.g. if uac_auth or session_timer have resent a UAC request
368    */
updateUACTransCSeq(unsigned int old_cseq,unsigned int new_cseq)369   virtual void updateUACTransCSeq(unsigned int old_cseq, unsigned int new_cseq) { }
370 
371   /* ----         Householding                              ---- */
372 
373   /**
374    * Get a session parameter ('P-App-Param' HF, etc...)
375    */
376   string getAppParam(const string& param_name) const;
377 
378   /**
379    * Destroy the session.
380    * It causes the session to be erased from the active session list
381    * and added to the dead session list.
382    * @see AmSessionContainer
383    */
384   virtual void destroy();
385 
386   /**
387    * Signals the session it should stop.
388    * This will cause the session to be able
389    * to exit the main loop.
390    * If wakeup is set, a bogus event will
391    * be sent to wake up the session.
392    */
393   virtual void setStopped(bool wakeup = false);
394 
395   /**
396    * Has the session already been stopped ?
397    */
getStopped()398   bool getStopped() { return sess_stopped.get(); }
399 
400   /* ----         Statistics                    ---- */
401   /**
402    * Gets the number of running sessions
403    */
404   static unsigned int getSessionNum();
405   /**
406    * Gets the number of sessions since last startup
407    */
408   static unsigned int getSessionCount();
409   /**
410    * Gets the maximum of running sessions since last query
411    */
412   static unsigned int getMaxSessionNum();
413   /**
414    * Gets the average of running sessions since last query
415    */
416   static unsigned int getAvgSessionNum();
417 
418   /* ----         DTMF                          ---- */
419   /**
420    * Entry point for DTMF events
421    */
422   void postDtmfEvent(AmDtmfEvent *);
423 
424   void setInbandDetector(Dtmf::InbandDetectorType t);
isDtmfDetectionEnabled()425   bool isDtmfDetectionEnabled() { return m_dtmfDetectionEnabled; }
setDtmfDetectionEnabled(bool e)426   void setDtmfDetectionEnabled(bool e) { m_dtmfDetectionEnabled = e; }
427   void putDtmfAudio(const unsigned char *buf, int size, unsigned long long system_ts);
428 
429   /**
430    * send a DTMF as RTP payload (RFC4733)
431    * @param event event ID (e.g. key press), see rfc
432    * @param duration_ms duration in milliseconds
433    */
434   void sendDtmf(int event, unsigned int duration_ms);
435 
436   /* ---- general purpose application level timers ------------ */
437 
438   /** Deprecated: check for support of timers
439     @return always true
440    */
441   static bool timersSupported();
442 
443   /**
444      set a Timer
445      @param timer_id the ID of the timer (<0 for system timers)
446      @param timeout timeout in seconds (fractal value allowed)
447      @return true on success
448   */
449   virtual bool setTimer(int timer_id, double timeout);
450 
451   /**
452      remove a Timer
453      @param timer_id the ID of the timer (<0 for system timers)
454      @return true on success
455   */
456   virtual bool removeTimer(int timer_id);
457 
458   /**
459      remove all Timers
460      @return true on success
461      Note: this doesn't clear timer events already in the
462            event queue
463   */
464   virtual bool removeTimers();
465 
466   /* ---------- event handlers ------------------------- */
467 
468   /** DTMF event handler for apps to use*/
469   virtual void onDtmf(int event, int duration);
470 
471   /**
472    * onStart will be called before everything else.
473    */
onStart()474   virtual void onStart() {}
475 
476   /**
477    * onStop will be called once session is marked to be stopped (called only
478    * once).
479    */
onStop()480   virtual void onStop() {}
481 
482   /**
483    * onInvite will be called if an INVITE or re-INVITE
484    * has been received for the session.
485    */
486   virtual void onInvite(const AmSipRequest& req);
487 
488   /**
489    * onOutgoingInvite will be called if an INVITE
490    * is sent in the session.
491    */
onOutgoingInvite(const string & headers)492   virtual void onOutgoingInvite(const string& headers) { }
493 
494   /**
495    * onCancel will be called if a CANCEL for a running
496    * dialog has been received. At this point, the CANCEL
497    * transaction has been replied with 200.
498    *
499    * A normal plug-in does not have to do anything special,
500    * as normal dialogs are immediatly replied with 200
501    * or error code.
502    *
503    * Note: You are still responsible for responding the
504    *       initial transaction.
505    */
506   virtual void onCancel(const AmSipRequest& req);
507 
508   /**
509    * onRinging will be called after 180 is received.
510    * If local audio is set up, session is added to media processor.
511    */
onRinging(const AmSipReply & reply)512   virtual void onRinging(const AmSipReply& reply) {}
513 
514   /**
515    * onBye is called whenever a BYE request is received.
516    */
517   virtual void onBye(const AmSipRequest& req);
518 
519   /** remote side is unreachable - 408/481 reply received */
520   virtual void onRemoteDisappeared(const AmSipReply&);
521 
522   /** Entry point for SIP Requests   */
523   virtual void onSipRequest(const AmSipRequest& req);
524 
525   /** Entry point for SIP Replies   */
526   virtual void onSipReply(const AmSipRequest& req, const AmSipReply& reply,
527 			  AmBasicSipDialog::Status old_dlg_status);
528 
529   /** 2xx reply has been received for an INVITE transaction */
530   virtual void onInvite2xx(const AmSipReply& reply);
531 
532   virtual void onInvite1xxRel(const AmSipReply &);
533 
534   /** answer for a locally sent PRACK is received */
535   virtual void onPrack2xx(const AmSipReply &);
536 
537   virtual void onFailure();
538 
539   virtual void onNoAck(unsigned int cseq);
540   virtual void onNoPrack(const AmSipRequest &req, const AmSipReply &rpl);
541 
542   /**
543    * Entry point for Audio events
544    */
545   virtual void onAudioEvent(AmAudioEvent* audio_ev);
546 
547   /**
548    * entry point for system events
549    */
550   virtual void onSystemEvent(AmSystemEvent* ev);
551 
552 #ifdef WITH_ZRTP
553   /**
554    * ZRTP events @see ZRTP
555    */
556   virtual void onZRTPProtocolEvent(zrtp_protocol_event_t event, zrtp_stream_t *stream_ctx);
557   virtual void onZRTPSecurityEvent(zrtp_security_event_t event, zrtp_stream_t *stream_ctx);
558 #endif
559 
560   /** This callback is called if RTP timeout encountered */
561   virtual void onRtpTimeout();
562 
563   /** This callback is called if session
564       timeout encountered (session timers) */
565   virtual void onSessionTimeout();
566 
567   /* Called by AmSipDialog when a request is sent */
568   virtual void onSendRequest(AmSipRequest& req, int& flags);
569 
570   /** Called by AmSipDialog when a reply is sent */
571   virtual void onSendReply(const AmSipRequest& req, AmSipReply& reply, int& flags);
572 
573   /** Hook called when an SDP offer is required */
574   virtual bool getSdpOffer(AmSdp& offer);
575 
576   /** Hook called when an SDP offer is required */
577   virtual bool getSdpAnswer(const AmSdp& offer, AmSdp& answer);
578 
579   /** Hook called when an SDP OA transaction has been completed */
580   virtual int onSdpCompleted(const AmSdp& offer, const AmSdp& answer);
581 
582   /** Hook called when an early session starts (SDP OA completed + dialog in early state) */
583   virtual void onEarlySessionStart();
584 
585   /** Hook called when the session creation is completed (INV trans replied with 200) */
586   virtual void onSessionStart();
587 
588   /**
589    * called in the session thread before the session is destroyed,
590    * i.e. after the main event loop has finished
591    */
onBeforeDestroy()592   virtual void onBeforeDestroy() { }
593 
594   // The IP address to put as c= in SDP bodies
595   string advertisedIP(int addrType = AT_NONE);
596 
597   // IP address used to bind the RTP socket
598   string localMediaIP(int addrType = AT_NONE);
599 
600   /** format session id for debugging */
601   string sid4dbg();
602 
603   /**
604    * Creates a new Id which can be used within sessions.
605    */
606   static string getNewId();
607 
608   /* ----------------- media processing interface ------------------- */
609 
610 public:
611   virtual int readStreams(unsigned long long ts, unsigned char *buffer);
612   virtual int writeStreams(unsigned long long ts, unsigned char *buffer);
clearRTPTimeout()613   virtual void clearRTPTimeout() { RTPStream()->clearRTPTimeout(); }
614   virtual void processDtmfEvents();
615 
616   /**
617    * Call-backs used by RTP stream(s)
618    *
619    * Note: these methods will be called from the RTP receiver thread.
620    */
onBeforeRTPRelay(AmRtpPacket * p,sockaddr_storage * remote_addr)621   virtual bool onBeforeRTPRelay(AmRtpPacket* p, sockaddr_storage* remote_addr)
622   { return true; }
623 
onAfterRTPRelay(AmRtpPacket * p,sockaddr_storage * remote_addr)624   virtual void onAfterRTPRelay(AmRtpPacket* p, sockaddr_storage* remote_addr) {}
625 
626   int getRtpInterface();
627   void setRtpInterface(int _rtp_interface);
628 };
629 
RTPStream()630 inline AmRtpAudio* AmSession::RTPStream() {
631   if (NULL == _rtp_str.get()) {
632     DBG("creating RTP stream instance for session [%p]\n",
633 	this);
634     _rtp_str.reset(new AmRtpAudio(this,rtp_interface));
635   }
636   return _rtp_str.get();
637 }
638 
639 
640 #endif
641 
642 /** EMACS **
643  * Local variables:
644  * mode: c++
645  * c-basic-offset: 2
646  * End:
647  */
648 
649