پروژه شبکه Mysterium در Golang (Go) ساخته شده است ، که یک زبان کاملاً تلفیقی است و یک کتابخانه استاندارد غنی را ارائه می دهد. Go از نظر نحوی شبیه به C است ، اما در مورد ایمنی حافظه ، جمع آوری زباله ، تایپ ساختاری و همزمانی با سبک CSP به عنوان برنده ظاهر می شود.

بنابراین ، چگونه کتابخانه C ++ OpenVPN 3 را در یک گره Mysterium Golang ادغام کرده ایم؟ ما از OpenVPN استفاده می کنیم و این اولین پروتکل ما بود که به عنوان یک باینری خارجی (پرونده اجرایی) مورد استفاده قرار گرفت. این اساساً بدان معنی است که یک گره Mysterium Node و OpenVPN دو فرایند مختلف هستند که با استفاده از پیکربندی OpenVPN و IPC ارتباط برقرار می کنند. (دقیق بودن سوکت های محلی).

اکنون این محدودیت ها وجود دارد – به عنوان مثال ، توزیع نرم افزار پیچیده می شود همانطور که شما نیاز دارید. دودویی OpenVPN را با هر گره Mysterium توزیع کنید ، که شامل دو مرحله است و هرگز برای UX عالی نیست. این برای نسخه های اثبات مفهوم یا نسخه های بسیار اولیه کارآمد بود ، اما با حرکت به سمت سیستم عامل های تلفن همراه ، این رویکرد بسیار پیچیده یا غیرقابل اجرا شد ، به خصوص هنگام بررسی iOS.

برای حل این چالش ، تصمیم گرفتیم راهی پیدا کنیم. برای ادغام OpenVPN به طور مستقیم در پروژه Golang. همچنین ، ما تصمیم گرفتیم که این بسته می تواند برای دیگران مفید باشد – اینگونه تولد کتابخانه Openvpn3 است. Openvpn3 یک کتابخانه رسمی است که توسط تیم OpenVPN نگهداری می شود و تقریباً در تمام سیستم عامل ها به عنوان مشتری یا اتصال به سرور OpenVPN مورد استفاده قرار می گیرد. همچنین ، در C ++ نوشته شده است که موانعی برای حل آنها به وجود آمده است.

اولین مانع ما این بود که کد C ++ را نمی توان مستقیماً توسط Golang فراخوانی کرد (Cgo). برای صادرات OpenVPN Client به عنوان کد فراخوان C ، باید تغییرات کوچکی در خود کتابخانه OpenVPN ایجاد کنیم. سپس چگونگی رفتار Golang با خود کد C وجود دارد. مشکل این بود که Golang و سیستم های مدیریت بسته آن انتظار دارند که کلیه کتابخانه ها پرونده های منبع باشند (یعنی مدیریت بسته باینری وجود ندارد یا بسیار محدود است). و روند ساخت کتابخانه Openvpn3 بسیار پیچیده بود و به آسانی به روش Go بیان نشده است.

مشاهده همچنین: گزارش API در سال 2019 می گوید که استاندارد سازی چالش شماره یک است

بنابراین تصمیم ما این بود که کتابخانه از قبل برای همه سیستم عامل هایی که در حال حاضر از آنها پشتیبانی می کنیم و یا باینری برای خانواده بازو (Android ، iOS) ، خانواده AMD64 (ویندوز ، لینوکس) ، برخی شبیه سازها تهیه می کنیم. از آنجا که از لینوکس برای سیستم ساخت اتوماتیک خود استفاده می کنیم ، مجبور شدیم همه کامپایلرها و SDK ها را در یک مکان تنظیم کنیم. نتیجه یک فایل هدر منفرد و مجموعه ای از کتابخانه های ایستا برای هر سیستم عامل / سیستم عامل مورد نیاز ما بود. ما همچنین باید اطمینان حاصل کردیم که این باینری ها قابل دریافت هستند (راهی برای گرفتن کتابخانه از Github).

