示例#1
0
        public void Parse183SessionProgress()
        {
            const string HexData =
                "5349502f322e30203138332053657373696f6e2050726f67726573730d0a416c6c6f773a20494e564954452c4259452c52454749535445522c41434b2c4f5054494f4e532c43414e43454c2c494e464f2c5355425343524942452c4e4f544946592c52454645522c5550444154450d0a43616c6c2d49443a2033646534363232302d343038622d343065302d386164612d3436393366616530386437394031302e302e352e32350d0a436f6e746163743a203c7369703a31353439394031302e302e382e34343a353036303e0d0a436f6e74656e742d547970653a206d756c7469706172742f6d697865643b626f756e646172793d756e697175652d626f756e646172792d310d0a435365713a203220494e564954450d0a46726f6d3a203c7369703a31313939323937313732314031302e302e352e32353a353036303b757365723d70686f6e653e0d0a526571756972653a2031303072656c0d0a525365713a20310d0a53657373696f6e2d49443a2030316538316263313366363434356262646130313161633866376431323564330d0a537570706f727465643a2074696d65722c7265706c616365730d0a546f3a203c7369703a31353439394031302e302e382e34343a353036303b757365723d70686f6e653e3b7461673d363833312d463133330d0a5669613a205349502f322e302f5544502031302e302e352e32353a353036303b72656365697665643d31302e302e352e32353b6272616e63683d7a39684734624b3766653864316366323864333831383631660d0a436f6e74656e742d4c656e6774683a203430380d0a0d0a2d2d756e697175652d626f756e646172792d310d0a436f6e74656e742d547970653a206170706c69636174696f6e2f7364700d0a0d0a763d300d0a6f3d2d2039203020494e204950342031302e302e382e34340d0a733d2d0d0a633d494e204950342031302e302e382e34340d0a743d3020300d0a6d3d617564696f203130303136205254502f4156502038203130310d0a613d7274706d61703a382050434d412f383030300d0a613d7274706d61703a3130312074656c6570686f6e652d6576656e742f383030300d0a613d666d74703a31303120302d31350d0a613d7074696d653a32340d0a613d73656e64726563760d0a0d0a2d2d756e697175652d626f756e646172792d310d0a436f6e74656e742d547970653a206170706c69636174696f6e2f495355503b76657273696f6e3d6974752d7439322b3b626173653d6e7876330d0a436f6e74656e742d446973706f736974696f6e3a207369676e616c3b68616e646c696e673d6f7074696f6e616c0d0a0d0a06120001290101000d0a2d2d756e697175652d626f756e646172792d312d2d0d0a";

            var binaryData = HexData.ToByteArray().ToArray();

            SipMessage.Parse(binaryData);
        }
示例#2
0
        public void Shall_parse_response_bytes()
        {
            const string str =
                "SIP/2.0 200 OK\r\nContent-Length: 0\r\n" +
                "\r\n";
            var response = (SipResponse)SipMessage.Parse(Encoding.UTF8.GetBytes(str));

            Assert.That(response.Version, Is.EqualTo("SIP/2.0"));
            Assert.That(response.StatusCode, Is.EqualTo(200));
            Assert.That(response.ReasonPhrase, Is.EqualTo("OK"));
        }
示例#3
0
        public void Shall_clone_request()
        {
            const string str =
                "INVITE sip:[email protected] SIP/2.0\r\n" +
                "From: John Smith <sip:[email protected]>\r\n" +
                "To: Joe Shmoe <sip:[email protected]>\r\n\r\n";
            var original = (SipRequest)SipMessage.Parse(str);
            var cloned   = original.DeepClone();

            original.Method = "REGISTER";

            Assert.That(cloned.ToString(), Does.Contain("INVITE"));
            Assert.That(original.Method, Does.Contain("REGISTER"));
        }
示例#4
0
        public void Shall_clone_response()
        {
            const string str =
                "SIP/2.0 200 OK\r\nContent-Length: 0\r\n" +
                "\r\n";
            var original = (SipResponse)SipMessage.Parse(str);
            var cloned   = original.DeepClone();

            original.StatusCode   = 183;
            original.ReasonPhrase = "Session Progress";

            Assert.That(cloned.ToString(), Does.Contain("200 OK"));
            Assert.That(original.ToString(), Does.Contain("183 Session Progress"));
        }
