This message was deleted.
# ask-ai
s
This message was deleted.
t
Thanks for reaching out, Omer. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about the
wait_pc_connection timed out
error when using
@livekit/rtc-node
(your logs show signaling succeeded but the WebRTC peer connection never completed). Below are the most likely causes and focused steps you can try to resolve it. Key cause summary • The error means signaling/join succeeded, but ICE/DTLS (the actual media peer connection) failed to complete within the timeout. This is typically a network/ICE issue (blocked ports, NAT, missing TURN, wrong public IP), or an environment incompatibility with the Node WebRTC stack. Quick checks to run now • Are you testing against a server reachable only at 127.0.0.1 from the client machine? If the server is local but the client is remote, ICE candidates may be private addresses and won’t be reachable. • Can the machine running
rtc-node
reach the LiveKit server’s media ports (UDP range) and TURN/STUN servers? Verify basic connectivity (ping/traceroute/tcping) to the server host and TURN host. Practical troubleshooting steps 1) Force relay (TURN) to confirm ICE reachability • Try forcing the client to use TURN (relay) so you can determine if UDP pathing is the problem:
Copy code
const room = new Room();
  await room.connect(url, token, {
    rtcConfig: { iceTransportPolicy: 'relay' }
  });
• If that connects, the problem is UDP/NAT/ICE — proceed to configure/allow TURN. 2) Verify TURN/STUN configuration on the LiveKit server • Ensure your LiveKit server is configured with reachable STUN/TURN servers and that credentials are valid. • If your TURN server is behind firewalls, make sure ports (TCP/UDP 3478, 5349 and any TURN media ports like 443) are open. 3) Ensure the server advertises a public IP/domain • If server binds only to localhost/private IP, remote peers won’t be able to reach the media address. Set the LiveKit server to bind to the public interface and set
public_ip
(or equivalent) so correct ICE candidates are advertised. 4) Open firewall / forward UDP media ports • Media uses UDP ephemeral ports (commonly 10000–20000). Make sure those are allowed/forwarded on the server side and not blocked on your network. 5) Compare CLI vs rtc-node ICE candidates • The CLI may succeed by using different ICE candidates or fallbacks. In
rtc-node
you can log the SDP/offers/answers to inspect what candidates are being exchanged and confirm whether host/public/relay candidates appear. 6) Node.js / rtc-node environment differences •
rtc-node
uses the WebRTC native implementation; behavior differs from the CLI. Try a known stable Node version (e.g., Node 18 or 20) instead of experimental versions that might break native modules. • Ensure system libs required by the native WebRTC bindings are present. 7) Collect server logs and look for handshake failures • On the server side, search for ICE/DTLS related messages such as “ICE connection failed”, “DTLS handshake timeout”, or “no candidate pair available”. Those messages confirm where the handshake is failing. If you want, I can help next with one of these targeted steps: • Walk through forcing TURN and configuring TURN credentials in your LiveKit server. • Show how to log/inspect the SDP candidates exchanged by
rtc-node
. • Review specific server logs if you paste the ICE/DTLS related lines (redact secrets). Which one would you like to try first? Sources: Firewall Tips for LiveKit Connectivity | LiveKit | Diagnosing Connection Errors with the Connection Test Utility | LiveKit | client-sdk-js | livekit/livekit_composite | DeepWiki
b
r": "[0xc0017f5348] abort chunk, with following errors: (User Initiated Abort: Close called)"} 2026-02-14T065658.889Z INFO livekit rtc/participant.go:1367 participant closing {"room": "voice-ae3d4920-f213-4c00-8483-6a3adb2dbd3d", "roomID": "RM_UtscPHFvxoGB", "participant": "a396ca52-e119-423f-9dd4-408ad642711d", "pID": "PA_LzZaWjjEHntn", "remote": false, "sendLeave": true, "reason": "CLIENT_REQUEST_LEAVE", "isExpectedToResume": false} 2026-02-14T065718.904Z INFO livekit.room rtc/room.go:807 closing room {"room": "voice-ae3d4920-f213-4c00-8483-6a3adb2dbd3d", "roomID": "RM_UtscPHFvxoGB"} 2026-02-14T065718.904Z INFO livekit service/roommanager.go:187 deleting room state {"room": "voice-ae3d4920-f213-4c00-8483-6a3adb2dbd3d"} 2026-02-14T065718.911Z INFO livekit.room service/roommanager.go:667 room closed {"room": "voice-ae3d4920-f213-4c00-8483-6a3adb2dbd3d", "roomID": "RM_UtscPHFvxoGB"} 2026-02-14T065718.911Z INFO livekit.room rtc/room.go:791 closing idle room {"room": "voice-ae3d4920-f213-4c00-8483-6a3adb2dbd3d", "roomID": "RM_UtscPHFvxoGB", "reason": "departure timeout"} 2026-02-14T070333.584Z INFO livekit service/roomallocator.go:166 selected node for room {"room": "test-bot-room", "selectedNodeID": "ND_XBt4dpaUSMWt"} 2026-02-14T070333.626Z INFO livekit service/roommanager.go:413 starting RTC session {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_HykboexeHEDc", "remote": false, "room": "test-bot-room", "nodeID": "ND_XBt4dpaUSMWt", "numParticipants": 0, "participantInit": {"Identity": "test-bot", "Reconnect": false, "ReconnectReason": "RR_UNKNOWN", "AutoSubscribe": false, "AutoSubscribeDataTrack": "not-set", "Client": {"sdk": "NODE", "version": "0.13.24", "protocol": 16}, "Grants": {"Identity": "test-bot", "Kind": "", "KindDetails": [], "Video": {"RoomCreate": false, "RoomList": false, "RoomRecord": false, "RoomAdmin": false, "RoomJoin": true, "Room": "test-bot-room", "CanPublish": true, "CanSubscribe": false, "CanPublishData": "not-set", "CanPublishSources": [], "CanUpdateOwnMetadata": "not-set", "IngressAdmin": false, "Hidden": false, "Recorder": false, "Agent": false, "CanSubscribeMetrics": "not-set", "DestinationRoom": ""}, "SIP": {}, "Agent": {}, "Inference": {}, "Observability": {}, "RoomConfig": {}, "RoomPreset": ""}, "Region": "", "AdaptiveStream": false, "ID": "", "SubscriberAllowPause": "not-set", "DisableICELite": false, "CreateRoom": {"name": "test-bot-room"}, "AddTrackRequests": [], "PublisherOffer": {}, "SyncState": {}, "UseSinglePeerConnection": false}} 2026-02-14T070348.689Z INFO livekit service/roommanager.go:379 removing duplicate participant {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_HykboexeHEDc", "remote": false} 2026-02-14T070348.689Z INFO livekit rtc/room.go:1431 removing participant without connection {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_HykboexeHEDc", "remote": false, "connectionType": "unknown", "reason": "DUPLICATE_IDENTITY", "clientInfo": {"sdk": "NODE", "version": "0.13.24", "protocol": 16}} 2026-02-14T070348.689Z INFO livekit rtc/participant.go:1367 participant closing {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_HykboexeHEDc", "remote": false, "sendLeave": true, "reason": "DUPLICATE_IDENTITY", "isExpectedToResume": false} 2026-02-14T070348.696Z INFO livekit service/roommanager.go:413 starting RTC session {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_tMQNF37Rje8z", "remote": false, "room": "test-bot-room", "nodeID": "ND_XBt4dpaUSMWt", "numParticipants": 0, "participantInit": {"Identity": "test-bot", "Reconnect": false, "ReconnectReason": "RR_UNKNOWN", "AutoSubscribe": false, "AutoSubscribeDataTrack": "not-set", "Client": {"sdk": "NODE", "version": "0.13.24", "protocol": 16}, "Grants": {"Identity": "test-bot", "Kind": "", "KindDetails": [], "Video": {"RoomCreate": false, "RoomList": false, "RoomRecord": false, "RoomAdmin": false, "RoomJoin": true, "Room": "test-bot-room", "CanPublish": true, "CanSubscribe": false, "CanPublishData": "not-set", "CanPublishSources": [], "CanUpdateOwnMetadata": "not-set", "IngressAdmin": false, "Hidden": false, "Recorder": false, "Agent": false, "CanSubscribeMetrics": "not-set", "DestinationRoom": ""}, "SIP": {}, "Agent": {}, "Inference": {}, "Observability": {}, "RoomConfig": {}, "RoomPreset": ""}, "Region": "", "AdaptiveStream": false, "ID": "", "SubscriberAllowPause": "not-set", "DisableICELite": false, "CreateRoom": {"name": "test-bot-room"}, "AddTrackRequests": [], "PublisherOffer": {}, "SyncState": {}, "UseSinglePeerConnection": false}} 2026-02-14T070403.756Z INFO livekit rtc/participant.go:1367 participant closing {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_tMQNF37Rje8z", "remote": false, "sendLeave": false, "reason": "SIGNAL_SOURCE_CLOSE", "isExpectedToResume": false} 2026-02-14T070403.756Z INFO livekit rtc/room.go:1431 removing participant without connection {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "participant": "test-bot", "pID": "PA_tMQNF37Rje8z", "remote": false, "connectionType": "unknown", "reason": "SIGNAL_SOURCE_CLOSE", "clientInfo": {"sdk": "NODE", "version": "0.13.24", "protocol": 16}} 2026-02-14T070423.904Z INFO livekit.room rtc/room.go:807 closing room {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV"} 2026-02-14T070423.905Z INFO livekit service/roommanager.go:187 deleting room state {"room": "test-bot-room"} 2026-02-14T070423.911Z INFO livekit.room service/roommanager.go:667 room closed {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV"} 2026-02-14T070423.911Z INFO livekit.room rtc/room.go:791 closing idle room {"room": "test-bot-room", "roomID": "RM_evSKDhZuVfwV", "reason": "departure timeout"}
t
Thanks — I’m responding to the server logs you pasted and the ongoing
wait_pc_connection timed out
problem with
@livekit/rtc-node
. What the logs show • The server accepts the client’s signaling/join request (you see "starting RTC session" with Client: NODE v0.13.24). That means token and WebSocket signaling succeed. • The participant is then removed “without connection” with reasons like
SIGNAL_SOURCE_CLOSE
and
DUPLICATE_IDENTITY
. That indicates the rtc-node client never completed the ICE/DTLS media handshake and the client closed the signaling channel (the sdk’s internal timeout was reached). • This confirms the failure point is the WebRTC media path (ICE/TURN), not authentication/signaling. Concrete next steps to isolate and fix the problem 1) Force TURN to confirm it’s an ICE/UDP issue • In your rtc-node client, force relay-only so all media goes via TURN:
Copy code
await room.connect(url, token, {
    rtcConfig: { iceTransportPolicy: 'relay' }
  });
