تماس‌ها

** توجه: این صفحه اصول حساب های Jami را توضیح می دهد. برای حساب های SIP، پروتکل SIP استفاده می شود.**

بذاريم يه تماس با جمي بگيريم

طرف ديمون

در هنگام ایجاد تماس بین دو همسال، جامی عمدتا از پروتکل های شناخته شده مانند ICE، SIP یا TLS استفاده می کند. با این حال، برای توزیع آن، فرآیند ایجاد تماس کمی متفاوت است. برای خلاصه، هنگامی که کسی می خواهد با یکی از تماس های خود تماس بگیرد، این کاری است که می کند:

  1. جستجوی حضور تماس در DHT (برای جزئیات بیشتر، ببینید تماس مدیریت)

  2. هنگامی که تماس پیدا شده است، درخواست تماس ارسال کنید و نامزدهای شناخته شده را اعلام کنید (IP هر رابط شبکه + آدرس های رله (TURN) + آدرس های بازتاب (UPnP، عمومی).

  3. منتظر پاسخ تماس باشید (آن ها به آدرس های شناخته شده خود پاسخ می دهند).

  4. مذاکره از سوکت از طریق ICE. در واقع، دو جلسه ICE مذاکره می شود. یکی (ترجیح) در TCP، یکی در UDP (به عنوان یک بازگشت).

  5. سپس، سوکت در TLS (اگر TCP) یا DTLS (اگر UDP) رمزگذاری می شود.

  6. تماس اکنون می تواند تماس را بپذیرد یا رد کند. هنگامی که آنها قبول می کنند، یک حمل و نقل ICE (UDP فقط برای حال حاضر) برای ایجاد 4 سوکت جدید برای رسانه ها (2 برای صوتی، 2 برای ویدیو) مذاکره می شود.

  7. تماس الان زنده شده

کاندیداهای ICE تبادل

همه چیز واقعا در jamiaccount.cpp (JamiAccount::startOutgoingCall) شروع می شود. هنگامی که هر دو شی ICE آماده هستند و وقتی تماس از طریق DHT پیدا می شود، درخواست تماس برای تماس ایجاد می شود. این درخواست شامل تمام اطلاعات لازم برای جلسه ICE از راه دور است که توسط:

dht::IceCandidates(callvid,  blob)

در حالی که callvid یک شماره تصادفی است که برای شناسایی تماس استفاده می شود و نقطه حاوی دو پیام ICE متصل شده است (IceTransport::packIceMsg در ice_transport.cpp) که حاوی رمز عبور جلسه، ufrag و ICE کاندیداها هستند.) مانند:

0d04b935
7c33834e7cf944bf0e367b42
H6e6ca382 1 UDP 2130706431 2607:fad8:4:6:9eb6:d0ff:dead:c0de 14133 typ host
H42c1g477 1 UDP 2130706431 fe80::9eb6:d0ff:fee7:1412 14133 typ host
Hc0a8027e 1 UDP 2130706431 192.168.0.123 34567 typ host
Sc0a8027e 1 UDP 1694498815 X.X.X.X 32589 typ srflx
0d04b932
7c33834e7cf944bf0e367b47
H6e6ca682 1 TCP 2130706431 2607:fad8:4:6:9eb6:d0ff:dead:c0de 50693 typ host tcptype passive
H6e6ca682 1 TCP 2130706431 2607:fad8:4:6:9eb6:d0ff:dead:c0de 9 typ host tcptype active
H42c1b577 1 TCP 2130706431 fe80::9eb6:d0ff:fee7:1412 50693 typ host tcptype passive
H42c1b577 1 TCP 2130706431 fe80::9eb6:d0ff:fee7:1412 9 typ host tcptype active
Hc0a8007e 1 TCP 2130706431 192.168.0.123 42751 typ host tcptype passive
Hc0a8007e 1 TCP 2130706431 192.168.0.123 9 typ host tcptype active
Sc0a8007e 1 TCP 1694498815 X.X.X.X 42751 typ srflx tcptype passive

