OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/renderer/p2p/p2p_transport_impl.h" | |
6 | |
7 #include "content/renderer/p2p/ipc_network_manager.h" | |
8 #include "content/renderer/p2p/ipc_socket_factory.h" | |
9 #include "content/renderer/p2p/port_allocator.h" | |
10 #include "jingle/glue/channel_socket_adapter.h" | |
11 #include "jingle/glue/pseudotcp_adapter.h" | |
12 #include "jingle/glue/thread_wrapper.h" | |
13 #include "jingle/glue/utils.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "third_party/libjingle/source/talk/base/helpers.h" | |
16 #include "third_party/libjingle/source/talk/p2p/base/constants.h" | |
17 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h" | |
18 #include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h" | |
19 | |
20 namespace content { | |
21 | |
22 P2PTransportImpl::P2PTransportImpl( | |
23 talk_base::NetworkManager* network_manager, | |
24 talk_base::PacketSocketFactory* socket_factory) | |
25 : socket_dispatcher_(NULL), | |
26 event_handler_(NULL), | |
27 state_(STATE_NONE), | |
28 network_manager_(network_manager), | |
29 socket_factory_(socket_factory) { | |
30 } | |
31 | |
32 P2PTransportImpl::P2PTransportImpl(P2PSocketDispatcher* socket_dispatcher) | |
33 : socket_dispatcher_(socket_dispatcher), | |
34 event_handler_(NULL), | |
35 state_(STATE_NONE), | |
36 network_manager_(new IpcNetworkManager(socket_dispatcher)), | |
37 socket_factory_(new IpcPacketSocketFactory(socket_dispatcher)) { | |
38 DCHECK(socket_dispatcher); | |
39 } | |
40 | |
41 P2PTransportImpl::~P2PTransportImpl() { | |
42 MessageLoop* message_loop = MessageLoop::current(); | |
43 | |
44 // Because libjingle's sigslot doesn't handle deletion from a signal | |
45 // handler we have to postpone deletion of libjingle objects. | |
46 message_loop->DeleteSoon(FROM_HERE, channel_.release()); | |
47 message_loop->DeleteSoon(FROM_HERE, allocator_.release()); | |
48 message_loop->DeleteSoon(FROM_HERE, socket_factory_.release()); | |
49 message_loop->DeleteSoon(FROM_HERE, network_manager_.release()); | |
50 } | |
51 | |
52 bool P2PTransportImpl::Init(WebKit::WebFrame* web_frame, | |
53 const std::string& name, | |
54 Protocol protocol, | |
55 const Config& config, | |
56 EventHandler* event_handler) { | |
57 DCHECK(event_handler); | |
58 | |
59 // Before proceeding, ensure we have libjingle thread wrapper for | |
60 // the current thread. | |
61 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | |
62 | |
63 name_ = name; | |
64 event_handler_ = event_handler; | |
65 | |
66 if (socket_dispatcher_) { | |
67 DCHECK(web_frame); | |
68 allocator_.reset(new P2PPortAllocator( | |
69 web_frame, socket_dispatcher_, network_manager_.get(), | |
70 socket_factory_.get(), config)); | |
71 } else { | |
72 // Use BasicPortAllocator if we don't have P2PSocketDispatcher | |
73 // (for unittests). | |
74 allocator_.reset(new cricket::BasicPortAllocator( | |
75 network_manager_.get(), socket_factory_.get())); | |
76 } | |
77 | |
78 DCHECK(!channel_.get()); | |
79 channel_.reset(new cricket::P2PTransportChannel( | |
80 "", 0, NULL, allocator_.get())); | |
81 channel_->SetIceUfrag( | |
82 talk_base::CreateRandomString(cricket::ICE_UFRAG_LENGTH)); | |
83 channel_->SetIcePwd(talk_base::CreateRandomString(cricket::ICE_PWD_LENGTH)); | |
84 channel_->SignalRequestSignaling.connect( | |
85 this, &P2PTransportImpl::OnRequestSignaling); | |
86 channel_->SignalCandidateReady.connect( | |
87 this, &P2PTransportImpl::OnCandidateReady); | |
88 | |
89 if (protocol == PROTOCOL_UDP) { | |
90 channel_->SignalReadableState.connect( | |
91 this, &P2PTransportImpl::OnReadableState); | |
92 channel_->SignalWritableState.connect( | |
93 this, &P2PTransportImpl::OnWriteableState); | |
94 } | |
95 | |
96 channel_adapter_.reset(new jingle_glue::TransportChannelSocketAdapter( | |
97 channel_.get())); | |
98 | |
99 channel_->Connect(); | |
100 | |
101 if (protocol == PROTOCOL_TCP) { | |
102 pseudo_tcp_adapter_.reset(new jingle_glue::PseudoTcpAdapter( | |
103 channel_adapter_.release())); | |
104 | |
105 if (config.tcp_receive_window > 0) | |
106 pseudo_tcp_adapter_->SetReceiveBufferSize(config.tcp_receive_window); | |
107 if (config.tcp_send_window > 0) | |
108 pseudo_tcp_adapter_->SetReceiveBufferSize(config.tcp_receive_window); | |
109 pseudo_tcp_adapter_->SetNoDelay(config.tcp_no_delay); | |
110 if (config.tcp_ack_delay_ms > 0) | |
111 pseudo_tcp_adapter_->SetAckDelay(config.tcp_ack_delay_ms); | |
112 | |
113 int result = pseudo_tcp_adapter_->Connect( | |
114 base::Bind(&P2PTransportImpl::OnTcpConnected, base::Unretained(this))); | |
115 if (result != net::ERR_IO_PENDING) | |
116 OnTcpConnected(result); | |
117 } | |
118 | |
119 return true; | |
120 } | |
121 | |
122 bool P2PTransportImpl::AddRemoteCandidate(const std::string& address) { | |
123 cricket::Candidate candidate; | |
124 if (!jingle_glue::DeserializeP2PCandidate(address, &candidate)) { | |
125 LOG(ERROR) << "Failed to parse candidate " << address; | |
126 return false; | |
127 } | |
128 | |
129 channel_->OnCandidate(candidate); | |
130 return true; | |
131 } | |
132 | |
133 void P2PTransportImpl::OnRequestSignaling( | |
134 cricket::TransportChannelImpl* channel) { | |
135 channel_->OnSignalingReady(); | |
136 } | |
137 | |
138 void P2PTransportImpl::OnCandidateReady( | |
139 cricket::TransportChannelImpl* channel, | |
140 const cricket::Candidate& candidate) { | |
141 event_handler_->OnCandidateReady( | |
142 jingle_glue::SerializeP2PCandidate(candidate)); | |
143 } | |
144 | |
145 void P2PTransportImpl::OnReadableState(cricket::TransportChannel* channel) { | |
146 state_ = static_cast<State>(state_ | STATE_READABLE); | |
147 event_handler_->OnStateChange(state_); | |
148 } | |
149 | |
150 void P2PTransportImpl::OnWriteableState(cricket::TransportChannel* channel) { | |
151 state_ = static_cast<State>(state_ | STATE_WRITABLE); | |
152 event_handler_->OnStateChange(state_); | |
153 } | |
154 | |
155 net::Socket* P2PTransportImpl::GetChannel() { | |
156 if (pseudo_tcp_adapter_.get()) { | |
157 DCHECK(!channel_adapter_.get()); | |
158 return pseudo_tcp_adapter_.get(); | |
159 } else { | |
160 DCHECK(channel_adapter_.get()); | |
161 return channel_adapter_.get(); | |
162 } | |
163 } | |
164 | |
165 void P2PTransportImpl::OnTcpConnected(int result) { | |
166 if (result < 0) { | |
167 event_handler_->OnError(result); | |
168 return; | |
169 } | |
170 state_ = static_cast<State>(STATE_READABLE | STATE_WRITABLE); | |
171 event_handler_->OnStateChange(state_); | |
172 } | |
173 | |
174 } // namespace content | |
OLD | NEW |