• If that succeeds, UDP/peer-to-peer connectivity is blocked and you need TURN for production. 2) Check TURN/STUN reachability and config • Verify the LiveKit server has correct TURN/STUN URIs and credentials configured and that the TURN server is reachable from the rtc-node host. • Ensure TURN ports are open (TCP 443 or TCP/UDP 3478 as applicable) and any relay ports are available. 3) Verify server public IP / advertised candidates • If your LiveKit server runs behind NAT or bound to private interfaces (127.0.0.1), make sure it advertises its public IP or hostname so correct ICE candidates are sent to clients. 4) Open/forward UDP media ports on server • WebRTC commonly uses UDP ephemeral ports (often configured 10000–20000). Confirm host/network firewalls allow inbound/return UDP on those ports or that TURN covers the path. 5) Compare CLI vs rtc-node behavior • The CLI may use different ICE candidates/fallbacks. Capture and compare the SDP/candidates from: ◦ rtc-node: log offers/answers or inspect
signal
events ◦ CLI: see which candidates it uses • If CLI succeeds but rtc-node fails on the same host/network, check for environment differences (Node version, required native libs). 6) Address duplicate identity messages (if relevant) • Your logs show a
DUPLICATE_IDENTITY
removal; that happens when a second participant tries to join with the same identity. If your bot reconnects quickly, ensure your client handles reconnection correctly (reuse same participant connection or wait for previous session to close) so duplicate identity removal doesn't interfere with ICE setup. If you want, I can help with any of these specific actions: • Walk through forcing TURN and verifying TURN config on your LiveKit server. • Show how to log/inspect the rtc-node SDP offers/answers and ICE candidates. • Help interpret server logs you paste that show ICE/DTLS failure messages (e.g., “ICE connection failed”, “DTLS handshake timeout”). Which of the above would you like to try first? Sources: Understanding the STATE_MISMATCH Disconnect Reason | LiveKit | Firewall Tips for LiveKit Connectivity | LiveKit | Diagnosing Connection Errors with the Connection Test Utility | LiveKit
Thanks — I looked through the server config you pasted and the logs. I can see signaling succeeds (server creates the NODE client session) but the peer connection never completes and the client times out. That points to an ICE/media-path issue (blocked UDP, TURN not used, or incorrect public IP), not auth or WebSocket signaling. Before we dig deeper, a few targeted questions to narrow the root cause — your answers will let me give the shortest, most effective next steps: 1) Public IP / interface • Is this LiveKit node running on a host with a public IP 91.99.52.65 (the
node_ip
you set), or is it behind NAT/load‑balancer? Is
use_external_ip
intentionally false because you set
node_ip
manually? 2) TURN/STUN setup • Are you using an external TURN server, or relying on an embedded TURN? If external, please confirm the TURN URI, protocol (tcp/tls/udp), and port (redact credentials). • Do clients have network access to that TURN server (try curl/tcping from the rtc-node host to the TURN host/port)? 3) Ports & firewalls • Are the UDP port range 50000–60000 open and forwarded to the LiveKit node from your cloud firewall / datacenter network? Is
tcp_port: 7881
exposed (if you expect TCP ICE fallback)? • Is there any host-level firewall (iptables/nftables, cloud security group) that might block UDP? 4) Where rtc-node runs vs CLI • Where did you run the LiveKit CLI that succeeded (same host as rtc-node app, or different machine)? If different, can you run the CLI from the same host/container where your rtc-node process runs to compare behavior? 5) Node runtime / native dependencies • Which Node.js version does your rtc-node app use in production? (You previously mentioned v25.6.1 — is that still what rtc-node runs on?) 6) Duplicate identity / reconnect behavior • Logs show
DUPLICATE_IDENTITY
at times. Is your bot or test client reconnecting repeatedly with the same identity? If so, are you intentionally creating multiple simultaneous connections with the same identity, or should the client be reusing a prior session? Immediate checks you can run now • Force TURN in rtc-node to test connectivity:
Copy code
await room.connect(url, token, {
    rtcConfig: { iceTransportPolicy: 'relay' }
  });
