| 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::EnsureForCurrentThread(); | |
| 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 |