示例#5
0
        public void Shall_set_level()
        {
            try
            {
                TraceEvent traceEvent = null;

                Trace.SetLogger(e => { traceEvent = e; });
                Trace.SetLevel(TraceLevel.Fatal);

                SipMessage.Parse("INVITE sip:[email protected] SIP/0.0\r\n\r\n");

                Assert.That(traceEvent, Is.Null);
            }
            finally
            {
                Trace.SetLogger(null);
            }
        }
示例#6
0
        public void Shall_intercept_trace()
        {
            try
            {
                TraceEvent traceEvent = null;
                Trace.SetLogger(e => { traceEvent = e; });

                SipMessage.Parse("INVITE sip:[email protected] SIP/0.0\r\n\r\n");

                Assert.That(traceEvent.FileName, Is.EqualTo("osip_message_parse.c"));
                Assert.That(traceEvent.LineNumber, Is.EqualTo(168));
                Assert.That(traceEvent.Level, Is.EqualTo(TraceLevel.Error));
                Assert.That(traceEvent.Message, Is.EqualTo("Wrong version number\n"));
            }
            finally
            {
                Trace.SetLogger(null);
            }
        }
示例#7
0
        public void Shall_byteify_response()
        {
            var response = new SipResponse
            {
                Version      = "SIP/2.0",
                StatusCode   = 200,
                ReasonPhrase = "OK"
            };

            var buffer = new byte[ushort.MaxValue];

            response.TryCopyTo(buffer, 0, out int length);

            var response2 = (SipResponse)SipMessage.Parse(new ArraySegment <byte>(buffer, 0, length));

            Assert.That(response2.ToString(), Is.EqualTo(
                            "SIP/2.0 200 OK\r\nContent-Length: 0\r\n" +
                            "\r\n"));
        }
示例#8
0
文件: Sip.cs 项目: inrg/sipstack
        public void DeserializeInviteMessageWithIsupAndSdp(bool includeIsup, bool includeSdp)
        {
            MediaGateway.RegisterCodec(MediaGateway.AudioCodec.G711Alaw, () => new AlawMediaCodec(null, null));

            const string CallId  = "ABC";
            const string LocalIp = "127.0.0.1";

            Contact to    = "[email protected]:5060;user=phone";
            var     @from = new Contact(
                "[email protected]:5060",
                null,
                new[] { new KeyValuePair <string, string>("user", "phone") });

            Contact callerContact = "[email protected]:5060";

            var invite = new InviteMessage(CallId, to, @from, @from);

            var port = MediaGateway.GetNextPort();

            if (includeSdp)
            {
                invite.SdpData = new Sdp();
                invite.SdpData.AddParameter("o", string.Format("- {0} 0 IN IP4 {1}", 10, LocalIp))
                .AddParameter("s", "-")
                .AddParameter("c", "IN IP4 " + LocalIp)
                .AddParameter("t", "0 0")
                .AddParameter("m", string.Format("audio {0} RTP/AVP 8 101", port))
                .AddParameter("a", "rtpmap:8 PCMA/8000")
                .AddParameter("a", "rtpmap:101 telephone-event/8000")
                .AddParameter("a", "fmtp:101 0-15").AddParameter("a", "sendrecv");
            }

            if (includeIsup)
            {
                var isup = new IsupInitialAddress();
                invite.IsupData = isup;
                isup.ForwardCallIndicator.LoadParameterData(new byte[] { 0x20, 0x01 });
                isup.CallingPartyCategory.CategoryFlags = CallingPartyCategory.Category.Unknown;
                isup.NatureOfConnectionIndicator.EchoControlIncluded      = false;
                isup.NatureOfConnectionIndicator.ContinuityCheckIndicator =
                    NatureOfConnection.ContinuityCheckIndicatorFlags.NotRequired;
                isup.NatureOfConnectionIndicator.SatelliteIndicator = NatureOfConnection.SatelliteIndicatorFlags.One;

                isup.CalledNumber.Number = new string(invite.To.Address.TakeWhile(a => a != '@').ToArray());

                isup.CalledNumber.NumberingFlags = NAIFlags.RoutingNotAllowed | NAIFlags.Isdn;
                isup.CalledNumber.Flags          = PhoneFlags.NAINationalNumber;

                var callingNumber = invite.IsupData.AddOptionalParameter(new IsupPhoneNumberParameter(IsupParameterType.CallingPartyNumber)
                {
                    Number = invite.From.Address.Split('@').FirstOrDefault()
                });

                callingNumber.NumberingFlags |= NAIFlags.ScreeningVerifiedAndPassed | NAIFlags.NetworProvided;

                isup.AddOptionalParameter(new IsupPhoneNumberParameter(IsupParameterType.OriginalCalledNumber)
                {
                    Number         = callerContact.Address.Split('@').FirstOrDefault(),
                    Flags          = callingNumber.Flags,
                    NumberingFlags = NAIFlags.PresentationRestricted | NAIFlags.Isdn
                });

                isup.AddOptionalParameter(new IsupPhoneNumberParameter(IsupParameterType.RedirectingNumber)
                {
                    Number         = callerContact.Address.Split('@').FirstOrDefault(),
                    Flags          = callingNumber.Flags,
                    NumberingFlags = NAIFlags.PresentationRestricted | NAIFlags.Isdn
                });

                isup.AddOptionalParameter(new RedirectInfo {
                    RedirectReason = RedirReason.NoReply, RedirectCounter = 1, RedirectIndicatorFlags = RedirectInfo.RedirectIndicator.CallDiverted
                });
            }

            if (includeSdp)
            {
                invite.Headers["Via"] = string.Format("SIP/2.0/UDP {0}:5060;branch=z9hG4bK7fe{1}", LocalIp, DateTime.Now.Ticks.ToString("X8").ToLowerInvariant());
            }

            var bytes = invite.Serialize();

            var deserialized = SipMessage.Parse(bytes) as InviteMessage;

            Assert.IsNotNull(deserialized, "message isn't an invite");

            Assert.That(invite.Contact, Is.EqualTo(deserialized.Contact));
            Assert.AreEqual(invite.Contact.ToString(), deserialized.Contact.ToString());

            Assert.AreEqual(invite.From, deserialized.From);
            Assert.AreEqual(invite.To, deserialized.To);

            if (includeSdp)
            {
                Assert.AreEqual(invite.SdpData.ContentText, deserialized.SdpData.ContentText);
            }

            if (includeIsup)
            {
                Assert.AreEqual(invite.IsupData.GetByteArray().ToHex().ToUpper(), deserialized.IsupData.GetByteArray().ToHex().ToUpper());
            }

            Assert.AreEqual(invite.Method, deserialized.Method);
        }
