功能:完善通用云管工作台、审计与诊断能力
This commit is contained in:
1 parent
5ac692724d
commit
9f05aa20ea
225 files changed
+14266
-141
No files matched your search
@@ -49,10 +49,29 @@ def guard():
|
||||
if len(lease) != 32 or any(c not in '0123456789abcdef' for c in lease):
|
||||
raise ValueError('invalid lease')
|
||||
manifest = json.loads((ROOT / 'manifest.json').read_text())
|
||||
if set(manifest) != {'sunshine', 'capture-no-cursor.so'}:
|
||||
raise RuntimeError('incomplete pinned capture manifest')
|
||||
for name, expected in manifest.items():
|
||||
if name not in ('sunshine', 'capture-no-cursor.so') or hashlib.sha256(
|
||||
(ROOT / name).read_bytes()).hexdigest() != expected:
|
||||
raise RuntimeError('pinned capture build changed')
|
||||
if (ROOT / 'hide-server-cursor').exists():
|
||||
# PRIME can flatten Xorg's software sprite into the framebuffer before
|
||||
# NvFBC sees it. Keep a separate XFixes hide owned by the capture guard;
|
||||
# GetCursorImage still supplies the unmodified native shape to stream().
|
||||
with XCursor() as cursor:
|
||||
cursor.hide_server_cursor()
|
||||
try:
|
||||
guard_capture(lease)
|
||||
finally:
|
||||
# Stop the video producer before restoring its visible sprite.
|
||||
# ExecStopPost then restores normal, non-leased capture.
|
||||
systemctl('stop', SERVICE)
|
||||
else:
|
||||
guard_capture(lease)
|
||||
|
||||
|
||||
def guard_capture(lease):
|
||||
kms_config = ROOT / 'kms.json'
|
||||
scanout = None
|
||||
def checked_scanout(timeout=3):
|
||||
@@ -145,8 +164,13 @@ class XCursor:
|
||||
for name in ('XDisplayWidth', 'XDisplayHeight'):
|
||||
getattr(self.x, name).argtypes = [C.c_void_p, C.c_int]
|
||||
self.x.XFree.argtypes = [C.c_void_p]
|
||||
self.x.XSync.argtypes = [C.c_void_p, C.c_int]
|
||||
self.x.XCloseDisplay.argtypes = [C.c_void_p]
|
||||
self.f.XFixesGetCursorImage.argtypes = [C.c_void_p]
|
||||
self.f.XFixesGetCursorImage.restype = C.POINTER(Cursor)
|
||||
self.f.XFixesHideCursor.argtypes = [C.c_void_p, C.c_ulong]
|
||||
self.f.XFixesShowCursor.argtypes = [C.c_void_p, C.c_ulong]
|
||||
self.hidden = False
|
||||
self.display = self.x.XOpenDisplay(None)
|
||||
if not self.display:
|
||||
raise RuntimeError('no authenticated X11 display')
|
||||
@@ -154,6 +178,28 @@ class XCursor:
|
||||
self.root = self.x.XDefaultRootWindow(self.display)
|
||||
self.size = self.dimensions()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_):
|
||||
self.close()
|
||||
|
||||
def hide_server_cursor(self):
|
||||
if not self.hidden:
|
||||
self.f.XFixesHideCursor(self.display, self.root)
|
||||
self.x.XSync(self.display, 0)
|
||||
self.hidden = True
|
||||
|
||||
def close(self):
|
||||
if self.display:
|
||||
try:
|
||||
if self.hidden:
|
||||
self.f.XFixesShowCursor(self.display, self.root)
|
||||
self.x.XSync(self.display, 0)
|
||||
finally:
|
||||
self.x.XCloseDisplay(self.display)
|
||||
self.display = None
|
||||
|
||||
def dimensions(self):
|
||||
root = C.c_ulong()
|
||||
x, y = C.c_int(), C.c_int()
|
||||
@@ -214,6 +260,11 @@ def stream():
|
||||
# Fail before touching the service if the native shape is unsupported.
|
||||
x.read()
|
||||
systemctl('stop', GUARD)
|
||||
# A display-manager restart can remove the transient unit before its
|
||||
# ExecStopPost runs. The exclusive stream lock and confirmed stop make
|
||||
# it safe to discard the old producer's readiness/receipt here.
|
||||
for name in ('ready', 'receipt'):
|
||||
(RUN / name).unlink(missing_ok=True)
|
||||
(RUN / 'lease').write_text(lease)
|
||||
systemctl('start', GUARD)
|
||||
deadline = time.monotonic() + 40
|
||||
@@ -221,6 +272,8 @@ def stream():
|
||||
while not (RUN / 'ready').exists():
|
||||
if time.monotonic() > deadline:
|
||||
raise RuntimeError('guard not ready')
|
||||
if not (RUN / 'lease').exists():
|
||||
raise RuntimeError('capture guard ended before ready; inspect guard journal')
|
||||
os.utime(RUN / 'lease', None)
|
||||
time.sleep(.05)
|
||||
if (RUN / 'ready').read_text() != lease:
|
||||
|
||||
Reference in new issue
Block a user