diff --git a/README.md b/README.md index b717558..7ed22c1 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,8 @@ curl -fsSL https://panel.example/install.sh | sudo HOST=https://panel.example EN - **lp** - только long-polling. ## Проброс портов и прямой туннель -Правила создаются на странице машины «Порты». Режим `http` идёт через адрес панели, +Правила создаются на странице машины «Порты». Режим `http` (в панели - http-lp) идёт через +соединение агента с панелью: по WebSocket, а если он недоступен - по long-polling; `tcp`/`udp` - через прямой туннель: агент держит исходящее соединение к порту туннеля хоста, по нему мультиплексируются все соединения. diff --git a/internal/agent/session.go b/internal/agent/session.go index 9c6e1ce..4bd84ec 100644 --- a/internal/agent/session.go +++ b/internal/agent/session.go @@ -33,7 +33,8 @@ func (a *Agent) runTerminal(parent context.Context, sid, user, dir string) { } // runForward dials 127.0.0.1:port on the client and bridges it to the session, -// giving the host a reverse TCP tunnel over the same long-poll transport. +// giving the host a reverse TCP tunnel over the agent's link to the server: +// the WebSocket, or the long polls without one. func (a *Agent) runForward(parent context.Context, sid string, port int) { d := net.Dialer{Timeout: 10 * time.Second} conn, err := d.DialContext(parent, "tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(port))) @@ -92,7 +93,8 @@ func (a *Agent) bridgeStream(parent context.Context, sid string, rw io.ReadWrite } } -// pollIn performs one downstream long-poll and applies the frames. +// pollIn takes the next input - pushed on the WebSocket, else by a long +// poll - and applies the frames. // Returns false when the session is gone and the loop should stop. func (a *Agent) pollIn(ctx context.Context, sid string, w io.Writer, onResize func(cols, rows uint16)) bool { // On the WebSocket the input comes pushed; if it drops, by a long poll. diff --git a/internal/proto/proto.go b/internal/proto/proto.go index fb83d55..b8f113c 100644 --- a/internal/proto/proto.go +++ b/internal/proto/proto.go @@ -1,8 +1,8 @@ // Package proto describes the wire messages shared by the server and the agent. // -// All agent<->server traffic is plain JSON over HTTP(S) long-polling so it -// survives NAT and restrictive egress firewalls: the agent only ever makes -// outbound requests. +// All agent<->server traffic is plain JSON, on a WebSocket the agent opens or, +// where that does not get through, over HTTP(S) long polls, so it survives +// NAT and restrictive egress firewalls: the agent only ever connects out. package proto import "strings" @@ -11,7 +11,7 @@ import "encoding/json" // Control poll message types (server -> agent, returned from /api/agent/poll). const ( - // CtrlIdle is returned when the long-poll times out with nothing to do. + // CtrlIdle is returned when the control poll times out with nothing to do. CtrlIdle = "idle" // CtrlOpenTerminal tells the agent to spawn a PTY for the session id. CtrlOpenTerminal = "open_terminal" @@ -56,7 +56,8 @@ type EnrollResponse struct { Token string `json:"token"` } -// ControlMessage is the body returned by the control long-poll. +// ControlMessage is a command for the agent: on the WebSocket, or the body of +// the control long poll. type ControlMessage struct { Type string `json:"type"` SessionID string `json:"session_id,omitempty"` diff --git a/internal/server/forward.go b/internal/server/forward.go index c16e291..91ea1b9 100644 --- a/internal/server/forward.go +++ b/internal/server/forward.go @@ -12,8 +12,9 @@ import ( // forwardManager owns the host-side listeners for port-forward rules. It // supports three transports: -// - "http": tunneled over the HTTP long-poll channel (works anywhere nginx -// reaches, highest latency); +// - "http": over the agent's own link to the panel - its WebSocket, or the +// HTTP long polls while there is none (works anywhere nginx reaches, +// highest latency); // - "tcp": direct TCP multiplexed over the tunnel port (low latency); // - "udp": direct UDP over the tunnel port. type forwardManager struct { @@ -103,7 +104,8 @@ func (m *forwardManager) bridgeDirect(rule ForwardRule, conn net.Conn) { at.openStream(rule.ClientPort, conn) } -// bridgeHTTP wires a connection through the HTTP long-poll hub session. +// bridgeHTTP wires a connection through a hub session: the agent carries it +// over its WebSocket, or by long polls while it has none. func (m *forwardManager) bridgeHTTP(rule ForwardRule, conn net.Conn) { sess := m.hub.CreateForward(rule.AgentID, rule.ClientPort) defer m.hub.CloseSession(sess.ID) diff --git a/internal/server/hub.go b/internal/server/hub.go index 7d98aa1..88d72e5 100644 --- a/internal/server/hub.go +++ b/internal/server/hub.go @@ -7,8 +7,9 @@ import ( "github.com/x-grk/longpolling-remote-access/internal/proto" ) -// Hub is the in-memory broker between agents (HTTP long-polling) and the panel. -// It carries three kinds of work to an agent through its single control poll: +// Hub is the in-memory broker between agents (on a WebSocket, or by HTTP +// long polls) and the panel. It carries three kinds of work to an agent +// through its single control channel: // terminal sessions, port-forward streams, and one-shot tasks (file manager). // Nothing here is persisted. type Hub struct { diff --git a/internal/server/web/static/pages.js b/internal/server/web/static/pages.js index bb5d767..67b089e 100644 --- a/internal/server/web/static/pages.js +++ b/internal/server/web/static/pages.js @@ -75,7 +75,7 @@ App.register('forwards', { mount(root) { var notes = { - http: 'Трафик идёт через порт панели ' + root.dataset.panelPort + ' (long-poll). Порт ' + root.dataset.tunnelPort + ' не требуется.', + http: 'Трафик идёт через соединение агента с панелью (порт ' + root.dataset.panelPort + '): по WebSocket, без него - long-poll. Порт ' + root.dataset.tunnelPort + ' не требуется.', tcp: 'Требуется открытый порт ' + root.dataset.tunnelPort + '/tcp на хосте. Самая низкая задержка.', udp: 'Требуется открытый порт ' + root.dataset.tunnelPort + '/udp на хосте.' }; diff --git a/internal/server/web/templates/forwards.html b/internal/server/web/templates/forwards.html index 711c036..e03fec4 100644 --- a/internal/server/web/templates/forwards.html +++ b/internal/server/web/templates/forwards.html @@ -108,7 +108,7 @@