If this succeeds, the issue is blocked UDP/ICE and you must ensure TURN is configured and reachable. • From the rtc-node host, test connectivity to STUN/TURN: ◦ Try connecting to the TURN port (e.g.,
tcping
or
curl
to TCP 443 if TURN over TLS). ◦ If you have access, run a packet capture (tcpdump) on the LiveKit node for UDP ports 50000–60000 while attempting a connection to see if ICE packets arrive. • Check the server’s advertised candidates: set
use_external_ip: true
or ensure
node_ip
is the correct public IP for that node so clients receive reachable candidates. What I can help with next • If you answer the 6 questions above, I’ll give a step-by-step plan (TURN config, firewall rules, and small config edits) tailored to your setup. • If you prefer, I can walk you through how to capture and paste the relevant ICE/DTLS failure lines from server logs or how to log the rtc-node SDP/ICE candidates for comparison. Which of the above would you like to do first — run the TURN-forcing test, or confirm the node IP / firewall/TURN details?
b
turn açmadım, sertifika soruyor yapamadım. iceTransportpolicy'i ekledim
t
Teşekkürler — anladım:
iceTransportPolicy
eklediniz fakat TURN kurulumunda “sertifika” sorunu olduğu için devam edemediniz. Bu durumda iki yönlü kısa rehber veriyorum: (A) hızlı test için geçici çözümler, (B) production için doğru TURN + TLS yapılandırması ve sertifika adımları. Hangisini tercih ettiğinizi söyleyin, sonra adım adım devam edelim. A — Hızlı test / geçici çözümler • iceTransportPolicy: 'relay' ekleyip yine bağlantı kuramıyorsanız TURN sunucunuza erişim veya sertifika problemi halen engel oluyor. Yine de bağlantının TURN ile çalışıp çalışmadığını doğrulamak için: a. TURN sunucusunun adresine (örn. turn.example.com) TCP 443 ile erişilebildiğini test edin (aynı makineden): • Basitçe:
curl -v <https://turn.example.com:443>
(TLS el sıkışması görmeniz gerekir; TURN protokolünü anlamaz ama port açık mı kontrolü sağlar). a. Eğer TURN yoksa, lokal test için aynı ağda (aynı LAN) client ve server çalıştırarak UDP doğrudan bağlantısını test edin — bu, ağ/port engeli olup olmadığını ayırır. B — TURN + TLS (sertifika) kurulum adımları (özet) • Neden TLS gerekiyor: Modern tarayıcılar ve pek çok ağ güvenlik kuralı TURN üzerinden TCP/TLS (443) isteklerini tercih eder. Eğer TURN sunucunuz TLS istemiyorsa veya sertifika hatalıysa bağlantılar reddedilir. Adımlar: 1) Alan adı ve sertifika • TURN sunucusu için bir alan adı (FQDN) kullanın. IP ile TLS hataları çıkabilir. • Üretimde en kolay yol: Let’s Encrypt ile gerçek sertifika almak (ücretsiz). Eğer test ortamıysa self-signed kullanabilirsiniz ama tarayıcılar/istemciler hata verir; rtc-node tarafında da ek konfig gerekebilir. • Let’s Encrypt kullanmak için sunucunuzun 80/443 portları erişilebilir olmalı. Certbot ile otomatik alınır. 2) TURN sunucusu (coturn) temel yapılandırma • Örnek /etc/turnserver.conf (TLS ile): ◦ listening-port=3478 ◦ tls-listening-port=5349 ◦ external-ip=<PUBLIC_IP> ◦ fingerprint ◦ use-auth-secret ◦ static-auth-secret=<strong-password> ◦ realm=<your-domain> ◦ cert=/etc/letsencrypt/live/your-domain/fullchain.pem ◦ pkey=/etc/letsencrypt/live/your-domain/privkey.pem ◦ no-stdout-log ◦ total-quota, bps-capacity vb. (opsiyonel) • TLS için
cert
ve
pkey
yolları Let’s Encrypt sertifikanızın gerçek yolları olmalı. 3) LiveKit server yapılandırması • LiveKit config içinde TURN bilgilerini belirtin (TURN URI, kullanıcı/secret ya da username/password). • Örnek: turn:turn.example.com:3478?transport=udp veya turns:turn.example.com:5349?transport=tcp • Eğer
use_auth_secret
ile coturn yapılandırdıysanız, LiveKit tarafında
turn
kullanıcı bilgilerini doğru şekilde besleyin. 4) Firewall / portlar • TURN (UDP 3478 ve TCP 5349/443) ve TF sürümlerine göre açın. • Media için LiveKit node üzerinde UDP ephemeral port aralığını açın (örn. 10000–20000). Alternatifler (eğer sertifika almak şu an mümkün değil) • Geçici olarak: ◦ Aynı ağ içinde test yapın (aynı LAN/VM host) — bu durumda TURN gerekmez. ◦ Self-signed sertifika kullanabilirsiniz; rtc-node tarafında self-signed TLS’ı kabul etmek için ek ayar/işlem gerekebilir (ve güvenlik riskleri vardır). • Eğer cloud sağlayıcınız varsa çoğu sağlayıcı (Cloudflare, AWS, GCP) SSL/TLS terminasyon ve/veya managed TURN benzeri hizmet sunabiliyor — bunları değerlendirebilirsiniz. Ek bilgiler / Benimle paylaşabilecekleriniz • TURN kurmayı tercih eder misiniz yoksa önce aynı LAN’da test mi yapmak istersiniz? • Eğer TURN kuracaksanız: kullanmak istediğiniz alan adı (veya public IP), coturn mu yoksa başka bir TURN mı tercih ediyorsunuz? • Let’s Encrypt ile sertifika almaya uygun bir domain mevcut mu? • rtc-node uygulamanızı hangi Node sürümünde çalıştırıyorsunuz (daha önce v25 belirtmiştiniz)? İsterseniz şimdi adım adım: 1) Eğer domain ve 80/443 açıksa Let’s Encrypt ile coturn sertifikası alma ve coturn.conf örneği veririm. 2) Ya da önce
iceTransportPolicy: 'relay'
ile denedikten sonra curl/tcping çıktılarınızı paylaşırsınız; birlikte kontrol ederiz. Hangi yolu tercih ediyorsunuz?
b
aynı ağ içinde test yapmama rağmen bağlanmıyor, turn'la ilgisi yok bence
t
Anladım — aynı ağ içindeyken bile bağlanmıyor; bu durumda TURN büyük olasılıkla suçlu değil. Elinizdeki loglar ve yaptıklarınız ışığında başka olası nedenleri daraltıp hızlı, hedefe yönelik testler önereceğim. Önce hangi noktaya cevap verdiğimi belirteyim: rtc-node ile signaling başarılı ama peer connection kurulamadı; şimdi aynı LAN testinde bile başarısız olduğunuzu söylediniz, o yüzden odak ağ/SDP/yerel ortam ve sdk ortam farklarına kayıyor. Kısa kontrol listesi (hızlı, sırayla deneyin) 1) RTC-Node süreç loglarını ve SDP/ICE adaylarını kaydedin • rtc-node tarafında offer/answer ve ICE candidate’ları loglayın. Böylece server’a hangi candidate’ları gönderdiğinizi görürüz. Eğer sadece host (127.x/192.168.x) adayları görünüyorsa ve karşı taraftan route yoksa sorun görülebilir. • Nasıl: bağlantı kurulurken
room.on('signal', msg => console.log(msg))
benzeri bir yakalama ile SDP/ICE mesajlarını alın. 2) Paket yakalama (aynı makinede) • Deneme sırasında server ve client makinelerinde udp portları için tcpdump çalıştırın (ör. 10000–20000 aralığı). • Amaç: ICE paketleri gerçekten gidip geliyor mu, yoksa hiç UDP paketi gelmiyor mu görmek. • Örnek: sudo tcpdump -n -i eth0 udp and portrange 10000-20000 3) Host binding / advertised IP kontrolü • LiveKit sunucunuzun node_ip veya public_ip ayarları doğru mu? Eğer sunucu kendini 127.0.0.1 veya iç IP ile ilan ediyorsa aynı LAN’da bile paket rotası bozulabilir. • Konfigda node’un hangi IP’yi advertise ettiğini (server loglarında görünen candidate IP’leri) kontrol edin. 4) localhost vs LAN test farkı • Client ve server aynı fiziksel makine üzerinde ise (localhost/127.0.0.1), deneyin: hem server hem client aynı hostta çalıştırıp bağlanıyor mu? • Ardından aynı LAN’daki farklı makineler (aynı switch/router) ile test edin. Bu adımın amacı host- ve ağ-özel farkları görmek. 5) Firewall / host güvenlik yazılımı • Hem client hem server makinelerinde OS firewall (iptables/nftables/ufw, Windows Defender vb.) kapatıp deneyin kısa süreli test için. • Bazı sistemlerde outbound UDP kısıtlı olabilir; bütün yönleri geçici olarak açık hale getirip tekrar deneyin. 6) Node / rtc-node native bağımlılıkları ve sürüm • Hangi Node.js sürümü kullanıyorsunuz? rtc-node native WebRTC binding’leri bazı Node sürümlerinde sorun çıkarabilir. Daha stabil olan Node 18 veya Node 20 ile deneyin. • rtc-node sürümü ile server sürümünün uyumluluğunu kontrol edin (SDK 0.13.24 görünüyor). 7) Duplicate identity / reconnect davranışı • Loglarda
DUPLICATE_IDENTITY
mesajları var; test sırasında aynı identity ile hızlı tekrar bağlantı denemeleri oluyor mu? Bu, eski oturum temizlenmeden yeni oturum açılmasına ve beklenmeyen kapanmalara yol açabilir. Testler sırasında tek katılımcı/tek identity kullanın. Hedefe yönelik ilk iki öneri (en hızlı sonuç üretecek) 1) SDP/ICE adaylarını logla ve paylaş • Bunu yapınca adaylarda sadece
host
mı yoksa `srflx`/`relay` de mi olduğunu göreceğiz. Host-only adaylar NAT/firewall problemi işaret eder. 2) Basit paket yakalama • İki makinede tcpdump ile bağlantı denenirken UDP paketleri gelip gelmediğini kontrol et. Eğer hiçbir UDP paket gelmiyorsa problem yerel firewall/OS ağ yönlendirmesinde demektir. Bana şu bilgileri paylaşırsanız daha doğrudan çözüm verebilirim • rtc-node uygulamanızın çalıştığı işletim sistemi, Node sürümü. • Server’ın LiveKit node olarak hangi IP’yi advertise ettiğinin çıktısı (ya da rtc-node tarafından görülen SDP’deki candidate’lardan birkaç örnek — IP’leri sansürleyebilirsiniz). • Paket yakalama çıktısında UDP trafiğinin gözüküp gözükmediği (kısa tcpdump çıktısı). • Testleri yaparken aynı kimlikle (identity) tekrar bağlanma yapıp yapmadığınız. İsterseniz önce SDP/ICE adaylarını nasıl loglayacağınızı gösteririm ve hemen ardından tcpdump komutlarını veririm. Hangi adımla başlamak istersiniz?
b
root@rendex-livekit:~# sudo tcpdump -n -i eth0 udp and portrange 10000-20000 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes bunda hiçbir sonuç çıkmıyor node v25.6.1 ubuntu 22 livekit server'ı public ipyi advertise ediyor onda da sorun yok. aynı kimlikle tekrar bağlanmıyoz
t
Thanks — this is helpful. You ran tcpdump and saw no UDP packets in the 10000–20000 range, you’re on Node v25.6.1 / Ubuntu 22, the LiveKit server advertises a public IP, and you’re not reusing the same identity. Given that, the next steps focus on why UDP traffic never shows up (which explains the ICE timeout). What this means • No UDP packets on the media port range means the client never attempted or never reached the server over those ports. That points to one of: ◦ OS or host-level firewall blocking outbound or inbound UDP on the rtc-node host. ◦ Network-level filtering (cloud security group, router, or enterprise network) blocking UDP egress or return traffic. ◦ rtc-node not actually using UDP on that host because of runtime/native issues (e.g., native WebRTC not initialized due to Node compatibility or missing libs). Targeted checks — do these in order (each is quick and helps narrow the cause) 1) Temporarily allow all UDP on both host and server (short test) • On both client and server hosts (if you control both), temporarily disable host firewall to eliminate OS-level blocking: ◦ Ubuntu quick test: ▪︎ sudo ufw status ▪︎ sudo ufw disable ◦ Or flush iptables rules (test only, be cautious if remote SSH): ▪︎ sudo iptables -S ▪︎ sudo iptables -F • Retry connection and re-run tcpdump. If UDP appears after disabling firewall, re-enable and add rules to allow the port range. 2) Test UDP connectivity with a simple UDP echo between hosts • From rtc-node host, send a UDP packet to the server’s media port and see if server receives it (and vice versa). Example using netcat: ◦ On server: sudo apt install netcat-openbsd ▪︎ nc -u -l 10001 ◦ On client: printf "ping" | nc -u <server_ip> 10001 • If packets never arrive, network-level filtering is blocking UDP. 3) Check cloud provider / network security rules • If hosts are in cloud (AWS/GCP/OVH etc.), verify Security Group / firewall / VPC rules allow UDP outbound from client and UDP inbound to server for the chosen media port range. Many clouds block ephemeral UDP by default. 4) Verify rtc-node actually attempts ICE/UDP (enable debug) • Enable verbose logs in rtc-node to capture SDP + ICE events. Add logging around signal events and ICE candidate gathering:
Copy code
room.on('signal', (msg) => console.log('signal:', msg));
  room.on('connectionStateChanged', (s) => console.log('conn state:', s));
  // and log offer/answer SDPs and candidate lines when received
