From 4e405741c0a713da07079b7e11604eacc5718b60 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 11 May 2026 15:03:56 +0000 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=E5=BC=95=E5=85=A5=20fixture=20?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E9=93=BE=EF=BC=88.gitattributes=20+=20tools/?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .gitattributes:将 *.raw 标记为 binary,禁止 git/编辑器对 SIP wire-format 做 CRLF↔LF 转换;其他源代码文件统一 LF。 - tools/write_fixture.py:从 .fixture 源文件(LF)生成 byte-exact .raw(CRLF) 和 .expect.properties 双文件。详细约定见脚本内文档。 - tools/rfc4475/rfc4475.txt:保留 RFC 4475 原始 ASCII 副本,作为后续 fixture byte-exact 提取的事实来源。 - tools/rfc4475/extract_message.py:按 'Message Details : ' 标记从 RFC 正文提取单条消息(剥去 RFC 6 空格缩进、跨页符、分页页脚),便于将更多 fixture 增量纳入仓库。 Co-authored-by: li xuanqun <793005378@qq.com> --- .gitattributes | 11 + .gitignore | 5 + tools/rfc4475/extract_message.py | 96 + tools/rfc4475/rfc4475.txt | 2971 ++++++++++++++++++++++++++++++ tools/write_fixture.py | 101 + 5 files changed, 3184 insertions(+) create mode 100644 .gitattributes create mode 100644 tools/rfc4475/extract_message.py create mode 100644 tools/rfc4475/rfc4475.txt create mode 100755 tools/write_fixture.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1372660 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# SIP wire-format fixtures must preserve CRLF byte-for-byte. Treating them as +# binary disables any text transformation git or editors might otherwise apply. +*.raw binary + +# Java sources, properties, markdown — normal LF normalisation in repo. +*.java text eol=lf +*.xml text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.md text eol=lf +*.properties text eol=lf diff --git a/.gitignore b/.gitignore index 0917b82..0f59b98 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,11 @@ Thumbs.db # Compiled class files *.class +# Python +__pycache__/ +*.pyc +*.pyo + # Package files *.jar *.war diff --git a/tools/rfc4475/extract_message.py b/tools/rfc4475/extract_message.py new file mode 100644 index 0000000..35c274a --- /dev/null +++ b/tools/rfc4475/extract_message.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +""" +Extract a single message body from the RFC 4475 plain-text source. + +RFC 4475 marks the start of each message with a line of the form +`` Message Details : ``. The message itself follows after a blank +line, with each line indented by 6 spaces. The message ends at the next +RFC pagination boundary (a form-feed character ``\\x0c`` or a "Sparks, et +al. Informational [Page N]" footer block) or at the next section header. + +Usage: + python3 tools/rfc4475/extract_message.py > out.txt + +Example: + python3 tools/rfc4475/extract_message.py lwsdisp + +The extractor strips the leading 6 spaces, drops form-feed pagination, +preserves blank lines (which delimit headers from body) and returns the +result on stdout (LF endings — callers wrap it into a .fixture source). +""" + +from __future__ import annotations + +import re +import sys +from pathlib import Path + +INDENT = " " # 6 spaces: RFC body indentation +SOURCE = Path(__file__).parent / "rfc4475.txt" + +PAGE_BREAK = re.compile(r"^Sparks,.*Informational.*\[Page \d+\]\s*$") +SECTION_RE = re.compile(r"^\s*\d+(\.\d+)+\.?\s+\S") +HEADER_RE = re.compile(r"^\s*Message Details\s*:\s*(\S+)\s*$") + + +def extract(text: str, target: str) -> str: + lines = text.splitlines() + n = len(lines) + i = 0 + while i < n: + m = HEADER_RE.match(lines[i]) + if m and m.group(1) == target: + break + i += 1 + if i == n: + raise SystemExit(f"message id not found: {target}") + + # Skip the header line and the mandatory blank line after it. + i += 1 + while i < n and lines[i].strip() == "": + i += 1 + + out: list[str] = [] + while i < n: + line = lines[i] + if "\f" in line: + i += 1 + continue + if PAGE_BREAK.match(line): + i += 1 + continue + if line.startswith("RFC 4475"): + i += 1 + continue + # Section boundary: ends the message. + if SECTION_RE.match(line) and not line.startswith(INDENT): + break + if line.startswith(INDENT): + out.append(line[len(INDENT):]) + elif line.strip() == "": + out.append("") + else: + # Outside the indented block — end of this fixture. + break + i += 1 + + # Trim trailing blank lines so callers can decide body framing. + while out and out[-1] == "": + out.pop() + + return "\n".join(out) + "\n" + + +def main(argv: list[str]) -> int: + if len(argv) != 2: + sys.stderr.write(f"usage: {argv[0]} \n") + return 2 + if not SOURCE.exists(): + sys.stderr.write(f"RFC source not found at {SOURCE}; run curl first\n") + return 1 + sys.stdout.write(extract(SOURCE.read_text(encoding="ascii"), argv[1])) + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/tools/rfc4475/rfc4475.txt b/tools/rfc4475/rfc4475.txt new file mode 100644 index 0000000..3c4e6e5 --- /dev/null +++ b/tools/rfc4475/rfc4475.txt @@ -0,0 +1,2971 @@ + + + + + + +Network Working Group R. Sparks, Ed. +Request for Comments: 4475 Estacado Systems +Category: Informational A. Hawrylyshen + Ditech Networks + A. Johnston + Avaya + J. Rosenberg + Cisco Systems + H. Schulzrinne + Columbia University + May 2006 + + + Session Initiation Protocol (SIP) Torture Test Messages + +Status of This Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2006). + +Abstract + + This informational document gives examples of Session Initiation + Protocol (SIP) test messages designed to exercise and "torture" a SIP + implementation. + +Table of Contents + + 1. Overview ........................................................3 + 2. Document Conventions ............................................3 + 2.1. Representing Long Lines ....................................4 + 2.2. Representing Non-printable Characters ......................4 + 2.3. Representing Long Repeating Strings ........................5 + 3. SIP Test Messages ...............................................5 + 3.1. Parser Tests (syntax) ......................................5 + 3.1.1. Valid Messages ......................................5 + 3.1.1.1. A Short Tortuous INVITE ....................5 + 3.1.1.2. Wide Range of Valid Characters .............8 + 3.1.1.3. Valid Use of the % Escaping Mechanism ......9 + 3.1.1.4. Escaped Nulls in URIs .....................11 + 3.1.1.5. Use of % When It Is Not an Escape .........11 + 3.1.1.6. Message with No LWS between + Display Name and < ........................12 + + + +Sparks, et al. Informational [Page 1] + +RFC 4475 SIP Torture Test Messages May 2006 + + + 3.1.1.7. Long Values in Header Fields ..............12 + 3.1.1.8. Extra Trailing Octets in a UDP Datagram ...14 + 3.1.1.9. Semicolon-Separated Parameters in + URI User Part .............................16 + 3.1.1.10. Varied and Unknown Transport Types .......16 + 3.1.1.11. Multipart MIME Message ...................17 + 3.1.1.12. Unusual Reason Phrase ....................18 + 3.1.1.13. Empty Reason Phrase ......................19 + 3.1.2. Invalid Messages ...................................20 + 3.1.2.1. Extraneous Header Field Separators ........20 + 3.1.2.2. Content Length Larger Than Message ........20 + 3.1.2.3. Negative Content-Length ...................21 + 3.1.2.4. Request Scalar Fields with + Overlarge Values ..........................22 + 3.1.2.5. Response Scalar Fields with + Overlarge Values ..........................23 + 3.1.2.6. Unterminated Quoted String in + Display Name ..............................24 + 3.1.2.7. <> Enclosing Request-URI ..................25 + 3.1.2.8. Malformed SIP Request-URI (embedded LWS) ..26 + 3.1.2.9. Multiple SP Separating + Request-Line Elements .....................27 + 3.1.2.10. SP Characters at End of Request-Line .....28 + 3.1.2.11. Escaped Headers in SIP Request-URI .......29 + 3.1.2.12. Invalid Timezone in Date Header Field ....30 + 3.1.2.13. Failure to Enclose name-addr URI in <> ...31 + 3.1.2.14. Spaces within addr-spec ..................31 + 3.1.2.15. Non-token Characters in Display Name .....32 + 3.1.2.16. Unknown Protocol Version .................32 + 3.1.2.17. Start Line and CSeq Method Mismatch ......33 + 3.1.2.18. Unknown Method with CSeq Method Mismatch .33 + 3.1.2.19. Overlarge Response Code ..................34 + 3.2. Transaction Layer Semantics ...............................34 + 3.2.1. Missing Transaction Identifier .....................34 + 3.3. Application-Layer Semantics ...............................35 + 3.3.1. Missing Required Header Fields .....................35 + 3.3.2. Request-URI with Unknown Scheme ....................36 + 3.3.3. Request-URI with Known but Atypical Scheme .........36 + 3.3.4. Unknown URI Schemes in Header Fields ...............37 + 3.3.5. Proxy-Require and Require ..........................37 + 3.3.6. Unknown Content-Type ...............................38 + 3.3.7. Unknown Authorization Scheme .......................38 + 3.3.8. Multiple Values in Single Value Required Fields ....39 + 3.3.9. Multiple Content-Length Values .....................40 + 3.3.10. 200 OK Response with Broadcast Via Header + Field Value .......................................40 + 3.3.11. Max-Forwards of Zero ..............................41 + 3.3.12. REGISTER with a Contact Header Parameter ..........42 + + + +Sparks, et al. Informational [Page 2] + +RFC 4475 SIP Torture Test Messages May 2006 + + + 3.3.13. REGISTER with a url-parameter .....................42 + 3.3.14. REGISTER with a URL Escaped Header ................43 + 3.3.15. Unacceptable Accept Offering ......................44 + 3.4. Backward Compatibility ....................................44 + 3.4.1. INVITE with RFC 2543 Syntax ........................44 + 4. Security Considerations ........................................45 + 5. Acknowledgements ...............................................46 + 6. Informative References .........................................46 + Appendix A. Bit-Exact Archive of Each Test Message ................47 + A.1. Encoded Reference Messages ................................48 + +1. Overview + + This document is informational and is NOT NORMATIVE on any aspect of + SIP. + + This document contains test messages based on the current version + (2.0) of the Session Initiation Protocol as, defined in [RFC3261]. + Some messages exercise SIP's use of the Session Description Protocol + (SDP), as described in [RFC3264]. + + These messages were developed and refined at the SIPIt + interoperability test events. + + The test messages are organized into several sections. Some stress + only a SIP parser, and others stress both the parser and the + application above it. Some messages are valid, and some are not. + Each example clearly calls out what makes any invalid messages + incorrect. + + This document does not attempt to catalog every way to make an + invalid message, nor does it attempt to be comprehensive in exploring + unusual, but valid, messages. Instead, it tries to focus on areas + that have caused interoperability problems or that have particularly + unfavorable characteristics if they are handled improperly. This + document is a seed for a test plan, not a test plan in itself. + + The messages are presented in the text using a set of markup + conventions to avoid ambiguity and meet Internet-Draft layout + requirements. To resolve any remaining ambiguity, a bit-accurate + version of each message is encapsulated in an appendix. + +2. Document Conventions + + This document contains many example SIP messages. Although SIP is a + text-based protocol, many of these examples cannot be unambiguously + rendered without additional markup due to the constraints placed on + the formatting of RFCs. This document defines and uses the markup + + + +Sparks, et al. Informational [Page 3] + +RFC 4475 SIP Torture Test Messages May 2006 + + + defined in this section to remove that ambiguity. This markup uses + the start and end tag conventions of XML but does not define any XML + document type. + + The appendix contains an encoded binary form of all the messages and + the algorithm needed to decode them into files. + +2.1. Representing Long Lines + + Several of these examples contain unfolded lines longer than 72 + characters. These are captured between tags. The + single unfolded line is reconstructed by directly concatenating all + lines appearing between the tags (discarding any line feeds or + carriage returns). There will be no whitespace at the end of lines. + Any whitespace appearing at a fold-point will appear at the beginning + of a line. + + The following represent the same string of bits: + + Header-name: first value, reallylongsecondvalue, third value + + + Header-name: first value, + reallylongsecondvalue + , third value + + + + Header-name: first value, + reallylong + second + value, + third value + + + Note that this is NOT SIP header-line folding, where different + strings of bits have equivalent meaning. + +2.2. Representing Non-printable Characters + + Several examples contain binary message bodies or header field values + containing non-ascii range UTF-8 encoded characters. These are + rendered here as a pair of hexadecimal digits per octet between + tags. This rendering applies even inside quoted-strings. + + + + + + + +Sparks, et al. Informational [Page 4] + +RFC 4475 SIP Torture Test Messages May 2006 + + + The following represent the same string of bits: + + Header-name: value one + Header-name: value206F6Ee + + The following is a Subject header field containing the euro symbol: + + Subject: E282AC + +2.3. Representing Long Repeating Strings + + Several examples contain very large data values created with + repeating bit strings. Those will be rendered here using value. As with , this rendering + applies even inside quoted strings. + + For example, the value "abcabcabc" can be rendered as abc. A display name of "1000000 bottles of beer" + could be rendered as + + To: "130 bottles of beer" + + + A Max-Forwards header field with a value of one google will be + rendered here as + + Max-Forwards: 10 + +3. SIP Test Messages + +3.1. Parser Tests (syntax) + +3.1.1. Valid Messages + +3.1.1.1. A Short Tortuous INVITE + + This short, relatively human-readable message contains: + + o line folding all over. + + o escaped characters within quotes. + + o an empty subject. + + o LWS between colons, semicolons, header field values, and other + fields. + + o both comma separated and separately listed header field values. + + + +Sparks, et al. Informational [Page 5] + +RFC 4475 SIP Torture Test Messages May 2006 + + + o a mix of short and long form for the same header field name. + + o unknown Request-URI parameter. + + o unknown header fields. + + o an unknown header field with a value that would be syntactically + invalid if it were defined in terms of generic-param. + + o unusual header field ordering. + + o unusual header field name character case. + + o unknown parameters of a known header field. + + o a uri parameter with no value. + + o a header parameter with no value. + + o integer fields (Max-Forwards and CSeq) with leading zeros. + + All elements should treat this as a well-formed request. + + The UnknownHeaderWithUnusualValue header field deserves special + attention. If this header field were defined in terms of comma- + separated values with semicolon-separated parameters (as would many + of the existing defined header fields), this would be invalid. + However, since the receiving element does not know the definition of + the syntax for this field, it must parse it as a header value. + Proxies would forward this header field unchanged. Endpoints would + ignore the header field. + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 6] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : wsinv + + INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0 + TO : + sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n + from : "J Rosenberg \\\"" + ; + tag = 98asjd8 + MaX-fOrWaRdS: 0068 + Call-ID: wsinv.ndaksdj@192.0.2.1 + Content-Length : 150 + cseq: 0009 + INVITE + Via : SIP / 2.0 + /UDP + 192.0.2.2;branch=390skdjuw + s : + NewFangledHeader: newfangled value + continued newfangled value + UnknownHeaderWithUnusualValue: ;;,,;;,; + Content-Type: application/sdp + Route: + + v: SIP / 2.0 / TCP spindle.example.com ; + branch = z9hG4bK9ikj8 , + SIP / 2.0 / UDP 192.168.255.111 ; branch= + z9hG4bK30239 + m:"Quoted string \"\"" ; newparam = + newvalue ; + secondparam ; q = 0.33 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.3 + s=- + c=IN IP4 192.0.2.4 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + +Sparks, et al. Informational [Page 7] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.1.2. Wide Range of Valid Characters + + This message exercises a wider range of characters in several key + syntactic elements than implementations usually see. In particular, + note the following: + + o The Method contains non-alpha characters from token. Note that % + is not an escape character for this field. A method of IN%56ITE + is an unknown method. It is not the same as a method of INVITE. + + o The Request-URI contains unusual, but legal, characters. + + o A branch parameter contains all non-alphanum characters from + token. + + o The To header field value's quoted string contains quoted-pair + expansions, including a quoted NULL character. + + o The name part of name-addr in the From header field value contains + multiple tokens (instead of a quoted string) with all non-alphanum + characters from the token production rule. That value also has an + unknown header parameter whose name contains the non-alphanum + token characters and whose value is a non-ascii range UTF-8 + encoded string. The tag parameter on this value contains the + non-alphanum token characters. + + o The Call-ID header field value contains the non-alphanum + characters from word. Notice that in this production: + + * % is not an escape character. It is only an escape character + in productions matching the rule "escaped". + + * " does not start a quoted string. None of ',` or " imply that + there will be a matching symbol later in the string. + + * The characters []{}()<> do not have any grouping semantics. + They are not required to appear in balanced pairs. + + o There is an unknown header field (matching extension-header) with + non-alphanum token characters in its name and a UTF8-NONASCII + value. + + If this unusual URI has been defined at a proxy, the proxy will + forward this request normally. Otherwise, a proxy will generate a + 404. Endpoints will generate a 501 listing the methods they + understand in an Allow header field. + + + + + +Sparks, et al. Informational [Page 8] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : intmeth + + + !interesting-Method0123456789_*+`.%indeed'~ + sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;* + :&it+has=1,weird!*pas$wo~d_too.(doesn't-it) + @example.com SIP/2.0 + + Via: SIP/2.0/TCP host1.example.com;branch=z9hG4bK-.!%66*_+`'~ + + To: "BEL:\07 NUL:\00 DEL:\7F" + + + + From: token1~` token2'+_ token3*%!.- + ;fromParam''~+*_!.-%= + "D180D0B0D0B1D0BED182D0B0D18ED189D0B8D0B9" + ;tag=_token~1'+`*%!-. + + Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\/"][?}{ + CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~ + Max-Forwards: 255 + + extensionHeader-!.%*+_`'~: + EFBBBFE5A4A7E5819CE99BBB + + Content-Length: 0 + +3.1.1.3. Valid Use of the % Escaping Mechanism + + This INVITE exercises the % HEX HEX escaping mechanism in several + places. The request is syntactically valid. Interesting features + include the following: + + o The request-URI has sips:user@example.com embedded in its + userpart. What that might mean to example.net is beyond the scope + of this document. + + o The From and To URIs have escaped characters in their userparts. + + o The Contact URI has escaped characters in the URI parameters. + Note that the "name" uri-parameter has a value of "value%41", + which is NOT equivalent to "valueA". Per [RFC3986], unescaping + URI components is never performed recursively. + + + + + + +Sparks, et al. Informational [Page 9] + +RFC 4475 SIP Torture Test Messages May 2006 + + + A parser must accept this as a well-formed message. The application + using the message must treat the % HEX HEX expansions as equivalent + to the character being encoded. The application must not try to + interpret % as an escape character in those places where % HEX HEX + ("escaped" in the grammar) is not a valid part of the construction. + In [RFC3261], "escaped" only occurs in the expansions of SIP-URI, + SIPS-URI, and Reason-Phrase. + + Message Details : esc01 + + INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0 + To: sip:%75se%72@example.com + From: ;tag=938 + Max-Forwards: 87 + i: esc01.239409asdfakjkn23onasd0-3234 + CSeq: 234234 INVITE + Via: SIP/2.0/UDP host5.example.net;branch=z9hG4bKkdjuw + C: application/sdp + Contact: + + Content-Length: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + s=- + c=IN IP4 192.0.2.1 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 10] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.1.4. Escaped Nulls in URIs + + This register request contains several URIs with nulls in the + userpart. The message is well formed - parsers must accept this + message. Implementations must take special care when unescaping the + Address-of-Record (AOR) in this request so as to not prematurely + shorten the username. This request registers two distinct contact + URIs. + + Message Details : escnull + + REGISTER sip:example.com SIP/2.0 + To: sip:null-%00-null@example.com + From: sip:null-%00-null@example.com;tag=839923423 + Max-Forwards: 70 + Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd + CSeq: 14398234 REGISTER + Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw + Contact: + Contact: + L:0 + +3.1.1.5. Use of % When It Is Not an Escape + + In most of the places % can appear in a SIP message, it is not an + escape character. This can surprise the unwary implementor. The + following well-formed request has these properties: + + o The request method is unknown. It is NOT equivalent to REGISTER. + + o The display name portion of the To and From header fields is + "%Z%45". Note that this is not the same as %ZE. + + o This message has two Contact header field values, not three. + is a C%6Fntact header field value. + + A parser should accept this message as well formed. A proxy would + forward or reject the message depending on what the Request-URI meant + to it. An endpoint would reject this message with a 501. + + + + + + + + + + + + +Sparks, et al. Informational [Page 11] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : esc02 + + RE%47IST%45R sip:registrar.example.com SIP/2.0 + To: "%Z%45" + From: "%Z%45" ;tag=f232jadfj23 + Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf + Via: SIP/2.0/TCP host.example.com;branch=z9hG4bK209%fzsnel234 + CSeq: 29344 RE%47IST%45R + Max-Forwards: 70 + Contact: + C%6Fntact: + Contact: + l: 0 + +3.1.1.6. Message with No LWS between Display Name and < + + This OPTIONS request is not valid per the grammar in RFC 3261 since + there is no LWS between the token in the display name and < in the + From header field value. This has been identified as a specification + bug that will be removed when RFC 3261 is revised. Elements should + accept this request as well formed. + + Message Details : lwsdisp + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:user@example.com + From: caller;tag=323 + Max-Forwards: 70 + Call-ID: lwsdisp.1234abcd@funky.example.com + CSeq: 60 OPTIONS + Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw + l: 0 + +3.1.1.7. Long Values in Header Fields + + This well-formed request contains header fields with many values and + values that are very long. Features include the following: + + o The To header field has a long display name, and long uri + parameter names and values. + + o The From header field has long header parameter names and values, + in particular, a very long tag. + + o The Call-ID is one long token. + + + + + + +Sparks, et al. Informational [Page 12] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : longreq + + INVITE sip:user@example.com SIP/2.0 + + To: "I have a user name of + extreme proportion" + longvalue; + longparamname=shortvalue; + verylongParameterNameWithNoValue> + + + F: sip: + amazinglylongcallername@example.net + ;tag=12982424 + ;unknownheaderparamname= + unknowheaderparamvalue + ;unknownValuelessparamname + + Call-ID: longreq.onereallylongcallid + CSeq: 3882340 INVITE + + Unknown-Long-Name: + unknown-long-value; + unknown-long-parameter-name = + unknown-long-parameter-value + + Via: SIP/2.0/TCP sip33.example.com + v: SIP/2.0/TCP sip32.example.com + V: SIP/2.0/TCP sip31.example.com + Via: SIP/2.0/TCP sip30.example.com + ViA: SIP/2.0/TCP sip29.example.com + VIa: SIP/2.0/TCP sip28.example.com + VIA: SIP/2.0/TCP sip27.example.com + via: SIP/2.0/TCP sip26.example.com + viA: SIP/2.0/TCP sip25.example.com + vIa: SIP/2.0/TCP sip24.example.com + vIA: SIP/2.0/TCP sip23.example.com + V : SIP/2.0/TCP sip22.example.com + v : SIP/2.0/TCP sip21.example.com + V : SIP/2.0/TCP sip20.example.com + v : SIP/2.0/TCP sip19.example.com + Via : SIP/2.0/TCP sip18.example.com + Via : SIP/2.0/TCP sip17.example.com + Via: SIP/2.0/TCP sip16.example.com + Via: SIP/2.0/TCP sip15.example.com + Via: SIP/2.0/TCP sip14.example.com + Via: SIP/2.0/TCP sip13.example.com + + + +Sparks, et al. Informational [Page 13] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Via: SIP/2.0/TCP sip12.example.com + Via: SIP/2.0/TCP sip11.example.com + Via: SIP/2.0/TCP sip10.example.com + Via: SIP/2.0/TCP sip9.example.com + Via: SIP/2.0/TCP sip8.example.com + Via: SIP/2.0/TCP sip7.example.com + Via: SIP/2.0/TCP sip6.example.com + Via: SIP/2.0/TCP sip5.example.com + Via: SIP/2.0/TCP sip4.example.com + Via: SIP/2.0/TCP sip3.example.com + Via: SIP/2.0/TCP sip2.example.com + Via: SIP/2.0/TCP sip1.example.com + + Via: SIP/2.0/TCP + host.example.com;received=192.0.2.5; + branch=verylongbranchvalue + + Max-Forwards: 70 + + Contact: amazinglylongcallername + @host5.example.net> + + Content-Type: application/sdp + l: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + s=- + c=IN IP4 192.0.2.1 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.1.1.8. Extra Trailing Octets in a UDP Datagram + + This message contains a single SIP REGISTER request, which ostensibly + arrived over UDP in a single datagram. The packet contains extra + octets after the body (which in this case has zero length). The + extra octets happen to look like a SIP INVITE request, but (per + section 18.3 of [RFC3261]) they are just spurious noise that must be + ignored. + + A SIP element receiving this datagram would handle the REGISTER + request normally and ignore the extra bits that look like an INVITE + request. If the element is a proxy choosing to forward the REGISTER, + the INVITE octets would not appear in the forwarded request. + + + +Sparks, et al. Informational [Page 14] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : dblreq + + REGISTER sip:example.com SIP/2.0 + To: sip:j.user@example.com + From: sip:j.user@example.com;tag=43251j3j324 + Max-Forwards: 8 + I: dblreq.0ha0isndaksdj99sdfafnl3lk233412 + Contact: sip:j.user@host.example.com + CSeq: 8 REGISTER + Via: SIP/2.0/UDP 192.0.2.125;branch=z9hG4bKkdjuw23492 + Content-Length: 0 + + INVITE sip:joe@example.com SIP/2.0 + t: sip:joe@example.com + From: sip:caller@example.net;tag=141334 + Max-Forwards: 8 + Call-ID: dblreq.0ha0isnda977644900765@192.0.2.15 + CSeq: 8 INVITE + Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw380234 + Content-Type: application/sdp + Content-Length: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.15 + s=- + c=IN IP4 192.0.2.15 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m =video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 15] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.1.9. Semicolon-Separated Parameters in URI User Part + + This request has a semicolon-separated parameter contained in the + "user" part of the Request-URI (whose value contains an escaped @ + symbol). Receiving elements will accept this as a well-formed + message. The Request-URI will parse so that the user part is + "user;par=u@example.net". + + Message Details : semiuri + + OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0 + To: sip:j_user@example.com + From: sip:caller@example.org;tag=33242 + Max-Forwards: 3 + Call-ID: semiuri.0ha0isndaksdj + CSeq: 8 OPTIONS + Accept: application/sdp, application/pkcs7-mime, + multipart/mixed, multipart/signed, + message/sip, message/sipfrag + Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw + l: 0 + +3.1.1.10. Varied and Unknown Transport Types + + This request contains Via header field values with all known + transport types and exercises the transport extension mechanism. + Parsers must accept this message as well formed. Elements receiving + this message would process it exactly as if the 2nd and subsequent + header field values specified UDP (or other transport). + + Message Details : transports + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:user@example.com + From: ;tag=323 + Max-Forwards: 70 + Call-ID: transports.kijh4akdnaqjkwendsasfdj + Accept: application/sdp + CSeq: 60 OPTIONS + Via: SIP/2.0/UDP t1.example.com;branch=z9hG4bKkdjuw + Via: SIP/2.0/SCTP t2.example.com;branch=z9hG4bKklasjdhf + Via: SIP/2.0/TLS t3.example.com;branch=z9hG4bK2980unddj + Via: SIP/2.0/UNKNOWN t4.example.com;branch=z9hG4bKasd0f3en + Via: SIP/2.0/TCP t5.example.com;branch=z9hG4bK0a9idfnee + l: 0 + + + + + + +Sparks, et al. Informational [Page 16] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.1.11. Multipart MIME Message + + This MESSAGE request contains two body parts. The second part is + binary encoded and contains null (0x00) characters. Receivers must + take care to frame the received message properly. + + Parsers must accept this message as well formed, even if the + application above the parser does not support multipart/signed. + + Additional examples of multipart/mime messages, in particular S/MIME + messages, are available in the security call flow examples document + [SIP-SEC]. + + Message Details : mpart01 + + MESSAGE sip:kumiko@example.org SIP/2.0 + + Via: SIP/2.0/UDP 127.0.0.1:5070 + ;branch=z9hG4bK-d87543-4dade06d0bdb11ee-1--d87543-;rport + + Max-Forwards: 70 + Route: + + Identity: r5mwreLuyDRYBi/0TiPwEsY3rEVsk/G2WxhgTV1PF7hHuL + IK0YWVKZhKv9Mj8UeXqkMVbnVq37CD+813gvYjcBUaZngQmXc9WNZSDN + GCzA+fWl9MEUHWIZo1CeJebdY/XlgKeTa0Olvq0rt70Q5jiSfbqMJmQF + teeivUhkMWYUA= + + Contact: + To: + From: ;tag=2fb0dcc9 + Call-ID: 3d9485ad0c49859b@Zmx1ZmZ5LW1hYy0xNi5sb2NhbA.. + CSeq: 1 MESSAGE + Content-Transfer-Encoding: binary + Content-Type: multipart/mixed;boundary=7a9cbec02ceef655 + Date: Sat, 15 Oct 2005 04:44:56 GMT + User-Agent: SIPimp.org/0.2.5 (curses) + Content-Length: 553 + + --7a9cbec02ceef655 + Content-Type: text/plain + Content-Transfer-Encoding: binary + + Hello + --7a9cbec02ceef655 + Content-Type: application/octet-stream + Content-Transfer-Encoding: binary + + + + +Sparks, et al. Informational [Page 17] + +RFC 4475 SIP Torture Test Messages May 2006 + + + + 3082015206092A86 + 4886F70D010702A08201433082013F02 + 01013109300706052B0E03021A300B06 + 092A864886F70D010701318201203082 + 011C020101307C3070310B3009060355 + 04061302555331133011060355040813 + 0A43616C69666F726E69613111300F06 + 03550407130853616E204A6F7365310E + 300C060355040A130573697069743129 + 3027060355040B132053697069742054 + 65737420436572746966696361746520 + 417574686F7269747902080195007102 + 330113300706052B0E03021A300D0609 + 2A864886F70D01010105000481808EF4 + 66F948F0522DD2E5978E9D95AAE9F2FE + 15A06659716292E8DA2AA8D8350A68CE + FFAE3CBD2BFF1675DDD5648E593DD647 + 28F26220F7E941749E330D9A15EDABDB + 93D10C42102E7B7289D29CC0C9AE2EFB + C7C0CFF9172F3B027E4FC027E1546DE4 + B6AA3ABB3E66CCCB5DD6C64B8383149C + B8E6FF182D944FE57B65BC99D005 + + --7a9cbec02ceef655-- + +3.1.1.12. Unusual Reason Phrase + + This 200 response contains a reason phrase other than "OK". The + reason phrase is intended for human consumption and may contain any + string produced by + + Reason-Phrase = *(reserved / unreserved / escaped + / UTF8-NONASCII / UTF8-CONT / SP / HTAB) + + This particular response contains unreserved and non-ascii UTF-8 + characters. This response is well formed. A parser must accept this + message. + + + + + + + + + + + + + +Sparks, et al. Informational [Page 18] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : unreason + + + SIP/2.0 200 = 2**3 * 5**2 D0BDD0BE20D181D182 + D0BE20D0B4D0B5D0B2D18FD0BDD0BED181D182D0BE20D0B4 + D0B5D0B2D18FD182D18C202D20D0BFD180D0BED181D182D0 + BED0B5 + + Via: SIP/2.0/UDP 192.0.2.198;branch=z9hG4bK1324923 + Call-ID: unreason.1234ksdfak3j2erwedfsASdf + CSeq: 35 INVITE + From: sip:user@example.com;tag=11141343 + To: sip:user@example.edu;tag=2229 + Content-Length: 154 + Content-Type: application/sdp + Contact: + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.198 + s=- + c=IN IP4 192.0.2.198 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.1.1.13. Empty Reason Phrase + + This well-formed response contains no reason phrase. A parser must + accept this message. The space character after the reason code is + required. If it were not present, this message could be rejected as + invalid (a liberal receiver would accept it anyway). + + Message Details : noreason + + SIP/2.0 10020 + Via: SIP/2.0/UDP 192.0.2.105;branch=z9hG4bK2398ndaoe + Call-ID: noreason.asndj203insdf99223ndf + CSeq: 35 INVITE + From: ;tag=39ansfi3 + To: ;tag=902jndnke3 + Content-Length: 0 + Contact: + + + + + + + + +Sparks, et al. Informational [Page 19] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2. Invalid Messages + + This section contains several invalid messages reflecting errors seen + at interoperability events and exploring important edge conditions + that can be induced through malformed messages. This section does + not attempt to be a comprehensive list of all types of invalid + messages. + +3.1.2.1. Extraneous Header Field Separators + + The Via header field of this request contains additional semicolons + and commas without parameters or values. The Contact header field + contains additional semicolons without parameters. This message is + syntactically invalid. + + An element receiving this request should respond with a 400 Bad + Request error. + + Message Details : badinv01 + + INVITE sip:user@example.com SIP/2.0 + To: sip:j.user@example.com + From: sip:caller@example.net;tag=134161461246 + Max-Forwards: 7 + Call-ID: badinv01.0ha0isndaksdjasdf3234nas + CSeq: 8 INVITE + Via: SIP/2.0/UDP 192.0.2.15;;,;,, + Contact: "Joe" ;;;; + Content-Length: 152 + Content-Type: application/sdp + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.15 + s=- + c=IN IP4 192.0.2.15 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.1.2.2. Content Length Larger Than Message + + This is a request message with a Content Length that is larger than + the actual length of the body. + + When sent over UDP (as this message ostensibly was), the receiving + element should respond with a 400 Bad Request error. If this message + arrived over a stream-based transport, such as TCP, there's not much + + + +Sparks, et al. Informational [Page 20] + +RFC 4475 SIP Torture Test Messages May 2006 + + + the receiving party could do but wait for more data on the stream and + close the connection if none is forthcoming within a reasonable + period of time. + + Message Details : clerr + + INVITE sip:user@example.com SIP/2.0 + Max-Forwards: 80 + To: sip:j.user@example.com + From: sip:caller@example.net;tag=93942939o2 + Contact: + Call-ID: clerr.0ha0isndaksdjweiafasdk3 + CSeq: 8 INVITE + Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bK-39234-23523 + Content-Type: application/sdp + Content-Length: 9999 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.155 + s=- + c=IN IP4 192.0.2.155 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.1.2.3. Negative Content-Length + + This request has a negative value for Content-Length. + + An element receiving this message should respond with an error. This + request appeared over UDP, so the remainder of the datagram can + simply be discarded. If a request like this arrives over TCP, the + framing error is not recoverable, and the connection should be + closed. The same behavior is appropriate for messages that arrive + without a numeric value in the Content-Length header field, such as + the following: + + Content-Length: five + + Implementors should take extra precautions if the technique they + choose for converting this ascii field into an integral form can + return a negative value. In particular, the result must not be used + as a counter or array index. + + + + + + + +Sparks, et al. Informational [Page 21] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : ncl + + INVITE sip:user@example.com SIP/2.0 + Max-Forwards: 254 + To: sip:j.user@example.com + From: sip:caller@example.net;tag=32394234 + Call-ID: ncl.0ha0isndaksdj2193423r542w35 + CSeq: 0 INVITE + Via: SIP/2.0/UDP 192.0.2.53;branch=z9hG4bKkdjuw + Contact: + Content-Type: application/sdp + Content-Length: -999 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.53 + s=- + c=IN IP4 192.0.2.53 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.1.2.4. Request Scalar Fields with Overlarge Values + + This request contains several scalar header field values outside + their legal range. + + o The CSeq sequence number is >2**32-1. + + o The Max-Forwards value is >255. + + o The Expires value is >2**32-1. + + o The Contact expires parameter value is >2**32-1. + + An element receiving this request should respond with a 400 Bad + Request due to the CSeq error. If only the Max-Forwards field were + in error, the element could choose to process the request as if the + field were absent. If only the expiry values were in error, the + element could treat them as if they contained the default values for + expiration (3600 in this case). + + Other scalar request fields that may contain aberrant values include, + but are not limited to, the Contact q value, the Timestamp value, and + the Via ttl parameter. + + + + + + +Sparks, et al. Informational [Page 22] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : scalar02 + + REGISTER sip:example.com SIP/2.0 + Via: SIP/2.0/TCP host129.example.com;branch=z9hG4bK342sdfoi3 + To: + From: ;tag=239232jh3 + CSeq: 36893488147419103232 REGISTER + Call-ID: scalar02.23o0pd9vanlq3wnrlnewofjas9ui32 + Max-Forwards: 300 + Expires: 10 + Contact: + ;expires=280297596632815 + Content-Length: 0 + +3.1.2.5. Response Scalar Fields with Overlarge Values + + This response contains several scalar header field values outside + their legal range. + + o The CSeq sequence number is >2**32-1. + + o The Retry-After field is unreasonably large (note that RFC 3261 + does not define a legal range for this field). + + o The Warning field has a warning-value with more than 3 digits. + + An element receiving this response will simply discard it. + + Message Details : scalarlg + + SIP/2.0 503 Service Unavailable + + Via: SIP/2.0/TCP host129.example.com + ;branch=z9hG4bKzzxdiwo34sw + ;received=192.0.2.129 + + To: + From: ;tag=2easdjfejw + CSeq: 9292394834772304023312 OPTIONS + Call-ID: scalarlg.noase0of0234hn2qofoaf0232aewf2394r + Retry-After: 949302838503028349304023988 + Warning: 1812 overture "In Progress" + Content-Length: 0 + + + + + + + + +Sparks, et al. Informational [Page 23] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.6. Unterminated Quoted String in Display Name + + This is a request with an unterminated quote in the display name of + the To field. An element receiving this request should return a 400 + Bad Request error. + + An element could attempt to infer a terminating quote and accept the + message. Such an element needs to take care that it makes a + reasonable inference when it encounters + + To: "Mr J. User + + Message Details : quotbal + + INVITE sip:user@example.com SIP/2.0 + To: "Mr. J. User + From: sip:caller@example.net;tag=93334 + Max-Forwards: 10 + Call-ID: quotbal.aksdj + Contact: + CSeq: 8 INVITE + Via: SIP/2.0/UDP 192.0.2.59:5050;branch=z9hG4bKkdjuw39234 + Content-Type: application/sdp + Content-Length: 152 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.15 + s=- + c=IN IP4 192.0.2.15 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 24] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.7. <> Enclosing Request-URI + + This INVITE request is invalid because the Request-URI has been + enclosed within in "<>". + + It is reasonable always to reject a request with this error with a + 400 Bad Request. Elements attempting to be liberal with what they + accept may choose to ignore the brackets. If the element forwards + the request, it must not include the brackets in the messages it + sends. + + Message Details : ltgtruri + + INVITE SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=39291 + Max-Forwards: 23 + Call-ID: ltgtruri.1@192.0.2.5 + CSeq: 1 INVITE + Via: SIP/2.0/UDP 192.0.2.5 + Contact: + Content-Type: application/sdp + Content-Length: 159 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.5 + s=- + c=IN IP4 192.0.2.5 + t=3149328700 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 25] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.8. Malformed SIP Request-URI (embedded LWS) + + This INVITE has illegal LWS within the Request-URI. + + An element receiving this request should respond with a 400 Bad + Request. + + An element could attempt to ignore the embedded LWS for those schemes + (like SIP) where doing so would not introduce ambiguity. + + Message Details : lwsruri + + INVITE sip:user@example.com; lr SIP/2.0 + To: sip:user@example.com;tag=3xfe-9921883-z9f + From: sip:caller@example.net;tag=231413434 + Max-Forwards: 5 + Call-ID: lwsruri.asdfasdoeoi2323-asdfwrn23-asd834rk423 + CSeq: 2130706432 INVITE + Via: SIP/2.0/UDP 192.0.2.1:5060;branch=z9hG4bKkdjuw2395 + Contact: + Content-Type: application/sdp + Content-Length: 159 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + s=- + c=IN IP4 192.0.2.1 + t=3149328700 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 26] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.9. Multiple SP Separating Request-Line Elements + + This INVITE has illegal multiple SP characters between elements of + the start line. + + It is acceptable to reject this request as malformed. An element + that is liberal in what it accepts may ignore these extra SP + characters when processing the request. If the element forwards the + request, it must not include these extra SP characters in the + messages it sends. + + Message Details : lwsstart + + INVITE sip:user@example.com SIP/2.0 + Max-Forwards: 8 + To: sip:user@example.com + From: sip:caller@example.net;tag=8814 + Call-ID: lwsstart.dfknq234oi243099adsdfnawe3@example.com + CSeq: 1893884 INVITE + Via: SIP/2.0/UDP host1.example.com;branch=z9hG4bKkdjuw3923 + Contact: + Content-Type: application/sdp + Content-Length: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + s=- + c=IN IP4 192.0.2.1 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 27] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.10. SP Characters at End of Request-Line + + This OPTIONS request contains SP characters between the SIP-Version + field and the CRLF terminating the Request-Line. + + It is acceptable to reject this request as malformed. An element + that is liberal in what it accepts may ignore these extra SP + characters when processing the request. If the element forwards the + request, it must not include these extra SP characters in the + messages it sends. + + Message Details : trws + + OPTIONS sip:remote-target@example.com SIP/2.02020 + Via: SIP/2.0/TCP host1.example.com;branch=z9hG4bK299342093 + To: + From: ;tag=329429089 + Call-ID: trws.oicu34958239neffasdhr2345r + Accept: application/sdp + CSeq: 238923 OPTIONS + Max-Forwards: 70 + Content-Length: 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 28] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.11. Escaped Headers in SIP Request-URI + + This INVITE is malformed, as the SIP Request-URI contains escaped + headers. + + It is acceptable for an element to reject this request with a 400 Bad + Request. An element could choose to be liberal in what it accepts + and ignore the escaped headers. If the element is a proxy, the + escaped headers must not appear in the Request-URI of the forwarded + request (and most certainly must not be translated into the actual + header of the forwarded request). + + Message Details : escruri + + INVITE sip:user@example.com?Route=%3Csip:example.com%3E SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=341518 + Max-Forwards: 7 + Contact: + Call-ID: escruri.23940-asdfhj-aje3br-234q098w-fawerh2q-h4n5 + CSeq: 149209342 INVITE + Via: SIP/2.0/UDP host-of-the-hour.example.com;branch=z9hG4bKkdjuw + Content-Type: application/sdp + Content-Length: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + s=- + c=IN IP4 192.0.2.1 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 29] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.12. Invalid Time Zone in Date Header Field + + This INVITE is invalid, as it contains a non-GMT time zone in the SIP + Date header field. + + It is acceptable to reject this request as malformed (though an + element shouldn't do that unless the contents of the Date header + field were actually important to its processing). An element wishing + to be liberal in what it accepts could ignore this value altogether + if it wasn't going to use the Date header field anyway. Otherwise, + it could attempt to interpret this date and adjust it to GMT. + + RFC 3261 explicitly defines the only acceptable time zone designation + as "GMT". "UT", while synonymous with GMT per [RFC2822], is not + valid. "UTC" and "UCT" are also invalid. + + Message Details : baddate + + INVITE sip:user@example.com SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=2234923 + Max-Forwards: 70 + Call-ID: baddate.239423mnsadf3j23lj42--sedfnm234 + CSeq: 1392934 INVITE + Via: SIP/2.0/UDP host.example.com;branch=z9hG4bKkdjuw + Date: Fri, 01 Jan 2010 16:00:00 EST + Contact: + Content-Type: application/sdp + Content-Length: 150 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.5 + s=- + c=IN IP4 192.0.2.5 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + +Sparks, et al. Informational [Page 30] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.13. Failure to Enclose name-addr URI in <> + + This REGISTER request is malformed. The SIP URI contained in the + Contact Header field has an escaped header, so the field must be in + name-addr form (which implies that the URI must be enclosed in <>). + + It is reasonable for an element receiving this request to respond + with a 400 Bad Request. An element choosing to be liberal in what it + accepts could infer the angle brackets since there is no ambiguity in + this example. In general, that won't be possible. + + Message Details : regbadct + + REGISTER sip:example.com SIP/2.0 + To: sip:user@example.com + From: sip:user@example.com;tag=998332 + Max-Forwards: 70 + Call-ID: regbadct.k345asrl3fdbv@10.0.0.1 + CSeq: 1 REGISTER + Via: SIP/2.0/UDP 135.180.130.133:5060;branch=z9hG4bKkdjuw + Contact: sip:user@example.com?Route=%3Csip:sip.example.com%3E + l: 0 + +3.1.2.14. Spaces within addr-spec + + This request is malformed, since the addr-spec in the To header field + contains spaces. Parsers receiving this request must not break. It + is reasonable to reject this request with a 400 Bad Request response. + Elements attempting to be liberal may ignore the spaces. + + Message Details : badaspec + + OPTIONS sip:user@example.org SIP/2.0 + Via: SIP/2.0/UDP host4.example.com:5060;branch=z9hG4bKkdju43234 + Max-Forwards: 70 + From: "Bell, Alexander" ;tag=433423 + To: "Watson, Thomas" < sip:t.watson@example.org > + Call-ID: badaspec.sdf0234n2nds0a099u23h3hnnw009cdkne3 + Accept: application/sdp + CSeq: 3923239 OPTIONS + l: 0 + + + + + + + + + + +Sparks, et al. Informational [Page 31] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.15. Non-token Characters in Display Name + + This OPTIONS request is malformed, since the display names in the To + and From header fields contain non-token characters but are unquoted. + + It is reasonable always to reject this kind of error with a 400 Bad + Request response. + + An element may attempt to be liberal in what it receives and infer + the missing quotes. If this element were a proxy, it must not + propagate the error into the request it forwards. As a consequence, + if the fields are covered by a signature, there's not much point in + trying to be liberal - the message should simply be rejected. + + Message Details : baddn + + OPTIONS sip:t.watson@example.org SIP/2.0 + Via: SIP/2.0/UDP c.example.com:5060;branch=z9hG4bKkdjuw + Max-Forwards: 70 + From: Bell, Alexander ;tag=43 + To: Watson, Thomas + Call-ID: baddn.31415@c.example.com + Accept: application/sdp + CSeq: 3923239 OPTIONS + l: 0 + +3.1.2.16. Unknown Protocol Version + + To an element implementing [RFC3261], this request is malformed due + to its high version number. + + The element should respond to the request with a 505 Version Not + Supported error. + + Message Details : badvers + + OPTIONS sip:t.watson@example.org SIP/7.0 + Via: SIP/7.0/UDP c.example.com;branch=z9hG4bKkdjuw + Max-Forwards: 70 + From: A. Bell ;tag=qweoiqpe + To: T. Watson + Call-ID: badvers.31417@c.example.com + CSeq: 1 OPTIONS + l: 0 + + + + + + + +Sparks, et al. Informational [Page 32] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.17. Start Line and CSeq Method Mismatch + + This request has mismatching values for the method in the start line + and the CSeq header field. Any element receiving this request will + respond with a 400 Bad Request. + + Message Details : mismatch01 + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:j.user@example.com + From: sip:caller@example.net;tag=34525 + Max-Forwards: 6 + Call-ID: mismatch01.dj0234sxdfl3 + CSeq: 8 INVITE + Via: SIP/2.0/UDP host.example.com;branch=z9hG4bKkdjuw + l: 0 + +3.1.2.18. Unknown Method with CSeq Method Mismatch + + This message has an unknown method in the start line, and a CSeq + method tag that does not match. + + Any element receiving this response should respond with a 501 Not + Implemented. A 400 Bad Request is also acceptable, but choosing a + 501 (particularly at proxies) has better future-proof + characteristics. + + Message Details : mismatch02 + + NEWMETHOD sip:user@example.com SIP/2.0 + To: sip:j.user@example.com + From: sip:caller@example.net;tag=34525 + Max-Forwards: 6 + Call-ID: mismatch02.dj0234sxdfl3 + CSeq: 8 INVITE + Contact: + Via: SIP/2.0/UDP host.example.net;branch=z9hG4bKkdjuw + Content-Type: application/sdp + l: 138 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.1 + c=IN IP4 192.0.2.1 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + +Sparks, et al. Informational [Page 33] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.1.2.19. Overlarge Response Code + + This response has a response code larger than 699. An element + receiving this response should simply drop it. + + Message Details : bigcode + + SIP/2.0 4294967301 better not break the receiver + Via: SIP/2.0/UDP 192.0.2.105;branch=z9hG4bK2398ndaoe + Call-ID: bigcode.asdof3uj203asdnf3429uasdhfas3ehjasdfas9i + CSeq: 353494 INVITE + From: ;tag=39ansfi3 + To: ;tag=902jndnke3 + Content-Length: 0 + Contact: + +3.2. Transaction Layer Semantics + + This section contains tests that exercise an implementation's parser + and transaction-layer logic. + +3.2.1. Missing Transaction Identifier + + This request indicates support for RFC 3261-style transaction + identifiers by providing the z9hG4bK prefix to the branch parameter, + but it provides no identifier. A parser must not break when + receiving this message. An element receiving this request could + reject the request with a 400 Response (preferably statelessly, as + other requests from the source are likely also to have a malformed + branch parameter), or it could fall back to the RFC 2543-style + transaction identifier. + + Message Details : badbranch + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.org;tag=33242 + Max-Forwards: 3 + Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bK + Accept: application/sdp + Call-ID: badbranch.sadonfo23i420jv0as0derf3j3n + CSeq: 8 OPTIONS + l: 0 + + + + + + + + +Sparks, et al. Informational [Page 34] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3. Application-Layer Semantics + + This section contains tests that exercise an implementation's parser + and application-layer logic. + +3.3.1. Missing Required Header Fields + + This request contains no Call-ID, From, or To header fields. + + An element receiving this message must not break because of the + missing information. Ideally, it will respond with a 400 Bad Request + error. + + Message Details : insuf + + INVITE sip:user@example.com SIP/2.0 + CSeq: 193942 INVITE + Via: SIP/2.0/UDP 192.0.2.95;branch=z9hG4bKkdj.insuf + Content-Type: application/sdp + l: 152 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.95 + s=- + c=IN IP4 192.0.2.95 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 35] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.2. Request-URI with Unknown Scheme + + This OPTIONS contains an unknown URI scheme in the Request-URI. A + parser must accept this as a well-formed SIP request. + + An element receiving this request will reject it with a 416 + Unsupported URI Scheme response. + + Some early implementations attempt to look at the contents of the To + header field to determine how to route this kind of request. That is + an error. Despite the fact that the To header field and the Request + URI frequently look alike in simplistic first-hop messages, the To + header field contains no routing information. + + Message Details : unkscm + + OPTIONS nobodyKnowsThisScheme:totallyopaquecontent SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=384 + Max-Forwards: 3 + Call-ID: unkscm.nasdfasser0q239nwsdfasdkl34 + CSeq: 3923423 OPTIONS + Via: SIP/2.0/TCP host9.example.com;branch=z9hG4bKkdjuw39234 + Content-Length: 0 + +3.3.3. Request-URI with Known but Atypical Scheme + + This OPTIONS contains an Request-URI with an IANA-registered scheme + that does not commonly appear in Request-URIs of SIP requests. A + parser must accept this as a well-formed SIP request. + + If an element will never accept this scheme as meaningful in a + Request-URI, it is appropriate to treat it as unknown and return a + 416 Unsupported URI Scheme response. If the element might accept + some URIs with this scheme, then a 404 Not Found is appropriate for + those URIs it doesn't accept. + + Message Details : novelsc + + OPTIONS soap.beep://192.0.2.103:3002 SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=384 + Max-Forwards: 3 + Call-ID: novelsc.asdfasser0q239nwsdfasdkl34 + CSeq: 3923423 OPTIONS + Via: SIP/2.0/TCP host9.example.com;branch=z9hG4bKkdjuw39234 + Content-Length: 0 + + + + +Sparks, et al. Informational [Page 36] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.4. Unknown URI Schemes in Header Fields + + This message contains registered schemes in the To, From, and Contact + header fields of a request. The message is syntactically valid. + Parsers must not fail when receiving this message. + + Proxies should treat this message as they would any other request for + this URI. A registrar would reject this request with a 400 Bad + Request response, since the To: header field is required to contain a + SIP or SIPS URI as an AOR. + + Message Details : unksm2 + + REGISTER sip:example.com SIP/2.0 + To: isbn:2983792873 + From: ;tag=3234233 + Call-ID: unksm2.daksdj@hyphenated-host.example.com + CSeq: 234902 REGISTER + Max-Forwards: 70 + Via: SIP/2.0/UDP 192.0.2.21:5060;branch=z9hG4bKkdjuw + Contact: + l: 0 + +3.3.5. Proxy-Require and Require + + This request tests proper implementation of SIP's Proxy-Require and + Require extension mechanisms. + + Any element receiving this request will respond with a 420 Bad + Extension response, containing an Unsupported header field listing + these features from either the Require or Proxy-Require header field, + depending on the role in which the element is responding. + + Message Details : bext01 + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:j_user@example.com + From: sip:caller@example.net;tag=242etr + Max-Forwards: 6 + Call-ID: bext01.0ha0isndaksdj + Require: nothingSupportsThis, nothingSupportsThisEither + Proxy-Require: noProxiesSupportThis, norDoAnyProxiesSupportThis + CSeq: 8 OPTIONS + Via: SIP/2.0/TLS fold-and-staple.example.com;branch=z9hG4bKkdjuw + Content-Length: 0 + + + + + + +Sparks, et al. Informational [Page 37] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.6. Unknown Content-Type + + This INVITE request contains a body of unknown type. It is + syntactically valid. A parser must not fail when receiving it. + + A proxy receiving this request would process it just as it would any + other INVITE. An endpoint receiving this request would reject it + with a 415 Unsupported Media Type error. + + Message Details : invut + + INVITE sip:user@example.com SIP/2.0 + Contact: + To: sip:j.user@example.com + From: sip:caller@example.net;tag=8392034 + Max-Forwards: 70 + Call-ID: invut.0ha0isndaksdjadsfij34n23d + CSeq: 235448 INVITE + Via: SIP/2.0/UDP somehost.example.com;branch=z9hG4bKkdjuw + Content-Type: application/unknownformat + Content-Length: 40 + + + +3.3.7. Unknown Authorization Scheme + + This REGISTER request contains an Authorization header field with an + unknown scheme. The request is well formed. A parser must not fail + when receiving it. + + A proxy will treat this request as it would any other REGISTER. If + it forwards the request, it will include this Authorization header + field unmodified in the forwarded messages. + + A registrar that does not care about challenge-response + authentication will simply ignore the Authorization header field, + processing this registration as if the field were not present. A + registrar that does care about challenge-response authentication will + reject this request with a 401, issuing a new challenge with a scheme + it understands. + + Endpoints choosing not to act as registrars will simply reject the + request. A 405 Method Not Allowed is appropriate. + + + + + + +Sparks, et al. Informational [Page 38] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : regaut01 + + REGISTER sip:example.com SIP/2.0 + To: sip:j.user@example.com + From: sip:j.user@example.com;tag=87321hj23128 + Max-Forwards: 8 + Call-ID: regaut01.0ha0isndaksdj + CSeq: 9338 REGISTER + Via: SIP/2.0/TCP 192.0.2.253;branch=z9hG4bKkdjuw + Authorization: NoOneKnowsThisScheme opaque-data=here + Content-Length:0 + +3.3.8. Multiple Values in Single Value Required Fields + + The message contains a request with multiple Call-ID, To, From, Max- + Forwards, and CSeq values. An element receiving this request must + not break. + + An element receiving this request would respond with a 400 Bad + Request error. + + Message Details : multi01 + + INVITE sip:user@company.com SIP/2.0 + Contact: + Via: SIP/2.0/UDP 192.0.2.25;branch=z9hG4bKkdjuw + Max-Forwards: 70 + CSeq: 5 INVITE + Call-ID: multi01.98asdh@192.0.2.1 + CSeq: 59 INVITE + Call-ID: multi01.98asdh@192.0.2.2 + From: sip:caller@example.com;tag=3413415 + To: sip:user@example.com + To: sip:other@example.net + From: sip:caller@example.net;tag=2923420123 + Content-Type: application/sdp + l: 154 + Contact: + Max-Forwards: 5 + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.25 + s=- + c=IN IP4 192.0.2.25 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + + + +Sparks, et al. Informational [Page 39] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.9. Multiple Content-Length Values + + Multiple conflicting Content-Length header field values appear in + this request. + + From a framing perspective, this situation is equivalent to an + invalid Content-Length value (or no value at all). + + An element receiving this message should respond with an error. This + request appeared over UDP, so the remainder of the datagram can + simply be discarded. If a request like this arrives over TCP, the + framing error is not recoverable, and the connection should be + closed. + + Message Details : mcl01 + + OPTIONS sip:user@example.com SIP/2.0 + Via: SIP/2.0/UDP host5.example.net;branch=z9hG4bK293423 + To: sip:user@example.com + From: sip:other@example.net;tag=3923942 + Call-ID: mcl01.fhn2323orihawfdoa3o4r52o3irsdf + CSeq: 15932 OPTIONS + Content-Length: 13 + Max-Forwards: 60 + Content-Length: 5 + Content-Type: text/plain + + There's no way to know how many octets are supposed to be here. + +3.3.10. 200 OK Response with Broadcast Via Header Field Value + + This message is a response with a 2nd Via header field value's sent- + by containing 255.255.255.255. The message is well formed; parsers + must not fail when receiving it. + + Per [RFC3261], an endpoint receiving this message should simply + discard it. + + If a proxy followed normal response processing rules blindly, it + would forward this response to the broadcast address. To protect + against this as an avenue of attack, proxies should drop such + responses. + + + + + + + + + +Sparks, et al. Informational [Page 40] + +RFC 4475 SIP Torture Test Messages May 2006 + + + Message Details : bcast + + SIP/2.0 200 OK + Via: SIP/2.0/UDP 192.0.2.198;branch=z9hG4bK1324923 + Via: SIP/2.0/UDP 255.255.255.255;branch=z9hG4bK1saber23 + Call-ID: bcast.0384840201234ksdfak3j2erwedfsASdf + CSeq: 35 INVITE + From: sip:user@example.com;tag=11141343 + To: sip:user@example.edu;tag=2229 + Content-Length: 154 + Content-Type: application/sdp + Contact: + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.198 + s=- + c=IN IP4 192.0.2.198 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.3.11. Max-Forwards of Zero + + This is a legal SIP request with the Max-Forwards header field value + set to zero. + + A proxy should not forward the request and should respond 483 (Too + Many Hops). An endpoint should process the request as if the Max- + Forwards field value were still positive. + + Message Details : zeromf + + OPTIONS sip:user@example.com SIP/2.0 + To: sip:user@example.com + From: sip:caller@example.net;tag=3ghsd41 + Call-ID: zeromf.jfasdlfnm2o2l43r5u0asdfas + CSeq: 39234321 OPTIONS + Via: SIP/2.0/UDP host1.example.com;branch=z9hG4bKkdjuw2349i + Max-Forwards: 0 + Content-Length: 0 + + + + + + + + + + +Sparks, et al. Informational [Page 41] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.12. REGISTER with a Contact Header Parameter + + This register request contains a contact where the 'unknownparam' + parameter must be interpreted as a contact-param and not a url-param. + + This REGISTER should succeed. The response must not include + "unknownparam" as a url-parameter for this binding. Likewise, + "unknownparam" must not appear as a url-parameter in any binding + during subsequent fetches. + + Behavior is the same, of course, for any known contact-param + parameter names. + + Message Details : cparam01 + + REGISTER sip:example.com SIP/2.0 + Via: SIP/2.0/UDP saturn.example.com:5060;branch=z9hG4bKkdjuw + Max-Forwards: 70 + From: sip:watson@example.com;tag=DkfVgjkrtMwaerKKpe + To: sip:watson@example.com + Call-ID: cparam01.70710@saturn.example.com + CSeq: 2 REGISTER + Contact: sip:+19725552222@gw1.example.net;unknownparam + l: 0 + +3.3.13. REGISTER with a url-parameter + + This register request contains a contact where the URI has an unknown + parameter. + + The register should succeed, and a subsequent retrieval of the + registration must include "unknownparam" as a url-parameter. + + Behavior is the same, of course, for any known url-parameter names. + + Message Details : cparam02 + + REGISTER sip:example.com SIP/2.0 + Via: SIP/2.0/UDP saturn.example.com:5060;branch=z9hG4bKkdjuw + Max-Forwards: 70 + From: sip:watson@example.com;tag=838293 + To: sip:watson@example.com + Call-ID: cparam02.70710@saturn.example.com + CSeq: 3 REGISTER + Contact: + l: 0 + + + + + +Sparks, et al. Informational [Page 42] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.14. REGISTER with a URL Escaped Header + + This register request contains a contact where the URI has an escaped + header. + + The register should succeed, and a subsequent retrieval of the + registration must include the escaped Route header in the contact URI + for this binding. + + Message Details : regescrt + + REGISTER sip:example.com SIP/2.0 + To: sip:user@example.com + From: sip:user@example.com;tag=8 + Max-Forwards: 70 + Call-ID: regescrt.k345asrl3fdbv@192.0.2.1 + CSeq: 14398234 REGISTER + Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw + M: + L:0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 43] + +RFC 4475 SIP Torture Test Messages May 2006 + + +3.3.15. Unacceptable Accept Offering + + This request indicates that the response must contain a body in an + unknown type. In particular, since the Accept header field does not + contain application/sdp, the response may not contain an SDP body. + The recipient of this request could respond with a 406 Not + Acceptable, with a Warning/399 indicating that a response cannot be + formulated in the formats offered in the Accept header field. It is + also appropriate to respond with a 400 Bad Request, since all SIP + User-Agents (UAs) supporting INVITE are required to support + application/sdp. + + Message Details : sdp01 + + INVITE sip:user@example.com SIP/2.0 + To: sip:j_user@example.com + Contact: + From: sip:caller@example.net;tag=234 + Max-Forwards: 5 + Call-ID: sdp01.ndaksdj9342dasdd + Accept: text/nobodyKnowsThis + CSeq: 8 INVITE + Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw + Content-Length: 150 + Content-Type: application/sdp + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.5 + s=- + c=IN IP4 192.0.2.5 + t=0 0 + m=audio 49217 RTP/AVP 0 12 + m=video 3227 RTP/AVP 31 + a=rtpmap:31 LPC + +3.4. Backward Compatibility + +3.4.1. INVITE with RFC 2543 Syntax + + This is a legal message per RFC 2543 (and several bis versions) that + should be accepted by RFC 3261 elements that want to maintain + backwards compatibility. + + o There is no branch parameter at all on the Via header field value. + + o There is no From tag. + + + + + +Sparks, et al. Informational [Page 44] + +RFC 4475 SIP Torture Test Messages May 2006 + + + o There is no explicit Content-Length. (The body is assumed to be + all octets in the datagram after the null-line.) + + o There is no Max-Forwards header field. + + Message Details : inv2543 + + INVITE sip:UserB@example.com SIP/2.0 + Via: SIP/2.0/UDP iftgw.example.com + From: + Record-Route: + To: sip:+16505552222@ss1.example.net;user=phone + Call-ID: inv2543.1717@ift.client.example.com + CSeq: 56 INVITE + Content-Type: application/sdp + + v=0 + o=mhandley 29739 7272939 IN IP4 192.0.2.5 + s=- + c=IN IP4 192.0.2.5 + t=0 0 + m=audio 49217 RTP/AVP 0 + +4. Security Considerations + + This document presents NON-NORMATIVE examples of SIP session + establishment. The security considerations in [RFC3261] apply. + + Parsers must carefully consider edge conditions and malicious input + as part of their design. Attacks on many Internet systems use + crafted input to cause implementations to behave in undesirable ways. + Many of the messages in this document are designed to stress a parser + implementation at points traditionally used for such attacks. + However, this document does not attempt to be comprehensive. It + should be considered a seed to stimulate thinking and planning, not + simply a set of tests to be passed. + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 45] + +RFC 4475 SIP Torture Test Messages May 2006 + + +5. Acknowledgements + + The final detailed review of this document was performed by Diego + Besprosvan, Vijay Gurbani, Shashi Kumar, Derek MacDonald, Gautham + Narasimhan, Nils Ohlmeier, Bob Penfield, Reinaldo Penno, Marc + Petit-Huguenin, Richard Sugarman, and Venkatesh Venkataramanan. + + Earlier versions of this document were reviewed by Aseem Agarwal, + Rafi Assadi, Gonzalo Camarillo, Ben Campbell, Cullen Jennings, Vijay + Gurbani, Sunitha Kumar, Rohan Mahy, Jon Peterson, Marc + Petit-Huguenin, Vidhi Rastogi, Adam Roach, Bodgey Yin Shaohua, and + Tom Taylor. + + Thanks to Cullen Jennings and Eric Rescorla for their contribution to + the multipart/mime sections of this document and their work + constructing S/MIME examples in [SIP-SEC]. Thanks to Neil Deason for + contributing several messages and to Kundan Singh for performing + parser validation of messages in earlier versions. + + The following individuals provided significant comments during the + early phases of the development of this document: Jean-Francois Mule, + Hemant Agrawal, Henry Sinnreich, David Devanatham, Joe Pizzimenti, + Matt Cannon, John Hearty, the whole MCI IPOP Design team, Scott + Orton, Greg Osterhout, Pat Sollee, Doug Weisenberg, Danny Mistry, + Steve McKinnon, and Denise Ingram, Denise Caballero, Tom Redman, Ilya + Slain, Pat Sollee, John Truetken, and others from MCI, 3Com, Cisco, + Lucent, and Nortel. + +6. Informative References + + [RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April + 2001. + + [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, + A., Peterson, J., Sparks, R., Handley, M., and E. + Schooler, "SIP: Session Initiation Protocol", RFC 3261, + June 2002. + + [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model + with Session Description Protocol (SDP)", RFC 3264, June + 2002. + + [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform + Resource Identifier (URI): Generic Syntax", STD 66, RFC + 3986, January 2005. + + [SIP-SEC] Jennings, C. and K. Ono, "Example call flows using SIP + security mechanisms", Work in Progress, July 2005. + + + +Sparks, et al. Informational [Page 46] + +RFC 4475 SIP Torture Test Messages May 2006 + + +Appendix A. Bit-Exact Archive of Each Test Message + + The following text block is an encoded, gzip-compressed TAR archive + of files that represent each of the example messages discussed in + Section 3. + + To recover the compressed archive file intact, the text of this + document may be passed as input to the following Perl script (the + output should be redirected to a file or piped to "tar -xzvf -"). + + #!/usr/bin/perl + use strict; + my $bdata = ""; + use MIME::Base64; + while(<>) { + if (/-- BEGIN MESSAGE ARCHIVE --/ .. /-- END MESSAGE ARCHIVE --/) { + if ( m/^\s*[^\s]+\s*$/) { + $bdata = $bdata . $_; + } + } + } + print decode_base64($bdata); + + + Figure 58 + + Alternatively, the base-64 encoded block can be edited by hand to + remove document structure lines and fed as input to any base-64 + decoding utility. + + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 47] + +RFC 4475 SIP Torture Test Messages May 2006 + + +A.1. Encoded Reference Messages + + -- BEGIN MESSAGE ARCHIVE -- + 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 + + + +Sparks, et al. Informational [Page 48] + +RFC 4475 SIP Torture Test Messages May 2006 + + + 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 + + + +Sparks, et al. Informational [Page 49] + +RFC 4475 SIP Torture Test Messages May 2006 + + + VvAdlxIKjgILniUHqGCvqlQ+dXc/z9lSrWmT6439i7fvntfnwYZ+q7ni3EX2 + ypZTnb8M7+yVtze2hFuX5PKVxvXVa+Duna1r98rXdpW1Sm6TvLFTXdsqmls7 + SL5wcS4noO3du5XS+U18z9x+vfZGSblz4976xRuXLzxYntPuGMrayuaVO6v3 + LOECuUqK6t35N4zta2QDg5vG7g6wXRm8LlX0da24s3a19vollxB9d7NcXbtz + d3O5EAYuzWho2v5Sbx8uBpaqij6KxZ4Rdq0DRLJsUCsCtVRSAtiKVEXMSVgF + JVHJSUpx6V5tT7hXuyddvyOU7+6DvRu65BThjXJxOZPppt1bjBHARJstqEVs + fsUsWapubrO1vExs74dhs9YwXJ3BynxN3yPqQtFiQ5/t/YKMlVKRlAAsEaJl + 2cjhi5g96XXsnqUeG3ez5LJ1aCUOiHlRzEtZ7vLaxvQUGwnIL2/TE3gcqNfq + rD/mvZQ690qpYTvEeTXGe5MQQ2qej562v1eX4Ganp64Qw7CSHDmoQDxvkHdc + m7DVQxKdB7x9/PbzL535+pWv/3j6+Asnvv328Qv0p9dOHD8uvAReeP65uc9+ + 6sQvgJe7JMeFt49zlOQXKQn4ZVAXXgYvPf+pzU8/f/LE5rpwEnyOfXnxJOMN + XbNsU8fC58BPsR9fOPniOja5q9RJFT4LPsN+mjr5HOU03RVeBbPs+8snuXX2 + ndsgjstdILara+zmCLfccMvUH3f3T7x4/FvHdk6g4ye7lzfdubzjx5879umv + fuWd/9F+cuW/b/M/+PA33vmdb33nox/93+e/rd3dKX7zP/7pzB/8ozRV/ruP + v3vuz+Y+/tnGv/yD+s7dwg8vv/KjIvfjj5bd30XTv/X5//zDf/61Dz5z/qcz + b9nf+MG77//1dzP/+1fv//1Pfm5+4cTDm+/P/utG7d/++Dv59xa1v/2bL//w + L6997Ws/8+73//3jn+d//eaHb5E//c1Hz8U9OJ5/Vr0DT1jHq/8FCILjv0Rf + /6frP40l/0s1SR2b+wnHf0JpkN3dtnfjV1uIrQjxx1t3Tf6Ok9BiVSXHlolc + CljSrV2UxPvAA5yWTk6bpafZIgT9Y5jtLZEIZpL8tzcTJptnI1khqnjQtHjZ + 0GOIZNQP6bHAvkVs8KgnVErDMmNtZskYcvYnQfynZ/5PD/9BWv83HvxPsP4n + ZFj0ZPEgL7WDgllgxoc9w/qh4KWQbEmETdQpBwYJyoFRkol9e69MQk+W6OUf + Z9VP5p/0qRRGIxsqYFrUIXEsc6zr/0EYyP/IXv0HSuV/JK29/jftf+6J1/bu + MBOmUsxW9tbZ7PyKAiGbx7u7kne6ivfk6H9rlxhOaaz1/yKUQvKf1v+PPP9r + 4XqmSEg9Pz/fFXqURwDAoxkGlItU+qIe6PD50K/0pYcHOxRhzKZf+Fs1uqt0 + IH8JgT5jANpjMJUklV9iOifhTsNyi3i863/IohS2/+V0/c8Jsv+9+X/W7Ax3 + NcOxaLyvRaOm/2ICHFBQzCKXQnAkUJslPTfgoLF9SthoT7rqpaTkJSCBBLCQ + uNATjmHly6PIEdtkGzeGnABONv97r/4X0/k/R9KGvP5vTkZQKFcgEmDuoJVt + O2zYEwNoizTFjL5r+jKF3w1O9vH9WxmqB54I57kb1k2TXDOtprNR1p31UplN + QWbV8U6D8FQOcIEVaEak/BNpGtCOL2K15I5X/lHY/wdp/mfS5P8g6Y+VfUXJ + IQQPHPTb4b4qEiXs2AbS1OLukgD8sohuNcJBC3ojKSPkKDViL9R3QF9oDfGD + Vzuir0zvikef0DJS+gTYuknjlX8pG43/pfWfT7v85waJvs94IdEPZ3X/v72j + 2W3bBt8L9B2IALsEcUqRki05c9Fi2LB2a7I169JDgUKxKFv+oRxSspqctp4H + 7F2G9bjtFZI3Gj9RdiXZlpN2tZNVbFLHlCjJ9Pf/+x+29nu2wtS4DvXvQBu/ + Dx5SKVSu+LQtgNfq/9RckP9Jjf+3BP+XN2AhVQY2ahLp+eFqs33eVlBh/Seg + jZNBfx4ITpu2Q01IIFUKogMxw5TkCMOcuMyhmtAQTzxn6vLRGU24GHGWhP7A + lU4cLMomFKvP+/WbSSBYapTYwFjtmijuMJQQRwdMP1uH2Jg4LctpNimxDesj + zJh6p0a9beJ/U+d/ENLEoCim8n9t/9us/8/CFB0zMQ26DL3g7tQNRu7piH0Q + +l9cvPEC6Ngtk8Xyh2rptanCQlxVRhaYK72BzwbJ3EBA0mxRm5qtFqHYhEQC + I5//WSQMCtx56EqGQx+STfqcnIV+6MIb4rLEh2sJ6EoSifPGYz9iQt3CdCgm + NrXVTsErvIX7OLaSc05cwdPgXcNWtw2nTESxYGjnCUc/iLCnUFbu3E5fg/Qm + W8//blkL8T+E1vr/7bL/p0a+14tKwOraCeXY0GuUBKosBqRBNTMNQnCQp8iA + d//e426XTaIsjp+Hp6F3Prft3cApYFjVOWGFog63pQfQRzsCJBsHW67/ha1W + Tv5vZvX/mjX+b2KU878P1IfsxF+YOIecNycKK1E9FD0dDUCJSariAWZwudQf + YL/n7DPkL6HgXmFiMuzKVmMcjNkeiNF6lNKU9nITMuhxNZM7VzFwt8fUAXXl + 3BtfuL0qknL789EjJj91+6/19r98/ReN/6RV+/82zf+VZMwfKdU4HAdZesMR + UohVntW4LdzRpF9E+mfuy4Z/JE7c596xgnDczDv4UjgrIHPe1Pfy/OLivEHU + aYpnI/WjBH/E4/EpE2olRzpCQJ9F23Nenk4UFHX1FMzVorgfhuhUfbXqa4On + DkN4I9KXJUzdvi5Pj3Sf1E6auHH37X8RJCBCJq7cYv2HZquE/5ZV2/+3w/8/ + + + +Sparks, et al. Informational [Page 50] + +RFC 4475 SIP Torture Test Messages May 2006 + + + rP7vR1X+RTkYHAaDvukOPe6eDYYJ4550pQ+MfwWfv1ZN4PVl4EqLjr/6Sa0i + VatGrhx4fb9sH/n+GEW0Yh1xbBxzDz5R8TEPvzs8OjlEkVmxWKk72KeMLzHK + VLo/sOsEns8ZWyJ6RCKR2+b/Fi7jv0lxjf8bx3/BxmHEGmo/esuFfoQq+7Gv + gHhQ1bGT9wWsvFHR/DcKFUlpCCbDWHTZMsLimMTBdr7aQQrPYdCNqelYNoQQ + Mx8iiPsCGpqLtYSEUNvJBxcv72Xy/4kYjvlQdseflgKslf9NWsb/Zo3/m8X/ + kt1Mx8S1ozCCpnk6NK6rAX8T2QAZVPI6G2AT+D8mW8Z/Ssr4b5Fa/78l/n/A + 8kCe8raSXWnLIXaLzrl0P4ogYShJkv1lYr9CzDJWp7CWqv/980mfcTdiXqNc + xvE9MzYdnHfwL3Lj1QUnjOtEAn4JzcHaT8M+f308DqL+w8+tWmTMt57/a2Cj + 7P+zDFrXf9vImEn2BGPUQWR3l6JdZO3uEnT51+Xf6OrXq7fq5fLPy3eXf1z9 + DnOlqau3V7+hBrr85+qX2bHLd1U2cccu4aRBiemQIqHIgBKaAQ2B6Q/pgDCR + MM+Xj48rUolXBiMahm43skJqYV6sXZAEwhMWXX7XSwlaFsbj2AsZxjdLE3Ls + lXlCcOj2tRSsxx0aiQz4dLvxH0bLMsrxH0oArOn/hv0/02DKhr1H3b4biIbH + RbegNGXdvtPe3Dnh8Ai1799bvxwdIIQUgQVnakcRMMOGf5Ty+/d8AZ1GUBvt + PEXPQ8n4KRM99OrVq52dzPuqs009AQcfLcREwn9w5Q6CIl8Dz17jidIQv8QJ + VaT66SOlsR5dmVaewdiBW+XiSLK20gg9UCen24GA1Wm38VwOnXE76mCZiZ8S + Nu2QJd+4vDdi3rfM9SDEDCHOEl/PoayXLgKtO+Cxmlk8mLWq1+tPlPj6gscy + dkc/w+E2OjjY21O/B2t5l664qm6W7rTUYYCy8PWPxAwCEnWfjm42P+sAz0Pd + qf1h2oZ9tiepwfABAh0chpwEwO4KUJF9fXqHADIQyoQCJxgObITABz/fYn1F + 9SfIE+kGG017n1jWvuLucK3sQh21aBaJDBF6igO2d36MQ6VqIBmJgCvw2gHw + WglY6lJqtzWsd2ZhAGom/ZT6mSXYQzx9ygE6U8+O9ym9MXtfWQPI3Axrv2AK + /fwt6/8EL9r/av3/Dvn/qix9vb70TCNHgDOQG4Apb+TzMQnJyKTCirE29xVM + e5QYFZ69a/V4AitCULYd4Lr0Rz3qUY/PfPwLcaRGXQDwAAA= + -- END MESSAGE ARCHIVE -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sparks, et al. Informational [Page 51] + +RFC 4475 SIP Torture Test Messages May 2006 + + +Authors' Addresses + + Robert J. Sparks (editor) + Estacado Systems + + EMail: RjS@estacado.net + + + Alan Hawrylyshen + Ditech Networks + 200 - 1167 Kensington Cr. NW + Calgary, Alberta T2N 1X7 + Canada + + Phone : +1.403.806.3366 + EMail : ahawrylyshen@ditechcom.com + + + Alan Johnston + Avaya + St. Louis, MO 63124 + + EMail: alan@sipstation.com + + + Jonathan Rosenberg + Cisco Systems + 600 Lanidex Plaza + Parsippany, NJ 07052 + + Phone: +1 973 952 5000 + EMail: jdrosen@cisco.com + URI: http://www.jdrosen.net + + + Henning Schulzrinne + Columbia University + Department of Computer Science + 450 Computer Science Building + New York, NY 10027 + US + + Phone: +1 212 939 7042 + EMail: hgs@cs.columbia.edu + URI: http://www.cs.columbia.edu + + + + + + +Sparks, et al. Informational [Page 52] + +RFC 4475 SIP Torture Test Messages May 2006 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2006). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at + ietf-ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is provided by the IETF + Administrative Support Activity (IASA). + + + + + + + +Sparks, et al. Informational [Page 53] + diff --git a/tools/write_fixture.py b/tools/write_fixture.py new file mode 100755 index 0000000..74f5d2d --- /dev/null +++ b/tools/write_fixture.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +""" +Tooling: write a SIP fixture .raw file with byte-exact CRLF line endings. + +The repository keeps fixtures under +`sip-compliance-tests/src/test/resources/torture/`. Editors silently strip CR +characters on save which corrupts wire-format fixtures, so we generate them +from text source files via this helper. + +Each text source file has the format: + + --- raw --- + + --- expect --- + + +Splitting convention (important): + + * The marker lines themselves are NOT part of the wire bytes. + * The `\\n` that terminates the line PRECEDING `--- expect ---` IS part + of the wire bytes (so the last content line keeps its trailing CRLF). + * Authors include CRLFCRLF terminators by putting a blank line BEFORE + `--- expect ---` (for no-body messages) or by placing body content + immediately above the marker (for with-body messages). + +This script reads such a `.fixture` file and emits both `.raw` (CRLF) +and `.expect.properties`. + +Usage: + python3 tools/write_fixture.py path/to/source.fixture +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +RAW_DELIM = "--- raw ---" +EXPECT_DELIM = "--- expect ---" + + +def split(text: str) -> tuple[str, str]: + """Split a .fixture into (raw, expect) sections. + + The split is strictly delimiter-based: ``raw`` consists of every byte + that appears AFTER the newline terminating the ``--- raw ---`` marker + and BEFORE the newline introducing the ``--- expect ---`` marker. + Whitespace inside the raw section is preserved exactly. The fixture + author controls the final CRLFCRLF (terminating empty line) explicitly + by putting a single blank line at the end of the raw section before + the next delimiter. + """ + if RAW_DELIM not in text or EXPECT_DELIM not in text: + raise SystemExit( + f"missing section markers in source: need '{RAW_DELIM}' and '{EXPECT_DELIM}'") + + raw_marker_idx = text.index(RAW_DELIM) + raw_start = text.index("\n", raw_marker_idx) + 1 + expect_marker_idx = text.index(EXPECT_DELIM, raw_start) + # Find the newline that precedes the expect marker so we don't include it. + raw_end = text.rfind("\n", raw_start, expect_marker_idx) + 1 + + raw = text[raw_start:raw_end] + expect = text[text.index("\n", expect_marker_idx) + 1:] + return raw, expect + + +def to_crlf(text: str) -> bytes: + """LF → CRLF transcoding. Idempotent for already-CRLF input.""" + return text.replace("\r\n", "\n").replace("\n", "\r\n").encode("ascii") + + +def main(argv: list[str]) -> int: + if len(argv) != 2: + sys.stderr.write(f"usage: {argv[0]} \n") + return 2 + + src = Path(argv[1]) + if not src.exists(): + sys.stderr.write(f"source not found: {src}\n") + return 1 + + raw_text, expect_text = split(src.read_text(encoding="utf-8")) + if not src.name.endswith(".fixture"): + raise SystemExit(f"source must end with .fixture: {src}") + base_name = src.name[: -len(".fixture")] + raw_path = src.with_name(base_name + ".raw") + expect_path = src.with_name(base_name + ".expect.properties") + + raw_bytes = to_crlf(raw_text) + raw_path.write_bytes(raw_bytes) + + expect_path.write_text(expect_text, encoding="utf-8") + + sys.stdout.write(f"wrote {raw_path} ({len(raw_bytes)} bytes, CRLF)\n") + sys.stdout.write(f"wrote {expect_path}\n") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) From db8135636af2f366bef8dd06e4cf352c00160a60 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 11 May 2026 15:04:27 +0000 Subject: [PATCH 2/3] =?UTF-8?q?feat(compliance):=20=E5=AE=9E=E7=8E=B0=20fi?= =?UTF-8?q?xture=20=E5=8A=A0=E8=BD=BD=E5=99=A8=E4=B8=8E=20manifest=20?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 com.sip.compliance.fixture 包: - MessageKind:sealed enum(REQUEST/RESPONSE) - FixtureExpectation:sealed 接口(Accept/Reject 两种 verdict) - TortureFixture:record,承载 id、source、bytes、expectation - FixtureRepository:从 classpath 'torture/' 根递归扫描所有 .raw + 配对的 .expect.properties,返回稳定排序的 fixture 列表 - FixtureRepositoryTest:harness 自身的 self-test,使用 JUnit 5 DynamicTest 对每个 fixture 做: · CRLF 字节级一致性(不允许 lone CR / lone LF) · accept 一致性(CRLFCRLF 终止符、body.length 与实际字节数匹配、 request/response 必填字段齐全) · reject 一致性(error.category 非空且符合 kebab-case) manifest 走 java.util.Properties,零依赖。 本提交不引入任何 fixture 数据,下一个提交单独添加。 旧的 Rfc4475TortureSmokeTest 占位测试被新的 self-test 取代。 Co-authored-by: li xuanqun <793005378@qq.com> --- .../compliance/Rfc4475TortureSmokeTest.java | 28 --- .../fixture/FixtureExpectation.java | 34 ++++ .../compliance/fixture/FixtureRepository.java | 183 ++++++++++++++++++ .../fixture/FixtureRepositoryTest.java | 143 ++++++++++++++ .../sip/compliance/fixture/MessageKind.java | 7 + .../compliance/fixture/TortureFixture.java | 38 ++++ 6 files changed, 405 insertions(+), 28 deletions(-) delete mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/Rfc4475TortureSmokeTest.java create mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureExpectation.java create mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepository.java create mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepositoryTest.java create mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/fixture/MessageKind.java create mode 100644 sip-compliance-tests/src/test/java/com/sip/compliance/fixture/TortureFixture.java diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/Rfc4475TortureSmokeTest.java b/sip-compliance-tests/src/test/java/com/sip/compliance/Rfc4475TortureSmokeTest.java deleted file mode 100644 index 10cb0b6..0000000 --- a/sip-compliance-tests/src/test/java/com/sip/compliance/Rfc4475TortureSmokeTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sip.compliance; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Placeholder for the RFC 4475 (SIP Torture Tests) gate. - * - *

