aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/api/webrtc_api/connectivity/index.html
blob: 167ddcff9a82772a9f4e4869b2daa1c26e4ffb92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
---
title: WebRTC connectivity
slug: Web/API/WebRTC_API/Connectivity
translation_of: Web/API/WebRTC_API/Connectivity
---
<div>{{WebRTCSidebar}}{{draft}}</div>

<p><span class="seoSummary">WebRTC ではさまざまなプロトコルが相互作用してピア間の接続を確立し、データやメディアの転送を行いますが、この記事ではその仕組みを解説します。</span></p>

<div class="note">
<p><strong>Note:</strong> This page needs heavy rewriting for structural integrity and content completeness. Lots of info here is good but the organization is a mess since this is sort of a dumping ground right now.</p>
</div>

<h2 id="シグナリング">シグナリング</h2>

<p>残念なことに、WebRTC は中間に何らかのサーバーがなければ接続を作成できません。このサーバーを<strong>シグナルチャンネル</strong>、または<strong>シグナリングサービス</strong>と呼びます。接続を確立する前に情報を交換する伝達手段はどんなものでも構いません。Eメール、はがき、伝書鳩でも...決めるのはあなたです。</p>

<p>交換する必要のある情報はオファーとアンサーと呼ばれ、その中身は下記で説明する {{Glossary("SDP")}} です。</p>

<p>ピア A が接続を初期化する側とすると、ピア A がオファーを作成します。それから選択されたシグナルチャンネルを使ってピア B にオファーを送ります。ピア B はシグナルチャンネルからオファーを受け取ると、アンサーを作成します。それからピア B はピア A にシグナルチャンネルを使ってアンサーを送り返します。</p>

<h3 id="Session_descriptions">Session descriptions</h3>

<p>WebRTC 接続のエンドポイント設定は <strong>session description</strong> と呼ばれます。そこに含まれる情報は、送られるメディアの種類、形式、使用される転送プロトコル、エンドポイントの IP アドレスとポート、またその他メディア転送エンドポイントを記述するのに必要な情報です。この情報を  <strong>Session Description Protocol</strong> ({{Glossary("SDP")}}) を使って交換し、保存します。SDP データ形式の詳細は {{RFC(2327)}} にあります。</p>

<p>ユーザーが WebRTC コールを他のユーザーに開始するとき、<strong>オファー</strong>と呼ばれる特別な記述を作成します。コールする側がコールに必要な設定を提案し、そのすべての情報をオファーの記述に盛り込みます。受け取る側は<strong>アンサー</strong>を返します。アンサーは受け取る側が用意する記述です。このようにして、両デバイスがお互いにメディアデータの交換に必要な情報を共有します。この交換は Interactive Connectivity Establishment ({{Glossary("ICE")}}) を使って行われます。ICE とは二つのデバイスが Network Address Translation ({{Glossary("NAT")}}) によって隔てられていてもオファーとアンサーを交換するために媒介を利用できるようにするプロトコルです。</p>

<p>各ピアは二つの記述を手に入れます。 <strong>local description</strong> が自分側の記述で、 <strong>remote description</strong> が相手側の記述です。</p>

<p>オファー/アンサーの交換はコールを最初に確立する際に実行されますが、それだけでなくフォーマットや他の設定に変更が必要なときにも随時実行されます。コールの新規作成時でも既存の設定変更時でも、いずれにしてもオファーとアンサーを交換するために以下のような基本的なステップが実行されます。なお、ここでは ICE レイヤーは除外しています。</p>

