Spaces:
Running
Running
| # remote_executor.py (مُحدَّث: يدعم التشفير والتوقيع واختيار السيرفر ديناميكياً) | |
| # ============================================================ | |
| # يرسل المهمّة إلى سيرفر RPC خارجي مع تشفير + توقيع، | |
| # أو يعمل بوضع JSON صافٍ لو لم يكن SecurityManager مفعَّل. | |
| # يستخدم قائمة الأقران المكتشفة لاختيار الـ endpoint بدل IP ثابت. | |
| # ============================================================ | |
| import requests | |
| import json | |
| import os | |
| from typing import Any | |
| # قائمة الأقران (URLs) المستخرجة من peer_discovery | |
| from peer_discovery import PEERS | |
| from peer_discovery import PORT | |
| # عنوان افتراضي احتياطي (يمكن تغييره بمتغير بيئي REMOTE_SERVER) | |
| FALLBACK_SERVER = os.getenv( | |
| "REMOTE_SERVER", | |
| "http://89.111.171.92:PORT/run" | |
| ) | |
| # محاولة استيراد SecurityManager (اختياري) | |
| try: | |
| from security_layer import SecurityManager | |
| security = SecurityManager(os.getenv("SHARED_SECRET", "my_shared_secret_123")) | |
| SECURITY_ENABLED = True | |
| except ImportError: | |
| security = None | |
| SECURITY_ENABLED = False | |
| def _choose_remote_server() -> str: | |
| """ | |
| يختار عنوان السيرفر الذي سترسل إليه المهمة: | |
| 1) إذا عُيّن متغير بيئي REMOTE_SERVER، يُستخدم. | |
| 2) وإلا إذا اكتشفنا أقران عبر LAN/Internet، نأخذ أولهم. | |
| 3) وإلا نعود إلى FALLBACK_SERVER. | |
| """ | |
| env_url = os.getenv("REMOTE_SERVER") | |
| if env_url: | |
| return env_url.rstrip('/') + '/run' | |
| # PEERS يحوي عناوين كاملة من نوع http://ip:port/run | |
| if PEERS: | |
| # نختار الحد الأدنى من التحميل (اختياري) أو أول عنصر | |
| # هنا ببساطة نأخذ أول URL | |
| return next(iter(PEERS)) | |
| # استخدام الافتراضي | |
| return FALLBACK_SERVER.rstrip('/') + '/run' | |
| def execute_remotely( | |
| func_name: str, | |
| args: list[Any] | None = None, | |
| kwargs: dict[str, Any] | None = None | |
| ) -> Any: | |
| """إرسال استدعاء دالة إلى الخادم البعيد وإرجاع النتيجة.""" | |
| if args is None: | |
| args = [] | |
| if kwargs is None: | |
| kwargs = {} | |
| task = { | |
| "func": func_name, | |
| "args": args, | |
| "kwargs": kwargs, | |
| "sender_id": "client_node" | |
| } | |
| # اختيار السيرفر الصحيح ديناميكياً | |
| target_url = _choose_remote_server() | |
| try: | |
| if SECURITY_ENABLED: | |
| # 1) وقّع المهمة ثم شفّرها | |
| signed_task = security.sign_task(task) | |
| encrypted = security.encrypt_data(json.dumps(signed_task).encode()) | |
| headers = { | |
| "X-Signature": security.signature_hex, | |
| "Content-Type": "application/octet-stream" | |
| } | |
| payload = encrypted # خام ثنائي | |
| resp = requests.post( | |
| target_url, | |
| headers=headers, | |
| data=payload, | |
| timeout=15 | |
| ) | |
| else: | |
| # وضع التطوير: أرسل JSON صريح | |
| headers = {"Content-Type": "application/json"} | |
| resp = requests.post( | |
| target_url, | |
| headers=headers, | |
| json=task, | |
| timeout=15 | |
| ) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| return data.get("result", "⚠️ لا يوجد نتيجة") | |
| except Exception as e: | |
| return f"❌ فشل التنفيذ البعيد على {target_url}: {e}" | |