Once the parser is implemented, this class will:

- *
    - *
  1. Load every torture vector from {@code src/test/resources/torture/}.
  2. - *
  3. Parse each fixture and assert it either succeeds (valid messages) - * or fails in the expected way (intentionally malformed messages).
  4. - *
  5. Round-trip every valid fixture through encoder → parser and check - * structural equality.
  6. - *
- * - *

RFC 5118 (IPv6 quirks) will follow the same pattern.

- */ -class Rfc4475TortureSmokeTest { - - @Test - void harnessIsWiredUp() { - // Smoke test so the compliance module isn't empty. - assertThat(getClass().getSimpleName()).isEqualTo("Rfc4475TortureSmokeTest"); - } -} diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureExpectation.java b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureExpectation.java new file mode 100644 index 0000000..0bf9746 --- /dev/null +++ b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureExpectation.java @@ -0,0 +1,34 @@ +package com.sip.compliance.fixture; + +import java.util.Optional; + +/** + * Declarative expectation attached to each torture fixture. + * + *

Sealed so the harness can pattern-match exhaustively on the verdict + * and tests stay total. Two outcomes:

+ * + *
    + *
  • {@link Accept} — the parser must succeed and produce a message + * matching the declared metadata.
  • + *
  • {@link Reject} — the parser must throw and the rejection should + * fall into the declared category.
  • + *
+ */ +public sealed interface FixtureExpectation + permits FixtureExpectation.Accept, FixtureExpectation.Reject { + + /** Expected verdict when the parser sees this fixture. */ + record Accept( + MessageKind kind, + Optional method, + Optional requestUri, + Optional status, + Optional reason, + String version, + int headerCount, + int bodyLength) implements FixtureExpectation { } + + /** The parser must reject this fixture; the category groups the failure. */ + record Reject(String category, String detail) implements FixtureExpectation { } +} diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepository.java b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepository.java new file mode 100644 index 0000000..24571ac --- /dev/null +++ b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepository.java @@ -0,0 +1,183 @@ +package com.sip.compliance.fixture; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.stream.Stream; + +/** + * Loads torture fixtures from the test-classpath {@code /torture/} root. + * + *

Layout

+ *
+ * torture/
+ *   self-test/
+ *     simple-options.raw
+ *     simple-options.expect.properties
+ *   rfc4475/
+ *     3.1.1.1-short-tortuous-invite.raw
+ *     3.1.1.1-short-tortuous-invite.expect.properties
+ * 
+ * + *

Each {@code .raw} file is a byte-exact SIP message, paired with a + * {@code .expect.properties} sibling that declares the expected parse + * outcome (see {@link FixtureExpectation}).

+ * + *

The repository walks the directory tree rooted at the classpath + * resource {@code torture/} — which resolves to + * {@code src/test/resources/torture/} when run from this module — and + * returns every paired fixture in deterministic id order.

+ */ +public final class FixtureRepository { + + private static final String ROOT = "torture"; + + private FixtureRepository() { } + + /** Loads all fixtures available on the test classpath. */ + public static List loadAll() { + Path root = resolveRoot(); + List out = new ArrayList<>(); + try (Stream stream = Files.walk(root)) { + stream + .filter(p -> p.toString().endsWith(".raw")) + .sorted(Comparator.comparing(Path::toString)) + .forEach(rawPath -> out.add(load(root, rawPath))); + } catch (IOException e) { + throw new UncheckedIOException("walking " + root, e); + } + return List.copyOf(out); + } + + private static Path resolveRoot() { + URL url = FixtureRepository.class.getClassLoader().getResource(ROOT); + if (url == null) { + throw new IllegalStateException("classpath root not found: " + ROOT); + } + try { + return Paths.get(url.toURI()); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + } + + private static TortureFixture load(Path root, Path rawPath) { + Path expectPath = sibling(rawPath, ".expect.properties"); + if (!Files.exists(expectPath)) { + throw new IllegalStateException( + "missing expectation file for fixture: " + rawPath + + " (expected at " + expectPath + ")"); + } + + byte[] bytes; + Properties props = new Properties(); + try { + bytes = Files.readAllBytes(rawPath); + try (var in = Files.newInputStream(expectPath)) { + props.load(in); + } + } catch (IOException e) { + throw new UncheckedIOException("loading fixture " + rawPath, e); + } + + Path relative = root.relativize(rawPath); + String idWithExt = relative.toString().replace('\\', '/'); + String id = idWithExt.substring(0, idWithExt.length() - ".raw".length()); + String source = relative.getNameCount() > 1 + ? relative.getName(0).toString() + : "ungrouped"; + + FixtureExpectation expectation = parseExpectation(id, props, bytes.length); + return new TortureFixture(id, source, bytes, expectation); + } + + private static Path sibling(Path rawPath, String suffix) { + String filename = rawPath.getFileName().toString(); + String base = filename.substring(0, filename.length() - ".raw".length()); + return rawPath.resolveSibling(base + suffix); + } + + private static FixtureExpectation parseExpectation(String id, Properties p, int rawSize) { + String verdict = required(p, "verdict", id).trim().toLowerCase(); + return switch (verdict) { + case "accept" -> parseAccept(id, p, rawSize); + case "reject" -> parseReject(id, p); + default -> throw new IllegalStateException( + "fixture " + id + ": unknown verdict '" + verdict + "'"); + }; + } + + private static FixtureExpectation.Accept parseAccept(String id, Properties p, int rawSize) { + MessageKind kind = parseKind(id, required(p, "message.type", id)); + Optional method = optional(p, "request.method"); + Optional requestUri = optional(p, "request.uri"); + Optional status = optional(p, "response.status").map(Integer::parseInt); + Optional reason = optional(p, "response.reason"); + String version = p.getProperty("sip.version", "SIP/2.0"); + int headerCount = Integer.parseInt(required(p, "header.count", id)); + int bodyLength = Integer.parseInt(p.getProperty("body.length", "0")); + + if (kind == MessageKind.REQUEST && (method.isEmpty() || requestUri.isEmpty())) { + throw new IllegalStateException( + "fixture " + id + ": request fixtures must declare both " + + "request.method and request.uri"); + } + if (kind == MessageKind.RESPONSE && (status.isEmpty() || reason.isEmpty())) { + throw new IllegalStateException( + "fixture " + id + ": response fixtures must declare both " + + "response.status and response.reason"); + } + if (bodyLength < 0 || bodyLength > rawSize) { + throw new IllegalStateException( + "fixture " + id + ": body.length out of range: " + bodyLength + + " (raw size " + rawSize + ")"); + } + + return new FixtureExpectation.Accept( + kind, method, requestUri, status, reason, version, headerCount, bodyLength); + } + + private static FixtureExpectation.Reject parseReject(String id, Properties p) { + String category = required(p, "error.category", id); + String detail = p.getProperty("error.detail", ""); + return new FixtureExpectation.Reject(category, detail); + } + + private static MessageKind parseKind(String id, String raw) { + return switch (raw.trim().toLowerCase()) { + case "request" -> MessageKind.REQUEST; + case "response" -> MessageKind.RESPONSE; + default -> throw new IllegalStateException( + "fixture " + id + ": invalid message.type '" + raw + "'"); + }; + } + + private static String required(Properties p, String key, String id) { + String v = p.getProperty(key); + if (v == null || v.isBlank()) { + throw new IllegalStateException( + "fixture " + id + ": missing required property '" + key + "'"); + } + return v; + } + + private static Optional optional(Properties p, String key) { + String v = p.getProperty(key); + return (v == null || v.isBlank()) ? Optional.empty() : Optional.of(v); + } + + /** Convenience for tests: helpful when reporting a fixture in a message. */ + public static URI uriOf(String id) { + return URI.create("classpath:" + ROOT + "/" + id + ".raw"); + } +} diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepositoryTest.java b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepositoryTest.java new file mode 100644 index 0000000..d7edbea --- /dev/null +++ b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/FixtureRepositoryTest.java @@ -0,0 +1,143 @@ +package com.sip.compliance.fixture; + +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +/** + * Self-test for the torture-fixture harness. + * + *

The parser itself does not exist yet — this test class verifies that the + * fixture authoring pipeline works end-to-end: every {@code .raw} file + * has a paired {@code .expect.properties}, every manifest is well-formed, + * every fixture preserves CRLF byte exactness, and the declared metadata + * is internally consistent with the raw bytes (e.g. {@code body.length} + * matches the actual number of bytes after {@code CRLFCRLF}).

+ * + *

Once the parser lands, a sibling test class will iterate the same + * fixture set and feed each one to {@link com.sip.codec.SipParser}.

+ */ +class FixtureRepositoryTest { + + private static final List FIXTURES = FixtureRepository.loadAll(); + + @Test + void repositoryFindsAllFixturesInDeterministicOrder() { + assertThat(FIXTURES) + .as("expected at least one fixture under each source bucket") + .isNotEmpty(); + assertThat(FIXTURES).extracting(TortureFixture::source) + .as("self-test and rfc4475 buckets must both be populated") + .contains("self-test", "rfc4475"); + + List ids = FIXTURES.stream().map(TortureFixture::id).toList(); + assertThat(ids) + .as("fixture ids must be unique") + .doesNotHaveDuplicates(); + assertThat(ids) + .as("fixture order is path-sorted for deterministic test runs") + .isSortedAccordingTo(String::compareTo); + } + + @TestFactory + Iterable everyFixturePreservesCrlfByteExactness() { + return FIXTURES.stream() + .map(fx -> dynamicTest("CRLF: " + fx.id(), () -> assertCrlfClean(fx))) + .toList(); + } + + @TestFactory + Iterable everyAcceptFixtureIsInternallyConsistent() { + return FIXTURES.stream() + .filter(fx -> fx.expectation() instanceof FixtureExpectation.Accept) + .map(fx -> dynamicTest("accept: " + fx.id(), () -> assertAcceptConsistent(fx))) + .toList(); + } + + @TestFactory + Iterable everyRejectFixtureCarriesACategory() { + return FIXTURES.stream() + .filter(fx -> fx.expectation() instanceof FixtureExpectation.Reject) + .map(fx -> dynamicTest("reject: " + fx.id(), () -> assertRejectWellFormed(fx))) + .toList(); + } + + private static void assertCrlfClean(TortureFixture fx) { + byte[] b = fx.bytes(); + for (int i = 0; i < b.length; i++) { + if (b[i] == '\n') { + assertThat(i > 0 && b[i - 1] == '\r') + .as("fixture " + fx.id() + " offset " + i + + ": LF must be preceded by CR (wire-format CRLF)") + .isTrue(); + } + if (b[i] == '\r') { + assertThat(i + 1 < b.length && b[i + 1] == '\n') + .as("fixture " + fx.id() + " offset " + i + + ": CR must be followed by LF (no lone CR)") + .isTrue(); + } + } + } + + private static void assertAcceptConsistent(TortureFixture fx) { + FixtureExpectation.Accept e = (FixtureExpectation.Accept) fx.expectation(); + + byte[] bytes = fx.bytes(); + int sep = indexOfCrlfCrlf(bytes); + assertThat(sep) + .as("accept fixture " + fx.id() + ": header block must terminate in CRLFCRLF") + .isGreaterThanOrEqualTo(0); + + int actualBody = bytes.length - (sep + 4); + assertThat(actualBody) + .as("accept fixture " + fx.id() + ": body.length manifest disagrees with raw") + .isEqualTo(e.bodyLength()); + + switch (e.kind()) { + case REQUEST -> { + assertThat(e.method()) + .as(fx.id() + ": request must declare request.method") + .isPresent(); + assertThat(e.requestUri()) + .as(fx.id() + ": request must declare request.uri") + .isPresent(); + } + case RESPONSE -> { + assertThat(e.status()) + .as(fx.id() + ": response must declare response.status") + .isPresent(); + assertThat(e.reason()) + .as(fx.id() + ": response must declare response.reason") + .isPresent(); + int s = e.status().orElseThrow(); + assertThat(s).isBetween(100, 699); + } + } + + assertThat(e.version()).startsWith("SIP/"); + assertThat(e.headerCount()).isGreaterThan(0); + } + + private static void assertRejectWellFormed(TortureFixture fx) { + FixtureExpectation.Reject r = (FixtureExpectation.Reject) fx.expectation(); + assertThat(r.category()).isNotBlank(); + assertThat(r.category()).matches("[a-z0-9][a-z0-9\\-]*[a-z0-9]"); + } + + /** Returns the offset of the first CRLFCRLF in {@code data}, or -1. */ + private static int indexOfCrlfCrlf(byte[] data) { + for (int i = 0; i + 3 < data.length; i++) { + if (data[i] == '\r' && data[i + 1] == '\n' + && data[i + 2] == '\r' && data[i + 3] == '\n') { + return i; + } + } + return -1; + } +} diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/MessageKind.java b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/MessageKind.java new file mode 100644 index 0000000..b94ae1f --- /dev/null +++ b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/MessageKind.java @@ -0,0 +1,7 @@ +package com.sip.compliance.fixture; + +/** Whether a fixture represents a SIP request or a SIP response. */ +public enum MessageKind { + REQUEST, + RESPONSE +} diff --git a/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/TortureFixture.java b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/TortureFixture.java new file mode 100644 index 0000000..1867243 --- /dev/null +++ b/sip-compliance-tests/src/test/java/com/sip/compliance/fixture/TortureFixture.java @@ -0,0 +1,38 @@ +package com.sip.compliance.fixture; + +import java.util.Objects; + +/** + * A single conformance fixture. + * + * @param id identifier of the form {@code source/name} (e.g. + * {@code rfc4475/3.1.1.1-short-tortuous-invite}). + * Used in test names and diagnostics. + * @param source source taxonomy bucket ({@code rfc4475}, {@code rfc5118}, + * {@code self-test}). + * @param bytes byte-exact wire representation, including CRLF and body. + * @param expectation declarative outcome the parser must satisfy. + */ +public record TortureFixture( + String id, + String source, + byte[] bytes, + FixtureExpectation expectation) { + + public TortureFixture { + Objects.requireNonNull(id, "id"); + Objects.requireNonNull(source, "source"); + Objects.requireNonNull(bytes, "bytes"); + Objects.requireNonNull(expectation, "expectation"); + bytes = bytes.clone(); + } + + @Override + public byte[] bytes() { + return bytes.clone(); + } + + public int size() { + return bytes.length; + } +} From 808ef05886652eab423075ee80ee2183cca532ac Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 11 May 2026 15:04:49 +0000 Subject: [PATCH 3/3] =?UTF-8?q?test(compliance):=20=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E9=A6=96=E6=89=B9=20self-test=20=E4=B8=8E=20RFC=204475=20fixtu?= =?UTF-8?q?res?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit self-test/(4 个我们自己撰写的基线 fixture): - simple-options.fixture clean OPTIONS request(accept) - simple-200-ok.fixture clean 200 OK response(accept) - invite-with-sdp.fixture INVITE + 162 字节 SDP body(accept, 验证 Content-Length-driven framing) - missing-sip-version.fixture Request-Line 缺 SIP-Version token (reject, malformed-start-line) rfc4475/(3 个从 RFC 4475 byte-exact 提取的 torture vector): - 3.1.1.6-lwsdisp.fixture display-name 与 < 之间无 LWS(accept) - 3.1.1.9-semiuri.fixture URI userpart 含分号参数 + Accept 头 LWS folding(accept) - 3.1.2.1-badinv01.fixture Via 与 Contact 头多余分隔符(reject, malformed-header) 每个 fixture 通过 tools/write_fixture.py 从 .fixture 源生成 .raw(CRLF byte-exact)和 .expect.properties(JDK Properties,零依赖)。 torture/README.md 详细说明 fixture 文件格式约定和 no-body / with-body 两种结构下空行的语义。 FixtureRepositoryTest 跑通全部 15 个动态测试: - 1 个全局排序/去重检查 - 7 个 CRLF 字节级一致性(每个 fixture 一个) - 5 个 accept 一致性(CRLFCRLF + body.length + 必填字段) - 2 个 reject 一致性(category 非空 + kebab-case) Co-authored-by: li xuanqun <793005378@qq.com> --- .../src/test/resources/torture/README.md | 127 +++++++++++++++--- .../rfc4475/3.1.1.6-lwsdisp.expect.properties | 7 + .../torture/rfc4475/3.1.1.6-lwsdisp.fixture | 30 +++++ .../torture/rfc4475/3.1.1.6-lwsdisp.raw | 9 ++ .../rfc4475/3.1.1.9-semiuri.expect.properties | 7 + .../torture/rfc4475/3.1.1.9-semiuri.fixture | 31 +++++ .../torture/rfc4475/3.1.1.9-semiuri.raw | 12 ++ .../3.1.2.1-badinv01.expect.properties | 3 + .../torture/rfc4475/3.1.2.1-badinv01.fixture | 35 +++++ .../torture/rfc4475/3.1.2.1-badinv01.raw | 19 +++ .../invite-with-sdp.expect.properties | 7 + .../torture/self-test/invite-with-sdp.fixture | 31 +++++ .../torture/self-test/invite-with-sdp.raw | 18 +++ .../missing-sip-version.expect.properties | 3 + .../self-test/missing-sip-version.fixture | 18 +++ .../torture/self-test/missing-sip-version.raw | 9 ++ .../self-test/simple-200-ok.expect.properties | 7 + .../torture/self-test/simple-200-ok.fixture | 19 +++ .../torture/self-test/simple-200-ok.raw | 8 ++ .../simple-options.expect.properties | 7 + .../torture/self-test/simple-options.fixture | 23 ++++ .../torture/self-test/simple-options.raw | 11 ++ 22 files changed, 424 insertions(+), 17 deletions(-) create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.raw create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-options.expect.properties create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-options.fixture create mode 100644 sip-compliance-tests/src/test/resources/torture/self-test/simple-options.raw diff --git a/sip-compliance-tests/src/test/resources/torture/README.md b/sip-compliance-tests/src/test/resources/torture/README.md index 7bd49d8..ed95f10 100644 --- a/sip-compliance-tests/src/test/resources/torture/README.md +++ b/sip-compliance-tests/src/test/resources/torture/README.md @@ -1,22 +1,115 @@ -# RFC 4475 / RFC 5118 Torture Test Fixtures +# Torture Fixture Repository -This directory hosts the verbatim message fixtures used by the compliance harness. +Byte-exact SIP message fixtures consumed by the conformance harness in +`com.sip.compliance.fixture`. -## Where to get them +## Layout -- **RFC 4475** — *Session Initiation Protocol (SIP) Torture Test Messages* - - The RFC contains 32 message fixtures embedded inline. The de-facto canonical - byte-exact versions live in the `sipit/torture` repositories — pick a single - source and commit the bytes verbatim, do not normalize line endings. -- **RFC 5118** — *Session Initiation Protocol (SIP) Torture Test Messages - for IPv6* +``` +torture/ +├── self-test/ fixtures we authored ourselves (baseline / harness sanity) +├── rfc4475/ RFC 4475 — SIP torture test messages +└── rfc5118/ RFC 5118 — IPv6 torture test messages +``` -## Conventions +## File pairs -- One file per fixture, named after the section in the RFC, e.g. - `3.1.1.1-short-tortuous-invite.txt`. -- For each fixture, a companion `*.expect.json` file declares whether the - parser is expected to `accept` or `reject` it, and (for accepted messages) - the expected start-line. -- Line endings are **CRLF** as on the wire. Do not let your editor convert. +Every fixture is a **two-file pair**: + +| File | Format | Notes | +|------|--------|-------| +| `.raw` | byte-exact SIP wire format | **CRLF line endings**, no BOM, no trailing edit, treated as binary by git (`.gitattributes`) | +| `.expect.properties` | JDK `java.util.Properties` | declarative parse expectation | + +## `.expect.properties` schema + +### Verdict (required) + +```properties +verdict = accept +# or: +verdict = reject +``` + +### When `verdict = accept` + +```properties +message.type = request # request | response +request.method = INVITE # required when message.type = request +request.uri = sip:bob@example.com +response.status = 200 # required when message.type = response +response.reason = OK +sip.version = SIP/2.0 +header.count = 14 +body.length = 0 # optional, defaults to 0 +``` + +### When `verdict = reject` + +```properties +error.category = malformed-start-line +error.detail = "missing SIP-Version token after Request-URI" +``` + +The `error.category` is a stable lower-kebab-case taxonomy: + +| Category | Meaning | +|----------|---------| +| `malformed-start-line` | request-line or status-line doesn't match ABNF | +| `unknown-version` | SIP version other than `SIP/2.0` | +| `malformed-header` | a header line cannot be parsed | +| `bad-content-length` | `Content-Length` missing/invalid on framed transport | +| `truncated` | message ends mid-header or mid-body | +| `unsupported-uri-scheme` | Request-URI scheme not recognized | + +The list grows as the parser learns to distinguish more failure modes. + +## How to add a fixture + +Use the `.fixture` source file workflow — never hand-edit `.raw` files +(editors strip CR characters silently and corrupt the wire format). + +1. **Author a `.fixture` source file** in the appropriate subdirectory, + following the format: + + ``` + Free-form description of what this fixture exercises and where it + came from (RFC section, self-test rationale, ...). + + --- raw --- + + --- expect --- + + ``` + + **Conventions for the `--- raw ---` section:** + - For a message **without a body** (`Content-Length: 0`), put one blank + line between the last header and `--- expect ---`. That blank line + becomes the CRLFCRLF terminator on the wire. + - For a message **with a body**, put one blank line between the last + header and the body content, then place the body **directly above** + `--- expect ---` (NO trailing blank line — that would add stray + bytes beyond `Content-Length`). + +2. **Run the generator** to emit `.raw` + `.expect.properties`: + + ``` + python3 tools/write_fixture.py path/to/.fixture + ``` + + The script transcodes LF → CRLF and preserves byte exactness. + +3. **Verify** with `od -c .raw | tail -2` that the message ends as + expected (CRLFCRLF for no-body; last body byte for with-body). + +4. **Re-run** `mvn -pl sip-compliance-tests test`. The harness picks up + the new fixture automatically; no Java code changes are required. + +## Provenance + +- **`rfc4475/`**: messages extracted verbatim from RFC 4475 §3.1 / §3.2. + Section numbers are preserved in fixture ids (e.g. `3.1.1.1-...`) so + fixtures map 1:1 back to the RFC. +- **`rfc5118/`**: messages from RFC 5118 (IPv6 torture tests). +- **`self-test/`**: messages we author to anchor the harness and lock down + baseline behaviour. These are NOT taken from any RFC and may be revised. diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.expect.properties b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.expect.properties new file mode 100644 index 0000000..38d1e86 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.expect.properties @@ -0,0 +1,7 @@ +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:user@example.com +sip.version = SIP/2.0 +header.count = 7 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.fixture b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.fixture new file mode 100644 index 0000000..0b65a9f --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.fixture @@ -0,0 +1,30 @@ +RFC 4475 §3.1.1.6 — Message with No LWS between Display Name and < + +A well-formed OPTIONS request whose From header field uses the form +`caller` with NO whitespace between the display-name token +and the `<`. This is a known RFC 3261 ABNF imperfection; conformant +parsers must accept it. + +Provenance: extracted byte-for-byte from RFC 4475 §3.1.1.6 (message id +`lwsdisp`). Section 2 of the RFC explains the indentation/markup +conventions used in the original text; this fixture removes the 6-space +RFC indent and uses CRLF as required on the wire. + +--- raw --- +OPTIONS sip:user@example.com SIP/2.0 +To: sip:user@example.com +From: caller;tag=323 +Max-Forwards: 70 +Call-ID: lwsdisp.1234abcd@funky.example.com +CSeq: 60 OPTIONS +Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw +l: 0 + +--- expect --- +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:user@example.com +sip.version = SIP/2.0 +header.count = 7 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.raw b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.raw new file mode 100644 index 0000000..64f5168 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.6-lwsdisp.raw @@ -0,0 +1,9 @@ +OPTIONS sip:user@example.com SIP/2.0 +To: sip:user@example.com +From: caller;tag=323 +Max-Forwards: 70 +Call-ID: lwsdisp.1234abcd@funky.example.com +CSeq: 60 OPTIONS +Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw +l: 0 + diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.expect.properties b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.expect.properties new file mode 100644 index 0000000..8a17372 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.expect.properties @@ -0,0 +1,7 @@ +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:user;par=u%40example.net@example.com +sip.version = SIP/2.0 +header.count = 8 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.fixture b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.fixture new file mode 100644 index 0000000..20ce294 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.fixture @@ -0,0 +1,31 @@ +RFC 4475 §3.1.1.9 — Semicolon-Separated Parameters in URI User Part + +Well-formed OPTIONS request whose Request-URI carries a semicolon +parameter inside the userpart (with an escaped `@`). Also exercises +LWS folding in the Accept header field (three folded continuation +lines combine into a single logical header value). + +Provenance: extracted byte-for-byte from RFC 4475 §3.1.1.9 (message +id `semiuri`). + +--- raw --- +OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0 +To: sip:j_user@example.com +From: sip:caller@example.org;tag=33242 +Max-Forwards: 3 +Call-ID: semiuri.0ha0isndaksdj +CSeq: 8 OPTIONS +Accept: application/sdp, application/pkcs7-mime, + multipart/mixed, multipart/signed, + message/sip, message/sipfrag +Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw +l: 0 + +--- expect --- +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:user;par=u%40example.net@example.com +sip.version = SIP/2.0 +header.count = 8 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.raw b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.raw new file mode 100644 index 0000000..d177493 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.1.9-semiuri.raw @@ -0,0 +1,12 @@ +OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0 +To: sip:j_user@example.com +From: sip:caller@example.org;tag=33242 +Max-Forwards: 3 +Call-ID: semiuri.0ha0isndaksdj +CSeq: 8 OPTIONS +Accept: application/sdp, application/pkcs7-mime, + multipart/mixed, multipart/signed, + message/sip, message/sipfrag +Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw +l: 0 + diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.expect.properties b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.expect.properties new file mode 100644 index 0000000..e97fbee --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.expect.properties @@ -0,0 +1,3 @@ +verdict = reject +error.category = malformed-header +error.detail = extraneous separators in Via and Contact header values diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.fixture b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.fixture new file mode 100644 index 0000000..87ac8fa --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.fixture @@ -0,0 +1,35 @@ +RFC 4475 §3.1.2.1 — Extraneous Header Field Separators + +Syntactically invalid INVITE: the Via header value contains +double semicolons and trailing commas, and the Contact value has +trailing semicolons without parameters. A conformant parser must +reject this message; an element receiving it should respond with +a 400 Bad Request. + +Provenance: extracted byte-for-byte from RFC 4475 §3.1.2.1 +(message id `badinv01`). + +--- raw --- +INVITE sip:user@example.com SIP/2.0 +To: sip:j.user@example.com +From: sip:caller@example.net;tag=134161461246 +Max-Forwards: 7 +Call-ID: badinv01.0ha0isndaksdjasdf3234nas +CSeq: 8 INVITE +Via: SIP/2.0/UDP 192.0.2.15;;,;,, +Contact: "Joe" ;;;; +Content-Length: 152 +Content-Type: application/sdp + +v=0 +o=mhandley 29739 7272939 IN IP4 192.0.2.15 +s=- +c=IN IP4 192.0.2.15 +t=0 0 +m=audio 49217 RTP/AVP 0 12 +m=video 3227 RTP/AVP 31 +a=rtpmap:31 LPC +--- expect --- +verdict = reject +error.category = malformed-header +error.detail = extraneous separators in Via and Contact header values diff --git a/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.raw b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.raw new file mode 100644 index 0000000..088437e --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/rfc4475/3.1.2.1-badinv01.raw @@ -0,0 +1,19 @@ +INVITE sip:user@example.com SIP/2.0 +To: sip:j.user@example.com +From: sip:caller@example.net;tag=134161461246 +Max-Forwards: 7 +Call-ID: badinv01.0ha0isndaksdjasdf3234nas +CSeq: 8 INVITE +Via: SIP/2.0/UDP 192.0.2.15;;,;,, +Contact: "Joe" ;;;; +Content-Length: 152 +Content-Type: application/sdp + +v=0 +o=mhandley 29739 7272939 IN IP4 192.0.2.15 +s=- +c=IN IP4 192.0.2.15 +t=0 0 +m=audio 49217 RTP/AVP 0 12 +m=video 3227 RTP/AVP 31 +a=rtpmap:31 LPC diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.expect.properties b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.expect.properties new file mode 100644 index 0000000..2491d01 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.expect.properties @@ -0,0 +1,7 @@ +verdict = accept +message.type = request +request.method = INVITE +request.uri = sip:bob@biloxi.example.com +sip.version = SIP/2.0 +header.count = 9 +body.length = 162 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.fixture b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.fixture new file mode 100644 index 0000000..90b34c7 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.fixture @@ -0,0 +1,31 @@ +INVITE carrying an SDP offer (RFC 3264). Exercises Content-Length-driven +body framing and Content-Type recognition. The body length below counts +only the SDP payload (after the empty CRLF line). + +--- raw --- +INVITE sip:bob@biloxi.example.com SIP/2.0 +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds8 +Max-Forwards: 70 +To: Bob +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 314159 INVITE +Contact: +Content-Type: application/sdp +Content-Length: 162 + +v=0 +o=alice 2890844526 2890844526 IN IP4 pc33.atlanta.example.com +s=- +c=IN IP4 pc33.atlanta.example.com +t=0 0 +m=audio 49170 RTP/AVP 0 +a=rtpmap:0 PCMU/8000 +--- expect --- +verdict = accept +message.type = request +request.method = INVITE +request.uri = sip:bob@biloxi.example.com +sip.version = SIP/2.0 +header.count = 9 +body.length = 162 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.raw b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.raw new file mode 100644 index 0000000..51d5119 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/invite-with-sdp.raw @@ -0,0 +1,18 @@ +INVITE sip:bob@biloxi.example.com SIP/2.0 +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds8 +Max-Forwards: 70 +To: Bob +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 314159 INVITE +Contact: +Content-Type: application/sdp +Content-Length: 162 + +v=0 +o=alice 2890844526 2890844526 IN IP4 pc33.atlanta.example.com +s=- +c=IN IP4 pc33.atlanta.example.com +t=0 0 +m=audio 49170 RTP/AVP 0 +a=rtpmap:0 PCMU/8000 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.expect.properties b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.expect.properties new file mode 100644 index 0000000..eef8e8c --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.expect.properties @@ -0,0 +1,3 @@ +verdict = reject +error.category = malformed-start-line +error.detail = Request-Line missing SIP-Version token diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.fixture b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.fixture new file mode 100644 index 0000000..cb1eebd --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.fixture @@ -0,0 +1,18 @@ +Request-Line missing the SIP-Version token. RFC 3261 §7.1 requires three +tokens separated by single SP: Method SP Request-URI SP SIP-Version CRLF. +The parser must reject this and report it under malformed-start-line. + +--- raw --- +OPTIONS sip:carol@chicago.example.com +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +Max-Forwards: 70 +To: +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Content-Length: 0 + +--- expect --- +verdict = reject +error.category = malformed-start-line +error.detail = Request-Line missing SIP-Version token diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.raw b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.raw new file mode 100644 index 0000000..4921e0a --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/missing-sip-version.raw @@ -0,0 +1,9 @@ +OPTIONS sip:carol@chicago.example.com +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +Max-Forwards: 70 +To: +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Content-Length: 0 + diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.expect.properties b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.expect.properties new file mode 100644 index 0000000..0f32c2d --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.expect.properties @@ -0,0 +1,7 @@ +verdict = accept +message.type = response +response.status = 200 +response.reason = OK +sip.version = SIP/2.0 +header.count = 6 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.fixture b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.fixture new file mode 100644 index 0000000..d38bd81 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.fixture @@ -0,0 +1,19 @@ +A minimal 200 OK response. Verifies the parser handles Status-Line correctly. + +--- raw --- +SIP/2.0 200 OK +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +To: ;tag=a6c85cf +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Content-Length: 0 + +--- expect --- +verdict = accept +message.type = response +response.status = 200 +response.reason = OK +sip.version = SIP/2.0 +header.count = 6 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.raw b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.raw new file mode 100644 index 0000000..cc99f63 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-200-ok.raw @@ -0,0 +1,8 @@ +SIP/2.0 200 OK +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +To: ;tag=a6c85cf +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Content-Length: 0 + diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.expect.properties b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.expect.properties new file mode 100644 index 0000000..cd9ef02 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.expect.properties @@ -0,0 +1,7 @@ +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:carol@chicago.example.com +sip.version = SIP/2.0 +header.count = 9 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.fixture b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.fixture new file mode 100644 index 0000000..af341fd --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.fixture @@ -0,0 +1,23 @@ +A minimal, well-formed OPTIONS request. Acts as the baseline "happy path" +that any parser worth shipping must handle. + +--- raw --- +OPTIONS sip:carol@chicago.example.com SIP/2.0 +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +Max-Forwards: 70 +To: +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Contact: +Accept: application/sdp +Content-Length: 0 + +--- expect --- +verdict = accept +message.type = request +request.method = OPTIONS +request.uri = sip:carol@chicago.example.com +sip.version = SIP/2.0 +header.count = 9 +body.length = 0 diff --git a/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.raw b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.raw new file mode 100644 index 0000000..4621834 --- /dev/null +++ b/sip-compliance-tests/src/test/resources/torture/self-test/simple-options.raw @@ -0,0 +1,11 @@ +OPTIONS sip:carol@chicago.example.com SIP/2.0 +Via: SIP/2.0/UDP pc33.atlanta.example.com;branch=z9hG4bKnashds10 +Max-Forwards: 70 +To: +From: Alice ;tag=1928301774 +Call-ID: a84b4c76e66710 +CSeq: 63104 OPTIONS +Contact: +Accept: application/sdp +Content-Length: 0 +