• Also enable debug env if supported (check rtc-node docs) so native WebRTC stack logs appear. Share the candidate lines you see (you can redact IPs). 5) Try a more stable Node runtime • Node v25 is experimental and can cause native addon issues. Try running your rtc-node app with Node 18 or 20 and repeat the test. If the native WebRTC binding fails silently on v25, it may not open UDP sockets. 6) Quick browser client check • From any machine on the same LAN as your rtc-node host, open a simple browser-based LiveKit client and connect to the same room. Browsers often have clearer fallbacks and easier debugging — if the browser also fails to establish ICE (and tcpdump still sees no UDP), it confirms network blocking rather than rtc-node-specific issues. 7) Check server advertised candidates in SDP • Capture the SDP the server sends back and verify the candidate types:
host
,
srflx
,
relay
. If the server only advertises
host
and it’s not reachable, that can still fail on same LAN if the IPs are incorrect. Paste a few candidate lines (redact IPs) and I’ll examine them. If you prefer a concrete next action, do this now and paste the results: 1. Temporarily disable ufw on the rtc-node host (sudo ufw disable), rerun tcpdump, attempt connect, and paste whether you now see UDP packets. 2. If you prefer not to disable firewall, run the UDP netcat test from step 2 and paste whether packets arrive. If you run into anything you’re unsure about, tell me which step you did and the exact output — I’ll interpret it and tell you the precise fix.
b
Test UDP connectivity with a simple UDP echo between hosts • From rtc-node host, send a UDP packet to the server’s media port and see if server receives it (and vice versa). Example using netcat: ◦ On server: sudo apt install netcat-openbsd ▪︎ nc -u -l 10001 ◦ On client: printf "ping" | nc -u <server_ip> 10001 • If packets never arrive, network-level filtering is blocking UDP. bundfan hiçbir sonuç gelmiyor ama firewall da kapalı sunucuda
t
Teşekkürler — paylaştıkların çok yardımcı oldu. Özetle: UDP echo/netcat testinde hiçbir paket gelmiyor, sunucu tarafında firewall kapalı, tcpdump da 10000–20000 aralığında hiçbir UDP trafik göstermiyor. Bu durumda UDP trafiğinin uçtan uca ya hiç gönderilmediği ya da ağda (host dışında) engellendiği kesinleşiyor. Hemen takip edebileceğin hedefe yönelik adımlar ve hangi çıktıları paylaşman gerektiğini aşağıda sıralıyorum. Neyi doğrulamış olduk • Signaling (WS/token) çalışıyor; server NODE client oturumunu kabul ediyor. • Ancak medya paketi (UDP) hiç görünmüyor — ICE candidate değiş tokuşu gerçekleşse bile medya yolu kurulmamış. • TURN kullanmıyorsun ve aynı LAN’da testte bile UDP görünmüyor; bu TURN dışı bir sorun. Öncelikli olasılıklar • Host işletim sistemi veya konteyner içinde UDP egress/inbound engelli (istemci uygulama UDP açmıyor veya native modül problemli). • Ağ (switch/router veya cloud security group) UDP trafiğini düşürüyor (özellikle outbound UDP kısıtlı). • rtc-node’nin native WebRTC kütüphanesi Node v25 ile düzgün çalışmıyor; bu durumda UDP soketleri açılmıyor. Hedefe yönelik adımlar (sırayla, her adım kısa ve açıklayıcı) 1) Basit UDP testi — iki yönden kontrol et (hızlı) • Sunucuda (alıcı): sudo apt update && sudo apt install -y netcat-openbsd nc -u -l 10001 • İstemcide (gönderici): printf "ping" | nc -u <SERVER_IP> 10001 • Beklenen: sunucuda "ping" gözükmeli. Göstermezse ağda/host düzeyinde UDP engelleniyor. • Lütfen bunu bir kez daha deneyip sonucu söyle (hangi hosttan denedin, aynı VM mi farklı makineler mi). 2) Host firewall ve iptables kontrolü (tekrar doğrulama) • UFW durumu: sudo ufw status verbose • Iptables kuralları: sudo iptables -L -n -v • Eğer kurallar varsa, geçici olarak tüm iptables kurallarını (özellikle UDP ile ilgili) temizleyip tekrar deneyebilirsin (SSH kullanıyorsan dikkatli ol): sudo iptables -F • Bu adımı yaptıktan sonra netcat testini tekrar dene ve sonucu paylaş. 3) Ağ sağlayıcı / cloud security group kontrolü • Eğer sunucu veya istemci bulutta ise (VPS/Cloud), güvenlik grupları ya da provider seviyesinde outbound UDP veya inbound UDP bloklanmış olabilir. Provider panelinden: ◦ VM/instance için UDP outbound izinlerini kontrol et. ◦ VPC/SG/Security Firewall kurallarını kontrol et. • Hangi sağlayıcıda olduğunu ve ilgili security group kurallarını paylaşabilir misin? Ben kontrol etmen için hangi rule’ları araman gerektiğini söyleyeyim. 4) Node sürümü/rtc-node native sorunu testi • Node v25 kullanıyorsun; bu sürüm native eklentilerle beklenmedik sorunlar çıkarabilir. Hızlı test: uygulamayı Node 18 veya Node 20 ile çalıştırıp tekrar deney. • Nasıl: ◦ nvm kullanıyorsan: nvm install 18 && nvm use 18 • Ardından rtc-node uygulamanı yeniden başlat ve tcpdump + netcat testini tekrar et. • Eğer Node 18 ile UDP paketi görülürse, sorunun kaynağı Node v25 uyumsuzluğudur. 5) rtc-node’in ICE/SDP üretip üretmediğini logla • Uygulamada
signal
ve ICE olaylarını loglamak bize adayların (candidates) tipini gösterecek:
Copy code
room.on('signal', (msg) => console.log('signal:', JSON.stringify(msg)));
     room.on('connectionStateChanged', (s) => console.log('conn state:', s));