<ol>
 <li>呼び出す側が {{domxref("navigator.mediaDevices.getUserMedia()")}} を通じてローカルメディアを取得する</li>
 <li>呼び出す側が <code>RTCPeerConnection</code> を作成し、 {{domxref("RTCPeerConnection.addTrack()")}} を実行する。(<code>addStream</code> が非推奨であるため)</li>
 <li>呼び出す側がオファーを作成するために {{domxref("RTCPeerConnection.createOffer()")}} を実行する</li>
 <li>呼び出す側がオファーを <em>local description</em> (ローカル側の接続の記述) として設定するために {{domxref("RTCPeerConnection.setLocalDescription()")}} を実行する</li>
 <li>呼び出す側は setLocalDescription() を実行した後、STUN サーバーに問い合わせて ICE 候補を生成する</li>
 <li>呼び出す側がシグナリングサーバーを使ってオファーを届けたい相手に送る</li>
 <li>受け取る側がオファーを受け取り、それを <em>remote description</em> (相手側の接続の記述) として記録するために {{domxref("RTCPeerConnection.setRemoteDescription()")}} を実行する</li>
 <li>受け取る側がコールに必要なセットアップを行う。ローカルメディアを取得し、 {{domxref("RTCPeerConnection.addTrack()")}} を通じてメディアトラックをピア接続にアタッチする</li>
 <li>受け取る側が {{domxref("RTCPeerConnection.createAnswer()")}} を実行することでアンサーを作成する</li>
 <li>受け取る側が {{domxref("RTCPeerConnection.setLocalDescription()")}} に作成したアンサーを渡して実行し、アンサーを自身の local description としてセットする。この時点で受け取る側は両側の接続設定を知ることになる。</li>
 <li>受け取る側がシグナリングサーバーを使ってアンサーを呼び出す側に送る</li>
 <li>呼び出す側がアンサーを受け取る。</li>
 <li>呼び出す側がアンサーを remote description として設定するために {{domxref("RTCPeerConnection.setRemoteDescription()")}} を実行する。これで呼び出す側も両者の設定を知ることになる。設定した通りにメディアが流れ始める。</li>
</ol>

<h3 id="Pending_and_current_descriptions">Pending and current descriptions</h3>

<p>Taking one step deeper into the process, we find that <code>localDescription</code> and <code>remoteDescription</code>, the properties which return these two descriptions, aren't as simple as they look. Because during renegotiation, an offer might be rejected because it proposes an incompatible format, it's necessary that each endpoint have the ability to propose a new format but not actually switch to it until it's accepted by the other peer. For that reason, WebRTC uses <em>pending</em> and <em>current</em> descriptions.</p>

<p>The <strong>current description</strong> (which is returned by the {{domxref("RTCPeerConnection.currentLocalDescription")}} and {{domxref("RTCPeerConnection.currentRemoteDescription")}} properties) represents the description currently in actual use by the connection. This is the most recent connection that both sides have fully agreed to use.</p>

<p>The <strong>pending description</strong> (returned by {{domxref("RTCPeerConnection.pendingLocalDescription")}} and {{domxref("RTCPeerConnection.pendingRemoteDescription")}}) indicates a description which is currently under consideration following a call to  <code>setLocalDescription()</code> or <code>setRemoteDescription()</code>, respectively.</p>

<p>When reading the description (returned by {{domxref("RTCPeerConnection.localDescription")}} and {{domxref("RTCPeerConnection.remoteDescription")}}), the returned value is the value of <code>pendingLocalDescription</code>/<code>pendingRemoteDescription</code> if there's a pending description (that is, the pending description isn't <code>null</code>); otherwise, the current description (<code>currentLocalDescription</code>/<code>currentRemoteDescription</code>) is returned.</p>

<p>When changing the description by calling <code>setLocalDescription()</code> or <code>setRemoteDescription()</code>, the specified description is set as the pending description, and the WebRTC layer begins to evaluate whether or not it's acceptable. Once the proposed description has been agreed upon, the value of <code>currentLocalDescription</code> or <code>currentRemoteDescription</code> is changed to the pending description, and the pending description is set to null again, indicating that there isn't a pending description.</p>

<div class="note">
<p>The <code>pendingLocalDescription</code> contains not just the offer or answer under consideration, but any local ICE candidates which have already been gathered since the offer or answer was created. Similarly, <code>pendingRemoteDescription</code> includes any remote ICE candidates which have been provided by calls to {{domxref("RTCPeerConnection.addIceCandidate()")}}.</p>
</div>