示例#9
0
        public void Shall_byteify_request()
        {
            var request = new SipRequest
            {
                Version     = "SIP/2.0",
                Method      = "INVITE",
                RequestUri  = SipUri.Parse("sip:[email protected]"),
                From        = NameAddressHeader.Parse("John Smith <sip:[email protected]>"),
                To          = NameAddressHeader.Parse("Joe Shmoe <sip:[email protected]>"),
                CallId      = CallIdHeader.Parse("*****@*****.**"),
                CSeq        = CSeqHeader.Parse("1 INVITE"),
                ContentType = ContentTypeHeader.Parse("text/plain"),
                MimeVersion = ContentLengthHeader.Parse("1.0")
            };

            request.Vias.Add(ViaHeader.Parse("SIP/2.0/UDP foo.bar.com"));
            request.RecordRoutes.Add(NameAddressHeader.Parse("Tommy Atkins <sip:[email protected]>"));
            request.Routes.Add(NameAddressHeader.Parse("John Doe <sip:[email protected]>"));
            request.Contacts.Add(NameAddressHeader.Parse("Prisoner X <sip:[email protected]>"));
            request.Authorizations.Add(AuthorizationHeader.Parse("Digest username=\"Alice\""));
            request.WwwAuthenticates.Add(WwwAuthenticateHeader.Parse("Digest realm=\"abc.com\""));
            request.ProxyAuthenticates.Add(WwwAuthenticateHeader.Parse("Digest realm=\"xyz.com\""));
            request.ProxyAuthorizations.Add(AuthorizationHeader.Parse("Digest username=\"Bob\""));
            request.CallInfos.Add(CallInfoHeader.Parse("<http://www.abc.com/photo.png>;purpose=icon"));
            request.Allows.Add(ContentLengthHeader.Parse("INVITE, ACK, BYE"));
            request.ContentEncodings.Add(ContentLengthHeader.Parse("deflate"));
            request.AlertInfos.Add(CallInfoHeader.Parse("<http://www.abc.com/sound.wav>"));
            request.ErrorInfos.Add(CallInfoHeader.Parse("<sip:[email protected]>"));
            request.Accepts.Add(ContentTypeHeader.Parse("application/sdp"));
            request.AcceptEncodings.Add(AcceptEncodingHeader.Parse("gzip"));
            request.AcceptLanguages.Add(AcceptEncodingHeader.Parse("en"));
            request.AuthenticationInfos.Add(AuthenticationInfoHeader.Parse("nextnonce=\"abc\""));
            request.ProxyAuthenticationInfos.Add(AuthenticationInfoHeader.Parse("nextnonce=\"def\""));
            request.OtherHeaders.Add(new GenericHeader("P-Asserted-Identity", "sip:[email protected]"));
            request.Bodies.Add(SipBody.Parse("Hello world!"));

            var buffer  = new byte[ushort.MaxValue];
            var success = request.TryCopyTo(buffer, 0, out int length);

            Assert.That(success, Is.True);

            var request2 = SipMessage.Parse(new ArraySegment <byte>(buffer, 0, length));

            Assert.That(request2.ToString(), Is.EqualTo(
                            "INVITE sip:[email protected] SIP/2.0\r\n" +
                            "Via: SIP/2.0/UDP foo.bar.com\r\n" +
                            "Record-Route: Tommy Atkins <sip:[email protected]>\r\n" +
                            "Route: John Doe <sip:[email protected]>\r\n" +
                            "From: John Smith <sip:[email protected]>\r\n" +
                            "To: Joe Shmoe <sip:[email protected]>\r\n" +
                            "Call-ID: [email protected]\r\n" +
                            "CSeq: 1 INVITE\r\n" +
                            "Contact: Prisoner X <sip:[email protected]>\r\n" +
                            "Authorization: Digest username=\"Alice\"\r\n" +
                            "WWW-Authenticate: Digest realm=\"abc.com\"\r\n" +
                            "Proxy-Authenticate: Digest realm=\"xyz.com\"\r\n" +
                            "Proxy-Authorization: Digest username=\"Bob\"\r\n" +
                            "Call-Info: <http://www.abc.com/photo.png>;purpose=icon\r\n" +
                            "Content-Type: text/plain\r\n" +
                            "Mime-Version: 1.0\r\n" +
                            "Allow: INVITE\r\n" +
                            "Allow: ACK\r\n" +
                            "Allow: BYE\r\n" +
                            "Content-Encoding: deflate\r\n" +
                            "Alert-Info: <http://www.abc.com/sound.wav>\r\n" +
                            "Error-Info: <sip:[email protected]>\r\n" +
                            "Accept: application/sdp\r\n" +
                            "Accept-Encoding: gzip\r\n" +
                            "Accept-Language: en\r\n" +
                            "Authentication-Info: nextnonce=\"abc\"\r\n" +
                            "Proxy-Authentication-Info: nextnonce=\"def\"\r\n" +
                            "P-asserted-identity: sip:[email protected]\r\n" +
                            "Content-Length:    12\r\n" +
                            "\r\n" +
                            "Hello world!"));
        }
