(Auto)update libjingle 64709629-> 64813990
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5897 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
		@@ -266,13 +266,6 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
 | 
			
		||||
                                                 server.password,
 | 
			
		||||
                                                 turn_transport_type,
 | 
			
		||||
                                                 secure));
 | 
			
		||||
        // STUN functionality is part of TURN.
 | 
			
		||||
        // Note: If there is only TURNS is supplied as part of configuration,
 | 
			
		||||
        // we will have problem in fetching server reflexive candidate, as
 | 
			
		||||
        // currently we don't have support of TCP/TLS in stunport.cc.
 | 
			
		||||
        // In that case we should fetch server reflexive addess from
 | 
			
		||||
        // TURN allocate response.
 | 
			
		||||
        stun_config->push_back(StunConfiguration(address, port));
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case INVALID:
 | 
			
		||||
 
 | 
			
		||||
@@ -184,12 +184,6 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) {
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::StunConfiguration stun1(
 | 
			
		||||
      "stun.l.google.com", 19302);
 | 
			
		||||
  stun_configs.push_back(stun1);
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::StunConfiguration stun2(
 | 
			
		||||
        "test.com", 1234);
 | 
			
		||||
  stun_configs.push_back(stun2);
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::StunConfiguration stun3(
 | 
			
		||||
        "hello.com", kDefaultStunPort);
 | 
			
		||||
  stun_configs.push_back(stun3);
 | 
			
		||||
  VerifyStunConfigurations(stun_configs);
 | 
			
		||||
  TurnConfigurations turn_configs;
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn1(
 | 
			
		||||
@@ -242,11 +236,6 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingTurnUrlWithTransportParam) {
 | 
			
		||||
      "hello.com", kDefaultStunPort, "test", kTurnPassword, "tcp", false);
 | 
			
		||||
  turn_configs.push_back(turn);
 | 
			
		||||
  VerifyTurnConfigurations(turn_configs);
 | 
			
		||||
  StunConfigurations stun_configs;
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::StunConfiguration stun(
 | 
			
		||||
        "hello.com", kDefaultStunPort);
 | 
			
		||||
  stun_configs.push_back(stun);
 | 
			
		||||
  VerifyStunConfigurations(stun_configs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) {
 | 
			
		||||
@@ -317,9 +306,8 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIPLiteralAddress) {
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::StunConfiguration stun4(
 | 
			
		||||
      "2401:fa00:4::", 3478);
 | 
			
		||||
  stun_configs.push_back(stun4);  // Default port
 | 
			
		||||
  // Turn Address has the same host information as |stun3|.
 | 
			
		||||
  stun_configs.push_back(stun3);
 | 
			
		||||
  VerifyStunConfigurations(stun_configs);
 | 
			
		||||
 | 
			
		||||
  TurnConfigurations turn_configs;
 | 
			
		||||
  webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn1(
 | 
			
		||||
      "2401:fa00:4::", 1234, "test", kTurnPassword, "udp", false);
 | 
			
		||||
 
 | 
			
		||||
@@ -301,7 +301,7 @@ class PeerConnectionInterfaceTest : public testing::Test {
 | 
			
		||||
    EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
 | 
			
		||||
 | 
			
		||||
    CreatePeerConnection(kTurnIceServerUri, kTurnPassword, NULL);
 | 
			
		||||
    EXPECT_EQ(1u, port_allocator_factory_->stun_configs().size());
 | 
			
		||||
    EXPECT_EQ(0u, port_allocator_factory_->stun_configs().size());
 | 
			
		||||
    EXPECT_EQ(1u, port_allocator_factory_->turn_configs().size());
 | 
			
		||||
    EXPECT_EQ(kTurnUsername,
 | 
			
		||||
              port_allocator_factory_->turn_configs()[0].username);
 | 
			
		||||
@@ -309,8 +309,6 @@ class PeerConnectionInterfaceTest : public testing::Test {
 | 
			
		||||
              port_allocator_factory_->turn_configs()[0].password);
 | 
			
		||||
    EXPECT_EQ(kTurnHostname,
 | 
			
		||||
              port_allocator_factory_->turn_configs()[0].server.hostname());
 | 
			
		||||
    EXPECT_EQ(kTurnHostname,
 | 
			
		||||
              port_allocator_factory_->stun_configs()[0].server.hostname());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void ReleasePeerConnection() {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,9 @@
 | 
			
		||||
#if !defined(USE_WEBRTC_DEV_BRANCH)
 | 
			
		||||
namespace webrtc {
 | 
			
		||||
 | 
			
		||||
bool operator==(const webrtc::VideoCodec& c1, const webrtc::VideoCodec& c2) {
 | 
			
		||||
// This function is 'inline' to avoid link errors.
 | 
			
		||||
inline bool operator==(const webrtc::VideoCodec& c1,
 | 
			
		||||
                       const webrtc::VideoCodec& c2) {
 | 
			
		||||
  return memcmp(&c1, &c2, sizeof(c1)) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -300,6 +302,7 @@ class FakeWebRtcVideoEngine
 | 
			
		||||
          send_nack_bitrate_(0),
 | 
			
		||||
          send_bandwidth_(0),
 | 
			
		||||
          receive_bandwidth_(0),
 | 
			
		||||
          reserved_transmit_bitrate_bps_(0),
 | 
			
		||||
          suspend_below_min_bitrate_(false),
 | 
			
		||||
          overuse_observer_(NULL) {
 | 
			
		||||
      ssrcs_[0] = 0;  // default ssrc.
 | 
			
		||||
@@ -343,6 +346,7 @@ class FakeWebRtcVideoEngine
 | 
			
		||||
    unsigned int send_nack_bitrate_;
 | 
			
		||||
    unsigned int send_bandwidth_;
 | 
			
		||||
    unsigned int receive_bandwidth_;
 | 
			
		||||
    unsigned int reserved_transmit_bitrate_bps_;
 | 
			
		||||
    bool suspend_below_min_bitrate_;
 | 
			
		||||
    webrtc::CpuOveruseObserver* overuse_observer_;
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
@@ -635,6 +639,10 @@ class FakeWebRtcVideoEngine
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_.find(channel)->second->suspend_below_min_bitrate_;
 | 
			
		||||
  }
 | 
			
		||||
  unsigned int GetReservedTransmitBitrate(int channel) {
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_.find(channel)->second->reserved_transmit_bitrate_bps_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  WEBRTC_STUB(Release, ());
 | 
			
		||||
 | 
			
		||||
@@ -883,6 +891,10 @@ class FakeWebRtcVideoEngine
 | 
			
		||||
  // Not using WEBRTC_STUB due to bool return value
 | 
			
		||||
  virtual bool IsIPv6Enabled(int channel) { return true; }
 | 
			
		||||
  WEBRTC_STUB(SetMTU, (int, unsigned int));
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  WEBRTC_STUB(ReceivedBWEPacket, (const int, int64_t, int,
 | 
			
		||||
      const webrtc::RTPHeader&));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // webrtc::ViERender
 | 
			
		||||
  WEBRTC_STUB(RegisterVideoRenderModule, (webrtc::VideoRender&));
 | 
			
		||||
@@ -1092,6 +1104,15 @@ class FakeWebRtcVideoEngine
 | 
			
		||||
    channels_[channel]->transmission_smoothing_ = enable;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  WEBRTC_FUNC(SetReservedTransmitBitrate, (int channel,
 | 
			
		||||
      unsigned int reserved_transmit_bitrate_bps)) {
 | 
			
		||||
    WEBRTC_CHECK_CHANNEL(channel);
 | 
			
		||||
    channels_[channel]->reserved_transmit_bitrate_bps_ =
 | 
			
		||||
        reserved_transmit_bitrate_bps;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  WEBRTC_STUB_CONST(GetRtcpPacketTypeCounters, (int,
 | 
			
		||||
      webrtc::RtcpPacketTypeCounter*, webrtc::RtcpPacketTypeCounter*));
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,10 @@
 | 
			
		||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
 | 
			
		||||
#include "webrtc/common.h"
 | 
			
		||||
 | 
			
		||||
namespace webrtc {
 | 
			
		||||
class ViENetwork;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace cricket {
 | 
			
		||||
 | 
			
		||||
// Function returning stats will return these values
 | 
			
		||||
@@ -106,6 +110,8 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
          dtmf_type(106),
 | 
			
		||||
          fec_type(117),
 | 
			
		||||
          nack_max_packets(0),
 | 
			
		||||
          vie_network(NULL),
 | 
			
		||||
          video_channel(-1),
 | 
			
		||||
          send_ssrc(0),
 | 
			
		||||
          send_audio_level_ext_(-1),
 | 
			
		||||
          send_absolute_sender_time_ext_(-1),
 | 
			
		||||
@@ -133,6 +139,8 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
    int dtmf_type;
 | 
			
		||||
    int fec_type;
 | 
			
		||||
    int nack_max_packets;
 | 
			
		||||
    webrtc::ViENetwork* vie_network;
 | 
			
		||||
    int video_channel;
 | 
			
		||||
    uint32 send_ssrc;
 | 
			
		||||
    int send_audio_level_ext_;
 | 
			
		||||
    int send_absolute_sender_time_ext_;
 | 
			
		||||
@@ -140,6 +148,7 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
    DtmfInfo dtmf_info;
 | 
			
		||||
    std::vector<webrtc::CodecInst> recv_codecs;
 | 
			
		||||
    webrtc::CodecInst send_codec;
 | 
			
		||||
    webrtc::PacketTime last_rtp_packet_time;
 | 
			
		||||
    std::list<std::string> packets;
 | 
			
		||||
    bool using_experimental_acm;
 | 
			
		||||
  };
 | 
			
		||||
@@ -218,6 +227,18 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
  int GetNACKMaxPackets(int channel) {
 | 
			
		||||
    return channels_[channel]->nack_max_packets;
 | 
			
		||||
  }
 | 
			
		||||
  webrtc::ViENetwork* GetViENetwork(int channel) {
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_[channel]->vie_network;
 | 
			
		||||
  }
 | 
			
		||||
  int GetVideoChannel(int channel) {
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_[channel]->video_channel;
 | 
			
		||||
  }
 | 
			
		||||
  const webrtc::PacketTime& GetLastRtpPacketTime(int channel) {
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_[channel]->last_rtp_packet_time;
 | 
			
		||||
  }
 | 
			
		||||
  bool IsUsingExperimentalAcm(int channel) {
 | 
			
		||||
    WEBRTC_ASSERT_CHANNEL(channel);
 | 
			
		||||
    return channels_[channel]->using_experimental_acm;
 | 
			
		||||
@@ -689,6 +710,19 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
        std::string(static_cast<const char*>(data), length));
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  WEBRTC_FUNC(ReceivedRTPPacket, (int channel, const void* data,
 | 
			
		||||
                                  unsigned int length,
 | 
			
		||||
                                  const webrtc::PacketTime& packet_time)) {
 | 
			
		||||
    WEBRTC_CHECK_CHANNEL(channel);
 | 
			
		||||
    if (ReceivedRTPPacket(channel, data, length) == -1) {
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
    channels_[channel]->last_rtp_packet_time = packet_time;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  WEBRTC_STUB(ReceivedRTCPPacket, (int channel, const void* data,
 | 
			
		||||
                                   unsigned int length));
 | 
			
		||||
 | 
			
		||||
@@ -824,6 +858,16 @@ class FakeWebRtcVoiceEngine
 | 
			
		||||
                                     unsigned short payloadSize));
 | 
			
		||||
  WEBRTC_STUB(GetLastRemoteTimeStamp, (int channel,
 | 
			
		||||
                                       uint32_t* lastRemoteTimeStamp));
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  WEBRTC_FUNC(SetVideoEngineBWETarget, (int channel,
 | 
			
		||||
                                        webrtc::ViENetwork* vie_network,
 | 
			
		||||
                                        int video_channel)) {
 | 
			
		||||
    WEBRTC_CHECK_CHANNEL(channel);
 | 
			
		||||
    channels_[channel]->vie_network = vie_network;
 | 
			
		||||
    channels_[channel]->video_channel = video_channel;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // webrtc::VoEVideoSync
 | 
			
		||||
  WEBRTC_STUB(GetPlayoutBufferSize, (int& bufferMs));
 | 
			
		||||
 
 | 
			
		||||
@@ -238,8 +238,8 @@ struct FlushBlackFrameData : public talk_base::MessageData {
 | 
			
		||||
 | 
			
		||||
class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 | 
			
		||||
 public:
 | 
			
		||||
  explicit WebRtcRenderAdapter(VideoRenderer* renderer)
 | 
			
		||||
      : renderer_(renderer), width_(0), height_(0) {
 | 
			
		||||
  WebRtcRenderAdapter(VideoRenderer* renderer, int channel_id)
 | 
			
		||||
      : renderer_(renderer), channel_id_(channel_id), width_(0), height_(0) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ~WebRtcRenderAdapter() {
 | 
			
		||||
@@ -256,7 +256,8 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 | 
			
		||||
    if (width_ > 0 && height_ > 0 && renderer_ != NULL) {
 | 
			
		||||
      if (!renderer_->SetSize(width_, height_, 0)) {
 | 
			
		||||
        LOG(LS_ERROR)
 | 
			
		||||
            << "WebRtcRenderAdapter SetRenderer failed to SetSize to: "
 | 
			
		||||
            << "WebRtcRenderAdapter (channel " << channel_id_
 | 
			
		||||
            << ") SetRenderer failed to SetSize to: "
 | 
			
		||||
            << width_ << "x" << height_;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -268,10 +269,12 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 | 
			
		||||
    talk_base::CritScope cs(&crit_);
 | 
			
		||||
    width_ = width;
 | 
			
		||||
    height_ = height;
 | 
			
		||||
    LOG(LS_INFO) << "WebRtcRenderAdapter frame size changed to: "
 | 
			
		||||
    LOG(LS_INFO) << "WebRtcRenderAdapter (channel " << channel_id_
 | 
			
		||||
                 << ") frame size changed to: "
 | 
			
		||||
                 << width << "x" << height;
 | 
			
		||||
    if (renderer_ == NULL) {
 | 
			
		||||
      LOG(LS_VERBOSE) << "WebRtcRenderAdapter the renderer has not been set. "
 | 
			
		||||
      LOG(LS_VERBOSE) << "WebRtcRenderAdapter (channel " << channel_id_
 | 
			
		||||
                      << ") the renderer has not been set. "
 | 
			
		||||
                      << "SetSize will be called later in SetRenderer.";
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -313,7 +316,8 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 | 
			
		||||
 | 
			
		||||
    // Sanity check on decoded frame size.
 | 
			
		||||
    if (buffer_size != static_cast<int>(VideoFrame::SizeOf(width_, height_))) {
 | 
			
		||||
      LOG(LS_WARNING) << "WebRtcRenderAdapter received a strange frame size: "
 | 
			
		||||
      LOG(LS_WARNING) << "WebRtcRenderAdapter (channel " << channel_id_
 | 
			
		||||
                      << ") received a strange frame size: "
 | 
			
		||||
                      << buffer_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -351,6 +355,7 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 | 
			
		||||
 private:
 | 
			
		||||
  talk_base::CriticalSection crit_;
 | 
			
		||||
  VideoRenderer* renderer_;
 | 
			
		||||
  int channel_id_;
 | 
			
		||||
  unsigned int width_;
 | 
			
		||||
  unsigned int height_;
 | 
			
		||||
  talk_base::RateTracker frame_rate_tracker_;
 | 
			
		||||
@@ -539,7 +544,7 @@ class WebRtcVideoChannelRecvInfo  {
 | 
			
		||||
  typedef std::map<int, webrtc::VideoDecoder*> DecoderMap;  // key: payload type
 | 
			
		||||
  explicit WebRtcVideoChannelRecvInfo(int channel_id)
 | 
			
		||||
      : channel_id_(channel_id),
 | 
			
		||||
        render_adapter_(NULL),
 | 
			
		||||
        render_adapter_(NULL, channel_id),
 | 
			
		||||
        decoder_observer_(channel_id) {
 | 
			
		||||
  }
 | 
			
		||||
  int channel_id() { return channel_id_; }
 | 
			
		||||
@@ -3008,6 +3013,8 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
       adjusted_min_bitrate || start_bitrate_changed);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  LOG(LS_INFO) << "Reset send codec needed is enabled? "
 | 
			
		||||
               << reset_send_codec_needed;
 | 
			
		||||
  if (reset_send_codec_needed) {
 | 
			
		||||
    // On success, SetSendCodec() will reset send_max_bitrate_ to
 | 
			
		||||
    // expected_bitrate.
 | 
			
		||||
@@ -3023,7 +3030,7 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
  if (leaky_bucket_changed) {
 | 
			
		||||
    bool enable_leaky_bucket =
 | 
			
		||||
        options_.video_leaky_bucket.GetWithDefaultIfUnset(false);
 | 
			
		||||
    LOG(LS_INFO) << "Leaky bucket is enabled : " << enable_leaky_bucket;
 | 
			
		||||
    LOG(LS_INFO) << "Leaky bucket is enabled? " << enable_leaky_bucket;
 | 
			
		||||
    for (SendChannelMap::iterator it = send_channels_.begin();
 | 
			
		||||
        it != send_channels_.end(); ++it) {
 | 
			
		||||
      if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(
 | 
			
		||||
@@ -3037,6 +3044,7 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
    int buffer_latency =
 | 
			
		||||
        options_.buffered_mode_latency.GetWithDefaultIfUnset(
 | 
			
		||||
            cricket::kBufferedModeDisabled);
 | 
			
		||||
    LOG(LS_INFO) << "Buffer latency is " << buffer_latency;
 | 
			
		||||
    for (SendChannelMap::iterator it = send_channels_.begin();
 | 
			
		||||
        it != send_channels_.end(); ++it) {
 | 
			
		||||
      if (engine()->vie()->rtp()->SetSenderBufferingMode(
 | 
			
		||||
@@ -3057,6 +3065,8 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
  if (cpu_overuse_detection_changed) {
 | 
			
		||||
    bool cpu_overuse_detection =
 | 
			
		||||
        options_.cpu_overuse_detection.GetWithDefaultIfUnset(false);
 | 
			
		||||
    LOG(LS_INFO) << "CPU overuse detection is enabled? "
 | 
			
		||||
                 << cpu_overuse_detection;
 | 
			
		||||
    for (SendChannelMap::iterator iter = send_channels_.begin();
 | 
			
		||||
         iter != send_channels_.end(); ++iter) {
 | 
			
		||||
      WebRtcVideoChannelSendInfo* send_channel = iter->second;
 | 
			
		||||
@@ -3067,12 +3077,14 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
    talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
 | 
			
		||||
    if (options_.dscp.GetWithDefaultIfUnset(false))
 | 
			
		||||
      dscp = kVideoDscpValue;
 | 
			
		||||
    LOG(LS_INFO) << "DSCP is " << dscp;
 | 
			
		||||
    if (MediaChannel::SetDscp(dscp) != 0) {
 | 
			
		||||
      LOG(LS_WARNING) << "Failed to set DSCP settings for video channel";
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (suspend_below_min_bitrate_changed) {
 | 
			
		||||
    if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
 | 
			
		||||
      LOG(LS_INFO) << "Suspend below min bitrate enabled.";
 | 
			
		||||
      for (SendChannelMap::iterator it = send_channels_.begin();
 | 
			
		||||
           it != send_channels_.end(); ++it) {
 | 
			
		||||
        engine()->vie()->codec()->SuspendBelowMinBitrate(
 | 
			
		||||
@@ -3084,6 +3096,7 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
 | 
			
		||||
  }
 | 
			
		||||
#ifdef USE_WEBRTC_DEV_BRANCH
 | 
			
		||||
  if (improved_wifi_bwe_changed) {
 | 
			
		||||
    LOG(LS_INFO) << "Improved WIFI BWE called.";
 | 
			
		||||
    webrtc::Config config;
 | 
			
		||||
    config.Set(new webrtc::AimdRemoteRateControl(
 | 
			
		||||
        options_.use_improved_wifi_bandwidth_estimator
 | 
			
		||||
 
 | 
			
		||||
@@ -755,6 +755,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
  if (options.experimental_acm.Get(&enable_acm2)) {
 | 
			
		||||
    EnableExperimentalAcm(enable_acm2);
 | 
			
		||||
  }
 | 
			
		||||
  LOG(LS_INFO) << "ACM2 enabled? " << enable_acm2;
 | 
			
		||||
 | 
			
		||||
  webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();
 | 
			
		||||
 | 
			
		||||
@@ -854,6 +855,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  bool highpass_filter;
 | 
			
		||||
  if (options.highpass_filter.Get(&highpass_filter)) {
 | 
			
		||||
    LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter;
 | 
			
		||||
    if (voep->EnableHighPassFilter(highpass_filter) == -1) {
 | 
			
		||||
      LOG_RTCERR1(SetHighpassFilterStatus, highpass_filter);
 | 
			
		||||
      return false;
 | 
			
		||||
@@ -862,6 +864,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  bool stereo_swapping;
 | 
			
		||||
  if (options.stereo_swapping.Get(&stereo_swapping)) {
 | 
			
		||||
    LOG(LS_INFO) << "Stereo swapping enabled? " << stereo_swapping;
 | 
			
		||||
    voep->EnableStereoChannelSwapping(stereo_swapping);
 | 
			
		||||
    if (voep->IsStereoChannelSwappingEnabled() != stereo_swapping) {
 | 
			
		||||
      LOG_RTCERR1(EnableStereoChannelSwapping, stereo_swapping);
 | 
			
		||||
@@ -871,6 +874,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  bool typing_detection;
 | 
			
		||||
  if (options.typing_detection.Get(&typing_detection)) {
 | 
			
		||||
    LOG(LS_INFO) << "Typing detection is enabled? " << typing_detection;
 | 
			
		||||
    if (voep->SetTypingDetectionStatus(typing_detection) == -1) {
 | 
			
		||||
      // In case of error, log the info and continue
 | 
			
		||||
      LOG_RTCERR1(SetTypingDetectionStatus, typing_detection);
 | 
			
		||||
@@ -879,6 +883,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  int adjust_agc_delta;
 | 
			
		||||
  if (options.adjust_agc_delta.Get(&adjust_agc_delta)) {
 | 
			
		||||
    LOG(LS_INFO) << "Adjust agc delta is " << adjust_agc_delta;
 | 
			
		||||
    if (!AdjustAgcLevel(adjust_agc_delta)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -886,6 +891,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  bool aec_dump;
 | 
			
		||||
  if (options.aec_dump.Get(&aec_dump)) {
 | 
			
		||||
    LOG(LS_INFO) << "Aec dump is enabled? " << aec_dump;
 | 
			
		||||
    if (aec_dump)
 | 
			
		||||
      StartAecDump(kAecDumpByAudioOptionFilename);
 | 
			
		||||
    else
 | 
			
		||||
@@ -894,6 +900,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  bool experimental_aec;
 | 
			
		||||
  if (options.experimental_aec.Get(&experimental_aec)) {
 | 
			
		||||
    LOG(LS_INFO) << "Experimental aec is " << experimental_aec;
 | 
			
		||||
    webrtc::AudioProcessing* audioproc =
 | 
			
		||||
        voe_wrapper_->base()->audio_processing();
 | 
			
		||||
    // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
 | 
			
		||||
@@ -908,6 +915,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  uint32 recording_sample_rate;
 | 
			
		||||
  if (options.recording_sample_rate.Get(&recording_sample_rate)) {
 | 
			
		||||
    LOG(LS_INFO) << "Recording sample rate is " << recording_sample_rate;
 | 
			
		||||
    if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
 | 
			
		||||
      LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
 | 
			
		||||
    }
 | 
			
		||||
@@ -915,6 +923,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
 | 
			
		||||
 | 
			
		||||
  uint32 playout_sample_rate;
 | 
			
		||||
  if (options.playout_sample_rate.Get(&playout_sample_rate)) {
 | 
			
		||||
    LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate;
 | 
			
		||||
    if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
 | 
			
		||||
      LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -248,6 +248,7 @@ Connection* Port::GetConnection(const talk_base::SocketAddress& remote_addr) {
 | 
			
		||||
 | 
			
		||||
void Port::AddAddress(const talk_base::SocketAddress& address,
 | 
			
		||||
                      const talk_base::SocketAddress& base_address,
 | 
			
		||||
                      const talk_base::SocketAddress& related_address,
 | 
			
		||||
                      const std::string& protocol,
 | 
			
		||||
                      const std::string& type,
 | 
			
		||||
                      uint32 type_preference,
 | 
			
		||||
@@ -263,7 +264,7 @@ void Port::AddAddress(const talk_base::SocketAddress& address,
 | 
			
		||||
  c.set_password(password_);
 | 
			
		||||
  c.set_network_name(network_->name());
 | 
			
		||||
  c.set_generation(generation_);
 | 
			
		||||
  c.set_related_address(related_address_);
 | 
			
		||||
  c.set_related_address(related_address);
 | 
			
		||||
  c.set_foundation(ComputeFoundation(type, protocol, base_address));
 | 
			
		||||
  candidates_.push_back(c);
 | 
			
		||||
  SignalCandidateReady(this, c);
 | 
			
		||||
 
 | 
			
		||||
@@ -172,13 +172,6 @@ class Port : public PortInterface, public talk_base::MessageHandler,
 | 
			
		||||
    send_retransmit_count_attribute_ = enable;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const talk_base::SocketAddress& related_address() const {
 | 
			
		||||
    return related_address_;
 | 
			
		||||
  }
 | 
			
		||||
  void set_related_address(const talk_base::SocketAddress& address) {
 | 
			
		||||
    related_address_ = address;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Identifies the generation that this port was created in.
 | 
			
		||||
  uint32 generation() { return generation_; }
 | 
			
		||||
  void set_generation(uint32 generation) { generation_ = generation; }
 | 
			
		||||
@@ -315,6 +308,7 @@ class Port : public PortInterface, public talk_base::MessageHandler,
 | 
			
		||||
  // Fills in the local address of the port.
 | 
			
		||||
  void AddAddress(const talk_base::SocketAddress& address,
 | 
			
		||||
                  const talk_base::SocketAddress& base_address,
 | 
			
		||||
                  const talk_base::SocketAddress& related_address,
 | 
			
		||||
                  const std::string& protocol, const std::string& type,
 | 
			
		||||
                  uint32 type_preference, bool final);
 | 
			
		||||
 | 
			
		||||
@@ -365,7 +359,6 @@ class Port : public PortInterface, public talk_base::MessageHandler,
 | 
			
		||||
  std::string content_name_;
 | 
			
		||||
  int component_;
 | 
			
		||||
  uint32 generation_;
 | 
			
		||||
  talk_base::SocketAddress related_address_;
 | 
			
		||||
  // In order to establish a connection to this Port (so that real data can be
 | 
			
		||||
  // sent through), the other side must send us a STUN binding request that is
 | 
			
		||||
  // authenticated with this username_fragment and password.
 | 
			
		||||
 
 | 
			
		||||
@@ -146,19 +146,21 @@ class TestPort : public Port {
 | 
			
		||||
 | 
			
		||||
  virtual void PrepareAddress() {
 | 
			
		||||
    talk_base::SocketAddress addr(ip(), min_port());
 | 
			
		||||
    AddAddress(addr, addr, "udp", Type(), ICE_TYPE_PREFERENCE_HOST, true);
 | 
			
		||||
    AddAddress(addr, addr, talk_base::SocketAddress(), "udp", Type(),
 | 
			
		||||
               ICE_TYPE_PREFERENCE_HOST, true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Exposed for testing candidate building.
 | 
			
		||||
  void AddCandidateAddress(const talk_base::SocketAddress& addr) {
 | 
			
		||||
    AddAddress(addr, addr, "udp", Type(), type_preference_, false);
 | 
			
		||||
    AddAddress(addr, addr, talk_base::SocketAddress(), "udp", Type(),
 | 
			
		||||
               type_preference_, false);
 | 
			
		||||
  }
 | 
			
		||||
  void AddCandidateAddress(const talk_base::SocketAddress& addr,
 | 
			
		||||
                           const talk_base::SocketAddress& base_address,
 | 
			
		||||
                           const std::string& type,
 | 
			
		||||
                           int type_preference,
 | 
			
		||||
                           bool final) {
 | 
			
		||||
    AddAddress(addr, base_address, "udp", type,
 | 
			
		||||
    AddAddress(addr, base_address, talk_base::SocketAddress(), "udp", type,
 | 
			
		||||
               type_preference, final);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2169,12 +2171,16 @@ TEST_F(PortTest, TestCandidateFoundation) {
 | 
			
		||||
  talk_base::scoped_ptr<Port> turnport(CreateTurnPort(
 | 
			
		||||
      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
 | 
			
		||||
  turnport->PrepareAddress();
 | 
			
		||||
  ASSERT_EQ_WAIT(1U, turnport->Candidates().size(), kTimeout);
 | 
			
		||||
  ASSERT_EQ_WAIT(2U, turnport->Candidates().size(), kTimeout);
 | 
			
		||||
  EXPECT_NE(turnport->Candidates()[0].foundation(),
 | 
			
		||||
            turnport->Candidates()[1].foundation());
 | 
			
		||||
  EXPECT_NE(udpport1->Candidates()[0].foundation(),
 | 
			
		||||
            turnport->Candidates()[0].foundation());
 | 
			
		||||
            turnport->Candidates()[1].foundation());
 | 
			
		||||
  EXPECT_NE(udpport2->Candidates()[0].foundation(),
 | 
			
		||||
            turnport->Candidates()[0].foundation());
 | 
			
		||||
            turnport->Candidates()[1].foundation());
 | 
			
		||||
  EXPECT_NE(stunport->Candidates()[0].foundation(),
 | 
			
		||||
            turnport->Candidates()[1].foundation());
 | 
			
		||||
  EXPECT_EQ(stunport->Candidates()[0].foundation(),
 | 
			
		||||
            turnport->Candidates()[0].foundation());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2217,11 +2223,13 @@ TEST_F(PortTest, TestCandidateRelatedAddress) {
 | 
			
		||||
  talk_base::scoped_ptr<Port> turnport(CreateTurnPort(
 | 
			
		||||
      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
 | 
			
		||||
  turnport->PrepareAddress();
 | 
			
		||||
  ASSERT_EQ_WAIT(1U, turnport->Candidates().size(), kTimeout);
 | 
			
		||||
  ASSERT_EQ_WAIT(2U, turnport->Candidates().size(), kTimeout);
 | 
			
		||||
  EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
 | 
			
		||||
            turnport->Candidates()[0].address().ipaddr());
 | 
			
		||||
  EXPECT_EQ(kNatAddr1.ipaddr(),
 | 
			
		||||
            turnport->Candidates()[1].address().ipaddr());
 | 
			
		||||
  EXPECT_EQ(kLocalAddr1.ipaddr(),
 | 
			
		||||
            turnport->Candidates()[0].related_address().ipaddr());
 | 
			
		||||
  EXPECT_EQ(kNatAddr1.ipaddr(),
 | 
			
		||||
            turnport->Candidates()[1].related_address().ipaddr());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test priority value overflow handling when preference is set to 3.
 | 
			
		||||
 
 | 
			
		||||
@@ -240,8 +240,11 @@ void RelayPort::SetReady() {
 | 
			
		||||
    for (iter = external_addr_.begin();
 | 
			
		||||
         iter != external_addr_.end(); ++iter) {
 | 
			
		||||
      std::string proto_name = ProtoToString(iter->proto);
 | 
			
		||||
      AddAddress(iter->address, iter->address, proto_name,
 | 
			
		||||
                 RELAY_PORT_TYPE, ICE_TYPE_PREFERENCE_RELAY, false);
 | 
			
		||||
      // In case of Gturn, related address is set to null socket address.
 | 
			
		||||
      // This is due to as mapped address stun attribute is used for allocated
 | 
			
		||||
      // address.
 | 
			
		||||
      AddAddress(iter->address, iter->address, talk_base::SocketAddress(),
 | 
			
		||||
                 proto_name, RELAY_PORT_TYPE, ICE_TYPE_PREFERENCE_RELAY, false);
 | 
			
		||||
    }
 | 
			
		||||
    ready_ = true;
 | 
			
		||||
    SignalPortComplete(this);
 | 
			
		||||
@@ -548,10 +551,6 @@ void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr,
 | 
			
		||||
            << " @ " << mapped_addr.ToSensitiveString();
 | 
			
		||||
  connected_ = true;
 | 
			
		||||
 | 
			
		||||
  // In case of Gturn related address is set to null socket address.
 | 
			
		||||
  // This is due to mapped address stun attribute is used for allocated
 | 
			
		||||
  // address.
 | 
			
		||||
  port_->set_related_address(talk_base::SocketAddress());
 | 
			
		||||
  port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
 | 
			
		||||
  port_->SetReady();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@ bool UDPPort::Init() {
 | 
			
		||||
 | 
			
		||||
UDPPort::~UDPPort() {
 | 
			
		||||
  if (resolver_) {
 | 
			
		||||
    resolver_->Destroy(false);
 | 
			
		||||
    resolver_->Destroy(true);
 | 
			
		||||
  }
 | 
			
		||||
  if (!SharedSocket())
 | 
			
		||||
    delete socket_;
 | 
			
		||||
@@ -243,7 +243,8 @@ int UDPPort::GetError() {
 | 
			
		||||
 | 
			
		||||
void UDPPort::OnLocalAddressReady(talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                                  const talk_base::SocketAddress& address) {
 | 
			
		||||
  AddAddress(address, address, UDP_PROTOCOL_NAME, LOCAL_PORT_TYPE,
 | 
			
		||||
  AddAddress(address, address, talk_base::SocketAddress(),
 | 
			
		||||
             UDP_PROTOCOL_NAME, LOCAL_PORT_TYPE,
 | 
			
		||||
             ICE_TYPE_PREFERENCE_HOST, false);
 | 
			
		||||
  MaybePrepareStunCandidate();
 | 
			
		||||
}
 | 
			
		||||
@@ -324,10 +325,9 @@ void UDPPort::OnStunBindingRequestSucceeded(
 | 
			
		||||
  if (!SharedSocket() || stun_addr != socket_->GetLocalAddress()) {
 | 
			
		||||
    // If socket is shared and |stun_addr| is equal to local socket
 | 
			
		||||
    // address then discarding the stun address.
 | 
			
		||||
    // Setting related address before STUN candidate is added. For STUN
 | 
			
		||||
    // related address is local socket address.
 | 
			
		||||
    set_related_address(socket_->GetLocalAddress());
 | 
			
		||||
    AddAddress(stun_addr, socket_->GetLocalAddress(), UDP_PROTOCOL_NAME,
 | 
			
		||||
    // For STUN related address is local socket address.
 | 
			
		||||
    AddAddress(stun_addr, socket_->GetLocalAddress(),
 | 
			
		||||
               socket_->GetLocalAddress(), UDP_PROTOCOL_NAME,
 | 
			
		||||
               STUN_PORT_TYPE, ICE_TYPE_PREFERENCE_SRFLX, false);
 | 
			
		||||
  }
 | 
			
		||||
  SetResult(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,8 @@ static const SocketAddress kBadAddr("0.0.0.1", 5000);
 | 
			
		||||
static const SocketAddress kStunHostnameAddr("localhost", 5000);
 | 
			
		||||
static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000);
 | 
			
		||||
static const int kTimeoutMs = 10000;
 | 
			
		||||
// stun prio = 100 << 24 | 30 (IPV4) << 8 | 256 - 0
 | 
			
		||||
static const uint32 kStunCandidatePriority = 1677729535;
 | 
			
		||||
 | 
			
		||||
// Tests connecting a StunPort to a fake STUN server (cricket::StunServer)
 | 
			
		||||
// TODO: Use a VirtualSocketServer here. We have to use a
 | 
			
		||||
@@ -178,6 +180,7 @@ TEST_F(StunPortTest, TestPrepareAddressHostname) {
 | 
			
		||||
  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
 | 
			
		||||
  ASSERT_EQ(1U, port()->Candidates().size());
 | 
			
		||||
  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
 | 
			
		||||
  EXPECT_EQ(kStunCandidatePriority, port()->Candidates()[0].priority());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we handle hostname lookup failures properly.
 | 
			
		||||
 
 | 
			
		||||
@@ -121,6 +121,7 @@ void TCPPort::PrepareAddress() {
 | 
			
		||||
    if (socket_->GetState() == talk_base::AsyncPacketSocket::STATE_BOUND ||
 | 
			
		||||
        socket_->GetState() == talk_base::AsyncPacketSocket::STATE_CLOSED)
 | 
			
		||||
      AddAddress(socket_->GetLocalAddress(), socket_->GetLocalAddress(),
 | 
			
		||||
                 talk_base::SocketAddress(),
 | 
			
		||||
                 TCP_PROTOCOL_NAME, LOCAL_PORT_TYPE,
 | 
			
		||||
                 ICE_TYPE_PREFERENCE_HOST_TCP, true);
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -128,8 +129,9 @@ void TCPPort::PrepareAddress() {
 | 
			
		||||
    // Note: We still add the address, since otherwise the remote side won't
 | 
			
		||||
    // recognize our incoming TCP connections.
 | 
			
		||||
    AddAddress(talk_base::SocketAddress(ip(), 0),
 | 
			
		||||
               talk_base::SocketAddress(ip(), 0), TCP_PROTOCOL_NAME,
 | 
			
		||||
               LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP, true);
 | 
			
		||||
               talk_base::SocketAddress(ip(), 0), talk_base::SocketAddress(),
 | 
			
		||||
               TCP_PROTOCOL_NAME, LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP,
 | 
			
		||||
               true);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -221,7 +223,7 @@ void TCPPort::OnReadyToSend(talk_base::AsyncPacketSocket* socket) {
 | 
			
		||||
 | 
			
		||||
void TCPPort::OnAddressReady(talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                             const talk_base::SocketAddress& address) {
 | 
			
		||||
  AddAddress(address, address, "tcp",
 | 
			
		||||
  AddAddress(address, address, talk_base::SocketAddress(), "tcp",
 | 
			
		||||
             LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP,
 | 
			
		||||
             true);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ static const int TURN_CHANNEL_NUMBER_START = 0x4000;
 | 
			
		||||
static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000;  // 5 minutes
 | 
			
		||||
 | 
			
		||||
static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
 | 
			
		||||
static const size_t MAX_CANDIDATES_PER_TURNPORT = 2;  // A STUN + TURN
 | 
			
		||||
 | 
			
		||||
inline bool IsTurnChannelData(uint16 msg_type) {
 | 
			
		||||
  return ((msg_type & 0xC000) == 0x4000);  // MSB are 0b01
 | 
			
		||||
@@ -168,6 +169,27 @@ class TurnEntry : public sigslot::has_slots<> {
 | 
			
		||||
  BindState state_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TurnPort::TurnPort(talk_base::Thread* thread,
 | 
			
		||||
                   talk_base::PacketSocketFactory* factory,
 | 
			
		||||
                   talk_base::Network* network,
 | 
			
		||||
                   talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                   const std::string& username,
 | 
			
		||||
                   const std::string& password,
 | 
			
		||||
                   const ProtocolAddress& server_address,
 | 
			
		||||
                   const RelayCredentials& credentials)
 | 
			
		||||
    : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
 | 
			
		||||
           username, password),
 | 
			
		||||
      server_address_(server_address),
 | 
			
		||||
      credentials_(credentials),
 | 
			
		||||
      socket_(socket),
 | 
			
		||||
      resolver_(NULL),
 | 
			
		||||
      error_(0),
 | 
			
		||||
      request_manager_(thread),
 | 
			
		||||
      next_channel_number_(TURN_CHANNEL_NUMBER_START),
 | 
			
		||||
      connected_(false) {
 | 
			
		||||
  request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TurnPort::TurnPort(talk_base::Thread* thread,
 | 
			
		||||
                   talk_base::PacketSocketFactory* factory,
 | 
			
		||||
                   talk_base::Network* network,
 | 
			
		||||
@@ -181,6 +203,7 @@ TurnPort::TurnPort(talk_base::Thread* thread,
 | 
			
		||||
           username, password),
 | 
			
		||||
      server_address_(server_address),
 | 
			
		||||
      credentials_(credentials),
 | 
			
		||||
      socket_(NULL),
 | 
			
		||||
      resolver_(NULL),
 | 
			
		||||
      error_(0),
 | 
			
		||||
      request_manager_(thread),
 | 
			
		||||
@@ -197,6 +220,9 @@ TurnPort::~TurnPort() {
 | 
			
		||||
  if (resolver_) {
 | 
			
		||||
    resolver_->Destroy(false);
 | 
			
		||||
  }
 | 
			
		||||
  if (!SharedSocket()) {
 | 
			
		||||
    delete socket_;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TurnPort::PrepareAddress() {
 | 
			
		||||
@@ -227,19 +253,18 @@ void TurnPort::PrepareAddress() {
 | 
			
		||||
    LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
 | 
			
		||||
                         << ProtoToString(server_address_.proto) << " @ "
 | 
			
		||||
                         << server_address_.address.ToSensitiveString();
 | 
			
		||||
    if (server_address_.proto == PROTO_UDP) {
 | 
			
		||||
      socket_.reset(socket_factory()->CreateUdpSocket(
 | 
			
		||||
          talk_base::SocketAddress(ip(), 0), min_port(), max_port()));
 | 
			
		||||
    if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
 | 
			
		||||
      socket_ = socket_factory()->CreateUdpSocket(
 | 
			
		||||
          talk_base::SocketAddress(ip(), 0), min_port(), max_port());
 | 
			
		||||
    } else if (server_address_.proto == PROTO_TCP) {
 | 
			
		||||
      int opts = talk_base::PacketSocketFactory::OPT_STUN;
 | 
			
		||||
      // If secure bit is enabled in server address, use TLS over TCP.
 | 
			
		||||
      if (server_address_.secure) {
 | 
			
		||||
        opts |= talk_base::PacketSocketFactory::OPT_TLS;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      socket_.reset(socket_factory()->CreateClientTcpSocket(
 | 
			
		||||
      socket_ = socket_factory()->CreateClientTcpSocket(
 | 
			
		||||
          talk_base::SocketAddress(ip(), 0), server_address_.address,
 | 
			
		||||
          proxy(), user_agent(), opts));
 | 
			
		||||
          proxy(), user_agent(), opts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!socket_) {
 | 
			
		||||
@@ -253,7 +278,11 @@ void TurnPort::PrepareAddress() {
 | 
			
		||||
      socket_->SetOption(iter->first, iter->second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
 | 
			
		||||
    if (!SharedSocket()) {
 | 
			
		||||
      // If socket is shared, AllocationSequence will receive the packet.
 | 
			
		||||
      socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
 | 
			
		||||
 | 
			
		||||
    if (server_address_.proto == PROTO_TCP) {
 | 
			
		||||
@@ -294,12 +323,18 @@ Connection* TurnPort::CreateConnection(const Candidate& address,
 | 
			
		||||
  // Create an entry, if needed, so we can get our permissions set up correctly.
 | 
			
		||||
  CreateEntry(address.address());
 | 
			
		||||
 | 
			
		||||
  // TODO(juberti): The '0' index will need to change if we start gathering STUN
 | 
			
		||||
  // candidates on this port.
 | 
			
		||||
  ProxyConnection* conn = new ProxyConnection(this, 0, address);
 | 
			
		||||
  conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
 | 
			
		||||
  AddConnection(conn);
 | 
			
		||||
  return conn;
 | 
			
		||||
  // A TURN port will have two candiates, STUN and TURN. STUN may not
 | 
			
		||||
  // present in all cases. If present stun candidate will be added first
 | 
			
		||||
  // and TURN candidate later.
 | 
			
		||||
  for (size_t index = 0; index < Candidates().size(); ++index) {
 | 
			
		||||
    if (Candidates()[index].type() == RELAY_PORT_TYPE) {
 | 
			
		||||
      ProxyConnection* conn = new ProxyConnection(this, index, address);
 | 
			
		||||
      conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
 | 
			
		||||
      AddConnection(conn);
 | 
			
		||||
      return conn;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TurnPort::SetOption(talk_base::Socket::Option opt, int value) {
 | 
			
		||||
@@ -360,7 +395,7 @@ void TurnPort::OnReadPacket(
 | 
			
		||||
    talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
 | 
			
		||||
    const talk_base::SocketAddress& remote_addr,
 | 
			
		||||
    const talk_base::PacketTime& packet_time) {
 | 
			
		||||
  ASSERT(socket == socket_.get());
 | 
			
		||||
  ASSERT(socket == socket_);
 | 
			
		||||
  ASSERT(remote_addr == server_address_.address);
 | 
			
		||||
 | 
			
		||||
  // The message must be at least the size of a channel header.
 | 
			
		||||
@@ -415,6 +450,8 @@ void TurnPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  SignalResolvedServerAddress(this, server_address_.address,
 | 
			
		||||
                              resolver_->address());
 | 
			
		||||
  PrepareAddress();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -428,15 +465,25 @@ void TurnPort::OnSendStunPacket(const void* data, size_t size,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TurnPort::OnStunAddress(const talk_base::SocketAddress& address) {
 | 
			
		||||
  // For relay, mapped address is rel-addr.
 | 
			
		||||
  set_related_address(address);
 | 
			
		||||
  if (server_address_.proto == PROTO_UDP  &&
 | 
			
		||||
      address != socket_->GetLocalAddress()) {
 | 
			
		||||
    AddAddress(address,
 | 
			
		||||
               socket_->GetLocalAddress(),
 | 
			
		||||
               socket_->GetLocalAddress(),
 | 
			
		||||
               UDP_PROTOCOL_NAME,
 | 
			
		||||
               STUN_PORT_TYPE,
 | 
			
		||||
               ICE_TYPE_PREFERENCE_SRFLX,
 | 
			
		||||
               false);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TurnPort::OnAllocateSuccess(const talk_base::SocketAddress& address) {
 | 
			
		||||
void TurnPort::OnAllocateSuccess(const talk_base::SocketAddress& address,
 | 
			
		||||
                                 const talk_base::SocketAddress& stun_address) {
 | 
			
		||||
  connected_ = true;
 | 
			
		||||
  AddAddress(address,
 | 
			
		||||
             socket_->GetLocalAddress(),
 | 
			
		||||
             "udp",
 | 
			
		||||
             stun_address,
 | 
			
		||||
             UDP_PROTOCOL_NAME,
 | 
			
		||||
             RELAY_PORT_TYPE,
 | 
			
		||||
             GetRelayPreference(server_address_.proto, server_address_.secure),
 | 
			
		||||
             true);
 | 
			
		||||
@@ -684,7 +731,7 @@ void TurnAllocateRequest::OnResponse(StunMessage* response) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // TODO(mallinath) - Use mapped address for STUN candidate.
 | 
			
		||||
  // Using XOR-Mapped-Address for stun.
 | 
			
		||||
  port_->OnStunAddress(mapped_attr->GetAddress());
 | 
			
		||||
 | 
			
		||||
  const StunAddressAttribute* relayed_attr =
 | 
			
		||||
@@ -703,7 +750,8 @@ void TurnAllocateRequest::OnResponse(StunMessage* response) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  // Notify the port the allocate succeeded, and schedule a refresh request.
 | 
			
		||||
  port_->OnAllocateSuccess(relayed_attr->GetAddress());
 | 
			
		||||
  port_->OnAllocateSuccess(relayed_attr->GetAddress(),
 | 
			
		||||
                           mapped_attr->GetAddress());
 | 
			
		||||
  port_->ScheduleRefresh(lifetime_attr->value());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,18 @@ class TurnEntry;
 | 
			
		||||
 | 
			
		||||
class TurnPort : public Port {
 | 
			
		||||
 public:
 | 
			
		||||
  static TurnPort* Create(talk_base::Thread* thread,
 | 
			
		||||
                          talk_base::PacketSocketFactory* factory,
 | 
			
		||||
                          talk_base::Network* network,
 | 
			
		||||
                          talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                          const std::string& username,  // ice username.
 | 
			
		||||
                          const std::string& password,  // ice password.
 | 
			
		||||
                          const ProtocolAddress& server_address,
 | 
			
		||||
                          const RelayCredentials& credentials) {
 | 
			
		||||
    return new TurnPort(thread, factory, network, socket, username, password,
 | 
			
		||||
                    server_address, credentials);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static TurnPort* Create(talk_base::Thread* thread,
 | 
			
		||||
                          talk_base::PacketSocketFactory* factory,
 | 
			
		||||
                          talk_base::Network* network,
 | 
			
		||||
@@ -79,10 +91,19 @@ class TurnPort : public Port {
 | 
			
		||||
  virtual int SetOption(talk_base::Socket::Option opt, int value);
 | 
			
		||||
  virtual int GetOption(talk_base::Socket::Option opt, int* value);
 | 
			
		||||
  virtual int GetError();
 | 
			
		||||
  virtual void OnReadPacket(
 | 
			
		||||
 | 
			
		||||
  virtual bool HandleIncomingPacket(
 | 
			
		||||
      talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
 | 
			
		||||
      const talk_base::SocketAddress& remote_addr,
 | 
			
		||||
      const talk_base::PacketTime& packet_time);
 | 
			
		||||
      const talk_base::PacketTime& packet_time) {
 | 
			
		||||
    OnReadPacket(socket, data, size, remote_addr, packet_time);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  virtual void OnReadPacket(talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                            const char* data, size_t size,
 | 
			
		||||
                            const talk_base::SocketAddress& remote_addr,
 | 
			
		||||
                            const talk_base::PacketTime& packet_time);
 | 
			
		||||
 | 
			
		||||
  virtual void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
 | 
			
		||||
 | 
			
		||||
  void OnSocketConnect(talk_base::AsyncPacketSocket* socket);
 | 
			
		||||
@@ -92,11 +113,27 @@ class TurnPort : public Port {
 | 
			
		||||
  const std::string& hash() const { return hash_; }
 | 
			
		||||
  const std::string& nonce() const { return nonce_; }
 | 
			
		||||
 | 
			
		||||
  // Signal with resolved server address.
 | 
			
		||||
  // Parameters are port, server address and resolved server address.
 | 
			
		||||
  // This signal will be sent only if server address is resolved successfully.
 | 
			
		||||
  sigslot::signal3<TurnPort*,
 | 
			
		||||
                   const talk_base::SocketAddress&,
 | 
			
		||||
                   const talk_base::SocketAddress&> SignalResolvedServerAddress;
 | 
			
		||||
 | 
			
		||||
  // This signal is only for testing purpose.
 | 
			
		||||
  sigslot::signal3<TurnPort*, const talk_base::SocketAddress&, int>
 | 
			
		||||
      SignalCreatePermissionResult;
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  TurnPort(talk_base::Thread* thread,
 | 
			
		||||
           talk_base::PacketSocketFactory* factory,
 | 
			
		||||
           talk_base::Network* network,
 | 
			
		||||
           talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
           const std::string& username,
 | 
			
		||||
           const std::string& password,
 | 
			
		||||
           const ProtocolAddress& server_address,
 | 
			
		||||
           const RelayCredentials& credentials);
 | 
			
		||||
 | 
			
		||||
  TurnPort(talk_base::Thread* thread,
 | 
			
		||||
           talk_base::PacketSocketFactory* factory,
 | 
			
		||||
           talk_base::Network* network,
 | 
			
		||||
@@ -131,7 +168,8 @@ class TurnPort : public Port {
 | 
			
		||||
  // Stun address from allocate success response.
 | 
			
		||||
  // Currently used only for testing.
 | 
			
		||||
  void OnStunAddress(const talk_base::SocketAddress& address);
 | 
			
		||||
  void OnAllocateSuccess(const talk_base::SocketAddress& address);
 | 
			
		||||
  void OnAllocateSuccess(const talk_base::SocketAddress& address,
 | 
			
		||||
                         const talk_base::SocketAddress& stun_address);
 | 
			
		||||
  void OnAllocateError();
 | 
			
		||||
  void OnAllocateRequestTimeout();
 | 
			
		||||
 | 
			
		||||
@@ -160,7 +198,7 @@ class TurnPort : public Port {
 | 
			
		||||
  ProtocolAddress server_address_;
 | 
			
		||||
  RelayCredentials credentials_;
 | 
			
		||||
 | 
			
		||||
  talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
 | 
			
		||||
  talk_base::AsyncPacketSocket* socket_;
 | 
			
		||||
  SocketOptionsMap socket_options_;
 | 
			
		||||
  talk_base::AsyncResolverInterface* resolver_;
 | 
			
		||||
  int error_;
 | 
			
		||||
 
 | 
			
		||||
@@ -157,7 +157,13 @@ class TurnPortTest : public testing::Test,
 | 
			
		||||
                       const talk_base::PacketTime& packet_time) {
 | 
			
		||||
    udp_packets_.push_back(talk_base::Buffer(data, size));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void OnSocketReadPacket(talk_base::AsyncPacketSocket* socket,
 | 
			
		||||
                          const char* data, size_t size,
 | 
			
		||||
                          const talk_base::SocketAddress& remote_addr,
 | 
			
		||||
                          const talk_base::PacketTime& packet_time) {
 | 
			
		||||
    turn_port_->HandleIncomingPacket(socket, data, size, remote_addr,
 | 
			
		||||
                                     packet_time);
 | 
			
		||||
  }
 | 
			
		||||
  talk_base::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
 | 
			
		||||
    talk_base::AsyncSocket* socket = ss_->CreateAsyncSocket(SOCK_STREAM);
 | 
			
		||||
    EXPECT_GE(socket->Bind(addr), 0);
 | 
			
		||||
@@ -185,6 +191,31 @@ class TurnPortTest : public testing::Test,
 | 
			
		||||
    // This TURN port will be the controlling.
 | 
			
		||||
    turn_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
 | 
			
		||||
    turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING);
 | 
			
		||||
    ConnectSignals();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void CreateSharedTurnPort(const std::string& username,
 | 
			
		||||
                            const std::string& password,
 | 
			
		||||
                            const cricket::ProtocolAddress& server_address) {
 | 
			
		||||
    socket_.reset(socket_factory_.CreateUdpSocket(
 | 
			
		||||
        talk_base::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0));
 | 
			
		||||
    ASSERT_TRUE(socket_ != NULL);
 | 
			
		||||
    socket_->SignalReadPacket.connect(this, &TurnPortTest::OnSocketReadPacket);
 | 
			
		||||
 | 
			
		||||
    cricket::RelayCredentials credentials(username, password);
 | 
			
		||||
    turn_port_.reset(cricket::TurnPort::Create(
 | 
			
		||||
        main_, &socket_factory_, &network_, socket_.get(), kIceUfrag1, kIcePwd1,
 | 
			
		||||
        server_address, credentials));
 | 
			
		||||
    // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
 | 
			
		||||
    // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
 | 
			
		||||
    // messages.
 | 
			
		||||
    // This TURN port will be the controlling.
 | 
			
		||||
    turn_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
 | 
			
		||||
    turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING);
 | 
			
		||||
    ConnectSignals();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void ConnectSignals() {
 | 
			
		||||
    turn_port_->SignalPortComplete.connect(this,
 | 
			
		||||
        &TurnPortTest::OnTurnPortComplete);
 | 
			
		||||
    turn_port_->SignalPortError.connect(this,
 | 
			
		||||
@@ -294,6 +325,7 @@ class TurnPortTest : public testing::Test,
 | 
			
		||||
  talk_base::SocketServerScope ss_scope_;
 | 
			
		||||
  talk_base::Network network_;
 | 
			
		||||
  talk_base::BasicPacketSocketFactory socket_factory_;
 | 
			
		||||
  talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
 | 
			
		||||
  cricket::TestTurnServer turn_server_;
 | 
			
		||||
  talk_base::scoped_ptr<TurnPort> turn_port_;
 | 
			
		||||
  talk_base::scoped_ptr<UDPPort> udp_port_;
 | 
			
		||||
@@ -349,6 +381,12 @@ TEST_F(TurnPortTest, TestTurnConnection) {
 | 
			
		||||
  TestTurnConnection();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Similar to above, except that this test will use the shared socket.
 | 
			
		||||
TEST_F(TurnPortTest, TestTurnConnectionUsingSharedSocket) {
 | 
			
		||||
  CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | 
			
		||||
  TestTurnConnection();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we can establish a TCP connection with TURN server.
 | 
			
		||||
TEST_F(TurnPortTest, TestTurnTcpConnection) {
 | 
			
		||||
  turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
 | 
			
		||||
 
 | 
			
		||||
@@ -148,6 +148,9 @@ class AllocationSequence : public talk_base::MessageHandler,
 | 
			
		||||
                    const talk_base::PacketTime& packet_time);
 | 
			
		||||
 | 
			
		||||
  void OnPortDestroyed(PortInterface* port);
 | 
			
		||||
  void OnResolvedTurnServerAddress(
 | 
			
		||||
    TurnPort* port, const talk_base::SocketAddress& server_address,
 | 
			
		||||
    const talk_base::SocketAddress& resolved_server_address);
 | 
			
		||||
 | 
			
		||||
  BasicPortAllocatorSession* session_;
 | 
			
		||||
  talk_base::Network* network_;
 | 
			
		||||
@@ -157,8 +160,10 @@ class AllocationSequence : public talk_base::MessageHandler,
 | 
			
		||||
  uint32 flags_;
 | 
			
		||||
  ProtocolList protocols_;
 | 
			
		||||
  talk_base::scoped_ptr<talk_base::AsyncPacketSocket> udp_socket_;
 | 
			
		||||
  // Keeping a list of all UDP based ports.
 | 
			
		||||
  std::deque<Port*> ports;
 | 
			
		||||
  // There will be only one udp port per AllocationSequence.
 | 
			
		||||
  Port* udp_port_;
 | 
			
		||||
  // Keeping a map for turn ports keyed with server addresses.
 | 
			
		||||
  std::map<talk_base::SocketAddress, Port*> turn_ports_;
 | 
			
		||||
  int phase_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -693,6 +698,7 @@ AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
 | 
			
		||||
      state_(kInit),
 | 
			
		||||
      flags_(flags),
 | 
			
		||||
      udp_socket_(),
 | 
			
		||||
      udp_port_(NULL),
 | 
			
		||||
      phase_(0) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -855,7 +861,6 @@ void AllocationSequence::CreateUDPPorts() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (port) {
 | 
			
		||||
    ports.push_back(port);
 | 
			
		||||
    // If shared socket is enabled, STUN candidate will be allocated by the
 | 
			
		||||
    // UDPPort.
 | 
			
		||||
    if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
 | 
			
		||||
@@ -866,7 +871,13 @@ void AllocationSequence::CreateUDPPorts() {
 | 
			
		||||
            << "AllocationSequence: No STUN server configured, skipping.";
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      port->set_server_addr(config_->stun_address);
 | 
			
		||||
      udp_port_ = port;
 | 
			
		||||
      // If there is a TURN UDP server available, then we will use TURN port
 | 
			
		||||
      // to get stun address, otherwise by UDP port.
 | 
			
		||||
      // Shared socket mode is not used in GTURN mode.
 | 
			
		||||
      if (config_ && !config_->SupportsProtocol(RELAY_TURN, PROTO_UDP)) {
 | 
			
		||||
        port->set_server_addr(config_->stun_address);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    session_->AddAllocatedPort(port, this, true);
 | 
			
		||||
@@ -992,15 +1003,40 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
 | 
			
		||||
  PortList::const_iterator relay_port;
 | 
			
		||||
  for (relay_port = config.ports.begin();
 | 
			
		||||
       relay_port != config.ports.end(); ++relay_port) {
 | 
			
		||||
    TurnPort* port = TurnPort::Create(session_->network_thread(),
 | 
			
		||||
                                      session_->socket_factory(),
 | 
			
		||||
                                      network_, ip_,
 | 
			
		||||
                                      session_->allocator()->min_port(),
 | 
			
		||||
                                      session_->allocator()->max_port(),
 | 
			
		||||
                                      session_->username(),
 | 
			
		||||
                                      session_->password(),
 | 
			
		||||
                                      *relay_port, config.credentials);
 | 
			
		||||
    TurnPort* port = NULL;
 | 
			
		||||
    if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
 | 
			
		||||
      port = TurnPort::Create(session_->network_thread(),
 | 
			
		||||
                              session_->socket_factory(),
 | 
			
		||||
                              network_, udp_socket_.get(),
 | 
			
		||||
                              session_->username(), session_->password(),
 | 
			
		||||
                              *relay_port, config.credentials);
 | 
			
		||||
    } else {
 | 
			
		||||
      port = TurnPort::Create(session_->network_thread(),
 | 
			
		||||
                              session_->socket_factory(),
 | 
			
		||||
                              network_, ip_,
 | 
			
		||||
                              session_->allocator()->min_port(),
 | 
			
		||||
                              session_->allocator()->max_port(),
 | 
			
		||||
                              session_->username(),
 | 
			
		||||
                              session_->password(),
 | 
			
		||||
                              *relay_port, config.credentials);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (port) {
 | 
			
		||||
      // If we are using shared socket for TURN and udp ports, we need to
 | 
			
		||||
      // find a way to demux the packets to the correct port when received.
 | 
			
		||||
      // Mapping against server_address is one way of doing this. When packet
 | 
			
		||||
      // is received the remote_address will be checked against the map.
 | 
			
		||||
      // If server address is not resolved, a signal will be sent from the port
 | 
			
		||||
      // after the address is resolved. The map entry will updated with the
 | 
			
		||||
      // resolved address when the signal is received from the port.
 | 
			
		||||
      if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
 | 
			
		||||
        // If server address is not resolved then listen for signal from port.
 | 
			
		||||
        if ((*relay_port).address.IsUnresolved()) {
 | 
			
		||||
          port->SignalResolvedServerAddress.connect(
 | 
			
		||||
              this, &AllocationSequence::OnResolvedTurnServerAddress);
 | 
			
		||||
        }
 | 
			
		||||
        turn_ports_[(*relay_port).address] = port;
 | 
			
		||||
      }
 | 
			
		||||
      session_->AddAllocatedPort(port, this, true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1011,22 +1047,46 @@ void AllocationSequence::OnReadPacket(
 | 
			
		||||
    const talk_base::SocketAddress& remote_addr,
 | 
			
		||||
    const talk_base::PacketTime& packet_time) {
 | 
			
		||||
  ASSERT(socket == udp_socket_.get());
 | 
			
		||||
  for (std::deque<Port*>::iterator iter = ports.begin();
 | 
			
		||||
       iter != ports.end(); ++iter) {
 | 
			
		||||
    // We have only one port in the queue.
 | 
			
		||||
    // TODO(mallinath) - Add shared socket support to Relay and Turn ports.
 | 
			
		||||
    if ((*iter)->HandleIncomingPacket(
 | 
			
		||||
        socket, data, size, remote_addr, packet_time)) {
 | 
			
		||||
      break;
 | 
			
		||||
  // If the packet is received from one of the TURN server in the config, then
 | 
			
		||||
  // pass down the packet to that port, otherwise it will be handed down to
 | 
			
		||||
  // the local udp port.
 | 
			
		||||
  Port* port = NULL;
 | 
			
		||||
  std::map<talk_base::SocketAddress, Port*>::iterator iter =
 | 
			
		||||
      turn_ports_.find(remote_addr);
 | 
			
		||||
  if (iter != turn_ports_.end()) {
 | 
			
		||||
    port = iter->second;
 | 
			
		||||
  } else if (udp_port_) {
 | 
			
		||||
    port = udp_port_;
 | 
			
		||||
  }
 | 
			
		||||
  ASSERT(port != NULL);
 | 
			
		||||
  port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AllocationSequence::OnPortDestroyed(PortInterface* port) {
 | 
			
		||||
  if (udp_port_ == port) {
 | 
			
		||||
    udp_port_ = NULL;
 | 
			
		||||
  } else {
 | 
			
		||||
    std::map<talk_base::SocketAddress, Port*>::iterator iter;
 | 
			
		||||
    for (iter = turn_ports_.begin(); iter != turn_ports_.end(); ++iter) {
 | 
			
		||||
      if (iter->second == port) {
 | 
			
		||||
        turn_ports_.erase(iter);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AllocationSequence::OnPortDestroyed(PortInterface* port) {
 | 
			
		||||
  std::deque<Port*>::iterator iter =
 | 
			
		||||
      std::find(ports.begin(), ports.end(), port);
 | 
			
		||||
  ASSERT(iter != ports.end());
 | 
			
		||||
  ports.erase(iter);
 | 
			
		||||
void AllocationSequence::OnResolvedTurnServerAddress(
 | 
			
		||||
    TurnPort* port, const talk_base::SocketAddress& server_address,
 | 
			
		||||
    const talk_base::SocketAddress& resolved_server_address) {
 | 
			
		||||
  std::map<talk_base::SocketAddress, Port*>::iterator iter;
 | 
			
		||||
  iter = turn_ports_.find(server_address);
 | 
			
		||||
 | 
			
		||||
  ASSERT(iter != turn_ports_.end());
 | 
			
		||||
  ASSERT(iter->second != port);
 | 
			
		||||
  // Remove old entry and then insert using the resolved address as key.
 | 
			
		||||
  turn_ports_.erase(iter);
 | 
			
		||||
  turn_ports_[resolved_server_address] = port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PortConfiguration
 | 
			
		||||
@@ -1044,7 +1104,7 @@ void PortConfiguration::AddRelay(const RelayServerConfig& config) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PortConfiguration::SupportsProtocol(
 | 
			
		||||
    const RelayServerConfig& relay, ProtocolType type) {
 | 
			
		||||
    const RelayServerConfig& relay, ProtocolType type) const {
 | 
			
		||||
  PortList::const_iterator relay_port;
 | 
			
		||||
  for (relay_port = relay.ports.begin();
 | 
			
		||||
        relay_port != relay.ports.end();
 | 
			
		||||
@@ -1055,4 +1115,14 @@ bool PortConfiguration::SupportsProtocol(
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PortConfiguration::SupportsProtocol(const RelayType turn_type,
 | 
			
		||||
                                         ProtocolType type) const {
 | 
			
		||||
  for (size_t i = 0; i < relays.size(); ++i) {
 | 
			
		||||
    if (relays[i].type == turn_type &&
 | 
			
		||||
        SupportsProtocol(relays[i], type))
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace cricket
 | 
			
		||||
 
 | 
			
		||||
@@ -232,8 +232,9 @@ struct PortConfiguration : public talk_base::MessageData {
 | 
			
		||||
  void AddRelay(const RelayServerConfig& config);
 | 
			
		||||
 | 
			
		||||
  // Determines whether the given relay server supports the given protocol.
 | 
			
		||||
  static bool SupportsProtocol(const RelayServerConfig& relay,
 | 
			
		||||
                               ProtocolType type);
 | 
			
		||||
  bool SupportsProtocol(const RelayServerConfig& relay,
 | 
			
		||||
                        ProtocolType type) const;
 | 
			
		||||
  bool SupportsProtocol(const RelayType turn_type, ProtocolType type) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace cricket
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ class FakeStunPort : public StunPort {
 | 
			
		||||
 | 
			
		||||
  // Just set external address and signal that we are done.
 | 
			
		||||
  virtual void PrepareAddress() {
 | 
			
		||||
    AddAddress(kExternalAddr, kExternalAddr, "udp",
 | 
			
		||||
    AddAddress(kExternalAddr, kExternalAddr, talk_base::SocketAddress(), "udp",
 | 
			
		||||
               STUN_PORT_TYPE, ICE_TYPE_PREFERENCE_SRFLX, true);
 | 
			
		||||
    SignalPortComplete(this);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
#include "talk/p2p/base/portallocatorsessionproxy.h"
 | 
			
		||||
#include "talk/p2p/base/testrelayserver.h"
 | 
			
		||||
#include "talk/p2p/base/teststunserver.h"
 | 
			
		||||
#include "talk/p2p/base/testturnserver.h"
 | 
			
		||||
#include "talk/p2p/client/basicportallocator.h"
 | 
			
		||||
#include "talk/p2p/client/httpportallocator.h"
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +56,7 @@ static const SocketAddress kClientIPv6Addr(
 | 
			
		||||
    "2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
 | 
			
		||||
static const SocketAddress kClientAddr2("22.22.22.22", 0);
 | 
			
		||||
static const SocketAddress kNatAddr("77.77.77.77", talk_base::NAT_SERVER_PORT);
 | 
			
		||||
static const SocketAddress kRemoteClientAddr("22.22.22.22", 0);
 | 
			
		||||
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
 | 
			
		||||
static const SocketAddress kRelayUdpIntAddr("99.99.99.2", 5000);
 | 
			
		||||
static const SocketAddress kRelayUdpExtAddr("99.99.99.3", 5001);
 | 
			
		||||
@@ -62,6 +64,8 @@ static const SocketAddress kRelayTcpIntAddr("99.99.99.2", 5002);
 | 
			
		||||
static const SocketAddress kRelayTcpExtAddr("99.99.99.3", 5003);
 | 
			
		||||
static const SocketAddress kRelaySslTcpIntAddr("99.99.99.2", 5004);
 | 
			
		||||
static const SocketAddress kRelaySslTcpExtAddr("99.99.99.3", 5005);
 | 
			
		||||
static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
 | 
			
		||||
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
 | 
			
		||||
 | 
			
		||||
// Minimum and maximum port for port range tests.
 | 
			
		||||
static const int kMinPort = 10000;
 | 
			
		||||
@@ -75,6 +79,8 @@ static const char kIcePwd0[] = "TESTICEPWD00000000000000";
 | 
			
		||||
static const char kContentName[] = "test content";
 | 
			
		||||
 | 
			
		||||
static const int kDefaultAllocationTimeout = 1000;
 | 
			
		||||
static const char kTurnUsername[] = "test";
 | 
			
		||||
static const char kTurnPassword[] = "test";
 | 
			
		||||
 | 
			
		||||
namespace cricket {
 | 
			
		||||
 | 
			
		||||
@@ -107,6 +113,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> {
 | 
			
		||||
        relay_server_(Thread::Current(), kRelayUdpIntAddr, kRelayUdpExtAddr,
 | 
			
		||||
                      kRelayTcpIntAddr, kRelayTcpExtAddr,
 | 
			
		||||
                      kRelaySslTcpIntAddr, kRelaySslTcpExtAddr),
 | 
			
		||||
        turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
 | 
			
		||||
        allocator_(new cricket::BasicPortAllocator(
 | 
			
		||||
            &network_manager_, kStunAddr,
 | 
			
		||||
            kRelayUdpIntAddr, kRelayTcpIntAddr, kRelaySslTcpIntAddr)),
 | 
			
		||||
@@ -245,6 +252,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> {
 | 
			
		||||
  talk_base::BasicPacketSocketFactory nat_socket_factory_;
 | 
			
		||||
  cricket::TestStunServer stun_server_;
 | 
			
		||||
  cricket::TestRelayServer relay_server_;
 | 
			
		||||
  cricket::TestTurnServer turn_server_;
 | 
			
		||||
  talk_base::FakeNetworkManager network_manager_;
 | 
			
		||||
  talk_base::scoped_ptr<cricket::BasicPortAllocator> allocator_;
 | 
			
		||||
  talk_base::scoped_ptr<cricket::PortAllocatorSession> session_;
 | 
			
		||||
@@ -653,7 +661,7 @@ TEST_F(PortAllocatorTest, TestDisableSharedUfrag) {
 | 
			
		||||
// is allocated for udp and stun. Also verify there is only one candidate
 | 
			
		||||
// (local) if stun candidate is same as local candidate, which will be the case
 | 
			
		||||
// in a public network like the below test.
 | 
			
		||||
TEST_F(PortAllocatorTest, TestEnableSharedSocketWithoutNat) {
 | 
			
		||||
TEST_F(PortAllocatorTest, TestSharedSocketWithoutNat) {
 | 
			
		||||
  AddInterface(kClientAddr);
 | 
			
		||||
  allocator_->set_flags(allocator().flags() |
 | 
			
		||||
                        cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
 | 
			
		||||
@@ -670,7 +678,7 @@ TEST_F(PortAllocatorTest, TestEnableSharedSocketWithoutNat) {
 | 
			
		||||
// Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled only one port
 | 
			
		||||
// is allocated for udp and stun. In this test we should expect both stun and
 | 
			
		||||
// local candidates as client behind a nat.
 | 
			
		||||
TEST_F(PortAllocatorTest, TestEnableSharedSocketWithNat) {
 | 
			
		||||
TEST_F(PortAllocatorTest, TestSharedSocketWithNat) {
 | 
			
		||||
  AddInterface(kClientAddr);
 | 
			
		||||
  talk_base::scoped_ptr<talk_base::NATServer> nat_server(
 | 
			
		||||
      CreateNatServer(kNatAddr, talk_base::NAT_OPEN_CONE));
 | 
			
		||||
@@ -693,10 +701,51 @@ TEST_F(PortAllocatorTest, TestEnableSharedSocketWithNat) {
 | 
			
		||||
  EXPECT_EQ(3U, candidates_.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled only one port
 | 
			
		||||
// is allocated for udp/stun/turn. In this test we should expect all local,
 | 
			
		||||
// stun and turn candidates.
 | 
			
		||||
TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) {
 | 
			
		||||
  AddInterface(kClientAddr);
 | 
			
		||||
  talk_base::scoped_ptr<talk_base::NATServer> nat_server(
 | 
			
		||||
      CreateNatServer(kNatAddr, talk_base::NAT_OPEN_CONE));
 | 
			
		||||
  allocator_.reset(new cricket::BasicPortAllocator(
 | 
			
		||||
      &network_manager_, &nat_socket_factory_, kStunAddr));
 | 
			
		||||
  cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
 | 
			
		||||
  cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
 | 
			
		||||
  relay_server.credentials = credentials;
 | 
			
		||||
  relay_server.ports.push_back(cricket::ProtocolAddress(
 | 
			
		||||
      kTurnUdpIntAddr, cricket::PROTO_UDP, false));
 | 
			
		||||
  allocator_->AddRelay(relay_server);
 | 
			
		||||
 | 
			
		||||
  allocator_->set_step_delay(cricket::kMinimumStepDelay);
 | 
			
		||||
  allocator_->set_flags(allocator().flags() |
 | 
			
		||||
                        cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
 | 
			
		||||
                        cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
 | 
			
		||||
                        cricket::PORTALLOCATOR_DISABLE_TCP);
 | 
			
		||||
  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
 | 
			
		||||
  session_->StartGettingPorts();
 | 
			
		||||
  ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout);
 | 
			
		||||
  ASSERT_EQ(2U, ports_.size());
 | 
			
		||||
  EXPECT_PRED5(CheckCandidate, candidates_[0],
 | 
			
		||||
      cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr);
 | 
			
		||||
  EXPECT_PRED5(CheckCandidate, candidates_[1],
 | 
			
		||||
      cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp",
 | 
			
		||||
      talk_base::SocketAddress(kNatAddr.ipaddr(), 0));
 | 
			
		||||
  EXPECT_PRED5(CheckCandidate, candidates_[2],
 | 
			
		||||
      cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp",
 | 
			
		||||
      talk_base::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0));
 | 
			
		||||
  EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
 | 
			
		||||
  EXPECT_EQ(3U, candidates_.size());
 | 
			
		||||
  // Local port will be created first and then TURN port.
 | 
			
		||||
  // Checking TURN port has two candidates, STUN + TURN.
 | 
			
		||||
  EXPECT_EQ(1U, ports_[0]->Candidates().size());
 | 
			
		||||
  EXPECT_EQ(2U, ports_[1]->Candidates().size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This test verifies when PORTALLOCATOR_ENABLE_SHARED_SOCKET flag is enabled
 | 
			
		||||
// and fail to generate STUN candidate, local UDP candidate is generated
 | 
			
		||||
// properly.
 | 
			
		||||
TEST_F(PortAllocatorTest, TestEnableSharedSocketNoUdpAllowed) {
 | 
			
		||||
TEST_F(PortAllocatorTest, TestSharedSocketNoUdpAllowed) {
 | 
			
		||||
  allocator().set_flags(allocator().flags() |
 | 
			
		||||
                        cricket::PORTALLOCATOR_DISABLE_RELAY |
 | 
			
		||||
                        cricket::PORTALLOCATOR_DISABLE_TCP |
 | 
			
		||||
 
 | 
			
		||||
@@ -320,17 +320,13 @@ XmppChatroomModuleImpl::RequestExitChatroom() {
 | 
			
		||||
  if (!engine())
 | 
			
		||||
    return XMPP_RETURN_BADSTATE;
 | 
			
		||||
 | 
			
		||||
  // currently, can't leave a room unless you've entered
 | 
			
		||||
  // no way to cancel a pending enter call - is that bad?
 | 
			
		||||
  if (chatroom_state_ != XMPP_CHATROOM_STATE_IN_ROOM)
 | 
			
		||||
    return XMPP_RETURN_BADSTATE; // $TODO - this isn't a bad state, it's a bad call,  diff error code?
 | 
			
		||||
 | 
			
		||||
  // exiting a chatroom is a presence request to the server
 | 
			
		||||
  XmlElement element(QN_PRESENCE);
 | 
			
		||||
  element.AddAttr(QN_TO, member_jid().Str());
 | 
			
		||||
  element.AddAttr(QN_TYPE, "unavailable");
 | 
			
		||||
  XmppReturnStatus status = engine()->SendStanza(&element);
 | 
			
		||||
  if (status == XMPP_RETURN_OK) {
 | 
			
		||||
  if (status == XMPP_RETURN_OK &&
 | 
			
		||||
      chatroom_state_ == XMPP_CHATROOM_STATE_IN_ROOM) {
 | 
			
		||||
    return ClientChangeMyPresence(XMPP_CHATROOM_STATE_REQUESTED_EXIT);
 | 
			
		||||
  }
 | 
			
		||||
  return status;
 | 
			
		||||
@@ -513,6 +509,7 @@ XmppChatroomModuleImpl::ServerChangedOtherPresence(const XmlElement&
 | 
			
		||||
      FireMemberChanged(member);
 | 
			
		||||
    }
 | 
			
		||||
    else if (presence->available() == XMPP_PRESENCE_UNAVAILABLE) {
 | 
			
		||||
      member->SetPresence(presence.get());
 | 
			
		||||
      chatroom_jid_members_.erase(pos);
 | 
			
		||||
      chatroom_jid_members_version_++;
 | 
			
		||||
      FireMemberExited(member);
 | 
			
		||||
 
 | 
			
		||||
@@ -173,9 +173,16 @@ void PubSubRequestTask::HandleResult(const XmlElement* stanza) {
 | 
			
		||||
  SignalResult(this, items);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PubSubReceiveTask::ProcessStart() {
 | 
			
		||||
  if (SignalUpdate.is_empty()) {
 | 
			
		||||
    return STATE_DONE;
 | 
			
		||||
  }
 | 
			
		||||
  return ReceiveTask::ProcessStart();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PubSubReceiveTask::WantsStanza(const XmlElement* stanza) {
 | 
			
		||||
  return MatchStanzaFrom(stanza, pubsubjid_) &&
 | 
			
		||||
      IsPubSubEventItemsElem(stanza, node_);
 | 
			
		||||
      IsPubSubEventItemsElem(stanza, node_) && !SignalUpdate.is_empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PubSubReceiveTask::ReceiveStanza(const XmlElement* stanza) {
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,7 @@ class PubSubReceiveTask : public ReceiveTask {
 | 
			
		||||
        node_(node) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual int ProcessStart();
 | 
			
		||||
  sigslot::signal2<PubSubReceiveTask*,
 | 
			
		||||
                   const std::vector<PubSubItem>&> SignalUpdate;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -351,10 +351,6 @@ XmppPresenceImpl::set_raw_xml(const XmlElement * xml) {
 | 
			
		||||
      xml->Name() != QN_PRESENCE)
 | 
			
		||||
    return XMPP_RETURN_BADARGUMENT;
 | 
			
		||||
 | 
			
		||||
  const std::string& type = xml->Attr(QN_TYPE);
 | 
			
		||||
  if (type != STR_EMPTY && type != "unavailable")
 | 
			
		||||
    return XMPP_RETURN_BADARGUMENT;
 | 
			
		||||
 | 
			
		||||
  raw_xml_.reset(new XmlElement(*xml));
 | 
			
		||||
  return XMPP_RETURN_OK;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user