• Paylaşman gereken: signal mesajlarında görünen ICE adaylarından birkaç satır (candidate=... içeren bölümü). IP’leri sansürleyebilirsin. • Eğer hiç candidate gözükmüyorsa, rtc-node ICE toplama yapmıyor demektir (runtime/native problem). 6) Alternatif hızlı kontrol — browser istemci ile test • Aynı LAN’daki bir bilgisayarda tarayıcı ile LiveKit demo/örnek bağlantısı kurmayı dene. Browser da UDP paketleri gönderip tcpdump üzerinde görünüyor mu kontrol et. Eğer tarayıcıdan da paket gelmiyorsa kesinlikle ağ/host düzeyinde bir engel var. Hangi çıktıları paylaşmalısın (bana gönder) • Netcat testinin tam çıktısı: hem sunucu tarafında (nc -u -l) hem istemci tarafında (nc komutunun çıktısı). •
sudo iptables -L -n -v
ve
sudo ufw status verbose
çıktıları. • Eğer Node sürümünü değiştirip denersen: Node sürümü ve tcpdump sonucu (yoksa “yine yok” diye belirt). • rtc-node’den aldığın
signal
mesajlarındaki ICE candidate satırlarından 2-3 örnek (IP’leri sansürle). Kısa yol önerisi (en hızlı teyit için) • Hemen şimdi yapabileceğin en hızlı iki test: 1) Netcat UDP testini hem yönde çalıştır (server dinle, client gönder) ve sonucu yaz. 2) Node sürümünü 18’e indirip uygulamayı çalıştır, tcpdump yeniden başlat, tekrar dene. Sonuçları paylaş. Benimle hangi testi yaptığını ve çıktılarını paylaşırsan bir sonraki adımı doğrudan söyleyeceğim (ör. iptables kuralı ekleme, cloud security rule örneği, veya rtc-node rebuild önerisi). Hangi testi şimdi yapıyorsun?
b
hiç candidate gözüğkmüyor
t
Anladım — “hiç candidate gözükmüyor” demen önemli bir tespit. Bu, artık büyük olasılıkla rtc-node tarafında ICE adaylarının hiç toplanmadığını (yani yerel WebRTC yığını başlatılamadığını) gösteriyor — ağ tarafı engeli olsa bile en azından host adayları görünür. Aşağıda adım adım yapılacakları veriyorum; önce en olası yazılım/sistem sebeplerini kontrol edeceğiz, sonra tekrar ICE toplama ve tcpdump testine bakarız. Özet teşhis (neden candidate yok) • rtc-node native WebRTC bileşeni doğru yüklenmemiş veya başlatılamıyor (native addon sorunları). • Node v25 kullanıyorsun; bu deneysel sürüm native eklentilerle uyumsuzluk yaratabilir. • Eksik sistem kütüphaneleri veya derleme zamanı hataları nedeniyle rtc-node ICE toplama yapmıyor. Hızlı yol haritası (öncelikli, sırayla yap) 1) Node sürümünü LTS’ye çek ve bağımlılıkları yeniden kur • Node 18 veya 20 kullan: ◦ Eğer nvm yüklü ise: i. nvm install 18 ii. nvm use 18 iii. node -v # doğrula: v18.x ◦ Proje dizininde: i. rm -rf node_modules package-lock.json ii. npm install • Amaç: rtc-node native modülünün stabil, uyumlu bir runtime altında düzgün kurulup başlatıldığını görmek. 2) Gerekli sistem kütüphanelerini yükle (Ubuntu 22 için) • native WebRTC/derlemeler için bazı kütüphaneler eksikse sorun olur. Aşağısını çalıştır: sudo apt update sudo apt install -y build-essential pkg-config libssl-dev git ca-certificates • Ardından proje dizininde tekrar
npm install
yap. 3) rtc-node paketinin kurulum ve runtime hatalarını yakala • npm install sırasında çıkan hataları kontrol et; özellikle native addon derleme/uprade uyarıları varsa kopyala. • Uygulamayı başlatırken stdout/stderr’i kaydet: node yourApp.js 2>&1 | tee run.log • Eğer native modül yükleme başarısızsa burada hata görünür. 4) RTC-NODE debug/ICE logging’i aç • Uygulamada signal/connection event’lerini logla. Örnek:
Copy code
room.on('signal', (msg) => console.log('signal:', JSON.stringify(msg)));
     room.on('connectionStateChanged', (s) => console.log('conn state:', s));
     room.on('iceCandidate', (c) => console.log('ice candidate:', c));
