MCPcopy Create free account
hub / github.com/aitjcize/Overlord / PersistentShellWebSocketClient

Class PersistentShellWebSocketClient

py/ovl.py:722–826  ·  view source on GitHub ↗

Holds one long-lived /bin/sh on the ghost over a single WS. Commands are framed by appending a per-command sentinel printf that emits `\\n__OVL_END_ : \\n` after the user command, so the merged stdout/stderr stream can be parsed without a fresh shell per call.

Source from the content-addressed store, hash-verified

720
721
722class PersistentShellWebSocketClient(SSLEnabledWebSocketBaseClient):
723
724 """Holds one long-lived /bin/sh on the ghost over a single WS.
725
726 Commands are framed by appending a per-command sentinel printf that emits
727 `\\n__OVL_END_<nonce>:<exit>\\n` after the user command, so the merged
728 stdout/stderr stream can be parsed without a fresh shell per call.
729 """
730
731 def __init__(self, state, *args, **kwargs):
732 super().__init__(state, *args, **kwargs)
733 self._opened = threading.Event()
734 self._cmd_mutex = threading.Lock() # serializes RunCommand callers
735 self._cv = threading.Condition()
736 self._buf = b''
737 self._active_nonce = None # bytes
738 self._active_writer = None
739 self._exit_code = None
740 self._died = False
741
742 def handshake_ok(self):
743 pass
744
745 def opened(self):
746 self._opened.set()
747
748 def closed(self, code, reason=None):
749 del code, reason
750 with self._cv:
751 self._died = True
752 self._cv.notify_all()
753
754 def received_message(self, message):
755 if not message.is_binary:
756 return
757 with self._cv:
758 self._buf += message.data
759 if self._active_nonce is None:
760 # Idle stream noise: drop it.
761 self._buf = b''
762 return
763 sentinel = b'\n__OVL_END_' + self._active_nonce + b':'
764 idx = self._buf.find(sentinel)
765 if idx == -1:
766 # Forward everything except a tail that might be a split sentinel.
767 keep = len(sentinel) - 1
768 if len(self._buf) > keep:
769 chunk = self._buf[:-keep] if keep else self._buf
770 self._buf = self._buf[len(chunk):]
771 if self._active_writer and chunk:
772 self._active_writer(chunk)
773 return
774 if idx > 0 and self._active_writer:
775 self._active_writer(self._buf[:idx])
776 tail = self._buf[idx + len(sentinel):]
777 nl = tail.find(b'\n')
778 if nl == -1:
779 # Sentinel found but exit code not yet complete; wait for more.

Callers 1

ShellPersistentMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected