Revision
15643
Author
joshrivers
Date
2009-11-23 17:22:27 -0600 (Mon, 23 Nov 2009)

Log Message

Modifications to CoreSession and ManagedSession and related code to match renamed members.
Added mockable interface for ManagedSession.
Added mockable interface for Event.
Added wrapper for EventConsumer with simplified, mockable interface.

Modified Paths

Diff

Modified: freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs (15642 => 15643)


--- freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs	2009-11-23 23:19:42 UTC (rev 15642)
+++ freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs	2009-11-23 23:22:27 UTC (rev 15643)
@@ -66,7 +66,7 @@
         }
 
         ChannelVariables _variables; // Set on ManagedSession init
-        public ChannelVariables Variables {
+        public IChannelVariables Variables {
             get {
                 if (_variables == null) {
                     _variables = new ChannelVariables(this);
@@ -75,8 +75,49 @@
             }
         }
 
+        public interface IChannelVariables
+        {
+            IDictionary<string, string> GetAllVariables();
+            bool BypassMedia { get; set; }
+            DateTime CreatedTime { get; }
+            DateTime? AnsweredTime { get; }
+            DateTime? HangupTime { get; }
+            DateTime? ProgressTime { get; }
+            DateTime? ProgressMediaTime { get; }
+            DateTime? TransferTime { get; }
+            string SofiaProfileName { get; }
+            string SipCallID { get; }
+            string SipReceivedIP { get; }
+            short? SipReceivedPort { get; }
+            string SipViaProtocolString { get; }
+            string SipFromUser { get; }
+            string SipFromUriString { get; }
+            string SipFromHost { get; }
+            string SipReqUser { get; }
+            string SipReqUriString { get; }
+            string SipReqHost { get; }
+            string SipToUser { get; }
+            string SipToUriString { get; }
+            string SipToHost { get; }
+            string SipContactUser { get; }
+            string SipContactUriString { get; }
+            string SipContactHost { get; }
+            short? SipContactPort { get; }
+            string SipDestinationUrlString { get; }
+            int? SipTermStatus { get; }
+            int? SipTermCause { get; }
+            string SwitchRSdp { get; }
+            string SwitchMSdp { get; }
+            string SipHangupPhrase { get; }
+            string ProtoSpecificHangupCause { get; }
+            string HangupCauseString { get; }
+            int? HangupCauseQ850 { get; }
+            string OriginateDispositionString { get; }
+            Native.switch_call_direction_t CallDirection { get; }
+        }
         /// <summary>Strongly typed access to common variables</summary>
-        public class ChannelVariables {
+        public class ChannelVariables : IChannelVariables
+        {
             readonly ManagedSession sess;
             internal ChannelVariables(ManagedSession session) {
                 this.sess = session;
@@ -84,12 +125,12 @@
 
             public IDictionary<string, string> GetAllVariables() {
                 var dic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-                var evt = Native.freeswitch.switch_channel_variable_first(sess.channel);
+                var evt = Native.freeswitch.switch_channel_variable_first(sess.Channel);
                 while(evt != null) {
                     dic.Add(evt.name, evt.value);
                     evt = evt.next;
                 }
-                Native.freeswitch.switch_channel_variable_last(sess.channel);
+                Native.freeswitch.switch_channel_variable_last(sess.Channel);
                 return dic;
             }
 

Modified: freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs (15642 => 15643)


--- freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs	2009-11-23 23:19:42 UTC (rev 15642)
+++ freeswitch/branches/joshrivers/mod_managed_working_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs	2009-11-23 23:22:27 UTC (rev 15643)
@@ -45,10 +45,71 @@
 
     // This callback is used for originate
     [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-    public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr); 
+    public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr);
 
-    public partial class ManagedSession
+    public interface IManagedSession
     {
+        int Answer();
+        bool Answered();
+        int Allocated { get; set; }
+        bool BeginAllowThreads();
+        input_callback_state_t CallbackState { get; set; }
+        switch_call_cause_t CallCause { get; set; }
+        SWIGTYPE_p_switch_channel Channel { get; set; }
+        void CheckHangupHook();
+        int CollectDigits(int abs_timeout);
+        int CollectDigits(int digit_timeout, int abs_timeout);
+        Func<Char, TimeSpan, string> DtmfReceivedFunction { get; set; }
+        void Destroy();
+        bool EndAllowThreads();
+        Func<Native.Event, string> EventReceivedFunction { get; set; }
+        void Execute(string app, string data);
+        uint Flags { get; set; }
+        int FlushEvents();
+        int FlushDigits();
+        switch_input_args_t GetCallbackArguments();
+        string GetState();
+        string GetUuid();
+        string GetDigits(int maxdigits, string terminators, int timeout);
+        string GetDigits(int maxdigits, string terminators, int timeout, int interdigit);
+        SWIGTYPE_p_void GetPrivate(string var);
+        string GetVariable(string var);
+        string GetXmlCdr();
+        void Hangup(string cause);
+        string HangupCause();
+        Action HangupFunction { get; set; }
+        void HangupState();
+        switch_channel_state_t HookState { get; set; }
+        SWIGTYPE_p_switch_core_session InternalSession { get; set; }
+        bool IsAvailable { get; }
+        bool MediaReady();
+        bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout);
+        string PlayAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, string terminators, string audio_files, string bad_input_audio_files, string digits_regex, string var_name);
+        int PreAnswer();
+        string Read(int min_digits, int max_digits, string prompt_audio_file, int timeout, string valid_terminators);
+        bool Ready();
+        int RecordFile(string file_name, int time_limit, int silence_threshold, int silence_hits);
+        int SetAutoHangup(bool val);
+        void SetPrivate(string var, SWIGTYPE_p_void val);
+        void SetVariable(string var, string val);
+        void Say(string tosay, string module_name, string say_type, string say_method);
+        void SayPhrase(string phrase_name, string phrase_data, string phrase_lang);
+        void SetTtsParameters(string tts_name, string voice_name);
+        int Speak(string text);
+        int StreamFile(string file, int starting_sample_count);
+        int Sleep(int ms, int sync);
+        void SendEvent(Event sendME);
+        void SetEventData(Event e);
+        int Transfer(string extension, string dialplan, string context);
+        string TextToSpeechEngine { get; set; }
+        string TextToSpeechVoice { get; set; }
+        Guid Uuid { get; }
+        string UuidString { get; set; }
+        ManagedSession.IChannelVariables Variables { get; }
+        void WaitForAnswer(CoreSession calling_session);
+    }
+    public partial class ManagedSession : IManagedSession
+    {
         // SWITCH_DECLARE(void) InitManagedSession(ManagedSession *session, MonoObject *dtmfDelegate, MonoObject *hangupDelegate)
         [DllImport("mod_managed.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
         static extern void InitManagedSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, CdeclAction hangupDelegate);
@@ -56,7 +117,8 @@
         /// <summary>Initializes the native ManagedSession. Called after Originate completes successfully .</summary>
         internal void Initialize()
         {
-            if (allocated == 0) {
+            if (Allocated == 0)
+            {
                 throw new InvalidOperationException("Cannot initialize a ManagedSession until it is allocated (originated successfully).");
             }
             // P/Invoke generated function pointers stick around until the delegate is collected
@@ -77,11 +139,13 @@
         void hangupCallback()
         {
             Log.WriteLine(LogLevel.Debug, "AppFunction is in hangupCallback.");
-            try {
+            try
+            {
                 var f = HangupFunction;
                 if (f != null) f();
             }
-            catch (Exception ex) {
+            catch (Exception ex)
+            {
                 Log.WriteLine(LogLevel.Warning, "Exception in hangupCallback: {0}", ex.ToString());
             }
         }
@@ -92,43 +156,54 @@
 
         string inputCallback(IntPtr input, Native.switch_input_type_t inputType)
         {
-            try {
-                switch (inputType) {
+            try
+            {
+                switch (inputType)
+                {
                     case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_DTMF:
-                        using (var dtmf = new Native.switch_dtmf_t(input, false)) {
+                        using (var dtmf = new Native.switch_dtmf_t(input, false))
+                        {
                             return dtmfCallback(dtmf);
                         }
                     case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_EVENT:
-                        using (var swevt = new Native.switch_event(input, false)) {
+                        using (var swevt = new Native.switch_event(input, false))
+                        {
                             return eventCallback(swevt);
                         }
                     default:
                         return "";
                 }
-            } catch (Exception ex) {
+            }
+            catch (Exception ex)
+            {
                 Log.WriteLine(LogLevel.Error, "InputCallback threw exception: " + ex.ToString());
                 return "-ERR InputCallback Exception: " + ex.Message;
             }
         }
 
-        string dtmfCallback(Native.switch_dtmf_t dtmf) {
+        string dtmfCallback(Native.switch_dtmf_t dtmf)
+        {
             var f = DtmfReceivedFunction;
-            return f == null ? "" 
+            return f == null ? ""
                 : f(((char)(byte)dtmf.digit), TimeSpan.FromMilliseconds(dtmf.duration));
         }
 
-        string eventCallback(Native.switch_event swevt) {
-            using (var evt = new FreeSWITCH.Native.Event(swevt, 0)) {
+        string eventCallback(Native.switch_event swevt)
+        {
+            using (var evt = new FreeSWITCH.Native.Event(swevt, 0))
+            {
                 var f = EventReceivedFunction;
-                return f == null ? "" 
+                return f == null ? ""
                     : f(evt);
             }
         }
 
         [Obsolete("Use static Originate method.", false)]
-        public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout) {
+        public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout)
+        {
             var res = 0 == this.originate(aLegSession, destination, (int)timeout.TotalMilliseconds, null);
-            if (res) {
+            if (res)
+            {
                 this.Initialize();
             }
             return res;
@@ -139,18 +214,22 @@
         // The delegate needs to be stored so it doesn't get GC'd, so we can't just return GetFunctionPointerForDelegate right away.
 
         /// <summary>Wraps a nice handler into a delegate suitable for reverse P/Invoke. This only currently works well for hangup/reporting handlers.</summary>
-        public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler) {
+        public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler)
+        {
             // We create a ManagedSession on top of the session so callbacks can use it "nicely"
             // Then we sort of dispose it.
-            switch_state_handler_t_delegate del = ptr => {
-                using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false))) {
+            switch_state_handler_t_delegate del = ptr =>
+            {
+                using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false)))
+                {
                     handler(sess);
                     return switch_status_t.SWITCH_STATUS_SUCCESS;
                 }
             };
             return del;
         }
-        public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del) {
+        public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del)
+        {
             return new SWIGTYPE_p_f_p_switch_core_session__switch_status_t(Marshal.GetFunctionPointerForDelegate(del), false);
         }
 
@@ -162,15 +241,18 @@
         switch_state_handler_table originate_table;
         GCHandle originate_keepalive_handle; // Make sure the B Leg is not collected and disposed until we run ondestroy
 
-        switch_status_t originate_ondestroy_method(IntPtr channelPtr) {
+        switch_status_t originate_ondestroy_method(IntPtr channelPtr)
+        {
             // CS_DESTROY lets the bleg be collected
             // and frees originate_table memory
             // Note that this (bleg ManagedSession) is invalid 
             // to touch right now - the unmanaged memory has already been free'd
-            if (this.originate_keepalive_handle.IsAllocated) {
+            if (this.originate_keepalive_handle.IsAllocated)
+            {
                 this.originate_keepalive_handle.Free(); // GC can now collect this bleg
             }
-            if (this.originate_table != null) {
+            if (this.originate_table != null)
+            {
                 this.originate_table.Dispose();
                 this.originate_table = null;
             }
@@ -181,12 +263,15 @@
         /// Performs originate. Returns ManagedSession on success, null on failure.
         /// onHangup is called as a state handler, after the channel is truly hungup (CS_REPORTING).
         /// </summary>
-        public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup) {
+        public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup)
+        {
             var bleg = new ManagedSession();
 
             bleg.originate_ondestroy_delegate = bleg.originate_ondestroy_method;
-            bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b => {
-                if (onHangup != null) {
+            bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b =>
+            {
+                if (onHangup != null)
+                {
                     onHangup(sess_b);
                 }
             });
@@ -196,35 +281,95 @@
             bleg.originate_table.flags = (int)switch_state_handler_flag_t.SSH_FLAG_STICKY;
             var res = 0 == bleg.originate(aLegSession, destination, (int)timeout.TotalSeconds, bleg.originate_table);
             bleg.originate_keepalive_handle = GCHandle.Alloc(bleg, GCHandleType.Normal); // Prevent GC from eating the bleg
-            if (res) {
+            if (res)
+            {
                 bleg.Initialize();
                 return bleg;
-            } else {
+            }
+            else
+            {
                 // Dispose to free the lock
                 // The bleg lives on with its unmanaged memory freed 
                 // Until CS_DESTROY gets called
-                bleg.Dispose(); 
+                bleg.Dispose();
                 return null;
             }
         }
 
         // Convenience
-        public bool IsAvailable {
+        public bool IsAvailable
+        {
             get { return this.Ready(); }
         }
 
-        public Guid Uuid {
-            get {
-                if (allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+        public Guid Uuid
+        {
+            get
+            {
+                if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
                 return new Guid(this.GetUuid());
             }
         }
 
-        public switch_call_cause_t CallCause {
-            get {
-                if (allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
-                return freeswitch.switch_channel_get_cause(this.channel);
+        public switch_call_cause_t CallCause
+        {
+            get
+            {
+                if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+                return freeswitch.switch_channel_get_cause(this.Channel);
             }
+            set
+            {
+                if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+                base.CallCause = value;
+            }
         }
     }
+
+    public interface IEvent
+    {
+        switch_event InternalEvent { get; set; }
+        string serialized_string { get; set; }
+        int mine { get; set; }
+        string Serialize(string format);
+        bool SetPriority(switch_priority_t priority);
+        string GetHeader(string header_name);
+        string GetBody();
+        string GetEventType();
+        bool AddBody(string value);
+        bool AddHeader(string header_name, string value);
+        bool DeleteHeader(string header_name);
+        bool Fire();
+    }
+    public partial class Event :  IEvent { }
+
+    public interface IManagedEventConsumer
+    {
+        IEvent Pop(bool block);
+    }
+    public class ManagedEventConsumer : IDisposable, IManagedEventConsumer
+    {
+        private EventConsumer _eventConsumer;
+        public ManagedEventConsumer(string eventClass, string EventSubclass)
+        {
+            this._eventConsumer = new EventConsumer(eventClass, EventSubclass);
+        }
+
+        public IEvent Pop(bool block)
+        {
+            if (block)
+            {
+                return this._eventConsumer.pop(1);
+            }
+            else
+            {
+                return this._eventConsumer.pop(0);
+            }
+        }
+
+        public void Dispose()
+        {
+            this._eventConsumer.Dispose();
+        }
+    }
 }