• Eğer
iceCandidate
veya signal içinde
candidate=
satırı yoksa rtc-node ICE toplama yapmıyor demektir. 5) Eğer hala candidate yoksa — package rebuild / reinstall deneyin • node-gyp/rebuild ile native modülü yeniden derle: npm rebuild @livekit/rtc-node --build-from-source • Ya da tamamen silip yeniden kur: npm uninstall @livekit/rtc-node npm install @livekit/rtc-node 6) Alternatif doğrulama: Minimal örnek çalıştır • Sıfırdan küçük bir test dosyası ile sadece
room.connect
yap ve tüm signal mesajlarını bas: ◦ Bu, kendi uygulama mantığının üstündeki bir sorun olup olmadığını ayırır. 7) Eğer native hata veya izin/sistem sorunu çıkarsa paylaş • npm install / rebuild çıktılarını paylaş (hataları kopyala, gizli anahtar yoksa logu olduğu gibi paylaşabilirsin). • run.log içindeki başlangıç hatalarını paylaş. Eğer yukarıdaki adımlardan sonra candidate görünür hale gelirse: • tcpdump ile tekrar kontrol et; artık UDP paketleri geliyorsa ICE başlayacaktır. • Eğer candidate’lar çıkıyor ama yine UDP yoksa ağ/iptables/security group adımlarına geri döneriz. Hızlı test önerisi — şu an ne yapalım? • Hemen önce: Node’u 18 yapıp
npm install
ile yeniden kurar mısın, sonra uygulamayı başlatıp signal/ice log çıktısını paylaşır mısın? • Eğer istersen `npm install`/`npm rebuild` çıktısını buraya yapıştır; ben çıktılarda native addon hatalarını arayıp yönlendireyim. Senin için sıradaki en etkili adım Node sürümünü 18’e almak ve yeniden kurmak olacaktır. Dilersen adımların komutlarını yine baştan veririm ve çıktıları nasıl paylaşacağını söylerim. Hangi adımla başlamak istersin?
b
hala candidateler gözükmüyor, yeniden build ettim node 18'e geçtim fakat çözülmedi.
t
Thanks — you’ve done a lot of great troubleshooting already. You’ve confirmed: • Signaling reaches the server and the server accepts the NODE client. • tcpdump shows no UDP media packets. • Netcat UDP tests show no UDP traffic arriving. • rtc-node shows no ICE candidates, even after switching to Node 18 and rebuilding. Given all that, the most likely remaining cause is that the native WebRTC component used by
@livekit/rtc-node
never initializes or cannot create sockets on your host — so it never gathers candidates. Let’s focus on deeper runtime/native diagnostics and a reproducible minimal test to identify the failure. Next focused checks (do these in order) 1) Capture runtime stderr/stdout for native initialization errors • Start your app and capture logs to a file: node yourApp.js > run.log 2>&1 • Reproduce a connection attempt, then paste the tail of run.log (last ~200 lines). Look for errors referencing native modules,
libwebrtc
,
dlopen
, symbol errors, or permission/EPERM errors. 2) Check that the native addon is loaded • In Node REPL or a tiny script, require the rtc-node module and log if it loads:
Copy code
try {
    const rtc = require('@livekit/rtc-node');
    console.log('rtc-node loaded', Object.keys(rtc));
  } catch (e) {
    console.error('failed to load rtc-node:', e);
  }
