sls/app/Services/IceCandidate/IceCandidateManager.php
kushal.saha 3aca6d90f3 feat(webrtc): implement IceCandidateProviderInterface with Metered and ConvexSol drivers
- Add Metered and ConvexSol (CoTURN) provider drivers with response validation and caching
- Add IceCandidateManager with automatic failover and structured logging
- Add IceCandidateProviderInterface and DTOs conforming to RTCIceServer format
2026-08-26 12:44:41 +00:00

86 lines
3.3 KiB
PHP

<?php
namespace App\Services\IceCandidate;
use App\Contracts\IceCandidateProviderInterface;
use App\DTOs\IceCandidatesDto;
use App\Services\IceCandidate\Providers\ConvexSolIceCandidateProvider;
use App\Services\IceCandidate\Providers\MeteredIceCandidateProvider;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Manager;
use Throwable;
class IceCandidateManager extends Manager implements IceCandidateProviderInterface
{
public function getDefaultDriver(): string
{
return $this->config->get('services.ice.default', 'metered');
}
public function getFallbackDriver(): ?string
{
return $this->config->get('services.ice.fallback', 'convexsol');
}
/**
* Retrieve ICE candidates with automatic failover and structured logging.
*/
public function getIceCandidates(): IceCandidatesDto
{
$primaryDriver = $this->getDefaultDriver();
try {
return $this->driver($primaryDriver)->getIceCandidates();
} catch (Throwable $primaryException) {
$fallbackDriver = $this->getFallbackDriver();
if ($fallbackDriver && $fallbackDriver !== $primaryDriver) {
Log::warning("Primary ICE candidate provider [{$primaryDriver}] failed: {$primaryException->getMessage()}. Falling back to [{$fallbackDriver}].", [
'primary_driver' => $primaryDriver,
'fallback_driver' => $fallbackDriver,
'error' => $primaryException->getMessage(),
]);
try {
return $this->driver($fallbackDriver)->getIceCandidates();
} catch (Throwable $fallbackException) {
Log::error("Fallback ICE candidate provider [{$fallbackDriver}] also failed: {$fallbackException->getMessage()}. Using default STUN servers.", [
'primary_error' => $primaryException->getMessage(),
'fallback_error' => $fallbackException->getMessage(),
]);
return IceCandidatesDto::defaultStun();
}
}
Log::error("ICE candidate provider [{$primaryDriver}] failed without fallback: {$primaryException->getMessage()}. Using default STUN servers.", [
'error' => $primaryException->getMessage(),
]);
return IceCandidatesDto::defaultStun();
}
}
protected function createMeteredDriver(): IceCandidateProviderInterface
{
$config = $this->config->get('services.ice.providers.metered', [
'url' => $this->config->get('services.metered.url'),
'key' => $this->config->get('services.metered.key'),
]);
return new MeteredIceCandidateProvider($config);
}
protected function createConvexsolDriver(): IceCandidateProviderInterface
{
$config = $this->config->get('services.ice.providers.convexsol', [
'username' => $this->config->get('services.convexsol.username'),
'password' => $this->config->get('services.convexsol.password'),
'turn_urls' => $this->config->get('services.convexsol.turn_urls'),
'stun_urls' => $this->config->get('services.convexsol.stun_urls'),
]);
return new ConvexSolIceCandidateProvider($config);
}
}