├── .github
├── dependabot.yml
└── workflows
│ └── ci.yaml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── composer.json
├── etc
├── editorconfig.txt
├── phpstan.neon
├── phpunit.xml.dist
└── psalm.xml
├── examples
├── 01-parse-request.php
├── 02-render-request.php
├── 03-parse-response.php
├── 04-render-response.php
├── 05-stream-parse.php
└── 99-crude-benchmark.php
├── src
├── Auth
│ ├── Digest
│ │ ├── AbstractParams.php
│ │ ├── ChallengeParams.php
│ │ └── ResponseParams.php
│ ├── OpaqueParams.php
│ └── ParamsInterface.php
├── Exception
│ ├── AuthException.php
│ ├── InvalidBodyLengthException.php
│ ├── InvalidCSeqValueException.php
│ ├── InvalidDuplicateHeaderException.php
│ ├── InvalidHeaderLineException.php
│ ├── InvalidHeaderParameterException.php
│ ├── InvalidHeaderSectionException.php
│ ├── InvalidHeaderValueException.php
│ ├── InvalidMessageStartLineException.php
│ ├── InvalidProtocolVersionException.php
│ ├── InvalidRequestMethodException.php
│ ├── InvalidRequestURIException.php
│ ├── InvalidScalarValueException.php
│ ├── InvalidStatusCodeException.php
│ ├── InvalidURIException.php
│ └── SIPException.php
├── Header
│ ├── AbstractAuthHeader.php
│ ├── AuthValue.php
│ ├── AuthenticateHeader.php
│ ├── AuthorizationHeader.php
│ ├── CSeqHeader.php
│ ├── CallIdHeader.php
│ ├── ContactHeader.php
│ ├── ContactValue.php
│ ├── FromHeader.php
│ ├── Header.php
│ ├── MaxForwardsHeader.php
│ ├── MultiValueHeader.php
│ ├── MultiValueWithParamsHeader.php
│ ├── NameAddrHeader.php
│ ├── RAckHeader.php
│ ├── ScalarHeader.php
│ ├── SingleValueWithParamsHeader.php
│ ├── ValueWithParams.php
│ ├── ViaHeader.php
│ └── ViaValue.php
├── Message.php
├── Request.php
├── Response.php
├── StreamParser.php
└── URI.php
└── tests
├── Auth
└── Digest
│ └── ResponseParamsTest.php
├── Header
├── AuthenticateHeaderTest.php
├── AuthorizationHeaderTest.php
├── CSeqHeaderTest.php
├── CallIdHeaderTest.php
├── ContactHeaderTest.php
├── FromHeaderTest.php
├── HeaderTest.php
├── MultiValueHeaderTest.php
├── MultiValueWithParamsHeaderTest.php
├── NameAddrHeaderTest.php
├── RAckHeaderTest.php
├── ScalarHeaderTest.php
├── SingleValueWithParamsHeaderTest.php
└── ViaHeaderTest.php
├── MessageTest.php
├── MiscTest.php
├── ProtosTest.php
├── RFC4475
├── RFC4475Case.php
├── S31101Test.php
├── S31102Test.php
├── S31103Test.php
├── S31104Test.php
├── S31105Test.php
├── S31106Test.php
├── S31107Test.php
├── S31108Test.php
├── S31109Test.php
├── S31110Test.php
├── S31111Test.php
├── S31112Test.php
├── S31113Test.php
├── S31201Test.php
├── S31202Test.php
├── S31203Test.php
├── S31204Test.php
├── S31205Test.php
├── S31206Test.php
├── S31207Test.php
├── S31208Test.php
├── S31209Test.php
├── S31210Test.php
├── S31211Test.php
├── S31212Test.php
├── S31213Test.php
├── S31214Test.php
├── S31215Test.php
├── S31216Test.php
├── S31217Test.php
├── S31218Test.php
├── S31219Test.php
├── S32010Test.php
├── S33010Test.php
├── S33020Test.php
├── S33030Test.php
├── S33040Test.php
├── S33050Test.php
├── S33060Test.php
├── S33070Test.php
├── S33080Test.php
├── S33090Test.php
├── S33100Test.php
├── S33110Test.php
├── S33120Test.php
├── S33130Test.php
├── S33140Test.php
├── S33150Test.php
└── S34010Test.php
├── RequestTest.php
├── ResponseTest.php
├── StreamParserTest.php
├── URITest.php
└── fixtures
├── misc
├── gh-21.yaml
├── rfc3327
│ ├── 5.5.1_example-of-mechanism-in-register-transaction.yaml
│ └── 5.5.2_example-of-mechanism-in-invite-transaction.yaml
├── rfc3515
│ ├── 4.1_prototypical-refer-callflow.yaml
│ └── 4.2_multiple-refers-in-a-dialog.yaml
├── rfc3665
│ ├── 2.01_sip-client-new-registration.yaml
│ ├── 2.02_update-of-contact-list.yaml
│ ├── 2.03_request-for-current-contact-list.yaml
│ ├── 2.04_cancellation-of-registration.yaml
│ ├── 2.05_unsuccessful-registration.yaml
│ ├── 3.01_successful-session-establishment.yaml
│ ├── 3.02_session-establishment-through-two-proxies.yaml
│ ├── 3.03_session-with-multiple-proxy-authentication.yaml
│ ├── 3.04_successful-session-with-proxy-failure.yaml
│ ├── 3.05_session-through-a-sip-alg.yaml
│ ├── 3.06_session-via-redirect-and-proxy-servers-with-sdp-in-ack.yaml
│ ├── 3.07_session-with-re-invite-ip-address-change.yaml
│ ├── 3.08_unsuccessful-no-answer.yaml
│ ├── 3.09_unsuccessful-busy.orig
│ ├── 3.09_unsuccessful-busy.yaml
│ ├── 3.10_unsuccessful-no-response-from-user-agent.yaml
│ └── 3.11_unsuccessful-temporarily-unavailable.yaml
├── rfc4916
│ ├── 5.1_sending-connected-identity-after-answering-a-call.yaml
│ └── 5.2_sending-revised-connected-identity-during-a-call.yaml
└── rfc5626
│ ├── 3.2_single-registrar-and-ua.yaml
│ ├── 9.1_subscription-to-configuration-package.yaml
│ ├── 9.2_registration.yaml
│ ├── 9.3_incoming_call_and_proxy_crash.yaml
│ ├── 9.4_re-registration.yaml
│ └── 9.5_outgoing_call.yaml
├── rfc4475
├── badaspec.dat
├── badbranch.dat
├── baddate.dat
├── baddn.dat
├── badinv01.dat
├── badvers.dat
├── bcast.dat
├── bext01.dat
├── bigcode.dat
├── clerr.dat
├── cparam01.dat
├── cparam02.dat
├── dblreq.dat
├── esc01.dat
├── esc02.dat
├── escnull.dat
├── escruri.dat
├── insuf.dat
├── intmeth.dat
├── inv2543.dat
├── invut.dat
├── longreq.dat
├── ltgtruri.dat
├── lwsdisp.dat
├── lwsruri.dat
├── lwsstart.dat
├── mcl01.dat
├── mismatch01.dat
├── mismatch02.dat
├── mpart01.dat
├── multi01.dat
├── ncl.dat
├── noreason.dat
├── novelsc.dat
├── quotbal.dat
├── regaut01.dat
├── regbadct.dat
├── regescrt.dat
├── scalar02.dat
├── scalarlg.dat
├── sdp01.dat
├── semiuri.dat
├── test.dat
├── transports.dat
├── trws.dat
├── unkscm.dat
├── unksm2.dat
├── unreason.dat
├── wsinv.dat
└── zeromf.dat
└── stream
├── generic.txt
└── lioneagle-sipparser.txt
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "composer"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | StaticAnalysis:
9 | name: StaticAnalysis (PHP ${{ matrix.php }} on ${{ matrix.os }})
10 | runs-on: ${{ matrix.os }}
11 | strategy:
12 | matrix:
13 | os:
14 | - ubuntu-20.04
15 | php:
16 | - 7.4
17 | - 8.0
18 | - 8.1
19 | - 8.2
20 | steps:
21 | - uses: actions/checkout@v2
22 | - uses: shivammathur/setup-php@v2
23 | with:
24 | php-version: ${{ matrix.php }}
25 | - run: composer install
26 | - run: composer phpstan
27 | - run: composer psalm -- --output-format=github --shepherd
28 |
29 | Coverage:
30 | name: Coverage (PHP ${{ matrix.php }} on ${{ matrix.os }})
31 | runs-on: ${{ matrix.os }}
32 | strategy:
33 | matrix:
34 | os:
35 | - ubuntu-20.04
36 | php:
37 | - 7.4
38 | - 8.0
39 | - 8.1
40 | - 8.2
41 | steps:
42 | - uses: actions/checkout@v2
43 | - uses: shivammathur/setup-php@v2
44 | with:
45 | php-version: ${{ matrix.php }}
46 | - run: composer install
47 | - uses: paambaati/codeclimate-action@v4.0.0
48 | env:
49 | CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
50 | with:
51 | coverageCommand: php -d memory_limit=-1 ./vendor/bin/phpunit -c ./etc/phpunit.xml.dist --coverage-clover clover.xml
52 | coverageLocations: clover.xml:clover
53 | debug: true
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .editorconfig
2 | .phpunit.result.cache
3 | reports
4 | vendor
5 | composer.lock
6 | tests/fixtures/protos
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | env:
2 | global:
3 | - GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi)
4 |
5 | language: php
6 |
7 | php:
8 | - '7.4'
9 | - nightly
10 |
11 | before_script:
12 | - composer install
13 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
14 | - chmod +x ./cc-test-reporter
15 | - ./cc-test-reporter before-build
16 | - echo "xdebug.mode=coverage" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
17 |
18 | script:
19 | - php -d memory_limit=-1 ./vendor/bin/phpstan analyse -c ./etc/phpstan.neon -n -vvv --ansi --level=max src
20 | - php -d memory_limit=-1 ./vendor/bin/psalm --config=./etc/psalm.xml --show-info=true
21 | - php -d memory_limit=-1 ./vendor/bin/phpunit -c ./etc/phpunit.xml.dist --coverage-text --coverage-clover build/logs/clover.xml
22 | - if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Ciprian Dosoftei
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rtckit/sip",
3 | "description": "SIP protocol implementation written in PHP",
4 | "version": "0.7.1",
5 | "type": "library",
6 | "keywords": [
7 | "sip",
8 | "session initiation protocol",
9 | "voip",
10 | "rfc 3261",
11 | "telephony",
12 | "telco"
13 | ],
14 | "homepage": "https://github.com/rtckit/php-sip",
15 | "license": "MIT",
16 | "authors": [
17 | {
18 | "name": "Ciprian Dosoftei"
19 | }
20 | ],
21 | "support": {
22 | "email": "hello@rtckit.io",
23 | "issues": "https://github.com/rtckit/php-sip/issues"
24 | },
25 | "require": {
26 | "php": ">=7.4.0",
27 | "ext-ctype": "*"
28 | },
29 | "require-dev": {
30 | "phpstan/phpstan": "^1.10",
31 | "phpunit/phpunit": "^9.5",
32 | "symfony/yaml": "^5.3",
33 | "vimeo/psalm": "^5.11"
34 | },
35 | "suggest": {
36 | "ext-hash": "Enables RFC 8760 authentication via SHA(-512)-256 hashing"
37 | },
38 | "autoload": {
39 | "psr-4": {
40 | "RTCKit\\SIP\\": "src/"
41 | }
42 | },
43 | "autoload-dev": {
44 | "psr-4": {
45 | "RTCKit\\SIP\\": "tests/"
46 | }
47 | },
48 | "config": {
49 | "allow-plugins": false,
50 | "platform": {
51 | "php": "7.4"
52 | }
53 | },
54 | "scripts": {
55 | "phpstan": "php -d memory_limit=-1 ./vendor/bin/phpstan analyse -c ./etc/phpstan.neon -n -vvv --ansi --level=max src",
56 | "psalm": "php -d memory_limit=-1 ./vendor/bin/psalm --config=./etc/psalm.xml",
57 | "test": "php -d memory_limit=-1 ./vendor/bin/phpunit -c ./etc/phpunit.xml.dist --debug",
58 | "coverage": "php -d extension=pcov -d memory_limit=-1 ./vendor/bin/phpunit -c ./etc/phpunit.xml.dist --coverage-text --coverage-html=reports/coverage",
59 | "profile": "php -d memory_limit=-1 ./examples/99-crude-benchmark.php"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/etc/phpstan.neon:
--------------------------------------------------------------------------------
1 | includes:
2 | - ../vendor/phpstan/phpstan/conf/bleedingEdge.neon
3 |
--------------------------------------------------------------------------------
/etc/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 | ../tests/
12 |
13 |
14 |
15 |
16 | ../src/
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/etc/psalm.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/01-parse-request.php:
--------------------------------------------------------------------------------
1 | ;tag=SFJbQ2oWh' . "\r\n" .
19 | 'To: sip:buzz@192.168.0.1' . "\r\n" .
20 | 'CSeq: 20 REGISTER' . "\r\n" .
21 | 'Call-ID: ob0EYyuyC0' . "\r\n" .
22 | 'Max-Forwards: 70' . "\r\n" .
23 | 'Supported: replaces, outbound' . "\r\n" .
24 | 'Accept: application/sdp' . "\r\n" .
25 | 'Accept: text/plain' . "\r\n" .
26 | 'Accept: application/vnd.gsma.rcs-ft-http+xml' . "\r\n" .
27 | 'Contact: ' . "\r\n" .
28 | ' ;q=0.7; expires=3600' . "\r\n" .
29 | ' ;+sip.instance=""' . "\r\n" .
30 | 'Contact: ;reg-id=1;expires=3600' . "\r\n" .
31 | ' ;+sip.instance=""' . "\r\n" .
32 | 'Contact: ;reg-id=2;expires=3600' . "\r\n" .
33 | ' ;+sip.instance=""' . "\r\n" .
34 | 'Expires: 3600' . "\r\n" .
35 | 'User-Agent: MyDeskPhone/1.0.0' . "\r\n" .
36 | "\r\n";
37 |
38 | $request = Message::parse($text);
39 |
40 | printf("Message type: %s" . PHP_EOL, (get_class($request) === Request::class) ? 'SIP Request' : 'BOGUS!!!');
41 | printf("Protocol version: %s" . PHP_EOL, $request->version);
42 | printf("Request method: %s" . PHP_EOL, $request->method);
43 | printf("Request URI scheme: %s" . PHP_EOL, $request->uri->scheme);
44 | printf("Request URI host: %s" . PHP_EOL, $request->uri->host);
45 | printf("Via: %s" . PHP_EOL, $request->via->values[0]->host);
46 | printf("Via branch: %s" . PHP_EOL, $request->via->values[0]->branch);
47 | printf("From scheme: %s" . PHP_EOL, $request->from->uri->scheme);
48 | printf("From user: %s" . PHP_EOL, $request->from->uri->user);
49 | printf("From host: %s" . PHP_EOL, $request->from->uri->host);
50 | printf("From tag: %s" . PHP_EOL, $request->from->tag);
51 | printf("To scheme: %s" . PHP_EOL, $request->to->uri->scheme);
52 | printf("To user: %s" . PHP_EOL, $request->to->uri->user);
53 | printf("To host: %s" . PHP_EOL, $request->to->uri->host);
54 | printf("CSeq: %s" . PHP_EOL, $request->cSeq->sequence);
55 | printf("Call ID: %s" . PHP_EOL, $request->callId->value);
56 | printf("Max forwards: %d" . PHP_EOL, $request->maxForwards->value);
57 |
58 | printf("Supported: ");
59 |
60 | foreach ($request->supported->values as $key => $val) {
61 | if ($key) {
62 | printf(" ");
63 | }
64 |
65 | printf("- %s" . PHP_EOL, $val);
66 | }
67 |
68 | printf("Accept: ");
69 |
70 | foreach ($request->accept->values as $key => $val) {
71 | if ($key) {
72 | printf(" ");
73 | }
74 |
75 | printf("- %s" . PHP_EOL, $val->value);
76 | }
77 |
78 | printf("Contact scheme: %s" . PHP_EOL, $request->contact->values[0]->uri->scheme);
79 | printf("Contact user: %s" . PHP_EOL, $request->contact->values[0]->uri->user);
80 | printf("Contact host: %s" . PHP_EOL, $request->contact->values[0]->uri->host);
81 | printf("Contact transport: %s" . PHP_EOL, $request->contact->values[0]->uri->transport);
82 | printf("Contact q-value: %s" . PHP_EOL, $request->contact->values[0]->q);
83 | printf("Contact expires: %s" . PHP_EOL, $request->contact->values[0]->expires);
84 | printf("Contact instance: %s" . PHP_EOL, $request->contact->values[0]->params['+sip.instance']);
85 | printf("Expires: %s" . PHP_EOL, $request->expires->value);
86 | printf("User agent: %s" . PHP_EOL, $request->userAgent->values[0]);
87 |
--------------------------------------------------------------------------------
/examples/02-render-request.php:
--------------------------------------------------------------------------------
1 | version = 'SIP/2.0';
25 | $request->method = 'REGISTER';
26 | $request->uri = new URI;
27 | $request->uri->scheme = 'sip';
28 | $request->uri->host = '192.168.0.1';
29 |
30 | $request->via = new ViaHeader;
31 | $request->via->values[0] = new ViaValue;
32 | $request->via->values[0]->protocol = 'SIP';
33 | $request->via->values[0]->version = '2.0';
34 | $request->via->values[0]->transport = 'UDP';
35 | $request->via->values[0]->host = '192.168.0.2:5050';
36 | $request->via->values[0]->branch = 'z9hG4bK.eAV4o0nXr';
37 |
38 | $request->from = new NameAddrHeader;
39 | $request->from->uri = new URI;
40 | $request->from->uri->scheme = 'sip';
41 | $request->from->uri->user = 'buzz';
42 | $request->from->uri->host = '192.168.0.1';
43 | $request->from->tag = 'SFJbQ2oWh';
44 |
45 | $request->to = new NameAddrHeader;
46 | $request->to->uri = new URI;
47 | $request->to->uri->scheme = 'sip';
48 | $request->to->uri->user = 'buzz';
49 | $request->to->uri->host = '192.168.0.1';
50 |
51 | $request->cSeq = new CSeqHeader;
52 | $request->cSeq->sequence = 20;
53 | $request->cSeq->method = $request->method;
54 |
55 | $request->callId = new CallIdHeader;
56 | $request->callId->value = 'ob0EYyuyC0';
57 |
58 | $request->maxForwards = new ScalarHeader;
59 | $request->maxForwards->value = 70;
60 |
61 | $request->contact = new ContactHeader;
62 | $request->contact->values[0] = new ContactValue;
63 | $request->contact->values[0]->uri = new URI;
64 | $request->contact->values[0]->uri->scheme = 'sip';
65 | $request->contact->values[0]->uri->user = 'buzz';
66 | $request->contact->values[0]->uri->host = '192.168.0.2';
67 | $request->contact->values[0]->uri->port = 5050;
68 | $request->contact->values[0]->uri->transport = 'udp';
69 | $request->contact->values[0]->q = 0.7;
70 | $request->contact->values[0]->expires = 3600;
71 | $request->contact->values[0]->params['+sip.instance'] = '""';
72 |
73 | $request->userAgent = new Header;
74 | $request->userAgent->values[0] = 'MyDeskPhone/1.0.0';
75 |
76 | echo $request->render();
77 |
--------------------------------------------------------------------------------
/examples/03-parse-response.php:
--------------------------------------------------------------------------------
1 | ;tag=8734a29d0ba1b4b0a195a091c7233452-6e53' . "\r\n" .
19 | 'To: ;tag=8cQtUyH6N5N9K' . "\r\n" .
20 | 'Call-ID: 5a3202932ab4128f-23935' . "\r\n" .
21 | 'User-Agent: MyDeskPhone/1.0.0' . "\r\n" .
22 | 'CSeq: 10 OPTIONS' . "\r\n" .
23 | 'Contact: ' . "\r\n" .
24 | 'Accept: application/sdp' . "\r\n" .
25 | 'Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY' . "\r\n" .
26 | 'Supported: timer' . "\r\n" .
27 | 'Supported: path' . "\r\n" .
28 | 'Supported: replaces' . "\r\n" .
29 | 'Allow-Events: talk' . "\r\n" .
30 | 'Content-Length: 0' . "\r\n" .
31 | "\r\n";
32 |
33 | $response = Message::parse($text);
34 |
35 | printf("Message type: %s" . PHP_EOL, (get_class($response) === Response::class) ? 'SIP Response' : 'BOGUS!!!');
36 | printf("Protocol version: %s" . PHP_EOL, $response->version);
37 | printf("Response code: %s" . PHP_EOL, $response->code);
38 | printf("Response reason: %s" . PHP_EOL, $response->reason);
39 | printf("Via: %s" . PHP_EOL, $response->via->values[0]->host);
40 | printf("Via branch: %s" . PHP_EOL, $response->via->values[0]->branch);
41 | printf("From scheme: %s" . PHP_EOL, $response->from->uri->scheme);
42 | printf("From user: %s" . PHP_EOL, $response->from->uri->user);
43 | printf("From host: %s" . PHP_EOL, $response->from->uri->host);
44 | printf("From tag: %s" . PHP_EOL, $response->from->tag);
45 | printf("To scheme: %s" . PHP_EOL, $response->to->uri->scheme);
46 | printf("To host: %s" . PHP_EOL, $response->to->uri->host);
47 | printf("To tag: %s" . PHP_EOL, $response->to->tag);
48 | printf("Call ID: %s" . PHP_EOL, $response->callId->value);
49 | printf("User agent: %s" . PHP_EOL, $response->userAgent->values[0]);
50 | printf("CSeq: %s" . PHP_EOL, $response->cSeq->sequence);
51 | printf("Contact scheme: %s" . PHP_EOL, $response->contact->values[0]->uri->scheme);
52 | printf("Contact user: %s" . PHP_EOL, $response->contact->values[0]->uri->user);
53 | printf("Contact host: %s" . PHP_EOL, $response->contact->values[0]->uri->host);
54 | printf("Contact port: %s" . PHP_EOL, $response->contact->values[0]->uri->port);
55 | printf("Contact transport: %s" . PHP_EOL, $response->contact->values[0]->uri->transport);
56 |
57 | printf("Accept: ");
58 |
59 | foreach ($response->accept->values as $key => $val) {
60 | if ($key) {
61 | printf(" ");
62 | }
63 |
64 | printf("- %s" . PHP_EOL, $val->value);
65 | }
66 |
67 | printf("Allow: ");
68 |
69 | foreach ($response->allow->values as $key => $val) {
70 | if ($key) {
71 | printf(" ");
72 | }
73 |
74 | printf("- %s" . PHP_EOL, $val);
75 | }
76 |
77 | printf("Supported: ");
78 |
79 | foreach ($response->supported->values as $key => $val) {
80 | if ($key) {
81 | printf(" ");
82 | }
83 |
84 | printf("- %s" . PHP_EOL, $val);
85 | }
86 |
87 | printf("Allow events: ");
88 |
89 | foreach ($response->allowEvents->values as $key => $val) {
90 | if ($key) {
91 | printf(" ");
92 | }
93 |
94 | printf("- %s" . PHP_EOL, $val);
95 | }
96 |
97 | printf("Content length: %s" . PHP_EOL, $response->contentLength->value);
98 |
--------------------------------------------------------------------------------
/examples/04-render-response.php:
--------------------------------------------------------------------------------
1 | version = 'SIP/2.0';
25 | $response->code = 200;
26 |
27 | $response->via = new ViaHeader;
28 | $response->via->values[0] = new ViaValue;
29 | $response->via->values[0]->protocol = 'SIP';
30 | $response->via->values[0]->version = '2.0';
31 | $response->via->values[0]->transport = 'UDP';
32 | $response->via->values[0]->host = '192.168.0.2:5050';
33 | $response->via->values[0]->branch = 'z9hG4bK.eAV4o0nXr';
34 |
35 | $response->from = new NameAddrHeader;
36 | $response->from->uri = new URI;
37 | $response->from->uri->scheme = 'sip';
38 | $response->from->uri->user = 'buzz';
39 | $response->from->uri->host = '192.168.0.1';
40 | $response->from->tag = 'SFJbQ2oWh';
41 |
42 | $response->to = new NameAddrHeader;
43 | $response->to->uri = new URI;
44 | $response->to->uri->scheme = 'sip';
45 | $response->to->uri->user = 'buzz';
46 | $response->to->uri->host = '192.168.0.1';
47 | $response->to->tag = '8cQtUyH6N5N9K';
48 |
49 | $response->cSeq = new CSeqHeader;
50 | $response->cSeq->sequence = 20;
51 | $response->cSeq->method = 'REGISTER';
52 |
53 | $response->callId = new CallIdHeader;
54 | $response->callId->value = 'ob0EYyuyC0';
55 |
56 | $response->maxForwards = new ScalarHeader;
57 | $response->maxForwards->value = 70;
58 |
59 | $response->contact = new ContactHeader;
60 | $response->contact->values[0] = new ContactValue;
61 | $response->contact->values[0]->uri = new URI;
62 | $response->contact->values[0]->uri->scheme = 'sip';
63 | $response->contact->values[0]->uri->user = 'buzz';
64 | $response->contact->values[0]->uri->host = '192.168.0.2';
65 | $response->contact->values[0]->uri->port = 5050;
66 | $response->contact->values[0]->uri->transport = 'udp';
67 | $response->contact->values[0]->q = 0.7;
68 | $response->contact->values[0]->expires = 3600;
69 | $response->contact->values[0]->params['+sip.instance'] = '""';
70 |
71 | $response->userAgent = new Header;
72 | $response->userAgent->values[0] = 'MyDeskPhone/1.0.0';
73 |
74 | echo $response->render();
75 |
--------------------------------------------------------------------------------
/examples/05-stream-parse.php:
--------------------------------------------------------------------------------
1 | process($bytes, $messages) === StreamParser::SUCCESS) {
23 | foreach($messages as $message) {
24 | /* Consume messages ... */
25 | if ($message instanceof Request) {
26 | printf(
27 | "Request %10s %30s %30s %40s" . PHP_EOL,
28 | $message->method,
29 | substr($message->from->uri->user, 0, 30),
30 | substr($message->to->uri->user, 0, 30),
31 | substr($message->callId->value, 0, 40)
32 | );
33 | } else {
34 | printf(
35 | "Response %10s %30s %30s %40s %03d %s" . PHP_EOL,
36 | $message->cSeq->method,
37 | substr($message->from->uri->user, 0, 30),
38 | substr($message->to->uri->user, 0, 30),
39 | substr($message->callId->value, 0, 40),
40 | $message->code,
41 | $message->reason
42 | );
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Auth/Digest/ChallengeParams.php:
--------------------------------------------------------------------------------
1 | Quality of protection options */
21 | public array $qop = [];
22 | }
23 |
--------------------------------------------------------------------------------
/src/Auth/OpaqueParams.php:
--------------------------------------------------------------------------------
1 | verbatim = $input;
27 |
28 | return $params;
29 | }
30 |
31 | /**
32 | * Renders opaque authentication scheme parameters as string
33 | *
34 | * @return string Opaque authentication parameters
35 | */
36 | public function render(): string
37 | {
38 | return $this->verbatim;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Auth/ParamsInterface.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
29 | }
30 |
31 | /**
32 | * Retrieve's exception's stub, if any
33 | *
34 | * @return ?Message Partial message
35 | */
36 | public function getStub(): ?Message
37 | {
38 | return $this->stub;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Header/AbstractAuthHeader.php:
--------------------------------------------------------------------------------
1 | Authentication/Authorization value(s) */
23 | public array $values = [];
24 |
25 | final public function __construct() {}
26 |
27 | /**
28 | * Authentication/Authorization field value parser
29 | *
30 | * @param list $hbody Header body
31 | * @throws InvalidHeaderLineException
32 | * @throws InvalidHeaderParameterException
33 | * @return AbstractAuthHeader
34 | */
35 | public static function parse(array $hbody): AbstractAuthHeader
36 | {
37 | $ret = new static;
38 | $challenge = static::class === AuthenticateHeader::class;
39 |
40 | foreach ($hbody as $hline) {
41 | $hparts = explode(' ', trim($hline), 2);
42 |
43 | if (count($hparts) !== 2) {
44 | throw new InvalidHeaderLineException('Invalid Auth header, missing scheme', Response::BAD_REQUEST);
45 | }
46 |
47 | $val = new AuthValue;
48 | $val->scheme = strtolower($hparts[0]);
49 |
50 | $params = ltrim($hparts[1]);
51 |
52 | switch ($val->scheme) {
53 | case DigestChallengeParams::SCHEME_NAME:
54 | if ($challenge) {
55 | $val->params = DigestChallengeParams::parse($params);
56 | } else {
57 | $val->params = DigestResponseParams::parse($params);
58 | }
59 | break;
60 |
61 | default:
62 | $val->params = OpaqueParams::parse($params);
63 | break;
64 | }
65 |
66 | $ret->values[] = $val;
67 | }
68 |
69 | return $ret;
70 | }
71 |
72 | /**
73 | * Authentication/Authorization header field value renderer
74 | *
75 | * @param string $hname Header field name
76 | * @throws InvalidHeaderValueException
77 | * @return string
78 | */
79 | public function render(string $hname): string
80 | {
81 | $ret = '';
82 |
83 | foreach ($this->values as $key => $value) {
84 | if (!isset($value->scheme, $value->params)) {
85 | throw new InvalidHeaderValueException('Malformed auth header, missing scheme and/or parameters');
86 | }
87 |
88 | $ret .= "{$hname}: {$value->scheme} " . $value->params->render() . "\r\n";
89 | }
90 |
91 | return $ret;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Header/AuthValue.php:
--------------------------------------------------------------------------------
1 | $hbody Header body
32 | * @throws InvalidDuplicateHeaderException
33 | * @throws InvalidHeaderLineException
34 | * @throws InvalidScalarValueException
35 | * @return CSeqHeader
36 | */
37 | public static function parse(array $hbody): CSeqHeader
38 | {
39 | if (isset($hbody[1])) {
40 | throw new InvalidDuplicateHeaderException('Cannot have more than one CSeq header', Response::BAD_REQUEST);
41 | }
42 |
43 | $cseq = trim($hbody[0]);
44 | $delimPos = strpos($cseq, ' ');
45 |
46 | if ($delimPos === false) {
47 | throw new InvalidHeaderLineException('Invalid CSeq header', Response::BAD_REQUEST);
48 | }
49 |
50 | $ret = new static;
51 | $ret->sequence = (int) substr($cseq, 0, $delimPos);
52 |
53 | if (($ret->sequence < 0) || ($ret->sequence > ScalarHeader::MAX_VALUE)) {
54 | throw new InvalidScalarValueException('CSeq sequence number out of bounds', Response::BAD_REQUEST);
55 | }
56 |
57 | $ret->method = ltrim(substr($cseq, $delimPos));
58 |
59 | return $ret;
60 | }
61 |
62 | /**
63 | * CSeq header value renderer
64 | *
65 | * @param string $hname Header field name
66 | * @throws InvalidHeaderValueException
67 | * @return string
68 | */
69 | public function render(string $hname): string
70 | {
71 | if (!isset($this->sequence, $this->method[0])) {
72 | throw new InvalidHeaderValueException('Missing Sequence/Method for CSeq header field value');
73 | }
74 |
75 | return "{$hname}: {$this->sequence} {$this->method}\r\n";
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Header/CallIdHeader.php:
--------------------------------------------------------------------------------
1 | $hbody Header body
27 | * @throws InvalidDuplicateHeaderException
28 | * @return CallIdHeader
29 | */
30 | public static function parse(array $hbody): CallIdHeader
31 | {
32 | if (isset($hbody[1])) {
33 | throw new InvalidDuplicateHeaderException('Cannot have more than one Call-ID header', Response::BAD_REQUEST);
34 | }
35 |
36 | $ret = new static;
37 | $ret->value = trim($hbody[0]);
38 |
39 | return $ret;
40 | }
41 |
42 | /**
43 | * Call-ID header value renderer
44 | *
45 | * @param string $hname Header field name
46 | * @throws InvalidHeaderValueException
47 | * @return string
48 | */
49 | public function render(string $hname): string
50 | {
51 | if (!isset($this->value[0])) {
52 | throw new InvalidHeaderValueException('Missing Call-ID header value');
53 | }
54 |
55 | return "{$hname}: {$this->value}\r\n";
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Header/ContactValue.php:
--------------------------------------------------------------------------------
1 | Additional/extension parameters */
29 | public array $params = [];
30 | }
31 |
--------------------------------------------------------------------------------
/src/Header/FromHeader.php:
--------------------------------------------------------------------------------
1 | $hbody Header body
21 | * @throws InvalidHeaderParameterException
22 | * @return NameAddrHeader
23 | */
24 | public static function parse(array $hbody): NameAddrHeader
25 | {
26 | $ret = parent::parse($hbody);
27 |
28 | if (!isset($ret->tag[0])) {
29 | throw new InvalidHeaderParameterException('Missing/empty tag parameter in From header field value', Response::BAD_REQUEST);
30 | }
31 |
32 | return $ret;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Header/Header.php:
--------------------------------------------------------------------------------
1 | Generic header field values */
15 | public array $values = [];
16 |
17 | final public function __construct() {}
18 |
19 | /**
20 | * Generic header value parser
21 | *
22 | * @param list $hbody Header body
23 | * @return Header
24 | */
25 | public static function parse(array $hbody): Header
26 | {
27 | $ret = new static;
28 |
29 | foreach ($hbody as $hline) {
30 | $ret->values[] = trim($hline);
31 | }
32 |
33 | return $ret;
34 | }
35 |
36 | /**
37 | * Generic header value renderer
38 | *
39 | * @param string $hname Header field name
40 | * @return string
41 | */
42 | public function render(string $hname): string
43 | {
44 | $ret = '';
45 |
46 | foreach ($this->values as $value) {
47 | $ret .= "{$hname}: {$value}\r\n";
48 | }
49 |
50 | return $ret;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Header/MaxForwardsHeader.php:
--------------------------------------------------------------------------------
1 | Header field values */
15 | public array $values = [];
16 |
17 | final public function __construct() {}
18 |
19 | /**
20 | * Multpiple value header parser (no parameters)
21 | *
22 | * @param list $hbody Header body
23 | * @return MultiValueHeader
24 | */
25 | public static function parse(array $hbody): MultiValueHeader
26 | {
27 | $ret = new static;
28 |
29 | foreach ($hbody as $hline) {
30 | $hvalues = explode(',', $hline);
31 |
32 | foreach ($hvalues as $hvalue) {
33 | $ret->values[] = trim($hvalue);
34 | }
35 | }
36 |
37 | return $ret;
38 | }
39 |
40 | /**
41 | * Multiple value header renderer
42 | *
43 | * @param string $hname Header field name
44 | * @return string
45 | */
46 | public function render(string $hname): string
47 | {
48 | return "{$hname}: " . implode(', ', $this->values) . "\r\n";
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Header/MultiValueWithParamsHeader.php:
--------------------------------------------------------------------------------
1 | Header value(s) */
20 | public array $values = [];
21 |
22 | final public function __construct() {}
23 |
24 | /**
25 | * Multiple value header parser, with optional parameters
26 | *
27 | * @param list $hbody Header body
28 | * @throws InvalidHeaderLineException
29 | * @throws InvalidHeaderParameterException
30 | * @return MultiValueWithParamsHeader
31 | */
32 | public static function parse(array $hbody): MultiValueWithParamsHeader
33 | {
34 | $ret = new static;
35 |
36 | foreach ($hbody as $hline) {
37 | $hvalues = explode(',', $hline);
38 |
39 | foreach ($hvalues as $hvalue) {
40 | $tok = strtok(trim($hvalue), ';');
41 |
42 | if ($tok === false) {
43 | throw new InvalidHeaderLineException('Empty header value', Response::BAD_REQUEST);
44 | }
45 |
46 | $val = new ValueWithParams;
47 | $val->value = $tok;
48 |
49 | while (($tok = strtok(';')) !== false) {
50 | $p = explode('=', $tok);
51 | $p[0] = trim($p[0]);
52 |
53 | if (!isset($p[0][0])) {
54 | throw new InvalidHeaderParameterException('Empty header parameters', Response::BAD_REQUEST);
55 | }
56 |
57 | $val->params[$p[0]] = isset($p[1]) ? trim($p[1]) : '';
58 | }
59 |
60 | $ret->values[] = $val;
61 | }
62 | }
63 |
64 | return $ret;
65 | }
66 |
67 | /**
68 | * Multiple value header renderer, with optional parameters
69 | *
70 | * @param string $hname Header field name
71 | * @throws InvalidHeaderValueException
72 | * @return string
73 | */
74 | public function render(string $hname): string
75 | {
76 | $ret = "{$hname}: ";
77 |
78 | foreach ($this->values as $key => $value) {
79 | if (!isset($value->value)) {
80 | throw new InvalidHeaderValueException('Malformed header, missing value');
81 | }
82 |
83 | if ($key) {
84 | $ret .= ', ';
85 | }
86 |
87 | $ret .= $value->value;
88 |
89 | foreach ($value->params as $pk => $pv) {
90 | if (!isset($pk[0])) {
91 | throw new InvalidHeaderValueException('Malformed header, invalid parameter key for header ' . $hname);
92 | }
93 |
94 | $ret .= ';' . $pk . (!isset($pv[0]) ? '' : "={$pv}");
95 | }
96 | }
97 |
98 | $ret .= "\r\n";
99 |
100 | return $ret;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Header/RAckHeader.php:
--------------------------------------------------------------------------------
1 | $hbody Header body
37 | * @throws InvalidDuplicateHeaderException
38 | * @throws InvalidHeaderLineException
39 | * @throws InvalidScalarValueException
40 | * @return RAckHeader
41 | */
42 | public static function parse(array $hbody): RAckHeader
43 | {
44 | if (isset($hbody[1])) {
45 | throw new InvalidDuplicateHeaderException('Cannot have more than one RAck header', Response::BAD_REQUEST);
46 | }
47 |
48 | $rack = preg_split('/\s+/', trim($hbody[0]), -1, PREG_SPLIT_NO_EMPTY);
49 |
50 | if (!is_array($rack) || (count($rack) != 3)) {
51 | throw new InvalidHeaderLineException('Invalid RAck header', Response::BAD_REQUEST);
52 | }
53 |
54 | $ret = new static;
55 | $ret->rSequence = (int) $rack[0];
56 |
57 | if (($ret->rSequence < 0) || ($ret->rSequence > ScalarHeader::MAX_VALUE)) {
58 | throw new InvalidScalarValueException('RAck provisional sequence number out of bounds', Response::BAD_REQUEST);
59 | }
60 |
61 | $ret->cSequence = (int) $rack[1];
62 |
63 | if (($ret->cSequence < 0) || ($ret->cSequence > ScalarHeader::MAX_VALUE)) {
64 | throw new InvalidScalarValueException('RAck sequence number out of bounds', Response::BAD_REQUEST);
65 | }
66 |
67 | $ret->method = $rack[2];
68 |
69 | return $ret;
70 | }
71 |
72 | /**
73 | * RAck header value renderer
74 | *
75 | * @param string $hname Header field name
76 | * @throws InvalidHeaderValueException
77 | * @return string
78 | */
79 | public function render(string $hname): string
80 | {
81 | if (!isset($this->rSequence, $this->cSequence, $this->method[0])) {
82 | throw new InvalidHeaderValueException('Missing Sequence(s)/Method for RAck header field value');
83 | }
84 |
85 | return "{$hname}: {$this->rSequence} {$this->cSequence} {$this->method}\r\n";
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Header/ScalarHeader.php:
--------------------------------------------------------------------------------
1 | $hbody Header body
31 | * @throws InvalidDuplicateHeaderException
32 | * @throws InvalidScalarValueException
33 | * @return ScalarHeader
34 | */
35 | public static function parse(array $hbody): ScalarHeader
36 | {
37 | if (isset($hbody[1])) {
38 | throw new InvalidDuplicateHeaderException('Scalar header fields can only have one value', Response::BAD_REQUEST);
39 | }
40 |
41 | $val = (int) $hbody[0];
42 |
43 | if ($val > static::MAX_VALUE) {
44 | throw new InvalidScalarValueException('Scalar header field value out of bounds, > ' . static::MAX_VALUE, Response::BAD_REQUEST);
45 | }
46 |
47 | if ($val < 0) {
48 | throw new InvalidScalarValueException('Scalar header field value out of bounds (negative)', Response::BAD_REQUEST);
49 | }
50 |
51 | $ret = new static;
52 | $ret->value = $val;
53 |
54 | return $ret;
55 | }
56 |
57 | /**
58 | * Scalar header value renderer
59 | *
60 | * @param string $hname Header field name
61 | * @throws InvalidHeaderValueException
62 | * @return string
63 | */
64 | public function render(string $hname): string
65 | {
66 | if (!isset($this->value)) {
67 | throw new InvalidHeaderValueException('Missing scalar header value');
68 | }
69 |
70 | return "{$hname}: {$this->value}\r\n";
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Header/SingleValueWithParamsHeader.php:
--------------------------------------------------------------------------------
1 | Parameters */
24 | public array $params = [];
25 |
26 | final public function __construct() {}
27 |
28 | /**
29 | * Single value header field parser, with parameters
30 | *
31 | * @param list $hbody Header body
32 | * @throws InvalidDuplicateHeaderException
33 | * @throws InvalidHeaderLineException
34 | * @throws InvalidHeaderParameterException
35 | * @return SingleValueWithParamsHeader
36 | */
37 | public static function parse(array $hbody): SingleValueWithParamsHeader
38 | {
39 | if (isset($hbody[1])) {
40 | throw new InvalidDuplicateHeaderException('Cannot have multiple single value headers', Response::BAD_REQUEST);
41 | }
42 |
43 | $tok = strtok(trim($hbody[0]), ';');
44 |
45 | if ($tok === false) {
46 | throw new InvalidHeaderLineException('Empty header value', Response::BAD_REQUEST);
47 | }
48 |
49 | $ret = new static;
50 | $ret->value = $tok;
51 |
52 | while (($tok = strtok(';')) !== false) {
53 | $p = explode('=', $tok);
54 | $p[0] = trim($p[0]);
55 |
56 | if (!isset($p[0][0])) {
57 | throw new InvalidHeaderParameterException('Empty header parameters', Response::BAD_REQUEST);
58 | }
59 |
60 | $ret->params[$p[0]] = isset($p[1]) ? trim($p[1]) : '';
61 | }
62 |
63 | return $ret;
64 | }
65 |
66 | /**
67 | * Single value header renderer, with optional parameters
68 | *
69 | * @param string $hname Header field name
70 | * @throws InvalidHeaderValueException
71 | * @return string
72 | */
73 | public function render(string $hname): string
74 | {
75 | if (!isset($this->value[0])) {
76 | throw new InvalidHeaderValueException('Missing header field value for header: ' . $hname);
77 | }
78 |
79 | $ret = "{$hname}: {$this->value}";
80 |
81 | foreach ($this->params as $pk => $pv) {
82 | if (!isset($pk[0]) && !is_numeric($pk)) {
83 | throw new InvalidHeaderValueException('Malformed header, invalid parameter key for header ' . $hname);
84 | }
85 |
86 | $ret .= ';' . $pk . (!isset($pv[0]) ? '' : "={$pv}");
87 | }
88 |
89 | $ret .= "\r\n";
90 |
91 | return $ret;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Header/ValueWithParams.php:
--------------------------------------------------------------------------------
1 | Parameters */
18 | public array $params = [];
19 | }
20 |
--------------------------------------------------------------------------------
/src/Header/ViaValue.php:
--------------------------------------------------------------------------------
1 | Additional parameters */
36 | public array $params = [];
37 | }
38 |
--------------------------------------------------------------------------------
/src/Request.php:
--------------------------------------------------------------------------------
1 | request URIs', Response::BAD_REQUEST);
47 | }
48 |
49 | if ($rqstLine[2] !== Message::SIP_VERSION) {
50 | throw new InvalidProtocolVersionException('Unsupported SIP version: ' . $rqstLine[2], Response::VERSION_NOT_SUPPORTED);
51 | }
52 |
53 | $this->version = $rqstLine[2];
54 | $this->method = $rqstLine[0];
55 | $this->uri = URI::parse($rqstLine[1]);
56 |
57 | if (count($this->uri->headers)) {
58 | /*
59 | * https://datatracker.ietf.org/doc/html/rfc3261#page-152
60 | *
61 | * We interpret this that, as a UAS, we should ignore any headers in Request-URIs.
62 | *
63 | * Also, relevant to RFC 4475 3.1.2.11:
64 | * https://datatracker.ietf.org/doc/html/rfc4475#section-3.1.2.11
65 | */
66 | $this->uri->headers = [];
67 | }
68 | }
69 |
70 | /**
71 | * SIP Response Renderer
72 | *
73 | * @param bool $compact Whether to output compact headers or not
74 | * @throws InvalidRequestMethodException
75 | * @throws InvalidRequestURIException
76 | * @return string SIP response as text
77 | */
78 | public function render(bool $compact = false): string
79 | {
80 | if (!isset($this->method[0])) {
81 | throw new InvalidRequestMethodException('Missing request method');
82 | }
83 |
84 | if (!isset($this->uri, $this->uri->scheme, $this->uri->host)) {
85 | throw new InvalidRequestURIException('Missing/invalid request URI');
86 | }
87 |
88 | if (count($this->uri->headers)) {
89 | /*
90 | * https://datatracker.ietf.org/doc/html/rfc3261#page-152
91 | *
92 | * We interpret this that, as a UAC, we should never issue headers in Request-URIs.
93 | */
94 | throw new InvalidRequestURIException('Headers present in request URI');
95 | }
96 |
97 | $uriStr = $this->uri->render();
98 | $this->version ??= Message::SIP_VERSION;
99 | $this->body ??= '';
100 | $headers = $this->renderHeaders($compact);
101 |
102 | return "{$this->method} {$uriStr} {$this->version}\r\n{$headers}\r\n{$this->body}";
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/StreamParser.php:
--------------------------------------------------------------------------------
1 | $messages Resulting messages, if any
31 | * @psalm-suppress ReferenceConstraintViolation Doesn't make a lot of sense here
32 | * @return int Execution status
33 | */
34 | public function process(string $chunk, ?array &$messages): int
35 | {
36 | if (!isset($this->buffer[0])) {
37 | $this->buffer = ltrim($chunk);
38 |
39 | if (!isset($this->buffer[0])) {
40 | /* Nothing to process! */
41 | return self::READY;
42 | }
43 | } else {
44 | $this->buffer .= $chunk;
45 | }
46 |
47 | $status = self::READY;
48 | $messages = [];
49 |
50 | do {
51 | if (!isset($this->message)) {
52 | /* We're waiting for new messages */
53 | $blocks = explode("\r\n\r\n", $this->buffer, 2);
54 |
55 | if (count($blocks) === 1) {
56 | /* We don't have a whole message just yet */
57 | $status = self::WAIT_MESSAGE;
58 |
59 | break;
60 | }
61 |
62 | assert(count($blocks) === 2);
63 |
64 | $this->message = Message::parse($this->buffer, true);
65 | $this->buffer = $blocks[1];
66 | } else {
67 | /* We are waiting for the remainder of the body of the current message */
68 | }
69 |
70 | $bodyLength = strlen($this->buffer);
71 |
72 | if (isset($this->message->contentLength)) {
73 | if ($bodyLength < $this->message->contentLength->value) {
74 | /* We need to wait for more body bytes */
75 | $status = self::WAIT_BODY;
76 |
77 | break;
78 | } else if ($bodyLength > $this->message->contentLength->value) {
79 | /* Move the remainder of bytes into the buffer and save the body */
80 | $this->message->body = substr($this->buffer, 0, $this->message->contentLength->value);
81 | $this->buffer = ltrim(substr($this->buffer, $this->message->contentLength->value));
82 | } else {
83 | /* We're all set! */
84 | $this->message->body = $this->buffer;
85 | $this->buffer = '';
86 | }
87 | } else {
88 | $this->message->body = '';
89 | }
90 |
91 | $messages[] = $this->message;
92 |
93 | unset($this->message);
94 |
95 | $status = self::SUCCESS;
96 | } while (true);
97 |
98 | return (isset($messages[0]))
99 | ? self::SUCCESS
100 | : $status;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/tests/Header/AuthorizationHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($auth);
26 | $this->assertInstanceOf(AuthorizationHeader::class, $auth);
27 | $this->assertCount(2, $auth->values);
28 | $this->assertEquals('digest', $auth->values[0]->scheme);
29 | $this->assertEquals('sip.domain.net', $auth->values[0]->params->realm);
30 | $this->assertEquals('xPgHm7ito95w8je2FGvPS-', $auth->values[0]->params->nonce);
31 | $this->assertEquals('jdudlKi/EjqLMlSgUFIFyQ', $auth->values[0]->params->cnonce);
32 | $this->assertEquals('MD5', $auth->values[0]->params->algorithm);
33 | $this->assertEquals('sip:sip.domain.net:5566;transport=udp', $auth->values[0]->params->uri);
34 | $this->assertEquals('d1ffd656b679aa3a0ace1c648b36ab7d', $auth->values[0]->params->response);
35 | $this->assertEquals('auth', $auth->values[0]->params->qop);
36 | $this->assertEquals('00000001', $auth->values[0]->params->nc);
37 |
38 | /* Basic authentication scheme has been obsoleted by RFC 3261, now it's handled as an opaque scheme */
39 | $this->assertEquals('basic', $auth->values[1]->scheme);
40 | $this->assertEquals('d1ffd656b679aa3a0ace1c648b36ab7d', $auth->values[1]->params->verbatim);
41 | }
42 |
43 | public function testShouldParseEnclosedCharacters()
44 | {
45 | $auth = AuthorizationHeader::parse([
46 | 'Digest username="QWxhZGRpbjpvcGVuIHNlc2FtZQ=="',
47 | 'Digest username="enclosed\"quotes\"test"',
48 | ]);
49 |
50 | $this->assertEquals('QWxhZGRpbjpvcGVuIHNlc2FtZQ==', $auth->values[0]->params->username);
51 | $this->assertEquals('enclosed"quotes"test', $auth->values[1]->params->username);
52 | }
53 |
54 | public function testShouldNotParseAlphaNcValues()
55 | {
56 | $this->expectException(InvalidHeaderParameterException::class);
57 | AuthorizationHeader::parse(['Digest nc=fortytwo']);
58 | }
59 |
60 | public function testShouldNotParseMixedNcValues()
61 | {
62 | $this->expectException(InvalidHeaderParameterException::class);
63 | AuthorizationHeader::parse(['Digest nc=O042']);
64 | }
65 |
66 | public function testShouldNotParseNonHexResponseValues()
67 | {
68 | $this->expectException(InvalidHeaderParameterException::class);
69 | AuthorizationHeader::parse(['Digest response="deadbeef_-~"']);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/Header/CSeqHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($cseq);
22 | $this->assertInstanceOf(CSeqHeader::class, $cseq);
23 | $this->assertEquals(7, $cseq->sequence);
24 | $this->assertEquals('METHOD', $cseq->method);
25 | }
26 |
27 | public function testShouldNotParseMultiValue()
28 | {
29 | $this->expectException(InvalidDuplicateHeaderException::class);
30 | CSeqHeader::parse([
31 | '7 METHOD',
32 | '9 INVITE',
33 | ]);
34 | }
35 |
36 | public function testShouldNotParseNondelimitedComponents()
37 | {
38 | $this->expectException(InvalidHeaderLineException::class);
39 | CSeqHeader::parse(['7METHOD']);
40 | }
41 |
42 | public function testShouldNotParseNegativeSequence()
43 | {
44 | $this->expectException(InvalidScalarValueException::class);
45 | CSeqHeader::parse(['-7 METHOD']);
46 | }
47 |
48 | public function testShouldNotParseOutOfBoundsSequence()
49 | {
50 | $this->expectException(InvalidScalarValueException::class);
51 | CSeqHeader::parse(['42949672950 METHOD']);
52 | }
53 |
54 | public function testShouldNotParseMissingMethod()
55 | {
56 | $this->expectException(InvalidHeaderLineException::class);
57 | CSeqHeader::parse(['7 ']);
58 | }
59 |
60 | public function testShouldRenderWellFormedValue()
61 | {
62 | $cseq = new CSeqHeader;
63 | $cseq->sequence = 7;
64 | $cseq->method = 'METHOD';
65 |
66 | $rendered = $cseq->render('CSeq');
67 |
68 | $this->assertNotNull($rendered);
69 | $this->assertIsString($rendered);
70 | $this->assertEquals("CSeq: 7 METHOD\r\n", $rendered);
71 | }
72 |
73 | public function testShouldNotRenderMissingSequence()
74 | {
75 | $cseq = new CSeqHeader;
76 | $cseq->method = 'METHOD';
77 |
78 | $this->expectException(InvalidHeaderValueException::class);
79 | $cseq->render('CSeq');
80 | }
81 |
82 | public function testShouldNotRenderMissingMethod()
83 | {
84 | $cseq = new CSeqHeader;
85 | $cseq->sequence = 7;
86 |
87 | $this->expectException(InvalidHeaderValueException::class);
88 | $cseq->render('CSeq');
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/Header/CallIdHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($callId);
20 | $this->assertInstanceOf(CallIdHeader::class, $callId);
21 | $this->assertEquals('65465496', $callId->value);
22 | }
23 |
24 | public function testShouldNotParseMultiValue()
25 | {
26 | $this->expectException(InvalidDuplicateHeaderException::class);
27 | CallIdHeader::parse([
28 | '78',
29 | '99',
30 | ]);
31 | }
32 |
33 | public function testShouldRenderWellFormedValue()
34 | {
35 | $callId = new CallIdHeader;
36 | $callId->value = '42';
37 |
38 | $rendered = $callId->render('Call-ID');
39 |
40 | $this->assertNotNull($rendered);
41 | $this->assertIsString($rendered);
42 | $this->assertEquals("Call-ID: 42\r\n", $rendered);
43 | }
44 |
45 | public function testShouldNotRenderMissingValue()
46 | {
47 | $callId = new CallIdHeader;
48 |
49 | $this->expectException(InvalidHeaderValueException::class);
50 | $callId->render('Call-ID');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Header/FromHeaderTest.php:
--------------------------------------------------------------------------------
1 | ;tag=4294967295;custom=parameter',
19 | ]);
20 |
21 | $this->assertNotNull($from);
22 | $this->assertInstanceOf(NameAddrHeader::class, $from);
23 | $this->assertEquals('Bob', $from->name);
24 | $this->assertEquals('sips:bob@biloxi.example.com', $from->uri->render());
25 | $this->assertEquals('4294967295', $from->tag);
26 | $this->assertEquals('parameter', $from->params['custom']);
27 | }
28 |
29 | public function testShouldNotParseMissingTagParameter()
30 | {
31 | $this->expectException(InvalidHeaderParameterException::class);
32 | FromHeader::parse(['Bob ']);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Header/HeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($header);
18 | $this->assertInstanceOf(Header::class, $header);
19 | $this->assertCount(1, $header->values);
20 | $this->assertEquals('Mysterious value', $header->values[0]);
21 | }
22 |
23 | public function testShouldRenderWellFormedValue()
24 | {
25 | $header = new Header;
26 | $header->values = [
27 | 'Something useful',
28 | 'Something else',
29 | ];
30 |
31 | $rendered = $header->render('X-Extra');
32 |
33 | $this->assertNotNull($rendered);
34 | $this->assertIsString($rendered);
35 | $this->assertEquals(
36 | 'X-Extra: Something useful' . "\r\n" .
37 | 'X-Extra: Something else' . "\r\n",
38 | $rendered
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Header/MultiValueHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($header);
18 | $this->assertInstanceOf(MultiValueHeader::class, $header);
19 | $this->assertCount(2, $header->values);
20 | $this->assertEquals('gzip', $header->values[0]);
21 | $this->assertEquals('compressed', $header->values[1]);
22 | }
23 |
24 | public function testShouldRenderWellFormedValue()
25 | {
26 | $header = new MultiValueHeader;
27 | $header->values = [
28 | 'compressed',
29 | 'gzip',
30 | ];
31 |
32 | $rendered = $header->render('Accept-Encoding');
33 |
34 | $this->assertNotNull($rendered);
35 | $this->assertIsString($rendered);
36 | $this->assertEquals("Accept-Encoding: compressed, gzip\r\n", $rendered);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/Header/MultiValueWithParamsHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($header);
22 | $this->assertInstanceOf(MultiValueWithParamsHeader::class, $header);
23 | $this->assertCount(2, $header->values);
24 | $this->assertEquals('text/plain', $header->values[0]->value);
25 | $this->assertEquals('utf-8', $header->values[0]->params['charset']);
26 | $this->assertEquals('application/sdp', $header->values[1]->value);
27 | $this->assertEquals('something', $header->values[1]->params['custom']);
28 | }
29 |
30 | public function testShouldNotParseMissingHeaderValue()
31 | {
32 | $this->expectException(InvalidHeaderLineException::class);
33 | MultiValueWithParamsHeader::parse([', application/sdp;custom=something']);
34 | }
35 |
36 | public function testShouldNotParseMissingHeaderParameterName()
37 | {
38 | $this->expectException(InvalidHeaderParameterException::class);
39 | MultiValueWithParamsHeader::parse(['text/plain;=utf-8, application/sdp;custom=something']);
40 | }
41 |
42 | public function testShouldRenderWellFormedValue()
43 | {
44 | $header = new MultiValueWithParamsHeader;
45 | $header->values[0] = new ValueWithParams;
46 | $header->values[0]->value = 'text/plain';
47 | $header->values[0]->params['charset'] = 'utf-8';
48 | $header->values[1] = new ValueWithParams;
49 | $header->values[1]->value = 'application/sdp';
50 | $header->values[1]->params['custom'] = 'something';
51 |
52 | $rendered = $header->render('Accept');
53 |
54 | $this->assertNotNull($rendered);
55 | $this->assertIsString($rendered);
56 | $this->assertEquals("Accept: text/plain;charset=utf-8, application/sdp;custom=something\r\n", $rendered);
57 | }
58 |
59 | public function testShouldNotRenderMissingHeaderValue()
60 | {
61 | $header = new MultiValueWithParamsHeader;
62 | $header->values[0] = new ValueWithParams;
63 |
64 | $this->expectException(InvalidHeaderValueException::class);
65 | $header->render('Accept');
66 | }
67 |
68 | public function testShouldNotRenderMissingHeaderParameterName()
69 | {
70 | $header = new MultiValueWithParamsHeader;
71 | $header->values[0] = new ValueWithParams;
72 | $header->values[0]->value = 'text/plain';
73 | $header->values[0]->params[''] = 'utf-8';
74 |
75 | $this->expectException(InvalidHeaderValueException::class);
76 | $header->render('Accept');
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/tests/Header/ScalarHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($scalar);
21 | $this->assertInstanceOf(ScalarHeader::class, $scalar);
22 | $this->assertEquals(65465496, $scalar->value);
23 | }
24 |
25 | public function testShouldNotParseMultiValue()
26 | {
27 | $this->expectException(InvalidDuplicateHeaderException::class);
28 | ScalarHeader::parse([
29 | '78',
30 | '99',
31 | ]);
32 | }
33 |
34 | public function testShouldNotParseNegativeValue()
35 | {
36 | $this->expectException(InvalidScalarValueException::class);
37 | ScalarHeader::parse(['-1969']);
38 | }
39 |
40 | public function testShouldNotParseOutOfBoundsValue()
41 | {
42 | $this->expectException(InvalidScalarValueException::class);
43 | ScalarHeader::parse(['42949672950']);
44 | }
45 |
46 | public function testShouldRenderWellFormedValue()
47 | {
48 | $scalar = new ScalarHeader;
49 | $scalar->value = 42;
50 |
51 | $rendered = $scalar->render('Max-Forwards');
52 |
53 | $this->assertNotNull($rendered);
54 | $this->assertIsString($rendered);
55 | $this->assertEquals("Max-Forwards: 42\r\n", $rendered);
56 | }
57 |
58 | public function testShouldNotRenderMissingValue()
59 | {
60 | $scalar = new ScalarHeader;
61 |
62 | $this->expectException(InvalidHeaderValueException::class);
63 | $scalar->render('Max-Forwards');
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/Header/SingleValueWithParamsHeaderTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($header);
22 | $this->assertInstanceOf(SingleValueWithParamsHeader::class, $header);
23 | $this->assertEquals('text/plain', $header->value);
24 | $this->assertEquals('utf-8', $header->params['charset']);
25 | $this->assertEquals('something', $header->params['custom']);
26 | }
27 |
28 | public function testShouldNotParseMissingValue()
29 | {
30 | $this->expectException(InvalidHeaderLineException::class);
31 | SingleValueWithParamsHeader::parse(['']);
32 | }
33 |
34 | public function testShouldNotParseMultiValue()
35 | {
36 | $this->expectException(InvalidDuplicateHeaderException::class);
37 | SingleValueWithParamsHeader::parse(['text/plain;charset=utf-8;custom=something', 'application/sdp']);
38 | }
39 |
40 | public function testShouldNotParseMissingHeaderParameterName()
41 | {
42 | $this->expectException(InvalidHeaderParameterException::class);
43 | SingleValueWithParamsHeader::parse(['text/plain;charset=utf-8;=something']);
44 | }
45 |
46 | public function testShouldRenderWellFormedValue()
47 | {
48 | $header = new SingleValueWithParamsHeader;
49 | $header->value = 'text/plain';
50 | $header->params['charset'] = 'utf-8';
51 | $header->params['custom'] = 'something';
52 |
53 | $rendered = $header->render('Content-Type');
54 |
55 | $this->assertNotNull($rendered);
56 | $this->assertIsString($rendered);
57 | $this->assertEquals("Content-Type: text/plain;charset=utf-8;custom=something\r\n", $rendered);
58 | }
59 |
60 | public function testShouldNotRenderMissingHeaderValue()
61 | {
62 | $header = new SingleValueWithParamsHeader;
63 |
64 | $this->expectException(InvalidHeaderValueException::class);
65 | $header->render('Accept');
66 | }
67 |
68 | public function testShouldNotRenderMissingHeaderParameterName()
69 | {
70 | $header = new SingleValueWithParamsHeader;
71 | $header->value = 'text/plain';
72 | $header->params[''] = 'utf-8';
73 |
74 | $this->expectException(InvalidHeaderValueException::class);
75 | $header->render('Accept');
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tests/MiscTest.php:
--------------------------------------------------------------------------------
1 | flows[$file] = Yaml::parse(file_get_contents($dir . '/' . $file));
39 | $this->flows[$file] = preg_replace('~\R~u', "\r\n", $this->flows[$file]);
40 | } catch (\Throwable $t) {
41 | echo $t->getMessage() . ' in flow ' . $file . "\n";
42 |
43 | throw $t;
44 | }
45 | }
46 | }
47 | }
48 |
49 | public function testMisc()
50 | {
51 | foreach ($this->flows as $name => $flow) {
52 | foreach ($flow as $i => $text) {
53 | try {
54 | $message = Message::parse($text);
55 | } catch (\Throwable $t) {
56 | echo $t->getMessage() . ' in flow ' . $name . "\n";
57 |
58 | throw $t;
59 | }
60 |
61 | /* Message could be parsed, no exceptions to be thrown */
62 | $this->assertInstanceOf(Message::class, $message);
63 |
64 | try {
65 | $reassembled = $message->render();
66 | } catch (\Throwable $t) {
67 | echo $t->getMessage() . ' in flow ' . $name . "\n";
68 |
69 | throw $t;
70 | }
71 |
72 | /* Resulting message can be rendered, no exceptions to be thrown */
73 | $this->assertIsString($reassembled);
74 |
75 | try {
76 | $reparsed = Message::parse($reassembled);
77 | } catch (\Throwable $t) {
78 | echo $t->getMessage() . ' in flow ' . $name . "\n";
79 |
80 | throw $t;
81 | }
82 |
83 | /* Reassembled message's message to be identical to the original message */
84 | $this->assertEquals($message, $reparsed, "In flow {$name}[{$i}]");
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/tests/RFC4475/RFC4475Case.php:
--------------------------------------------------------------------------------
1 | loadFixture('wsinv');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* unknown Request-URI parameter */
25 | $this->assertNotNull($msg->uri->params['unknownparam']);
26 |
27 | /* tag From/To header value parameters */
28 | $this->assertEquals("1918181833n", $msg->to->tag);
29 | $this->assertEquals("98asjd8", $msg->from->tag);
30 |
31 | /* escaped characters within quotes */
32 | $this->assertEquals("J Rosenberg \\\\\"", $msg->from->name);
33 | $this->assertEquals('Quoted string \\"\\"', $msg->contact->values[0]->name);
34 |
35 | /* an empty subject */
36 | $this->assertCount(0, $msg->subject->values);
37 |
38 | /* both comma separated and separately listed header field values */
39 | /* a mix of short and long form for the same header field name */
40 | $this->assertCount(3, $msg->via->values);
41 |
42 | $this->assertEquals('390skdjuw', $msg->via->values['0']->branch);
43 | $this->assertEquals('z9hG4bK9ikj8', $msg->via->values['1']->branch);
44 | $this->assertEquals('z9hG4bK30239', $msg->via->values['2']->branch);
45 |
46 | /* unknown header fields */
47 | $this->assertNotNull($msg->extraHeaders['newfangledheader']->values[0]);
48 | $this->assertNotNull($msg->extraHeaders['unknownheaderwithunusualvalue']->values[0]);
49 |
50 | /* an unknown header field with a value that would be syntactically invalid if it were defined in terms of generic-param */
51 | $this->assertEquals(';;,,;;,;', $msg->extraHeaders['unknownheaderwithunusualvalue']->values[0]);
52 |
53 | /* unknown parameters of a known header field */
54 | $this->assertEquals('newvalue', $msg->contact->values[0]->params['newparam']);
55 |
56 | /* a header parameter with no value */
57 | $this->assertEquals('', $msg->contact->values[0]->params['secondparam']);
58 |
59 | /* integer fields (Max-Forwards and CSeq) with leading zeros */
60 | $this->assertIsNumeric($msg->maxForwards->value);
61 | $this->assertEquals(68, $msg->maxForwards->value);
62 | $this->assertIsNumeric($msg->cSeq->sequence);
63 | $this->assertEquals(9, $msg->cSeq->sequence);
64 | $this->assertIsString($msg->cSeq->method);
65 | $this->assertEquals('INVITE', $msg->cSeq->method);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31102Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('intmeth');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* The Method contains non-alpha characters from token */
25 | $this->assertEquals('!interesting-Method0123456789_*+`.%indeed\'~', $msg->method);
26 |
27 | /* The Request-URI contains unusual, but legal, characters */
28 | $this->assertEquals('sip', $msg->uri->scheme);
29 | $this->assertEquals("1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*", $msg->uri->user);
30 | $this->assertEquals("&it+has=1,weird!*pas\$wo~d_too.(doesn't-it)", $msg->uri->password);
31 | $this->assertEquals('example.com', $msg->uri->host);
32 |
33 | /* A branch parameter contains all non-alphanum characters from token */
34 | $this->assertEquals('z9hG4bK-.!%66*_+`\'~', $msg->via->values[0]->branch);
35 |
36 | /* The To header field value's quoted string contains quoted-pair expansions, including a quoted NULL character */
37 | $this->assertEquals('BEL:\\' . "\x07" . ' NUL:\\' . "\x00" . ' DEL:\\' . "\x7f", $msg->to->name);
38 |
39 | /* The name part of name-addr in the From header field value contains
40 | multiple tokens (instead of a quoted string) with all non-alphanum
41 | characters from the token production rule. */
42 | $this->assertEquals('token1~` token2\'+_ token3*%!.-', $msg->from->name);
43 |
44 | /* That value also has an unknown header parameter whose name contains the non-alphanum
45 | token characters and whose value is a non-ascii range UTF-8 encoded string. */
46 | $this->assertNotNull($msg->from->params['fromParam\'\'~+*_!.-%']);
47 | $this->assertEquals(
48 | "\"\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9\"",
49 | $msg->from->params['fromParam\'\'~+*_!.-%']
50 | );
51 |
52 | /* The tag parameter on this value contains the non-alphanum token characters. */
53 | $this->assertEquals('_token~1\'+`*%!-.', $msg->from->tag);
54 |
55 | /* The Call-ID header field value contains the non-alphanum characters from word */
56 | $this->assertEquals('intmeth.word%ZK-!.*_+\'@word`~)(><:\\/"][?}{', $msg->callId->value);
57 |
58 | /* There is an unknown header field (matching extension-header) with
59 | non-alphanum token characters in its name and a UTF8-NONASCII value. */
60 | $this->assertEquals(
61 | "\xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB",
62 | $msg->extraHeaders['extensionheader-!.%*+_`\'~']->values[0]
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31103Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('esc01');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* The request-URI has sips:user@example.com embedded in its
25 | userpart. What that might mean to example.net is beyond the scope
26 | of this document. */
27 | $this->assertEquals('sip', $msg->uri->scheme);
28 | $this->assertEquals('sips:user@example.com', $msg->uri->user);
29 | $this->assertEquals('example.net', $msg->uri->host);
30 | $this->assertFalse(isset($msg->uri->password));
31 |
32 | /* The From and To URIs have escaped characters in their userparts. */
33 | $this->assertEquals('sip', $msg->from->uri->scheme);
34 | $this->assertEquals('I have spaces', $msg->from->uri->user);
35 | $this->assertEquals('example.net', $msg->from->uri->host);
36 | $this->assertFalse(isset($msg->from->uri->password));
37 |
38 | $this->assertEquals('sip', $msg->to->uri->scheme);
39 | $this->assertEquals('user', $msg->to->uri->user);
40 | $this->assertEquals('example.com', $msg->to->uri->host);
41 | $this->assertFalse(isset($msg->to->uri->password));
42 |
43 | /* The Contact URI has escaped characters in the URI parameters.
44 | Note that the "name" uri-parameter has a value of "value%41",
45 | which is NOT equivalent to "valueA". */
46 | $this->assertEquals('sip', $msg->contact->values[0]->uri->scheme);
47 | $this->assertEquals('caller', $msg->contact->values[0]->uri->user);
48 | $this->assertEquals('host5.example.net', $msg->contact->values[0]->uri->host);
49 | $this->assertFalse(isset($msg->contact->values[0]->uri->password));
50 | $this->assertEquals('', $msg->contact->values[0]->uri->lr);
51 | $this->assertEquals('value%41', $msg->contact->values[0]->uri->params['name']);
52 | $this->assertNotEquals('valueA', $msg->contact->values[0]->uri->params['name']);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31104Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('escnull');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* This register request contains several URIs with nulls in the
26 | userpart. The message is well formed - parsers must accept this
27 | message. Implementations must take special care when unescaping the
28 | Address-of-Record (AOR) in this request so as to not prematurely
29 | shorten the username. This request registers two distinct contact
30 | URIs. */
31 | $this->assertEquals(URI::unescape('null-%00-null'), $msg->to->uri->user);
32 | $this->assertEquals(0x00, ord($msg->to->uri->user[5]));
33 | $this->assertEquals(URI::escape(URI::unescape('null-%00-null')), 'null-%00-null');
34 | $this->assertEquals(URI::unescape('null-%00-null'), $msg->from->uri->user);
35 | $this->assertEquals(0x00, ord($msg->from->uri->user[5]));
36 | $this->assertEquals('839923423', $msg->from->tag);
37 | $this->assertEquals(chr(0x00), $msg->contact->values[0]->uri->user);
38 | $this->assertEquals(1, strlen($msg->contact->values[0]->uri->user));
39 | $this->assertEquals(chr(0x00) . chr(0x00), $msg->contact->values[1]->uri->user);
40 | $this->assertEquals(2, strlen($msg->contact->values[1]->uri->user));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31105Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('esc02');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* The request method is unknown. It is NOT equivalent to REGISTER. */
25 | $this->assertEquals('RE%47IST%45R', $msg->method);
26 |
27 | /* The display name portion of the To and From header fields is
28 | "%Z%45". Note that this is not the same as %ZE. */
29 | $this->assertEquals('%Z%45', $msg->to->name);
30 | $this->assertEquals('%Z%45', $msg->from->name);
31 |
32 | /* This message has two Contact header field values, not three.
33 | is a C%6Fntact header field value. */
34 | $this->assertCount(2, $msg->contact->values);
35 | $this->assertEquals('sip:alias1@host1.example.com', $msg->contact->values[0]->uri->render());
36 | $this->assertEquals('sip:alias3@host3.example.com', $msg->contact->values[1]->uri->render());
37 | $this->assertEquals('', $msg->extraHeaders['c%6fntact']->values[0]);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31106Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('lwsdisp');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | $this->assertEquals('OPTIONS', $msg->method);
25 |
26 | /* This OPTIONS request is not valid per the grammar in RFC 3261 since
27 | there is no LWS between the token in the display name and < in the
28 | From header field value. This has been identified as a specification
29 | bug that will be removed when RFC 3261 is revised. Elements should
30 | accept this request as well formed. */
31 | $this->assertEquals('sip', $msg->from->uri->scheme);
32 | $this->assertEquals('caller', $msg->from->uri->user);
33 | $this->assertEquals('example.com', $msg->from->uri->host);
34 | $this->assertEquals('caller', $msg->from->name);
35 | $this->assertEquals('323', $msg->from->tag);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31107Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('longreq');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* The To header field has a long display name, and long uri parameter names and values. */
25 | $this->assertEquals('sip', $msg->to->uri->scheme);
26 | $this->assertEquals('user', $msg->to->uri->user);
27 | $this->assertEquals('example.com', $msg->to->uri->host);
28 | $this->assertEquals(6000, $msg->to->uri->port);
29 | $this->assertEquals('very' . str_repeat('long', 20) . 'value', $msg->to->uri->params['unknownparam1']);
30 | $this->assertEquals('shortvalue', $msg->to->uri->params['longparam' . str_repeat('name', 25)]);
31 | $this->assertEquals('', $msg->to->uri->params['very' . str_repeat('long', 25) . 'parameternamewithnovalue']);
32 | $this->assertEquals('I have a user name of ' . str_repeat('extreme', 10) . ' proportion', $msg->to->name);
33 |
34 | /* The From header field has long header parameter names and values, in particular, a very long tag. */
35 | $this->assertEquals('sip', $msg->from->uri->scheme);
36 | $this->assertEquals(str_repeat('amazinglylongcallername', 5), $msg->from->uri->user);
37 | $this->assertEquals('example.net', $msg->from->uri->host);
38 | $this->assertEquals('12' . str_repeat('982', 50) . '424', $msg->from->tag);
39 | $this->assertEquals(
40 | 'unknowheaderparam' . str_repeat('value', 15),
41 | $msg->from->params['unknownheaderparam' . str_repeat('name', 20)]
42 | );
43 | $this->assertEquals('', $msg->from->params['unknownValueless' . str_repeat('paramname', 10)]);
44 |
45 | /* The Call-ID is one long token */
46 | $this->assertEquals('longreq.one' . str_repeat('really', 20) . 'longcallid', $msg->callId->value);
47 |
48 | /* Other cases */
49 | $this->assertEquals(
50 | 'unknown-' .
51 | str_repeat('long', 20) .
52 | '-value; unknown-' .
53 | str_repeat('long', 20) .
54 | '-parameter-name = unknown-' .
55 | str_repeat('long', 20) .
56 | '-parameter-value',
57 | $msg->extraHeaders['unknown-' . str_repeat('long', 20) . '-name']->values[0]
58 | );
59 | $this->assertCount(34, $msg->via->values);
60 | $this->assertEquals(
61 | 'very' . str_repeat('long', 50) . 'branchvalue',
62 | $msg->via->values[33]->branch
63 | );
64 | $this->assertEquals(str_repeat('amazinglylongcallername', 5), $msg->contact->values[0]->uri->user);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31108Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('dblreq');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* A SIP element receiving this datagram would handle the REGISTER
25 | request normally and ignore the extra bits that look like an INVITE
26 | request. If the element is a proxy choosing to forward the REGISTER,
27 | the INVITE octets would not appear in the forwarded request. */
28 | $this->assertEquals('REGISTER', $msg->method);
29 | $this->assertEquals(0, $msg->contentLength->value);
30 | $this->assertEquals('', $msg->body);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31109Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('semiuri');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* The Request-URI will parse so that the user part is "user;par=u@example.net" */
25 | $this->assertEquals('user;par=u@example.net', $msg->uri->user);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31110Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('transports');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* This request contains Via header field values with all known
25 | transport types and exercises the transport extension mechanism.
26 | Parsers must accept this message as well formed. Elements receiving
27 | this message would process it exactly as if the 2nd and subsequent
28 | header field values specified UDP (or other transport). */
29 | $this->assertEquals('UDP', $msg->via->values[0]->transport);
30 | $this->assertEquals('SCTP', $msg->via->values[1]->transport);
31 | $this->assertEquals('TLS', $msg->via->values[2]->transport);
32 | $this->assertEquals('UNKNOWN', $msg->via->values[3]->transport);
33 | $this->assertEquals('TCP', $msg->via->values[4]->transport);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31111Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('mpart01');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* This MESSAGE request contains two body parts. The second part is
25 | binary encoded and contains null (0x00) characters. Receivers must
26 | take care to frame the received message properly. */
27 | $this->assertEquals('MESSAGE', $msg->method);
28 | $this->assertEquals(553, $msg->contentLength->value);
29 | $this->assertEquals(553, strlen($msg->body));
30 | $this->assertEquals(
31 | "--7a9cbec02ceef655" . "\r\n" .
32 | "Content-Type: text/plain" . "\r\n" .
33 | "Content-Transfer-Encoding: binary" . "\r\n" .
34 | "\r\n" .
35 | "Hello" . "\r\n" .
36 | "--7a9cbec02ceef655" . "\r\n" .
37 | "Content-Type: application/octet-stream" . "\r\n" .
38 | "Content-Transfer-Encoding: binary" . "\r\n" .
39 | "\r\n" .
40 | "\x30\x82\x01\x52\x06\x09\x2A\x86" .
41 | "\x48\x86\xF7\x0D\x01\x07\x02\xA0\x82\x01\x43\x30\x82\x01\x3F\x02" .
42 | "\x01\x01\x31\x09\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x30\x0B\x06" .
43 | "\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01\x31\x82\x01\x20\x30\x82" .
44 | "\x01\x1C\x02\x01\x01\x30\x7C\x30\x70\x31\x0B\x30\x09\x06\x03\x55" .
45 | "\x04\x06\x13\x02\x55\x53\x31\x13\x30\x11\x06\x03\x55\x04\x08\x13" .
46 | "\x0A\x43\x61\x6C\x69\x66\x6F\x72\x6E\x69\x61\x31\x11\x30\x0F\x06" .
47 | "\x03\x55\x04\x07\x13\x08\x53\x61\x6E\x20\x4A\x6F\x73\x65\x31\x0E" .
48 | "\x30\x0C\x06\x03\x55\x04\x0A\x13\x05\x73\x69\x70\x69\x74\x31\x29" .
49 | "\x30\x27\x06\x03\x55\x04\x0B\x13\x20\x53\x69\x70\x69\x74\x20\x54" .
50 | "\x65\x73\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20" .
51 | "\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x02\x08\x01\x95\x00\x71\x02" .
52 | "\x33\x01\x13\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x30\x0D\x06\x09" .
53 | "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x04\x81\x80\x8E\xF4" .
54 | "\x66\xF9\x48\xF0\x52\x2D\xD2\xE5\x97\x8E\x9D\x95\xAA\xE9\xF2\xFE" .
55 | "\x15\xA0\x66\x59\x71\x62\x92\xE8\xDA\x2A\xA8\xD8\x35\x0A\x68\xCE" .
56 | "\xFF\xAE\x3C\xBD\x2B\xFF\x16\x75\xDD\xD5\x64\x8E\x59\x3D\xD6\x47" .
57 | "\x28\xF2\x62\x20\xF7\xE9\x41\x74\x9E\x33\x0D\x9A\x15\xED\xAB\xDB" .
58 | "\x93\xD1\x0C\x42\x10\x2E\x7B\x72\x89\xD2\x9C\xC0\xC9\xAE\x2E\xFB" .
59 | "\xC7\xC0\xCF\xF9\x17\x2F\x3B\x02\x7E\x4F\xC0\x27\xE1\x54\x6D\xE4" .
60 | "\xB6\xAA\x3A\xBB\x3E\x66\xCC\xCB\x5D\xD6\xC6\x4B\x83\x83\x14\x9C" .
61 | "\xB8\xE6\xFF\x18\x2D\x94\x4F\xE5\x7B\x65\xBC\x99\xD0\x05" . "\r\n" .
62 | "--7a9cbec02ceef655--" . "\r\n",
63 | $msg->body
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31112Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('unreason');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Response::class, $msg);
23 |
24 | /* This particular response contains unreserved and non-ascii UTF-8
25 | characters. This response is well formed. A parser must accept this
26 | message */
27 | $this->assertEquals(
28 | '= 2**3 * 5**2 ' .
29 | "\xD0\xBD\xD0\xBE\x20\xD1\x81\xD1\x82" .
30 | "\xD0\xBE\x20\xD0\xB4\xD0\xB5\xD0\xB2\xD1\x8F\xD0\xBD\xD0\xBE\xD1\x81\xD1\x82\xD0\xBE\x20\xD0\xB4" .
31 | "\xD0\xB5\xD0\xB2\xD1\x8F\xD1\x82\xD1\x8C\x20\x2D\x20\xD0\xBF\xD1\x80\xD0\xBE\xD1\x81\xD1\x82\xD0" .
32 | "\xBE\xD0\xB5",
33 | $msg->reason
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31113Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('noreason');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Response::class, $msg);
23 |
24 | /* This well-formed response contains no reason phrase. A parser must
25 | accept this message. The space character after the reason code is
26 | required. If it were not present, this message could be rejected as
27 | invalid (a liberal receiver would accept it anyway). */
28 | $this->assertEquals('', $msg->reason);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31201Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('badinv01');
19 |
20 | // Throws InvalidHeaderParameterException for blank Via and Contact parameters
21 | $this->expectException(InvalidHeaderParameterException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31202Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('clerr');
19 |
20 | // Throws InvalidBodyLengthException for length mismatch
21 | $this->expectException(InvalidBodyLengthException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31203Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('ncl');
19 |
20 | // Throws InvalidScalarValueException for length mismatch
21 | $this->expectException(InvalidScalarValueException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31204Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('scalar02');
19 |
20 | // Throws InvalidScalarValueException for aberrant values
21 | $this->expectException(InvalidScalarValueException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31205Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('scalarlg');
19 |
20 | // Throws InvalidScalarValueException for aberrant values
21 | $this->expectException(InvalidScalarValueException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31206Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('quotbal');
19 |
20 | // Throws InvalidHeaderLineException for unmatched quotes
21 | $this->expectException(InvalidHeaderLineException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31207Test.php:
--------------------------------------------------------------------------------
1 | Enclosing Request-URI
13 | */
14 | class S31207Test extends RFC4475Case
15 | {
16 | public function testShouldNotParse()
17 | {
18 | $pdu = $this->loadFixture('ltgtruri');
19 |
20 | // Throws InvalidRequestURIException for escaped request URIs
21 | $this->expectException(InvalidRequestURIException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31208Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('lwsruri');
19 |
20 | // Throws InvalidMessageStartLineException for malformed request URI
21 | $this->expectException(InvalidMessageStartLineException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31209Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('lwsstart');
19 |
20 | // Throws InvalidMessageStartLineException for malformed request URI
21 | $this->expectException(InvalidMessageStartLineException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31210Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('trws');
19 |
20 | // Throws InvalidMessageStartLineException for malformed request URI
21 | $this->expectException(InvalidMessageStartLineException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31211Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('escruri');
22 |
23 | $msg = Message::parse($pdu);
24 |
25 | $this->assertInstanceOf(Request::class, $msg);
26 | $this->assertEquals([], $msg->uri->headers);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31212Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('baddate');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | $this->assertEquals('Fri, 01 Jan 2010 16:00:00 EST', $msg->date->values[0]);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31213Test.php:
--------------------------------------------------------------------------------
1 |
13 | *
14 | * As an UAS, this implementation will take the liberal route and accept
15 | * unenclosed SIP name-addr URIs
16 | */
17 | class S31213Test extends RFC4475Case
18 | {
19 | public function testShouldParse()
20 | {
21 | $pdu = $this->loadFixture('regbadct');
22 |
23 | $msg = Message::parse($pdu);
24 |
25 | $this->assertInstanceOf(Request::class, $msg);
26 | $this->assertEquals('', $msg->contact->values[0]->uri->headers['Route']);
27 |
28 | /* However, as an UAC, this implementation will always enclose SIP name-addr URIs */
29 | $this->assertEquals(
30 | "Contact: \r\n",
31 | $msg->contact->render('Contact')
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31214Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('badaspec');
22 |
23 | $msg = Message::parse($pdu);
24 |
25 | $this->assertInstanceOf(Request::class, $msg);
26 |
27 | $this->assertEquals('sip', $msg->to->uri->scheme);
28 | $this->assertEquals('t.watson', $msg->to->uri->user);
29 | $this->assertEquals('example.org', $msg->to->uri->host);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31215Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('baddn');
22 |
23 | $msg = Message::parse($pdu);
24 |
25 | $this->assertInstanceOf(Request::class, $msg);
26 |
27 | $this->assertEquals('sip', $msg->to->uri->scheme);
28 | $this->assertEquals('t.watson', $msg->to->uri->user);
29 | $this->assertEquals('example.org', $msg->to->uri->host);
30 | $this->assertEquals('Watson, Thomas', $msg->to->name);
31 | $this->assertEquals('sip', $msg->from->uri->scheme);
32 | $this->assertEquals('a.g.bell', $msg->from->uri->user);
33 | $this->assertEquals('example.com', $msg->from->uri->host);
34 | $this->assertEquals('Bell, Alexander', $msg->from->name);
35 | $this->assertEquals('43', $msg->from->tag);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31216Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('badvers');
19 |
20 | // Throws InvalidProtocolVersionException for bogus version
21 | $this->expectException(InvalidProtocolVersionException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31217Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('mismatch01');
19 |
20 | // Throws InvalidCSeqValueException for bogus mismatched request methods
21 | $this->expectException(InvalidCSeqValueException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31218Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('mismatch02');
19 |
20 | // Throws InvalidCSeqValueException for bogus mismatched request methods
21 | $this->expectException(InvalidCSeqValueException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S31219Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('bigcode');
19 |
20 | // Throws InvalidStatusCodeException for bogus response codes
21 | $this->expectException(InvalidStatusCodeException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S32010Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('badbranch');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure via branch tag is readable; application must be able to tell
26 | only the prefix was sent over, no identifier. */
27 | $this->assertEquals('z9hG4bK', $msg->via->values[0]->branch);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33010Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('insuf');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility to determine
26 | Call-ID, From, or To headers are missing */
27 | $this->assertFalse(isset($msg->callId));
28 | $this->assertFalse(isset($msg->from));
29 | $this->assertFalse(isset($msg->to));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33020Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('unkscm');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to work
25 | with the request URI scheme as it wishes */
26 | $this->assertEquals('nobodyknowsthisscheme', $msg->uri->scheme);
27 | $this->assertEquals('totallyopaquecontent', $msg->uri->host);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33030Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('novelsc');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to work
25 | with the request URI scheme as it wishes */
26 | $this->assertEquals('soap.beep', $msg->uri->scheme);
27 | $this->assertEquals('192.0.2.103', $msg->uri->host);
28 | $this->assertEquals(3002, $msg->uri->port);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33040Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('unksm2');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to work
25 | with the To header field value scheme as it wishes */
26 | $this->assertEquals('isbn', $msg->to->uri->scheme);
27 | $this->assertEquals('2983792873', $msg->to->uri->host);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33050Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('bext01');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility to read *Require header fields */
26 | $this->assertEquals('nothingSupportsThis', $msg->require->values[0]);
27 | $this->assertEquals('nothingSupportsThisEither', $msg->require->values[1]);
28 | $this->assertEquals('noProxiesSupportThis', $msg->proxyRequire->values[0]);
29 | $this->assertEquals('norDoAnyProxiesSupportThis', $msg->proxyRequire->values[1]);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33060Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('invut');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility read the content's type */
26 | $this->assertEquals('application/unknownformat', $msg->contentType->value);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33070Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('regaut01');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility read the authorization */
26 | $this->assertEquals('nooneknowsthisscheme', $msg->authorization->values[0]->scheme);
27 | $this->assertEquals('opaque-data=here', $msg->authorization->values[0]->params->verbatim);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33080Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('multi01');
19 |
20 | // Throws InvalidDuplicateHeaderException for duplicate header fields
21 | $this->expectException(InvalidDuplicateHeaderException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33090Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('mcl01');
19 |
20 | // Throws InvalidDuplicateHeaderException for duplicate header fields
21 | $this->expectException(InvalidDuplicateHeaderException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33100Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('bcast');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Response::class, $msg);
24 |
25 | /* Make sure the application has enough visibility to read the broadcast address */
26 | $this->assertEquals('255.255.255.255', $msg->via->values[1]->host);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33110Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('zeromf');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility to read the Max-Forwards header value */
26 | $this->assertNotNull($msg->maxForwards->value);
27 | $this->assertEquals(0, $msg->maxForwards->value);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33120Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('cparam01');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to
25 | determine this is a REGISTER request with a contact
26 | header parameter (not URI parameter!) */
27 | $this->assertEquals('REGISTER', $msg->method);
28 | $this->assertEquals('sip', $msg->contact->values[0]->uri->scheme);
29 | $this->assertEquals('+19725552222', $msg->contact->values[0]->uri->user);
30 | $this->assertEquals('gw1.example.net', $msg->contact->values[0]->uri->host);
31 | $this->assertEquals('', $msg->contact->values[0]->params['unknownparam']);
32 | $this->assertTrue(!isset($msg->contact->values[0]->uri->params['unknownparam']));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33130Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('cparam02');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to
25 | determine this is a REGISTER request with a URI
26 | parameter (not a contact parameter!) */
27 | $this->assertEquals('REGISTER', $msg->method);
28 | $this->assertEquals('sip', $msg->contact->values[0]->uri->scheme);
29 | $this->assertEquals('+19725552222', $msg->contact->values[0]->uri->user);
30 | $this->assertEquals('gw1.example.net', $msg->contact->values[0]->uri->host);
31 | $this->assertEquals('', $msg->contact->values[0]->uri->params['unknownparam']);
32 | $this->assertTrue(!isset($msg->contact->values[0]->params['unknownparam']));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33140Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('regescrt');
19 |
20 | $msg = Message::parse($pdu);
21 |
22 | $this->assertInstanceOf(Request::class, $msg);
23 |
24 | /* Make sure the application has enough visibility to
25 | determine this is a REGISTER request with a URI
26 | parameter (escaped header, not a contact parameter!) */
27 | $this->assertEquals('REGISTER', $msg->method);
28 | $this->assertEquals('', $msg->contact->values[0]->uri->headers['Route']);
29 | $this->assertTrue(!isset($msg->contact->values[0]->params['Route']));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/RFC4475/S33150Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('sdp01');
20 |
21 | $msg = Message::parse($pdu);
22 |
23 | $this->assertInstanceOf(Request::class, $msg);
24 |
25 | /* Make sure the application has enough visibility to
26 | read the Accept reader */
27 | $this->assertEquals('text/nobodyKnowsThis', $msg->accept->values[0]->value);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/RFC4475/S34010Test.php:
--------------------------------------------------------------------------------
1 | loadFixture('inv2543');
19 |
20 | // Throws InvalidHeaderParameterException for missing From header value tag parameter
21 | $this->expectException(InvalidHeaderParameterException::class);
22 | Message::parse($pdu);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/RequestTest.php:
--------------------------------------------------------------------------------
1 | assertNotNull($request);
25 | $this->assertInstanceOf(Request::class, $request);
26 | }
27 |
28 | public function testShouldInstantiateWithCorrectStartLine()
29 | {
30 | $request = new Request('INVITE sip:something.com SIP/2.0');
31 |
32 | $this->assertNotNull($request);
33 | $this->assertInstanceOf(Request::class, $request);
34 | }
35 |
36 | public function testShouldFailWithoutVersion()
37 | {
38 | // Throws InvalidMessageStartLineException
39 | $this->expectException(InvalidMessageStartLineException::class);
40 | $request = new Request('INVITE sip:something.com');
41 | }
42 |
43 | public function testShouldFailWithBadVersion()
44 | {
45 | // Throws InvalidProtocolVersionException
46 | $this->expectException(InvalidProtocolVersionException::class);
47 | $request = new Request('INVITE sip:something.com SIP/7.0');
48 | }
49 |
50 | public function testShouldFailWithBadURI()
51 | {
52 | // Throws InvalidRequestURIException
53 | $this->expectException(InvalidRequestURIException::class);
54 | $request = new Request('INVITE SIP/2.0');
55 | }
56 |
57 | public function testShouldRender()
58 | {
59 | $request = new Request();
60 | $request->method = 'REGISTER';
61 | $request->uri = URI::parse('sip:user@domain.com');
62 | $request->from = new NameAddrHeader;
63 | $request->from->uri = URI::parse('sip:user@domain.com');
64 | $request->from->tag = 'rand0m';
65 | $request->to = new NameAddrHeader;
66 | $request->to->uri = URI::parse('sip:user@domain.com');
67 |
68 | $text = $request->render();
69 |
70 | $this->assertNotNull($text);
71 | $this->assertIsString($text);
72 | $this->assertEquals(
73 | 'REGISTER sip:user@domain.com SIP/2.0' . "\r\n" .
74 | 'From: ;tag=rand0m' . "\r\n" .
75 | 'To: ' . "\r\n" .
76 | "\r\n",
77 | $text
78 | );
79 | }
80 |
81 | public function testShouldNotRenderWithoutMethod()
82 | {
83 | $request = new Request();
84 | $request->uri = URI::parse('sip:user@domain.com');
85 |
86 | // Throws InvalidRequestMethodException
87 | $this->expectException(InvalidRequestMethodException::class);
88 | $request->render();
89 | }
90 |
91 | public function testShouldNotRenderWithoutURI()
92 | {
93 | $request = new Request();
94 | $request->method = 'REGISTER';
95 |
96 | // Throws InvalidRequestURIException
97 | $this->expectException(InvalidRequestURIException::class);
98 | $request->render();
99 | }
100 |
101 | public function testShouldNotRenderWithHeadersInURI()
102 | {
103 | $request = new Request();
104 | $request->method = 'REGISTER';
105 | $request->uri = new URI;
106 | $request->uri->scheme = 'sip';
107 | $request->uri->user = 'user';
108 | $request->uri->host = 'domain.com';
109 | $request->uri->headers['Header'] = 'Value';
110 |
111 | // Throws InvalidRequestURIException
112 | $this->expectException(InvalidRequestURIException::class);
113 | $request->render();
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/gh-21.yaml:
--------------------------------------------------------------------------------
1 | # https://github.com/rtckit/php-sip/issues/21
2 | - |+
3 | SIP/2.0 200 OK
4 | Via: SIP/2.0/TCP 192.0.2.15;branch=z9hG4bKnuiqisi
5 | From: Bob ;tag=7F94778B653B
6 | To: Bob ;tag=6AF99445E44A
7 | Call-ID: 16CB75F21C70
8 | CSeq: 1 REGISTER
9 | Supported: path, outbound
10 | Require: outbound
11 | Contact: ;expires=111;received="sip:e52@78.102.16.243:55497";reg-id=1;+sip.instance="",;expires=258;received="sip:e52@78.102.16.243:17127";reg-id=2;+sip.instance="<65be01c100f2ccd762df61057569f037bd46a367>"
12 | Path:
13 | Content-Length: 0
14 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3327/5.5.2_example-of-mechanism-in-invite-transaction.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3327
2 | # 5.5.2 Example of Mechanism in INVITE Transaction
3 | #
4 | # UA1----P1---------P3-----REGISTRAR
5 | # | |
6 | # P2 |
7 | # |
8 | # UA2--------------------------
9 | - |+
10 | INVITE sip:UA1@EXAMPLEHOME.COM SIP/2.0
11 | Via: SIP/2.0/UDP 71.91.180.10:5060;branch=z9hG4bKe2i95c5st3R
12 | To: UA1
13 | From: UA2 ;tag=224497
14 | Call-ID: 48273181116@71.91.180.10
15 | CSeq: 29 INVITE
16 | Contact:
17 |
18 | - |+
19 | INVITE sip:UA1@192.0.2.4 SIP/2.0
20 | Via: SIP/2.0/UDP 143.70.6.83:5060;branch=z9hG4bKlj25C107a7b176
21 | Via: SIP/2.0/UDP 71.91.180.10:5060;branch=z9hG4bKe2i95c5st3R
22 | To: UA1
23 | From: UA2 ;tag=224497
24 | Call-ID: 48273181116@71.91.180.10
25 | CSeq: 29 INVITE
26 | Contact:
27 | Route: ,
28 |
29 | - |+
30 | INVITE sip:UA1@192.0.2.4 SIP/2.0
31 | Via: SIP/2.0/UDP 19.31.97.3:5060;branch=z9hG4bKjasg7li7nc9e
32 | Via: SIP/2.0/UDP 143.70.6.83:5060;branch=z9hG4bKlj25C107a7b176
33 | Via: SIP/2.0/UDP 71.91.180.10:5060;branch=z9hG4bKe2i95c5st3R
34 | To: UA1
35 | From: UA2 ;tag=224497
36 | Call-ID: 48273181116@71.91.180.10
37 | CSeq: 29 INVITE
38 | Contact:
39 | Record-Route:
40 | Route:
41 |
42 | - |+
43 | INVITE sip:UA1@192.0.2.4 SIP/2.0
44 | Via: SIP/2.0/UDP 112.68.155.4:5060;branch=z9hG4bKk5l1833o43p
45 | Via: SIP/2.0/UDP 19.31.97.3:5060;branch=z9hG4bKjasg7li7nc9e
46 | Via: SIP/2.0/UDP 143.70.6.83:5060;branch=z9hG4bKlj25C107a7b176
47 | Via: SIP/2.0/UDP 71.91.180.10:5060;branch=z9hG4bKe2i95c5st3R
48 | To: UA1
49 | From: UA2 ;tag=224497
50 | Call-ID: 48273181116@71.91.180.10
51 | CSeq: 29 INVITE
52 | Contact:
53 | Record-Route:
54 | Record-Route:
55 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3515/4.1_prototypical-refer-callflow.yaml:
--------------------------------------------------------------------------------
1 | # https://datatracker.ietf.org/doc/html/rfc3515
2 | # 4.1 Prototypical REFER callflow
3 | #
4 | # Agent A Agent B
5 | # | |
6 | # | F1 REFER |
7 | # |----------------------->|
8 | # | F2 202 Accepted |
9 | # |<-----------------------|
10 | # | F3 NOTIFY |
11 | # |<-----------------------|
12 | # | F4 200 OK |
13 | # |----------------------->|
14 | # | |
15 | # | |
16 | # | |------->
17 | # | | (whatever)
18 | # | |<------
19 | # | |
20 | # | F5 NOTIFY |
21 | # |<-----------------------|
22 | # | F6 200 OK |
23 | # |----------------------->|
24 | # | |
25 | # | |
26 | - |+
27 | REFER sip:b@atlanta.example.com SIP/2.0
28 | Via: SIP/2.0/UDP agenta.atlanta.example.com;branch=z9hG4bK2293940223
29 | To:
30 | From: ;tag=193402342
31 | Call-ID: 898234234@agenta.atlanta.example.com
32 | CSeq: 93809823 REFER
33 | Max-Forwards: 70
34 | Refer-To: (whatever URI)
35 | Contact: sip:a@atlanta.example.com
36 | Content-Length: 0
37 |
38 | - |+
39 | SIP/2.0 202 Accepted
40 | Via: SIP/2.0/UDP agenta.atlanta.example.com;branch=z9hG4bK2293940223
41 | To: ;tag=4992881234
42 | From: ;tag=193402342
43 | Call-ID: 898234234@agenta.atlanta.example.com
44 | CSeq: 93809823 REFER
45 | Contact: sip:b@atlanta.example.com
46 | Content-Length: 0
47 |
48 | - |+
49 | NOTIFY sip:a@atlanta.example.com SIP/2.0
50 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9922ef992-25
51 | To: ;tag=193402342
52 | From: ;tag=4992881234
53 | Call-ID: 898234234@agenta.atlanta.example.com
54 | CSeq: 1993402 NOTIFY
55 | Max-Forwards: 70
56 | Event: refer
57 | Subscription-State: active;expires=(depends on Refer-To URI)
58 | Contact: sip:b@atlanta.example.com
59 | Content-Type: message/sipfrag;version=2.0
60 | Content-Length: 20
61 |
62 | SIP/2.0 100 Trying
63 |
64 | - |+
65 | SIP/2.0 200 OK
66 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9922ef992-25
67 | To: ;tag=193402342
68 | From: ;tag=4992881234
69 | Call-ID: 898234234@agenta.atlanta.example.com
70 | CSeq: 1993402 NOTIFY
71 | Contact: sip:a@atlanta.example.com
72 | Content-Length: 0
73 |
74 | - |+
75 | NOTIFY sip:a@atlanta.example.com SIP/2.0
76 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9323394234
77 | To: ;tag=193402342
78 | From: ;tag=4992881234
79 | Call-ID: 898234234@agenta.atlanta.example.com
80 | CSeq: 1993403 NOTIFY
81 | Max-Forwards: 70
82 | Event: refer
83 | Subscription-State: terminated;reason=noresource
84 | Contact: sip:b@atlanta.example.com
85 | Content-Type: message/sipfrag;version=2.0
86 | Content-Length: 16
87 |
88 | SIP/2.0 200 OK
89 |
90 | - |+
91 | SIP/2.0 200 OK
92 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9323394234
93 | To: ;tag=193402342
94 | From: ;tag=4992881234
95 | Call-ID: 898234234@agenta.atlanta.example.com
96 | CSeq: 1993403 NOTIFY
97 | Contact: sip:a@atlanta.example.com
98 | Content-Length: 0
99 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3515/4.2_multiple-refers-in-a-dialog.yaml:
--------------------------------------------------------------------------------
1 | # https://datatracker.ietf.org/doc/html/rfc3515
2 | # 4.2 Multiple REFERs in a dialog
3 | #
4 | # Agent A Agent B
5 | # | |
6 | # | F7 REFER |
7 | # |----------------------->|
8 | # | F8 202 Accepted |
9 | # |<-----------------------|
10 | # | F9 NOTIFY |
11 | # |<-----------------------|
12 | # | F10 200 OK |
13 | # |----------------------->|
14 | # | |------->
15 | # | | (something different)
16 | # | |<------
17 | # | |
18 | # | F11 NOTIFY |
19 | # |<-----------------------|
20 | # | F12 200 OK |
21 | # |----------------------->|
22 | # | |
23 | # | |
24 | - |+
25 | REFER sip:b@atlanta.example.com SIP/2.0
26 | Via: SIP/2.0/UDP agenta.atlanta.example.com;branch=z9hG4bK9390399231
27 | To: ;tag=4992881234
28 | From: ;tag=193402342
29 | Call-ID: 898234234@agenta.atlanta.example.com
30 | CSeq: 93809824 REFER
31 | Max-Forwards: 70
32 | Refer-To: (some different URI)
33 | Contact: sip:a@atlanta.example.com
34 | Content-Length: 0
35 |
36 | - |+
37 | SIP/2.0 202 Accepted
38 | Via: SIP/2.0/UDP agenta.atlanta.example.com;branch=z9hG4bK9390399231
39 | To: ;tag=4992881234
40 | From: ;tag=193402342
41 | Call-ID: 898234234@agenta.atlanta.example.com
42 | CSeq: 93809824 REFER
43 | Contact: sip:b@atlanta.example.com
44 | Content-Length: 0
45 |
46 | - |+
47 | NOTIFY sip:a@atlanta.example.com SIP/2.0
48 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9320394238995
49 | To: ;tag=193402342
50 | From: ;tag=4992881234
51 | Call-ID: 898234234@agenta.atlanta.example.com
52 | CSeq: 1993404 NOTIFY
53 | Max-Forwards: 70
54 | Event: refer;id=93809824
55 | Subscription-State: active;expires=(depends on Refer-To URI)
56 | Contact: sip:b@atlanta.example.com
57 | Content-Type: message/sipfrag;version=2.0
58 | Content-Length: 20
59 |
60 | SIP/2.0 100 Trying
61 |
62 | - |+
63 | SIP/2.0 200 OK
64 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK9320394238995
65 | To: ;tag=193402342
66 | From: ;tag=4992881234
67 | Call-ID: 898234234@agenta.atlanta.example.com
68 | CSeq: 1993404 NOTIFY
69 | Contact: sip:a@atlanta.example.com
70 | Content-Length: 0
71 |
72 | - |+
73 | NOTIFY sip:a@atlanta.example.com SIP/2.0
74 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK2994a93eb-fe
75 | To: ;tag=193402342
76 | From: ;tag=4992881234
77 | Call-ID: 898234234@agenta.atlanta.example.com
78 | CSeq: 1993405 NOTIFY
79 | Max-Forwards: 70
80 | Event: refer;id=93809824
81 | Subscription-State: terminated;reason=noresource
82 | Contact: sip:b@atlanta.example.com
83 | Content-Type: message/sipfrag;version=2.0
84 | Content-Length: 16
85 |
86 | SIP/2.0 200 OK
87 |
88 | - |+
89 | SIP/2.0 200 OK
90 | Via: SIP/2.0/UDP agentb.atlanta.example.com;branch=z9hG4bK2994a93eb-fe
91 | To: ;tag=193402342
92 | From: ;tag=4992881234
93 | Call-ID: 898234234@agenta.atlanta.example.com
94 | CSeq: 1993405 NOTIFY
95 | Contact: sip:a@atlanta.example.com
96 | Content-Length: 0
97 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/2.01_sip-client-new-registration.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 2.1. Successful New Registration
3 | #
4 | # Bob SIP Server
5 | # | |
6 | # | REGISTER F1 |
7 | # |------------------------------>|
8 | # | 401 Unauthorized F2 |
9 | # |<------------------------------|
10 | # | REGISTER F3 |
11 | # |------------------------------>|
12 | # | 200 OK F4 |
13 | # |<------------------------------|
14 | # | |
15 | - |+
16 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
17 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
18 | Max-Forwards: 70
19 | From: Bob ;tag=a73kszlfl
20 | To: Bob
21 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
22 | CSeq: 1 REGISTER
23 | Contact:
24 | Content-Length: 0
25 |
26 | - |+
27 | SIP/2.0 401 Unauthorized
28 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
29 | ;received=192.0.2.201
30 | From: Bob ;tag=a73kszlfl
31 | To: Bob ;tag=1410948204
32 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
33 | CSeq: 1 REGISTER
34 | WWW-Authenticate: Digest realm="atlanta.example.com", qop="auth",
35 | nonce="ea9c8e88df84f1cec4341ae6cbe5a359",
36 | opaque="", stale=FALSE, algorithm=MD5
37 | Content-Length: 0
38 |
39 | - |+
40 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
41 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashd92
42 | Max-Forwards: 70
43 | From: Bob ;tag=ja743ks76zlflH
44 | To: Bob
45 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
46 | CSeq: 2 REGISTER
47 | Contact:
48 | Authorization: Digest username="bob", realm="atlanta.example.com",
49 | nonce="ea9c8e88df84f1cec4341ae6cbe5a359", opaque="",
50 | uri="sips:ss2.biloxi.example.com",
51 | response="dfe56131d1958046689d83306477ecc"
52 | Content-Length: 0
53 |
54 | - |+
55 | SIP/2.0 200 OK
56 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashd92
57 | ;received=192.0.2.201
58 | From: Bob ;tag=ja743ks76zlflH
59 | To: Bob ;tag=37GkEhwl6
60 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
61 | CSeq: 2 REGISTER
62 | Contact: ;expires=3600
63 | Content-Length: 0
64 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/2.02_update-of-contact-list.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 2.2. Update of Contact List
3 | #
4 | # Bob SIP Server
5 | # | |
6 | # | REGISTER F1 |
7 | # |------------------------------>|
8 | # | 200 OK F2 |
9 | # |<------------------------------|
10 | # | |
11 | - |+
12 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
13 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
14 | Max-Forwards: 70
15 | From: Bob ;tag=a73kszlfl
16 | To: Bob
17 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
18 | CSeq: 1 REGISTER
19 | Contact: mailto:bob@biloxi.example.com
20 | Authorization: Digest username="bob", realm="atlanta.example.com",
21 | qop="auth", nonce="1cec4341ae6cbe5a359ea9c8e88df84f", opaque="",
22 | uri="sips:ss2.biloxi.example.com",
23 | response="71ba27c64bd01de719686aa4590d5824"
24 | Content-Length: 0
25 |
26 | - |+
27 | SIP/2.0 200 OK
28 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
29 | ;received=192.0.2.201
30 | From: Bob ;tag=a73kszlfl
31 | To: Bob ;tag=34095828jh
32 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
33 | CSeq: 1 REGISTER
34 | Contact: ;expires=3600
35 | Contact: ;expires=4294967295
36 | Content-Length: 0
37 |
38 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/2.03_request-for-current-contact-list.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 2.3. Request for Current Contact List
3 | #
4 | # Bob SIP Server
5 | # | |
6 | # | REGISTER F1 |
7 | # |------------------------------>|
8 | # | 200 OK F2 |
9 | # |<------------------------------|
10 | # | |
11 | - |+
12 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
13 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
14 | Max-Forwards: 70
15 | From: Bob ;tag=a73kszlfl
16 | To: Bob
17 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
18 | CSeq: 1 REGISTER
19 | Authorization: Digest username="bob", realm="atlanta.example.com",
20 | nonce="df84f1cec4341ae6cbe5ap359a9c8e88", opaque="",
21 | uri="sips:ss2.biloxi.example.com",
22 | response="aa7ab4678258377c6f7d4be6087e2f60"
23 | Content-Length: 0
24 |
25 | - |+
26 | SIP/2.0 200 OK
27 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
28 | ;received=192.0.2.201
29 | From: Bob ;tag=a73kszlfl
30 | To: Bob ;tag=jqoiweu75
31 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
32 | CSeq: 1 REGISTER
33 | Contact: ;expires=3600
34 | Contact: ;expires=4294967295
35 | Content-Length: 0
36 |
37 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/2.04_cancellation-of-registration.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 2.4. Cancellation of Registration
3 | #
4 | # Bob SIP Server
5 | # | |
6 | # | REGISTER F1 |
7 | # |------------------------------>|
8 | # | 200 OK F2 |
9 | # |<------------------------------|
10 | # | |
11 | - |+
12 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
13 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
14 | Max-Forwards: 70
15 | From: Bob ;tag=a73kszlfl
16 | To: Bob
17 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
18 | CSeq: 1 REGISTER
19 | Expires: 0
20 | Contact: *
21 | Authorization: Digest username="bob", realm="atlanta.example.com",
22 | nonce="88df84f1cac4341aea9c8ee6cbe5a359", opaque="",
23 | uri="sips:ss2.biloxi.example.com",
24 | response="ff0437c51696f9a76244f0cf1dbabbea"
25 | Content-Length: 0
26 |
27 | - |+
28 | SIP/2.0 200 OK
29 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
30 | ;received=192.0.2.201
31 | From: Bob ;tag=a73kszlfl
32 | To: Bob ;tag=1418nmdsrf
33 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
34 | CSeq: 1 REGISTER
35 | Content-Length: 0
36 |
37 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/2.05_unsuccessful-registration.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 2.5. Unsuccessful Registration
3 | #
4 | # Bob SIP Server
5 | # | |
6 | # | REGISTER F1 |
7 | # |------------------------------>|
8 | # | 401 Unauthorized F2 |
9 | # |<------------------------------|
10 | # | REGISTER F3 |
11 | # |------------------------------>|
12 | # | 401 Unauthorized F4 |
13 | # |<------------------------------|
14 | # | |
15 | - |+
16 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
17 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
18 | ;received=192.0.2.201
19 | From: Bob ;tag=a73kszlfl
20 | To: Bob
21 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
22 | CSeq: 1 REGISTER
23 | Contact:
24 | Content-Length: 0
25 |
26 | - |+
27 | SIP/2.0 401 Unauthorized
28 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashds7
29 | ;received=192.0.2.201
30 | From: Bob ;tag=a73kszlfl
31 | To: Bob ;tag=1410948204
32 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
33 | CSeq: 1 REGISTER
34 | WWW-Authenticate: Digest realm="atlanta.example.com", qop="auth",
35 | nonce="f1cec4341ae6ca9c8e88df84be55a359",
36 | opaque="", stale=FALSE, algorithm=MD5
37 | Content-Length: 0
38 |
39 | - |+
40 | REGISTER sips:ss2.biloxi.example.com SIP/2.0
41 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashd92
42 | Max-Forwards: 70
43 | From: Bob ;tag=JueHGuidj28dfga
44 | To: Bob
45 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
46 | CSeq: 2 REGISTER
47 | Contact:
48 | Authorization: Digest username="bob", realm="atlanta.example.com",
49 | nonce="f1cec4341ae6ca9c8e88df84be55a359", opaque="",
50 | uri="sips:ss2.biloxi.example.com",
51 | response="61f8470ceb87d7ebf508220214ed438b"
52 | Content-Length: 0
53 |
54 | - |+
55 | SIP/2.0 401 Unauthorized
56 | Via: SIP/2.0/TLS client.biloxi.example.com:5061;branch=z9hG4bKnashd92
57 | ;received=192.0.2.201
58 | From: Bob ;tag=JueHGuidj28dfga
59 | To: Bob ;tag=1410948204
60 | Call-ID: 1j9FpLxk3uxtm8tn@biloxi.example.com
61 | CSeq: 2 REGISTER
62 | WWW-Authenticate: Digest realm="atlanta.example.com", qop="auth",
63 | nonce="84f1c1ae6cbe5ua9c8e88dfa3ecm3459",
64 | opaque="", stale=FALSE, algorithm=MD5
65 | Content-Length: 0
66 |
67 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc3665/3.01_successful-session-establishment.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc3665
2 | # 3.1. Successful Session Establishment
3 | #
4 | # Alice Bob
5 | # | |
6 | # | INVITE F1 |
7 | # |----------------------->|
8 | # | 180 Ringing F2 |
9 | # |<-----------------------|
10 | # | |
11 | # | 200 OK F3 |
12 | # |<-----------------------|
13 | # | ACK F4 |
14 | # |----------------------->|
15 | # | Both Way RTP Media |
16 | # |<======================>|
17 | # | |
18 | # | BYE F5 |
19 | # |<-----------------------|
20 | # | 200 OK F6 |
21 | # |----------------------->|
22 | # | |
23 | - |+
24 | INVITE sip:bob@biloxi.example.com SIP/2.0
25 | Via: SIP/2.0/TCP client.atlanta.example.com:5060;branch=z9hG4bK74bf9
26 | Max-Forwards: 70
27 | From: Alice ;tag=9fxced76sl
28 | To: Bob
29 | Call-ID: 3848276298220188511@atlanta.example.com
30 | CSeq: 1 INVITE
31 | Contact:
32 | Content-Type: application/sdp
33 | Content-Length: 151
34 |
35 | v=0
36 | o=alice 2890844526 2890844526 IN IP4 client.atlanta.example.com
37 | s=-
38 | c=IN IP4 192.0.2.101
39 | t=0 0
40 | m=audio 49172 RTP/AVP 0
41 | a=rtpmap:0 PCMU/8000
42 | - |+
43 | SIP/2.0 180 Ringing
44 | Via: SIP/2.0/TCP client.atlanta.example.com:5060;branch=z9hG4bK74bf9
45 | ;received=192.0.2.101
46 | From: Alice ;tag=9fxced76sl
47 | To: Bob ;tag=8321234356
48 | Call-ID: 3848276298220188511@atlanta.example.com
49 | CSeq: 1 INVITE
50 | Contact:
51 | Content-Length: 0
52 |
53 | - |+
54 | SIP/2.0 200 OK
55 | Via: SIP/2.0/TCP client.atlanta.example.com:5060;branch=z9hG4bK74bf9
56 | ;received=192.0.2.101
57 | From: Alice ;tag=9fxced76sl
58 | To: Bob ;tag=8321234356
59 | Call-ID: 3848276298220188511@atlanta.example.com
60 | CSeq: 1 INVITE
61 | Contact:
62 | Content-Type: application/sdp
63 | Content-Length: 147
64 |
65 | v=0
66 | o=bob 2890844527 2890844527 IN IP4 client.biloxi.example.com
67 | s=-
68 | c=IN IP4 192.0.2.201
69 | t=0 0
70 | m=audio 3456 RTP/AVP 0
71 | a=rtpmap:0 PCMU/8000
72 | - |+
73 | ACK sip:bob@client.biloxi.example.com SIP/2.0
74 | Via: SIP/2.0/TCP client.atlanta.example.com:5060;branch=z9hG4bK74bd5
75 | Max-Forwards: 70
76 | From: Alice ;tag=9fxced76sl
77 | To: Bob ;tag=8321234356
78 | Call-ID: 3848276298220188511@atlanta.example.com
79 | CSeq: 1 ACK
80 | Content-Length: 0
81 |
82 | - |+
83 | BYE sip:alice@client.atlanta.example.com SIP/2.0
84 | Via: SIP/2.0/TCP client.biloxi.example.com:5060;branch=z9hG4bKnashds7
85 | Max-Forwards: 70
86 | From: Bob ;tag=8321234356
87 | To: Alice ;tag=9fxced76sl
88 | Call-ID: 3848276298220188511@atlanta.example.com
89 | CSeq: 1 BYE
90 | Content-Length: 0
91 |
92 | - |+
93 | SIP/2.0 200 OK
94 | Via: SIP/2.0/TCP client.biloxi.example.com:5060;branch=z9hG4bKnashds7
95 | ;received=192.0.2.201
96 | From: Bob ;tag=8321234356
97 | To: Alice ;tag=9fxced76sl
98 | Call-ID: 3848276298220188511@atlanta.example.com
99 | CSeq: 1 BYE
100 | Content-Length: 0
101 |
102 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/3.2_single-registrar-and-ua.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 3.2. Single Registrar and UA
3 | #
4 | # +-----------+
5 | # | Registrar |
6 | # | Proxy |
7 | # +-----+-----+
8 | # |
9 | # |
10 | # +----+--+
11 | # | User |
12 | # | Agent |
13 | # +-------+
14 | # Note: this has been tampered with ... the semicolon after reg-id=1 was been removed
15 | # to comply with the general spec (also, demonstrated in https://tools.ietf.org/html/rfc4475#section-3.1.2.1)
16 | - |+
17 | REGISTER sip:example.com SIP/2.0
18 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bK-bad0ce-11-1036
19 | Max-Forwards: 70
20 | From: Bob ;tag=d879h76
21 | To: Bob
22 | Call-ID: 8921348ju72je840.204
23 | CSeq: 1 REGISTER
24 | Supported: path, outbound
25 | Contact: ; reg-id=1
26 | ;+sip.instance=""
27 | Content-Length: 0
28 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/9.1_subscription-to-configuration-package.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 9.1. Subscription to Configuration Package
3 | #
4 | # [----example.com domain-------------------------]
5 | # Bob EP1 EP2 Proxy Config
6 | # | | | | |
7 | # 1)|SUBSCRIBE->| | | |
8 | # 2)| |---SUBSCRIBE Event: ua-profile ->|
9 | # 3)| |<--200 OK -----------------------|
10 | # 4)|<--200 OK--| | | |
11 | # 5)| |<--NOTIFY------------------------|
12 | # 6)|<--NOTIFY--| | | |
13 | # 7)|---200 OK->| | | |
14 | # 8)| |---200 OK ---------------------->|
15 | # | | | | |
16 | - |+
17 | SUBSCRIBE sip:00000000-0000-1000-8000-AABBCCDDEEFF@example.com SIP/2.0
18 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bKnlsdkdj2
19 | Max-Forwards: 70
20 | From: ;tag=23324
21 | To:
22 | Call-ID: nSz1TWN54x7My0GvpEBj
23 | CSeq: 1 SUBSCRIBE
24 | Event: ua-profile ;profile-type=device
25 | ;vendor="example.com";model="uPhone";version="1.1"
26 | Expires: 0
27 | Supported: path, outbound
28 | Accept: message/external-body, application/x-uPhone-config
29 | Contact:
30 | ;+sip.instance=""
31 | Content-Length: 0
32 |
33 | - |+
34 | NOTIFY sip:192.0.2.2;transport=tcp;ob SIP/2.0
35 | Via: SIP/2.0/TCP 192.0.2.5;branch=z9hG4bKn81dd2
36 | Max-Forwards: 70
37 | To: ;tag=23324
38 | From: ;tag=0983
39 | Call-ID: nSz1TWN54x7My0GvpEBj
40 | CSeq: 1 NOTIFY
41 | Route:
42 | Subscription-State: terminated;reason=timeout
43 | Event: ua-profile
44 | Content-Type: message/external-body; access-type="URL"
45 | ;expiration="Thu, 01 Jan 2009 09:00:00 UTC"
46 | ;URL="http://example.com/uPhone.cfg"
47 | ;size=9999;hash=10AB568E91245681AC1B
48 | Content-Length: 0
49 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/9.2_registration.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 9.2. Registration
3 | #
4 | # Bob EP1 EP2 Proxy Alice
5 | # | | | | |
6 | # 9)|-REGISTER->| | | |
7 | # 10)| |---REGISTER-->| |
8 | # 11)| |<----200 OK---| |
9 | # 12)|<-200 OK---| | | |
10 | # 13)|----REGISTER---->| | |
11 | # 14)| | |--REG-->| |
12 | # 15)| | |<-200---| |
13 | # 16)|<----200 OK------| | |
14 | # | | | | |
15 | # | about 120 seconds later... |
16 | # | | | | |
17 | # 17)|--2CRLF--->| | | |
18 | # 18)|<--CRLF----| | | |
19 | # 19)|------2CRLF----->| | |
20 | # 20)|<------CRLF------| | |
21 | # | | | | |
22 | - |+
23 | REGISTER sip:example.com SIP/2.0
24 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bKnashds7
25 | Max-Forwards: 70
26 | From: Bob ;tag=7F94778B653B
27 | To: Bob
28 | Call-ID: 16CB75F21C70
29 | CSeq: 1 REGISTER
30 | Supported: path, outbound
31 | Route:
32 | Contact: ;reg-id=1
33 | ;+sip.instance=""
34 | Content-Length: 0
35 |
36 | - |+
37 | SIP/2.0 200 OK
38 | Via: SIP/2.0/TCP 192.0.2.15;branch=z9hG4bKnuiqisi
39 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bKnashds7
40 | From: Bob ;tag=7F94778B653B
41 | To: Bob ;tag=6AF99445E44A
42 | Call-ID: 16CB75F21C70
43 | CSeq: 1 REGISTER
44 | Supported: path, outbound
45 | Require: outbound
46 | Contact: ;reg-id=1;expires=3600
47 | ;+sip.instance=""
48 | Path:
49 | Content-Length: 0
50 |
51 | - |+
52 | REGISTER sip:example.com SIP/2.0
53 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bKnqr9bym
54 | Max-Forwards: 70
55 | From: Bob ;tag=755285EABDE2
56 | To: Bob
57 | Call-ID: E05133BD26DD
58 | CSeq: 1 REGISTER
59 | Supported: path, outbound
60 | Route:
61 | Contact: ;reg-id=2
62 | ;+sip.instance=""
63 | Content-Length: 0
64 |
65 | - |+
66 | SIP/2.0 200 OK
67 | Via: SIP/2.0/TCP 192.0.2.2;branch=z9hG4bKnqr9bym
68 | From: Bob ;tag=755285EABDE2
69 | To: Bob ;tag=49A9AD0B3F6A
70 | Call-ID: E05133BD26DD
71 | Supported: path, outbound
72 | Require: outbound
73 | CSeq: 1 REGISTER
74 | Contact: ;reg-id=1;expires=3600
75 | ;+sip.instance=""
76 | Contact: ;reg-id=2;expires=3600
77 | ;+sip.instance=""
78 | Path:
79 | Content-Length: 0
80 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/9.3_incoming_call_and_proxy_crash.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 9.3. Incoming Call and Proxy Crash
3 | #
4 | # Bob EP1 EP2 Proxy Alice
5 | # | | | | |
6 | # | CRASH X | | |
7 | # | Reboot | | |
8 | # | | | | |
9 | # 21)| | | |<-INVITE-|
10 | # 22)| |<---INVITE----| |
11 | # 23)| |----430------>| |
12 | # 24)| | |<-INVITE| |
13 | # 25)|<---INVITE-------| | |
14 | # 26)|----200 OK------>| | |
15 | # 27)| | |200 OK->| |
16 | # 28)| | | |-200 OK->|
17 | # 29)| | |<----------ACK----|
18 | # 30)|<---ACK----------| | |
19 | # | | | | |
20 | # 31)| | |<----------BYE----|
21 | # 32)|<---BYE----------| | |
22 | # 33)|----200 OK------>| | |
23 | # 34)| | |--------200 OK--->|
24 | # | | | | |
25 | - |+
26 | INVITE sip:bob@example.com SIP/2.0
27 | To: Bob
28 | From: Alice ;tag=02935
29 | Call-ID: klmvCxVWGp6MxJp2T2mb
30 | CSeq: 1 INVITE
31 |
32 | - |+
33 | INVITE sip:bob@192.0.2.2;transport=tcp SIP/2.0
34 | To: Bob
35 | From: Alice ;tag=02935
36 | Call-ID: klmvCxVWGp6MxJp2T2mb
37 | CSeq: 1 INVITE
38 | Route:
39 |
40 | - |+
41 | SIP/2.0 430 Flow Failed
42 | To: Bob
43 | From: Alice ;tag=02935
44 | Call-ID: klmvCxVWGp6MxJp2T2mb
45 | CSeq: 1 INVITE
46 |
47 | - |+
48 | INVITE sip:bob@192.0.2.2;transport=tcp SIP/2.0
49 | To: Bob
50 | From: Alice ;tag=02935
51 | Call-ID: klmvCxVWGp6MxJp2T2mb
52 | CSeq: 1 INVITE
53 | Route:
54 |
55 | - |+
56 | INVITE sip:bob@192.0.2.2;transport=tcp SIP/2.0
57 | To: Bob
58 | From: Alice ;tag=02935
59 | Call-ID: klmvCxVWGp6MxJp2T2mb
60 | CSeq: 1 INVITE
61 | Record-Route:
62 |
63 | - |+
64 | SIP/2.0 200 OK
65 | To: Bob ;tag=skduk2
66 | From: Alice ;tag=02935
67 | Call-ID: klmvCxVWGp6MxJp2T2mb
68 | CSeq: 1 INVITE
69 | Record-Route:
70 |
71 | - |+
72 | ACK sip:bob@192.0.2.2;transport=tcp SIP/2.0
73 | To: Bob ;tag=skduk2
74 | From: Alice ;tag=02935
75 | Call-ID: klmvCxVWGp6MxJp2T2mb
76 | CSeq: 1 ACK
77 | Route:
78 |
79 | - |+
80 | BYE sip:bob@192.0.2.2;transport=tcp SIP/2.0
81 | To: Bob ;tag=skduk2
82 | From: Alice ;tag=02935
83 | Call-ID: klmvCxVWGp6MxJp2T2mb
84 | CSeq: 2 BYE
85 | Route:
86 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/9.4_re-registration.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 9.4. Re-Registration
3 | #
4 | # Bob EP1 EP2 Proxy Alice
5 | # | | | | |
6 | # 35)|------2CRLF----->| | |
7 | # 36)|<------CRLF------| | |
8 | # 37)|--2CRLF->X | | | |
9 | # | | | | |
10 | # 38)|-REGISTER->| | | |
11 | # 39)| |---REGISTER-->| |
12 | # 40)| |<----200 OK---| |
13 | # 41)|<-200 OK---| | | |
14 | # | | | | |
15 | - |+
16 | REGISTER sip:example.com SIP/2.0
17 | From: Bob ;tag=7F94778B653B
18 | To: Bob
19 | Call-ID: 16CB75F21C70
20 | CSeq: 2 REGISTER
21 | Supported: path, outbound
22 | Route:
23 | Contact: ;reg-id=1
24 | ;+sip.instance=""
25 |
--------------------------------------------------------------------------------
/tests/fixtures/misc/rfc5626/9.5_outgoing_call.yaml:
--------------------------------------------------------------------------------
1 | # https://tools.ietf.org/html/rfc5626
2 | # 9.5. Outgoing Call
3 | #
4 | # Bob EP1 EP2 Proxy Alice
5 | # | | | | |
6 | # 42)|--INVITE-->| | | |
7 | # 43)| |---INVITE---->| |
8 | # 44)| | | |-INVITE->|
9 | # 45)| | | |<--200---|
10 | # 46)| |<----200 OK---| |
11 | # 47)|<-200 OK---| | | |
12 | # 48)|--ACK----->| | | |
13 | # 49)| |-----ACK--------------->|
14 | # | | | | |
15 | # 50)|-- BYE---->| | | |
16 | # 51)| |-----------BYE--------->|
17 | # 52)| |<----------200 OK-------|
18 | # 53)|<--200 OK--| | | |
19 | # | | | | |
20 | - |+
21 | INVITE sip:alice@a.example SIP/2.0
22 | From: Bob ;tag=ldw22z
23 | To: Alice
24 | Call-ID: 95KGsk2V/Eis9LcpBYy3
25 | CSeq: 1 INVITE
26 | Route:
27 | Contact:
28 |
29 | - |+
30 | BYE sip:alice@a.example SIP/2.0
31 | From: Bob ;tag=ldw22z
32 | To: Alice ;tag=plqus8
33 | Call-ID: 95KGsk2V/Eis9LcpBYy3
34 | CSeq: 2 BYE
35 | Route:
36 | Contact:
37 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/badaspec.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.org SIP/2.0
2 | Via: SIP/2.0/UDP host4.example.com:5060;branch=z9hG4bKkdju43234
3 | Max-Forwards: 70
4 | From: "Bell, Alexander" ;tag=433423
5 | To: "Watson, Thomas" < sip:t.watson@example.org >
6 | Call-ID: badaspec.sdf0234n2nds0a099u23h3hnnw009cdkne3
7 | Accept: application/sdp
8 | CSeq: 3923239 OPTIONS
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/badbranch.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.org;tag=33242
4 | Max-Forwards: 3
5 | Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bK
6 | Accept: application/sdp
7 | Call-ID: badbranch.sadonfo23i420jv0as0derf3j3n
8 | CSeq: 8 OPTIONS
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/baddate.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=2234923
4 | Max-Forwards: 70
5 | Call-ID: baddate.239423mnsadf3j23lj42--sedfnm234
6 | CSeq: 1392934 INVITE
7 | Via: SIP/2.0/UDP host.example.com;branch=z9hG4bKkdjuw
8 | Date: Fri, 01 Jan 2010 16:00:00 EST
9 | Contact:
10 | Content-Type: application/sdp
11 | Content-Length: 150
12 |
13 | v=0
14 | o=mhandley 29739 7272939 IN IP4 192.0.2.5
15 | s=-
16 | c=IN IP4 192.0.2.5
17 | t=0 0
18 | m=audio 49217 RTP/AVP 0 12
19 | m=video 3227 RTP/AVP 31
20 | a=rtpmap:31 LPC
21 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/baddn.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:t.watson@example.org SIP/2.0
2 | Via: SIP/2.0/UDP c.example.com:5060;branch=z9hG4bKkdjuw
3 | Max-Forwards: 70
4 | From: Bell, Alexander ;tag=43
5 | To: Watson, Thomas
6 | Call-ID: baddn.31415@c.example.com
7 | Accept: application/sdp
8 | CSeq: 3923239 OPTIONS
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/badinv01.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | To: sip:j.user@example.com
3 | From: sip:caller@example.net;tag=134161461246
4 | Max-Forwards: 7
5 | Call-ID: badinv01.0ha0isndaksdjasdf3234nas
6 | CSeq: 8 INVITE
7 | Via: SIP/2.0/UDP 192.0.2.15;;,;,,
8 | Contact: "Joe" ;;;;
9 | Content-Length: 152
10 | Content-Type: application/sdp
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.15
14 | s=-
15 | c=IN IP4 192.0.2.15
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/badvers.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:t.watson@example.org SIP/7.0
2 | Via: SIP/7.0/UDP c.example.com;branch=z9hG4bKkdjuw
3 | Max-Forwards: 70
4 | From: A. Bell ;tag=qweoiqpe
5 | To: T. Watson
6 | Call-ID: badvers.31417@c.example.com
7 | CSeq: 1 OPTIONS
8 | l: 0
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/bcast.dat:
--------------------------------------------------------------------------------
1 | SIP/2.0 200 OK
2 | Via: SIP/2.0/UDP 192.0.2.198;branch=z9hG4bK1324923
3 | Via: SIP/2.0/UDP 255.255.255.255;branch=z9hG4bK1saber23
4 | Call-ID: bcast.0384840201234ksdfak3j2erwedfsASdf
5 | CSeq: 35 INVITE
6 | From: sip:user@example.com;tag=11141343
7 | To: sip:user@example.edu;tag=2229
8 | Content-Length: 154
9 | Content-Type: application/sdp
10 | Contact:
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.198
14 | s=-
15 | c=IN IP4 192.0.2.198
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/bext01.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:j_user@example.com
3 | From: sip:caller@example.net;tag=242etr
4 | Max-Forwards: 6
5 | Call-ID: bext01.0ha0isndaksdj
6 | Require: nothingSupportsThis, nothingSupportsThisEither
7 | Proxy-Require: noProxiesSupportThis, norDoAnyProxiesSupportThis
8 | CSeq: 8 OPTIONS
9 | Via: SIP/2.0/TLS fold-and-staple.example.com;branch=z9hG4bKkdjuw
10 | Content-Length: 0
11 |
12 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/bigcode.dat:
--------------------------------------------------------------------------------
1 | SIP/2.0 4294967301 better not break the receiver
2 | Via: SIP/2.0/UDP 192.0.2.105;branch=z9hG4bK2398ndaoe
3 | Call-ID: bigcode.asdof3uj203asdnf3429uasdhfas3ehjasdfas9i
4 | CSeq: 353494 INVITE
5 | From: ;tag=39ansfi3
6 | To: ;tag=902jndnke3
7 | Content-Length: 0
8 | Contact:
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/clerr.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | Max-Forwards: 80
3 | To: sip:j.user@example.com
4 | From: sip:caller@example.net;tag=93942939o2
5 | Contact:
6 | Call-ID: clerr.0ha0isndaksdjweiafasdk3
7 | CSeq: 8 INVITE
8 | Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bK-39234-23523
9 | Content-Type: application/sdp
10 | Content-Length: 9999
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.155
14 | s=-
15 | c=IN IP4 192.0.2.155
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/cparam01.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | Via: SIP/2.0/UDP saturn.example.com:5060;branch=z9hG4bKkdjuw
3 | Max-Forwards: 70
4 | From: sip:watson@example.com;tag=DkfVgjkrtMwaerKKpe
5 | To: sip:watson@example.com
6 | Call-ID: cparam01.70710@saturn.example.com
7 | CSeq: 2 REGISTER
8 | Contact: sip:+19725552222@gw1.example.net;unknownparam
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/cparam02.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | Via: SIP/2.0/UDP saturn.example.com:5060;branch=z9hG4bKkdjuw
3 | Max-Forwards: 70
4 | From: sip:watson@example.com;tag=838293
5 | To: sip:watson@example.com
6 | Call-ID: cparam02.70710@saturn.example.com
7 | CSeq: 3 REGISTER
8 | Contact:
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/dblreq.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: sip:j.user@example.com
3 | From: sip:j.user@example.com;tag=43251j3j324
4 | Max-Forwards: 8
5 | I: dblreq.0ha0isndaksdj99sdfafnl3lk233412
6 | Contact: sip:j.user@host.example.com
7 | CSeq: 8 REGISTER
8 | Via: SIP/2.0/UDP 192.0.2.125;branch=z9hG4bKkdjuw23492
9 | Content-Length: 0
10 |
11 |
12 | INVITE sip:joe@example.com SIP/2.0
13 | t: sip:joe@example.com
14 | From: sip:caller@example.net;tag=141334
15 | Max-Forwards: 8
16 | Call-ID: dblreq.0ha0isnda977644900765@192.0.2.15
17 | CSeq: 8 INVITE
18 | Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw380234
19 | Content-Type: application/sdp
20 | Content-Length: 150
21 |
22 | v=0
23 | o=mhandley 29739 7272939 IN IP4 192.0.2.15
24 | s=-
25 | c=IN IP4 192.0.2.15
26 | t=0 0
27 | m=audio 49217 RTP/AVP 0 12
28 | m =video 3227 RTP/AVP 31
29 | a=rtpmap:31 LPC
30 |
31 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/esc01.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0
2 | To: sip:%75se%72@example.com
3 | From: ;tag=938
4 | Max-Forwards: 87
5 | i: esc01.239409asdfakjkn23onasd0-3234
6 | CSeq: 234234 INVITE
7 | Via: SIP/2.0/UDP host5.example.net;branch=z9hG4bKkdjuw
8 | C: application/sdp
9 | Contact:
10 |
11 | Content-Length: 150
12 |
13 | v=0
14 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
15 | s=-
16 | c=IN IP4 192.0.2.1
17 | t=0 0
18 | m=audio 49217 RTP/AVP 0 12
19 | m=video 3227 RTP/AVP 31
20 | a=rtpmap:31 LPC
21 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/esc02.dat:
--------------------------------------------------------------------------------
1 | RE%47IST%45R sip:registrar.example.com SIP/2.0
2 | To: "%Z%45"
3 | From: "%Z%45" ;tag=f232jadfj23
4 | Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf
5 | Via: SIP/2.0/TCP host.example.com;branch=z9hG4bK209%fzsnel234
6 | CSeq: 29344 RE%47IST%45R
7 | Max-Forwards: 70
8 | Contact:
9 | C%6Fntact:
10 | Contact:
11 | l: 0
12 |
13 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/escnull.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: sip:null-%00-null@example.com
3 | From: sip:null-%00-null@example.com;tag=839923423
4 | Max-Forwards: 70
5 | Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd
6 | CSeq: 14398234 REGISTER
7 | Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw
8 | Contact:
9 | Contact:
10 | L:0
11 |
12 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/escruri.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com?Route=%3Csip:example.com%3E SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=341518
4 | Max-Forwards: 7
5 | Contact:
6 | Call-ID: escruri.23940-asdfhj-aje3br-234q098w-fawerh2q-h4n5
7 | CSeq: 149209342 INVITE
8 | Via: SIP/2.0/UDP host-of-the-hour.example.com;branch=z9hG4bKkdjuw
9 | Content-Type: application/sdp
10 | Content-Length: 150
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
14 | s=-
15 | c=IN IP4 192.0.2.1
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/insuf.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | CSeq: 193942 INVITE
3 | Via: SIP/2.0/UDP 192.0.2.95;branch=z9hG4bKkdj.insuf
4 | Content-Type: application/sdp
5 | l: 152
6 |
7 | v=0
8 | o=mhandley 29739 7272939 IN IP4 192.0.2.95
9 | s=-
10 | c=IN IP4 192.0.2.95
11 | t=0 0
12 | m=audio 49217 RTP/AVP 0 12
13 | m=video 3227 RTP/AVP 31
14 | a=rtpmap:31 LPC
15 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/intmeth.dat:
--------------------------------------------------------------------------------
1 | !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
2 | Via: SIP/2.0/TCP host1.example.com;branch=z9hG4bK-.!%66*_+`'~
3 | To: "BEL:\ NUL:\ DEL:\"
4 | From: token1~` token2'+_ token3*%!.- ;fromParam''~+*_!.-%="работающий";tag=_token~1'+`*%!-.
5 | Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\/"][?}{
6 | CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~
7 | Max-Forwards: 255
8 | extensionHeader-!.%*+_`'~:大停電
9 | Content-Length: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/inv2543.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:UserB@example.com SIP/2.0
2 | Via: SIP/2.0/UDP iftgw.example.com
3 | From:
4 | Record-Route:
5 | To: sip:+16505552222@ss1.example.net;user=phone
6 | Call-ID: inv2543.1717@ift.client.example.com
7 | CSeq: 56 INVITE
8 | Content-Type: application/sdp
9 |
10 | v=0
11 | o=mhandley 29739 7272939 IN IP4 192.0.2.5
12 | s=-
13 | c=IN IP4 192.0.2.5
14 | t=0 0
15 | m=audio 49217 RTP/AVP 0
16 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/invut.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | Contact:
3 | To: sip:j.user@example.com
4 | From: sip:caller@example.net;tag=8392034
5 | Max-Forwards: 70
6 | Call-ID: invut.0ha0isndaksdjadsfij34n23d
7 | CSeq: 235448 INVITE
8 | Via: SIP/2.0/UDP somehost.example.com;branch=z9hG4bKkdjuw
9 | Content-Type: application/unknownformat
10 | Content-Length: 40
11 |
12 |
15 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/longreq.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | To: "I have a user name of extremeextremeextremeextremeextremeextremeextremeextremeextremeextreme proportion"
3 | F: sip:amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername@example.net;tag=12982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982424;unknownheaderparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename=unknowheaderparamvaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevalue;unknownValuelessparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamname
4 | Call-ID: longreq.onereallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongcallid
5 | CSeq: 3882340 INVITE
6 | Unknown-LongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLong-Name: unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-value; unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-name = unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-value
7 | Via: SIP/2.0/TCP sip33.example.com
8 | v: SIP/2.0/TCP sip32.example.com
9 | V: SIP/2.0/TCP sip31.example.com
10 | Via: SIP/2.0/TCP sip30.example.com
11 | ViA: SIP/2.0/TCP sip29.example.com
12 | VIa: SIP/2.0/TCP sip28.example.com
13 | VIA: SIP/2.0/TCP sip27.example.com
14 | via: SIP/2.0/TCP sip26.example.com
15 | viA: SIP/2.0/TCP sip25.example.com
16 | vIa: SIP/2.0/TCP sip24.example.com
17 | vIA: SIP/2.0/TCP sip23.example.com
18 | V : SIP/2.0/TCP sip22.example.com
19 | v : SIP/2.0/TCP sip21.example.com
20 | V : SIP/2.0/TCP sip20.example.com
21 | v : SIP/2.0/TCP sip19.example.com
22 | Via : SIP/2.0/TCP sip18.example.com
23 | Via : SIP/2.0/TCP sip17.example.com
24 | Via: SIP/2.0/TCP sip16.example.com
25 | Via: SIP/2.0/TCP sip15.example.com
26 | Via: SIP/2.0/TCP sip14.example.com
27 | Via: SIP/2.0/TCP sip13.example.com
28 | Via: SIP/2.0/TCP sip12.example.com
29 | Via: SIP/2.0/TCP sip11.example.com
30 | Via: SIP/2.0/TCP sip10.example.com
31 | Via: SIP/2.0/TCP sip9.example.com
32 | Via: SIP/2.0/TCP sip8.example.com
33 | Via: SIP/2.0/TCP sip7.example.com
34 | Via: SIP/2.0/TCP sip6.example.com
35 | Via: SIP/2.0/TCP sip5.example.com
36 | Via: SIP/2.0/TCP sip4.example.com
37 | Via: SIP/2.0/TCP sip3.example.com
38 | Via: SIP/2.0/TCP sip2.example.com
39 | Via: SIP/2.0/TCP sip1.example.com
40 | Via: SIP/2.0/TCP host.example.com;received=192.0.2.5;branch=verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongbranchvalue
41 | Max-Forwards: 70
42 | Contact:
43 | Content-Type: application/sdp
44 | l: 150
45 |
46 | v=0
47 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
48 | s=-
49 | c=IN IP4 192.0.2.1
50 | t=0 0
51 | m=audio 49217 RTP/AVP 0 12
52 | m=video 3227 RTP/AVP 31
53 | a=rtpmap:31 LPC
54 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/ltgtruri.dat:
--------------------------------------------------------------------------------
1 | INVITE SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=39291
4 | Max-Forwards: 23
5 | Call-ID: ltgtruri.1@192.0.2.5
6 | CSeq: 1 INVITE
7 | Via: SIP/2.0/UDP 192.0.2.5
8 | Contact:
9 | Content-Type: application/sdp
10 | Content-Length: 159
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.5
14 | s=-
15 | c=IN IP4 192.0.2.5
16 | t=3149328700 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/lwsdisp.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: caller;tag=323
4 | Max-Forwards: 70
5 | Call-ID: lwsdisp.1234abcd@funky.example.com
6 | CSeq: 60 OPTIONS
7 | Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw
8 | l: 0
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/lwsruri.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com; lr SIP/2.0
2 | To: sip:user@example.com;tag=3xfe-9921883-z9f
3 | From: sip:caller@example.net;tag=231413434
4 | Max-Forwards: 5
5 | Call-ID: lwsruri.asdfasdoeoi2323-asdfwrn23-asd834rk423
6 | CSeq: 2130706432 INVITE
7 | Via: SIP/2.0/UDP 192.0.2.1:5060;branch=z9hG4bKkdjuw2395
8 | Contact:
9 | Content-Type: application/sdp
10 | Content-Length: 159
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
14 | s=-
15 | c=IN IP4 192.0.2.1
16 | t=3149328700 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/lwsstart.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | Max-Forwards: 8
3 | To: sip:user@example.com
4 | From: sip:caller@example.net;tag=8814
5 | Call-ID: lwsstart.dfknq234oi243099adsdfnawe3@example.com
6 | CSeq: 1893884 INVITE
7 | Via: SIP/2.0/UDP host1.example.com;branch=z9hG4bKkdjuw3923
8 | Contact:
9 | Content-Type: application/sdp
10 | Content-Length: 150
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
14 | s=-
15 | c=IN IP4 192.0.2.1
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/mcl01.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | Via: SIP/2.0/UDP host5.example.net;branch=z9hG4bK293423
3 | To: sip:user@example.com
4 | From: sip:other@example.net;tag=3923942
5 | Call-ID: mcl01.fhn2323orihawfdoa3o4r52o3irsdf
6 | CSeq: 15932 OPTIONS
7 | Content-Length: 13
8 | Max-Forwards: 60
9 | Content-Length: 5
10 | Content-Type: text/plain
11 |
12 | There's no way to know how many octets are supposed to be here.
13 |
14 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/mismatch01.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:j.user@example.com
3 | From: sip:caller@example.net;tag=34525
4 | Max-Forwards: 6
5 | Call-ID: mismatch01.dj0234sxdfl3
6 | CSeq: 8 INVITE
7 | Via: SIP/2.0/UDP host.example.com;branch=z9hG4bKkdjuw
8 | l: 0
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/mismatch02.dat:
--------------------------------------------------------------------------------
1 | NEWMETHOD sip:user@example.com SIP/2.0
2 | To: sip:j.user@example.com
3 | From: sip:caller@example.net;tag=34525
4 | Max-Forwards: 6
5 | Call-ID: mismatch02.dj0234sxdfl3
6 | CSeq: 8 INVITE
7 | Contact:
8 | Via: SIP/2.0/UDP host.example.net;branch=z9hG4bKkdjuw
9 | Content-Type: application/sdp
10 | l: 138
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.1
14 | c=IN IP4 192.0.2.1
15 | m=audio 49217 RTP/AVP 0 12
16 | m=video 3227 RTP/AVP 31
17 | a=rtpmap:31 LPC
18 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/mpart01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rtckit/php-sip/7e931877d45c5c64771c09393408ca04c0f5caa6/tests/fixtures/rfc4475/mpart01.dat
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/multi01.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@company.com SIP/2.0
2 | Contact:
3 | Via: SIP/2.0/UDP 192.0.2.25;branch=z9hG4bKkdjuw
4 | Max-Forwards: 70
5 | CSeq: 5 INVITE
6 | Call-ID: multi01.98asdh@192.0.2.1
7 | CSeq: 59 INVITE
8 | Call-ID: multi01.98asdh@192.0.2.2
9 | From: sip:caller@example.com;tag=3413415
10 | To: sip:user@example.com
11 | To: sip:other@example.net
12 | From: sip:caller@example.net;tag=2923420123
13 | Content-Type: application/sdp
14 | l: 154
15 | Contact:
16 | Max-Forwards: 5
17 |
18 | v=0
19 | o=mhandley 29739 7272939 IN IP4 192.0.2.25
20 | s=-
21 | c=IN IP4 192.0.2.25
22 | t=0 0
23 | m=audio 49217 RTP/AVP 0 12
24 | m=video 3227 RTP/AVP 31
25 | a=rtpmap:31 LPC
26 |
27 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/ncl.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | Max-Forwards: 254
3 | To: sip:j.user@example.com
4 | From: sip:caller@example.net;tag=32394234
5 | Call-ID: ncl.0ha0isndaksdj2193423r542w35
6 | CSeq: 0 INVITE
7 | Via: SIP/2.0/UDP 192.0.2.53;branch=z9hG4bKkdjuw
8 | Contact:
9 | Content-Type: application/sdp
10 | Content-Length: -999
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.53
14 | s=-
15 | c=IN IP4 192.0.2.53
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/noreason.dat:
--------------------------------------------------------------------------------
1 | SIP/2.0 100
2 | Via: SIP/2.0/UDP 192.0.2.105;branch=z9hG4bK2398ndaoe
3 | Call-ID: noreason.asndj203insdf99223ndf
4 | CSeq: 35 INVITE
5 | From: ;tag=39ansfi3
6 | To: ;tag=902jndnke3
7 | Content-Length: 0
8 | Contact:
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/novelsc.dat:
--------------------------------------------------------------------------------
1 | OPTIONS soap.beep://192.0.2.103:3002 SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=384
4 | Max-Forwards: 3
5 | Call-ID: novelsc.asdfasser0q239nwsdfasdkl34
6 | CSeq: 3923423 OPTIONS
7 | Via: SIP/2.0/TCP host9.example.com;branch=z9hG4bKkdjuw39234
8 | Content-Length: 0
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/quotbal.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | To: "Mr. J. User
3 | From: sip:caller@example.net;tag=93334
4 | Max-Forwards: 10
5 | Call-ID: quotbal.aksdj
6 | Contact:
7 | CSeq: 8 INVITE
8 | Via: SIP/2.0/UDP 192.0.2.59:5050;branch=z9hG4bKkdjuw39234
9 | Content-Type: application/sdp
10 | Content-Length: 152
11 |
12 | v=0
13 | o=mhandley 29739 7272939 IN IP4 192.0.2.15
14 | s=-
15 | c=IN IP4 192.0.2.15
16 | t=0 0
17 | m=audio 49217 RTP/AVP 0 12
18 | m=video 3227 RTP/AVP 31
19 | a=rtpmap:31 LPC
20 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/regaut01.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: sip:j.user@example.com
3 | From: sip:j.user@example.com;tag=87321hj23128
4 | Max-Forwards: 8
5 | Call-ID: regaut01.0ha0isndaksdj
6 | CSeq: 9338 REGISTER
7 | Via: SIP/2.0/TCP 192.0.2.253;branch=z9hG4bKkdjuw
8 | Authorization: NoOneKnowsThisScheme opaque-data=here
9 | Content-Length:0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/regbadct.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:user@example.com;tag=998332
4 | Max-Forwards: 70
5 | Call-ID: regbadct.k345asrl3fdbv@10.0.0.1
6 | CSeq: 1 REGISTER
7 | Via: SIP/2.0/UDP 135.180.130.133:5060;branch=z9hG4bKkdjuw
8 | Contact: sip:user@example.com?Route=%3Csip:sip.example.com%3E
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/regescrt.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:user@example.com;tag=8
4 | Max-Forwards: 70
5 | Call-ID: regescrt.k345asrl3fdbv@192.0.2.1
6 | CSeq: 14398234 REGISTER
7 | Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw
8 | M:
9 | L:0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/scalar02.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | Via: SIP/2.0/TCP host129.example.com;branch=z9hG4bK342sdfoi3
3 | To:
4 | From: ;tag=239232jh3
5 | CSeq: 36893488147419103232 REGISTER
6 | Call-ID: scalar02.23o0pd9vanlq3wnrlnewofjas9ui32
7 | Max-Forwards: 300
8 | Expires: 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
9 | Contact:
10 | ;expires=280297596632815
11 | Content-Length: 0
12 |
13 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/scalarlg.dat:
--------------------------------------------------------------------------------
1 | SIP/2.0 503 Service Unavailable
2 | Via: SIP/2.0/TCP host129.example.com;branch=z9hG4bKzzxdiwo34sw;received=192.0.2.129
3 | To:
4 | From: ;tag=2easdjfejw
5 | CSeq: 9292394834772304023312 OPTIONS
6 | Call-ID: scalarlg.noase0of0234hn2qofoaf0232aewf2394r
7 | Retry-After: 949302838503028349304023988
8 | Warning: 1812 overture "In Progress"
9 | Content-Length: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/sdp01.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:user@example.com SIP/2.0
2 | To: sip:j_user@example.com
3 | Contact:
4 | From: sip:caller@example.net;tag=234
5 | Max-Forwards: 5
6 | Call-ID: sdp01.ndaksdj9342dasdd
7 | Accept: text/nobodyKnowsThis
8 | CSeq: 8 INVITE
9 | Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw
10 | Content-Length: 150
11 | Content-Type: application/sdp
12 |
13 | v=0
14 | o=mhandley 29739 7272939 IN IP4 192.0.2.5
15 | s=-
16 | c=IN IP4 192.0.2.5
17 | t=0 0
18 | m=audio 49217 RTP/AVP 0 12
19 | m=video 3227 RTP/AVP 31
20 | a=rtpmap:31 LPC
21 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/semiuri.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0
2 | To: sip:j_user@example.com
3 | From: sip:caller@example.org;tag=33242
4 | Max-Forwards: 3
5 | Call-ID: semiuri.0ha0isndaksdj
6 | CSeq: 8 OPTIONS
7 | Accept: application/sdp, application/pkcs7-mime,
8 | multipart/mixed, multipart/signed,
9 | message/sip, message/sipfrag
10 | Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw
11 | l: 0
12 |
13 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/test.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:alan@jasomi.com
2 | TO : alan@jasomi.com
3 | From: ralph@example.com
4 | MaX-fOrWaRdS: 0068
5 | Call-ID: test.0ha0isndaksdj@192.0.2.1
6 | Xyzzy-2: this is the number ten : 10
7 | Xyzzy-3: INVITE
8 | Xyzzy: 10000000000
9 | Meaning: foo bar spam
10 | Foobar roobar
11 | Content-Length: 18
12 | Content-Type: application/sdp
13 |
14 | v=0
15 | testing=123
16 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/transports.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: ;tag=323
4 | Max-Forwards: 70
5 | Call-ID: transports.kijh4akdnaqjkwendsasfdj
6 | Accept: application/sdp
7 | CSeq: 60 OPTIONS
8 | Via: SIP/2.0/UDP t1.example.com;branch=z9hG4bKkdjuw
9 | Via: SIP/2.0/SCTP t2.example.com;branch=z9hG4bKklasjdhf
10 | Via: SIP/2.0/TLS t3.example.com;branch=z9hG4bK2980unddj
11 | Via: SIP/2.0/UNKNOWN t4.example.com;branch=z9hG4bKasd0f3en
12 | Via: SIP/2.0/TCP t5.example.com;branch=z9hG4bK0a9idfnee
13 | l: 0
14 |
15 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/trws.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:remote-target@example.com SIP/2.0
2 | Via: SIP/2.0/TCP host1.examle.com;branch=z9hG4bK299342093
3 | To:
4 | From: ;tag=329429089
5 | Call-ID: trws.oicu34958239neffasdhr2345r
6 | Accept: application/sdp
7 | CSeq: 238923 OPTIONS
8 | Max-Forwards: 70
9 | Content-Length: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/unkscm.dat:
--------------------------------------------------------------------------------
1 | OPTIONS nobodyKnowsThisScheme:totallyopaquecontent SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=384
4 | Max-Forwards: 3
5 | Call-ID: unkscm.nasdfasser0q239nwsdfasdkl34
6 | CSeq: 3923423 OPTIONS
7 | Via: SIP/2.0/TCP host9.example.com;branch=z9hG4bKkdjuw39234
8 | Content-Length: 0
9 |
10 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/unksm2.dat:
--------------------------------------------------------------------------------
1 | REGISTER sip:example.com SIP/2.0
2 | To: isbn:2983792873
3 | From: ;tag=3234233
4 | Call-ID: unksm2.daksdj@hyphenated-host.example.com
5 | CSeq: 234902 REGISTER
6 | Max-Forwards: 70
7 | Via: SIP/2.0/UDP 192.0.2.21:5060;branch=z9hG4bKkdjuw
8 | Contact:
9 | l: 0
10 |
11 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/unreason.dat:
--------------------------------------------------------------------------------
1 | SIP/2.0 200 = 2**3 * 5**2 но сто девяносто девять - простое
2 | Via: SIP/2.0/UDP 192.0.2.198;branch=z9hG4bK1324923
3 | Call-ID: unreason.1234ksdfak3j2erwedfsASdf
4 | CSeq: 35 INVITE
5 | From: sip:user@example.com;tag=11141343
6 | To: sip:user@example.edu;tag=2229
7 | Content-Length: 154
8 | Content-Type: application/sdp
9 | Contact:
10 |
11 | v=0
12 | o=mhandley 29739 7272939 IN IP4 192.0.2.198
13 | s=-
14 | c=IN IP4 192.0.2.198
15 | t=0 0
16 | m=audio 49217 RTP/AVP 0 12
17 | m=video 3227 RTP/AVP 31
18 | a=rtpmap:31 LPC
19 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/wsinv.dat:
--------------------------------------------------------------------------------
1 | INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0
2 | TO :
3 | sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n
4 | from : "J Rosenberg \\\""
5 | ;
6 | tag = 98asjd8
7 | MaX-fOrWaRdS: 0068
8 | Call-ID: wsinv.ndaksdj@192.0.2.1
9 | Content-Length : 150
10 | cseq: 0009
11 | INVITE
12 | Via : SIP / 2.0
13 | /UDP
14 | 192.0.2.2;branch=390skdjuw
15 | s :
16 | NewFangledHeader: newfangled value
17 | continued newfangled value
18 | UnknownHeaderWithUnusualValue: ;;,,;;,;
19 | Content-Type: application/sdp
20 | Route:
21 |
22 | v: SIP / 2.0 / TCP spindle.example.com ;
23 | branch = z9hG4bK9ikj8 ,
24 | SIP / 2.0 / UDP 192.168.255.111 ; branch=
25 | z9hG4bK30239
26 | m:"Quoted string \"\"" ; newparam =
27 | newvalue ;
28 | secondparam ; q = 0.33
29 |
30 | v=0
31 | o=mhandley 29739 7272939 IN IP4 192.0.2.3
32 | s=-
33 | c=IN IP4 192.0.2.4
34 | t=0 0
35 | m=audio 49217 RTP/AVP 0 12
36 | m=video 3227 RTP/AVP 31
37 | a=rtpmap:31 LPC
38 |
--------------------------------------------------------------------------------
/tests/fixtures/rfc4475/zeromf.dat:
--------------------------------------------------------------------------------
1 | OPTIONS sip:user@example.com SIP/2.0
2 | To: sip:user@example.com
3 | From: sip:caller@example.net;tag=3ghsd41
4 | Call-ID: zeromf.jfasdlfnm2o2l43r5u0asdfas
5 | CSeq: 39234321 OPTIONS
6 | Via: SIP/2.0/UDP host1.example.com;branch=z9hG4bKkdjuw2349i
7 | Max-Forwards: 0
8 | Content-Length: 0
9 |
10 |
--------------------------------------------------------------------------------