<p>See the individual articles on these properties and methods for more specifics, and <a href="/ja/docs/Web/Media/Formats/WebRTC_codecs">Codecs used by WebRTC</a> for information about codecs supported by WebRTC and which are compatible with which browsers. The codecs guide also offers guidance to help you choose the best codecs for your needs.</p>

<h2 id="ICE_candidates">ICE candidates</h2>

<p>As well as exchanging information about the media (discussed above in Offer/Answer and SDP), peers must exchange information about the network connection. This is known as an <strong>ICE candidate</strong> and details the available methods the peer is able to communicate (directly or through a TURN server). Typically, each peer will propose its best candidates first, making their way down the line toward their worse candidates. Ideally, candidates are UDP (since it's faster, and media streams are able to recover from interruptions relatively easily), but the ICE standard does allow TCP candidates as well.</p>

<div class="note">
<p>Generally, ICE candidates using TCP are only going to be used when UDP is not available or is restricted in ways that make it not suitable for media streaming. Not all browsers support ICE over TCP, however.</p>
</div>

<p>ICE allows candidates to represent connections over either {{Glossary("TCP")}} or {{Glossary("UDP")}}, with UDP generally being preferred (and being more widely supported). Each protocol supports a few types of candidate, with the candidate types defining how the data makes its way from peer to peer.</p>

<h3 id="UDP_candidate_types">UDP candidate types</h3>

<p>UDP candidates (candidates with their {{domxref("RTCIceCandidate.protocol", "protocol")}} set to <code>udp</code>) can be one of these types:</p>

<dl>
 <dt><code>host</code></dt>
 <dd>A host candidate is one for which its {{domxref("RTCIceCandidate.ip", "ip")}} address is the actual, direct IP address of the remote peer.</dd>
 <dt><code>prflx</code></dt>
 <dd>A peer reflexive candidate is one whose IP address comes from a symmetric NAT between the two peers, usually as an additional candidate during trickle ICE (that is, additional candidate exchanges that occur after primary signaling but before the connection verification phase is finished).</dd>
 <dt><code>srflx</code></dt>
 <dd>A server reflexive candidate is generated by a STUN/TURN server; the connection's initiator requests a candidate from the STUN server, which forwards the request through the remote peer's NAT, which creates and returns a candidate whose IP address is local to the remote peer. The STUN server then replies to the initiator's request with a candidate whose IP address is unrelated to the remote peer.</dd>
 <dt><code>relay</code></dt>
 <dd>A relay candidate is generated just like a server reflexive candidate (<code>"srflx"</code>), but using {{Glossary("TURN")}} instead of {{Glossary("STUN")}}.</dd>
</dl>

<h3 id="TCP_candidate_types">TCP candidate types</h3>

<p>TCP candidates (that is, candidates whose {{domxref("RTCIceCandidate.protocol", "protocol")}} is <code>tcp</code>) can be of these types:</p>

<dl>
 <dt><code>active</code></dt>
 <dd>The transport will try to open an outbound connection but won't receive incoming connection requests. This is the most common type, and the only one that most user agents will gather.</dd>
 <dt><code>passive</code></dt>
 <dd>The transport will receive incoming connection attempts but won't attempt a connection itself.</dd>
 <dt><code>so</code></dt>
 <dd>The transport will try to simultaneously open a connection with its peer.</dd>
</dl>

<h3 id="Choosing_a_candidate_pair">Choosing a candidate pair</h3>

<p>The ICE layer selects one of the two peers to serve as the <strong>controlling agent</strong>. This is the ICE agent which will make the final decision as to which candidate pair to use for the connection. The other peer is called the <strong>controlled agent</strong>. You can identify which one your end of the connection is by examining the value of {{domxref("RTCIceTransport.role", "RTCIceCandidate.transport.role")}}, although in general it doesn't matter which is which.</p>

<p>The controlling agent not only takes responsibility for making the final decision as to which candidate pair to use, but also for signaling that selection to the controlled agent by using STUN and an updated offer, if necessary. The controlled agent just waits to be told which candidate pair to use.</p>

<p>It's important to keep in mind that a single ICE session may result in the controlling agent choosing more than one candidate pair. Each time it does so and shares that information with the controlled agent, the two peers reconfigure their connection to use the new configuration described by the new candidate pair.</p>

<p>Once the ICE session is complete, the configuration that's currently in effect is the final one, unless an ICE reset occurs.</p>

<p>At the end of each generation of candidates, an end-of-candidates notification is sent in the form of an {{domxref("RTCIceCandidate")}} whose {{domxref("RTCIceCandidate.candidate", "candidate")}} property is an empty string. This candidate should still be added to the connection using {{domxref("RTCPeerConnection.addIceCandidate", "addIceCandidate()")}} method, as usual, in order to deliver that notification to the remote peer.</p>

<p>When there are no more candidates at all to be expected during the current negotiation exchange, an end-of-candidates notification is sent by delivering a {{domxref("RTCIceCandidate")}} whose {{domxref("RTCIceCandidate.candidate", "candidate")}} property is <code>null</code>. This message does <em>not</em> need to be sent to the remote peer. It's a legacy notification of a state which can be detected instead by watching for the {{domxref("RTCPeerConnection.iceGatheringState", "iceGatheringState")}} to change to <code>complete</code>, by watching for the {{domxref("RTCPeerConnection.icegatheringstatechange_event", "icegatheringstatechange")}} event.</p>

<h2 id="When_things_go_wrong">When things go wrong</h2>

<p>During negotiation, there will be times when things just don't work out. For example, when renegotiating a connection—for example, to adapt to changing hardware or network configurations—it's possible that negotiation could reach a dead end, or some form of error might occur that prevents negotiation at all. There may be permissions issues or other problems as well, for that matter.</p>

<h3 id="ICE_rollbacks">ICE rollbacks</h3>

<p>When renegotiating a connection that's already active and a situation arises in which the negotiation fails, you don't really want to kill the already-running call. After all, you were most likely just trying to upgrade or downgrade the connection, or to otherwise make adaptations to an ongoing session. Aborting the call would be an excessive reaction in that situation.</p>

<p>Instead, you can initiate an <strong>ICE rollback</strong>. A rollback restores the SDP offer (and the connection configuration by extension) to the configuration it had the last time the connection's {{domxref("RTCPeerConnection.signalingState", "signalingState")}} was <code>stable</code>.</p>

<p>To programmatically initiate a rollback, send a description whose {{domxref("RTCSessionDescription.type", "type")}} is <code>rollback</code>. Any other properties in the description object are ignored.</p>

<p>In addition, the ICE agent will automatically initiate a rollback when a peer that had previously created an offer receives an offer from the remote peer. In other words, if the local peer is in the state <code>have-local-offer</code>, indicating that the local peer had previously <em>sent</em> an offer, calling <code>setRemoteDescription()</code> with a <em>received</em> offer triggers rollback so that the negotiation switches from the remote peer being the caller to the local peer being the caller.</p>

<h3 id="ICE_restarts">ICE restarts</h3>

<p>For now, see {{SectionOnPage("/en-US/docs/Web/API/WebRTC_API/Session_lifetime", "ICE restart")}}.</p>

<h2 id="The_entire_exchange_in_a_complicated_diagram">The entire exchange in a complicated diagram</h2>

<p><a href="https://hacks.mozilla.org/wp-content/uploads/2013/07/webrtc-complete-diagram.png"><img alt="A complete architectural diagram showing the whole WebRTC process." src="https://mdn.mozillademos.org/files/6119/webrtc-complete-diagram.png" style="display: block; height: 559px; margin: 0px auto; width: 641px;"></a></p>