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/ipc_socket_factory.h" 6 7 #include <algorithm> 8 #include <deque> 9 10 #include "base/compiler_specific.h" 11 #include "base/debug/trace_event.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop_proxy.h" 14 #include "base/metrics/histogram.h" 15 #include "base/strings/stringprintf.h" 16 #include "base/threading/non_thread_safe.h" 17 #include "content/renderer/media/webrtc_logging.h" 18 #include "content/renderer/p2p/host_address_request.h" 19 #include "content/renderer/p2p/socket_client_delegate.h" 20 #include "content/renderer/p2p/socket_client_impl.h" 21 #include "content/renderer/p2p/socket_dispatcher.h" 22 #include "jingle/glue/utils.h" 23 #include "third_party/webrtc/base/asyncpacketsocket.h" 24 25 namespace content { 26 27 namespace { 28 29 const int kDefaultNonSetOptionValue = -1; 30 31 bool IsTcpClientSocket(P2PSocketType type) { 32 return (type == P2P_SOCKET_STUN_TCP_CLIENT) || 33 (type == P2P_SOCKET_TCP_CLIENT) || 34 (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) || 35 (type == P2P_SOCKET_SSLTCP_CLIENT) || 36 (type == P2P_SOCKET_TLS_CLIENT) || 37 (type == P2P_SOCKET_STUN_TLS_CLIENT); 38 } 39 40 bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option, 41 P2PSocketOption* ipc_option) { 42 switch (option) { 43 case rtc::Socket::OPT_RCVBUF: 44 *ipc_option = P2P_SOCKET_OPT_RCVBUF; 45 break; 46 case rtc::Socket::OPT_SNDBUF: 47 *ipc_option = P2P_SOCKET_OPT_SNDBUF; 48 break; 49 case rtc::Socket::OPT_DSCP: 50 *ipc_option = P2P_SOCKET_OPT_DSCP; 51 break; 52 case rtc::Socket::OPT_DONTFRAGMENT: 53 case rtc::Socket::OPT_NODELAY: 54 case rtc::Socket::OPT_IPV6_V6ONLY: 55 case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID: 56 return false; // Not supported by the chrome sockets. 57 default: 58 NOTREACHED(); 59 return false; 60 } 61 return true; 62 } 63 64 // TODO(miu): This needs tuning. http://crbug.com/237960 65 const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB 66 67 // IpcPacketSocket implements rtc::AsyncPacketSocket interface 68 // using P2PSocketClient that works over IPC-channel. It must be used 69 // on the thread it was created. 70 class IpcPacketSocket : public rtc::AsyncPacketSocket, 71 public P2PSocketClientDelegate { 72 public: 73 IpcPacketSocket(); 74 virtual ~IpcPacketSocket(); 75 76 // Always takes ownership of client even if initialization fails. 77 bool Init(P2PSocketType type, P2PSocketClientImpl* client, 78 const rtc::SocketAddress& local_address, 79 const rtc::SocketAddress& remote_address); 80 81 // rtc::AsyncPacketSocket interface. 82 virtual rtc::SocketAddress GetLocalAddress() const OVERRIDE; 83 virtual rtc::SocketAddress GetRemoteAddress() const OVERRIDE; 84 virtual int Send(const void *pv, size_t cb, 85 const rtc::PacketOptions& options) OVERRIDE; 86 virtual int SendTo(const void *pv, size_t cb, 87 const rtc::SocketAddress& addr, 88 const rtc::PacketOptions& options) OVERRIDE; 89 virtual int Close() OVERRIDE; 90 virtual State GetState() const OVERRIDE; 91 virtual int GetOption(rtc::Socket::Option option, int* value) OVERRIDE; 92 virtual int SetOption(rtc::Socket::Option option, int value) OVERRIDE; 93 virtual int GetError() const OVERRIDE; 94 virtual void SetError(int error) OVERRIDE; 95 96 // P2PSocketClientDelegate implementation. 97 virtual void OnOpen(const net::IPEndPoint& local_address, 98 const net::IPEndPoint& remote_address) OVERRIDE; 99 virtual void OnIncomingTcpConnection( 100 const net::IPEndPoint& address, 101 P2PSocketClient* client) OVERRIDE; 102 virtual void OnSendComplete() OVERRIDE; 103 virtual void OnError() OVERRIDE; 104 virtual void OnDataReceived(const net::IPEndPoint& address, 105 const std::vector<char>& data, 106 const base::TimeTicks& timestamp) OVERRIDE; 107 108 private: 109 enum InternalState { 110 IS_UNINITIALIZED, 111 IS_OPENING, 112 IS_OPEN, 113 IS_CLOSED, 114 IS_ERROR, 115 }; 116 117 // Increment the counter for consecutive bytes discarded as socket is running 118 // out of buffer. 119 void IncrementDiscardCounters(size_t bytes_discarded); 120 121 // Update trace of send throttling internal state. This should be called 122 // immediately after any changes to |send_bytes_available_| and/or 123 // |in_flight_packet_sizes_|. 124 void TraceSendThrottlingState() const; 125 126 void InitAcceptedTcp(P2PSocketClient* client, 127 const rtc::SocketAddress& local_address, 128 const rtc::SocketAddress& remote_address); 129 130 int DoSetOption(P2PSocketOption option, int value); 131 132 P2PSocketType type_; 133 134 // Message loop on which this socket was created and being used. 135 base::MessageLoop* message_loop_; 136 137 // Corresponding P2P socket client. 138 scoped_refptr<P2PSocketClient> client_; 139 140 // Local address is allocated by the browser process, and the 141 // renderer side doesn't know the address until it receives OnOpen() 142 // event from the browser. 143 rtc::SocketAddress local_address_; 144 145 // Remote address for client TCP connections. 146 rtc::SocketAddress remote_address_; 147 148 // Current state of the object. 149 InternalState state_; 150 151 // Track the number of bytes allowed to be sent non-blocking. This is used to 152 // throttle the sending of packets to the browser process. For each packet 153 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs 154 // from the browser process) are made, the value is increased back. This 155 // allows short bursts of high-rate sending without dropping packets, but 156 // quickly restricts the client to a sustainable steady-state rate. 157 size_t send_bytes_available_; 158 std::deque<size_t> in_flight_packet_sizes_; 159 160 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the 161 // caller expects SignalWritable notification. 162 bool writable_signal_expected_; 163 164 // Current error code. Valid when state_ == IS_ERROR. 165 int error_; 166 int options_[P2P_SOCKET_OPT_MAX]; 167 168 // Track the maximum and current consecutive bytes discarded due to not enough 169 // send_bytes_available_. 170 size_t max_discard_bytes_sequence_; 171 size_t current_discard_bytes_sequence_; 172 173 // Track the total number of packets and the number of packets discarded. 174 size_t packets_discarded_; 175 size_t total_packets_; 176 177 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket); 178 }; 179 180 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this 181 // class is to send SignalDone, after OnDone callback from 182 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case 183 // of MT sig slots clients must call disconnect. This class is to make sure 184 // we destruct from the same thread on which is created. 185 class AsyncAddressResolverImpl : public base::NonThreadSafe, 186 public rtc::AsyncResolverInterface { 187 public: 188 AsyncAddressResolverImpl(P2PSocketDispatcher* dispatcher); 189 virtual ~AsyncAddressResolverImpl(); 190 191 // rtc::AsyncResolverInterface interface. 192 virtual void Start(const rtc::SocketAddress& addr) OVERRIDE; 193 virtual bool GetResolvedAddress( 194 int family, rtc::SocketAddress* addr) const OVERRIDE; 195 virtual int GetError() const OVERRIDE; 196 virtual void Destroy(bool wait) OVERRIDE; 197 198 private: 199 virtual void OnAddressResolved(const net::IPAddressList& addresses); 200 201 scoped_refptr<P2PAsyncAddressResolver> resolver_; 202 int port_; // Port number in |addr| from Start() method. 203 std::vector<rtc::IPAddress> addresses_; // Resolved addresses. 204 }; 205 206 IpcPacketSocket::IpcPacketSocket() 207 : type_(P2P_SOCKET_UDP), 208 message_loop_(base::MessageLoop::current()), 209 state_(IS_UNINITIALIZED), 210 send_bytes_available_(kMaximumInFlightBytes), 211 writable_signal_expected_(false), 212 error_(0), 213 max_discard_bytes_sequence_(0), 214 current_discard_bytes_sequence_(0), 215 packets_discarded_(0), 216 total_packets_(0) { 217 COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate); 218 std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX), 219 kDefaultNonSetOptionValue); 220 } 221 222 IpcPacketSocket::~IpcPacketSocket() { 223 if (state_ == IS_OPENING || state_ == IS_OPEN || 224 state_ == IS_ERROR) { 225 Close(); 226 } 227 228 UMA_HISTOGRAM_COUNTS_10000("WebRTC.ApplicationMaxConsecutiveBytesDiscard", 229 max_discard_bytes_sequence_); 230 231 if (total_packets_ > 0) { 232 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded", 233 (packets_discarded_ * 100) / total_packets_); 234 } 235 } 236 237 void IpcPacketSocket::TraceSendThrottlingState() const { 238 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), 239 send_bytes_available_); 240 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), 241 in_flight_packet_sizes_.size()); 242 } 243 244 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) { 245 current_discard_bytes_sequence_ += bytes_discarded; 246 packets_discarded_++; 247 248 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) { 249 max_discard_bytes_sequence_ = current_discard_bytes_sequence_; 250 } 251 } 252 253 bool IpcPacketSocket::Init(P2PSocketType type, 254 P2PSocketClientImpl* client, 255 const rtc::SocketAddress& local_address, 256 const rtc::SocketAddress& remote_address) { 257 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 258 DCHECK_EQ(state_, IS_UNINITIALIZED); 259 260 type_ = type; 261 client_ = client; 262 local_address_ = local_address; 263 remote_address_ = remote_address; 264 state_ = IS_OPENING; 265 266 net::IPEndPoint local_endpoint; 267 if (!jingle_glue::SocketAddressToIPEndPoint( 268 local_address, &local_endpoint)) { 269 return false; 270 } 271 272 net::IPEndPoint remote_endpoint; 273 if (!remote_address.IsNil()) { 274 DCHECK(IsTcpClientSocket(type_)); 275 276 if (remote_address.IsUnresolvedIP()) { 277 remote_endpoint = 278 net::IPEndPoint(net::IPAddressNumber(), remote_address.port()); 279 } else { 280 if (!jingle_glue::SocketAddressToIPEndPoint(remote_address, 281 &remote_endpoint)) { 282 return false; 283 } 284 } 285 } 286 287 // We need to send both resolved and unresolved address in Init. Unresolved 288 // address will be used in case of TLS for certificate hostname matching. 289 // Certificate will be tied to domain name not to IP address. 290 P2PHostAndIPEndPoint remote_info(remote_address.hostname(), remote_endpoint); 291 292 client->Init(type, local_endpoint, remote_info, this); 293 294 return true; 295 } 296 297 void IpcPacketSocket::InitAcceptedTcp( 298 P2PSocketClient* client, 299 const rtc::SocketAddress& local_address, 300 const rtc::SocketAddress& remote_address) { 301 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 302 DCHECK_EQ(state_, IS_UNINITIALIZED); 303 304 client_ = client; 305 local_address_ = local_address; 306 remote_address_ = remote_address; 307 state_ = IS_OPEN; 308 TraceSendThrottlingState(); 309 client_->SetDelegate(this); 310 } 311 312 // rtc::AsyncPacketSocket interface. 313 rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const { 314 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 315 return local_address_; 316 } 317 318 rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const { 319 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 320 return remote_address_; 321 } 322 323 int IpcPacketSocket::Send(const void *data, size_t data_size, 324 const rtc::PacketOptions& options) { 325 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 326 return SendTo(data, data_size, remote_address_, options); 327 } 328 329 int IpcPacketSocket::SendTo(const void *data, size_t data_size, 330 const rtc::SocketAddress& address, 331 const rtc::PacketOptions& options) { 332 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 333 334 switch (state_) { 335 case IS_UNINITIALIZED: 336 NOTREACHED(); 337 return EWOULDBLOCK; 338 case IS_OPENING: 339 return EWOULDBLOCK; 340 case IS_CLOSED: 341 return ENOTCONN; 342 case IS_ERROR: 343 return error_; 344 case IS_OPEN: 345 // Continue sending the packet. 346 break; 347 } 348 349 if (data_size == 0) { 350 NOTREACHED(); 351 return 0; 352 } 353 354 total_packets_++; 355 356 if (data_size > send_bytes_available_) { 357 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", 358 TRACE_EVENT_SCOPE_THREAD, 359 "id", 360 client_->GetSocketID()); 361 if (!writable_signal_expected_) { 362 WebRtcLogMessage(base::StringPrintf( 363 "IpcPacketSocket: sending is blocked. %d packets_in_flight.", 364 static_cast<int>(in_flight_packet_sizes_.size()))); 365 366 writable_signal_expected_ = true; 367 } 368 369 error_ = EWOULDBLOCK; 370 IncrementDiscardCounters(data_size); 371 return -1; 372 } else { 373 current_discard_bytes_sequence_ = 0; 374 } 375 376 net::IPEndPoint address_chrome; 377 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { 378 NOTREACHED(); 379 error_ = EINVAL; 380 return -1; 381 } 382 383 send_bytes_available_ -= data_size; 384 in_flight_packet_sizes_.push_back(data_size); 385 TraceSendThrottlingState(); 386 387 const char* data_char = reinterpret_cast<const char*>(data); 388 std::vector<char> data_vector(data_char, data_char + data_size); 389 client_->SendWithDscp(address_chrome, data_vector, options); 390 391 // Fake successful send. The caller ignores result anyway. 392 return data_size; 393 } 394 395 int IpcPacketSocket::Close() { 396 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 397 398 client_->Close(); 399 state_ = IS_CLOSED; 400 401 return 0; 402 } 403 404 rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const { 405 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 406 407 switch (state_) { 408 case IS_UNINITIALIZED: 409 NOTREACHED(); 410 return STATE_CLOSED; 411 412 case IS_OPENING: 413 return STATE_BINDING; 414 415 case IS_OPEN: 416 if (IsTcpClientSocket(type_)) { 417 return STATE_CONNECTED; 418 } else { 419 return STATE_BOUND; 420 } 421 422 case IS_CLOSED: 423 case IS_ERROR: 424 return STATE_CLOSED; 425 } 426 427 NOTREACHED(); 428 return STATE_CLOSED; 429 } 430 431 int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) { 432 P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX; 433 if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) { 434 // unsupported option. 435 return -1; 436 } 437 438 *value = options_[p2p_socket_option]; 439 return 0; 440 } 441 442 int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) { 443 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 444 445 P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX; 446 if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) { 447 // Option is not supported. 448 return -1; 449 } 450 451 options_[p2p_socket_option] = value; 452 453 if (state_ == IS_OPEN) { 454 // Options will be applied when state becomes IS_OPEN in OnOpen. 455 return DoSetOption(p2p_socket_option, value); 456 } 457 return 0; 458 } 459 460 int IpcPacketSocket::DoSetOption(P2PSocketOption option, int value) { 461 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 462 DCHECK_EQ(state_, IS_OPEN); 463 464 client_->SetOption(option, value); 465 return 0; 466 } 467 468 int IpcPacketSocket::GetError() const { 469 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 470 return error_; 471 } 472 473 void IpcPacketSocket::SetError(int error) { 474 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 475 error_ = error; 476 } 477 478 void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address, 479 const net::IPEndPoint& remote_address) { 480 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 481 482 if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) { 483 // Always expect correct IPv4 address to be allocated. 484 NOTREACHED(); 485 OnError(); 486 return; 487 } 488 489 state_ = IS_OPEN; 490 TraceSendThrottlingState(); 491 492 // Set all pending options if any. 493 for (int i = 0; i < P2P_SOCKET_OPT_MAX; ++i) { 494 if (options_[i] != kDefaultNonSetOptionValue) 495 DoSetOption(static_cast<P2PSocketOption> (i), options_[i]); 496 } 497 498 SignalAddressReady(this, local_address_); 499 if (IsTcpClientSocket(type_)) { 500 SignalConnect(this); 501 // If remote address is unresolved, set resolved remote IP address received 502 // in the callback. This address will be used while sending the packets 503 // over the network. 504 if (remote_address_.IsUnresolvedIP()) { 505 rtc::SocketAddress jingle_socket_address; 506 if (!jingle_glue::IPEndPointToSocketAddress( 507 remote_address, &jingle_socket_address)) { 508 NOTREACHED(); 509 } 510 // Set only the IP address. 511 remote_address_.SetResolvedIP(jingle_socket_address.ipaddr()); 512 } 513 } 514 } 515 516 void IpcPacketSocket::OnIncomingTcpConnection( 517 const net::IPEndPoint& address, 518 P2PSocketClient* client) { 519 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 520 521 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); 522 523 rtc::SocketAddress remote_address; 524 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) { 525 // Always expect correct IPv4 address to be allocated. 526 NOTREACHED(); 527 } 528 socket->InitAcceptedTcp(client, local_address_, remote_address); 529 SignalNewConnection(this, socket.release()); 530 } 531 532 void IpcPacketSocket::OnSendComplete() { 533 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 534 535 CHECK(!in_flight_packet_sizes_.empty()); 536 send_bytes_available_ += in_flight_packet_sizes_.front(); 537 538 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes); 539 540 in_flight_packet_sizes_.pop_front(); 541 TraceSendThrottlingState(); 542 543 if (writable_signal_expected_ && send_bytes_available_ > 0) { 544 WebRtcLogMessage(base::StringPrintf( 545 "IpcPacketSocket: sending is unblocked. %d packets in flight.", 546 static_cast<int>(in_flight_packet_sizes_.size()))); 547 548 SignalReadyToSend(this); 549 writable_signal_expected_ = false; 550 } 551 } 552 553 void IpcPacketSocket::OnError() { 554 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 555 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED); 556 state_ = IS_ERROR; 557 error_ = ECONNABORTED; 558 if (!was_closed) { 559 SignalClose(this, 0); 560 } 561 } 562 563 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, 564 const std::vector<char>& data, 565 const base::TimeTicks& timestamp) { 566 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 567 568 rtc::SocketAddress address_lj; 569 if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) { 570 // We should always be able to convert address here because we 571 // don't expect IPv6 address on IPv4 connections. 572 NOTREACHED(); 573 return; 574 } 575 576 rtc::PacketTime packet_time(timestamp.ToInternalValue(), 0); 577 SignalReadPacket(this, &data[0], data.size(), address_lj, 578 packet_time); 579 } 580 581 AsyncAddressResolverImpl::AsyncAddressResolverImpl( 582 P2PSocketDispatcher* dispatcher) 583 : resolver_(new P2PAsyncAddressResolver(dispatcher)) { 584 } 585 586 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() { 587 } 588 589 void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) { 590 DCHECK(CalledOnValidThread()); 591 // Copy port number from |addr|. |port_| must be copied 592 // when resolved address is returned in GetResolvedAddress. 593 port_ = addr.port(); 594 595 resolver_->Start(addr, base::Bind( 596 &AsyncAddressResolverImpl::OnAddressResolved, 597 base::Unretained(this))); 598 } 599 600 bool AsyncAddressResolverImpl::GetResolvedAddress( 601 int family, rtc::SocketAddress* addr) const { 602 DCHECK(CalledOnValidThread()); 603 604 if (addresses_.empty()) 605 return false; 606 607 for (size_t i = 0; i < addresses_.size(); ++i) { 608 if (family == addresses_[i].family()) { 609 addr->SetResolvedIP(addresses_[i]); 610 addr->SetPort(port_); 611 return true; 612 } 613 } 614 return false; 615 } 616 617 int AsyncAddressResolverImpl::GetError() const { 618 DCHECK(CalledOnValidThread()); 619 return addresses_.empty() ? -1 : 0; 620 } 621 622 void AsyncAddressResolverImpl::Destroy(bool wait) { 623 DCHECK(CalledOnValidThread()); 624 resolver_->Cancel(); 625 // Libjingle doesn't need this object any more and it's not going to delete 626 // it explicitly. 627 delete this; 628 } 629 630 void AsyncAddressResolverImpl::OnAddressResolved( 631 const net::IPAddressList& addresses) { 632 DCHECK(CalledOnValidThread()); 633 for (size_t i = 0; i < addresses.size(); ++i) { 634 rtc::SocketAddress socket_address; 635 if (!jingle_glue::IPEndPointToSocketAddress( 636 net::IPEndPoint(addresses[i], 0), &socket_address)) { 637 NOTREACHED(); 638 } 639 addresses_.push_back(socket_address.ipaddr()); 640 } 641 SignalDone(this); 642 } 643 644 } // namespace 645 646 IpcPacketSocketFactory::IpcPacketSocketFactory( 647 P2PSocketDispatcher* socket_dispatcher) 648 : socket_dispatcher_(socket_dispatcher) { 649 } 650 651 IpcPacketSocketFactory::~IpcPacketSocketFactory() { 652 } 653 654 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket( 655 const rtc::SocketAddress& local_address, int min_port, int max_port) { 656 rtc::SocketAddress crome_address; 657 P2PSocketClientImpl* socket_client = 658 new P2PSocketClientImpl(socket_dispatcher_); 659 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); 660 // TODO(sergeyu): Respect local_address and port limits here (need 661 // to pass them over IPC channel to the browser). 662 if (!socket->Init(P2P_SOCKET_UDP, socket_client, 663 local_address, rtc::SocketAddress())) { 664 return NULL; 665 } 666 return socket.release(); 667 } 668 669 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket( 670 const rtc::SocketAddress& local_address, int min_port, int max_port, 671 int opts) { 672 // TODO(sergeyu): Implement SSL support. 673 if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) 674 return NULL; 675 676 P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN) ? 677 P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER; 678 P2PSocketClientImpl* socket_client = 679 new P2PSocketClientImpl(socket_dispatcher_); 680 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); 681 if (!socket->Init(type, socket_client, local_address, 682 rtc::SocketAddress())) { 683 return NULL; 684 } 685 return socket.release(); 686 } 687 688 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket( 689 const rtc::SocketAddress& local_address, 690 const rtc::SocketAddress& remote_address, 691 const rtc::ProxyInfo& proxy_info, 692 const std::string& user_agent, int opts) { 693 P2PSocketType type; 694 if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) { 695 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ? 696 P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT; 697 } else if (opts & rtc::PacketSocketFactory::OPT_TLS) { 698 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ? 699 P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT; 700 } else { 701 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ? 702 P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT; 703 } 704 P2PSocketClientImpl* socket_client = 705 new P2PSocketClientImpl(socket_dispatcher_); 706 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); 707 if (!socket->Init(type, socket_client, local_address, remote_address)) 708 return NULL; 709 return socket.release(); 710 } 711 712 rtc::AsyncResolverInterface* 713 IpcPacketSocketFactory::CreateAsyncResolver() { 714 scoped_ptr<AsyncAddressResolverImpl> resolver( 715 new AsyncAddressResolverImpl(socket_dispatcher_)); 716 return resolver.release(); 717 } 718 719 } // namespace content 720