Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120824663
Room.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
9 KB
Referenced Files
None
Subscribers
None
Room.php
View Options
<?php
namespace
App\Meet
;
use
App\Traits\BelongsToTenantTrait
;
use
App\Traits\EntitleableTrait
;
use
App\Traits\Meet\RoomConfigTrait
;
use
App\Traits\PermissibleTrait
;
use
App\Traits\SettingsTrait
;
use
Dyrynda\Database\Support\NullableFields
;
use
Illuminate\Database\Eloquent\Model
;
use
Illuminate\Database\Eloquent\SoftDeletes
;
use
Illuminate\Support\Facades\Cache
;
/**
* The eloquent definition of a Room.
*
* @property int $id Room identifier
* @property ?string $description Description
* @property string $name Room name
* @property int $tenant_id Tenant identifier
* @property ?string $session_id Meet session identifier
*/
class
Room
extends
Model
{
use
BelongsToTenantTrait
;
use
EntitleableTrait
;
use
RoomConfigTrait
;
use
NullableFields
;
use
SettingsTrait
;
use
PermissibleTrait
;
use
SoftDeletes
;
public
const
ROLE_SUBSCRIBER
=
1
<<
0
;
public
const
ROLE_PUBLISHER
=
1
<<
1
;
public
const
ROLE_MODERATOR
=
1
<<
2
;
public
const
ROLE_SCREEN
=
1
<<
3
;
public
const
ROLE_OWNER
=
1
<<
4
;
public
const
REQUEST_ACCEPTED
=
'accepted'
;
public
const
REQUEST_DENIED
=
'denied'
;
/** @var array<string, string> The attributes that should be cast */
protected
$casts
=
[
'created_at'
=>
'datetime:Y-m-d H:i:s'
,
'deleted_at'
=>
'datetime:Y-m-d H:i:s'
,
'updated_at'
=>
'datetime:Y-m-d H:i:s'
,
];
/** @var array<int, string> The attributes that are mass assignable */
protected
$fillable
=
[
'name'
,
'description'
];
/** @var array<int, string> The attributes that can be not set */
protected
$nullable
=
[
'description'
];
/** @var string Database table name */
protected
$table
=
'openvidu_rooms'
;
/** @var \GuzzleHttp\Client|null HTTP client instance */
private
$client
=
null
;
/**
* Select a Meet server for this room
*
* This needs to always result in the same server for the same room,
* so all participants end up on the same server.
*
* @return string The server url
*/
private
function
selectMeetServer
()
{
$urls
=
\config
(
'meet.api_urls'
);
$count
=
count
(
$urls
);
if
(
$count
==
0
)
{
\Log
::
error
(
"No meet server configured."
);
return
""
;
}
//Select a random backend.
//If the names are evenly distributed this should theoretically result in an even distribution.
$index
=
abs
(
intval
(
hash
(
"crc32b"
,
$this
->
name
),
16
)
%
$count
);
return
$urls
[
$index
];
}
/**
* Creates HTTP client for connections to Meet server
*
* @return \GuzzleHttp\Client HTTP client instance
*/
private
function
client
()
{
if
(!
$this
->
client
)
{
$url
=
$this
->
selectMeetServer
();
$this
->
client
=
new
\GuzzleHttp\Client
(
[
'http_errors'
=>
false
,
// No exceptions from Guzzle
'base_uri'
=>
$url
,
'verify'
=>
\config
(
'meet.api_verify_tls'
),
'headers'
=>
[
'X-Auth-Token'
=>
\config
(
'meet.api_token'
),
],
'connect_timeout'
=>
10
,
'timeout'
=>
10
,
'on_stats'
=>
function
(
\GuzzleHttp\TransferStats
$stats
)
{
$threshold
=
\config
(
'logging.slow_log'
);
if
(
$threshold
&&
(
$sec
=
$stats
->
getTransferTime
())
>
$threshold
)
{
$url
=
$stats
->
getEffectiveUri
();
$method
=
$stats
->
getRequest
()->
getMethod
();
\Log
::
warning
(
sprintf
(
"[STATS] %s %s: %.4f sec."
,
$method
,
$url
,
$sec
));
}
},
]
);
}
return
$this
->
client
;
}
/**
* Create a Meet session
*
* @return array|null Session data on success, NULL otherwise
*/
public
function
createSession
():
?
array
{
$params
=
[
'json'
=>
[
/* request params here */
]
];
$response
=
$this
->
client
()->
request
(
'POST'
,
"sessions"
,
$params
);
if
(
$response
->
getStatusCode
()
!==
200
)
{
$this
->
logError
(
"Failed to create the meet session"
,
$response
);
$this
->
session_id
=
null
;
$this
->
save
();
return
null
;
}
$session
=
json_decode
(
$response
->
getBody
(),
true
);
$this
->
session_id
=
$session
[
'id'
];
$this
->
save
();
return
$session
;
}
/**
* Create a Meet session (connection) token
*
* @param int $role User role (see self::ROLE_* constants)
*
* @return array|null Token data on success, NULL otherwise
* @throws \Exception if session does not exist
*/
public
function
getSessionToken
(
$role
=
self
::
ROLE_SUBSCRIBER
):
?
array
{
if
(!
$this
->
session_id
)
{
throw
new
\Exception
(
"The room session does not exist"
);
}
$url
=
'sessions/'
.
$this
->
session_id
.
'/connection'
;
$post
=
[
'json'
=>
[
'role'
=>
$role
,
]
];
$response
=
$this
->
client
()->
request
(
'POST'
,
$url
,
$post
);
if
(
$response
->
getStatusCode
()
==
200
)
{
$json
=
json_decode
(
$response
->
getBody
(),
true
);
return
[
'token'
=>
$json
[
'token'
],
'role'
=>
$role
,
];
}
$this
->
logError
(
"Failed to create the meet peer connection"
,
$response
);
return
null
;
}
/**
* Check if the room has an active session
*
* @return bool True when the session exists, False otherwise
*/
public
function
hasSession
():
bool
{
if
(!
$this
->
session_id
)
{
return
false
;
}
$response
=
$this
->
client
()->
request
(
'GET'
,
"sessions/{$this->session_id}"
);
$this
->
logError
(
"Failed to check that a meet session exists"
,
$response
);
return
$response
->
getStatusCode
()
==
200
;
}
/**
* Accept the join request.
*
* @param string $id Request identifier
*
* @return bool True on success, False on failure
*/
public
function
requestAccept
(
string
$id
):
bool
{
$request
=
Cache
::
get
(
$this
->
session_id
.
'-'
.
$id
);
if
(
$request
)
{
$request
[
'status'
]
=
self
::
REQUEST_ACCEPTED
;
return
Cache
::
put
(
$this
->
session_id
.
'-'
.
$id
,
$request
,
now
()->
addHours
(
1
));
}
return
false
;
}
/**
* Deny the join request.
*
* @param string $id Request identifier
*
* @return bool True on success, False on failure
*/
public
function
requestDeny
(
string
$id
):
bool
{
$request
=
Cache
::
get
(
$this
->
session_id
.
'-'
.
$id
);
if
(
$request
)
{
$request
[
'status'
]
=
self
::
REQUEST_DENIED
;
return
Cache
::
put
(
$this
->
session_id
.
'-'
.
$id
,
$request
,
now
()->
addHours
(
1
));
}
return
false
;
}
/**
* Get the join request data.
*
* @param string $id Request identifier
*
* @return array|null Request data (e.g. nickname, status, picture?)
*/
public
function
requestGet
(
string
$id
):
?
array
{
return
Cache
::
get
(
$this
->
session_id
.
'-'
.
$id
);
}
/**
* Save the join request.
*
* @param string $id Request identifier
* @param array $request Request data
*
* @return bool True on success, False on failure
*/
public
function
requestSave
(
string
$id
,
array
$request
):
bool
{
// We don't really need the picture in the cache
// As we use this cache for the request status only
unset
(
$request
[
'picture'
]);
return
Cache
::
put
(
$this
->
session_id
.
'-'
.
$id
,
$request
,
now
()->
addHours
(
1
));
}
/**
* Send a signal to the Meet session participants (peers)
*
* @param string $name Signal name (type)
* @param array $data Signal data array
* @param int $target Limit targets by their participant role
*
* @return bool True on success, False on failure
* @throws \Exception if session does not exist
*/
public
function
signal
(
string
$name
,
array
$data
=
[],
$target
=
null
):
bool
{
if
(!
$this
->
session_id
)
{
throw
new
\Exception
(
"The room session does not exist"
);
}
$post
=
[
'roomId'
=>
$this
->
session_id
,
'type'
=>
$name
,
'role'
=>
$target
,
'data'
=>
$data
,
];
$response
=
$this
->
client
()->
request
(
'POST'
,
'signal'
,
[
'json'
=>
$post
]);
$this
->
logError
(
"Failed to send a signal to the meet session"
,
$response
);
return
$response
->
getStatusCode
()
==
200
;
}
/**
* Returns a map of supported ACL labels.
*
* @return array Map of supported permission rights/ACL labels
*/
protected
function
supportedACL
():
array
{
return
[
'full'
=>
\App\Permission
::
READ
|
\App\Permission
::
WRITE
|
\App\Permission
::
ADMIN
,
];
}
/**
* Returns room name (required by the EntitleableTrait).
*
* @return string|null Room name
*/
public
function
toString
():
?
string
{
return
$this
->
name
;
}
/**
* Log an error for a failed request to the meet server
*
* @param string $str The error string
* @param object $response Guzzle client response
*/
private
function
logError
(
string
$str
,
$response
)
{
$code
=
$response
->
getStatusCode
();
if
(
$code
!=
200
)
{
\Log
::
error
(
"$str [$code]"
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Apr 24, 10:25 AM (1 d, 3 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8f/17/14c541f27729947a48472b4ef643
Default Alt Text
Room.php (9 KB)
Attached To
Mode
rK kolab
Attached
Detach File
Event Timeline