سه بخش اصلی، یک هدف
در پشت صحنه، Timmy به شکلی کاملاً کاربردی ساخته شده است: Flutter برای اپ، WebRTC برای صدا و ویدیوی لحظهای، و Firebase برای هماهنگی. نمیخواستم پلتفرم بزرگی بسازم که همهچیز را از فضای ابری عبور دهد. هر بخش باید تا حد ممکن به اطلاعات کمتری دسترسی داشته باشد و در عین حال با بخشهای دیگر بهطور قابلاعتماد کار کند.
WebRTC: اتصال مستقیم، رمزگذاریشده بهصورت پیشفرض
WebRTC (ارتباط بلادرنگ وب) صدا و ویدیو را میان دستگاه کودک و دستگاه والدین منتقل میکند. در بهترین حالت، دادهها مستقیماً بین دو دستگاه، بهصورت همتابههمتا و بدون سرور رسانه در میان آنها جریان پیدا میکنند.
هر اتصال WebRTC بهطور پیشفرض از DTLS-SRTP استفاده میکند. اگر کسی بستههای شبکه را ضبط کند، به صدای قابلشنیدن یا ویدیوی قابلمشاهده دست پیدا نمیکند. این رمزگذاری بخشی از پروتکل است و در WebRTC نمیتوان آن را بهسادگی غیرفعال کرد.
این نکته برای من مهم بود: رسانههای اتاق کودک نباید روی سرور من باشند. آنها فقط بین دستگاههای شما میمانند.
سیگنالدهی از طریق Firebase Firestore
پیش از شروع WebRTC، دستگاهها باید همدیگر را پیدا کنند و درباره روش اتصال با هم توافق کنند. به این بخش سیگنالدهی میگویند. Timmy برای این کار از Firebase Firestore، پایگاه داده ابری گوگل، استفاده میکند.
فقط دادههای فنی اتصال ردوبدل میشوند:
- پیشنهادها و پاسخهای SDP: قابلیتهای دستگاهها را توضیح میدهند (کدکهای پشتیبانیشده، وضوح تصویر و غیره).
- نامزدهای ICE: مسیرهای احتمالی شبکه که دستگاهها از طریق آنها میتوانند به هم برسند.
صدا و ویدیو وارد Firebase نمیشوند. Firestore فقط دادههای فنی اتصال را جابهجا میکند. Timmy این لایه سیگنالدهی را هم رمزگذاری میکند تا Firestore به محل تبادل متنِ آشکار برای SDP و ICE تبدیل نشود.
سرورهای TURN: وقتی مسیر مستقیم جواب نمیدهد
برخی شبکهها اتصال مستقیم را مسدود میکنند؛ مثلاً فایروالهای سختگیر یا بعضی اپراتورهای موبایل. در این شرایط WebRTC به یک رله TURN (عبور با استفاده از رلهها در اطراف NAT) نیاز دارد.
Timmy ابتدا سرور TURN محلی را امتحان میکند و اگر رله محلی در دسترس نباشد یا بیشازحد شلوغ باشد، از Cloudflare بهعنوان جایگزین استفاده میکند. رله بستههای رمزگذاریشده را فقط منتقل میکند. کلیدهای صدا یا ویدیو را در اختیار ندارد؛ رمزگذاری WebRTC دستنخورده میماند.
اعتبارنامههای TURN از یک Firebase Cloud Function میآیند و فقط 24 ساعت اعتبار دارند. به نظر من، استفاده از اعتبارنامههای دائمی در یک اپ مانیتور کودک بیشازحد پرخطر است.
Nearby Connections: دستگاهها خودکار همدیگر را پیدا میکنند
برای اینکه راهاندازی میان دستگاه کودک و دستگاه والدین دردسرساز نباشد، Timmy از Nearby Connections استفاده میکند. گوگل این لایه شناسایی را از طریق بلوتوث و وایفای فراهم میکند.
جفتسازی خودکار در Timmy بدون وارد کردن دستی کد کار میکند: دستگاهها همدیگر را پیدا میکنند و برای تبادل کلید به یک نقطه ملاقات مشترک میرسند. اگر این روش جواب ندهد، میتوانید یک کد 4 کاراکتری وارد کنید. کد جفتسازی هرگز از دستگاه خارج نمیشود؛ Firestore فقط یک هش رمزنگاری (SHA-256) را بهعنوان شناسه سند میبیند.
احراز هویت ناشناس
Timmy از Firebase Anonymous Authentication استفاده میکند. در اولین اجرا، هر دستگاه یک شناسه موقت و ناشناس دریافت میکند. نه حساب کاربری وجود دارد، نه آدرس ایمیل و نه رمز عبور. این شناسه فقط برای اعمال قوانین Firestore است: تنها دستگاههای احراز هویتشده میتوانند دادههای جلسه را بخوانند یا بنویسند.
معماری: چه کسی میفرستد، چه کسی دریافت میکند
Timmy دو حالت دارد:
- حالت کودک (فرستنده): دستگاه با میکروفون صدا را ضبط میکند و از طریق WebRTC به دستگاه والدین میفرستد. در صورت تمایل، دوربین هم فعال میشود و ویدیو نیز مستقیم ارسال میشود.
- حالت والدین (گیرنده): دستگاه صدا و ویدیو را دریافت میکند، تصویر دوربین را نمایش میدهد و قابلیت «فشار دهید و صحبت کنید» را برای فرستادن پیامهای صوتی کوتاه به دستگاه کودک ارائه میدهد.
کنترلهایی مانند «فشار دهید و صحبت کنید» و روشن یا خاموش کردن دوربین از یک DataChannel استفاده میکنند؛ کانال دیگری در WebRTC که پیامهای کوچک رمزگذاریشده را مستقیماً میان دستگاهها میفرستد.
چرا Flutter؟
Flutter چارچوب گوگل برای ساخت اپ روی چند پلتفرم است. برای Timmy یعنی میتوانم بخش زیادی از منطق را یکبار بنویسم و در Android و iOS به کار ببرم. Timmy در Android در دسترس است و نسخه iOS هم به انتشار نزدیک است. کد تکراری کمتر یعنی جاهای کمتری برای وارد شدن باگها.
خلاصه
قاعده فنی ساده است: Timmy باید فقط به دادههایی دست بزند که واقعاً لازم دارد. WebRTC از رسانه محافظت میکند، Firebase راهاندازی اتصال را هماهنگ میکند، TURN فقط بستههای رمزگذاریشده را میبیند و Nearby Connections دردسر جفتسازی را کم میکند.
فناوری خوب کمی در زندگی روزمره محو میشود. کارش را انجام میدهد، بدون اینکه اتاق کودک را به یک پروژه ابری تبدیل کند.