The Via header field indicates the path taken by the request so far and indicates the path that should be followed in routing responses.

The branch ID parameter in the Via header field values serves as a transaction identifier, and is used by proxies to detect loops.

A Via header field value contains the transport protocol used to send the message, the client's host name or network address, and possibly the port number at which it wishes to receive responses. A Via header field value can also contain parameters such as "maddr", "ttl", "received", and "branch", whose meaning and use are described in other sections. For implementations compliant to this specification, the value of the branch parameter MUST start with the magic cookie "z9hG4bK", as discussed in Section 8.1.1.7.

The compact form of the via header is "v".

Inheritance: IHeader, ICloneable
Beispiel #1
0
 private ViaEntry(ViaEntry entry)
 {
     Protocol = entry.Protocol;
     SipVersion = entry.SipVersion;
     Transport = entry.Transport;
     Domain = entry.Domain;
     foreach (var pair in entry._parameters)
         _parameters.Add(pair.Key, pair.Value);
 }
Beispiel #2
0
 private ViaEntry(ViaEntry entry)
 {
     Protocol   = entry.Protocol;
     SipVersion = entry.SipVersion;
     Transport  = entry.Transport;
     Domain     = entry.Domain;
     foreach (var pair in entry._parameters)
     {
         _parameters.Add(pair.Key, pair.Value);
     }
 }
Beispiel #3
0
        public static ViaEntry ParseEntry(ITextReader reader)
        {
            //SIP/2.0/UDP erlang.bell-telephone.com:5060;branch=z9hG4bK87asdks7
            var entry = new ViaEntry();

            // read SIP/
            reader.ConsumeWhiteSpaces();
            entry.Protocol = reader.ReadUntil("/ \t");
            if (entry.Protocol == null)
                throw new FormatException("Expected Via header to start with 'SIP' or 'SIPS'.");
            reader.ConsumeWhiteSpaces('/');

            // read 2.0/
            entry.SipVersion = reader.ReadUntil("/ \t");
            if (entry.SipVersion == null)
                throw new FormatException("Expected to find sip version in Via header.");
            reader.ConsumeWhiteSpaces('/');

            // read UDP or TCP
            entry.Transport = reader.ReadWord();
            if (entry.Transport == null)
                throw new FormatException("Expected to find transport protocol after sip version in Via header.");
            reader.ConsumeWhiteSpaces();

            entry.Domain = reader.ReadUntil(";: \t");
            if (entry.Domain == null)
                throw new FormatException("Failed to find domain in via header.");
            reader.ConsumeWhiteSpaces();

            if (reader.Current == ':')
            {
                reader.Read();
                reader.ConsumeWhiteSpaces();
                string temp = reader.ReadToEnd("; \t");
                reader.ConsumeWhiteSpaces();
                int port;
                if (!int.TryParse(temp, out port))
                    throw new FormatException("Invalid port specified.");
                entry.Port = port;
            }

            UriParser.ParseParameters(entry.Parameters, reader);
            string rport = entry.Parameters["rport"];
            if (!string.IsNullOrEmpty(rport)) //parameter can exist, but be empty. = rport requested.
            {
                int value;
                if (!int.TryParse(rport, out value))
                    throw new FormatException("RPORT is not a number.");
                entry.Rport = value;
            }

            return entry;
        }