示例#10
0
        public void Shall_parse_request_bytes()
        {
            const string str =
                "INVITE sip:[email protected] SIP/2.0\r\n" +
                "Via: SIP/2.0/UDP foo.bar.com\r\n" +
                "Record-Route: Tommy Atkins <sip:[email protected]>\r\n" +
                "Route: John Doe <sip:[email protected]>\r\n" +
                "From: John Smith <sip:[email protected]>\r\n" +
                "To: Joe Shmoe <sip:[email protected]>\r\n" +
                "Call-ID: [email protected]\r\n" +
                "CSeq: 1 INVITE\r\n" +
                "Contact: Prisoner X <sip:[email protected]>\r\n" +
                "Authorization: Digest username=\"Alice\"\r\n" +
                "WWW-Authenticate: Digest realm=\"abc.com\"\r\n" +
                "Proxy-Authenticate: Digest realm=\"xyz.com\"\r\n" +
                "Proxy-Authorization: Digest username=\"Bob\"\r\n" +
                "Call-Info: <http://www.abc.com/photo.png>;purpose=icon\r\n" +
                "Content-Type: text/plain\r\n" +
                "Mime-Version: 1.0\r\n" +
                "Allow: INVITE, BYE\r\n" +
                "Content-Encoding: deflate\r\n" +
                "Alert-Info: <http://www.abc.com/sound.wav>\r\n" +
                "Error-Info: <sip:[email protected]>\r\n" +
                "Accept: application/sdp\r\n" +
                "Accept-Encoding: gzip\r\n" +
                "Accept-Language: en\r\n" +
                "Authentication-Info: nextnonce=\"abc\"\r\n" +
                "Proxy-Authentication-Info: nextnonce=\"def\"\r\n" +
                "P-Asserted-Identity: sip:[email protected]\r\n" +
                "Content-Length:    12\r\n" +
                "\r\n" +
                "Hello world!";
            var request = (SipRequest)SipMessage.Parse(Encoding.UTF8.GetBytes(str));

            Assert.That(request.Version, Is.EqualTo("SIP/2.0"));
            Assert.That(request.Method, Is.EqualTo("INVITE"));
            Assert.That(request.RequestUri.ToString(), Is.EqualTo("sip:[email protected]"));
            Assert.That(request.Vias[0].ToString(), Is.EqualTo("SIP/2.0/UDP foo.bar.com"));
            Assert.That(request.RecordRoutes[0].ToString(), Is.EqualTo("Tommy Atkins <sip:[email protected]>"));
            Assert.That(request.Routes[0].ToString(), Is.EqualTo("John Doe <sip:[email protected]>"));
            Assert.That(request.From.ToString(), Is.EqualTo("John Smith <sip:[email protected]>"));
            Assert.That(request.To.ToString(), Is.EqualTo("Joe Shmoe <sip:[email protected]>"));
            Assert.That(request.CallId.ToString(), Is.EqualTo("*****@*****.**"));
            Assert.That(request.CSeq.ToString(), Is.EqualTo("1 INVITE"));
            Assert.That(request.Contacts[0].ToString(), Is.EqualTo("Prisoner X <sip:[email protected]>"));
            Assert.That(request.Authorizations[0].ToString(), Is.EqualTo("Digest username=\"Alice\""));
            Assert.That(request.WwwAuthenticates[0].ToString(), Is.EqualTo("Digest realm=\"abc.com\""));
            Assert.That(request.ProxyAuthenticates[0].ToString(), Is.EqualTo("Digest realm=\"xyz.com\""));
            Assert.That(request.ProxyAuthorizations[0].ToString(), Is.EqualTo("Digest username=\"Bob\""));
            Assert.That(request.CallInfos[0].ToString(), Is.EqualTo("<http://www.abc.com/photo.png>;purpose=icon"));
            Assert.That(request.ContentType.ToString(), Is.EqualTo("text/plain"));
            Assert.That(request.MimeVersion.ToString(), Is.EqualTo("1.0"));
            Assert.That(request.Allows.Count, Is.EqualTo(2));
            Assert.That(request.Allows[0].ToString(), Is.EqualTo("INVITE"));
            Assert.That(request.Allows[1].ToString(), Is.EqualTo("BYE"));
            Assert.That(request.ContentEncodings[0].ToString(), Is.EqualTo("deflate"));
            Assert.That(request.AlertInfos[0].ToString(), Is.EqualTo("<http://www.abc.com/sound.wav>"));
            Assert.That(request.ErrorInfos[0].ToString(), Is.EqualTo("<sip:[email protected]>"));
            Assert.That(request.Accepts[0].ToString(), Is.EqualTo("application/sdp"));
            Assert.That(request.AcceptEncodings[0].ToString(), Is.EqualTo("gzip"));
            Assert.That(request.AcceptLanguages[0].ToString(), Is.EqualTo("en"));
            Assert.That(request.AuthenticationInfos[0].ToString(), Is.EqualTo("nextnonce=\"abc\""));
            Assert.That(request.ProxyAuthenticationInfos[0].ToString(), Is.EqualTo("nextnonce=\"def\""));
            Assert.That(request.OtherHeaders[0].Name, Is.EqualTo("p-asserted-identity"));
            Assert.That(request.OtherHeaders[0].Value, Is.EqualTo("sip:[email protected]"));
            Assert.That(request.ContentLength.ToString(), Is.EqualTo("12"));
            Assert.That(request.Bodies[0].ToString(), Is.EqualTo("Hello world!"));
        }
