hujiao-gui/app/Service/SwooleFreeswitch.php

276 lines
7.0 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Service;
/**
* Class SwooleFreeswitch
* @package App\Service
*/
class SwooleFreeswitch
{
/**
* @var Socket | null
*/
public $socket = null;
/**
* @var int
*/
protected $length = 0;
public function __construct()
{
$this->socket = new \Swoole\Coroutine\Socket(AF_INET, SOCK_STREAM, SOL_TCP);
$this->socket->setProtocol(['open_eof_check' => true, 'package_eof' => "\n"]);
}
/**
* 连接fs并认证
* @param string $host
* @param string $port
* @param string|null $password
* @return bool
*/
public function connect(?string $host = null, ?string $port = null, ?string $password = null)
{
$host = $host ?? config('freeswitch.esl.host');
$port = $port ?? config('freeswitch.esl.port');
$password = $password ?? config('freeswitch.esl.password');
$res = $this->socket->connect($host, $port);
if (!$res) return false;
$this->socket->bind($host, $port);
$socketInfoFirst = $this->socket->recv();
$socketInfoFirst = $this->eliminate($socketInfoFirst);
if ($socketInfoFirst == 'Content-Type:auth/request') {
$this->socket->send("auth " . $password . "\r\n\r\n");
}
$socketInfoSecond = $this->socket->recv();
$socketInfoSecond = $this->typeClear($socketInfoSecond);
$socketInfoSecond = trim($socketInfoSecond);
if ($socketInfoSecond == "Reply-Text: +OK accepted") return true;
return false;
}
public function eliminate($parameter)
{
$array = array(" ", " ", "\t", "\n", "\r");
return str_replace($array, '', $parameter);
}
public function eliminateLine($parameter)
{
return str_replace("\n\n", "\n", $parameter);
}
/**
* 清除内容类型
* @param $response
* @return string|string[]
*/
public function typeClear($response)
{
$commenType = [
"Content-Type: text/event-xml\n",
"Content-Type: text/event-plain\n",
"Content-Type: text/event-json\n",
"Content-Type: api/response\n",
"Content-Type: command/reply\n",
];
return str_replace($commenType, '', $response);
}
/**
* 发送API命令
* @param $api
* @param string $args
* @return false|string|string[]
*/
public function api($api, $args = "")
{
if ($this->socket) {
$this->socket->send("api " . $api . " " . $args . "\r\n\r\n");
}
return $this->recvEvent("common");
}
/**
* 异步发送API命令
* @param $api
* @param string $args
* @param string $custom_job_uuid
* @return null
*/
public function bgapi($api, $args = "", $custom_job_uuid = "")
{
if ($this->socket) {
$this->socket->send("bgapi " . $api . " " . $args . " " . $custom_job_uuid . "\r\n\r\n");
}
return $custom_job_uuid;
}
/**
* 执行app
* @param $app
* @param $args
* @param $uuid
* @return false|string|string[]
*/
public function execute($app, $args, $uuid)
{
if ($this->socket) {
$str = "sendmsg " . $uuid . "\ncall-command: execute\nexecute-app-name: " . $app . "\nexecute-app-arg: " . $args . "\n\n";
$this->socket->send($str);
}
return $this->recvEvent();
}
/**
* 异步执行app
* @param $app
* @param $args
* @param $uuid
* @return null
*/
public function executeAsync($app, $args, $uuid)
{
if ($this->socket) {
$str = "sendmsg " . $uuid . "\ncall-command: executeAsync\nexecute-app-name: " . $app . "\nexecute-app-arg: " . $args . "\n\n";
$this->socket->send($str);
}
return null;
}
/**
* 发送消息
* @param $uuid
* @return null
*/
public function sendmsg($uuid)
{
if ($this->socket) {
$this->socket->send("sendmsg " . $uuid . "\r\n\r\n");
}
return null;
}
/**
* 设置需要监听的事件,默认监听所有
* @param string $eventnames
* @return null
*/
public function events($eventnames = "ALL")
{
if ($this->socket) {
$this->socket->send("event plain " . $eventnames . "\r\n\r\n");
}
return null;
}
/**
* @param string $type
* @return string
*/
public function recvEvent($type = "event")
{
$response = "";
$x = 0;
$length = 0;
while (true) {
$x++;
$socketInfo = $this->socket->recvPacket();
if ($length > 0) {
$response .= $socketInfo;
}
if (strpos($socketInfo, 'Content-Length:') !== false) {
$lengtharray = explode("Content-Length:", $socketInfo);
if ($type == "event") {
$length = (int)$lengtharray[1] + 30;
} else {
$length = (int)$lengtharray[1];
}
}
if ($length > 0 && strlen($response) >= $length) {
break;
}
if ($x > 10000) break;
}
if ($type == "event") {
$response = $this->typeClear($response);
} else {
$response = $this->eliminateLine($response);
}
return trim($response);
}
/**
* 解析数据
* @param $response
* @return mixed
*/
public function serialize($response)
{
$res = [];
if (!$response) return $res;
try {
$arr1 = explode("\n", $response);
foreach ($arr1 as $line) {
if (strpos($line, ":") !== false) {
$item = explode(":", $line);
$res[$item[0]] = trim(urldecode($item[1]));
}
}
} catch (\Exception $exception) {
print_r("esl解析事件数据异常" . $exception->getMessage() . "\n");
}
return $res;
}
/**
* 过滤uuid
* @param $uuid
* @return null
*/
public function filteruuid($uuid)
{
if ($this->socket) {
$this->socket->send("filter Unique-ID " . $uuid . "\r\n\r\n");
}
return null;
}
/**
* 断开连接
*/
public function disconnect()
{
if ($this->socket) {
$this->socket->send("exit" . "\r\n\r\n");
$this->socket->close();
$this->socket = null;
}
}
/**
* 广播
* @param string $uuid
* @param string $audio_path
* @param string $idx 比如aleg或bleg等
*/
public function uuidBroadcast(string $uuid, string $audio_path, string $idx = '')
{
$this->bgapi("uuid_broadcast", sprintf("%s %s %s", $uuid, $audio_path, $idx));
}
/**
* 结束广播
* @param string $uuid
*/
public function uuidBreak(string $uuid)
{
$this->bgapi("uuid_break", sprintf("%s all", $uuid)); // 结束音乐播放
}
}