sls/app/Services/IceCandidate/Providers/MeteredIceCandidateProvider.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

58 lines
1.9 KiB
PHP

<?php
namespace App\Services\IceCandidate\Providers;
use App\Contracts\IceCandidateProviderInterface;
use App\DTOs\IceCandidatesDto;
use App\Services\IceCandidate\Validators\IceResponseValidator;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use RuntimeException;
class MeteredIceCandidateProvider implements IceCandidateProviderInterface
{
public function __construct(
protected array $config = []
) {}
public function getIceCandidates(): IceCandidatesDto
{
$baseUrl = $this->config['url'] ?? config('services.metered.url');
$apiKey = $this->config['key'] ?? config('services.metered.key');
$timeout = (int) ($this->config['timeout'] ?? 5);
$cacheTtl = (int) ($this->config['cache_ttl'] ?? 600);
if (empty($baseUrl)) {
throw new RuntimeException('Metered ICE provider URL is not configured.');
}
$url = $baseUrl;
if ($apiKey && ! str_contains($url, 'apiKey=')) {
$separator = str_contains($url, '?') ? '&' : '?';
$url .= $separator.'apiKey='.urlencode($apiKey);
}
$cacheKey = 'metered_credentials_cache_'.md5($url);
$data = Cache::remember($cacheKey, now()->addSeconds($cacheTtl), function () use ($url, $timeout) {
$response = Http::timeout($timeout)->get($url);
if (! $response->successful()) {
Log::error('Metered API error response', [
'status' => $response->status(),
'body' => $response->body(),
]);
throw new RuntimeException('Metered API Error: '.$response->status());
}
$json = $response->json();
return IceResponseValidator::validate($json, 'Metered');
});
return IceCandidatesDto::fromArray($data);
}
}