示例#11
0
        public void SipResponse_Serialize()
        {
            SipResponse response;
            string      input;
            string      output;

            input =
                @"SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.200
Content-Length: 0

";
            response = (SipResponse)SipMessage.Parse(Helper.ToUTF8(input), true);
            Assert.AreEqual("SIP/2.0", response.SipVersion);
            Assert.AreEqual(SipStatus.OK, response.Status);
            Assert.AreEqual("OK", response.ReasonPhrase);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", response[SipHeader.Via].Text);
            Assert.AreEqual("0", response[SipHeader.ContentLength].Text);

            output = response.ToString();
            Assert.AreEqual(input, output);
            CollectionAssert.AreEqual(Helper.ToUTF8(input), response.ToArray());

            // Header continuation

            input =
                @"SIP/2.0 200 OK
Via: SIP/2.0/UDP
 192.168.1.200
Content-Length: 0

";
            response = (SipResponse)SipMessage.Parse(Helper.ToUTF8(input), true);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", response[SipHeader.Via].Text);
            Assert.AreEqual("0", response[SipHeader.ContentLength].Text);

            // Data with Content-Length header

            input =
                @"SIP/2.0 200 OK
Via: SIP/2.0/UDP
 192.168.1.200
Content-Length: 4

";
            response = (SipResponse)SipMessage.Parse(Helper.Concat(Helper.ToUTF8(input), new byte[] { 0, 1, 2, 3 }), true);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", response[SipHeader.Via].Text);
            Assert.AreEqual("4", response[SipHeader.ContentLength].Text);
            Assert.AreEqual(4, response.ContentLength);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, response.Contents);

            // Data with no Content-Length header

            input =
                @"SIP/2.0 200 OK
