Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
46d7f1f
Add one-command Windows startup script for OpenKore remote stack
boscv Apr 15, 2026
c68d5f2
Support launcher exe and double-click startup for Windows remote stack
boscv Apr 15, 2026
bbc2e4a
Clarify auto-detection behavior and existing OpenKore reuse in Window…
boscv Apr 15, 2026
d53b4b4
Make Windows helper configure-only by default and document launcher u…
boscv Apr 15, 2026
7603471
Fix PowerShell automatic variable collisions in TCP checks
boscv Apr 15, 2026
de65216
Fix remaining PowerShell Host automatic variable collision
boscv Apr 15, 2026
f233e50
Use platform console loader in Socket interface to avoid Utils::Unix …
boscv Apr 15, 2026
dba46ce
Launch OpenKore in a new window from generated env helper
boscv Apr 15, 2026
5497c8b
Open TCP env launcher in interactive cmd window for local typing
boscv Apr 15, 2026
b487f5f
Use Console::Simple safely on Windows for Socket interface input loop
boscv Apr 15, 2026
6d6eb00
Add one-shot Windows launcher to start OpenKore socket endpoint and g…
boscv Apr 15, 2026
090b88f
Make run-remote.cmd fully standalone and mark as primary simple flow
boscv Apr 15, 2026
ff3df63
Rewrite run-remote.cmd with robust batch conditionals to avoid parser…
boscv Apr 15, 2026
58e3154
Remove dependency on if.pm for Windows compatibility in Console::Simple
boscv Apr 15, 2026
81f6eb7
Use platform console backend in Socket interface to restore Windows i…
boscv Apr 15, 2026
7ce94ee
Launch OpenKore via cmd /k in run-remote to preserve interactive typing
boscv Apr 15, 2026
883f775
Launch OpenKore with normal launcher flow in run-remote
boscv Apr 16, 2026
9b8dee4
Simplify PT-BR docs to single run-remote.cmd flow
boscv Apr 16, 2026
07df042
Remove launcher auto-detection from run-remote and require explicit u…
boscv Apr 16, 2026
979394f
Fix Windows console input by reading from CONIN$
boscv Apr 16, 2026
bcad671
Fix run-remote.cmd to open separate Windows consoles
boscv Apr 16, 2026
37e776f
Fix run-remote.cmd Windows quoting for start/cmd invocations
boscv Apr 16, 2026
983adb5
Default Windows Socket interface to TCP endpoint
boscv Apr 16, 2026
a5ff5d2
Avoid UNIX socket path on Perl builds without sockaddr_un
boscv Apr 16, 2026
442d41e
Fallback to TCP when OPENKORE_SOCKET_TCP_PORT is empty/invalid
boscv Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/guia-acesso-remoto-pt-br.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Por quê:
- O gateway conecta no OpenKore via socket Unix (`--socket`) **ou** via TCP (`--kore-host` + `--kore-port`).
- O fluxo padrão do projeto usa caminhos Unix (`/etc/...`) e serviço `systemd`.

> Importante: para funcionar, o endpoint precisa falar o protocolo de console do OpenKore (`set active/input`). Nem toda porta TCP do OpenKore (ex.: `XKore_port`) é compatível com esse protocolo.
> No Windows nativo, para fluxo simples, use só `tools/run-remote.cmd SEU_TOKEN start.exe` (ou `tkstart.exe`, etc.).
> Esse comando único abre OpenKore + gateway e expõe o endpoint TCP compatível.

Isso significa:

- **Linux nativo**: cenário recomendado e documentado.
Expand Down Expand Up @@ -250,6 +254,8 @@ perl tools/remote_gateway.pl \
```

> Nesse modo, use `--kore-host` + `--kore-port` juntos.
> Importante: `XKore_port` no `config.txt` não garante compatibilidade com o protocolo de console (`set active/input`) usado pelo gateway.
> Se a porta não for compatível, o `/health` ficará com `connected=false` e `/commands` retornará `503 core_unavailable`.

---

Expand Down
72 changes: 60 additions & 12 deletions docs/guia-acesso-remoto-windows-nativo.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,37 @@ python -m json.tool .\config\gateway-users.json | Out-Null; Write-Host "JSON OK"

Você precisa saber host/porta do endpoint TCP.

Exemplo deste guia:
### Pré-requisito crítico

- host: `127.0.0.1`
- porta: `2350`
O `remote_gateway.pl` só consegue falar com um endpoint que implemente o protocolo de console do OpenKore (`set active` / `input`).
Esse endpoint é nativo da **Interface Socket** (arquivo `console.socket`).

Em outras palavras: deixar apenas `XKore_port` configurado não abre automaticamente esse protocolo para o gateway.

⚠️ **Importante:** no OpenKore padrão, `XKore_port` (ex.: `2350`) **não é automaticamente** o endpoint de console remoto esperado pelo `remote_gateway.pl` (`set active/input`).

### Fluxo único (simples, recomendado)

> No Windows, ao usar `--interface=Socket`, o OpenKore agora usa TCP por padrão em `127.0.0.1:2350` se `OPENKORE_SOCKET_TCP_PORT` não estiver definido.

Use **só** este arquivo:

```text
tools\run-remote.cmd UM_TOKEN_LONGO_E_ALEATORIO start.exe
```

Ele já:
- abre **uma janela separada** para OpenKore com `--interface=Socket` usando o launcher que **você** informar (`start.exe`, `tkstart.exe`, etc.);
- configura endpoint TCP de console em `127.0.0.1:2350`;
- abre **outra janela separada** para o gateway em `127.0.0.1:18085`.

Valide:

```powershell
Test-NetConnection 127.0.0.1 -Port 2350
```

Se `TcpTestSucceeded` for `False`, o gateway vai subir com `/health`, mas ficará com `connected=false` e retornará `503 core_unavailable` em `/commands`.

---

Expand All @@ -114,6 +141,24 @@ No PowerShell, dentro de `C:\openkore`:
perl .\tools\remote_gateway.pl --kore-host 127.0.0.1 --kore-port 2350 --listen-host 127.0.0.1 --listen-port 18085 --command-token "UM_TOKEN_LONGO_E_ALEATORIO" --audit-file ".\\logs\\gateway_audit.jsonl" --command-rate-limit 30 --command-rate-window 60 --auth-enabled --users-file ".\\config\\gateway-users.json" --token-ttl 900 --session-file ".\\data\\gateway_sessions.json"
```

> Se quiser manter nativo no Windows, prefira abrir o endpoint com `OPENKORE_SOCKET_TCP_PORT` + `--interface=Socket` (bloco acima).

### Modo ultra simples (recomendado)

Sem digitar vários comandos: execute **um arquivo**:

```text
tools\run-remote.cmd UM_TOKEN_LONGO_E_ALEATORIO
```

Esse `.cmd`:
- abre OpenKore (launcher detectado automaticamente) com `--interface=Socket`;
- configura `OPENKORE_SOCKET_TCP_HOST=127.0.0.1` e `OPENKORE_SOCKET_TCP_PORT=2350`;
- inicia o gateway em `127.0.0.1:18085` **sem depender** de `start-gateway.ps1`.
- o OpenKore é aberto pelo launcher normal (`start.exe`/`tkstart.exe`/etc), como no fluxo de duplo clique.

> Se seu objetivo é simplicidade, use somente `tools\run-remote.cmd` e ignore os outros scripts auxiliares.

---

## 7) Testar pelo Windows (browser + PowerShell)
Expand Down Expand Up @@ -158,28 +203,31 @@ Se seu Windows não aceita SSH inbound, use VPN/Tailscale/ZeroTier e exponha ape

## 9) Inicialização automática no Windows

Use o script pronto: `scripts/start-gateway.ps1`.

Ele detecta automaticamente a raiz do OpenKore quando executado de dentro do repositório.
Também existe atalho em `tools/start-gateway.ps1`.

Exemplo manual (PowerShell):
Para manter simples, agende **um comando só**:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\start-gateway.ps1 -KoreHost "127.0.0.1" -KorePort 2350 -ListenHost "127.0.0.1" -ListenPort 18085 -CommandToken "UM_TOKEN_LONGO_E_ALEATORIO"
powershell -NoProfile -ExecutionPolicy Bypass -Command "& { cd 'C:\openkore'; .\tools\run-remote.cmd UM_TOKEN_LONGO_E_ALEATORIO }"
```

Depois crie uma tarefa no **Task Scheduler** chamando:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File C:\openkore\scripts\start-gateway.ps1
powershell -NoProfile -ExecutionPolicy Bypass -Command "& { cd 'C:\openkore'; .\tools\run-remote.cmd UM_TOKEN_LONGO_E_ALEATORIO }"
```

---

## 10) Troubleshooting comum (Windows nativo)

