C# OpenVPN اسٹیٹ آبزرور: سیشن پر نظر رکھیں، NIC پر نہیں
NetworkAvailabilityChanged کوئی VPN واقعہ نہیں ہے۔ سرنگ کے مالک کلائنٹ کی اسٹیٹ اسٹریم پڑھیں، پرانی جانچوں سے بچیں اور ہر کنکشن کے لیے تیاری شائع کریں۔
سرنگ مرتے وقت بھی آپ کی ایپلیکیشن کام کرتی رہتی ہے۔ Wi-Fi ابھی چالو ہے، انٹرنیٹ ابھی جواب دے رہا ہے، اور ایپلیکیشن جس نجی API پر منحصر ہے وہ ناقابلِ رسائی ہو گئی ہے۔ لوگ یہاں عام طور پر جس .NET واقعے کی طرف جاتے ہیں، NetworkAvailabilityChanged، وہ اس صورتحال کو بالکل بیان نہیں کرتا۔ وہ مشین کی مجموعی حالت میں تبدیلی کی اطلاع دیتا ہے، اور VPN منقطع اور دوبارہ منسلک ہونے کے دوران بھی وہ حالت درست رہ سکتی ہے۔ آبزرور کو اس کلائنٹ کی نگرانی کرنی چاہیے جو سرنگ کا مالک ہے، نیٹ ورک اسٹیک کے خلاصے کی نہیں۔
دستیابی ایک مجموعی قدر ہے، آپ کی سرنگ نہیں
NetworkAvailabilityChanged اس وقت فعال ہوتا ہے جب مشین کا مجموعی دستیابی کا جواب بدلتا ہے، اور وہ جواب loopback یا سرنگ کے علاوہ ہر فعال انٹرفیس کو شمار کرتا ہے۔
Wi-Fi چالو ہونے کے دوران VPN کا گرنا اس چیز میں کچھ نہیں بدلتا جسے وہ ماپتا ہے، اسی لیے واقعہ ٹھیک اسی خرابی کے دوران خاموش رہ سکتا ہے جس کی آپ کو فکر ہے۔
اسٹیٹ اسٹریم اس کلائنٹ کی ہے جو سرنگ کا مالک ہے
شناخت کریں کہ کون سا جزو کنکشن کا مالک ہے: OpenVPN GUI یا سروس، OpenVPN Connect، یا وہ عمل جو آپ کی ایپلیکیشن نے شروع کیا اور کنٹرول کرتا ہے۔ یہ مختلف معاون انٹرفیس رکھنے والے مختلف مالکان ہیں، اور آبزرور کو وہی استعمال کرنا چاہیے جو تعیناتی سے مطابقت رکھتا ہو۔ جس OpenVPN عمل کے ساتھ آپ کو ضم ہونے کا اختیار ہے، اس کے لیے مینجمنٹ انٹرفیس موجودہ حالت، تاریخ اور حقیقی وقت کی اطلاعات کی اطلاع دیتا ہے۔ مقامی بنائے گئے GUI کیپشن میں connected لفظ تلاش کرنے کے بجائے دستاویزی ساختی پیغامات کا تجزیہ کریں۔
مینجمنٹ چینل ایک مراعات یافتہ کنٹرول سطح ہے، اس لیے نیا سننے والا نہ کھولیں اور GUI سے اس چینل کے لیے نہ لڑیں جو اس کے پاس پہلے سے ہے۔
نسل کے محافظ پرانے نتائج روکتے ہیں
ہر مشاہدہ کسی مخصوص کنکشن کوشش سے تعلق رکھتا ہے۔ نئی کوشش شروع ہونے، چینل گم ہونے اور کلائنٹ کے باہر نکلنے کی اطلاع دینے پر نسل کا کاؤنٹر بڑھائیں۔
A کنکشن کے دوران شروع ہونے والی جانچ پر غور کریں۔ سرنگ گرتی ہے، B کنکشن شروع ہوتا ہے، اور پھر A کی تاخیر سے آنے والی HTTP کامیابی آتی ہے۔ محافظ کے بغیر وہ پرانا نتیجہ ڈسپلے کو سبز کر دیتا ہے جبکہ B ابھی تصدیق کر رہا ہوتا ہے۔ منسوخی ضائع ہونے والا کام کم کرتی ہے، اور نسل کی جانچ ہی پرانی تکمیل کو موجودہ حالت بننے سے روکتی ہے:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
UI بھیجنے کے گرد بھی یہی اصول لاگو کریں، کیونکہ مارشل شدہ اپ ڈیٹ نسل آگے بڑھنے کے بعد بھی آ سکتی ہے۔
ابتداء اور دوبارہ منسلک ہونا ایک ہی زندگی کا چکر ہے
پہلے کنکشن، دوبارہ منسلک ہونے اور چینل کے نقصان کو ایک ہی اصولوں کے مجموعے کے ساتھ ایک ہی زندگی کا چکر سمجھیں:
- جہاں انٹرفیس اجازت دے وہاں ایک ہی مرحلے میں موجودہ حالت پڑھیں اور اطلاعات کی رکنیت لیں۔
- ہر مشاہدے کو کنکشن کی شناخت اور نسل کے ساتھ ٹیگ کریں۔
- دوبارہ منسلک ہونے، باہر نکلنے یا گمشدہ مشاہداتی چینل پر تیاری کو کالعدم کریں۔
- نجی وسیلے کی جانچ صرف اس وقت کریں جب مالک ابتداء مکمل ہونے کی اطلاع دے۔
- صرف وہی نتائج شائع کریں جو اب بھی موجودہ نسل سے تعلق رکھتے ہوں۔
گمشدہ چینل کا مطلب نامعلوم ہے، منقطع نہیں۔ نامعلوم کی اطلاع دینا اس منقطع ہونے کی اطلاع دینے سے زیادہ ایماندار ہے جسے آپ ثابت نہیں کر سکتے، اور یہ دوبارہ کوشش کی منطق کو اندازے پر عمل کرنے سے روکتا ہے۔
شواہد کی اطلاع دیں، بولین کی نہیں
نامزد سیشن کی حالت اور وسیلے کی تیاری کو الگ الگ اقدار کے طور پر واپس کریں، ہر ایک کے ساتھ عمر۔ جسے کچھ فیصلہ کرنا ہے وہ دیکھ سکتا ہے کہ آخری کامیاب جانچ کی عمر چالیس سیکنڈ ہے، جو تازہ معلومات سے مختلف معلومات ہے۔
عوامی IP کی تلاش اس بات کا ثبوت نہیں کہ کسی نجی API نے مطلوبہ راستہ استعمال کیا، اس لیے اسے ایسا پیش نہ کریں جیسے ہو۔
نفاذ کو آبزرور سے باہر رکھیں
کال بیک واقعے کے بعد چلتا ہے۔ یہ ضمانت نہیں دے سکتا کہ واقعے اور ہینڈلر کے درمیان مشین سے کوئی پیکٹ نہیں نکلا۔ اگر ڈیزائن کو روک تھام درکار ہو تو نیٹ ورکنگ پالیسی کو وہ فراہم کرنا ہوگا، اور آبزرور کا کام اپنے کال کرنے والے کو شواہد سمجھانا ہے۔ دونوں کو ملانے سے ایسا کوڈ بنتا ہے جو بولین رکھنے کی وجہ سے خود کو فائر وال سمجھتا ہے۔ نفاذ کی تہہ کو بورنگ اور قابلِ جانچ رکھیں، اور آبزرور کو پڑھنے والا ہی رہنے دیں۔
پھر UI کا سوال سادہ ہو جاتا ہے: جو معلوم ہے اسے اس کی عمر کے ساتھ دکھائیں، اور جب نامعلوم ہو تو نامعلوم کہیں۔