/// <summary> /// Default constructor. /// </summary> public SIP_UA() { m_pStack = new SIP_Stack(); m_pStack.RequestReceived += m_pStack_RequestReceived; m_pCalls = new List<SIP_UA_Call>(); }
/// <summary> /// Initializes dialog. /// </summary> /// <param name="stack">Owner stack.</param> /// <param name="transaction">Owner transaction.</param> /// <param name="response">SIP response what caused dialog creation.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>transaction</b> or <b>response</b>.</exception> protected internal override void Init(SIP_Stack stack, SIP_Transaction transaction, SIP_Response response) { if (stack == null) { throw new ArgumentNullException("stack"); } if (transaction == null) { throw new ArgumentNullException("transaction"); } if (response == null) { throw new ArgumentNullException("response"); } base.Init(stack, transaction, response); if (transaction is SIP_ServerTransaction) { if (response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_DialogState.Early, false); // We need to retransmit 2xx response while we get ACK or timeout. (RFC 3261 13.3.1.4.) m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, response)); } else if (response.StatusCodeType == SIP_StatusCodeType.Provisional) { SetState(SIP_DialogState.Early, false); m_pActiveInvite = transaction; m_pActiveInvite.StateChanged += delegate { if (m_pActiveInvite != null && m_pActiveInvite.State == SIP_TransactionState.Terminated) { m_pActiveInvite = null; } }; // Once we send 2xx response, we need to retransmit it while get ACK or timeout. (RFC 3261 13.3.1.4.) ((SIP_ServerTransaction)m_pActiveInvite).ResponseSent += delegate(object s, SIP_ResponseSentEventArgs a) { if (a.Response.StatusCodeType == SIP_StatusCodeType.Success) { m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, a.Response)); } }; } else { throw new ArgumentException( "Argument 'response' has invalid status code, 1xx - 2xx is only allowed."); } } else { if (response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_DialogState.Confirmed, false); // Wait for retransmited 2xx responses. (RFC 3261 13.2.2.4.) m_pUacInvite2xxRetransmitWaits.Add(new UacInvite2xxRetransmissionWaiter(this, transaction. Request)); } else if (response.StatusCodeType == SIP_StatusCodeType.Provisional) { SetState(SIP_DialogState.Early, false); m_pActiveInvite = transaction; m_pActiveInvite.StateChanged += delegate { if (m_pActiveInvite != null && m_pActiveInvite.State == SIP_TransactionState.Terminated) { m_pActiveInvite = null; } }; // Once we receive 2xx response, we need to wait for retransmitted 2xx responses. (RFC 3261 13.2.2.4) ((SIP_ClientTransaction)m_pActiveInvite).ResponseReceived += delegate(object s, SIP_ResponseReceivedEventArgs a) { if (a.Response.StatusCodeType == SIP_StatusCodeType.Success) { UacInvite2xxRetransmissionWaiter waiter = new UacInvite2xxRetransmissionWaiter(this, m_pActiveInvite.Request); m_pUacInvite2xxRetransmitWaits.Add(waiter); // Force to send initial ACK to 2xx response. waiter.Process(a.Response); SetState(SIP_DialogState.Confirmed, true); } }; } else { throw new ArgumentException( "Argument 'response' has invalid status code, 1xx - 2xx is only allowed."); } } }
/// <summary> /// Initializes dialog. /// </summary> /// <param name="stack">Owner stack.</param> /// <param name="transaction">Owner transaction.</param> /// <param name="response">SIP response what caused dialog creation.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>transaction</b> or <b>response</b>.</exception> internal protected virtual void Init(SIP_Stack stack, SIP_Transaction transaction, SIP_Response response) { if (stack == null) { throw new ArgumentNullException("stack"); } if (transaction == null) { throw new ArgumentNullException("transaction"); } if (response == null) { throw new ArgumentNullException("response"); } m_pStack = stack; /* RFC 3261 12.1.1. * The UAS then constructs the state of the dialog. This state MUST be * maintained for the duration of the dialog. * * If the request arrived over TLS, and the Request-URI contained a SIPS * URI, the "secure" flag is set to TRUE. * * The route set MUST be set to the list of URIs in the Record-Route * header field from the request, taken in order and preserving all URI * parameters. If no Record-Route header field is present in the * request, the route set MUST be set to the empty set. This route set, * even if empty, overrides any pre-existing route set for future * requests in this dialog. The remote target MUST be set to the URI * from the Contact header field of the request. * * The remote sequence number MUST be set to the value of the sequence * number in the CSeq header field of the request. The local sequence * number MUST be empty. The call identifier component of the dialog ID * MUST be set to the value of the Call-ID in the request. The local * tag component of the dialog ID MUST be set to the tag in the To field * in the response to the request (which always includes a tag), and the * remote tag component of the dialog ID MUST be set to the tag from the * From field in the request. A UAS MUST be prepared to receive a * request without a tag in the From field, in which case the tag is * considered to have a value of null. * * This is to maintain backwards compatibility with RFC 2543, which * did not mandate From tags. * * The remote URI MUST be set to the URI in the From field, and the * local URI MUST be set to the URI in the To field. */ if (transaction is SIP_ServerTransaction) { m_IsSecure = ((SIP_Uri)transaction.Request.RequestLine.Uri).IsSecure; m_pRouteSet = (SIP_t_AddressParam[])Net_Utils.ReverseArray(transaction.Request.RecordRoute.GetAllValues()); m_pRemoteTarget = (SIP_Uri)transaction.Request.Contact.GetTopMostValue().Address.Uri; m_RemoteSeqNo = transaction.Request.CSeq.SequenceNumber; m_LocalSeqNo = 0; m_CallID = transaction.Request.CallID; m_LocalTag = response.To.Tag; m_RemoteTag = transaction.Request.From.Tag; m_pRemoteUri = transaction.Request.From.Address.Uri; m_pLocalUri = transaction.Request.To.Address.Uri; m_pLocalContact = (SIP_Uri)response.Contact.GetTopMostValue().Address.Uri; List <string> allow = new List <string>(); foreach (SIP_t_Method m in response.Allow.GetAllValues()) { allow.Add(m.Method); } m_pRemoteAllow = allow.ToArray(); List <string> supported = new List <string>(); foreach (SIP_t_OptionTag s in response.Supported.GetAllValues()) { supported.Add(s.OptionTag); } m_pRemoteSupported = supported.ToArray(); } /* RFC 3261 12.1.2. * When a UAC receives a response that establishes a dialog, it * constructs the state of the dialog. This state MUST be maintained * for the duration of the dialog. * * If the request was sent over TLS, and the Request-URI contained a * SIPS URI, the "secure" flag is set to TRUE. * * The route set MUST be set to the list of URIs in the Record-Route * header field from the response, taken in reverse order and preserving * all URI parameters. If no Record-Route header field is present in * the response, the route set MUST be set to the empty set. This route * set, even if empty, overrides any pre-existing route set for future * requests in this dialog. The remote target MUST be set to the URI * from the Contact header field of the response. * * The local sequence number MUST be set to the value of the sequence * number in the CSeq header field of the request. The remote sequence * number MUST be empty (it is established when the remote UA sends a * request within the dialog). The call identifier component of the * dialog ID MUST be set to the value of the Call-ID in the request. * The local tag component of the dialog ID MUST be set to the tag in * the From field in the request, and the remote tag component of the * dialog ID MUST be set to the tag in the To field of the response. A * UAC MUST be prepared to receive a response without a tag in the To * field, in which case the tag is considered to have a value of null. * * This is to maintain backwards compatibility with RFC 2543, which * did not mandate To tags. * * The remote URI MUST be set to the URI in the To field, and the local * URI MUST be set to the URI in the From field. */ else { // TODO: Validate request or client transaction must do it ? m_IsSecure = ((SIP_Uri)transaction.Request.RequestLine.Uri).IsSecure; m_pRouteSet = (SIP_t_AddressParam[])Net_Utils.ReverseArray(response.RecordRoute.GetAllValues()); m_pRemoteTarget = (SIP_Uri)response.Contact.GetTopMostValue().Address.Uri; m_LocalSeqNo = transaction.Request.CSeq.SequenceNumber; m_RemoteSeqNo = 0; m_CallID = transaction.Request.CallID; m_LocalTag = transaction.Request.From.Tag; m_RemoteTag = response.To.Tag; m_pRemoteUri = transaction.Request.To.Address.Uri; m_pLocalUri = transaction.Request.From.Address.Uri; m_pLocalContact = (SIP_Uri)transaction.Request.Contact.GetTopMostValue().Address.Uri; List <string> allow = new List <string>(); foreach (SIP_t_Method m in response.Allow.GetAllValues()) { allow.Add(m.Method); } m_pRemoteAllow = allow.ToArray(); List <string> supported = new List <string>(); foreach (SIP_t_OptionTag s in response.Supported.GetAllValues()) { supported.Add(s.OptionTag); } m_pRemoteSupported = supported.ToArray(); } m_pFlow = transaction.Flow; AddTransaction(transaction); }
/// <summary> /// Initializes dialog. /// </summary> /// <param name="stack">Owner stack.</param> /// <param name="transaction">Owner transaction.</param> /// <param name="response">SIP response what caused dialog creation.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>transaction</b> or <b>response</b>.</exception> internal protected override void Init(SIP_Stack stack, SIP_Transaction transaction, SIP_Response response) { if (stack == null) { throw new ArgumentNullException("stack"); } if (transaction == null) { throw new ArgumentNullException("transaction"); } if (response == null) { throw new ArgumentNullException("response"); } base.Init(stack, transaction, response); if (transaction is SIP_ServerTransaction) { if (response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_DialogState.Early, false); } else if (response.StatusCodeType == SIP_StatusCodeType.Provisional) { SetState(SIP_DialogState.Early, false); m_pActiveInvite = transaction; m_pActiveInvite.StateChanged += delegate(object s, EventArgs a){ if (m_pActiveInvite != null && m_pActiveInvite.State == SIP_TransactionState.Terminated) { m_pActiveInvite = null; /* RFC 3261 13.3.1.4. * If the server retransmits the 2xx response for 64*T1 seconds without * receiving an ACK, the dialog is confirmed, but the session SHOULD be * terminated. */ if (this.State == SIP_DialogState.Early) { this.SetState(SIP_DialogState.Confirmed, true); Terminate("ACK was not received for initial INVITE 2xx response.", true); } else if (this.State == SIP_DialogState.Terminating) { this.SetState(SIP_DialogState.Confirmed, false); Terminate(m_TerminateReason, true); } } }; } else { throw new ArgumentException("Argument 'response' has invalid status code, 1xx - 2xx is only allowed."); } } else { if (response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_DialogState.Confirmed, false); } else if (response.StatusCodeType == SIP_StatusCodeType.Provisional) { SetState(SIP_DialogState.Early, false); m_pActiveInvite = transaction; m_pActiveInvite.StateChanged += delegate(object s, EventArgs a){ if (m_pActiveInvite != null && m_pActiveInvite.State == SIP_TransactionState.Terminated) { m_pActiveInvite = null; } }; // Once we receive 2xx response, dialog will switch to confirmed state. ((SIP_ClientTransaction)transaction).ResponseReceived += delegate(object s, SIP_ResponseReceivedEventArgs a){ if (a.Response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_DialogState.Confirmed, true); } }; } else { throw new ArgumentException("Argument 'response' has invalid status code, 1xx - 2xx is only allowed."); } } }
/// <summary> /// Cleans up any resources being used. /// </summary> public void Dispose() { if (m_IsDisposed) { return; } m_IsDisposed = true; if (m_pStack != null) { m_pStack.Dispose(); m_pStack = null; } m_pRegistrar = null; m_pB2BUA = null; m_pProxyContexts = null; }
/// <summary> /// Default constructor. /// </summary> /// <param name="stack">Reference to SIP stack.</param> /// <exception cref="ArgumentNullException">Is raised when <b>sipStack</b> is null.</exception> public SIP_ProxyCore(SIP_Stack stack) { if (stack == null) { throw new ArgumentNullException("stack"); } m_pStack = stack; m_pStack.RequestReceived += m_pStack_RequestReceived; m_pStack.ResponseReceived += m_pStack_ResponseReceived; m_pRegistrar = new SIP_Registrar(this); m_pB2BUA = new SIP_B2BUA(this); m_Opaque = Auth_HttpDigest.CreateOpaque(); m_pProxyContexts = new List<SIP_ProxyContext>(); }
/// <summary> /// Default constructor. /// </summary> /// <param name="stack">Reference to SIP stack.</param> /// <param name="flow">SIP data flow.</param> /// <param name="request">Recieved request.</param> internal SIP_RequestReceivedEventArgs(SIP_Stack stack, SIP_Flow flow, SIP_Request request) : this(stack, flow, request, null) { }
/// <summary> /// Cleans up any resources being used. /// </summary> internal void Dispose() { if (m_IsDisposed) { return; } m_IsDisposed = true; CanRegister = null; AorRegistered = null; AorUnregistered = null; AorUpdated = null; m_pProxy = null; m_pStack = null; m_pRegistrations = null; if (m_pTimer != null) { m_pTimer.Dispose(); m_pTimer = null; } }
/// <summary> /// Default constructor. /// </summary> /// <param name="proxy">Owner proxy.</param> /// <exception cref="ArgumentNullException">Is raised when <b>proxy</b> is null reference.</exception> internal SIP_Registrar(SIP_ProxyCore proxy) { if (proxy == null) { throw new ArgumentNullException("proxy"); } m_pProxy = proxy; m_pStack = m_pProxy.Stack; m_pRegistrations = new SIP_RegistrationCollection(); m_pTimer = new Timer(15000); m_pTimer.Elapsed += m_pTimer_Elapsed; m_pTimer.Enabled = true; }
static void Main(string[] args) { throw new NotImplementedException(""); System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); DirectoryInfo tmpPath = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(asm.Location), "audio")); if (!tmpPath.Exists) { tmpPath.Create(); //Descompacta os zips em uma estrutura temporária //DecompressData(Resource1.audios, tmpPath); } //Carrega arquivo de config if (args.Length == 0) { return; } if (!File.Exists(args[0])) { return; } XmlDocument doc = new XmlDocument(); doc.LoadXml(File.ReadAllText(args[0], Encoding.UTF8)); XmlNode configNode = doc.SelectSingleNode("/call/config"); XmlNode commandsNode = doc.SelectSingleNode("/call/commands"); if ((configNode == null) || (commandsNode == null)) { return; } String target = ""; String server = ""; String username = ""; String password = ""; foreach (XmlNode n in doc.SelectNodes("/call/config/item")) { XmlNode key = n.SelectSingleNode("key"); XmlNode value = n.SelectSingleNode("value"); switch (key.InnerText.ToLower()) { case "target": target = value.InnerText; break; case "host": server = value.InnerText; break; case "username": username = value.InnerText; break; case "password": password = value.InnerText; break; } } SIP_Debug.DebugLevel = 5; List <String> cmds = new List <string>(); foreach (XmlNode n in commandsNode.ChildNodes) { cmds.Add(n.InnerText); } SIP_Stack stack = new SIP_Stack(server, 5060, username, password); try { using (SIP_Dial dial = new SIP_Dial(ref stack, target)) { dial.Dial(true, cmds); dial.WaitEnd(); //dial.DialOK } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Default constructor. /// </summary> /// <param name="stack">Reference to SIP stack.</param> /// <param name="transaction">Client transaction what response it is. This value can be null if no matching client response.</param> /// <param name="response">Received response.</param> internal SIP_ResponseReceivedEventArgs(SIP_Stack stack, SIP_ClientTransaction transaction, SIP_Response response) { m_pStack = stack; m_pResponse = response; m_pTransaction = transaction; }
/// <summary> /// Cleans up any resources being used. /// </summary> public void Dispose() { lock (m_pLock) { if (m_IsDisposed) { return; } // Hang up all calls. foreach (SIP_UA_Call call in m_pCalls.ToArray()) { call.Terminate(); } // Wait till all registrations and calls disposed or wait timeout reached. DateTime start = DateTime.Now; while (m_pCalls.Count > 0) { Thread.Sleep(500); // Timeout, just kill all UA. if (((DateTime.Now - start)).Seconds > 15) { break; } } m_IsDisposed = true; RequestReceived = null; IncomingCall = null; m_pStack.Dispose(); m_pStack = null; } }