Ejemplo n.º 1
0
        /// <summary>
        /// New transaction ACK requests are for 2xx responses, i.e. INVITE accepted and dialogue being created.
        /// </summary>
        /// <remarks>
        /// From RFC 3261 Chapter 17.1.1.3 - ACK for non-2xx final responses
        ///
        /// IMPORTANT:
        /// an ACK for a non-2xx response will also have the same branch ID as the INVITE whose response it acknowledges.
        ///
        /// The ACK request constructed by the client transaction MUST contain
        /// values for the Call-ID, From, and Request-URI that are equal to the
        /// values of those header fields in the request passed to the transport
        /// by the client transaction (call this the "original request").  The To
        /// header field in the ACK MUST equal the To header field in the
        /// response being acknowledged, and therefore will usually differ from
        /// the To header field in the original request by the addition of the
        /// tag parameter.  The ACK MUST contain a single Via header field, and
        /// this MUST be equal to the top Via header field of the original
        /// request.  The CSeq header field in the ACK MUST contain the same
        /// value for the sequence number as was present in the original request,
        /// but the method parameter MUST be equal to "ACK".
        ///
        /// If the INVITE request whose response is being acknowledged had Route
        /// header fields, those header fields MUST appear in the ACK.  This is
        /// to ensure that the ACK can be routed properly through any downstream
        /// stateless proxies.
        ///
        /// From RFC 3261 Chapter 13.2.2.4 - ACK for 2xx final responses
        ///
        /// IMPORTANT:
        /// an ACK for a 2xx final response is a new transaction and has a new branch ID.
        ///
        /// The UAC core MUST generate an ACK request for each 2xx received from
        /// the transaction layer.  The header fields of the ACK are constructed
        /// in the same way as for any request sent within a dialog (see Section
        /// 12) with the exception of the CSeq and the header fields related to
        /// authentication.  The sequence number of the CSeq header field MUST be
        /// the same as the INVITE being acknowledged, but the CSeq method MUST
        /// be ACK.  The ACK MUST contain the same credentials as the INVITE.  If
        /// the 2xx contains an offer (based on the rules above), the ACK MUST
        /// carry an answer in its body.  If the offer in the 2xx response is not
        /// acceptable, the UAC core MUST generate a valid answer in the ACK and
        /// then send a BYE immediately.
        /// </remarks>
        private SIPRequest GetNewTransactionACKRequest(SIPResponse sipResponse, SIPURI ackURI, SIPEndPoint localSIPEndPoint)
        {
            SIPRequest ackRequest = new SIPRequest(SIPMethodsEnum.ACK, ackURI.ToString())
            {
                LocalSIPEndPoint = localSIPEndPoint
            };

            SIPHeader header = new SIPHeader(TransactionRequest.Header.From, sipResponse.Header.To, sipResponse.Header.CSeq, sipResponse.Header.CallId)
            {
                CSeqMethod           = SIPMethodsEnum.ACK,
                AuthenticationHeader = TransactionRequest.Header.AuthenticationHeader,
                ProxySendFrom        = base.TransactionRequest.Header.ProxySendFrom
            };

            // If the UAS supplies a desired Record-Route list use that first. Otherwise fall back to any Route list used in the original transaction.
            if (sipResponse.Header.RecordRoutes != null)
            {
                header.Routes = sipResponse.Header.RecordRoutes.Reversed();
            }
            else if (base.TransactionRequest.Header.Routes != null)
            {
                header.Routes = base.TransactionRequest.Header.Routes;
            }

            ackRequest.Header = header;

            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId());

            ackRequest.Header.Vias.PushViaHeader(viaHeader);

            return(ackRequest);
        }
Ejemplo n.º 2
0
        public string CreateBranchId()
        {
            string routeStr   = (Header.Routes != null) ? Header.Routes.ToString() : null;
            string toTagStr   = (Header.To != null) ? Header.To.ToTag : null;
            string fromTagStr = (Header.From != null) ? Header.From.FromTag : null;
            string topViaStr  = (Header.Vias != null && Header.Vias.TopViaHeader != null) ? Header.Vias.TopViaHeader.ToString() : null;

            return(CallProperties.CreateBranchId(
                       SIPConstants.SIP_BRANCH_MAGICCOOKIE,
                       toTagStr,
                       fromTagStr,
                       Header.CallId,
                       URI.ToString(),
                       topViaStr,
                       Header.CSeq,
                       routeStr,
                       Header.ProxyRequire,
                       null));
        }
Ejemplo n.º 3
0
        private SIPRequest GetByeRequest(SIPEndPoint localSIPEndPoint)
        {
            SIPRequest    byeRequest    = new SIPRequest(SIPMethodsEnum.BYE, RemoteTarget);
            SIPFromHeader byeFromHeader = SIPFromHeader.ParseFromHeader(LocalUserField.ToString());
            SIPToHeader   byeToHeader   = SIPToHeader.ParseToHeader(RemoteUserField.ToString());
            int           cseq          = CSeq + 1;

            SIPHeader byeHeader = new SIPHeader(byeFromHeader, byeToHeader, cseq, CallId);

            byeHeader.CSeqMethod            = SIPMethodsEnum.BYE;
            byeRequest.Header               = byeHeader;
            byeRequest.Header.Routes        = RouteSet;
            byeRequest.Header.ProxySendFrom = ProxySendFrom;

            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId());

            byeRequest.Header.Vias.PushViaHeader(viaHeader);

            return(byeRequest);
        }
Ejemplo n.º 4
0
            private SIPRequest GetDummyINVITERequest(SIPURI dummyURI)
            {
                string     dummyFrom     = "<sip:[email protected]>";
                string     dummyContact  = "sip:127.0.0.1:1234";
                SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, dummyURI);

                SIPHeader inviteHeader = new SIPHeader(SIPFromHeader.ParseFromHeader(dummyFrom), new SIPToHeader(null, dummyURI, null), 1, CallProperties.CreateNewCallId());

                inviteHeader.From.FromTag = CallProperties.CreateNewTag();
                inviteHeader.Contact      = SIPContactHeader.ParseContactHeader(dummyContact);
                inviteHeader.CSeqMethod   = SIPMethodsEnum.INVITE;
                inviteHeader.UserAgent    = "unittest";
                inviteRequest.Header      = inviteHeader;

                SIPViaHeader viaHeader = new SIPViaHeader("127.0.0.1", 1234, CallProperties.CreateBranchId(), SIPProtocolsEnum.udp);

                inviteRequest.Header.Vias.PushViaHeader(viaHeader);

                inviteRequest.Body = "dummy";
                inviteRequest.Header.ContentLength = inviteRequest.Body.Length;
                inviteRequest.Header.ContentType   = "application/sdp";

                return(inviteRequest);
            }