1 /*
2  * localep.h
3  *
4  * Local EndPoint/Connection.
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (c) 2008 Vox Lucida Pty. Ltd.
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24  *
25  * Contributor(s): ______________________________________.
26  *
27  * $Revision: 28040 $
28  * $Author: rjongbloed $
29  * $Date: 2012-07-16 01:23:59 -0500 (Mon, 16 Jul 2012) $
30  */
31 
32 #ifndef OPAL_OPAL_LOCALEP_H
33 #define OPAL_OPAL_LOCALEP_H
34 
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38 
39 #include <opal/buildopts.h>
40 
41 #include <opal/endpoint.h>
42 
43 class OpalLocalConnection;
44 
45 
46 /** Local EndPoint.
47     This class represents an endpoint on the local machine that can receive
48     media via virtual functions.
49  */
50 class OpalLocalEndPoint : public OpalEndPoint
51 {
52     PCLASSINFO(OpalLocalEndPoint, OpalEndPoint);
53   public:
54   /**@name Construction */
55   //@{
56     /**Create a new endpoint.
57      */
58     OpalLocalEndPoint(
59       OpalManager & manager,        ///<  Manager of all endpoints.
60       const char * prefix = "local" ///<  Prefix for URL style address strings
61     );
62 
63     /**Destroy endpoint.
64      */
65     ~OpalLocalEndPoint();
66   //@}
67 
68   /**@name Overrides from OpalEndPoint */
69   //@{
70     /**Get the data formats this endpoint is capable of operating.
71        This provides a list of media data format names that may be used by an
72        OpalMediaStream may be created by a connection from this endpoint.
73 
74        Note that a specific connection may not actually support all of the
75        media formats returned here, but should return no more.
76 
77        The default behaviour returns the most basic media formats, PCM audio
78        and YUV420P video.
79       */
80     virtual OpalMediaFormatList GetMediaFormats() const;
81 
82     /**Set up a connection to a remote party.
83        This is called from the OpalManager::MakeConnection() function once
84        it has determined that this is the endpoint for the protocol.
85 
86        The general form for this party parameter is:
87 
88             [proto:][alias@][transport$]address[:port]
89 
90        where the various fields will have meanings specific to the endpoint
91        type. For example, with H.323 it could be "h323:Fred@site.com" which
92        indicates a user Fred at gatekeeper size.com. Whereas for the PSTN
93        endpoint it could be "pstn:5551234" which is to call 5551234 on the
94        first available PSTN line.
95 
96        The proto field is optional when passed to a specific endpoint. If it
97        is present, however, it must agree with the endpoints protocol name or
98        false is returned.
99 
100        This function usually returns almost immediately with the connection
101        continuing to occur in a new background thread.
102 
103        If false is returned then the connection could not be established. For
104        example if a PSTN endpoint is used and the assiciated line is engaged
105        then it may return immediately. Returning a non-NULL value does not
106        mean that the connection will succeed, only that an attempt is being
107        made.
108 
109        The default behaviour is pure.
110      */
111     virtual PSafePtr<OpalConnection> MakeConnection(
112       OpalCall & call,           ///<  Owner of connection
113       const PString & party,     ///<  Remote party to call
114       void * userData = NULL,    ///<  Arbitrary data to pass to connection
115       unsigned int options = 0,  ///<  options to pass to conneciton
116       OpalConnection::StringOptions * stringOptions  = NULL ///< Options to pass to connection
117     );
118   //@}
119 
120   /**@name Customisation call backs */
121   //@{
122     /**Find a connection that uses the specified token.
123        This searches the endpoint for the connection that contains the token
124        as provided by functions such as MakeConnection(). If not then it
125        attempts to use the token as a OpalCall token and find a connection
126        of the same class.
127       */
128     PSafePtr<OpalLocalConnection> GetLocalConnectionWithLock(
129       const PString & token,     ///<  Token to identify connection
130       PSafetyMode mode = PSafeReadWrite   ///< Lock mode
131     ) { return GetConnectionWithLockAs<OpalLocalConnection>(token, mode); }
132 
133     /**Create a connection for the PCSS endpoint.
134        The default implementation is to create a OpalLocalConnection.
135       */
136     virtual OpalLocalConnection * CreateConnection(
137       OpalCall & call,    ///<  Owner of connection
138       void * userData,    ///<  Arbitrary data to pass to connection
139       unsigned options,   ///< Option bit mask to pass to connection
140       OpalConnection::StringOptions * stringOptions ///< Options to pass to connection
141     );
142 
143     /**Call back just before remote is contacted.
144        If false is returned the call is aborted with EndedByNoAccept.
145 
146        The default implementation returns true.
147       */
148     virtual bool OnOutgoingSetUp(
149       const OpalLocalConnection & connection ///<  Connection having event
150     );
151 
152     /**Call back to indicate that remote is ringing.
153        If false is returned the call is aborted.
154 
155        The default implementation does nothing.
156       */
157     virtual bool OnOutgoingCall(
158       const OpalLocalConnection & connection ///<  Connection having event
159     );
160 
161     /**Call back to indicate that there is an incoming call.
162        Note this function should not block or it will impede the operation of
163        the stack.
164 
165        The default implementation returns true;
166 
167        @return false is returned the call is aborted with status of EndedByLocalBusy.
168       */
169     virtual bool OnIncomingCall(
170       OpalLocalConnection & connection ///<  Connection having event
171     );
172 
173     /**Indicate alerting for the incoming connection.
174        Returns false if the connection token does not correspond to a valid
175        connection.
176       */
177     virtual bool AlertingIncomingCall(
178       const PString & token, ///<  Token of connection to indicate alerting
179       OpalConnection::StringOptions * options = NULL  ///< Optional string optiosn to apply
180     );
181 
182     /**Accept the incoming connection.
183        Returns false if the connection token does not correspond to a valid
184        connection.
185       */
186     virtual bool AcceptIncomingCall(
187       const PString & token, ///<  Token of connection to accept call
188       OpalConnection::StringOptions * options = NULL  ///< Optional string optiosn to apply
189     );
190 
191     /**Reject the incoming connection.
192        Returns false if the connection token does not correspond to a valid
193        connection.
194       */
195     virtual bool RejectIncomingCall(
196       const PString & token,                 ///<  Token of connection to accept call
197       const OpalConnection::CallEndReason & reason = OpalConnection::EndedByAnswerDenied ///<  Reason for rejecting the call
198     );
199 
200     /**Call back to indicate that the remote user has indicated something.
201        If false is returned the call is aborted.
202 
203        The default implementation does nothing.
204       */
205     virtual bool OnUserInput(
206       const OpalLocalConnection & connection, ///<  Connection having event
207       const PString & indication    ///< User input received
208     );
209 
210     /**Call back to get media data for transmission.
211        If false is returned then OnReadMediaData() is called.
212 
213        Care with the handling of real time is rqeuired, see GetSynchronicity
214        for more details.
215 
216        The default implementation returns false.
217       */
218     virtual bool OnReadMediaFrame(
219       const OpalLocalConnection & connection, ///<  Connection for media
220       const OpalMediaStream & mediaStream,    ///<  Media stream data is required for
221       RTP_DataFrame & frame                   ///<  RTP frame for data
222     );
223 
224     /**Call back to handle received media data.
225        If false is returned then OnWriteMediaData() is called.
226 
227        Care with the handling of real time is rqeuired, see GetSynchronicity
228        for more details.
229 
230        The default implementation returns false.
231       */
232     virtual bool OnWriteMediaFrame(
233       const OpalLocalConnection & connection, ///<  Connection for media
234       const OpalMediaStream & mediaStream,    ///<  Media stream data is required for
235       RTP_DataFrame & frame                   ///<  RTP frame for data
236     );
237 
238     /**Call back to get media data for transmission.
239        If false is returned the media stream will be closed.
240 
241        Care with the handling of real time is rqeuired, see GetSynchronicity
242        for more details.
243 
244        The default implementation returns false.
245       */
246     virtual bool OnReadMediaData(
247       const OpalLocalConnection & connection, ///<  Connection for media
248       const OpalMediaStream & mediaStream,    ///<  Media stream data is required for
249       void * data,                            ///<  Data to send
250       PINDEX size,                            ///<  Maximum size of data buffer
251       PINDEX & length                         ///<  Number of bytes placed in buffer
252     );
253 
254     /**Call back to handle received media data.
255        If false is returned the media stream will be closed.
256 
257        Care with the handling of real time is rqeuired, see GetSynchronicity
258        for more details.
259 
260        The default implementation returns false.
261       */
262     virtual bool OnWriteMediaData(
263       const OpalLocalConnection & connection, ///<  Connection for media
264       const OpalMediaStream & mediaStream,    ///<  Media stream data is required for
265       const void * data,                      ///<  Data received
266       PINDEX length,                          ///<  Amount of data available to write
267       PINDEX & written                        ///<  Amount of data written
268     );
269 
270     /**Indicate the synchronous mode for I/O.
271        This indicates that the OnReadMediaXXX and OnWriteMediaXXX functions
272        will execute blocking to the correct real time synchronisation.
273        If GetSynchronicity() returns e_Synchronous, then, for example, when
274        OnWriteMediaData() is sent 320 bytes of PCM data, it will block for
275        20 milliseconds.
276 
277        If GetSynchronicity() returns e_SimulateSyncronous, then the system will try and
278        simulate the correct timing using the operating system sleep function.
279        This is not desirable as this function is notoriously inaccurate, and
280        OPAL does it's best to compensate, but very often there is no other
281        choice.
282 
283        Note, it is important for the correct oeprating of the jitter buffer
284        that one of the above two modes is used for audio.
285 
286        If GetSynchronicity() returns e_Asynchronous, then the system will indicate
287        that blocking is not required in any way. For example, when playing video,
288        this is done as fast as data comes in from the network and there is no
289        real time pacing required.
290       */
291     enum Synchronicity {
292       e_Synchronous,        ///< Functions will block for correct real time
293       e_Asynchronous,       ///< Functions will not block, and do not require any real time handling.
294       e_SimulateSyncronous  ///< Functions wlll not block, but do require real time handling.
295     };
296 
297     /**Indicate the I/O synchronous mode.
298        See Synchronicity for more details.
299 
300        Default behaviour returns m_defaultAudioSynchronicity (initially
301        e_Synchronous) when is audio source or sink,
302        m_defaultVideoSourceSynchronicity (initially e_Synchronous) when a
303        video source, e_Asynchronous in all other cases.
304       */
305     virtual Synchronicity GetSynchronicity(
306       const OpalMediaFormat & mediaFormat,  ///< Media format for stream being opened.
307       bool isSource                         ///< Stream is a a source
308     ) const;
309 
310     /**Get default synchronous mode for audio sources and sinks.
311       */
GetDefaultAudioSynchronicity()312     Synchronicity GetDefaultAudioSynchronicity() const { return m_defaultAudioSynchronicity; }
313 
314     /**Set default synchronous mode for audio sources and sinks.
315       */
SetDefaultAudioSynchronicity(Synchronicity sync)316     void SetDefaultAudioSynchronicity(Synchronicity sync) { m_defaultAudioSynchronicity = sync; }
317 
318     /**Get default synchronous mode for video sources.
319       */
GetDefaultVideoSourceSynchronicity()320     Synchronicity GetDefaultVideoSourceSynchronicity() const { return m_defaultVideoSourceSynchronicity; }
321 
322     /**Set default synchronous mode for video sources.
323       */
SetDefaultVideoSourceSynchronicity(Synchronicity sync)324     void SetDefaultVideoSourceSynchronicity(Synchronicity sync) { m_defaultVideoSourceSynchronicity = sync; }
325 
326     /**Indicate OnAlerting() is be deferred or immediate.
327       */
IsDeferredAlerting()328     bool IsDeferredAlerting() const { return m_deferredAlerting; }
329 
330     /**Indicate OnAlerting() is be deferred or immediate.
331       */
SetDeferredAlerting(bool defer)332     void SetDeferredAlerting(bool defer) { m_deferredAlerting = defer; }
333 
334     /**Indicate AcceptIncomingCall() execution is be deferred or immediate on OnIncomingCall().
335       */
IsDeferredAnswer()336     bool IsDeferredAnswer() const { return m_deferredAnswer; }
337 
338     /**Indicate AcceptIncomingCall() execution is be deferred or immediate on OnIncomingCall().
339       */
SetDeferredAnswer(bool defer)340     void SetDeferredAnswer(bool defer) { m_deferredAnswer = defer; }
341   //@}
342 
343   protected:
344     bool m_deferredAlerting;
345     bool m_deferredAnswer;
346 
347     Synchronicity m_defaultAudioSynchronicity;
348     Synchronicity m_defaultVideoSourceSynchronicity;
349 
350   private:
351     P_REMOVE_VIRTUAL(OpalLocalConnection *, CreateConnection(OpalCall &, void *), 0);
352     P_REMOVE_VIRTUAL(bool, IsSynchronous() const, false);
353 };
354 
355 
356 /** Local connection.
357     This class represents a connection on the local machine that can receive
358     media via virtual functions.
359  */
360 class OpalLocalConnection : public OpalConnection
361 {
362     PCLASSINFO(OpalLocalConnection, OpalConnection);
363   public:
364   /**@name Construction */
365   //@{
366     /**Create a new connection.
367      */
368     OpalLocalConnection(
369       OpalCall & call,              ///<  Owner call for connection
370       OpalLocalEndPoint & endpoint, ///<  Owner endpoint for connection
371       void * userData,              ///<  Arbitrary data to pass to connection
372       unsigned options,             ///< Option bit mask to pass to connection
373       OpalConnection::StringOptions * stringOptions, ///< Options to pass to connection
374       char tokenPrefix = 'L'        ///< Prefix for token generation
375     );
376 
377     /**Destroy connection.
378      */
379     ~OpalLocalConnection();
380   //@}
381 
382   /**@name Overrides from OpalConnection */
383   //@{
384     /**Get indication of connection being to a "network".
385        This indicates the if the connection may be regarded as a "network"
386        connection. The distinction is about if there is a concept of a "remote"
387        party being connected to and is best described by example: sip, h323,
388        iax and pstn are all "network" connections as they connect to something
389        "remote". While pc, pots and ivr are not as the entity being connected
390        to is intrinsically local.
391       */
IsNetworkConnection()392     virtual PBoolean IsNetworkConnection() const { return false; }
393 
394     /// Call back for connection to act on changed string options
395     virtual void OnApplyStringOptions();
396 
397     /**Start an outgoing connection.
398        This function will initiate the connection to the remote entity, for
399        example in H.323 it sends a SETUP, in SIP it sends an INVITE etc.
400 
401        The default behaviour determines if this si incoming or outgoing call
402        by checking if we are party A or B, then does approriate setting up
403        of the conenction, including calling OnOutgoing() or OnIncoming() as
404        appropriate.
405       */
406     virtual PBoolean SetUpConnection();
407 
408     /**Indicate to remote endpoint an alert is in progress.
409        If this is an incoming connection and the AnswerCallResponse is in a
410        AnswerCallDeferred or AnswerCallPending state, then this function is
411        used to indicate to that endpoint that an alert is in progress. This is
412        usually due to another connection which is in the call (the B party)
413        has received an OnAlerting() indicating that its remote endpoint is
414        "ringing".
415 
416        The default behaviour does nothing.
417       */
418     virtual PBoolean SetAlerting(
419       const PString & calleeName,   ///<  Name of endpoint being alerted.
420       PBoolean withMedia            ///<  Open media with alerting
421     );
422 
423     /**Indicate to remote endpoint we are connected.
424 
425        The default behaviour sets the phase to ConnectedPhase, sets the
426        connection start time and then checks if there is any media channels
427        opened and if so, moves on to the established phase, calling
428        OnEstablished().
429 
430        In other words, this method is used to handle incoming calls,
431        and is an indication that we have accepted the incoming call.
432       */
433     virtual PBoolean SetConnected();
434 
435     /**Open a new media stream.
436        This will create a media stream of an appropriate subclass as required
437        by the underlying connection protocol. For instance H.323 would create
438        an OpalRTPStream.
439 
440        The sessionID parameter may not be needed by a particular media stream
441        and may be ignored. In the case of an OpalRTPStream it us used.
442 
443        Note that media streams may be created internally to the underlying
444        protocol. This function is not the only way a stream can come into
445        existance.
446 
447        The default behaviour is pure.
448      */
449     virtual OpalMediaStream * CreateMediaStream(
450       const OpalMediaFormat & mediaFormat, ///<  Media format for stream
451       unsigned sessionID,                  ///<  Session number for stream
452       PBoolean isSource                    ///<  Is a source stream
453     );
454 
455     /**Open source or sink media stream for session.
456       */
457     virtual OpalMediaStreamPtr OpenMediaStream(
458       const OpalMediaFormat & mediaFormat, ///<  Media format to open
459       unsigned sessionID,                  ///<  Session to start stream on
460       bool isSource                        ///< Stream is a source/sink
461     );
462 
463     /**Send a user input indication to the remote endpoint.
464        This sends an arbitrary string as a user indication. If DTMF tones in
465        particular are required to be sent then the SendIndicationTone()
466        function should be used.
467 
468        The default behaviour plays the DTMF tones on the line.
469       */
470     virtual PBoolean SendUserInputString(
471       const PString & value                   ///<  String value of indication
472     );
473   //@}
474 
475   /**@name New operations */
476   //@{
477     /**Call back just before remote is contacted.
478 
479        The default implementation call OpalLocalEndPoint::OnOutgoingSetUp().
480 
481        @return false if the call is to be aborted with EndedByNoAccept.
482       */
483     virtual bool OnOutgoingSetUp();
484 
485     /**Call back to indicate that remote is ringing.
486 
487        The default implementation call OpalLocalEndPoint::OnOutgoingCall().
488 
489        @return false if the call is to be aborted with EndedByNoAccept.
490       */
491     virtual bool OnOutgoing();
492 
493     /**Call back to indicate that there is an incoming call.
494        Note this function should not block or it will impede the operation of
495        the stack.
496 
497        The default implementation call OpalLocalEndPoint::OnIncomingCall().
498 
499        @return false if the call is to be aborted with status of EndedByLocalBusy.
500       */
501     virtual bool OnIncoming();
502 
503     /**Indicate alerting for the incoming connection.
504       */
505     virtual void AlertingIncoming();
506 
507     /**Accept the incoming connection.
508       */
509     virtual void AcceptIncoming();
510   //@}
511 
512   /**@name Member variable access */
513   //@{
514     /// Get user data pointer.
GetUserData()515     void * GetUserData() const  { return m_userData; }
516 
517     /// Set user data pointer.
SetUserData(void * v)518     void SetUserData(void * v)  { m_userData = v; }
519   //@}
520 
521   protected:
522     OpalLocalEndPoint & endpoint;
523     void * m_userData;
524 };
525 
526 
527 /**Local media stream.
528     This class represents a media stream on the local machine that can receive
529     media via virtual functions.
530   */
531 class OpalLocalMediaStream : public OpalMediaStream, public OpalMediaStreamPacing
532 {
533     PCLASSINFO(OpalLocalMediaStream, OpalMediaStream);
534   public:
535   /**@name Construction */
536   //@{
537     /**Construct a new media stream for local system.
538       */
539     OpalLocalMediaStream(
540       OpalLocalConnection & conn,          ///<  Connection for media stream
541       const OpalMediaFormat & mediaFormat, ///<  Media format for stream
542       unsigned sessionID,                  ///<  Session number for stream
543       bool isSource,                       ///<  Is a source stream
544       OpalLocalEndPoint::Synchronicity synchronicity ///< Synchronous mode
545     );
546   //@}
547 
548   /**@name Overrides of OpalMediaStream class */
549   //@{
550     /**Read an RTP frame of data from the source media stream.
551        The default behaviour simply calls ReadData() on the data portion of the
552        RTP_DataFrame and sets the frames timestamp and marker from the internal
553        member variables of the media stream class.
554       */
555     virtual PBoolean ReadPacket(
556       RTP_DataFrame & packet
557     );
558 
559     /**Write an RTP frame of data to the sink media stream.
560        The default behaviour simply calls WriteData() on the data portion of the
561        RTP_DataFrame and and sets the internal timestamp and marker from the
562        member variables of the media stream class.
563       */
564     virtual PBoolean WritePacket(
565       RTP_DataFrame & packet
566     );
567 
568     /**Read raw media data from the source media stream.
569        The default behaviour reads from the OpalLine object.
570       */
571     virtual PBoolean ReadData(
572       BYTE * data,      ///<  Data buffer to read to
573       PINDEX size,      ///<  Size of buffer
574       PINDEX & length   ///<  Length of data actually read
575     );
576 
577     /**Write raw media data to the sink media stream.
578        The default behaviour writes to the OpalLine object.
579       */
580     virtual PBoolean WriteData(
581       const BYTE * data,   ///<  Data to write
582       PINDEX length,       ///<  Length of data to read.
583       PINDEX & written     ///<  Length of data actually written
584     );
585 
586     /**Indicate if the media stream is synchronous.
587        Returns true for LID streams.
588       */
589     virtual PBoolean IsSynchronous() const;
590   //@}
591 
592   protected:
InternalClose()593     virtual void InternalClose() { }
594 
595     OpalLocalEndPoint::Synchronicity m_synchronicity;
596 };
597 
598 
599 #endif // OPAL_OPAL_LOCALEP_H
600 
601 
602 // End of File ///////////////////////////////////////////////////////////////
603