/// <summary> /// Default constructor. /// </summary> /// <param name="sipStack">Reference to SIP stack.</param> /// <param name="request">SIP request to what caused to create client transaction.</param> /// <param name="destination">Remote destination info.</param> /// <param name="addVia">Specified if transaction adds new Via: header. If this value is false, /// then its user responsibility to add valid Via: header to <b>request</b> argument.</param> internal SIP_ClientTransaction(SIP_Stack sipStack,SIP_Request request,SIP_Destination destination,bool addVia) { m_pSipStack = sipStack; m_pRequest = request; m_pDestination = destination; m_pResponses = new List<SIP_Response>(); // Add Via: header field. if(addVia){ m_ID = SIP_t_ViaParm.CreateBranch(); SIP_t_ViaParm via = new SIP_t_ViaParm(); via.ProtocolName = "SIP"; via.ProtocolVersion = "2.0"; via.ProtocolTransport = m_pDestination.Transport; via.SentBy = "transport_layer_will_replace_it"; via.Branch = m_ID; request.Via.AddToTop(via.ToStringValue()); } // User provided Via:. else{ // Validate Via: SIP_t_ViaParm via = request.Via.GetTopMostValue(); if(via == null){ throw new ArgumentException("Via: header is missing !"); } if(via.Branch == null){ throw new ArgumentException("Via: header 'branch' prameter is missing !"); } m_ID = via.Branch; } }
/// <summary> /// Creates new SIP client transaction for specified request. /// </summary> /// <param name="request">SIP request.</param> /// <param name="destination">Remote destination info.</param> /// <param name="addVia">Specified if transaction adds new Via: header. If this value is false, /// then its user responsibility to add vlid Via: header to <b>request</b> argument.</param> /// <returns>Returns ncreated SIP client transaction.</returns> public SIP_ClientTransaction CreateClientTransaction(SIP_Request request,SIP_Destination destination,bool addVia) { SIP_ClientTransaction transaction = new SIP_ClientTransaction(m_pSipStack,request,destination,addVia); m_pClientTransactions.Add(transaction); return transaction; }
/// <summary> /// Default constructor. /// </summary> /// <param name="stack">Owner stack.</param> /// <param name="request">Request to forward.</param> /// <param name="forkingMode">Specifies how proxy context must handle forking.</param> /// <param name="noCancel">Specifies if proxy should not send Cancel to forked requests.</param> /// <param name="noRecurse">Specifies what proxy server does when it gets 3xx response. If true proxy will forward /// request to new specified address if false, proxy will return 3xx response to caller.</param> /// <param name="destinations">Possible destinations. NOTE: These values must be in priority order !</param> /// <exception cref="ArgumentNullException">Is raised when any of the reference type prameters is null.</exception> public SIP_ProxyContext(SIP_Stack stack,SIP_Request request,SIP_ForkingMode forkingMode,bool noCancel,bool noRecurse,SIP_Destination[] destinations) { if(stack == null){ throw new ArgumentNullException("stack"); } if(request == null){ throw new ArgumentNullException("serverTransaction"); } if(destinations == null){ throw new ArgumentNullException("destinations"); } m_pStack = stack; m_pServerTransaction = stack.TransactionLayer.CreateServerTransaction(request); m_pServerTransaction.CanCreateDialog = false; m_pServerTransaction.Canceled += new EventHandler(m_pServerTransaction_Canceled); m_pServerTransaction.Terminated += new EventHandler(m_pServerTransaction_Terminated); m_ForkingMode = forkingMode; m_NoCancel = noCancel; m_NoRecurse = noRecurse; m_pClientTransactions = new List<SIP_ClientTransaction>(); m_pResponses = new List<SIP_Response>(); m_CreateTime = DateTime.Now; // Queue destinations up, higest to lowest. m_pRemainingDestinations = new Queue<SIP_Destination>(); foreach(SIP_Destination destination in destinations){ m_pRemainingDestinations.Enqueue(destination); } }
/// <summary> /// Creates client transaction and starts processing it. /// </summary> /// <param name="destination">SIP destination.</param> private void CreateClientTransaction(SIP_Destination destination) { /* Sequential handling: If there are more that 1 destination, then m_SequentialTimeout interval is used to to try next destination. Otherwise 3 minute is used. */ SIP_ClientTransaction transaction = m_pStack.TransactionLayer.CreateClientTransaction(m_pServerTransaction.Request.Copy(),destination,true); if(m_ForkingMode == SIP_ForkingMode.Sequential && m_pRemainingDestinations.Count > 0){ transaction.Timeout = 15; } else{ transaction.Timeout = 180; } transaction.CanCreateDialog = false; transaction.ResponseReceived += new SIP_ResponseReceivedEventHandler(ClientTransaction_ResponseReceived); transaction.TimedOut += new EventHandler(ClientTransaction_TimedOut); transaction.TransportError += new EventHandler(ClientTransaction_TransportError); transaction.Terminated += new EventHandler(ClientTransaction_Terminated); m_pClientTransactions.Add(transaction); transaction.Begin(); }
/// <summary> /// Sends request to the specified destination. /// </summary> /// <param name="request">SIP request to send.</param> /// <param name="destination">Destination info.</param> /// <exception cref="SIP_TransportException">Is raised when sending fails.</exception> public void SendRequest(SIP_Request request,SIP_Destination destination) { try{ SendRequest(request,destination.LocalEndPoint,new IPEndPoint(System.Net.Dns.GetHostAddresses(destination.Host)[0],destination.Port),destination.Transport); } catch(Exception x){ throw new SIP_TransportException(x.Message); } }