mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-15 23:25:48 -07:00
Fixed Agent Role Implementation Errors / Bugs
This commit is contained in:
@@ -29,7 +29,7 @@ from typing import Callable, Deque, Dict, Iterable, List, Optional, Tuple
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from .ReverseTunnel.Powershell import PowershellChannelServer
|
from .ReverseTunnelProtocols import PowershellChannelServer
|
||||||
|
|
||||||
try: # websockets is added to engine requirements
|
try: # websockets is added to engine requirements
|
||||||
import websockets
|
import websockets
|
||||||
@@ -1000,7 +1000,12 @@ class ReverseTunnelService:
|
|||||||
if lease is None or (lease.domain or "").lower() != "ps":
|
if lease is None or (lease.domain or "").lower() != "ps":
|
||||||
return None
|
return None
|
||||||
bridge = self.ensure_bridge(lease)
|
bridge = self.ensure_bridge(lease)
|
||||||
server = PowershellChannelServer(bridge=bridge, service=self)
|
server = PowershellChannelServer(
|
||||||
|
bridge=bridge,
|
||||||
|
service=self,
|
||||||
|
frame_cls=TunnelFrame,
|
||||||
|
close_frame_fn=close_frame,
|
||||||
|
)
|
||||||
self._ps_servers[tunnel_id] = server
|
self._ps_servers[tunnel_id] = server
|
||||||
return server
|
return server
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
"""Protocol-specific helpers for Reverse Tunnel (Engine side)."""
|
|
||||||
|
|
||||||
@@ -5,24 +5,21 @@ import json
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
from typing import Any, Deque, Dict, List, Optional
|
from typing import Any, Deque, Dict, List, Optional
|
||||||
|
|
||||||
from ..ReverseTunnel import (
|
# Mirror framing constants to avoid circular imports.
|
||||||
CLOSE_AGENT_SHUTDOWN,
|
MSG_CHANNEL_OPEN = 0x03
|
||||||
CLOSE_OK,
|
MSG_CHANNEL_ACK = 0x04
|
||||||
CLOSE_PROTOCOL_ERROR,
|
MSG_DATA = 0x05
|
||||||
MSG_CHANNEL_ACK,
|
MSG_CONTROL = 0x09
|
||||||
MSG_CHANNEL_OPEN,
|
MSG_CLOSE = 0x08
|
||||||
MSG_CLOSE,
|
CLOSE_OK = 0
|
||||||
MSG_CONTROL,
|
CLOSE_PROTOCOL_ERROR = 3
|
||||||
MSG_DATA,
|
CLOSE_AGENT_SHUTDOWN = 6
|
||||||
TunnelFrame,
|
|
||||||
close_frame,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PowershellChannelServer:
|
class PowershellChannelServer:
|
||||||
"""Coordinate PowerShell channel frames over a TunnelBridge."""
|
"""Coordinate PowerShell channel frames over a TunnelBridge."""
|
||||||
|
|
||||||
def __init__(self, bridge, service, *, channel_id: int = 1):
|
def __init__(self, bridge, service, *, channel_id: int = 1, frame_cls=None, close_frame_fn=None):
|
||||||
self.bridge = bridge
|
self.bridge = bridge
|
||||||
self.service = service
|
self.service = service
|
||||||
self.channel_id = channel_id
|
self.channel_id = channel_id
|
||||||
@@ -33,9 +30,11 @@ class PowershellChannelServer:
|
|||||||
self._output: Deque[str] = deque()
|
self._output: Deque[str] = deque()
|
||||||
self._close_reason: Optional[str] = None
|
self._close_reason: Optional[str] = None
|
||||||
self._close_code: Optional[int] = None
|
self._close_code: Optional[int] = None
|
||||||
|
self._frame_cls = frame_cls
|
||||||
|
self._close_frame_fn = close_frame_fn
|
||||||
|
|
||||||
# ------------------------------------------------------------------ Agent frame handling
|
# ------------------------------------------------------------------ Agent frame handling
|
||||||
def handle_agent_frame(self, frame: TunnelFrame) -> None:
|
def handle_agent_frame(self, frame) -> None:
|
||||||
if frame.channel_id != self.channel_id:
|
if frame.channel_id != self.channel_id:
|
||||||
return
|
return
|
||||||
if frame.msg_type == MSG_CHANNEL_ACK:
|
if frame.msg_type == MSG_CHANNEL_ACK:
|
||||||
@@ -73,7 +72,7 @@ class PowershellChannelServer:
|
|||||||
{"protocol": "ps", "metadata": {"cols": cols, "rows": rows}},
|
{"protocol": "ps", "metadata": {"cols": cols, "rows": rows}},
|
||||||
separators=(",", ":"),
|
separators=(",", ":"),
|
||||||
).encode("utf-8")
|
).encode("utf-8")
|
||||||
frame = TunnelFrame(msg_type=MSG_CHANNEL_OPEN, channel_id=self.channel_id, payload=payload)
|
frame = self._frame_cls(msg_type=MSG_CHANNEL_OPEN, channel_id=self.channel_id, payload=payload)
|
||||||
self.bridge.operator_to_agent(frame)
|
self.bridge.operator_to_agent(frame)
|
||||||
self._open_sent = True
|
self._open_sent = True
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
@@ -88,21 +87,29 @@ class PowershellChannelServer:
|
|||||||
if self._closed:
|
if self._closed:
|
||||||
return
|
return
|
||||||
payload = data.encode("utf-8", errors="replace")
|
payload = data.encode("utf-8", errors="replace")
|
||||||
frame = TunnelFrame(msg_type=MSG_DATA, channel_id=self.channel_id, payload=payload)
|
frame = self._frame_cls(msg_type=MSG_DATA, channel_id=self.channel_id, payload=payload)
|
||||||
self.bridge.operator_to_agent(frame)
|
self.bridge.operator_to_agent(frame)
|
||||||
|
|
||||||
def send_resize(self, cols: int, rows: int) -> None:
|
def send_resize(self, cols: int, rows: int) -> None:
|
||||||
if self._closed:
|
if self._closed:
|
||||||
return
|
return
|
||||||
payload = json.dumps({"cols": cols, "rows": rows}, separators=(",", ":")).encode("utf-8")
|
payload = json.dumps({"cols": cols, "rows": rows}, separators=(",", ":")).encode("utf-8")
|
||||||
frame = TunnelFrame(msg_type=MSG_CONTROL, channel_id=self.channel_id, payload=payload)
|
frame = self._frame_cls(msg_type=MSG_CONTROL, channel_id=self.channel_id, payload=payload)
|
||||||
self.bridge.operator_to_agent(frame)
|
self.bridge.operator_to_agent(frame)
|
||||||
|
|
||||||
def close(self, code: int = CLOSE_AGENT_SHUTDOWN, reason: str = "operator_close") -> None:
|
def close(self, code: int = CLOSE_AGENT_SHUTDOWN, reason: str = "operator_close") -> None:
|
||||||
if self._closed:
|
if self._closed:
|
||||||
return
|
return
|
||||||
self._closed = True
|
self._closed = True
|
||||||
self.bridge.operator_to_agent(close_frame(self.channel_id, code, reason))
|
if callable(self._close_frame_fn):
|
||||||
|
frame = self._close_frame_fn(self.channel_id, code, reason)
|
||||||
|
else:
|
||||||
|
frame = self._frame_cls(
|
||||||
|
msg_type=MSG_CLOSE,
|
||||||
|
channel_id=self.channel_id,
|
||||||
|
payload=json.dumps({"code": code, "reason": reason}, separators=(",", ":")).encode("utf-8"),
|
||||||
|
)
|
||||||
|
self.bridge.operator_to_agent(frame)
|
||||||
|
|
||||||
# ------------------------------------------------------------------ Output polling
|
# ------------------------------------------------------------------ Output polling
|
||||||
def drain_output(self) -> List[str]:
|
def drain_output(self) -> List[str]:
|
||||||
@@ -127,4 +134,3 @@ class PowershellChannelServer:
|
|||||||
"close_reason": self._close_reason,
|
"close_reason": self._close_reason,
|
||||||
"close_code": self._close_code,
|
"close_code": self._close_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
"""Protocol-specific helpers for Reverse Tunnel (Engine side)."""
|
||||||
|
|
||||||
|
from .Powershell import PowershellChannelServer
|
||||||
|
|
||||||
|
__all__ = ["PowershellChannelServer"]
|
||||||
|
|
||||||
Reference in New Issue
Block a user