PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/sipsorcery-core/SIPSorcery.SIP.App/SIPUserAgents/SIPTransferServerUserAgent.cs

https://github.com/thecc4re/sipsorcery-mono
C# | 255 lines | 185 code | 23 blank | 47 comment | 9 complexity | 3eb23209d3e5375bff31feb564aa7e3a MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //-----------------------------------------------------------------------------
  2. // Filename: SIPTransferServerUserAgent.cs
  3. //
  4. // Description: The interface definition for SIP Server User Agents (UAC).
  5. //
  6. // History:
  7. // 21 Jan 2010 Aaron Clauson Created.
  8. //
  9. // License:
  10. // This software is licensed under the BSD License http://www.opensource.org/licenses/bsd-license.php
  11. //
  12. // Copyright (c) 2010 Aaron Clauson (aaron@sipsorcery.com), SIP Sorcery Ltd, London, UK (www.sipsorcery.com)
  13. // All rights reserved.
  14. //
  15. // Redistribution and use in source and binary forms, with or without modification, are permitted provided that
  16. // the following conditions are met:
  17. //
  18. // Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  19. // Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  20. // disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Blue Face Ltd.
  21. // nor the names of its contributors may be used to endorse or promote products derived from this software without specific
  22. // prior written permission.
  23. //
  24. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
  25. // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  26. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  27. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  28. // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. // POSSIBILITY OF SUCH DAMAGE.
  31. //-----------------------------------------------------------------------------
  32. using System;
  33. using System.Collections.Generic;
  34. using System.Linq;
  35. using System.Net;
  36. using System.Text;
  37. using SIPSorcery.Sys;
  38. using log4net;
  39. namespace SIPSorcery.SIP.App
  40. {
  41. /// <summary>
  42. /// A server user agent that replaces an existing sip dialogue rather than creating a new dialogue with
  43. /// a client user agent.
  44. /// </summary>
  45. public class SIPTransferServerUserAgent : ISIPServerUserAgent
  46. {
  47. private static ILog logger = AppState.logger;
  48. public SIPCallDirection CallDirection
  49. {
  50. get { return SIPCallDirection.Out; }
  51. }
  52. public SIPDialogue SIPDialogue
  53. {
  54. get { throw new NotImplementedException("SIPTransferServerUserAgent SIPDialogue"); }
  55. }
  56. public SIPAccount SIPAccount
  57. {
  58. get
  59. {
  60. return null;
  61. }
  62. set
  63. {
  64. throw new NotImplementedException("SIPTransferServerUserAgent SIPAccount set");
  65. }
  66. }
  67. public bool IsAuthenticated
  68. {
  69. get
  70. {
  71. throw new NotImplementedException("SIPTransferServerUserAgent IsAuthenticated get");
  72. }
  73. set
  74. {
  75. throw new NotImplementedException("SIPTransferServerUserAgent IsAuthenticated set");
  76. }
  77. }
  78. public bool IsB2B
  79. {
  80. get { return false; }
  81. }
  82. public SIPRequest CallRequest
  83. {
  84. get { return m_dummyRequest; }
  85. }
  86. public string CallDestination
  87. {
  88. get { return m_callDestination; }
  89. }
  90. public bool IsUASAnswered
  91. {
  92. get { return m_answered; }
  93. }
  94. public string Owner
  95. {
  96. get { return m_owner; }
  97. }
  98. private SIPMonitorLogDelegate Log_External = (e) => { }; //SIPMonitorEvent.DefaultSIPMonitorLogger;
  99. private BlindTransferDelegate BlindTransfer_External;
  100. private SIPTransport m_sipTransport;
  101. private SIPEndPoint m_outboundProxy; // If the system needs to use an outbound proxy for every request this will be set and overrides any user supplied values.
  102. private SIPDialogue m_dialogueToReplace;
  103. private SIPDialogue m_oppositeDialogue;
  104. private string m_owner;
  105. private string m_adminID;
  106. private bool m_answered;
  107. private string m_callDestination;
  108. private SIPRequest m_dummyRequest; // Used to get the SDP for into the dialplan.
  109. public event SIPUASDelegate CallCancelled;
  110. public event SIPUASDelegate NoRingTimeout;
  111. public event SIPUASDelegate TransactionComplete;
  112. public event SIPUASStateChangedDelegate UASStateChanged;
  113. public SIPTransferServerUserAgent(
  114. SIPMonitorLogDelegate logDelegate,
  115. BlindTransferDelegate blindTransfer,
  116. SIPTransport sipTransport,
  117. SIPEndPoint outboundProxy,
  118. SIPDialogue dialogueToReplace,
  119. SIPDialogue oppositeDialogue,
  120. string callDestination,
  121. string owner,
  122. string adminID)
  123. {
  124. Log_External = logDelegate;
  125. BlindTransfer_External = blindTransfer;
  126. m_sipTransport = sipTransport;
  127. m_outboundProxy = outboundProxy;
  128. m_dialogueToReplace = dialogueToReplace;
  129. m_oppositeDialogue = oppositeDialogue;
  130. m_callDestination = callDestination;
  131. m_owner = owner;
  132. m_adminID = adminID;
  133. m_dummyRequest = CreateDummyRequest(m_dialogueToReplace, m_callDestination);
  134. }
  135. public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody)
  136. {
  137. if (UASStateChanged != null)
  138. {
  139. UASStateChanged(this, progressStatus, reasonPhrase);
  140. }
  141. if (progressBody != null)
  142. {
  143. // Re-invite the remote dialogue so that they can listen to some real progress tones.
  144. }
  145. }
  146. public SIPDialogue Answer(string contentType, string body, SIPDialogue answeredDialogue, SIPDialogueTransferModesEnum transferMode)
  147. {
  148. return Answer(contentType, body, null, answeredDialogue, transferMode);
  149. }
  150. /// <summary>
  151. /// An answer on a blind transfer means the remote end of the dialogue being replaced should be re-invited and then the replaced dialogue
  152. /// should be hungup.
  153. /// </summary>
  154. /// <param name="contentType"></param>
  155. /// <param name="body"></param>
  156. /// <param name="toTag"></param>
  157. /// <param name="answeredDialogue"></param>
  158. /// <param name="transferMode"></param>
  159. /// <returns></returns>
  160. public SIPDialogue Answer(string contentType, string body, string toTag, SIPDialogue answeredDialogue, SIPDialogueTransferModesEnum transferMode)
  161. {
  162. try
  163. {
  164. if (m_answered)
  165. {
  166. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A blind transfer received an answer on an already answered call, hanging up dialogue.", m_owner));
  167. answeredDialogue.Hangup(m_sipTransport, m_outboundProxy);
  168. }
  169. else
  170. {
  171. m_answered = true;
  172. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A blind transfer received an answer.", m_owner));
  173. if (UASStateChanged != null)
  174. {
  175. UASStateChanged(this, SIPResponseStatusCodesEnum.Ok, null);
  176. }
  177. BlindTransfer_External(m_dialogueToReplace, m_oppositeDialogue, answeredDialogue);
  178. }
  179. return null;
  180. }
  181. catch (Exception excp)
  182. {
  183. logger.Error("Exception SIPTransferServerUserAgent Answer. " + excp.Message);
  184. throw;
  185. }
  186. }
  187. public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders)
  188. {
  189. logger.Warn("SIPTransferServerUserAgent Reject called with " + failureStatus + " " + reasonPhrase + ".");
  190. if (UASStateChanged != null)
  191. {
  192. UASStateChanged(this, failureStatus, reasonPhrase);
  193. }
  194. }
  195. public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI)
  196. {
  197. throw new NotImplementedException("SIPTransferServerUserAgent Redirect");
  198. }
  199. public void NoCDR()
  200. {
  201. throw new NotImplementedException("SIPTransferServerUserAgent NoCDR");
  202. }
  203. public void SetTraceDelegate(SIPTransactionTraceMessageDelegate traceDelegate)
  204. {
  205. //throw new NotImplementedException();
  206. }
  207. public bool LoadSIPAccountForIncomingCall()
  208. {
  209. throw new NotImplementedException("SIPTransferServerUserAgent LoadSIPAccountForIncomingCall");
  210. }
  211. public bool AuthenticateCall()
  212. {
  213. throw new NotImplementedException("SIPTransferServerUserAgent AuthenticateCall");
  214. }
  215. public void SetOwner(string owner, string adminMemberId)
  216. {
  217. m_owner = owner;
  218. m_adminID = adminMemberId;
  219. }
  220. private SIPRequest CreateDummyRequest(SIPDialogue dialogueToReplace, string callDestination)
  221. {
  222. SIPRequest dummyInvite = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURIRelaxed(callDestination + "@sipsorcery.com"));
  223. SIPHeader dummyHeader = new SIPHeader("<sip:anon@sipsorcery.com>", "<sip:anon@sipsorcery.com>", 1, CallProperties.CreateNewCallId());
  224. dummyHeader.CSeqMethod = SIPMethodsEnum.INVITE;
  225. dummyHeader.Vias.PushViaHeader(new SIPViaHeader(new IPEndPoint(SIPTransport.BlackholeAddress, 0), CallProperties.CreateBranchId()));
  226. dummyInvite.Header = dummyHeader;
  227. dummyInvite.Header.ContentType = "application/sdp";
  228. dummyInvite.Body = dialogueToReplace.SDP;
  229. return dummyInvite;
  230. }
  231. }
  232. }