{"id":401425,"date":"2026-11-12T16:09:21","date_gmt":"2026-11-12T16:09:21","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/tlloancy-turn-relay\/"},"modified":"2026-11-13T02:50:05","modified_gmt":"2026-11-13T02:50:05","slug":"tlloancy-turn-relay","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/tlloancy-turn-relay\/","author":22011295,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.0","stable_tag":"1.1.0","tested":"7.1.4","requires":"6.2","requires_php":"8.1","requires_plugins":null,"header_name":"tlloancy Turn Relay","header_author":"tlloancy","header_description":"Issues short-lived TURN credentials for a shared coturn server, and an optional card of backup STUN and TURN nodes.","last_updated":"2026-11-13 02:50:05","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/donorbox.org\/wordpress-plugins","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":91,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0":{"tag":"1.0","author":"tlloancy","date":"2026-11-12 16:09:11","revision":3798744},"1.1.0":{"tag":"1.1.0","author":"tlloancy","date":"2026-11-13 02:50:05","revision":3799570}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3798744,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3798744,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3798744,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3798744,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3799570,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"landingPage\":\"\\\/wp-admin\\\/options-general.php?page=tlloancy-turn-relay\",\"preferredVersions\":{\"php\":\"8.3\",\"wp\":\"latest\"},\"features\":{\"networking\":true},\"steps\":[{\"step\":\"login\",\"username\":\"admin\",\"password\":\"password\"},{\"step\":\"activatePlugin\",\"pluginPath\":\"tlloancy-turn-relay\\\/tlloancy-turn-relay.php\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"tlloancy-turn-relay\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.0","1.1.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[292327,292326,30195,8025],"plugin_category":[],"plugin_contributors":[232640],"plugin_business_model":[],"class_list":["post-401425","plugin","type-plugin","status-publish","hentry","plugin_tags-coturn","plugin_tags-stun","plugin_tags-turn","plugin_tags-webrtc","plugin_contributors-tlloancy","plugin_committers-tlloancy"],"banners":{"banner":"https:\/\/ps.w.org\/tlloancy-turn-relay\/assets\/banner-772x250.png?rev=3798744","banner_2x":"https:\/\/ps.w.org\/tlloancy-turn-relay\/assets\/banner-1544x500.png?rev=3798744","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/tlloancy-turn-relay\/assets\/icon-128x128.png?rev=3798744","icon_2x":"https:\/\/ps.w.org\/tlloancy-turn-relay\/assets\/icon-256x256.png?rev=3798744","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>WebRTC in the browser needs ICE servers. STUN discovers a public address. TURN relays the media when a direct path is impossible. coturn does that work. This plugin does not.<\/p>\n\n<p><strong>tlloancy Turn Relay<\/strong> signs a username and a password that coturn accepts for a limited time (<code>use-auth-secret<\/code>). The shared secret stays on the server. Callers receive <code>iceServers<\/code> for <code>RTCPeerConnection<\/code> and leave <code>iceTransportPolicy<\/code> at <code>all<\/code>.<\/p>\n\n<p>Other plugins, including a video plugin, call <code>tlloancy_turn_relay_get_ice_servers()<\/code> when a call starts. They do not collect a TURN host of their own.<\/p>\n\n<p>Publication is off until you turn it on. A published card is JSON. It never contains the shared secret.<\/p>\n\n<ul>\n<li><strong>STUN only<\/strong> \u2014 the card lists a <code>stun:<\/code> URL.<\/li>\n<li><strong>Shared<\/strong> \u2014 the card also lists the credential endpoint. Another site must present an invitation token.<\/li>\n<li><strong>Private<\/strong> \u2014 the card contains the class and nothing else.<\/li>\n<\/ul>\n\n<p>You can paste another site\u2019s card URL. Private and loopback addresses are refused. The admin drawing measures latency in your browser with <code>RTCPeerConnection<\/code>. A figure advertised by the remote card is ignored.<\/p>\n\n<p>Step-by-step guides: <code>docs\/USER-GUIDE.md<\/code> (English) and <code>docs\/MODE-DEMPLOI.md<\/code> (French).<\/p>\n\n<h3>External services<\/h3>\n\n<p>Nothing is contacted when you only issue credentials for your own coturn host.<\/p>\n\n<p>If an administrator pastes a card URL, the server fetches that HTTPS URL once. The request sends no secret and no visitor data. The response is limited to 8 KB and redirects are not followed.<\/p>\n\n<p>If an administrator then enables \u201cDuring a call\u201d on a shared node and stores that node\u2019s invitation token, a call requests credentials from that node\u2019s endpoint. The request sends the invitation token. It does not send your shared secret or the contents of the call. At most two nodes are asked.<\/p>\n\n<p>The diagnostics buttons resolve your own TURN host and open a TCP connection to its TLS port. They run only when an administrator clicks them.<\/p>\n\n<p><strong>Issue a test credential<\/strong> also prints a QR code. The code opens a page on this site. That page runs the TURN test in the phone\u2019s browser with a credential that expires in five minutes. The shared secret is not in the link.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>tlloancy-turn-relay<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate <strong>tlloancy Turn Relay<\/strong>.<\/li>\n<li>Open <strong>Settings \u2192 tlloancy Turn Relay<\/strong>.<\/li>\n<li>Enter the TURN host and a shared secret of at least 32 characters. The same secret is configured on coturn as <code>static-auth-secret<\/code>.<\/li>\n<li>Leave publication off until you want another site to read a card.<\/li>\n<\/ol>\n\n<p>To keep the secret out of the database, define it in <code>wp-config.php<\/code>:<\/p>\n\n<pre><code>define( 'TLLOANCY_TURN_RELAY_SECRET', 'paste-a-long-random-secret' );\n<\/code><\/pre>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20plugin%20relay%20audio%20or%20video%3F\"><h3>Does this plugin relay audio or video?<\/h3><\/dt>\n<dd><p>No. coturn relays the media. The plugin only signs credentials and, if you turn it on, publishes a card.<\/p><\/dd>\n<dt id=\"why%20do%20the%20credentials%20change%3F\"><h3>Why do the credentials change?<\/h3><\/dt>\n<dd><p>The password is visible in the browser. It expires. A fixed TURN user would keep working after someone copies it. An administrator sets the host and the secret once. Visitors never edit them.<\/p><\/dd>\n<dt id=\"how%20does%20another%20plugin%20start%20a%20call%3F\"><h3>How does another plugin start a call?<\/h3><\/dt>\n<dd><p>tlloancy_turn_relay_get_ice_servers() returns the list. In the browser, enqueue the helper and call <code>TlloancyTurnRelay.getIceServers()<\/code>. Guests are allowed by returning true from the <code>tlloancy_turn_relay_can_issue<\/code> filter.<\/p><\/dd>\n<dt id=\"what%20is%20the%20invitation%20token%3F\"><h3>What is the invitation token?<\/h3><\/dt>\n<dd><p>It is not the shared secret. A shared card tells another site where to ask for credentials. That request must include the token in the <code>X-Tlloancy-Turn-Relay-Token<\/code> header. The HMAC secret never leaves this server.<\/p><\/dd>\n<dt id=\"how%20do%20i%20test%20the%20relay%20from%20another%20network%3F\"><h3>How do I test the relay from another network?<\/h3><\/dt>\n<dd><p>Open <strong>Settings \u2192 tlloancy Turn Relay<\/strong>, click <strong>Issue a test credential<\/strong>, and scan the QR code with a phone on mobile data. The result <code>Relay<\/code> plus the public address means the phone reached coturn.<\/p><\/dd>\n<dt id=\"can%20i%20list%20every%20wordpress%20site%20that%20has%20the%20plugin%3F\"><h3>Can I list every WordPress site that has the plugin?<\/h3><\/dt>\n<dd><p>No. A site appears only after an administrator pastes its card URL, and only if that administrator has published the card.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>A five-minute phone test: the diagnostics screen prints a QR code that opens the TURN check with the test credential already loaded.<\/li>\n<\/ul>\n\n<h4>1.0<\/h4>\n\n<ul>\n<li>Short-lived TURN credentials for a coturn server configured with <code>use-auth-secret<\/code>.<\/li>\n<li>Optional public card, manual nodes, and an admin latency drawing.<\/li>\n<\/ul>","raw_excerpt":"Issues short-lived TURN credentials for a shared coturn server. An optional card can share a STUN address or a credential endpoint.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/401425","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=401425"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/tlloancy"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=401425"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=401425"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=401425"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=401425"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=401425"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=401425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}