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); } }