Beispiel #4
0
        /// <summary>
        /// Create a new request
        /// </summary>
        /// <param name="method">Sip method.</param>
        /// <param name="from">Who is dialing?</param>
        /// <param name="to">Destination</param>
        /// <returns>Request object.</returns>
        /// <seealso cref="SipMethod"/>
        public IRequest CreateRequest(string method, Contact from, Contact to)
        {
            // A valid SIP request formulated by a UAC MUST, at a minimum, contain
            // the following header fields: To, From, CSeq, Call-ID, Max-Forwards,
            // and Via; all of these header fields are mandatory in all SIP
            // requests.  These six header fields are the fundamental building
            // blocks of a SIP message, as they jointly provide for most of the
            // critical message routing services including the addressing of
            // messages, the routing of responses, limiting message propagation,
            // ordering of messages, and the unique identification of transactions.
            // These header fields are in addition to the mandatory request line,
            // which contains the method, Request-URI, and SIP version.

            // The initial Request-URI of the message SHOULD be set to the value of
            // the URI in the To field.  One notable exception is the REGISTER
            // method; behavior for setting the Request-URI of REGISTER is given in
            // Section 10.
            var request = new Request(method, from.Uri, "SIP/2.0");
            request.From = from;

            // A request outside of a dialog MUST NOT contain a To tag; the tag in
            // the To field of a request identifies the peer of the dialog.  Since
            // no dialog is established, no tag is present.
            // For further information on the To header field, see RFC 3261 Section 20.39.
            request.To = to;

            // The Call-ID header field acts as a unique identifier to group
            // together a series of messages.  It MUST be the same for all requests
            // and responses sent by either UA in a dialog.  It SHOULD be the same
            // in each registration from a UA.
            // In a new request created by a UAC outside of any dialog, the Call-ID
            // header field MUST be selected by the UAC as a globally unique
            // identifier over space and time unless overridden by method-specific
            // behavior.  All SIP UAs must have a means to guarantee that the Call-
            // ID header fields they produce will not be inadvertently generated by
            // any other UA.
            request.CallId = CreateCallId();

            // The CSeq header field serves as a way to identify and order
            // transactions.  It consists of a sequence number and a method.  The
            // method MUST match that of the request.  For non-REGISTER requests
            // outside of a dialog, the sequence number value is arbitrary.  The
            // sequence number value MUST be expressible as a 32-bit unsigned
            // integer and MUST be less than 2**31.  As long as it follows the above
            // guidelines, a client may use any mechanism it would like to select
            // CSeq header field values.
            request.CSeq = new CSeq(GetNextSequenceNumber(), method);

            request.MaxForwards = 70;

            // When the UAC creates a request, it MUST insert a Via into that
            // request.  The protocol name and protocol version in the header field
            // MUST be SIP and 2.0, respectively.  The Via header field value MUST
            // contain a branch parameter.  This parameter is used to identify the
            // transaction created by that request.  This parameter is used by both
            // the client and the server.
            //
            // The branch parameter value MUST be unique across space and time for
            // all requests sent by the UA.  The exceptions to this rule are CANCEL
            // and ACK for non-2xx responses.  As discussed below, a CANCEL request
            // will have the same value of the branch parameter as the request it
            // cancels.  As discussed in Section 17.1.1.3, an ACK for a non-2xx
            // response will also have the same branch ID as the INVITE whose
            // response it acknowledges.
            //
            //    The uniqueness property of the branch ID parameter, to facilitate
            //    its use as a transaction ID, was not part of RFC 2543.
            //
            // The branch ID inserted by an element compliant with this
            // specification MUST always begin with the characters "z9hG4bK".  These
            // 7 characters are used as a magic cookie (7 is deemed sufficient to
            // ensure that an older RFC 2543 implementation would not pick such a
            // value), so that servers receiving the request can determine
            // specification (that is, globally unique).  Beyond this requirement,
            // the precise format of the branch token is implementation-defined.
            //
            // The Via header maddr, ttl, and sent-by components will be set when
            // the request is processed by the transport layer (Section 18).
            //
            // Via processing for proxies is described in Section 16.6 Item 8 and
            // Section 16.7 Item 3.
            var viaEntry = new ViaEntry(_endPoint.Address.ToString(), CreateBranch());
            viaEntry.RportWanted = true;
            request.Via.Add(viaEntry);

            // The Contact header field provides a SIP or SIPS URI that can be used
            // to contact that specific instance of the UA for subsequent requests.
            // The Contact header field MUST be present and contain exactly one SIP
            // or SIPS URI in any request that can result in the establishment of a
            // dialog.  For the methods defined in this specification, that includes
            // only the INVITE request.  For these requests, the scope of the
            // Contact is global.  That is, the Contact header field value contains
            // the URI at which the UA would like to receive requests, and this URI
            // MUST be valid even if used in subsequent requests outside of any
            // dialogs.
            //
            // If the Request-URI or top Route header field value contains a SIPS
            // URI, the Contact header field MUST contain a SIPS URI as well.
            request.Contact = _contact;

            return request;
        }