- **Gateway não inicia com erro de conexão**: host/porta TCP do OpenKore incorretos.
- **`Status conectado ao OpenKore: False` + erro `core_unavailable (503)` na UI**:
- O gateway está de pé, mas **não conseguiu abrir sessão com o endpoint do OpenKore**.
- Confira no PowerShell se a porta realmente aceita TCP:
```powershell
Test-NetConnection 127.0.0.1 -Port 2350
```
- Se `TcpTestSucceeded` vier `False`, a porta configurada em `--kore-port` está incorreta/inativa.
- Atenção: `XKore_port` pode existir no `config.txt` e **mesmo assim não ser** o endpoint que fala o protocolo de console (`set active/input`) esperado pelo `remote_gateway.pl`.
- **porta 18085 não abre no Windows**: confirme que gateway está rodando e bound em `127.0.0.1`.
- **401/403**: revisar usuário/senha/token/header.
- **sem eventos**: OpenKore não está acessível no endpoint TCP configurado.
Expand All @@ -191,4 +239,4 @@ powershell -NoProfile -ExecutionPolicy Bypass -File C:\openkore\scripts\start-ga
```powershell
perl .\src\test\unittests.pl RemoteGatewaySmokeTest
bash .\tools\check_gateway_release.sh
```
```
40 changes: 29 additions & 11 deletions src/Interface/Console/Simple.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,56 @@ use Globals qw(%consoleColors);
use Interface;
use base qw(Interface);
use I18N qw(UTF8ToString);
use Utils::Unix;

BEGIN {
if ($^O ne 'MSWin32') {
require Utils::Unix;
Utils::Unix->import();
}
}

sub new {
my $class = shift;
binmode STDOUT;
STDOUT->autoflush(0);
return bless {}, $class;
my $self = bless {}, $class;
if ($^O eq 'MSWin32') {
if (open(my $conin, '<', 'CONIN$')) {
$self->{conin} = $conin;
}
}
return $self;
}

sub DESTROY {
print STDOUT Utils::Unix::getColor('default');
print STDOUT Utils::Unix::getColor('default') if $^O ne 'MSWin32';
STDOUT->flush;
}

sub getInput {
my ($self, $timeout) = @_;
my $line;
my $bits;
my $in = $self->{conin} || \*STDIN;
my $fd = fileno($in);
return undef if !defined $fd;

if ($timeout < 0) {
my $done;
while (!$done) {
$bits = '';
vec($bits, fileno(STDIN), 1) = 1;
vec($bits, $fd, 1) = 1;
if (select($bits, undef, undef, 1) > 0) {
$line = <STDIN>;
$line = <$in>;
$done = 1;
}
}

} else {
$bits = '';
vec($bits, fileno(STDIN), 1) = 1;
vec($bits, $fd, 1) = 1;
if (select($bits, undef, undef, $timeout) > 0) {
$line = <STDIN>;
$line = <$in>;
}
}

Expand All @@ -79,10 +94,13 @@ sub getInput {

sub writeOutput {
my ($self, $type, $message, $domain) = @_;
my ($code, $reset) = (
Utils::Unix::getColorForMessage(\%consoleColors, $type, $domain),
Utils::Unix::getColor('reset'),
);
my ($code, $reset) = ('', '');
if ($^O ne 'MSWin32') {
($code, $reset) = (
Utils::Unix::getColorForMessage(\%consoleColors, $type, $domain),
Utils::Unix::getColor('reset'),
);
}
$message =~ s/\n/$reset\n$code/sg;
$message = $code.$message.$reset;

Expand Down
88 changes: 63 additions & 25 deletions src/Interface/Socket.pm
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use Interface;
use Translation;
use base qw(Interface);
use Utils qw(timeOut);
use Interface::Console::Simple;
use Interface::Console;

use constant MAX_LOG_ENTRIES => 5000;

Expand All @@ -66,7 +66,7 @@ sub new {
my (%self, $f);

$self{server} = new Interface::Socket::Server();
$self{console} = new Interface::Console::Simple();
$self{console} = new Interface::Console();
open($f, ">:utf8", "$Settings::logs_folder/console.log");
$self{consoleLogFile} = $f;
$self{logEntryCount} = 0;
Expand Down Expand Up @@ -169,6 +169,9 @@ package Interface::Socket::Server;

use strict;
use IO::Socket::UNIX;
use IO::Socket::INET;
use Socket ();
use Errno qw(EADDRINUSE);
use Base::Server;
use base qw(Base::Server);
use Settings;
Expand All @@ -184,39 +187,72 @@ sub new {
my ($class) = @_;
my $socket_file = "$Settings::logs_folder/console.socket";
my $pid_file = "$Settings::logs_folder/openkore.pid";
my $socket = new IO::Socket::UNIX(
Local => $socket_file,
Type => SOCK_STREAM,
Listen => 5
);
if (!$socket && $! == 98) {
$socket = new IO::Socket::UNIX(
Peer => $socket_file,
Type => SOCK_STREAM
my $tcp_host = $ENV{OPENKORE_SOCKET_TCP_HOST} || '127.0.0.1';
my $unix_socket_supported = eval { Socket::pack_sockaddr_un($socket_file); 1 };
my $tcp_port_env = $ENV{OPENKORE_SOCKET_TCP_PORT};
my $default_tcp_port = (!$unix_socket_supported || $^O eq 'MSWin32') ? 2350 : 0;
my $tcp_port = ($tcp_port_env && $tcp_port_env =~ /^\d+$/ && $tcp_port_env > 0)
? $tcp_port_env
: $default_tcp_port;
my $use_tcp = ($tcp_port =~ /^\d+$/ && $tcp_port > 0);
my ($socket, $endpoint_desc);

if ($use_tcp) {
$socket = new IO::Socket::INET(
LocalAddr => $tcp_host,
LocalPort => $tcp_port,
Proto => 'tcp',
Type => SOCK_STREAM,
Listen => 5,
ReuseAddr => 1
);
if (!$socket) {
unlink($socket_file);
print STDERR "Cannot listen at '$tcp_host:$tcp_port': $!\n";
exit 1;
}
$endpoint_desc = "$tcp_host:" . $socket->sockport;
print "Interface::Socket TCP endpoint listening at $endpoint_desc\n";
} else {
$socket = new IO::Socket::UNIX(
Local => $socket_file,
Type => SOCK_STREAM,
Listen => 5
);
if (!$socket && $! == EADDRINUSE) {
$socket = new IO::Socket::UNIX(
Local => $socket_file,
Type => SOCK_STREAM,
Listen => 5
Peer => $socket_file,
Type => SOCK_STREAM
);
} else {
print STDERR "There is already an OpenKore instance listening at '$socket_file'.\n";
if (!$socket) {
unlink($socket_file);
$socket = new IO::Socket::UNIX(
Local => $socket_file,
Type => SOCK_STREAM,
Listen => 5
);
} else {
print STDERR "There is already an OpenKore instance listening at '$socket_file'.\n";
exit 1;
}
}
if (!$socket) {
if ($^O eq 'MSWin32') {
print STDERR "Cannot listen at UNIX socket '$socket_file' on Windows: $!\n";
print STDERR "Set OPENKORE_SOCKET_TCP_PORT (example: 2350) to use TCP console endpoint.\n";
} else {
print STDERR "Cannot listen at '$socket_file': $!\n";
}
exit 1;
}
}
if (!$socket) {
print STDERR "Cannot listen at '$socket_file': $!\n";
exit 1;
$endpoint_desc = $socket_file;
}

my $f;
if (open($f, ">", $pid_file)) {
print $f $$;
close($f);
} else {
unlink $socket_file;
unlink $socket_file if !$use_tcp;
print STDERR "Cannot write to PID file '$pid_file'.\n";
exit 1;
}
Expand All @@ -228,11 +264,13 @@ sub new {
$self->{messages} = [];
$self->{inputs} = [];
$self->{socket_file} = $socket_file;
$self->{use_tcp} = $use_tcp;
$self->{endpoint_desc} = $endpoint_desc;
$self->{pid_file} = $pid_file;
$self->{waitingForInput} = 0;

$SIG{INT} = $SIG{TERM} = $SIG{QUIT} = sub {
unlink $socket_file;
unlink $socket_file if !$use_tcp;
unlink $pid_file;
exit 2;
};
Expand All @@ -242,7 +280,7 @@ sub new {

sub DESTROY {
my ($self) = @_;
unlink $self->{socket_file};
unlink $self->{socket_file} if !$self->{use_tcp};
unlink $self->{pid_file};
$self->SUPER::DESTROY();
}
Expand Down Expand Up @@ -362,4 +400,4 @@ sub onClientData {
}
}

1;
1;
Loading
Loading