File size: 7,364 Bytes
e62aafd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env python3
"""
Teste WebRTC automatizado com Playwright headless
"""

import asyncio
from playwright.async_api import async_playwright
import sys

SERVER_URL = "http://62.107.25.198:47898"

async def test_webrtc():
    print("="*60)
    print("Teste WebRTC com Playwright (Headless)")
    print("="*60)

    async with async_playwright() as p:
        # Iniciar browser headless
        print("\n[1/6] Iniciando browser headless...")
        browser = await p.chromium.launch(
            headless=True,
            args=[
                '--use-fake-ui-for-media-stream',
                '--use-fake-device-for-media-stream',
                '--no-sandbox'
            ]
        )

        context = await browser.new_context(
            permissions=['camera', 'microphone']
        )

        page = await context.new_page()

        # Coletar logs do console e erros
        console_logs = []
        page_errors = []

        page.on("console", lambda msg: console_logs.append(f"[{msg.type}] {msg.text}"))
        page.on("pageerror", lambda exc: page_errors.append(f"ERROR: {exc}"))

        # Capturar requests/responses
        network_logs = []

        def handle_response(response):
            if '/offer' in response.url:
                network_logs.append(f"POST /offer → Status: {response.status}")
                if response.status != 200:
                    network_logs.append(f"  Error: {response.status_text}")

        page.on("response", handle_response)

        # Navegar para a página
        print(f"[2/6] Navegando para {SERVER_URL}...")
        try:
            await page.goto(SERVER_URL, timeout=10000)
            print("✓ Página carregada")
        except Exception as e:
            print(f"✗ Erro ao carregar página: {e}")
            await browser.close()
            return False

        # Verificar se a página carregou
        print("[3/6] Verificando elementos...")
        try:
            await page.wait_for_selector('#btnConnect', timeout=5000)
            print("✓ Botão 'Conectar' encontrado")
        except Exception as e:
            print(f"✗ Erro: {e}")
            await browser.close()
            return False

        # Injetar código para capturar eventos ICE
        print("[4/6] Configurando captura de eventos ICE...")
        await page.evaluate("""
            window.iceInfo = {
                candidates: [],
                states: [],
                connectionStates: []
            };

            // Interceptar console.log de ICE candidates
            const originalLog = console.log;
            console.log = function(...args) {
                if (args[0] === 'ICE Candidate:') {
                    window.iceInfo.candidates.push(args[1]);
                } else if (args[0] === 'ICE State:') {
                    window.iceInfo.states.push(args[1]);
                } else if (args[0] === 'Estado WebRTC:') {
                    window.iceInfo.connectionStates.push(args[1]);
                }
                originalLog.apply(console, args);
            };
        """)

        # Clicar em conectar
        print("[5/6] Clicando em 'Conectar'...")
        await page.click('#btnConnect')

        # Aguardar tentativa de conexão
        print("[6/6] Aguardando conexão (15s)...")
        await asyncio.sleep(15)

        # Capturar informações ICE
        ice_info = await page.evaluate("window.iceInfo")

        # Capturar estado da conexão
        webrtc_state = await page.evaluate("""
            (() => {
                const pc = window.pc;
                if (!pc) return null;
                return {
                    connectionState: pc.connectionState,
                    iceConnectionState: pc.iceConnectionState,
                    iceGatheringState: pc.iceGatheringState,
                    signalingState: pc.signalingState
                };
            })()
        """)

        # Resultados
        print("\n" + "="*60)
        print("RESULTADOS")
        print("="*60)

        if webrtc_state:
            print(f"\nEstados WebRTC:")
            print(f"  Connection:     {webrtc_state['connectionState']}")
            print(f"  ICE Connection: {webrtc_state['iceConnectionState']}")
            print(f"  ICE Gathering:  {webrtc_state['iceGatheringState']}")
            print(f"  Signaling:      {webrtc_state['signalingState']}")
        else:
            print("\n✗ Peer connection não foi criada!")

        # Análise de candidatos ICE
        candidates = ice_info.get('candidates', [])
        print(f"\nCandidatos ICE: {len(candidates)}")

        candidate_types = {}
        for c in candidates:
            ctype = c.get('type', 'unknown')
            candidate_types[ctype] = candidate_types.get(ctype, 0) + 1

        for ctype, count in candidate_types.items():
            icon = "✓" if ctype == "relay" else "•"
            print(f"  {icon} {ctype}: {count}")

        # Diagnóstico
        print("\n" + "="*60)
        print("DIAGNÓSTICO")
        print("="*60)

        success = False

        if not webrtc_state:
            print("\n✗ FALHA: Peer connection não foi criada")
            print("  → Verificar JavaScript do frontend")

        elif webrtc_state['connectionState'] == 'connected':
            print("\n✓ SUCESSO: WebRTC conectado!")
            success = True

        elif webrtc_state['iceConnectionState'] == 'failed':
            print("\n✗ FALHA: ICE connection failed")

            if len(candidates) == 0:
                print("  → Problema: Nenhum candidato ICE gerado")
                print("  → Solução: Verificar configuração STUN/TURN")

            elif 'relay' not in candidate_types:
                print("  → Problema: Nenhum candidato TURN (relay)")
                print("  → Solução: Servidores TURN não estão funcionando")
                print("  → Tentar outros servidores TURN")

            else:
                print("  → Problema: Candidatos gerados mas não conectam")
                print("  → Solução: Problema de firewall/NAT no servidor")
                print("  → Verificar port mapping UDP no vast.ai")

        elif webrtc_state['connectionState'] == 'connecting':
            print("\n⚠ TIMEOUT: Conexão travada em 'connecting'")
            print("  → Problema: ICE negotiation timeout")
            print("  → Causa provável: Port mapping UDP não configurado")
            print("  → Solução: Expor portas UDP no vast.ai ou usar ngrok")

        # Erros de página
        if page_errors:
            print("\n" + "="*60)
            print("ERROS JAVASCRIPT")
            print("="*60)
            for err in page_errors:
                print(err)

        # Logs de rede
        if network_logs:
            print("\n" + "="*60)
            print("LOGS DE REDE")
            print("="*60)
            for log in network_logs:
                print(log)

        # Logs do console
        if console_logs:
            print("\n" + "="*60)
            print("LOGS DO CONSOLE (últimos 20)")
            print("="*60)
            for log in console_logs[-20:]:
                print(log)

        await browser.close()
        return success

async def main():
    success = await test_webrtc()
    sys.exit(0 if success else 1)

if __name__ == "__main__":
    asyncio.run(main())