1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * 3. Neither the name of Google Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32
33#if ENABLE(MEDIA_STREAM)
34
35#include "RTCPeerConnection.h"
36
37#include "ArrayValue.h"
38#include "ExceptionCode.h"
39#include "KURL.h"
40#include "ScriptExecutionContext.h"
41
42namespace WebCore {
43
44// FIXME: RTCIceServer and RTCConfigration are placed here temporarily.
45// Their final place is in Source/WebCore/platform/mediastream.
46class RTCIceServer : public RefCounted<RTCIceServer> {
47public:
48 static PassRefPtr<RTCIceServer> create(const KURL& uri, const String& credential) { return adoptRef(new RTCIceServer(uri, credential)); }
49 virtual ~RTCIceServer() { }
50
51 const KURL& uri() { return m_uri; }
52 const String& credential() { return m_credential; }
53
54private:
55 RTCIceServer(const KURL& uri, const String& credential)
56 : m_uri(uri)
57 , m_credential(credential)
58 {
59 }
60
61 KURL m_uri;
62 String m_credential;
63};
64
65class RTCConfiguration : public RefCounted<RTCConfiguration> {
66public:
67 static PassRefPtr<RTCConfiguration> create() { return adoptRef(new RTCConfiguration()); }
68 virtual ~RTCConfiguration() { }
69
70 void appendServer(PassRefPtr<RTCIceServer> server) { m_servers.append(server); }
71 size_t numberOfServers() { return m_servers.size(); }
72 RTCIceServer* server(size_t index) { return m_servers[index].get(); }
73
74private:
75 RTCConfiguration() { }
76
77 Vector<RefPtr<RTCIceServer> > m_servers;
78};
79
80PassRefPtr<RTCConfiguration> RTCPeerConnection::parseConfiguration(const Dictionary& configuration, ExceptionCode& ec)
81{
82 if (configuration.isUndefinedOrNull())
83 return 0;
84
85 ArrayValue iceServers;
86 bool ok = configuration.get("iceServers", iceServers);
87 if (!ok) {
88 ec = TYPE_MISMATCH_ERR;
89 return 0;
90 }
91
92 size_t numberOfServers;
93 ok = iceServers.length(numberOfServers);
94 if (!ok) {
95 ec = TYPE_MISMATCH_ERR;
96 return 0;
97 }
98
99 RefPtr<RTCConfiguration> rtcConfiguration = RTCConfiguration::create();
100
101 for (size_t i = 0; i < numberOfServers; ++i) {
102 Dictionary iceServer;
103 ok = iceServers.get(i, iceServer);
104 if (!ok) {
105 ec = TYPE_MISMATCH_ERR;
106 return 0;
107 }
108
109 String uri, credential;
110 ok = iceServer.get("uri", uri);
111 if (!ok) {
112 ec = TYPE_MISMATCH_ERR;
113 return 0;
114 }
115 KURL url(KURL(), uri);
116 if (!url.isValid() || !(url.protocolIs("turn") || url.protocolIs("stun"))) {
117 ec = TYPE_MISMATCH_ERR;
118 return 0;
119 }
120
121 iceServer.get("credential", credential);
122
123 rtcConfiguration->appendServer(RTCIceServer::create(url, credential));
124 }
125 return rtcConfiguration.release();
126}
127
128PassRefPtr<RTCPeerConnection> RTCPeerConnection::create(ScriptExecutionContext* context, const Dictionary& rtcConfiguration, const Dictionary&, ExceptionCode& ec)
129{
130 RefPtr<RTCConfiguration> configuration = parseConfiguration(rtcConfiguration, ec);
131 if (ec)
132 return 0;
133
134 RefPtr<RTCPeerConnection> peerConnection = adoptRef(new RTCPeerConnection(context, configuration.release(), ec));
135 if (ec)
136 return 0;
137
138 peerConnection->suspendIfNeeded();
139 return peerConnection.release();
140}
141
142RTCPeerConnection::RTCPeerConnection(ScriptExecutionContext* context, PassRefPtr<RTCConfiguration>, ExceptionCode& ec)
143 : ActiveDOMObject(context, this)
144{
145}
146
147RTCPeerConnection::~RTCPeerConnection()
148{
149}
150
151const AtomicString& RTCPeerConnection::interfaceName() const
152{
153 return eventNames().interfaceForRTCPeerConnection;
154}
155
156ScriptExecutionContext* RTCPeerConnection::scriptExecutionContext() const
157{
158 return ActiveDOMObject::scriptExecutionContext();
159}
160
161void RTCPeerConnection::stop()
162{
163 // FIXME: Make sure that this object stops posting events and releases resources at this stage.
164}
165
166EventTargetData* RTCPeerConnection::eventTargetData()
167{
168 return &m_eventTargetData;
169}
170
171EventTargetData* RTCPeerConnection::ensureEventTargetData()
172{
173 return &m_eventTargetData;
174}
175
176} // namespace WebCore
177
178#endif // ENABLE(MEDIA_STREAM)