rtckit/sip

PHP 编写的 SIP 协议实现

0.7.1 2023-05-22 14:24 UTC

This package is auto-updated.

Last update: 2024-09-22 17:37:01 UTC


README

php-sip

PHP SIP 解析/渲染库

符合 RFC 3261 的 PHP 7.4 SIP 解析和渲染库。

CI Status Psalm Type Coverage Latest Stable Version Installs on Packagist Test Coverage Maintainability License

快速入门

SIP 消息解析

安装后,您可以直接按照以下方式解析 SIP 消息

/*
 * $text holds your SIP message as a string, for example
 * $text = 'REGISTER sip:192.168.0.1 SIP/2.0 /.../';
 */
$message = \RTCKit\SIP\Message::parse($text);

/* Outputs "RTCKit\SIP\Request" */
echo get_class($message) . PHP_EOL;

/* Outputs something similar to:
 * Protocol version:   SIP/2.0
 * Request method:     REGISTER
 * Request URI:        sip:192.168.0.1
 * Via:                192.168.0.2:5050
 * Via branch:         z9hG4bK.eAV4o0nXr
 * From scheme:        sip
 * From user:          buzz
 * From host:          192.168.0.1
 * From tag:           SFJbQ2oWh
 * To scheme:          sip
 * To user:            buzz
 * To host:            192.168.0.1
 * Sequence number:    20
 * Call ID:            ob0EYyuyC0
 */
printf("Protocol version:   %s" . PHP_EOL, $message->version);
printf("Request method:     %s" . PHP_EOL, $message->method);
printf("Request URI:        %s" . PHP_EOL, $message->uri);
printf("Via:                %s" . PHP_EOL, $message->via->values[0]->host);
printf("Via branch:         %s" . PHP_EOL, $message->via->values[0]->branch);
printf("From scheme:        %s" . PHP_EOL, $request->from->uri->scheme);
printf("From user:          %s" . PHP_EOL, $request->from->uri->user);
printf("From host:          %s" . PHP_EOL, $request->from->uri->host);
printf("From tag:           %s" . PHP_EOL, $request->from->tag);
printf("To scheme:          %s" . PHP_EOL, $request->to->uri->scheme);
printf("To user:            %s" . PHP_EOL, $request->to->uri->user);
printf("To host:            %s" . PHP_EOL, $request->to->uri->host);
printf("Sequence number:    %s" . PHP_EOL, $message->cSeq->sequence);
printf("Call ID:            %s" . PHP_EOL, $message->callId->value);

SIP 消息渲染

渲染是解析的反操作;例如,让我们为 REGISTER 请求准备一个 200 OK 响应

$response = new \RTCKit\SIP\Response;
$response->version = 'SIP/2.0';
$response->code = 200;

$response->via = new \RTCKit\SIP\Header\ViaHeader;
$response->via->values[0] = new \RTCKit\SIP\Header\ViaValue;
$response->via->values[0]->protocol = 'SIP';
$response->via->values[0]->version = '2.0';
$response->via->values[0]->transport = 'UDP';
$response->via->values[0]->host = '192.168.0.2:5050';
$response->via->values[0]->branch = 'z9hG4bK.eAV4o0nXr';

$response->from = new \RTCKit\SIP\Header\NameAddrHeader;
$response->from->uri = new \RTCKit\SIP\URI;
$response->from->uri->scheme = 'sip';
$response->from->uri->user = 'buzz';
$response->from->uri->host = '192.168.0.1';
$response->from->tag = 'SFJbQ2oWh';

$response->to = new \RTCKit\SIP\Header\NameAddrHeader;
$response->to->uri = new \RTCKit\SIP\URI;
$response->to->uri->scheme = 'sip';
$response->to->uri->user = 'buzz';
$response->to->uri->host = '192.168.0.1';
$response->to->tag = '8cQtUyH6N5N9K';

$response->cSeq = new \RTCKit\SIP\Header\CSeqHeader;
$response->cSeq->sequence = 20;
$response->cSeq->method = 'REGISTER';

$response->callId = new \RTCKit\SIP\Header\CallIdHeader;
$response->callId->value = 'ob0EYyuyC0';

$response->maxForwards = new \RTCKit\SIP\Header\ScalarHeader;
$response->maxForwards->value = 70;

$response->contact = new \RTCKit\SIP\Header\ContactHeader;
$response->contact->values[0] = new \RTCKit\SIP\Header\ContactValue;
$response->contact->values[0]->uri = new \RTCKit\SIP\URI;
$response->contact->values[0]->uri->scheme = 'sip';
$response->contact->values[0]->uri->user = 'buzz';
$response->contact->values[0]->uri->host = '192.168.0.2';
$response->contact->values[0]->uri->port = 5050;
$response->contact->values[0]->uri->transport = 'udp';
$response->contact->values[0]->expires = 3600;

$response->userAgent = new \RTCKit\SIP\Header\Header;
$response->userAgent->values[0] = 'MyDeskPhone/1.0.0';

/* Outputs:
 * SIP/2.0 200 OK
 * Via: SIP/2.0/UDP 192.168.0.2:5050;branch=z9hG4bK.eAV4o0nXr
 * From: <sip:buzz@192.168.0.1>;tag=SFJbQ2oWh
 * To: <sip:buzz@192.168.0.1>;tag=8cQtUyH6N5N9K
 * Contact: <sip:buzz@192.168.0.2:5050;transport=udp>;expires=3600
 * Call-ID: ob0EYyuyC0
 * CSeq: 20 REGISTER
 * Max-Forwards: 70
 * User-Agent: MyDeskPhone/1.0.0
 */
echo $response->render();

SIP 消息流解析

如果您的用例涉及连续数据流而不是单个消息,则 StreamParser 类可以帮助您;这对于分析 SIP 跟踪文件或数据包捕获特别有用,例如解析 TCP 上的 SIP 流量等。

/* Instantiate the Stream Parser */
$parser = new \RTCKit\SIP\StreamParser;

$fp = fopen(/.../);

while (!feof($fp)) {
    $bytes = fread($fp, 256);

    /* The actual input string ($bytes) can be retrieved from any stream-like source */
    if ($parser->process($bytes, $messages) === \RTCKit\SIP\StreamParser::SUCCESS) {
        foreach ($messages as $message) {
            /*
             * $message is either a Request or a Response object, using
             * the same structure as messages returned by Message::parse()
             */
        }
    }
}

最后,提供的 示例 是一个很好的起点。

要求

RTCKit\SIP 与 PHP 7.4+ 兼容,没有外部库和扩展依赖。

安装

您可以使用 Composer 将库作为项目依赖项添加

composer require rtckit/sip

如果您只在开发期间需要库,例如在测试套件中使用,则应将其添加为仅开发依赖项

composer require --dev rtckit/sip

测试

要运行测试套件,请克隆此存储库,然后使用 Composer 安装依赖项

composer install

然后,转到项目根目录并运行

php -d memory_limit=-1 ./vendor/bin/phpunit -c ./etc/phpunit.xml.dist

静态分析

为了确保高代码质量,RTCKit\SIP 使用 PHPStanPsalm

php -d memory_limit=-1 ./vendor/bin/phpstan analyse -c ./etc/phpstan.neon -n -vvv --ansi --level=max src
php -d memory_limit=-1 ./vendor/bin/psalm --config=./etc/psalm.xml

许可

MIT,请参阅 LICENSE 文件

致谢

贡献

可以通过 问题跟踪器 提交错误报告(以及小型补丁)。对于重大补丁,建议您分支存储库并提交拉取请求。