ما به سادگی متعهد شدیم که این کتابخانه ها به همراه همه پشتیبانی از کد بروید. این بهترین روش برای توزیع نرم افزار نبود ، اما هدف ما یک کتابخانه Go gettable بود. قسمت بعدی آمد: برای تماس با توابع Openvpn3 از برو. کاملاً به راحتی قابل انجام بود. با این حال ، چند مشکل وجود دارد. اول از همه ، قوانین سختگیرانه ای راجع به آنچه می توان و نمی تواند به کد C منتقل شود و برعکس (به عنوان مثال ، شما نمی توانید مرجع تابع Go را به کد C منتقل کنید). مشتری Openvpn3 همچنین به عملکردهای برگشتی بستگی زیادی دارد. یك راه برای دستیابی به این امر استفاده از توابع استاتیک فقط برای تماسهای برگشتی بود. با این وجود ، این امر قابلیت انعطاف پذیری و قابلیت استفاده کتابخانه را محدود می کند. یک راه حل ترکیبی برای تعریف عملکردهای برگشت پذیر قابل تنظیم در Go و ثبت آنها در نقشه با شناسه عملکرد بود. توابع استاتیک در سرویس گیرنده Openvpn3 می تواند تماس های مربوطه را به توابع ثبت شده با شناسه های مربوطه اعزام کند.

در اینجا نحوه عملکرد (بیایید به عنوان مثال عملکرد برگشتی رویداد را بگیریم). اول ، کاربر ساختارهای عادی Go را با روش هایی تعریف می کند ، که رابط های مورد انتظار توسط رجیستر پاسخ به تماس را برآورده می کند. سپس ، ساختار به رجیستری پاسخ دادن ارسال می شود که در واقع شناسه جهانی برای نقشه پاسخگویی است. در مرحله بعد چه اتفاقی می افتد ، رجیستری تماس با استفاده از متد ، ساختار ارائه شده توسط کاربر را ایجاد می کند و یک ساختار C را ایجاد می کند ، آماده است تا به کد C منتقل شود ، اما به جای گذر از تابع Go به مرجع کد C ، کد ID را ارسال می کند ، که به سادگی کلید برگشت به نقشه است تابع برو (با نظر ویژه) صادر شده است.

وقتی کد C می خواهد کاربر را از تغییرات حالت مطلع کند ، آن را تابع استاتیک Go می نامد و یکی از پارامترها شناسه است. سپس این شناسه برای یافتن و تماس با پاسخ مناسب برای تعریف شده توسط کاربر ، به رجیستری پاسخ داده ارسال می شود. پس از این ، آن را گردآوری می کند. حداقل قسمت Go – این بدان معنی است که کد C قابل دستیابی است ، و همه سرصفحات خوب است.

مشاهده همچنین: Golang بالاترین مهارت در پرده در ایالات متحده است ، گزارش نشان می دهد

اکثر اژدها ها شروع شدند. هنگام اتصال بسته های Go با كتابخانه های ایستا OpenVPN بزرگتر شد. بزرگترین مسئله این بود كه: كتابخانه با کامپایلر C ++ ساخته شده است ، اما Golang cgo بطور پیش فرض از کامپایلر C استفاده كرده است. در نتیجه همه خطاهای عجیب و زشت در مرحله پیوند به وجود آمدند. بنابراین ، اگر خطاهای مشابهی را مشاهده می کنید مانند مثال – شما تنها نیستید. پس از ساعتها کاوش در سرریز پشته ، یک راه حل ساده برای خالی کردن محل کار بود. به این ترتیب cgo با استفاده از پیوند C ++ که از قبل به طور پیش فرض کتابخانه C ++ داشت فریب خورد.

هنگام استفاده از فن آوری های جدید مانند Golang ، باید گاهی اوقات به زنجیره ای بروید تا راه حل هایی پیدا کنید که به شما در استفاده از کتابخانه های موجود کمک کند تا شما نتوانید استفاده کنید. باید همه چیز را از ابتدا شروع کنید. با این حال ، مانند اکثر راه حل ها در فناوری اطلاعات ، این یک گلوله نقره ای نیست. به عنوان مثال ، كتابخانه های از پیش تنظیم شده به خودی خود خطری امنیتی دارند – كاربران بالقوه كتابخانه نمی توانند مطمئن باشند كه دقیقاً چه چیزی در آن گردآوری شده است ، به این معنی كه كدی برای بررسی وجود ندارد. هر سیستم عامل و معماری باید نسخه های جداگانه ای از همین کتابخانه داشته باشد. همچنین ، مشکل فریم ورک iOS است – iOS frame frame (تهیه شده توسط ابزار Gomobile) یک کتابخانه ثابت است. بنابراین هر وابستگی دیگری با یکدیگر در ارتباط است اما با یک چارچوب ترکیب نمی شود – و این باید به عنوان یک گام جداگانه انجام شود. گولانگ معمولاً انتظار دارد که تمام منابع مورد نیاز یک بسته در یک مکان باشد.