• Run that script under Node 18 and paste the output/error. 3) Rebuild with verbose output and watch for errors • Run: npm rebuild @livekit/rtc-node --build-from-source 2>&1 | tee rebuild.log • Inspect rebuild.log for build/link errors or missing libraries. Paste any errors you see. 4) Ensure required system libraries are installed (Ubuntu 22) • Install libraries commonly needed by native WebRTC bindings: sudo apt update sudo apt install -y build-essential pkg-config libssl-dev ca-certificates \ libasound2 libpulse0 libudev1 libx11-6 libxrandr2 libxss1 \ libxtst6 libpci3 libglib2.0-0 libnss3 libgbm1 • After installing, remove node_modules and reinstall: rm -rf node_modules package-lock.json npm install 5) Run a minimal repro that only attempts connect and logs signals • Create test.js:
Copy code
const { Room } = require('@livekit/rtc-node');

  (async () => {
    const room = new Room();
    room.on('signal', (msg) => console.log('signal:', JSON.stringify(msg)));
    room.on('connectionStateChanged', (s) => console.log('conn state:', s));
    try {
      await room.connect(process.env.LK_URL, process.env.LK_TOKEN);
      console.log('connected');
    } catch (e) {
      console.error('connect failed:', e);
    }
  })();
• Run with environment variables set and capture output: LK_URL=... LK_TOKEN=... node test.js > test.log 2>&1 • Paste the test.log tail (redact token). 6) If rtc-node loads but still no candidates, check permission/SELinux/container issues • Are you running inside a container (Docker) or with AppArmor/SELinux enabled? Some container runtimes restrict raw sockets or UDP behavior. • If Docker: ensure the container has NET_ADMIN or the network mode is host for tests: docker run --network host ... • If running as non-root, try running as root for a quick test. 7) Try a prebuilt example from LiveKit repo / official example • Clone the JS examples and run their Node native example to see if candidates appear: git clone https://github.com/livekit/client-sdk-js cd client-sdk-js/examples/node npm install follow example README to run with your URL/token What to share next (paste these outputs) • Output of the tiny require test (step 2). • Tail of run.log or rebuild.log showing native errors (steps 1 & 3). • test.log from the minimal repro (step 5). • Tell me whether you run in Docker or bare VM, and whether you can try host networking or run as root temporarily. If you prefer, I can give the exact commands to run each step and explain how to redact sensitive lines. Which step would you like to run first?