Implement GetState() for channel's connectivity check state.
Previously, IceState is considered completed when there is only one connection (and the rest was trimmed). However, since the trimming logic is only done within the scope of network, when IPv6 and IPv4 both exist, the completion event is never fired. This change adds the GetState() to each channel and it could decide what Completion means. The transport object then aggregates all channels before determining it's completed. Each channel's IceState will be aggregrated at Transport level for overall Ice state BUG=411086 R=pthatcher@webrtc.org Review URL: https://webrtc-codereview.appspot.com/30949004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7804 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
fd4acf6d55
commit
ff72f9e692
@ -109,9 +109,6 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
|
|||||||
virtual IceRole GetIceRole() const {
|
virtual IceRole GetIceRole() const {
|
||||||
return channel_->GetIceRole();
|
return channel_->GetIceRole();
|
||||||
}
|
}
|
||||||
virtual size_t GetConnectionCount() const {
|
|
||||||
return channel_->GetConnectionCount();
|
|
||||||
}
|
|
||||||
virtual bool SetLocalIdentity(rtc::SSLIdentity *identity);
|
virtual bool SetLocalIdentity(rtc::SSLIdentity *identity);
|
||||||
virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const;
|
virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const;
|
||||||
|
|
||||||
@ -175,6 +172,10 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
|
|||||||
virtual Transport* GetTransport() {
|
virtual Transport* GetTransport() {
|
||||||
return transport_;
|
return transport_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual TransportChannelState GetState() const {
|
||||||
|
return channel_->GetState();
|
||||||
|
}
|
||||||
virtual void SetIceTiebreaker(uint64 tiebreaker) {
|
virtual void SetIceTiebreaker(uint64 tiebreaker) {
|
||||||
channel_->SetIceTiebreaker(tiebreaker);
|
channel_->SetIceTiebreaker(tiebreaker);
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,20 @@ class FakeTransportChannel : public TransportChannelImpl,
|
|||||||
return transport_;
|
return transport_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual TransportChannelState GetState() const {
|
||||||
|
if (connection_count_ == 0) {
|
||||||
|
return TransportChannelState::STATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection_count_ == 1) {
|
||||||
|
return TransportChannelState::STATE_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TransportChannelState::STATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void SetIceRole(IceRole role) { role_ = role; }
|
virtual void SetIceRole(IceRole role) { role_ = role; }
|
||||||
virtual IceRole GetIceRole() const { return role_; }
|
virtual IceRole GetIceRole() const { return role_; }
|
||||||
virtual size_t GetConnectionCount() const { return connection_count_; }
|
|
||||||
virtual void SetIceTiebreaker(uint64 tiebreaker) { tiebreaker_ = tiebreaker; }
|
virtual void SetIceTiebreaker(uint64 tiebreaker) { tiebreaker_ = tiebreaker; }
|
||||||
virtual bool GetIceProtocolType(IceProtocolType* type) const {
|
virtual bool GetIceProtocolType(IceProtocolType* type) const {
|
||||||
*type = ice_proto_;
|
*type = ice_proto_;
|
||||||
|
@ -226,6 +226,36 @@ void P2PTransportChannel::SetIceTiebreaker(uint64 tiebreaker) {
|
|||||||
tiebreaker_ = tiebreaker;
|
tiebreaker_ = tiebreaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Currently a channel is considered ICE completed once there is no
|
||||||
|
// more than one connection per Network. This works for a single NIC
|
||||||
|
// with both IPv4 and IPv6 enabled. However, this condition won't
|
||||||
|
// happen when there are multiple NICs and all of them have
|
||||||
|
// connectivity.
|
||||||
|
// TODO(guoweis): Change Completion to be driven by a channel level
|
||||||
|
// timer.
|
||||||
|
TransportChannelState P2PTransportChannel::GetState() const {
|
||||||
|
std::set<rtc::Network*> networks;
|
||||||
|
|
||||||
|
if (connections_.size() == 0) {
|
||||||
|
return TransportChannelState::STATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < connections_.size(); ++i) {
|
||||||
|
rtc::Network* network = connections_[i]->port()->Network();
|
||||||
|
if (networks.find(network) == networks.end()) {
|
||||||
|
networks.insert(network);
|
||||||
|
} else {
|
||||||
|
LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as "
|
||||||
|
<< network->ToString()
|
||||||
|
<< " has more than 1 connection.";
|
||||||
|
return TransportChannelState::STATE_CONNECTING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel.";
|
||||||
|
|
||||||
|
return TransportChannelState::STATE_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const {
|
bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const {
|
||||||
*type = protocol_type_;
|
*type = protocol_type_;
|
||||||
return true;
|
return true;
|
||||||
@ -1065,7 +1095,7 @@ void P2PTransportChannel::HandleAllTimedOut() {
|
|||||||
// If we have a best connection, return it, otherwise return top one in the
|
// If we have a best connection, return it, otherwise return top one in the
|
||||||
// list (later we will mark it best).
|
// list (later we will mark it best).
|
||||||
Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
|
Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
|
||||||
rtc::Network* network) {
|
rtc::Network* network) const {
|
||||||
// If the best connection is on this network, then it wins.
|
// If the best connection is on this network, then it wins.
|
||||||
if (best_connection_ && (best_connection_->port()->Network() == network))
|
if (best_connection_ && (best_connection_->port()->Network() == network))
|
||||||
return best_connection_;
|
return best_connection_;
|
||||||
|
@ -59,10 +59,10 @@ class P2PTransportChannel : public TransportChannelImpl,
|
|||||||
|
|
||||||
// From TransportChannelImpl:
|
// From TransportChannelImpl:
|
||||||
virtual Transport* GetTransport() { return transport_; }
|
virtual Transport* GetTransport() { return transport_; }
|
||||||
|
virtual TransportChannelState GetState() const;
|
||||||
virtual void SetIceRole(IceRole role);
|
virtual void SetIceRole(IceRole role);
|
||||||
virtual IceRole GetIceRole() const { return ice_role_; }
|
virtual IceRole GetIceRole() const { return ice_role_; }
|
||||||
virtual void SetIceTiebreaker(uint64 tiebreaker);
|
virtual void SetIceTiebreaker(uint64 tiebreaker);
|
||||||
virtual size_t GetConnectionCount() const { return connections_.size(); }
|
|
||||||
virtual bool GetIceProtocolType(IceProtocolType* type) const;
|
virtual bool GetIceProtocolType(IceProtocolType* type) const;
|
||||||
virtual void SetIceProtocolType(IceProtocolType type);
|
virtual void SetIceProtocolType(IceProtocolType type);
|
||||||
virtual void SetIceCredentials(const std::string& ice_ufrag,
|
virtual void SetIceCredentials(const std::string& ice_ufrag,
|
||||||
@ -164,7 +164,7 @@ class P2PTransportChannel : public TransportChannelImpl,
|
|||||||
void HandleNotWritable();
|
void HandleNotWritable();
|
||||||
void HandleAllTimedOut();
|
void HandleAllTimedOut();
|
||||||
|
|
||||||
Connection* GetBestConnectionOnNetwork(rtc::Network* network);
|
Connection* GetBestConnectionOnNetwork(rtc::Network* network) const;
|
||||||
bool CreateConnections(const Candidate &remote_candidate,
|
bool CreateConnections(const Candidate &remote_candidate,
|
||||||
PortInterface* origin_port, bool readable);
|
PortInterface* origin_port, bool readable);
|
||||||
bool CreateConnection(PortInterface* port, const Candidate& remote_candidate,
|
bool CreateConnection(PortInterface* port, const Candidate& remote_candidate,
|
||||||
|
@ -927,7 +927,8 @@ void Connection::set_write_state(WriteState value) {
|
|||||||
WriteState old_value = write_state_;
|
WriteState old_value = write_state_;
|
||||||
write_state_ = value;
|
write_state_ = value;
|
||||||
if (value != old_value) {
|
if (value != old_value) {
|
||||||
LOG_J(LS_VERBOSE, this) << "set_write_state";
|
LOG_J(LS_VERBOSE, this) << "set_write_state from: " << old_value << " to "
|
||||||
|
<< value;
|
||||||
SignalStateChange(this);
|
SignalStateChange(this);
|
||||||
CheckTimeout();
|
CheckTimeout();
|
||||||
}
|
}
|
||||||
@ -1102,8 +1103,10 @@ void Connection::UpdateState(uint32 now) {
|
|||||||
pings_since_last_response_[i]);
|
pings_since_last_response_[i]);
|
||||||
pings.append(buf).append(" ");
|
pings.append(buf).append(" ");
|
||||||
}
|
}
|
||||||
LOG_J(LS_VERBOSE, this) << "UpdateState(): pings_since_last_response_=" <<
|
LOG_J(LS_VERBOSE, this) << "UpdateState(): pings_since_last_response_="
|
||||||
pings << ", rtt=" << rtt << ", now=" << now;
|
<< pings << ", rtt=" << rtt << ", now=" << now
|
||||||
|
<< ", last ping received: " << last_ping_received_
|
||||||
|
<< ", last data_received: " << last_data_received_;
|
||||||
|
|
||||||
// Check the readable state.
|
// Check the readable state.
|
||||||
//
|
//
|
||||||
@ -1187,6 +1190,12 @@ void Connection::ReceivedPing() {
|
|||||||
set_read_state(STATE_READABLE);
|
set_read_state(STATE_READABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Connection::ToDebugId() const {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::hex << this;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string Connection::ToString() const {
|
std::string Connection::ToString() const {
|
||||||
const char CONNECT_STATE_ABBREV[2] = {
|
const char CONNECT_STATE_ABBREV[2] = {
|
||||||
'-', // not connected (false)
|
'-', // not connected (false)
|
||||||
@ -1212,7 +1221,8 @@ std::string Connection::ToString() const {
|
|||||||
const Candidate& local = local_candidate();
|
const Candidate& local = local_candidate();
|
||||||
const Candidate& remote = remote_candidate();
|
const Candidate& remote = remote_candidate();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Conn[" << port_->content_name()
|
ss << "Conn[" << ToDebugId()
|
||||||
|
<< ":" << port_->content_name()
|
||||||
<< ":" << local.id() << ":" << local.component()
|
<< ":" << local.id() << ":" << local.component()
|
||||||
<< ":" << local.generation()
|
<< ":" << local.generation()
|
||||||
<< ":" << local.type() << ":" << local.protocol()
|
<< ":" << local.type() << ":" << local.protocol()
|
||||||
|
@ -517,6 +517,7 @@ class Connection : public rtc::MessageHandler,
|
|||||||
void ReceivedPing();
|
void ReceivedPing();
|
||||||
|
|
||||||
// Debugging description of this connection
|
// Debugging description of this connection
|
||||||
|
std::string ToDebugId() const;
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
std::string ToSensitiveString() const;
|
std::string ToSensitiveString() const;
|
||||||
|
|
||||||
|
@ -54,6 +54,9 @@ class RawTransportChannel : public TransportChannelImpl,
|
|||||||
|
|
||||||
// Implements TransportChannelImpl.
|
// Implements TransportChannelImpl.
|
||||||
virtual Transport* GetTransport() { return raw_transport_; }
|
virtual Transport* GetTransport() { return raw_transport_; }
|
||||||
|
virtual TransportChannelState GetState() const {
|
||||||
|
return TransportChannelState::STATE_COMPLETED;
|
||||||
|
}
|
||||||
virtual void SetIceCredentials(const std::string& ice_ufrag,
|
virtual void SetIceCredentials(const std::string& ice_ufrag,
|
||||||
const std::string& ice_pwd) {}
|
const std::string& ice_pwd) {}
|
||||||
virtual void SetRemoteIceCredentials(const std::string& ice_ufrag,
|
virtual void SetRemoteIceCredentials(const std::string& ice_ufrag,
|
||||||
|
@ -669,8 +669,7 @@ void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t connections = channel->GetConnectionCount();
|
if (channel->GetState() == TransportChannelState::STATE_FAILED) {
|
||||||
if (connections == 0) {
|
|
||||||
// A Transport has failed if any of its channels have no remaining
|
// A Transport has failed if any of its channels have no remaining
|
||||||
// connections.
|
// connections.
|
||||||
signaling_thread_->Post(this, MSG_FAILED);
|
signaling_thread_->Post(this, MSG_FAILED);
|
||||||
@ -680,6 +679,12 @@ void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
|
|||||||
void Transport::MaybeCompleted_w() {
|
void Transport::MaybeCompleted_w() {
|
||||||
ASSERT(worker_thread()->IsCurrent());
|
ASSERT(worker_thread()->IsCurrent());
|
||||||
|
|
||||||
|
// When there is no channel created yet, calling this function could fire an
|
||||||
|
// IceConnectionCompleted event prematurely.
|
||||||
|
if (channels_.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// A Transport's ICE process is completed if all of its channels are writable,
|
// A Transport's ICE process is completed if all of its channels are writable,
|
||||||
// have finished allocating candidates, and have pruned all but one of their
|
// have finished allocating candidates, and have pruned all but one of their
|
||||||
// connections.
|
// connections.
|
||||||
@ -687,7 +692,7 @@ void Transport::MaybeCompleted_w() {
|
|||||||
for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
|
for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
|
||||||
const TransportChannelImpl* channel = iter->second.get();
|
const TransportChannelImpl* channel = iter->second.get();
|
||||||
if (!(channel->writable() &&
|
if (!(channel->writable() &&
|
||||||
channel->GetConnectionCount() == 1 &&
|
channel->GetState() == TransportChannelState::STATE_COMPLETED &&
|
||||||
channel->GetIceRole() == ICEROLE_CONTROLLING &&
|
channel->GetIceRole() == ICEROLE_CONTROLLING &&
|
||||||
iter->second.candidates_allocated())) {
|
iter->second.candidates_allocated())) {
|
||||||
return;
|
return;
|
||||||
|
@ -36,6 +36,9 @@ enum PacketFlags {
|
|||||||
// crypto provided by the transport (e.g. DTLS)
|
// crypto provided by the transport (e.g. DTLS)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used to indicate channel's connection state.
|
||||||
|
enum TransportChannelState { STATE_CONNECTING, STATE_COMPLETED, STATE_FAILED };
|
||||||
|
|
||||||
// A TransportChannel represents one logical stream of packets that are sent
|
// A TransportChannel represents one logical stream of packets that are sent
|
||||||
// between the two sides of a session.
|
// between the two sides of a session.
|
||||||
class TransportChannel : public sigslot::has_slots<> {
|
class TransportChannel : public sigslot::has_slots<> {
|
||||||
@ -46,6 +49,8 @@ class TransportChannel : public sigslot::has_slots<> {
|
|||||||
readable_(false), writable_(false) {}
|
readable_(false), writable_(false) {}
|
||||||
virtual ~TransportChannel() {}
|
virtual ~TransportChannel() {}
|
||||||
|
|
||||||
|
virtual TransportChannelState GetState() const = 0;
|
||||||
|
|
||||||
// TODO(mallinath) - Remove this API, as it's no longer useful.
|
// TODO(mallinath) - Remove this API, as it's no longer useful.
|
||||||
// Returns the session id of this channel.
|
// Returns the session id of this channel.
|
||||||
virtual const std::string SessionId() const { return std::string(); }
|
virtual const std::string SessionId() const { return std::string(); }
|
||||||
|
@ -36,7 +36,6 @@ class TransportChannelImpl : public TransportChannel {
|
|||||||
virtual IceRole GetIceRole() const = 0;
|
virtual IceRole GetIceRole() const = 0;
|
||||||
virtual void SetIceRole(IceRole role) = 0;
|
virtual void SetIceRole(IceRole role) = 0;
|
||||||
virtual void SetIceTiebreaker(uint64 tiebreaker) = 0;
|
virtual void SetIceTiebreaker(uint64 tiebreaker) = 0;
|
||||||
virtual size_t GetConnectionCount() const = 0;
|
|
||||||
// To toggle G-ICE/ICE.
|
// To toggle G-ICE/ICE.
|
||||||
virtual bool GetIceProtocolType(IceProtocolType* type) const = 0;
|
virtual bool GetIceProtocolType(IceProtocolType* type) const = 0;
|
||||||
virtual void SetIceProtocolType(IceProtocolType type) = 0;
|
virtual void SetIceProtocolType(IceProtocolType type) = 0;
|
||||||
|
@ -111,6 +111,14 @@ int TransportChannelProxy::GetError() {
|
|||||||
return impl_->GetError();
|
return impl_->GetError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransportChannelState TransportChannelProxy::GetState() const {
|
||||||
|
ASSERT(rtc::Thread::Current() == worker_thread_);
|
||||||
|
if (!impl_) {
|
||||||
|
return TransportChannelState::STATE_CONNECTING;
|
||||||
|
}
|
||||||
|
return impl_->GetState();
|
||||||
|
}
|
||||||
|
|
||||||
bool TransportChannelProxy::GetStats(ConnectionInfos* infos) {
|
bool TransportChannelProxy::GetStats(ConnectionInfos* infos) {
|
||||||
ASSERT(rtc::Thread::Current() == worker_thread_);
|
ASSERT(rtc::Thread::Current() == worker_thread_);
|
||||||
if (!impl_) {
|
if (!impl_) {
|
||||||
|
@ -41,6 +41,8 @@ class TransportChannelProxy : public TransportChannel,
|
|||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
TransportChannelImpl* impl() { return impl_; }
|
TransportChannelImpl* impl() { return impl_; }
|
||||||
|
|
||||||
|
virtual TransportChannelState GetState() const;
|
||||||
|
|
||||||
// Sets the implementation to which we will proxy.
|
// Sets the implementation to which we will proxy.
|
||||||
void SetImplementation(TransportChannelImpl* impl);
|
void SetImplementation(TransportChannelImpl* impl);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user