Via: 
 SIP/2.0/UDP
 192.168.1.200

";
            response = (SipResponse)SipMessage.Parse(Helper.Concat(Helper.ToUTF8(input), new byte[] { 0, 1, 2, 3 }), true);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", response[SipHeader.Via].Text);
            Assert.IsNull(response[SipHeader.ContentLength]);
            Assert.AreEqual(4, response.ContentLength);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, response.Contents);
        }
示例#12
0
        public void Parse100Trying(string msg)
        {
            var bytes = Encoding.Default.GetBytes(msg);

            SipMessage.Parse(bytes);
        }
示例#13
0
        public void SipRequest_Serialize()
        {
            SipRequest request;
            string     input;
            string     output;

            input =
                @"INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 192.168.1.200
Content-Length: 0

";
            request = (SipRequest)SipMessage.Parse(Helper.ToUTF8(input), true);
            Assert.AreEqual("SIP/2.0", request.SipVersion);
            Assert.AreEqual("INVITE", request.MethodText);
            Assert.AreEqual(SipMethod.Invite, request.Method);
            Assert.AreEqual("sip:[email protected]", request.Uri);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", request[SipHeader.Via].Text);
            Assert.AreEqual("0", request[SipHeader.ContentLength].Text);

            output = request.ToString();
            Assert.AreEqual(input, output);
            CollectionAssert.AreEqual(Helper.ToUTF8(input), request.ToArray());

            // Header continuation

            input =
                @"invite sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP
 192.168.1.200
Content-Length: 0

";
            request = (SipRequest)SipMessage.Parse(Helper.ToUTF8(input), true);
            Assert.AreEqual("SIP/2.0", request.SipVersion);
            Assert.AreEqual("INVITE", request.MethodText);
            Assert.AreEqual(SipMethod.Invite, request.Method);
            Assert.AreEqual("sip:[email protected]", request.Uri);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", request[SipHeader.Via].Text);
            Assert.AreEqual("0", request[SipHeader.ContentLength].Text);

            // Data with Content-Length header

            input =
                @"register sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP
 192.168.1.200
Content-Length: 4

";
            request = (SipRequest)SipMessage.Parse(Helper.Concat(Helper.ToUTF8(input), new byte[] { 0, 1, 2, 3 }), true);
            Assert.AreEqual("REGISTER", request.MethodText);
            Assert.AreEqual(SipMethod.Register, request.Method);
            Assert.AreEqual("SIP/2.0", request.SipVersion);
            Assert.AreEqual("sip:[email protected]", request.Uri);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", request[SipHeader.Via].Text);
            Assert.AreEqual("4", request[SipHeader.ContentLength].Text);
            Assert.AreEqual(4, request.ContentLength);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, request.Contents);

            // Data with no Content-Length header

            input =
                @"INVITE sip:[email protected] SIP/2.0
Via: 
 SIP/2.0/UDP
 192.168.1.200

";
            request = (SipRequest)SipMessage.Parse(Helper.Concat(Helper.ToUTF8(input), new byte[] { 0, 1, 2, 3 }), true);
            Assert.AreEqual("INVITE", request.MethodText);
            Assert.AreEqual(SipMethod.Invite, request.Method);
            Assert.AreEqual("SIP/2.0", request.SipVersion);
            Assert.AreEqual("sip:[email protected]", request.Uri);
            Assert.AreEqual("SIP/2.0/UDP 192.168.1.200", request[SipHeader.Via].Text);
            Assert.IsNull(request[SipHeader.ContentLength]);
            Assert.AreEqual(4, request.ContentLength);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, request.Contents);
        }