و از طریق DHT در یک پیام رمزگذاری شده برای دستگاه به hash(call:xxxxxx) ارسال می شود که xxxxxx نام دستگاه است. همتایان در همان مکان (اما رمزگذاری شده برای دستگاه فرستنده) پاسخ خود را به dht::IceCandidates می دهند. برای جزئیات بیشتر ، به JamiAccount::replyToIncomingIceMsg مراجعه کنید.

جلسه ICE در هر دو طرف ایجاد می شود وقتی که همه کاندیداها در دست دارند (به همین ترتیب برای فرستنده، وقتی پاسخ از تماس دریافت می شود).

مذاکره با ICE

تماس های منتظر توسط JamiAccount::handlePendingCallList() ، که ابتدا منتظر می باشند تا مذاکرات TCP به پایان برسد (و اگر شکست خورد، منتظر UDP باشید). کد مذاکره ICE عمدتا توسط [pjproject] (https://github.com/pjsip/pjproject) مدیریت می شود، اما برای Jami، بخش جالب در ice_transport.cpp قرار دارد. علاوه بر این، برخی از پیچ ها / ویژگی های مهم را در بالای pjproject اضافه می کنیم که تاکنون به طور پیشرو ترکیب نشده است (به عنوان مثال، ICE بر روی TCP). این پیچ ها در contrib/src/pjproject حضور دارند.

رمزگذاری سوکت کنترل

هنگامی که سوکت توسط یک IceTransport نمونه ایجاد و مدیریت می شود، سپس به SipTransport مربوط به TlsIceTransport بسته می شود. کد اصلی در JamiAccount::handlePendingCall() قرار دارد و بسته بندی به SipTransportBroker::getTlsIceTransport انجام می شود. سرانجام، جلسه ما توسط TlsSession در daemon/src/security/tls_session.cpp مدیریت می شود و از کتابخانه GnuTLS استفاده می کند.

بنابراین، سوکت کنترل یک TLS (1.3 خواهد بود اگر نسخه شما و gnutls همسال شما آن را پشتیبانی می کند) اگر یک سوکت TCP مذاکره شود. اگر یک سوکت UDP در عوض مذاکره شود (به دلیل محدودیت های فایروال / مشکل در مذاکره / و غیره) ، سوکت از DTLS استفاده می کند (هم اکنون توسط همان بخش ها مدیریت می شود).

سوکت کنترل برای انتقال بسته های SIP مانند دعوت نامه ها، پیام های سفارشی (جامی کارت پروفایل شما را در این سوکت در آغاز تماس یا چرخش دوربین) ، پیام های متنی ارسال می کند.

مقالات مرتبط:

  • https://jami.net/improved-video-rotation-support/

  • https://jami.net/peer-to-peer-file-sharing-support-in-jami/

سوکت های رسانه ای

سوکت های رسانه ای سوکت های SRTP هستند که کلید را از طریق جلسه TLS که قبلاً ایجاد شده است، مذاکره می کند. TODO

معماری

** تود**

جریان های متعدد

از آنجا که نسخه 13.3.0 دیمون به طور کامل پشتیبانی شده است، این ویژگی به کاربران اجازه می دهد تا در طول یک تماس چندین ویدیو را در همان زمان به اشتراک بگذارند. در بخش های بعدی، ما تمام تغییرات مرتبط را توصیف خواهیم کرد.

پجسیپ

بخش اول این است که به اندازه کافی جریان های رسانه ای را مذاکره کنیم. در واقع هر جریان رسانه ای از 2 سوکت UDP استفاده می کند. ما سه سناریو را در نظر می گیریم:

  1. اگر میزبان یک کنفرانس می خواهد رسانه ای اضافه کند، هیچ چیز دیگری برای مذاکره نیست، چون ما ویدیوها را در یک جریان مخلوط کرده ایم. بنابراین، ما رسانه های جدید را مستقیماً به مکسر ویدئویی بدون مذاکره اضافه می کنیم.

  2. اگر در 1:1 هستیم، به عنوان اطلاعات کنفرانس وجود ندارد، چند جریان پشتیبانی نمی شود.

  3. در غیر این صورت، دو سوکت جدید برای رسانه های جدید مذاکره می شود.

برای اینکه pjsip بتواند سوکت های بیشتری را در هر جلسه ICE تولید کند، PJ_ICE_COMP_BITS به 5 تغییر داده شد (که به 2^5 مطابقت دارد، بنابراین 32 جریان).

تغییر تغییرات را حذف کنید، درخواست پشتیبانیMediaChange

در دیمون، API قدیمی switchInput اکنون DEPRECATED است؛ همان برای switchSecondaryInput:

<method name="switchInput" tp:name-for-bindings="switchInput">
    <tp:docstring>
        Switch input for the specified call
    </tp:docstring>
    <arg type="s" name="accountId" direction="in"/>
    <arg type="s" name="callId" direction="in"/>
    <arg type="s" name="input" direction="in"/>
    <arg type="b" direction="out" />
</method>

<method name="switchSecondaryInput" tp:name-for-bindings="switchSecondaryInput">
    <tp:added version="11.0.0"/>
    <tp:docstring>
        Switch secondary input for the specified conference
    </tp:docstring>
    <arg type="s" name="accountId" direction="in" />
    <arg type="s" name="conferenceId" direction="in"/>
    <arg type="s" name="input" direction="in"/>
    <arg type="b" direction="out" />
</method>

requestMediaChange این را برای تماس ها و کنفرانس ها جایگزین می کند:

<method name="requestMediaChange" tp:name-for-bindings="requestMediaChange">
    <tp:added version="11.0.0"/>
    <tp:docstring>
        <p>Request changes in the media of the specified call.</p>
    </tp:docstring>
    <arg type="s" name="accountId" direction="in" />
    <arg type="s" name="callId" direction="in">
        <tp:docstring>
        The ID of the call.
        </tp:docstring>
    </arg>
    <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="VectorMapStringString"/>
    <arg type="aa{ss}" name="mediaList" direction="in">
        <tp:docstring>
        A list of media attributes to apply.
        </tp:docstring>
    </arg>
    <arg type="b" name="requestMediaChangeSucceeded" direction="out"/>
</method>

مطابقت

اگر یک تماس با یک همتایان انجام شود که نسخه ی دیمون < 13.3.0 باشد، جریان چندگانه فعال نیست و رفتار قدیمی استفاده می شود (تنها یک ویدیو).

شناسایی جریان ها

از آنجا که اکنون می توان چندین جریان داشت، هر جریان رسانه ای با شناسه اش شناسایی می شود و فرمت "_" است؛ به عنوان مثال: "audio_0" ، "video_2" و غیره.

چرخش

XML برای اضافه کردن جریان مورد نظر به روز شده است:

<?xml version="1.0" encoding="utf-8" ?>
<media_control>
  <vc_primitive>
    <stream_id>{}</stream_id>
    <to_encoder>
      <device_orientation>0</device_orientation>
    </to_encoder>
  </vc_primitive>
</media_control>

فریم کلید

XML برای اضافه کردن جریان مورد نظر به روز شده است:

<?xml version="1.0" encoding="utf-8" ?>
<media_control>
  <vc_primitive>
    <stream_id>{}</stream_id>
    <to_encoder><picture_fast_update/></to_encoder>
  </vc_primitive>
</media_control>

فعالیت صوتی

XML برای اضافه کردن جریان مورد نظر به روز شده است:

<?xml version="1.0" encoding="utf-8" ?>
<media_control>
  <vc_primitive>
    <stream_id>{}</stream_id>
    <to_encoder>
      <voice_activity>true</voice_activity>
    </to_encoder>
  </vc_primitive>
</media_control>

نشست

تغییرات منعکس شده در اینجا مستند شده است.

مشتری

حتی اگر پشت سرانه به حداکثر 32 رسانه در یک زمان پشتیبانی کند، به جز مشتریان سفارشی ما در حال حاضر توصیه می کنیم فقط امکان به اشتراک گذاشتن یک دوربین و یک ویدیو در یک زمان را فراهم کنیم. دوربین از طریق دکمه دوربین و سایر رسانه ها از طریق دکمه "به اشتراک گذاری" کنترل می شود.

در client-qt، بخش جالب در AvAdapter (و روش هایی مانند isCapturing، shareAllScreens، stopSharing) است. در منطق کتابخانه، addMedia و removeMedia در callModel مستقیما از requestMediaChange استفاده می کنند و می توانند به عنوان مرجع طراحی استفاده شوند.