diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 21:36:59 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 21:36:59 +0000 |
commit | 6d2464543977cd709ae1108f958dee5d2c09667b (patch) | |
tree | e9860999bae763a0b4ad65746246ff38097df915 /third_party | |
parent | 131c7d21f8d44f015acd121d3d1e7133463905af (diff) | |
download | chromium_src-6d2464543977cd709ae1108f958dee5d2c09667b.zip chromium_src-6d2464543977cd709ae1108f958dee5d2c09667b.tar.gz chromium_src-6d2464543977cd709ae1108f958dee5d2c09667b.tar.bz2 |
Ripped out talk/p2p directory from third_party/libjingle.
Fixed a few compile errors as a result.
BUG=none
TEST=trybots
Review URL: http://codereview.chromium.org/790002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41210 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
66 files changed, 38 insertions, 15668 deletions
diff --git a/third_party/libjingle/files/talk/p2p/Makefile.am b/third_party/libjingle/files/talk/p2p/Makefile.am deleted file mode 100644 index c935a6b..0000000 --- a/third_party/libjingle/files/talk/p2p/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS=base client diff --git a/third_party/libjingle/files/talk/p2p/base/Makefile.am b/third_party/libjingle/files/talk/p2p/base/Makefile.am deleted file mode 100644 index 537b6c2..0000000 --- a/third_party/libjingle/files/talk/p2p/base/Makefile.am +++ /dev/null @@ -1,68 +0,0 @@ -libcricketp2pbase_la_SOURCES = stun.cc \ - port.cc \ - udpport.cc \ - tcpport.cc \ - stunport.cc \ - relayport.cc \ - stunrequest.cc \ - sessionmanager.cc \ - session.cc \ - transport.cc \ - transportchannel.cc \ - transportchannelproxy.cc \ - p2ptransport.cc \ - p2ptransportchannel.cc \ - rawtransport.cc \ - rawtransportchannel.cc \ - constants.cc \ - pseudotcp.cc - -noinst_HEADERS = candidate.h \ - portallocator.h \ - relayport.h \ - session.h \ - stunport.h \ - tcpport.h \ - port.h \ - sessionid.h \ - stunrequest.h \ - udpport.h \ - pseudotcp.h \ - sessiondescription.h \ - sessionmanager.h \ - stun.h \ - relayserver.h \ - stunserver.h \ - sessionclient.h \ - transport.h \ - transportchannel.h \ - transportchannelproxy.h \ - transportchannelimpl.h \ - p2ptransport.h \ - p2ptransportchannel.h \ - rawtransport.h \ - rawtransportchannel.h \ - constants.h \ - common.h - -AM_CPPFLAGS = -DPOSIX -DENABLE_DEBUG -D_DEBUG -g - -P2PLIBS = libcricketp2pbase.la ../../base/libcricketbase.la -lpthread -XMLLIBS = ../../xmllite/libcricketxmllite.la ../../xmpp/libcricketxmpp.la $(EXPAT_LIBS) -TESTLIBS = ../../base/libcrickettest.la - -bin_PROGRAMS = relayserver stunserver -noinst_PROGRAMS = stunserver_unittest session_unittest port_unittest - -relayserver_SOURCES = relayserver.cc relayserver_main.cc -relayserver_LDADD = $(P2PLIBS) -stunserver_SOURCES = stunserver.cc stunserver_main.cc -stunserver_LDADD = $(P2PLIBS) -stunserver_unittest_SOURCES = stunserver_unittest.cc stunserver.cc -stunserver_unittest_LDADD = $(P2PLIBS) $(TESTLIBS) -session_unittest_SOURCES = session_unittest.cc stunserver.cc relayserver.cc -session_unittest_LDADD = $(TESTLIBS) $(P2PLIBS) $(XMLLIBS) -port_unittest_SOURCES = port_unittest.cc stunserver.cc relayserver.cc -port_unittest_LDADD = $(P2PLIBS) $(TESTLIBS) - -noinst_LTLIBRARIES = libcricketp2pbase.la diff --git a/third_party/libjingle/files/talk/p2p/base/candidate.h b/third_party/libjingle/files/talk/p2p/base/candidate.h deleted file mode 100644 index bc88a42..0000000 --- a/third_party/libjingle/files/talk/p2p/base/candidate.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CANDIDATE_H_ -#define _CANDIDATE_H_ - -#include <string> -#include <sstream> -#include "talk/base/socketaddress.h" - -namespace cricket { - -// Candidate for ICE based connection discovery. - -class Candidate { -public: - - const std::string & name() const { return name_; } - void set_name(const std::string & name) { name_ = name; } - - const std::string & protocol() const { return protocol_; } - void set_protocol(const std::string & protocol) { protocol_ = protocol; } - - const talk_base::SocketAddress & address() const { return address_; } - void set_address(const talk_base::SocketAddress & address) - { address_ = address; } - - float preference() const { return preference_; } - void set_preference(const float preference) { preference_ = preference; } - const std::string preference_str() const { - std::ostringstream ost; - ost << preference_; - return ost.str(); - } - void set_preference_str(const std::string & preference) { - std::istringstream ist(preference); - ist >> preference_; - } - - const std::string & username() const { return username_; } - void set_username(const std::string & username) { username_ = username; } - - const std::string & password() const { return password_; } - void set_password(const std::string & password) { password_ = password; } - - const std::string & type() const { return type_; } - void set_type(const std::string & type) { type_ = type; } - - const std::string & network_name() const { return network_name_; } - void set_network_name(const std::string & network_name) { - network_name_ = network_name; - } - - // Candidates in a new generation replace those in the old generation. - uint32 generation() const { return generation_; } - void set_generation(uint32 generation) { generation_ = generation; } - const std::string generation_str() const { - std::ostringstream ost; - ost << generation_; - return ost.str(); - } - void set_generation_str(const std::string& str) { - std::istringstream ist(str); - ist >> generation_; - } - - // Determines whether this candidate is equivalent to the given one. - bool IsEquivalent(const Candidate& c) const { - // We ignore the network name, since that is just debug information, and - // the preference, since that should be the same if the rest is (and it's - // a float so equality checking is always worrisome). - return (name_ == c.name_) && - (protocol_ == c.protocol_) && - (address_ == c.address_) && - (username_ == c.username_) && - (password_ == c.password_) && - (type_ == c.type_) && - (generation_ == c.generation_); - } - -private: - std::string name_; - std::string protocol_; - talk_base::SocketAddress address_; - float preference_; - std::string username_; - std::string password_; - std::string type_; - std::string network_name_; - uint32 generation_; -}; - -} // namespace cricket - -#endif // _CANDIDATE_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/common.h b/third_party/libjingle/files/talk/p2p/base/common.h deleted file mode 100644 index 72f8cfa..0000000 --- a/third_party/libjingle/files/talk/p2p/base/common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CRICKET_P2P_BASE_COMMON_H__ -#define CRICKET_P2P_BASE_COMMON_H__ - -#include "talk/base/logging.h" - -// Common log description format for jingle messages -#define LOG_J(sev,obj) LOG(sev) << "Jingle:" << obj->ToString() << ": " - -#endif // CRICKET_P2P_BASE_COMMON_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/constants.cc b/third_party/libjingle/files/talk/p2p/base/constants.cc deleted file mode 100644 index 13b9f2d..0000000 --- a/third_party/libjingle/files/talk/p2p/base/constants.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/constants.h" - -namespace cricket { - -const std::string NS_EMPTY(""); -const std::string NS_GOOGLESESSION("http://www.google.com/session"); -#ifdef FEATURE_ENABLE_VOICEMAIL -const std::string NS_GOOGLEVOICEMAIL("http://www.google.com/session/voicemail"); -#endif - -const buzz::QName QN_SESSION(true, NS_GOOGLESESSION, "session"); - -const buzz::QName QN_REDIRECT_TARGET(true, NS_GOOGLESESSION, "target"); -const buzz::QName QN_REDIRECT_COOKIE(true, NS_GOOGLESESSION, "cookie"); -const buzz::QName QN_REDIRECT_REGARDING(true, NS_GOOGLESESSION, "regarding"); - -#ifdef FEATURE_ENABLE_VOICEMAIL -const buzz::QName QN_VOICEMAIL_REGARDING(true, NS_GOOGLEVOICEMAIL, "regarding"); -#endif - -const buzz::QName QN_INITIATOR(true, NS_EMPTY, "initiator"); - -const buzz::QName QN_ADDRESS(true, cricket::NS_EMPTY, "address"); -const buzz::QName QN_PORT(true, cricket::NS_EMPTY, "port"); -const buzz::QName QN_NETWORK(true, cricket::NS_EMPTY, "network"); -const buzz::QName QN_GENERATION(true, cricket::NS_EMPTY, "generation"); -const buzz::QName QN_USERNAME(true, cricket::NS_EMPTY, "username"); -const buzz::QName QN_PASSWORD(true, cricket::NS_EMPTY, "password"); -const buzz::QName QN_PREFERENCE(true, cricket::NS_EMPTY, "preference"); -const buzz::QName QN_PROTOCOL(true, cricket::NS_EMPTY, "protocol"); - -// Legacy transport messages -const buzz::QName kQnLegacyCandidate(true, cricket::NS_GOOGLESESSION, - "candidate"); -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/constants.h b/third_party/libjingle/files/talk/p2p/base/constants.h deleted file mode 100644 index 46315eb..0000000 --- a/third_party/libjingle/files/talk/p2p/base/constants.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_CONSTANTS_H_ -#define _CRICKET_P2P_BASE_CONSTANTS_H_ - -#include <string> -#include "talk/xmllite/qname.h" - -// This file contains constants related to signaling that are used in various -// classes in this directory. - -namespace cricket { - -extern const std::string NS_EMPTY; -extern const std::string NS_GOOGLESESSION; -#ifdef FEATURE_ENABLE_VOICEMAIL -extern const std::string NS_GOOGLEVOICEMAIL; -#endif - -extern const buzz::QName QN_SESSION; - -extern const buzz::QName QN_REDIRECT_TARGET; -extern const buzz::QName QN_REDIRECT_COOKIE; -extern const buzz::QName QN_REDIRECT_REGARDING; -#ifdef FEATURE_ENABLE_VOICEMAIL -extern const buzz::QName QN_VOICEMAIL_REGARDING; -#endif - -extern const buzz::QName QN_INITIATOR; - -extern const buzz::QName QN_ADDRESS; -extern const buzz::QName QN_PORT; -extern const buzz::QName QN_NETWORK; -extern const buzz::QName QN_GENERATION; -extern const buzz::QName QN_USERNAME; -extern const buzz::QName QN_PASSWORD; -extern const buzz::QName QN_PREFERENCE; -extern const buzz::QName QN_PROTOCOL; - -// Legacy transport messages -extern const buzz::QName kQnLegacyCandidate; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_CONSTANTS_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/p2ptransport.cc b/third_party/libjingle/files/talk/p2p/base/p2ptransport.cc deleted file mode 100644 index 4a995cf..0000000 --- a/third_party/libjingle/files/talk/p2p/base/p2ptransport.cc +++ /dev/null @@ -1,209 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/p2ptransport.h" -#include "talk/base/common.h" -#include "talk/p2p/base/candidate.h" -#include "talk/p2p/base/constants.h" -#include "talk/base/helpers.h" -#include "talk/p2p/base/p2ptransportchannel.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/xmllite/qname.h" -#include "talk/xmllite/xmlelement.h" -#include "talk/xmpp/xmppconstants.h" - -namespace { - -// We only allow usernames to be this many characters or fewer. -const size_t kMaxUsernameSize = 16; - -} // namespace - -namespace cricket { - -const std::string kNsP2pTransport("http://www.google.com/transport/p2p"); -const buzz::QName kQnP2pTransport(true, kNsP2pTransport, "transport"); -const buzz::QName kQnP2pCandidate(true, kNsP2pTransport, "candidate"); -const buzz::QName kQnP2pUnknownChannelName(true, kNsP2pTransport, - "unknown-channel-name"); - -P2PTransport::P2PTransport(SessionManager* session_manager) - : Transport(session_manager, kNsP2pTransport) { -} - -P2PTransport::~P2PTransport() { - DestroyAllChannels(); -} - -buzz::XmlElement* P2PTransport::CreateTransportOffer() { - return new buzz::XmlElement(kQnP2pTransport, true); -} - -buzz::XmlElement* P2PTransport::CreateTransportAnswer() { - return new buzz::XmlElement(kQnP2pTransport, true); -} - -bool P2PTransport::OnTransportOffer(const buzz::XmlElement* elem) { - ASSERT(elem->Name() == kQnP2pTransport); - // We don't support any options, so we ignore them. - return true; -} - -bool P2PTransport::OnTransportAnswer(const buzz::XmlElement* elem) { - ASSERT(elem->Name() == kQnP2pTransport); - // We don't support any options. We fail if any are given. The other side - // should know from our request that we expected an empty response. - return elem->FirstChild() == NULL; -} - -bool P2PTransport::OnTransportMessage(const buzz::XmlElement* msg, - const buzz::XmlElement* stanza) { - ASSERT(msg->Name() == kQnP2pTransport); - for (const buzz::XmlElement* elem = msg->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - if (elem->Name() == kQnP2pCandidate) { - // Make sure this candidate is valid. - Candidate candidate; - if (!ParseCandidate(stanza, elem, &candidate)) - return false; - - ForwardChannelMessage(elem->Attr(buzz::QN_NAME), - new buzz::XmlElement(*elem)); - } - } - return true; -} - -bool P2PTransport::OnTransportError(const buzz::XmlElement* session_msg, - const buzz::XmlElement* error) { - ASSERT(error->Name().Namespace() == kNsP2pTransport); - if ((error->Name() == kQnP2pUnknownChannelName) - && error->HasAttr(buzz::QN_NAME)) { - std::string channel_name = error->Attr(buzz::QN_NAME); - if (HasChannel(channel_name)) { - SignalChannelGone(this, channel_name); - } - } - return true; -} - -void P2PTransport::OnTransportChannelMessages( - const std::vector<buzz::XmlElement*>& candidates) { - buzz::XmlElement* transport = - new buzz::XmlElement(kQnP2pTransport, true); - for (size_t i = 0; i < candidates.size(); ++i) - transport->AddElement(candidates[i]); - - std::vector<buzz::XmlElement*> elems; - elems.push_back(transport); - SignalTransportMessage(this, elems); -} - -bool P2PTransport::ParseCandidate(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - Candidate* candidate) { - // Check for all of the required attributes. - if (!elem->HasAttr(buzz::QN_NAME) || - !elem->HasAttr(QN_ADDRESS) || - !elem->HasAttr(QN_PORT) || - !elem->HasAttr(QN_USERNAME) || - !elem->HasAttr(QN_PREFERENCE) || - !elem->HasAttr(QN_PROTOCOL) || - !elem->HasAttr(QN_GENERATION)) { - return BadRequest(stanza, "candidate missing required attribute", NULL); - } - - // Make sure the channel named actually exists. - if (!HasChannel(elem->Attr(buzz::QN_NAME))) { - scoped_ptr<buzz::XmlElement> - extra_info(new buzz::XmlElement(kQnP2pUnknownChannelName)); - extra_info->AddAttr(buzz::QN_NAME, elem->Attr(buzz::QN_NAME)); - return BadRequest(stanza, "channel named in candidate does not exist", - extra_info.get()); - } - - // Parse the address given. - talk_base::SocketAddress address; - if (!ParseAddress(stanza, elem, &address)) - return false; - - candidate->set_name(elem->Attr(buzz::QN_NAME)); - candidate->set_address(address); - candidate->set_username(elem->Attr(QN_USERNAME)); - candidate->set_preference_str(elem->Attr(QN_PREFERENCE)); - candidate->set_protocol(elem->Attr(QN_PROTOCOL)); - candidate->set_generation_str(elem->Attr(QN_GENERATION)); - - // Check that the username is not too long and does not use any bad chars. - if (candidate->username().size() > kMaxUsernameSize) - return BadRequest(stanza, "candidate username is too long", NULL); - if (!IsBase64Encoded(candidate->username())) - return BadRequest(stanza, - "candidate username has non-base64 encoded characters", - NULL); - - // Look for the non-required attributes. - if (elem->HasAttr(QN_PASSWORD)) - candidate->set_password(elem->Attr(QN_PASSWORD)); - if (elem->HasAttr(buzz::QN_TYPE)) - candidate->set_type(elem->Attr(buzz::QN_TYPE)); - if (elem->HasAttr(QN_NETWORK)) - candidate->set_network_name(elem->Attr(QN_NETWORK)); - - return true; -} - -buzz::XmlElement* P2PTransport::TranslateCandidate(const Candidate& c) { - buzz::XmlElement* candidate = new buzz::XmlElement(kQnP2pCandidate); - candidate->SetAttr(buzz::QN_NAME, c.name()); - candidate->SetAttr(QN_ADDRESS, c.address().IPAsString()); - candidate->SetAttr(QN_PORT, c.address().PortAsString()); - candidate->SetAttr(QN_PREFERENCE, c.preference_str()); - candidate->SetAttr(QN_USERNAME, c.username()); - candidate->SetAttr(QN_PROTOCOL, c.protocol()); - candidate->SetAttr(QN_GENERATION, c.generation_str()); - if (c.password().size() > 0) - candidate->SetAttr(QN_PASSWORD, c.password()); - if (c.type().size() > 0) - candidate->SetAttr(buzz::QN_TYPE, c.type()); - if (c.network_name().size() > 0) - candidate->SetAttr(QN_NETWORK, c.network_name()); - return candidate; -} - -TransportChannelImpl* P2PTransport::CreateTransportChannel( - const std::string& name, const std::string &session_type) { - return new P2PTransportChannel( - name, session_type, this, session_manager()->port_allocator()); -} - -void P2PTransport::DestroyTransportChannel(TransportChannelImpl* channel) { - delete channel; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/p2ptransport.h b/third_party/libjingle/files/talk/p2p/base/p2ptransport.h deleted file mode 100644 index 2027d4a..0000000 --- a/third_party/libjingle/files/talk/p2p/base/p2ptransport.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_P2PTRANSPORT_H_ -#define _CRICKET_P2P_BASE_P2PTRANSPORT_H_ - -#include "talk/p2p/base/transport.h" - -namespace cricket { - -class Candidate; - -// Xml names used to name this transport and create our elements -extern const std::string kNsP2pTransport; -extern const buzz::QName kQnP2pTransport; -extern const buzz::QName kQnP2pCandidate; - -class P2PTransport: public Transport { - public: - P2PTransport(SessionManager* session_manager); - virtual ~P2PTransport(); - - // Implements negotiation of the P2P protocol. - virtual buzz::XmlElement* CreateTransportOffer(); - virtual buzz::XmlElement* CreateTransportAnswer(); - virtual bool OnTransportOffer(const buzz::XmlElement* elem); - virtual bool OnTransportAnswer(const buzz::XmlElement* elem); - - // Forwards each candidate message to the appropriate channel. - virtual bool OnTransportMessage(const buzz::XmlElement* msg, - const buzz::XmlElement* stanza); - virtual bool OnTransportError(const buzz::XmlElement* session_msg, - const buzz::XmlElement* error); - - protected: - // Creates and destroys P2PTransportChannel. - virtual TransportChannelImpl* CreateTransportChannel(const std::string& name, const std::string &session_type); - virtual void DestroyTransportChannel(TransportChannelImpl* channel); - - // Sends a given set of channel messages, which each describe a candidate, - // to the other client as a single transport message. - void OnTransportChannelMessages( - const std::vector<buzz::XmlElement*>& candidates); - - private: - // Attempts to parse the given XML into a candidate. Returns true if the - // XML is valid. If not, we will signal an error. - bool ParseCandidate(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - Candidate* candidate); - - // Generates a XML element describing the given candidate. - buzz::XmlElement* TranslateCandidate(const Candidate& c); - - friend class P2PTransportChannel; - - DISALLOW_EVIL_CONSTRUCTORS(P2PTransport); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_P2PTRANSPORT_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.cc b/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.cc deleted file mode 100644 index 717ae70..0000000 --- a/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.cc +++ /dev/null @@ -1,911 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif - -#include <errno.h> - -#include <iostream> - -#include "talk/base/common.h" -#include "talk/base/logging.h" -#include "talk/p2p/base/common.h" -#include "talk/p2p/base/p2ptransportchannel.h" - -namespace { - -// messages for queuing up work for ourselves -const uint32 MSG_SORT = 1; -const uint32 MSG_PING = 2; -const uint32 MSG_ALLOCATE = 3; - -// When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) -// for pinging. When the socket is writable, we will use only 1 Kbps because -// we don't want to degrade the quality on a modem. These numbers should work -// well on a 28.8K modem, which is the slowest connection on which the voice -// quality is reasonable at all. -static const uint32 PING_PACKET_SIZE = 60 * 8; -static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms -static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000;// 50ms - -// If there is a current writable connection, then we will also try hard to -// make sure it is pinged at this rate. -static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit - -// The minimum improvement in MOS that justifies a switch. -static const double kMinImprovement = 10; - -// Amount of time that we wait when *losing* writability before we try doing -// another allocation. -static const int kAllocateDelay = 1 * 1000; // 1 second - -// We will try creating a new allocator from scratch after a delay of this -// length without becoming writable (or timing out). -static const int kAllocatePeriod = 20 * 1000; // 20 seconds - -cricket::Port::CandidateOrigin GetOrigin(cricket::Port* port, - cricket::Port* origin_port) { - if (!origin_port) - return cricket::Port::ORIGIN_MESSAGE; - else if (port == origin_port) - return cricket::Port::ORIGIN_THIS_PORT; - else - return cricket::Port::ORIGIN_OTHER_PORT; -} - -// Compares two connections based only on static information about them. -int CompareConnectionCandidates(cricket::Connection* a, - cricket::Connection* b) { - // Combine local and remote preferences - ASSERT(a->local_candidate().preference() == a->port()->preference()); - ASSERT(b->local_candidate().preference() == b->port()->preference()); - double a_pref = a->local_candidate().preference() - * a->remote_candidate().preference(); - double b_pref = b->local_candidate().preference() - * b->remote_candidate().preference(); - - // Now check combined preferences. Lower values get sorted last. - if (a_pref > b_pref) - return 1; - if (a_pref < b_pref) - return -1; - - return 0; -} - -// Compare two connections based on their writability and static preferences. -int CompareConnections(cricket::Connection *a, cricket::Connection *b) { - // Sort based on write-state. Better states have lower values. - if (a->write_state() < b->write_state()) - return 1; - if (a->write_state() > b->write_state()) - return -1; - - // Compare the candidate information. - return CompareConnectionCandidates(a, b); -} - -// Wraps the comparison connection into a less than operator that puts higher -// priority writable connections first. -class ConnectionCompare { -public: - bool operator()(const cricket::Connection *ca, - const cricket::Connection *cb) { - cricket::Connection* a = const_cast<cricket::Connection*>(ca); - cricket::Connection* b = const_cast<cricket::Connection*>(cb); - - // Compare first on writability and static preferences. - int cmp = CompareConnections(a, b); - if (cmp > 0) - return true; - if (cmp < 0) - return false; - - // Otherwise, sort based on latency estimate. - return a->rtt() < b->rtt(); - - // Should we bother checking for the last connection that last received - // data? It would help rendezvous on the connection that is also receiving - // packets. - // - // TODO: Yes we should definitely do this. The TCP protocol gains - // efficiency by being used bidirectionally, as opposed to two separate - // unidirectional streams. This test should probably occur before - // comparison of local prefs (assuming combined prefs are the same). We - // need to be careful though, not to bounce back and forth with both sides - // trying to rendevous with the other. - } -}; - -// Determines whether we should switch between two connections, based first on -// static preferences and then (if those are equal) on latency estimates. -bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) { - if (a_conn == b_conn) - return false; - - if ((a_conn == NULL) || (b_conn == NULL)) // don't think the latter should happen - return true; - - int prefs_cmp = CompareConnections(a_conn, b_conn); - if (prefs_cmp < 0) - return true; - if (prefs_cmp > 0) - return false; - - return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; -} - -} // unnamed namespace - -namespace cricket { - -P2PTransportChannel::P2PTransportChannel(const std::string &name, - const std::string &session_type, - P2PTransport* transport, - PortAllocator *allocator) -: TransportChannelImpl(name, session_type), transport_(transport), - allocator_(allocator), worker_thread_(talk_base::Thread::Current()), - waiting_for_signaling_(false), error_(0), best_connection_(NULL), - pinging_started_(false), sort_dirty_(false), was_writable_(false), - was_timed_out_(true) { -} - -P2PTransportChannel::~P2PTransportChannel() { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - for (uint32 i = 0; i < allocator_sessions_.size(); ++i) - delete allocator_sessions_[i]; -} - -// Add the allocator session to our list so that we know which sessions -// are still active. -void P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) { - session->set_generation(static_cast<uint32>(allocator_sessions_.size())); - allocator_sessions_.push_back(session); - - // We now only want to apply new candidates that we receive to the ports - // created by this new session because these are replacing those of the - // previous sessions. - ports_.clear(); - - session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); - session->SignalCandidatesReady.connect( - this, &P2PTransportChannel::OnCandidatesReady); - session->GetInitialPorts(); - if (pinging_started_) - session->StartGetAllPorts(); -} - -// Go into the state of processing candidates, and running in general -void P2PTransportChannel::Connect() { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Kick off an allocator session - OnAllocate(); - - // Start pinging as the ports come in. - thread()->Post(this, MSG_PING); -} - -// Reset the socket, clear up any previous allocations and start over -void P2PTransportChannel::Reset() { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Get rid of all the old allocators. This should clean up everything. - for (uint32 i = 0; i < allocator_sessions_.size(); ++i) - delete allocator_sessions_[i]; - - allocator_sessions_.clear(); - ports_.clear(); - connections_.clear(); - best_connection_ = NULL; - - // Forget about all of the candidates we got before. - remote_candidates_.clear(); - - // Revert to the initial state. - set_readable(false); - set_writable(false); - - // Reinitialize the rest of our state. - waiting_for_signaling_ = false; - pinging_started_ = false; - sort_dirty_ = false; - was_writable_ = false; - was_timed_out_ = true; - - // If we allocated before, start a new one now. - if (transport_->connect_requested()) - OnAllocate(); - - // Start pinging as the ports come in. - thread()->Clear(this); - thread()->Post(this, MSG_PING); -} - -// A new port is available, attempt to make connections for it -void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, - Port* port) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Set in-effect options on the new port - for (OptionMap::const_iterator it = options_.begin(); - it != options_.end(); - ++it) { - int val = port->SetOption(it->first, it->second); - if (val < 0) { - LOG_J(LS_WARNING, port) << "SetOption(" << it->first - << ", " << it->second - << ") failed: " << port->GetError(); - } - } - - // Remember the ports and candidates, and signal that candidates are ready. - // The session will handle this, and send an initiate/accept/modify message - // if one is pending. - - ports_.push_back(port); - port->SignalUnknownAddress.connect( - this, &P2PTransportChannel::OnUnknownAddress); - port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); - - // Attempt to create a connection from this new port to all of the remote - // candidates that we were given so far. - - std::vector<RemoteCandidate>::iterator iter; - for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); - ++iter) - CreateConnection(port, *iter, iter->origin_port(), false); - - SortConnections(); -} - -// A new candidate is available, let listeners know -void P2PTransportChannel::OnCandidatesReady( - PortAllocatorSession *session, const std::vector<Candidate>& candidates) { - for (size_t i = 0; i < candidates.size(); ++i) { - buzz::XmlElement* msg = transport_->TranslateCandidate(candidates[i]); - SignalChannelMessage(this, msg); - } -} - -// Handle stun packets -void P2PTransportChannel::OnUnknownAddress( - Port *port, const talk_base::SocketAddress &address, StunMessage *stun_msg, - const std::string &remote_username) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Port has received a valid stun packet from an address that no Connection - // is currently available for. See if the remote user name is in the remote - // candidate list. If it isn't return error to the stun request. - - const Candidate *candidate = NULL; - std::vector<RemoteCandidate>::iterator it; - for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) { - if ((*it).username() == remote_username) { - candidate = &(*it); - break; - } - } - if (candidate == NULL) { - // Don't know about this username, the request is bogus - // This sometimes happens if a binding response comes in before the ACCEPT - // message. It is totally valid; the retry state machine will try again. - - port->SendBindingErrorResponse(stun_msg, address, - STUN_ERROR_STALE_CREDENTIALS, STUN_ERROR_REASON_STALE_CREDENTIALS); - delete stun_msg; - return; - } - - // Check for connectivity to this address. Create connections - // to this address across all local ports. First, add this as a new remote - // address - - Candidate new_remote_candidate = *candidate; - new_remote_candidate.set_address(address); - //new_remote_candidate.set_protocol(port->protocol()); - - // This remote username exists. Now create connections using this candidate, - // and resort - - if (CreateConnections(new_remote_candidate, port, true)) { - // Send the pinger a successful stun response. - port->SendBindingResponse(stun_msg, address); - - // Update the list of connections since we just added another. We do this - // after sending the response since it could (in principle) delete the - // connection in question. - SortConnections(); - } else { - // Hopefully this won't occur, because changing a destination address - // shouldn't cause a new connection to fail - ASSERT(false); - port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR, - STUN_ERROR_REASON_SERVER_ERROR); - } - - delete stun_msg; -} - -// We received a candidate from the other side, make connections so we -// can try to use these remote candidates with our local candidates. -void P2PTransportChannel::OnChannelMessage(const buzz::XmlElement* msg) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - Candidate remote_candidate; - bool valid = transport_->ParseCandidate(NULL, msg, &remote_candidate); - ASSERT(valid); - - // Create connections to this remote candidate. - CreateConnections(remote_candidate, NULL, false); - - // Resort the connections list, which may have new elements. - SortConnections(); -} - -// Creates connections from all of the ports that we care about to the given -// remote candidate. The return value is true iff we created a connection from -// the origin port. -bool P2PTransportChannel::CreateConnections(const Candidate &remote_candidate, - Port* origin_port, - bool readable) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Add a new connection for this candidate to every port that allows such a - // connection (i.e., if they have compatible protocols) and that does not - // already have a connection to an equivalent candidate. We must be careful - // to make sure that the origin port is included, even if it was pruned, - // since that may be the only port that can create this connection. - - bool created = false; - - std::vector<Port *>::reverse_iterator it; - for (it = ports_.rbegin(); it != ports_.rend(); ++it) { - if (CreateConnection(*it, remote_candidate, origin_port, readable)) { - if (*it == origin_port) - created = true; - } - } - - if ((origin_port != NULL) && - find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { - if (CreateConnection(origin_port, remote_candidate, origin_port, readable)) - created = true; - } - - // Remember this remote candidate so that we can add it to future ports. - RememberRemoteCandidate(remote_candidate, origin_port); - - return created; -} - -// Setup a connection object for the local and remote candidate combination. -// And then listen to connection object for changes. -bool P2PTransportChannel::CreateConnection(Port* port, - const Candidate& remote_candidate, - Port* origin_port, - bool readable) { - // Look for an existing connection with this remote address. If one is not - // found, then we can create a new connection for this address. - Connection* connection = port->GetConnection(remote_candidate.address()); - if (connection != NULL) { - // It is not legal to try to change any of the parameters of an existing - // connection; however, the other side can send a duplicate candidate. - if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { - LOG(INFO) << "Attempt to change a remote candidate"; - return false; - } - } else { - Port::CandidateOrigin origin = GetOrigin(port, origin_port); - connection = port->CreateConnection(remote_candidate, origin); - if (!connection) - return false; - - connections_.push_back(connection); - connection->SignalReadPacket.connect( - this, &P2PTransportChannel::OnReadPacket); - connection->SignalStateChange.connect( - this, &P2PTransportChannel::OnConnectionStateChange); - connection->SignalDestroyed.connect( - this, &P2PTransportChannel::OnConnectionDestroyed); - } - - // If we are readable, it is because we are creating this in response to a - // ping from the other side. This will cause the state to become readable. - if (readable) - connection->ReceivedPing(); - - return true; -} - -// Maintain our remote candidate list, adding this new remote one. -void P2PTransportChannel::RememberRemoteCandidate( - const Candidate& remote_candidate, Port* origin_port) { - // Remove any candidates whose generation is older than this one. The - // presence of a new generation indicates that the old ones are not useful. - uint32 i = 0; - while (i < remote_candidates_.size()) { - if (remote_candidates_[i].generation() < remote_candidate.generation()) { - LOG(INFO) << "Pruning candidate from old generation: " - << remote_candidates_[i].address().ToString(); - remote_candidates_.erase(remote_candidates_.begin() + i); - } else { - i += 1; - } - } - - // Make sure this candidate is not a duplicate. - for (uint32 i = 0; i < remote_candidates_.size(); ++i) { - if (remote_candidates_[i].IsEquivalent(remote_candidate)) { - LOG(INFO) << "Duplicate candidate: " - << remote_candidate.address().ToString(); - return; - } - } - - // Try this candidate for all future ports. - remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port)); - - // We have some candidates from the other side, we are now serious about - // this connection. Let's do the StartGetAllPorts thing. - if (!pinging_started_) { - pinging_started_ = true; - for (size_t i = 0; i < allocator_sessions_.size(); ++i) { - if (!allocator_sessions_[i]->IsGettingAllPorts()) - allocator_sessions_[i]->StartGetAllPorts(); - } - } -} - -// Send data to the other side, using our best connection -int P2PTransportChannel::SendPacket(const char *data, size_t len) { - // This can get called on any thread that is convenient to write from! - if (best_connection_ == NULL) { - error_ = EWOULDBLOCK; - return SOCKET_ERROR; - } - int sent = best_connection_->Send(data, len); - if (sent <= 0) { - ASSERT(sent < 0); - error_ = best_connection_->GetError(); - } - return sent; -} - -// Monitor connection states -void P2PTransportChannel::UpdateConnectionStates() { - uint32 now = talk_base::Time(); - - // We need to copy the list of connections since some may delete themselves - // when we call UpdateState. - for (uint32 i = 0; i < connections_.size(); ++i) - connections_[i]->UpdateState(now); -} - -// Prepare for best candidate sorting -void P2PTransportChannel::RequestSort() { - if (!sort_dirty_) { - worker_thread_->Post(this, MSG_SORT); - sort_dirty_ = true; - } -} - -// Sort the available connections to find the best one. We also monitor -// the number of available connections and the current state so that we -// can possibly kick off more allocators (for more connections). -void P2PTransportChannel::SortConnections() { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Make sure the connection states are up-to-date since this affects how they - // will be sorted. - UpdateConnectionStates(); - - // Any changes after this point will require a re-sort. - sort_dirty_ = false; - - // Get a list of the networks that we are using. - std::set<talk_base::Network*> networks; - for (uint32 i = 0; i < connections_.size(); ++i) - networks.insert(connections_[i]->port()->network()); - - // Find the best alternative connection by sorting. It is important to note - // that amongst equal preference, writable connections, this will choose the - // one whose estimated latency is lowest. So it is the only one that we - // need to consider switching to. - - ConnectionCompare cmp; - std::stable_sort(connections_.begin(), connections_.end(), cmp); - Connection* top_connection = NULL; - if (connections_.size() > 0) - top_connection = connections_[0]; - - // If necessary, switch to the new choice. - if (ShouldSwitch(best_connection_, top_connection)) - SwitchBestConnectionTo(top_connection); - - // We can prune any connection for which there is a writable connection on - // the same network with better or equal prefences. We leave those with - // better preference just in case they become writable later (at which point, - // we would prune out the current best connection). We leave connections on - // other networks because they may not be using the same resources and they - // may represent very distinct paths over which we can switch. - std::set<talk_base::Network*>::iterator network; - for (network = networks.begin(); network != networks.end(); ++network) { - Connection* primier = GetBestConnectionOnNetwork(*network); - if (!primier || (primier->write_state() != Connection::STATE_WRITABLE)) - continue; - - for (uint32 i = 0; i < connections_.size(); ++i) { - if ((connections_[i] != primier) && - (connections_[i]->port()->network() == *network) && - (CompareConnectionCandidates(primier, connections_[i]) >= 0)) { - connections_[i]->Prune(); - } - } - } - - // Count the number of connections in the various states. - - int writable = 0; - int write_connect = 0; - int write_timeout = 0; - - for (uint32 i = 0; i < connections_.size(); ++i) { - switch (connections_[i]->write_state()) { - case Connection::STATE_WRITABLE: - ++writable; - break; - case Connection::STATE_WRITE_CONNECT: - ++write_connect; - break; - case Connection::STATE_WRITE_TIMEOUT: - ++write_timeout; - break; - default: - ASSERT(false); - } - } - - if (writable > 0) { - HandleWritable(); - } else if (write_connect > 0) { - HandleNotWritable(); - } else { - HandleAllTimedOut(); - } - - // Update the state of this channel. This method is called whenever the - // state of any connection changes, so this is a good place to do this. - UpdateChannelState(); - - // Notify of connection state change - SignalConnectionMonitor(this); -} - -// Track the best connection, and let listeners know -void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { - // Note: the previous best_connection_ may be destroyed by now, so don't - // use it. - best_connection_ = conn; - if (best_connection_) { - LOG_J(LS_VERBOSE, this) << "New best connection: " << conn->ToString(); - SignalRouteChange(this, best_connection_->remote_candidate().address()); - } -} - -void P2PTransportChannel::UpdateChannelState() { - // The Handle* functions already set the writable state. We'll just double- - // check it here. - bool writable = - (best_connection_ != NULL) && - (best_connection_->write_state() == Connection::STATE_WRITABLE); - ASSERT(writable == this->writable()); - - bool readable = false; - for (uint32 i = 0; i < connections_.size(); ++i) { - if (connections_[i]->read_state() == Connection::STATE_READABLE) - readable = true; - } - set_readable(readable); -} - -// We checked the status of our connections and we had at least one that -// was writable, go into the writable state. -void P2PTransportChannel::HandleWritable() { - // - // One or more connections writable! - // - if (!writable()) { - for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { - if (allocator_sessions_[i]->IsGettingAllPorts()) { - allocator_sessions_[i]->StopGetAllPorts(); - } - } - - // Stop further allocations. - thread()->Clear(this, MSG_ALLOCATE); - } - - // We're writable, obviously we aren't timed out - was_writable_ = true; - was_timed_out_ = false; - set_writable(true); -} - -// We checked the status of our connections and we didn't have any that -// were writable, go into the connecting state (kick off a new allocator -// session). -void P2PTransportChannel::HandleNotWritable() { - // - // No connections are writable but not timed out! - // - if (was_writable_) { - // If we were writable, let's kick off an allocator session immediately - was_writable_ = false; - OnAllocate(); - } - - // We were connecting, obviously not ALL timed out. - was_timed_out_ = false; - set_writable(false); -} - -// We checked the status of our connections and not only weren't they writable -// but they were also timed out, we really need a new allocator. -void P2PTransportChannel::HandleAllTimedOut() { - // - // No connections... all are timed out! - // - if (!was_timed_out_) { - // We weren't timed out before, so kick off an allocator now (we'll still - // be in the fully timed out state until the allocator actually gives back - // new ports) - OnAllocate(); - } - - // NOTE: we start was_timed_out_ in the true state so that we don't get - // another allocator created WHILE we are in the process of building up - // our first allocator. - was_timed_out_ = true; - was_writable_ = false; - set_writable(false); -} - -// If we have a best connection, return it, otherwise return top one in the -// list (later we will mark it best). -Connection* P2PTransportChannel::GetBestConnectionOnNetwork( - talk_base::Network* network) { - // If the best connection is on this network, then it wins. - if (best_connection_ && (best_connection_->port()->network() == network)) - return best_connection_; - - // Otherwise, we return the top-most in sorted order. - for (uint32 i = 0; i < connections_.size(); ++i) { - if (connections_[i]->port()->network() == network) - return connections_[i]; - } - - return NULL; -} - -// Handle any queued up requests -void P2PTransportChannel::OnMessage(talk_base::Message *pmsg) { - if (pmsg->message_id == MSG_SORT) - OnSort(); - else if (pmsg->message_id == MSG_PING) - OnPing(); - else if (pmsg->message_id == MSG_ALLOCATE) - OnAllocate(); - else - ASSERT(false); -} - -// Handle queued up sort request -void P2PTransportChannel::OnSort() { - // Resort the connections based on the new statistics. - SortConnections(); -} - -// Handle queued up ping request -void P2PTransportChannel::OnPing() { - // Make sure the states of the connections are up-to-date (since this affects - // which ones are pingable). - UpdateConnectionStates(); - - // Find the oldest pingable connection and have it do a ping. - Connection* conn = FindNextPingableConnection(); - if (conn) - conn->Ping(talk_base::Time()); - - // Post ourselves a message to perform the next ping. - uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; - thread()->PostDelayed(delay, this, MSG_PING); -} - -// Is the connection in a state for us to even consider pinging the other side? -bool P2PTransportChannel::IsPingable(Connection* conn) { - // An unconnected connection cannot be written to at all, so pinging is out - // of the question. - if (!conn->connected()) - return false; - - if (writable()) { - // If we are writable, then we only want to ping connections that could be - // better than this one, i.e., the ones that were not pruned. - return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT); - } else { - // If we are not writable, then we need to try everything that might work. - // This includes both connections that do not have write timeout as well as - // ones that do not have read timeout. A connection could be readable but - // be in write-timeout if we pruned it before. Since the other side is - // still pinging it, it very well might still work. - return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) || - (conn->read_state() != Connection::STATE_READ_TIMEOUT); - } -} - -// Returns the next pingable connection to ping. This will be the oldest -// pingable connection unless we have a writable connection that is past the -// maximum acceptable ping delay. -Connection* P2PTransportChannel::FindNextPingableConnection() { - uint32 now = talk_base::Time(); - if (best_connection_ && - (best_connection_->write_state() == Connection::STATE_WRITABLE) && - (best_connection_->last_ping_sent() - + MAX_CURRENT_WRITABLE_DELAY <= now)) { - return best_connection_; - } - - Connection* oldest_conn = NULL; - uint32 oldest_time = 0xFFFFFFFF; - for (uint32 i = 0; i < connections_.size(); ++i) { - if (IsPingable(connections_[i])) { - if (connections_[i]->last_ping_sent() < oldest_time) { - oldest_time = connections_[i]->last_ping_sent(); - oldest_conn = connections_[i]; - } - } - } - return oldest_conn; -} - -// return the number of "pingable" connections -uint32 P2PTransportChannel::NumPingableConnections() { - uint32 count = 0; - for (uint32 i = 0; i < connections_.size(); ++i) { - if (IsPingable(connections_[i])) - count += 1; - } - return count; -} - -// When a connection's state changes, we need to figure out who to use as -// the best connection again. It could have become usable, or become unusable. -void P2PTransportChannel::OnConnectionStateChange(Connection *connection) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // We have to unroll the stack before doing this because we may be changing - // the state of connections while sorting. - RequestSort(); -} - -// When a connection is removed, edit it out, and then update our best -// connection. -void P2PTransportChannel::OnConnectionDestroyed(Connection *connection) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Note: the previous best_connection_ may be destroyed by now, so don't - // use it. - - // Remove this connection from the list. - std::vector<Connection*>::iterator iter = - find(connections_.begin(), connections_.end(), connection); - ASSERT(iter != connections_.end()); - connections_.erase(iter); - - LOG_J(LS_INFO, this) << "Removed connection (" - << static_cast<int>(connections_.size()) << " remaining)"; - - // If this is currently the best connection, then we need to pick a new one. - // The call to SortConnections will pick a new one. It looks at the current - // best connection in order to avoid switching between fairly similar ones. - // Since this connection is no longer an option, we can just set best to NULL - // and re-choose a best assuming that there was no best connection. - if (best_connection_ == connection) { - SwitchBestConnectionTo(NULL); - RequestSort(); - } -} - -// When a port is destroyed remove it from our list of ports to use for -// connection attempts. -void P2PTransportChannel::OnPortDestroyed(Port* port) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Remove this port from the list (if we didn't drop it already). - std::vector<Port*>::iterator iter = find(ports_.begin(), ports_.end(), port); - if (iter != ports_.end()) - ports_.erase(iter); - - LOG(INFO) << "Removed port from p2p socket: " - << static_cast<int>(ports_.size()) << " remaining"; -} - -// We data is available, let listeners know -void P2PTransportChannel::OnReadPacket(Connection *connection, - const char *data, size_t len) { - ASSERT(worker_thread_ == talk_base::Thread::Current()); - - // Let the client know of an incoming packet - - SignalReadPacket(this, data, len); -} - -// Set options on ourselves is simply setting options on all of our available -// port objects. -int P2PTransportChannel::SetOption(talk_base::Socket::Option opt, int value) { - OptionMap::iterator it = options_.find(opt); - if (it == options_.end()) { - options_.insert(std::make_pair(opt, value)); - } else if (it->second == value) { - return 0; - } else { - it->second = value; - } - - for (uint32 i = 0; i < ports_.size(); ++i) { - int val = ports_[i]->SetOption(opt, value); - if (val < 0) { - // Because this also occurs deferred, probably no point in reporting an - // error - LOG(WARNING) << "SetOption(" << opt << ", " << value << ") failed: " - << ports_[i]->GetError(); - } - } - return 0; -} - -// Time for a new allocator, lets make sure we have a signalling channel -// to communicate candidates through first. -void P2PTransportChannel::OnAllocate() { - waiting_for_signaling_ = true; - SignalRequestSignaling(); -} - -// When the signalling channel is ready, we can really kick off the allocator -void P2PTransportChannel::OnSignalingReady() { - if (waiting_for_signaling_) { - waiting_for_signaling_ = false; - AddAllocatorSession(allocator_->CreateSession(name(), session_type())); - thread()->PostDelayed(kAllocatePeriod, this, MSG_ALLOCATE); - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.h b/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.h deleted file mode 100644 index bea1537..0000000 --- a/third_party/libjingle/files/talk/p2p/base/p2ptransportchannel.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// P2PTransportChannel wraps up the state management of the connection between -// two P2P clients. Clients have candidate ports for connecting, and -// connections which are combinations of candidates from each end (Alice and -// Bob each have candidates, one candidate from Alice and one candidate from -// Bob are used to make a connection, repeat to make many connections). -// -// When all of the available connections become invalid (non-writable), we -// kick off a process of determining more candidates and more connections. -// -#ifndef _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_ -#define _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_ - -#include <vector> -#include <string> -#include "talk/base/sigslot.h" -#include "talk/p2p/base/candidate.h" -#include "talk/p2p/base/port.h" -#include "talk/p2p/base/portallocator.h" -#include "talk/p2p/base/transport.h" -#include "talk/p2p/base/transportchannelimpl.h" -#include "talk/p2p/base/p2ptransport.h" - -namespace cricket { - -// Adds the port on which the candidate originated. -class RemoteCandidate : public Candidate { - public: - RemoteCandidate(const Candidate& c, Port* origin_port) - : Candidate(c), origin_port_(origin_port) {} - - Port* origin_port() { return origin_port_; } - - private: - Port* origin_port_; -}; - -// P2PTransportChannel manages the candidates and connection process to keep -// two P2P clients connected to each other. -class P2PTransportChannel : public TransportChannelImpl, - public talk_base::MessageHandler { - public: - P2PTransportChannel(const std::string &name, - const std::string &session_type, - P2PTransport* transport, - PortAllocator *allocator); - virtual ~P2PTransportChannel(); - - // From TransportChannelImpl: - virtual Transport* GetTransport() { return transport_; } - virtual void Connect(); - virtual void Reset(); - virtual void OnSignalingReady(); - virtual void OnChannelMessage(const buzz::XmlElement* msg); - - // From TransportChannel: - virtual int SendPacket(const char *data, size_t len); - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError() { return error_; } - - // These are used by the connection monitor. - sigslot::signal1<P2PTransportChannel*> SignalConnectionMonitor; - const std::vector<Connection *>& connections() const { return connections_; } - Connection* best_connection() const { return best_connection_; } - - // Handler for internal messages. - virtual void OnMessage(talk_base::Message *pmsg); - - private: - void UpdateConnectionStates(); - void RequestSort(); - void SortConnections(); - void SwitchBestConnectionTo(Connection* conn); - void UpdateChannelState(); - void HandleWritable(); - void HandleNotWritable(); - void HandleAllTimedOut(); - Connection* GetBestConnectionOnNetwork(talk_base::Network* network); - bool CreateConnections(const Candidate &remote_candidate, Port* origin_port, - bool readable); - bool CreateConnection(Port* port, const Candidate& remote_candidate, - Port* origin_port, bool readable); - void RememberRemoteCandidate(const Candidate& remote_candidate, - Port* origin_port); - void OnUnknownAddress(Port *port, const talk_base::SocketAddress &addr, - StunMessage *stun_msg, - const std::string &remote_username); - void OnPortReady(PortAllocatorSession *session, Port* port); - void OnCandidatesReady(PortAllocatorSession *session, - const std::vector<Candidate>& candidates); - void OnConnectionStateChange(Connection *connection); - void OnConnectionDestroyed(Connection *connection); - void OnPortDestroyed(Port* port); - void OnAllocate(); - void OnReadPacket(Connection *connection, const char *data, size_t len); - void OnSort(); - void OnPing(); - bool IsPingable(Connection* conn); - Connection* FindNextPingableConnection(); - uint32 NumPingableConnections(); - PortAllocatorSession* allocator_session() { - return allocator_sessions_.back(); - } - void AddAllocatorSession(PortAllocatorSession* session); - - talk_base::Thread* thread() const { return worker_thread_; } - - P2PTransport* transport_; - PortAllocator *allocator_; - talk_base::Thread *worker_thread_; - bool waiting_for_signaling_; - int error_; - std::vector<PortAllocatorSession*> allocator_sessions_; - std::vector<Port *> ports_; - std::vector<Connection *> connections_; - Connection *best_connection_; - std::vector<RemoteCandidate> remote_candidates_; - bool pinging_started_; // indicates whether StartGetAllCandidates has been called - bool sort_dirty_; // indicates whether another sort is needed right now - bool was_writable_; - bool was_timed_out_; - typedef std::map<talk_base::Socket::Option, int> OptionMap; - OptionMap options_; - - DISALLOW_EVIL_CONSTRUCTORS(P2PTransportChannel); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/port.cc b/third_party/libjingle/files/talk/p2p/base/port.cc deleted file mode 100644 index 2411e5f..0000000 --- a/third_party/libjingle/files/talk/p2p/base/port.cc +++ /dev/null @@ -1,927 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif - -#include <errno.h> - -#include <algorithm> -#include <cstring> -#include <iostream> -#include <vector> - -#include "talk/base/asyncudpsocket.h" -#include "talk/base/asynctcpsocket.h" -#include "talk/base/helpers.h" -#include "talk/base/logging.h" -#include "talk/base/scoped_ptr.h" -#include "talk/base/socketadapters.h" -#include "talk/p2p/base/common.h" -#include "talk/p2p/base/port.h" - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std { - using ::memcmp; -} -#endif - -namespace { - -// The length of time we wait before timing out readability on a connection. -const uint32 CONNECTION_READ_TIMEOUT = 30 * 1000; // 30 seconds - -// The length of time we wait before timing out writability on a connection. -const uint32 CONNECTION_WRITE_TIMEOUT = 15 * 1000; // 15 seconds - -// The length of time we wait before we become unwritable. -const uint32 CONNECTION_WRITE_CONNECT_TIMEOUT = 5 * 1000; // 5 seconds - -// The number of pings that must fail to respond before we become unwritable. -const uint32 CONNECTION_WRITE_CONNECT_FAILURES = 5; - -// This is the length of time that we wait for a ping response to come back. -const int CONNECTION_RESPONSE_TIMEOUT = 5 * 1000; // 5 seconds - -// Determines whether we have seen at least the given maximum number of -// pings fail to have a response. -inline bool TooManyFailures( - const std::vector<uint32>& pings_since_last_response, - uint32 maximum_failures, - uint32 rtt_estimate, - uint32 now) { - - // If we haven't sent that many pings, then we can't have failed that many. - if (pings_since_last_response.size() < maximum_failures) - return false; - - // Check if the window in which we would expect a response to the ping has - // already elapsed. - return pings_since_last_response[maximum_failures - 1] + rtt_estimate < now; -} - -// Determines whether we have gone too long without seeing any response. -inline bool TooLongWithoutResponse( - const std::vector<uint32>& pings_since_last_response, - uint32 maximum_time, - uint32 now) { - - if (pings_since_last_response.size() == 0) - return false; - - return pings_since_last_response[0] + maximum_time < now; -} - -// We will restrict RTT estimates (when used for determining state) to be -// within a reasonable range. -const uint32 MINIMUM_RTT = 100; // 0.1 seconds -const uint32 MAXIMUM_RTT = 3000; // 3 seconds - -// When we don't have any RTT data, we have to pick something reasonable. We -// use a large value just in case the connection is really slow. -const uint32 DEFAULT_RTT = MAXIMUM_RTT; - -// Computes our estimate of the RTT given the current estimate and the number -// of data points on which it is based. -inline uint32 ConservativeRTTEstimate(uint32 rtt, uint32 rtt_data_points) { - if (rtt_data_points == 0) - return DEFAULT_RTT; - else - return talk_base::_max(MINIMUM_RTT, talk_base::_min(MAXIMUM_RTT, 2 * rtt)); -} - -// Weighting of the old rtt value to new data. -const int RTT_RATIO = 3; // 3 : 1 - -// The delay before we begin checking if this port is useless. -const int kPortTimeoutDelay = 30 * 1000; // 30 seconds - -const uint32 MSG_CHECKTIMEOUT = 1; -const uint32 MSG_DELETE = 1; - -} - -namespace cricket { - -static const char * const PROTO_NAMES[PROTO_LAST+1] = { "udp", "tcp", "ssltcp" }; - -const char * ProtoToString(ProtocolType proto) { - return PROTO_NAMES[proto]; -} - -bool StringToProto(const char * value, ProtocolType& proto) { - for (size_t i=0; i<=PROTO_LAST; ++i) { - if (strcmp(PROTO_NAMES[i], value) == 0) { - proto = static_cast<ProtocolType>(i); - return true; - } - } - return false; -} - -std::string Port::agent_; -talk_base::ProxyInfo Port::proxy_; - -Port::Port(talk_base::Thread* thread, const std::string& type, - talk_base::SocketFactory* factory, talk_base::Network* network) - : thread_(thread), factory_(factory), type_(type), network_(network), - preference_(-1), lifetime_(LT_PRESTART), enable_port_packets_(false) { - - if (factory_ == NULL) - factory_ = thread_->socketserver(); - - set_username_fragment(CreateRandomString(16)); - set_password(CreateRandomString(16)); -} - -Port::~Port() { - // Delete all of the remaining connections. We copy the list up front - // because each deletion will cause it to be modified. - - std::vector<Connection*> list; - - AddressMap::iterator iter = connections_.begin(); - while (iter != connections_.end()) { - list.push_back(iter->second); - ++iter; - } - - for (uint32 i = 0; i < list.size(); i++) - delete list[i]; -} - -Connection* Port::GetConnection(const talk_base::SocketAddress& remote_addr) { - AddressMap::const_iterator iter = connections_.find(remote_addr); - if (iter != connections_.end()) - return iter->second; - else - return NULL; -} - -void Port::AddAddress(const talk_base::SocketAddress& address, - const std::string& protocol, - bool final) { - Candidate c; - c.set_name(name_); - c.set_type(type_); - c.set_protocol(protocol); - c.set_address(address); - c.set_preference(preference_); - c.set_username(username_frag_); - c.set_password(password_); - c.set_network_name(network_->name()); - c.set_generation(generation_); - candidates_.push_back(c); - - if (final) - SignalAddressReady(this); -} - -void Port::AddConnection(Connection* conn) { - connections_[conn->remote_candidate().address()] = conn; - conn->SignalDestroyed.connect(this, &Port::OnConnectionDestroyed); - SignalConnectionCreated(this, conn); -} - -void Port::OnReadPacket( - const char* data, size_t size, const talk_base::SocketAddress& addr) { - // If the user has enabled port packets, just hand this over. - if (enable_port_packets_) { - SignalReadPacket(this, data, size, addr); - return; - } - - // If this is an authenticated STUN request, then signal unknown address and - // send back a proper binding response. - StunMessage* msg; - std::string remote_username; - if (!GetStunMessage(data, size, addr, msg, remote_username)) { - LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address (" - << addr.ToString() << ")"; - } else if (!msg) { - // STUN message handled already - } else if (msg->type() == STUN_BINDING_REQUEST) { - SignalUnknownAddress(this, addr, msg, remote_username); - } else { - LOG_J(LS_ERROR, this) << "Received unexpected STUN message type (" - << msg->type() << ") from unknown address (" - << addr.ToString() << ")"; - delete msg; - } -} - -void Port::SendBindingRequest(Connection* conn) { - - // Construct the request message. - - StunMessage request; - request.SetType(STUN_BINDING_REQUEST); - request.SetTransactionID(CreateRandomString(16)); - - StunByteStringAttribute* username_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - std::string username = conn->remote_candidate().username(); - username.append(username_frag_); - username_attr->CopyBytes(username.c_str(), (uint16)username.size()); - request.AddAttribute(username_attr); - - // Send the request message. - // NOTE: If we wanted to, this is where we would add the HMAC. - talk_base::ByteBuffer buf; - request.Write(&buf); - SendTo(buf.Data(), buf.Length(), conn->remote_candidate().address(), false); -} - -bool Port::GetStunMessage(const char* data, size_t size, - const talk_base::SocketAddress& addr, - StunMessage *& msg, std::string& remote_username) { - // NOTE: This could clearly be optimized to avoid allocating any memory. - // However, at the data rates we'll be looking at on the client side, - // this probably isn't worth worrying about. - - msg = 0; - - // Parse the request message. If the packet is not a complete and correct - // STUN message, then ignore it. - scoped_ptr<StunMessage> stun_msg(new StunMessage()); - talk_base::ByteBuffer buf(data, size); - if (!stun_msg->Read(&buf) || (buf.Length() > 0)) { - return false; - } - - // The packet must include a username that either begins or ends with our - // fragment. It should begin with our fragment if it is a request and it - // should end with our fragment if it is a response. - const StunByteStringAttribute* username_attr = - stun_msg->GetByteString(STUN_ATTR_USERNAME); - - int remote_frag_len = (username_attr ? username_attr->length() : 0); - remote_frag_len -= static_cast<int>(username_frag_.size()); - - if (stun_msg->type() == STUN_BINDING_REQUEST) { - if ((remote_frag_len < 0) - || (std::memcmp(username_attr->bytes(), - username_frag_.c_str(), username_frag_.size()) != 0)) { - LOG_J(LS_ERROR, this) << "Received STUN request with bad username"; - SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST, - STUN_ERROR_REASON_BAD_REQUEST); - return true; - } - - remote_username.assign(username_attr->bytes() + username_frag_.size(), - username_attr->bytes() + username_attr->length()); - } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) - || (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) { - if ((remote_frag_len < 0) - || (std::memcmp(username_attr->bytes() + remote_frag_len, - username_frag_.c_str(), username_frag_.size()) != 0)) { - LOG_J(LS_ERROR, this) << "Received STUN response with bad username"; - // Do not send error response to a response - return true; - } - - remote_username.assign(username_attr->bytes(), - username_attr->bytes() + remote_frag_len); - - if (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE) { - if (const StunErrorCodeAttribute* error_code = stun_msg->GetErrorCode()) { - LOG_J(LS_ERROR, this) << "Received STUN binding error:" - << " class=" << error_code->error_class() - << " number=" << error_code->number() - << " reason='" << error_code->reason() << "'"; - // Return message to allow error-specific processing - } else { - LOG_J(LS_ERROR, this) - << "Received STUN error response with no error code"; - // Drop corrupt message - return true; - } - } - } else { - LOG_J(LS_ERROR, this) << "Received STUN packet with invalid type (" - << stun_msg->type() << ")"; - return true; - } - - // Return the STUN message found. - msg = stun_msg.release(); - return true; -} - -void Port::SendBindingResponse( - StunMessage* request, const talk_base::SocketAddress& addr) { - - assert(request->type() == STUN_BINDING_REQUEST); - - // Retrieve the username from the request. - const StunByteStringAttribute* username_attr = - request->GetByteString(STUN_ATTR_USERNAME); - assert(username_attr); - - // Fill in the response message. - - StunMessage response; - response.SetType(STUN_BINDING_RESPONSE); - response.SetTransactionID(request->transaction_id()); - - StunByteStringAttribute* username2_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username2_attr->CopyBytes(username_attr->bytes(), username_attr->length()); - response.AddAttribute(username2_attr); - - StunAddressAttribute* addr_attr = - StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); - addr_attr->SetFamily(1); - addr_attr->SetPort(addr.port()); - addr_attr->SetIP(addr.ip()); - response.AddAttribute(addr_attr); - - // Send the response message. - // NOTE: If we wanted to, this is where we would add the HMAC. - talk_base::ByteBuffer buf; - response.Write(&buf); - SendTo(buf.Data(), buf.Length(), addr, false); - - // The fact that we received a successful request means that this connection - // (if one exists) should now be readable. - Connection* conn = GetConnection(addr); - assert(conn); - if (conn) - conn->ReceivedPing(); -} - -void Port::SendBindingErrorResponse( - StunMessage* request, const talk_base::SocketAddress& addr, int error_code, - const std::string& reason) { - - assert(request->type() == STUN_BINDING_REQUEST); - - // Retrieve the username from the request. If it didn't have one, we - // shouldn't be responding at all. - const StunByteStringAttribute* username_attr = - request->GetByteString(STUN_ATTR_USERNAME); - assert(username_attr); - - // Fill in the response message. - - StunMessage response; - response.SetType(STUN_BINDING_ERROR_RESPONSE); - response.SetTransactionID(request->transaction_id()); - - StunByteStringAttribute* username2_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username2_attr->CopyBytes(username_attr->bytes(), username_attr->length()); - response.AddAttribute(username2_attr); - - StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode(); - error_attr->SetErrorCode(error_code); - error_attr->SetReason(reason); - response.AddAttribute(error_attr); - - // Send the response message. - // NOTE: If we wanted to, this is where we would add the HMAC. - talk_base::ByteBuffer buf; - response.Write(&buf); - SendTo(buf.Data(), buf.Length(), addr, false); -} - -talk_base::AsyncPacketSocket* Port::CreatePacketSocket(ProtocolType proto) { - if (proto == PROTO_UDP) { - return new talk_base::AsyncUDPSocket( - factory_->CreateAsyncSocket(SOCK_DGRAM)); - } else if ((proto == PROTO_TCP) || (proto == PROTO_SSLTCP)) { - talk_base::AsyncSocket * socket = factory_->CreateAsyncSocket(SOCK_STREAM); - switch (proxy().type) { - case talk_base::PROXY_NONE: - break; - case talk_base::PROXY_SOCKS5: - socket = new talk_base::AsyncSocksProxySocket( - socket, proxy().address, proxy().username, proxy().password); - break; - case talk_base::PROXY_HTTPS: - default: - socket = new talk_base::AsyncHttpsProxySocket( - socket, user_agent(), proxy().address, proxy().username, - proxy().password); - break; - } - if (proto == PROTO_SSLTCP) { - socket = new talk_base::AsyncSSLSocket(socket); - } - return new talk_base::AsyncTCPSocket(socket); - } else { - LOG_J(LS_INFO, this) << "Unknown protocol (" << proto << ")"; - return 0; - } -} - -void Port::OnMessage(talk_base::Message *pmsg) { - assert(pmsg->message_id == MSG_CHECKTIMEOUT); - assert(lifetime_ == LT_PRETIMEOUT); - lifetime_ = LT_POSTTIMEOUT; - CheckTimeout(); -} - -std::string Port::ToString() const { - std::stringstream ss; - ss << "Port[" << name_ << ":" << type_ << ":" << network_->ToString() << "]"; - return ss.str(); -} - -void Port::EnablePortPackets() { - enable_port_packets_ = true; -} - -void Port::Start() { - // The port sticks around for a minimum lifetime, after which - // we destroy it when it drops to zero connections. - if (lifetime_ == LT_PRESTART) { - lifetime_ = LT_PRETIMEOUT; - thread_->PostDelayed(kPortTimeoutDelay, this, MSG_CHECKTIMEOUT); - } else { - LOG_J(LS_WARNING, this) << "Port restart attempted"; - } -} - -void Port::OnConnectionDestroyed(Connection* conn) { - AddressMap::iterator iter = connections_.find(conn->remote_candidate().address()); - assert(iter != connections_.end()); - connections_.erase(iter); - - CheckTimeout(); -} - -void Port::Destroy() { - assert(connections_.empty()); - LOG_J(LS_INFO, this) << "Port deleted"; - SignalDestroyed(this); - delete this; -} - -void Port::CheckTimeout() { - // If this port has no connections, then there's no reason to keep it around. - // When the connections time out (both read and write), they will delete - // themselves, so if we have any connections, they are either readable or - // writable (or still connecting). - if ((lifetime_ == LT_POSTTIMEOUT) && connections_.empty()) { - Destroy(); - } -} - -// A ConnectionRequest is a simple STUN ping used to determine writability. -class ConnectionRequest : public StunRequest { -public: - ConnectionRequest(Connection* connection) : connection_(connection) { - } - - virtual ~ConnectionRequest() { - } - - virtual void Prepare(StunMessage* request) { - request->SetType(STUN_BINDING_REQUEST); - StunByteStringAttribute* username_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - std::string username = connection_->remote_candidate().username(); - username.append(connection_->port()->username_fragment()); - username_attr->CopyBytes(username.c_str(), (uint16)username.size()); - request->AddAttribute(username_attr); - } - - virtual void OnResponse(StunMessage* response) { - connection_->OnConnectionRequestResponse(response, Elapsed()); - } - - virtual void OnErrorResponse(StunMessage* response) { - connection_->OnConnectionRequestErrorResponse(response, Elapsed()); - } - - virtual void OnTimeout() { - } - - virtual int GetNextDelay() { - // Each request is sent only once. After a single delay , the request will - // time out. - timeout_ = true; - return CONNECTION_RESPONSE_TIMEOUT; - } - -private: - Connection* connection_; -}; - -// -// Connection -// - -Connection::Connection(Port* port, size_t index, const Candidate& remote_candidate) - : requests_(port->thread()), port_(port), local_candidate_index_(index), - remote_candidate_(remote_candidate), read_state_(STATE_READ_TIMEOUT), - write_state_(STATE_WRITE_CONNECT), connected_(true), pruned_(false), - rtt_(0), rtt_data_points_(0), last_ping_sent_(0), last_ping_received_(0), - recv_total_bytes_(0), recv_bytes_second_(0), - last_recv_bytes_second_time_((uint32)-1), last_recv_bytes_second_calc_(0), - sent_total_bytes_(0), sent_bytes_second_(0), - last_sent_bytes_second_time_((uint32)-1), last_sent_bytes_second_calc_(0), - reported_(false) { - - // Wire up to send stun packets - requests_.SignalSendPacket.connect(this, &Connection::OnSendStunPacket); -} - -Connection::~Connection() { -} - -const Candidate& Connection::local_candidate() const { - if (local_candidate_index_ < port_->candidates().size()) - return port_->candidates()[local_candidate_index_]; - assert(false); - static Candidate foo; - return foo; -} - -void Connection::set_read_state(ReadState value) { - ReadState old_value = read_state_; - read_state_ = value; - if (value != old_value) { - LOG_J(LS_VERBOSE, this) << "set_read_state"; - SignalStateChange(this); - CheckTimeout(); - } -} - -void Connection::set_write_state(WriteState value) { - WriteState old_value = write_state_; - write_state_ = value; - if (value != old_value) { - LOG_J(LS_VERBOSE, this) << "set_write_state"; - SignalStateChange(this); - CheckTimeout(); - } -} - -void Connection::set_connected(bool value) { - bool old_value = connected_; - connected_ = value; - if (value != old_value) { - LOG_J(LS_VERBOSE, this) << "set_connected"; - } -} - -void Connection::OnSendStunPacket( - const void* data, size_t size, StunRequest* req) { - port_->SendTo(data, size, remote_candidate_.address(), false); -} - -void Connection::OnReadPacket(const char* data, size_t size) { - StunMessage* msg; - std::string remote_username; - const talk_base::SocketAddress& addr(remote_candidate_.address()); - if (!port_->GetStunMessage(data, size, addr, msg, remote_username)) { - // The packet did not parse as a valid STUN message - - // If this connection is readable, then pass along the packet. - if (read_state_ == STATE_READABLE) { - // readable means data from this address is acceptable - // Send it on! - - recv_total_bytes_ += size; - SignalReadPacket(this, data, size); - - // If timed out sending writability checks, start up again - if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) - set_write_state(STATE_WRITE_CONNECT); - } else { - // Not readable means the remote address hasn't send a valid - // binding request yet. - - LOG_J(LS_WARNING, this) - << "Received non-STUN packet from an unreadable connection."; - } - } else if (!msg) { - // The packet was STUN, but was already handled - } else if (remote_username != remote_candidate_.username()) { - // Not destined this connection - LOG_J(LS_ERROR, this) << "Received STUN packet on wrong address."; - if (msg->type() == STUN_BINDING_REQUEST) { - port_->SendBindingErrorResponse(msg, addr, STUN_ERROR_BAD_REQUEST, - STUN_ERROR_REASON_BAD_REQUEST); - } - delete msg; - } else { - // The packet is STUN, with the current username - // If this is a STUN request, then update the readable bit and respond. - // If this is a STUN response, then update the writable bit. - - switch (msg->type()) { - case STUN_BINDING_REQUEST: - // Incoming, validated stun request from remote peer. - // This call will also set the connection readable. - - port_->SendBindingResponse(msg, addr); - - // If timed out sending writability checks, start up again - if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) - set_write_state(STATE_WRITE_CONNECT); - break; - - case STUN_BINDING_RESPONSE: - case STUN_BINDING_ERROR_RESPONSE: - // Response from remote peer. Does it match request sent? - // This doesn't just check, it makes callbacks if transaction - // id's match - requests_.CheckResponse(msg); - break; - - default: - assert(false); - break; - } - - // Done with the message; delete - - delete msg; - } -} - -void Connection::Prune() { - if (!pruned_) { - LOG_J(LS_VERBOSE, this) << "Connection pruned"; - pruned_ = true; - requests_.Clear(); - set_write_state(STATE_WRITE_TIMEOUT); - } -} - -void Connection::Destroy() { - LOG_J(LS_VERBOSE, this) << "Connection destroyed"; - set_read_state(STATE_READ_TIMEOUT); - set_write_state(STATE_WRITE_TIMEOUT); -} - -void Connection::UpdateState(uint32 now) { - // Check the readable state. - // - // Since we don't know how many pings the other side has attempted, the best - // test we can do is a simple window. - - if ((read_state_ == STATE_READABLE) && - (last_ping_received_ + CONNECTION_READ_TIMEOUT <= now)) { - set_read_state(STATE_READ_TIMEOUT); - } - - // Check the writable state. (The order of these checks is important.) - // - // Before becoming unwritable, we allow for a fixed number of pings to fail - // (i.e., receive no response). We also have to give the response time to - // get back, so we include a conservative estimate of this. - // - // Before timing out writability, we give a fixed amount of time. This is to - // allow for changes in network conditions. - - uint32 rtt = ConservativeRTTEstimate(rtt_, rtt_data_points_); - - if ((write_state_ == STATE_WRITABLE) && - TooManyFailures(pings_since_last_response_, - CONNECTION_WRITE_CONNECT_FAILURES, - rtt, - now) && - TooLongWithoutResponse(pings_since_last_response_, - CONNECTION_WRITE_CONNECT_TIMEOUT, - now)) { - set_write_state(STATE_WRITE_CONNECT); - } - - if ((write_state_ == STATE_WRITE_CONNECT) && - TooLongWithoutResponse(pings_since_last_response_, - CONNECTION_WRITE_TIMEOUT, - now)) { - set_write_state(STATE_WRITE_TIMEOUT); - } -} - -void Connection::Ping(uint32 now) { - assert(connected_); - last_ping_sent_ = now; - pings_since_last_response_.push_back(now); - requests_.Send(new ConnectionRequest(this)); -} - -void Connection::ReceivedPing() { - last_ping_received_ = talk_base::Time(); - set_read_state(STATE_READABLE); -} - -std::string Connection::ToString() const { - const char CONNECT_STATE_ABBREV[2] = { - '-', // not connected (false) - 'C', // connected (true) - }; - const char READ_STATE_ABBREV[2] = { - 'R', // STATE_READABLE - '-', // STATE_READ_TIMEOUT - }; - const char WRITE_STATE_ABBREV[3] = { - 'W', // STATE_WRITABLE - 'w', // STATE_WRITE_CONNECT - '-', // STATE_WRITE_TIMEOUT - }; - const Candidate& local = local_candidate(); - const Candidate& remote = remote_candidate(); - std::stringstream ss; - ss << "Conn[" << local.generation() - << ":" << local.name() << ":" << local.type() << ":" << local.address().ToString() - << "->" << remote.name() << ":" << remote.type() << ":" << remote.address().ToString() - << "|" - << CONNECT_STATE_ABBREV[connected()] - << READ_STATE_ABBREV[read_state()] - << WRITE_STATE_ABBREV[write_state()] - << "]"; - return ss.str(); -} - -void Connection::OnConnectionRequestResponse(StunMessage *response, uint32 rtt) { - // We have a potentially valid reply from the remote address. - // The packet must include a username that ends with our fragment, - // since it is a response. - - // Check exact message type - bool valid = true; - if (response->type() != STUN_BINDING_RESPONSE) - valid = false; - - // Must have username attribute - const StunByteStringAttribute* username_attr = - response->GetByteString(STUN_ATTR_USERNAME); - if (valid) { - if (!username_attr) { - LOG_J(LS_ERROR, this) << "Received likely STUN packet with no username"; - valid = false; - } - } - - // Length must be at least the size of our fragment (actually, should - // be bigger since our fragment is at the end!) - if (valid) { - if (username_attr->length() <= port_->username_fragment().size()) { - LOG_J(LS_ERROR, this) << "Received likely STUN packet with short username"; - valid = false; - } - } - - // Compare our fragment with the end of the username - must be exact match - if (valid) { - std::string username_fragment = port_->username_fragment(); - int offset = (int)(username_attr->length() - username_fragment.size()); - if (std::memcmp(username_attr->bytes() + offset, - username_fragment.c_str(), username_fragment.size()) != 0) { - LOG_J(LS_ERROR, this) << "Received STUN response with bad username"; - valid = false; - } - } - - if (valid) { - // Valid response. If we're not already, become writable. We may be - // bringing a pruned connection back to life, but if we don't really want - // it, we can always prune it again. - set_write_state(STATE_WRITABLE); - - pings_since_last_response_.clear(); - rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1); - rtt_data_points_ += 1; - } -} - -void Connection::OnConnectionRequestErrorResponse(StunMessage *response, uint32 rtt) { - const StunErrorCodeAttribute* error = response->GetErrorCode(); - uint32 error_code = error ? error->error_code() : STUN_ERROR_GLOBAL_FAILURE; - - if ((error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE) - || (error_code == STUN_ERROR_SERVER_ERROR) - || (error_code == STUN_ERROR_UNAUTHORIZED)) { - // Recoverable error, retry - } else if (error_code == STUN_ERROR_STALE_CREDENTIALS) { - // Race failure, retry - } else { - // This is not a valid connection. - set_write_state(STATE_WRITE_TIMEOUT); - } -} - -void Connection::CheckTimeout() { - // If both read and write have timed out, then this connection can contribute - // no more to p2p socket unless at some later date readability were to come - // back. However, we gave readability a long time to timeout, so at this - // point, it seems fair to get rid of this connectoin. - if ((read_state_ == STATE_READ_TIMEOUT) && - (write_state_ == STATE_WRITE_TIMEOUT)) { - port_->thread()->Post(this, MSG_DELETE); - } -} - -void Connection::OnMessage(talk_base::Message *pmsg) { - assert(pmsg->message_id == MSG_DELETE); - - LOG_J(LS_INFO, this) << "Connection deleted"; - SignalDestroyed(this); - delete this; -} - -size_t Connection::recv_bytes_second() { - // Snapshot bytes / second calculator - - uint32 current_time = talk_base::Time(); - if (last_recv_bytes_second_time_ != (uint32)-1) { - int delta = talk_base::TimeDiff(current_time, last_recv_bytes_second_time_); - if (delta >= 1000) { - int fraction_time = delta % 1000; - int seconds_time = delta - fraction_time; - int fraction_bytes = (int)(recv_total_bytes_ - last_recv_bytes_second_calc_) * fraction_time / delta; - recv_bytes_second_ = (recv_total_bytes_ - last_recv_bytes_second_calc_ - fraction_bytes) * seconds_time / delta; - last_recv_bytes_second_time_ = current_time - fraction_time; - last_recv_bytes_second_calc_ = recv_total_bytes_ - fraction_bytes; - } - } - if (last_recv_bytes_second_time_ == (uint32)-1) { - last_recv_bytes_second_time_ = current_time; - last_recv_bytes_second_calc_ = recv_total_bytes_; - } - - return recv_bytes_second_; -} - -size_t Connection::recv_total_bytes() { - return recv_total_bytes_; -} - -size_t Connection::sent_bytes_second() { - // Snapshot bytes / second calculator - - uint32 current_time = talk_base::Time(); - if (last_sent_bytes_second_time_ != (uint32)-1) { - int delta = talk_base::TimeDiff(current_time, last_sent_bytes_second_time_); - if (delta >= 1000) { - int fraction_time = delta % 1000; - int seconds_time = delta - fraction_time; - int fraction_bytes = (int)(sent_total_bytes_ - last_sent_bytes_second_calc_) * fraction_time / delta; - sent_bytes_second_ = (sent_total_bytes_ - last_sent_bytes_second_calc_ - fraction_bytes) * seconds_time / delta; - last_sent_bytes_second_time_ = current_time - fraction_time; - last_sent_bytes_second_calc_ = sent_total_bytes_ - fraction_bytes; - } - } - if (last_sent_bytes_second_time_ == (uint32)-1) { - last_sent_bytes_second_time_ = current_time; - last_sent_bytes_second_calc_ = sent_total_bytes_; - } - - return sent_bytes_second_; -} - -size_t Connection::sent_total_bytes() { - return sent_total_bytes_; -} - -ProxyConnection::ProxyConnection(Port* port, size_t index, const Candidate& candidate) - : Connection(port, index, candidate), error_(0) { -} - -int ProxyConnection::Send(const void* data, size_t size) { - if (write_state() != STATE_WRITABLE) { - error_ = EWOULDBLOCK; - return SOCKET_ERROR; - } - int sent = port_->SendTo(data, size, remote_candidate_.address(), true); - if (sent <= 0) { - assert(sent < 0); - error_ = port_->GetError(); - } else { - sent_total_bytes_ += sent; - } - return sent; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/port.h b/third_party/libjingle/files/talk/p2p/base/port.h deleted file mode 100644 index 57c0727..0000000 --- a/third_party/libjingle/files/talk/p2p/base/port.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __PORT_H__ -#define __PORT_H__ - -#include "talk/base/network.h" -#include "talk/base/socketaddress.h" -#include "talk/base/proxyinfo.h" -#include "talk/base/sigslot.h" -#include "talk/base/thread.h" -#include "talk/p2p/base/candidate.h" -#include "talk/p2p/base/stun.h" -#include "talk/p2p/base/stunrequest.h" - -#include <string> -#include <vector> -#include <map> - -namespace talk_base { -class AsyncPacketSocket; -} - -namespace cricket { - -class Connection; - -enum ProtocolType { - PROTO_UDP, - PROTO_TCP, - PROTO_SSLTCP, - PROTO_LAST = PROTO_SSLTCP -}; - -const char * ProtoToString(ProtocolType proto); -bool StringToProto(const char * value, ProtocolType& proto); - -struct ProtocolAddress { - talk_base::SocketAddress address; - ProtocolType proto; - - ProtocolAddress(const talk_base::SocketAddress& a, ProtocolType p) - : address(a), proto(p) { } -}; - -// Represents a local communication mechanism that can be used to create -// connections to similar mechanisms of the other client. Subclasses of this -// one add support for specific mechanisms like local UDP ports. -class Port : public talk_base::MessageHandler, public sigslot::has_slots<> { -public: - Port(talk_base::Thread* thread, const std::string &type, - talk_base::SocketFactory* factory, talk_base::Network* network); - virtual ~Port(); - - // The thread on which this port performs its I/O. - talk_base::Thread* thread() { return thread_; } - - // The factory used to create the sockets of this port. - talk_base::SocketFactory* socket_factory() const { return factory_; } - void set_socket_factory(talk_base::SocketFactory* factory) - { factory_ = factory; } - - // Each port is identified by a name (for debugging purposes). - const std::string& name() const { return name_; } - void set_name(const std::string& name) { name_ = name; } - - // 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 and password. - const std::string& username_fragment() const { return username_frag_; } - const std::string& password() const { return password_; } - - // A value in [0,1] that indicates the preference for this port versus other - // ports on this client. (Larger indicates more preference.) - float preference() const { return preference_; } - void set_preference(float preference) { preference_ = preference; } - - // Identifies the port type. - //const std::string& protocol() const { return proto_; } - const std::string& type() const { return type_; } - - // Identifies network that this port was allocated on. - talk_base::Network* network() { return network_; } - - // Identifies the generation that this port was created in. - uint32 generation() { return generation_; } - void set_generation(uint32 generation) { generation_ = generation; } - - // PrepareAddress will attempt to get an address for this port that other - // clients can send to. It may take some time before the address is read. - // Once it is ready, we will send SignalAddressReady. If errors are - // preventing the port from getting an address, it may send - // SignalAddressError. - virtual void PrepareAddress() = 0; - sigslot::signal1<Port*> SignalAddressReady; - sigslot::signal1<Port*> SignalAddressError; - - // Provides all of the above information in one handy object. - const std::vector<Candidate>& candidates() const { return candidates_; } - - // Returns a map containing all of the connections of this port, keyed by the - // remote address. - typedef std::map<talk_base::SocketAddress, Connection*> AddressMap; - const AddressMap& connections() { return connections_; } - - // Returns the connection to the given address or NULL if none exists. - Connection* GetConnection(const talk_base::SocketAddress& remote_addr); - - // Creates a new connection to the given address. - enum CandidateOrigin { ORIGIN_THIS_PORT, ORIGIN_OTHER_PORT, ORIGIN_MESSAGE }; - virtual Connection* CreateConnection(const Candidate& remote_candidate, - CandidateOrigin origin) = 0; - - // Called each time a connection is created. - sigslot::signal2<Port*, Connection*> SignalConnectionCreated; - - // Sends the given packet to the given address, provided that the address is - // that of a connection or an address that has sent to us already. - virtual int SendTo( - const void* data, size_t size, const talk_base::SocketAddress& addr, - bool payload) = 0; - - // Indicates that we received a successful STUN binding request from an - // address that doesn't correspond to any current connection. To turn this - // into a real connection, call CreateConnection. - sigslot::signal4<Port*, const talk_base::SocketAddress&, StunMessage*, - const std::string&> SignalUnknownAddress; - - // Sends a response message (normal or error) to the given request. One of - // these methods should be called as a response to SignalUnknownAddress. - // NOTE: You MUST call CreateConnection BEFORE SendBindingResponse. - void SendBindingResponse(StunMessage* request, - const talk_base::SocketAddress& addr); - void SendBindingErrorResponse( - StunMessage* request, const talk_base::SocketAddress& addr, - int error_code, const std::string& reason); - - // Indicates that errors occurred when performing I/O. - sigslot::signal2<Port*, int> SignalReadError; - sigslot::signal2<Port*, int> SignalWriteError; - - // Functions on the underlying socket(s). - virtual int SetOption(talk_base::Socket::Option opt, int value) = 0; - virtual int GetError() = 0; - - static void set_proxy(const std::string& user_agent, - const talk_base::ProxyInfo& proxy) { - agent_ = user_agent; proxy_ = proxy; - } - static const std::string& user_agent() { return agent_; } - static const talk_base::ProxyInfo& proxy() { return proxy_; } - - talk_base::AsyncPacketSocket * CreatePacketSocket(ProtocolType proto); - - // Normally, packets arrive through a connection (or they result signaling of - // unknown address). Calling this method turns off delivery of packets - // through their respective connection and instead delivers every packet - // through this port. - void EnablePortPackets(); - sigslot::signal4<Port*, const char*, size_t, const talk_base::SocketAddress&> - SignalReadPacket; - - // Indicates to the port that its official use has now begun. This will - // start the timer that checks to see if the port is being used. - void Start(); - - // Called if the port has no connections and is no longer useful. - void Destroy(); - - // Signaled when this port decides to delete itself because it no longer has - // any usefulness. - sigslot::signal1<Port*> SignalDestroyed; - - virtual void OnMessage(talk_base::Message *pmsg); - - // Debugging description of this port - std::string ToString() const; - -protected: - talk_base::Thread* thread_; - talk_base::SocketFactory* factory_; - std::string type_; - talk_base::Network* network_; - uint32 generation_; - std::string name_; - std::string username_frag_; - std::string password_; - float preference_; - std::vector<Candidate> candidates_; - AddressMap connections_; - enum Lifetime { LT_PRESTART, LT_PRETIMEOUT, LT_POSTTIMEOUT } lifetime_; - bool enable_port_packets_; - - // Fills in the username fragment and password. These will be initially set - // in the constructor to random values. Subclasses can override, though. - void set_username_fragment(const std::string& username_fragment) { - username_frag_ = username_fragment; - } - void set_password(const std::string& password) { password_ = password; } - - // Fills in the local address of the port. - void AddAddress(const talk_base::SocketAddress& address, - const std::string& protocol, bool final); - - // Adds the given connection to the list. (Deleting removes them.) - void AddConnection(Connection* conn); - - // Called when a packet is received from an unknown address that is not - // currently a connection. If this is an authenticated STUN binding request, - // then we will signal the client. - void OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& addr); - - // Constructs a STUN binding request for the given connection and sends it. - void SendBindingRequest(Connection* conn); - - // If the given data comprises a complete and correct STUN message then the - // return value is true, otherwise false. If the message username corresponds - // with this port's username fragment, msg will contain the parsed STUN - // message. Otherwise, the function may send a STUN response internally. - // remote_username contains the remote fragment of the STUN username. - bool GetStunMessage(const char* data, size_t size, - const talk_base::SocketAddress& addr, - StunMessage *& msg, std::string& remote_username); - - friend class Connection; - -private: - // Called when one of our connections deletes itself. - void OnConnectionDestroyed(Connection* conn); - - // Checks if this port is useless, and hence, should be destroyed. - void CheckTimeout(); - - static std::string agent_; - static talk_base::ProxyInfo proxy_; -}; - -// Represents a communication link between a port on the local client and a -// port on the remote client. -class Connection : public talk_base::MessageHandler, - public sigslot::has_slots<> { -public: - virtual ~Connection(); - - // The local port where this connection sends and receives packets. - Port* port() { return port_; } - const Port* port() const { return port_; } - - // Returns the description of the local port - virtual const Candidate& local_candidate() const; - - // Returns the description of the remote port to which we communicate. - const Candidate& remote_candidate() const { return remote_candidate_; } - - enum ReadState { - STATE_READABLE = 0, // we have received pings recently - STATE_READ_TIMEOUT = 1 // we haven't received pings in a while - }; - - ReadState read_state() const { return read_state_; } - - enum WriteState { - STATE_WRITABLE = 0, // we have received ping responses recently - STATE_WRITE_CONNECT = 1, // we have had a few ping failures - STATE_WRITE_TIMEOUT = 2 // we have had a large number of ping failures - }; - - WriteState write_state() const { return write_state_; } - - // Determines whether the connection has finished connecting. This can only - // be false for TCP connections. - bool connected() const { return connected_; } - - // Estimate of the round-trip time over this connection. - uint32 rtt() const { return rtt_; } - - size_t sent_total_bytes(); - size_t sent_bytes_second(); - size_t recv_total_bytes(); - size_t recv_bytes_second(); - sigslot::signal1<Connection*> SignalStateChange; - - // Sent when the connection has decided that it is no longer of value. It - // will delete itself immediately after this call. - sigslot::signal1<Connection*> SignalDestroyed; - - // The connection can send and receive packets asynchronously. This matches - // the interface of AsyncPacketSocket, which may use UDP or TCP under the - // covers. - virtual int Send(const void* data, size_t size) = 0; - - // Error if Send() returns < 0 - virtual int GetError() = 0; - - sigslot::signal3<Connection*, const char*, size_t> SignalReadPacket; - - // Called when a packet is received on this connection. - void OnReadPacket(const char* data, size_t size); - - // Called when a connection is determined to be no longer useful to us. We - // still keep it around in case the other side wants to use it. But we can - // safely stop pinging on it and we can allow it to time out if the other - // side stops using it as well. - bool pruned() { return pruned_; } - void Prune(); - - // Makes the connection go away. - void Destroy(); - - // Checks that the state of this connection is up-to-date. The argument is - // the current time, which is compared against various timeouts. - void UpdateState(uint32 now); - - // Called when this connection should try checking writability again. - uint32 last_ping_sent() { return last_ping_sent_; } - void Ping(uint32 now); - - // Called whenever a valid ping is received on this connection. This is - // public because the connection intercepts the first ping for us. - void ReceivedPing(); - - // Debugging description of this connection - std::string ToString() const; - - bool reported() { return reported_; } - void set_reported(bool reported) { reported_ = reported;} - -protected: - Port* port_; - size_t local_candidate_index_; - Candidate remote_candidate_; - ReadState read_state_; - WriteState write_state_; - bool connected_; - bool pruned_; - StunRequestManager requests_; - uint32 rtt_; - uint32 rtt_data_points_; - uint32 last_ping_sent_; // last time we sent a ping to the other side - uint32 last_ping_received_; // last time we received a ping from the other - // side - std::vector<uint32> pings_since_last_response_; - - size_t recv_total_bytes_; - size_t recv_bytes_second_; - uint32 last_recv_bytes_second_time_; - size_t last_recv_bytes_second_calc_; - - size_t sent_total_bytes_; - size_t sent_bytes_second_; - uint32 last_sent_bytes_second_time_; - size_t last_sent_bytes_second_calc_; - - // Callbacks from ConnectionRequest - void OnConnectionRequestResponse(StunMessage *response, uint32 rtt); - void OnConnectionRequestErrorResponse(StunMessage *response, uint32 rtt); - - // Called back when StunRequestManager has a stun packet to send - void OnSendStunPacket(const void* data, size_t size, StunRequest* req); - - // Constructs a new connection to the given remote port. - Connection(Port* port, size_t index, const Candidate& candidate); - - // Changes the state and signals if necessary. - void set_read_state(ReadState value); - void set_write_state(WriteState value); - void set_connected(bool value); - - // Checks if this connection is useless, and hence, should be destroyed. - void CheckTimeout(); - - void OnMessage(talk_base::Message *pmsg); - - friend class Port; - friend class ConnectionRequest; - -private: - bool reported_; -}; - -// ProxyConnection defers all the interesting work to the port - -class ProxyConnection : public Connection { -public: - ProxyConnection(Port* port, size_t index, const Candidate& candidate); - - virtual int Send(const void* data, size_t size); - virtual int GetError() { return error_; } - -private: - int error_; -}; - -} // namespace cricket - -#endif // __PORT_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/port_unittest.cc b/third_party/libjingle/files/talk/p2p/base/port_unittest.cc deleted file mode 100644 index 4687c19..0000000 --- a/third_party/libjingle/files/talk/p2p/base/port_unittest.cc +++ /dev/null @@ -1,363 +0,0 @@ -#include "talk/base/helpers.h" -#include "talk/base/host.h" -#include "talk/base/natserver.h" -#include "talk/base/natsocketfactory.h" -#include "talk/base/socketaddress.h" -#include "talk/base/thread.h" -#include "talk/base/virtualsocketserver.h" -#include "talk/p2p/base/udpport.h" -#include "talk/p2p/base/relayport.h" -#include "talk/p2p/base/relayserver.h" -#include "talk/p2p/base/stunport.h" -#include "talk/p2p/base/stunserver.h" -#include <iostream> - -using namespace cricket; - -const uint32 MSG_CONNECT = 1; -const uint32 MSG_PREP_ADDRESS = 2; -const uint32 MSG_CREATE_CONN = 3; -const uint32 MSG_ACCEPT_CONN = 4; -const uint32 MSG_PING = 5; - -Candidate GetCandidate(Port* port) { - assert(port->candidates().size() == 1); - return port->candidates()[0]; -} - -talk_base::SocketAddress GetAddress(Port* port) { - return GetCandidate(port).address(); -} - -struct Foo : public talk_base::MessageHandler, public sigslot::has_slots<> { - int count; - talk_base::SocketAddress address; - StunMessage* request; - std::string remote_frag; - - talk_base::Thread* thread; - Port* port1; - Port* port2; - Connection* conn; - - Foo(talk_base::Thread* th, Port* p1, Port* p2) - : count(0), thread(th), port1(p1), port2(p2), conn(0) { - } - - void OnAddressReady(Port* port) { - count += 1; - } - - void OnUnknownAddress( - Port* port, const talk_base::SocketAddress& addr, StunMessage* msg, - const std::string& rf) { - assert(port == port1); - if (!address.IsAny()) { - assert(addr == address); - delete request; - } - address = addr; - request = msg; - remote_frag = rf; - } - - void OnMessage(talk_base::Message* pmsg) { - assert(talk_base::Thread::Current() == thread); - - switch (pmsg->message_id) { - case MSG_CONNECT: - port1->SignalAddressReady.connect(this, &Foo::OnAddressReady); - port1->SignalUnknownAddress.connect(this, &Foo::OnUnknownAddress); - break; - - case MSG_PREP_ADDRESS: - port1->PrepareAddress(); - break; - - case MSG_CREATE_CONN: - conn = port1->CreateConnection(GetCandidate(port2), Port::ORIGIN_MESSAGE); - assert(conn); - conn->Ping(0); - break; - - case MSG_PING: - assert(conn); - conn->Ping(0); - break; - - case MSG_ACCEPT_CONN: { - Candidate c = GetCandidate(port2); - c.set_address(address); - conn = port1->CreateConnection(c, Port::ORIGIN_MESSAGE); - assert(conn); - port1->SendBindingResponse(request, address); - conn->Ping(0); - delete request; - break; - } - - default: - assert(false); - break; - } - } -}; - -void test(talk_base::Thread* pthMain, const char* name1, Port* port1, - talk_base::Thread* pthBack, const char* name2, Port* port2, - bool accept = true, bool same_addr = true) { - Foo* foo1 = new Foo(pthMain, port1, port2); - Foo* foo2 = new Foo(pthBack, port2, port1); - - std::cout << "Test: " << name1 << " to " << name2 << ": "; - std::cout.flush(); - - pthBack->Start(); - - pthMain->Post(foo1, MSG_CONNECT); - pthBack->Post(foo2, MSG_CONNECT); - pthMain->ProcessMessages(10); - assert(foo1->count == 0); - assert(foo2->count == 0); - - pthMain->Post(foo1, MSG_PREP_ADDRESS); - pthMain->ProcessMessages(200); - assert(foo1->count == 1); - - pthBack->Post(foo2, MSG_PREP_ADDRESS); - pthMain->ProcessMessages(200); - assert(foo2->count == 1); - - pthMain->Post(foo1, MSG_CREATE_CONN); - pthMain->ProcessMessages(200); - - if (accept) { - - assert(foo1->address.IsAny()); - assert(foo2->remote_frag == port1->username_fragment()); - assert(!same_addr || (foo2->address == GetAddress(port1))); - - pthBack->Post(foo2, MSG_ACCEPT_CONN); - pthMain->ProcessMessages(200); - - } else { - - assert(foo1->address.IsAny()); - assert(foo2->address.IsAny()); - - pthBack->Post(foo2, MSG_CREATE_CONN); - pthMain->ProcessMessages(200); - - if (same_addr) { - assert(foo1->conn->read_state() == Connection::STATE_READABLE); - assert(foo2->conn->write_state() == Connection::STATE_WRITABLE); - - // First connection may not be writable if the first ping did not get - // through. So we will have to do another. - if (foo1->conn->write_state() == Connection::STATE_WRITE_CONNECT) { - pthMain->Post(foo1, MSG_PING); - pthMain->ProcessMessages(200); - } - } else { - assert(foo1->address.IsAny()); - assert(foo2->address.IsAny()); - - pthMain->Post(foo1, MSG_PING); - pthMain->ProcessMessages(200); - - assert(foo1->address.IsAny()); - assert(!foo2->address.IsAny()); - - pthBack->Post(foo2, MSG_ACCEPT_CONN); - pthMain->ProcessMessages(200); - } - } - - assert(foo1->conn->read_state() == Connection::STATE_READABLE); - assert(foo1->conn->write_state() == Connection::STATE_WRITABLE); - assert(foo2->conn->read_state() == Connection::STATE_READABLE); - assert(foo2->conn->write_state() == Connection::STATE_WRITABLE); - - pthBack->Stop(); - - delete port1; - delete port2; - delete foo1; - delete foo2; - - std::cout << "PASS" << std::endl; -} - -const talk_base::SocketAddress local_addr = talk_base::SocketAddress("127.0.0.1", 0); -const talk_base::SocketAddress relay_int_addr = talk_base::SocketAddress("127.0.0.1", 5000); -const talk_base::SocketAddress relay_ext_addr = talk_base::SocketAddress("127.0.0.1", 5001); -const talk_base::SocketAddress stun_addr = talk_base::SocketAddress("127.0.0.1", STUN_SERVER_PORT); -const talk_base::SocketAddress nat_addr = talk_base::SocketAddress("127.0.0.1", talk_base::NAT_SERVER_PORT); - -void test_udp() { - talk_base::Thread* pthMain = talk_base::Thread::Current(); - talk_base::Thread* pthBack = new talk_base::Thread(); - talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); - - test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr), - pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr)); - - delete pthBack; -} - -void test_relay() { - talk_base::Thread* pthMain = talk_base::Thread::Current(); - talk_base::Thread* pthBack = new talk_base::Thread(); - talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); - - RelayServer relay_server(pthBack); - - talk_base::AsyncUDPSocket* int_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); - assert(int_socket->Bind(relay_int_addr) >= 0); - relay_server.AddInternalSocket(int_socket); - - talk_base::AsyncUDPSocket* ext_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); - assert(ext_socket->Bind(relay_ext_addr) >= 0); - relay_server.AddExternalSocket(ext_socket); - - std::string username = CreateRandomString(16); - std::string password = CreateRandomString(16); - - RelayPort* rport = - new RelayPort(pthBack, NULL, network, local_addr, username, password, ""); - rport->AddServerAddress(ProtocolAddress(relay_int_addr, PROTO_UDP)); - - test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr), - pthBack, "relay", rport); - - delete pthBack; -} - -const char* NATName(talk_base::NATType type) { - switch (type) { - case talk_base::NAT_OPEN_CONE: return "open cone"; - case talk_base::NAT_ADDR_RESTRICTED: return "addr restricted"; - case talk_base::NAT_PORT_RESTRICTED: return "port restricted"; - case talk_base::NAT_SYMMETRIC: return "symmetric"; - default: - assert(false); - return 0; - } -} - -void test_stun(talk_base::NATType nat_type) { - talk_base::Thread* pthMain = talk_base::Thread::Current(); - talk_base::Thread* pthBack = new talk_base::Thread(); - talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); - - talk_base::NATServer* nat = new talk_base::NATServer( - nat_type, pthMain->socketserver(), nat_addr, - pthMain->socketserver(), nat_addr); - talk_base::NATSocketFactory* nat_factory = - new talk_base::NATSocketFactory(pthMain->socketserver(), nat_addr); - - StunPort* stun_port = - new StunPort(pthMain, nat_factory, network, local_addr, stun_addr); - - talk_base::AsyncUDPSocket* stun_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); - assert(stun_socket->Bind(stun_addr) >= 0); - StunServer* stun_server = new StunServer(stun_socket); - - char name[256]; - sprintf(name, "stun (%s)", NATName(nat_type)); - - test(pthMain, name, stun_port, - pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr), - true, nat_type != talk_base::NAT_SYMMETRIC); - - delete stun_server; - delete stun_socket; - delete nat; - delete nat_factory; - delete pthBack; -} - -void test_stun(talk_base::NATType nat1_type, talk_base::NATType nat2_type) { - - talk_base::Thread* pthMain = talk_base::Thread::Current(); - talk_base::Thread* pthBack = new talk_base::Thread(); - talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); - - talk_base::SocketAddress local_addr1(talk_base::LocalHost().networks()[0]->ip(), 0); - talk_base::SocketAddress local_addr2(talk_base::LocalHost().networks()[1]->ip(), 0); - - talk_base::SocketAddress nat1_addr(local_addr1.ip(), talk_base::NAT_SERVER_PORT); - talk_base::SocketAddress nat2_addr(local_addr2.ip(), talk_base::NAT_SERVER_PORT); - - talk_base::SocketAddress stun1_addr(local_addr1.ip(), STUN_SERVER_PORT); - talk_base::SocketAddress stun2_addr(local_addr2.ip(), STUN_SERVER_PORT); - - talk_base::NATServer* nat1 = new talk_base::NATServer( - nat1_type, pthMain->socketserver(), nat1_addr, - pthMain->socketserver(), nat1_addr); - talk_base::NATSocketFactory* nat1_factory = - new talk_base::NATSocketFactory(pthMain->socketserver(), nat1_addr); - - StunPort* stun1_port = - new StunPort(pthMain, nat1_factory, network, local_addr1, stun1_addr); - - talk_base::NATServer* nat2 = new talk_base::NATServer( - nat2_type, pthBack->socketserver(), nat2_addr, - pthBack->socketserver(), nat2_addr); - talk_base::NATSocketFactory* nat2_factory = - new talk_base::NATSocketFactory(pthBack->socketserver(), nat2_addr); - - StunPort* stun2_port = - new StunPort(pthMain, nat2_factory, network, local_addr2, stun2_addr); - - talk_base::AsyncUDPSocket* stun1_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); - assert(stun1_socket->Bind(stun_addr) >= 0); - StunServer* stun1_server = new StunServer(stun1_socket); - - talk_base::AsyncUDPSocket* stun2_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); - assert(stun2_socket->Bind(stun2_addr) >= 0); - StunServer* stun2_server = new StunServer(stun2_socket); - - char name1[256], name2[256]; - sprintf(name1, "stun (%s)", NATName(nat1_type)); - sprintf(name2, "stun (%s)", NATName(nat2_type)); - - test(pthMain, name1, stun1_port, - pthBack, name2, stun2_port, - nat2_type == talk_base::NAT_OPEN_CONE, nat1_type != talk_base::NAT_SYMMETRIC); - - delete stun1_server; - delete stun1_socket; - delete stun2_server; - delete stun2_socket; - delete nat1; - delete nat1_factory; - delete nat2; - delete nat2_factory; - delete pthBack; -} - -int main(int argc, char* argv[]) { - InitRandom(NULL, 0); - - test_udp(); - - test_relay(); - - test_stun(talk_base::NAT_OPEN_CONE); - test_stun(talk_base::NAT_ADDR_RESTRICTED); - test_stun(talk_base::NAT_PORT_RESTRICTED); - test_stun(talk_base::NAT_SYMMETRIC); - - test_stun(talk_base::NAT_OPEN_CONE, talk_base::NAT_OPEN_CONE); - test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_OPEN_CONE); - test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_OPEN_CONE); - test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_OPEN_CONE); - - test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED); - test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED); - test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_PORT_RESTRICTED); - test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_ADDR_RESTRICTED); - - return 0; -} diff --git a/third_party/libjingle/files/talk/p2p/base/portallocator.h b/third_party/libjingle/files/talk/p2p/base/portallocator.h deleted file mode 100644 index 50f52cf..0000000 --- a/third_party/libjingle/files/talk/p2p/base/portallocator.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _PORTALLOCATOR_H_ -#define _PORTALLOCATOR_H_ - -#include "talk/base/sigslot.h" -#include "talk/p2p/base/port.h" -#include <string> -#undef SetPort - -namespace cricket { - -// PortAllocator is responsible for allocating Port types for a given -// P2PSocket. It also handles port freeing. -// -// Clients can override this class to control port allocation, including -// what kinds of ports are allocated. - -const uint32 PORTALLOCATOR_DISABLE_UDP = 0x01; -const uint32 PORTALLOCATOR_DISABLE_STUN = 0x02; -const uint32 PORTALLOCATOR_DISABLE_RELAY = 0x04; -const uint32 PORTALLOCATOR_DISABLE_TCP = 0x08; -const uint32 PORTALLOCATOR_ENABLE_SHAKER = 0x10; - -const uint32 kDefaultPortAllocatorFlags = 0; - -class PortAllocatorSession : public sigslot::has_slots<> { -public: - PortAllocatorSession(uint32 flags) : flags_(flags) {} - - // Subclasses should clean up any ports created. - virtual ~PortAllocatorSession() {} - - uint32 flags() const { return flags_; } - void set_flags(uint32 flags) { flags_ = flags; } - - // Prepares an initial set of ports to try. - virtual void GetInitialPorts() = 0; - - // Starts and stops the flow of additional ports to try. - virtual void StartGetAllPorts() = 0; - virtual void StopGetAllPorts() = 0; - virtual bool IsGettingAllPorts() = 0; - - sigslot::signal2<PortAllocatorSession*, Port*> SignalPortReady; - sigslot::signal2<PortAllocatorSession*, const std::vector<Candidate>&> SignalCandidatesReady; - - uint32 generation() { return generation_; } - void set_generation(uint32 generation) { generation_ = generation; } - -private: - uint32 flags_; - uint32 generation_; -}; - -class PortAllocator { -public: - PortAllocator() : flags_(kDefaultPortAllocatorFlags) {} - - virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type) = 0; - - uint32 flags() const { return flags_; } - void set_flags(uint32 flags) { flags_ = flags; } - - const std::string& user_agent() const { return agent_; } - const talk_base::ProxyInfo& proxy() const { return proxy_; } - void set_proxy(const std::string& agent, const talk_base::ProxyInfo& proxy) { - agent_ = agent; proxy_ = proxy; - } - -protected: - uint32 flags_; - std::string agent_; - talk_base::ProxyInfo proxy_; -}; - -} // namespace cricket - -#endif // _PORTALLOCATOR_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/pseudotcp.cc b/third_party/libjingle/files/talk/p2p/base/pseudotcp.cc deleted file mode 100644 index 2f52d65..0000000 --- a/third_party/libjingle/files/talk/p2p/base/pseudotcp.cc +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/base/basicdefs.h" -#include "talk/base/basictypes.h" -#include "talk/base/byteorder.h" -#include "talk/base/common.h" -#include "talk/base/logging.h" -#include "talk/base/socket.h" -#include "talk/base/stringutils.h" -#include "talk/base/time.h" -#include "talk/p2p/base/pseudotcp.h" - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -// The following logging is for detailed (packet-level) pseudotcp analysis only. -#define _DBG_NONE 0 -#define _DBG_NORMAL 1 -#define _DBG_VERBOSE 2 -#define _DEBUGMSG _DBG_NONE - -namespace cricket { - -////////////////////////////////////////////////////////////////////// -// Network Constants -////////////////////////////////////////////////////////////////////// - -// Standard MTUs -const uint16 PACKET_MAXIMUMS[] = { - 65535, // Theoretical maximum, Hyperchannel - 32000, // Nothing - 17914, // 16Mb IBM Token Ring - 8166, // IEEE 802.4 - //4464, // IEEE 802.5 (4Mb max) - 4352, // FDDI - //2048, // Wideband Network - 2002, // IEEE 802.5 (4Mb recommended) - //1536, // Expermental Ethernet Networks - //1500, // Ethernet, Point-to-Point (default) - 1492, // IEEE 802.3 - 1006, // SLIP, ARPANET - //576, // X.25 Networks - //544, // DEC IP Portal - //512, // NETBIOS - 508, // IEEE 802/Source-Rt Bridge, ARCNET - 296, // Point-to-Point (low delay) - //68, // Official minimum - 0, // End of list marker -}; - -const uint32 MAX_PACKET = 65535; -// Note: we removed lowest level because packet overhead was larger! -const uint32 MIN_PACKET = 296; - -const uint32 IP_HEADER_SIZE = 20; // (+ up to 40 bytes of options?) -const uint32 ICMP_HEADER_SIZE = 8; -const uint32 UDP_HEADER_SIZE = 8; -// TODO: Make JINGLE_HEADER_SIZE transparent to this code? -const uint32 JINGLE_HEADER_SIZE = 64; // when relay framing is in use - -////////////////////////////////////////////////////////////////////// -// Global Constants and Functions -////////////////////////////////////////////////////////////////////// -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 0 | Conversation Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 4 | Sequence Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 8 | Acknowledgment Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | | |U|A|P|R|S|F| | -// 12 | Control | |R|C|S|S|Y|I| Window | -// | | |G|K|H|T|N|N| | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 16 | Timestamp sending | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 20 | Timestamp receiving | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 24 | data | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -////////////////////////////////////////////////////////////////////// - -#define PSEUDO_KEEPALIVE 0 - -const uint32 MAX_SEQ = 0xFFFFFFFF; -const uint32 HEADER_SIZE = 24; -const uint32 PACKET_OVERHEAD = HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE; - -const uint32 MIN_RTO = 250; // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second") -const uint32 DEF_RTO = 3000; // 3 seconds (RFC1122, Sec 4.2.3.1) -const uint32 MAX_RTO = 60000; // 60 seconds -const uint32 ACK_DELAY = 100; // 100 milliseconds - -const uint8 FLAG_CTL = 0x02; -const uint8 FLAG_RST = 0x04; - -const uint8 CTL_CONNECT = 0; -//const uint8 CTL_REDIRECT = 1; -const uint8 CTL_EXTRA = 255; - -/* -const uint8 FLAG_FIN = 0x01; -const uint8 FLAG_SYN = 0x02; -const uint8 FLAG_ACK = 0x10; -*/ - -const uint32 CTRL_BOUND = 0x80000000; - -const long DEFAULT_TIMEOUT = 4000; // If there are no pending clocks, wake up every 4 seconds -const long CLOSED_TIMEOUT = 60 * 1000; // If the connection is closed, once per minute - -#if PSEUDO_KEEPALIVE -// !?! Rethink these times -const uint32 IDLE_PING = 20 * 1000; // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds) -const uint32 IDLE_TIMEOUT = 90 * 1000; // 90 seconds; -#endif // PSEUDO_KEEPALIVE - -////////////////////////////////////////////////////////////////////// -// Helper Functions -////////////////////////////////////////////////////////////////////// - -inline void long_to_bytes(uint32 val, void* buf) { - *static_cast<uint32*>(buf) = talk_base::HostToNetwork32(val); -} - -inline void short_to_bytes(uint16 val, void* buf) { - *static_cast<uint16*>(buf) = talk_base::HostToNetwork16(val); -} - -inline uint32 bytes_to_long(const void* buf) { - return talk_base::NetworkToHost32(*static_cast<const uint32*>(buf)); -} - -inline uint16 bytes_to_short(const void* buf) { - return talk_base::NetworkToHost16(*static_cast<const uint16*>(buf)); -} - -uint32 bound(uint32 lower, uint32 middle, uint32 upper) { - return talk_base::_min(talk_base::_max(lower, middle), upper); -} - -////////////////////////////////////////////////////////////////////// -// Debugging Statistics -////////////////////////////////////////////////////////////////////// - -#if 0 // Not used yet - -enum Stat { - S_SENT_PACKET, // All packet sends - S_RESENT_PACKET, // All packet sends that are retransmits - S_RECV_PACKET, // All packet receives - S_RECV_NEW, // All packet receives that are too new - S_RECV_OLD, // All packet receives that are too old - S_NUM_STATS -}; - -const char* const STAT_NAMES[S_NUM_STATS] = { - "snt", - "snt-r", - "rcv" - "rcv-n", - "rcv-o" -}; - -int g_stats[S_NUM_STATS]; -inline void Incr(Stat s) { ++g_stats[s]; } -void ReportStats() { - char buffer[256]; - size_t len = 0; - for (int i=0; i<S_NUM_STATS; ++i) { - len += talk_base::sprintfn(buffer, ARRAY_SIZE(buffer), "%s%s:%d", - (i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]); - g_stats[i] = 0; - } - LOG(LS_INFO) << "Stats[" << buffer << "]"; -} - -#endif - -////////////////////////////////////////////////////////////////////// -// PseudoTcp -////////////////////////////////////////////////////////////////////// - -uint32 PseudoTcp::Now() { -#if 0 // Use this to synchronize timers with logging timestamps (easier debug) - return talk_base::ElapsedTime(); -#else - return talk_base::Time(); -#endif -} - -PseudoTcp::PseudoTcp(IPseudoTcpNotify * notify, uint32 conv) - : m_notify(notify), m_shutdown(SD_NONE), m_error(0) { - - // Sanity check on buffer sizes (needed for OnTcpWriteable notification logic) - ASSERT(sizeof(m_rbuf) + MIN_PACKET < sizeof(m_sbuf)); - - uint32 now = Now(); - - m_state = TCP_LISTEN; - m_conv = conv; - m_rcv_wnd = sizeof(m_rbuf); - m_snd_nxt = m_slen = 0; - m_snd_wnd = 1; - m_snd_una = m_rcv_nxt = m_rlen = 0; - m_bReadEnable = true; - m_bWriteEnable = false; - m_t_ack = 0; - - m_msslevel = 0; - m_largest = 0; - ASSERT(MIN_PACKET > PACKET_OVERHEAD); - m_mss = MIN_PACKET - PACKET_OVERHEAD; - m_mtu_advise = MAX_PACKET; - - m_rto_base = 0; - - m_cwnd = 2 * m_mss; - m_ssthresh = sizeof(m_rbuf); - m_lastrecv = m_lastsend = m_lasttraffic = now; - m_bOutgoing = false; - - m_dup_acks = 0; - m_recover = 0; - - m_ts_recent = m_ts_lastack = 0; - - m_rx_rto = DEF_RTO; - m_rx_srtt = m_rx_rttvar = 0; -} - -PseudoTcp::~PseudoTcp() { -} - -int -PseudoTcp::Connect() { - if (m_state != TCP_LISTEN) { - m_error = EINVAL; - return -1; - } - - m_state = TCP_SYN_SENT; - LOG(LS_INFO) << "State: TCP_SYN_SENT"; - - char buffer[1]; - buffer[0] = CTL_CONNECT; - queue(buffer, 1, true); - attemptSend(); - - return 0; -} - -void -PseudoTcp::NotifyMTU(uint16 mtu) { - m_mtu_advise = mtu; - if (m_state == TCP_ESTABLISHED) { - adjustMTU(); - } -} - -void -PseudoTcp::NotifyClock(uint32 now) { - if (m_state == TCP_CLOSED) - return; - - // Check if it's time to retransmit a segment - if (m_rto_base && (talk_base::TimeDiff(m_rto_base + m_rx_rto, now) <= 0)) { - if (m_slist.empty()) { - ASSERT(false); - } else { - // Note: (m_slist.front().xmit == 0)) { - // retransmit segments -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto - << ") (rto_base: " << m_rto_base - << ") (now: " << now - << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks) - << ")"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return; - } - - uint32 nInFlight = m_snd_nxt - m_snd_una; - m_ssthresh = talk_base::_max(nInFlight / 2, 2 * m_mss); - //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << " nInFlight: " << nInFlight << " m_mss: " << m_mss; - m_cwnd = m_mss; - - // Back off retransmit timer. Note: the limit is lower when connecting. - uint32 rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO; - m_rx_rto = talk_base::_min(rto_limit, m_rx_rto * 2); - m_rto_base = now; - } - } - - // Check if it's time to probe closed windows - if ((m_snd_wnd == 0) - && (talk_base::TimeDiff(m_lastsend + m_rx_rto, now) <= 0)) { - if (talk_base::TimeDiff(now, m_lastrecv) >= 15000) { - closedown(ECONNABORTED); - return; - } - - // probe the window - packet(m_snd_nxt - 1, 0, 0, 0); - m_lastsend = now; - - // back off retransmit timer - m_rx_rto = talk_base::_min(MAX_RTO, m_rx_rto * 2); - } - - // Check if it's time to send delayed acks - if (m_t_ack && (talk_base::TimeDiff(m_t_ack + ACK_DELAY, now) <= 0)) { - packet(m_snd_nxt, 0, 0, 0); - } - -#if PSEUDO_KEEPALIVE - // Check for idle timeout - if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) { - closedown(ECONNABORTED); - return; - } - - // Check for ping timeout (to keep udp mapping open) - if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now) <= 0)) { - packet(m_snd_nxt, 0, 0, 0); - } -#endif // PSEUDO_KEEPALIVE -} - -bool -PseudoTcp::NotifyPacket(const char * buffer, size_t len) { - if (len > MAX_PACKET) { - LOG_F(WARNING) << "packet too large"; - return false; - } - return parse(reinterpret_cast<const uint8 *>(buffer), uint32(len)); -} - -bool -PseudoTcp::GetNextClock(uint32 now, long& timeout) { - return clock_check(now, timeout); -} - -// -// IPStream Implementation -// - -int -PseudoTcp::Recv(char * buffer, size_t len) { - if (m_state != TCP_ESTABLISHED) { - m_error = ENOTCONN; - return SOCKET_ERROR; - } - - if (m_rlen == 0) { - m_bReadEnable = true; - m_error = EWOULDBLOCK; - return SOCKET_ERROR; - } - - uint32 read = talk_base::_min(uint32(len), m_rlen); - memcpy(buffer, m_rbuf, read); - m_rlen -= read; - - // !?! until we create a circular buffer, we need to move all of the rest of the buffer up! - memmove(m_rbuf, m_rbuf + read, sizeof(m_rbuf) - read/*m_rlen*/); - - if ((sizeof(m_rbuf) - m_rlen - m_rcv_wnd) - >= talk_base::_min<uint32>(sizeof(m_rbuf) / 2, m_mss)) { - bool bWasClosed = (m_rcv_wnd == 0); // !?! Not sure about this was closed business - - m_rcv_wnd = sizeof(m_rbuf) - m_rlen; - - if (bWasClosed) { - attemptSend(sfImmediateAck); - } - } - - return read; -} - -int -PseudoTcp::Send(const char * buffer, size_t len) { - if (m_state != TCP_ESTABLISHED) { - m_error = ENOTCONN; - return SOCKET_ERROR; - } - - if (m_slen == sizeof(m_sbuf)) { - m_bWriteEnable = true; - m_error = EWOULDBLOCK; - return SOCKET_ERROR; - } - - int written = queue(buffer, uint32(len), false); - attemptSend(); - return written; -} - -void -PseudoTcp::Close(bool force) { - LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")"; - m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL; -} - -int PseudoTcp::GetError() { - return m_error; -} - -// -// Internal Implementation -// - -uint32 -PseudoTcp::queue(const char * data, uint32 len, bool bCtrl) { - if (len > sizeof(m_sbuf) - m_slen) { - ASSERT(!bCtrl); - len = sizeof(m_sbuf) - m_slen; - } - - // We can concatenate data if the last segment is the same type - // (control v. regular data), and has not been transmitted yet - if (!m_slist.empty() && (m_slist.back().bCtrl == bCtrl) && (m_slist.back().xmit == 0)) { - m_slist.back().len += len; - } else { - SSegment sseg(m_snd_una + m_slen, len, bCtrl); - m_slist.push_back(sseg); - } - - memcpy(m_sbuf + m_slen, data, len); - m_slen += len; - //LOG(LS_INFO) << "PseudoTcp::queue - m_slen = " << m_slen; - return len; -} - -IPseudoTcpNotify::WriteResult -PseudoTcp::packet(uint32 seq, uint8 flags, const char * data, uint32 len) { - ASSERT(HEADER_SIZE + len <= MAX_PACKET); - - uint32 now = Now(); - - uint8 buffer[MAX_PACKET]; - long_to_bytes(m_conv, buffer); - long_to_bytes(seq, buffer + 4); - long_to_bytes(m_rcv_nxt, buffer + 8); - buffer[12] = 0; - buffer[13] = flags; - short_to_bytes(uint16(m_rcv_wnd), buffer + 14); - - // Timestamp computations - long_to_bytes(now, buffer + 16); - long_to_bytes(m_ts_recent, buffer + 20); - m_ts_lastack = m_rcv_nxt; - - memcpy(buffer + HEADER_SIZE, data, len); - -#if _DEBUGMSG >= _DBG_VERBOSE - LOG(LS_INFO) << "<-- <CONV=" << m_conv - << "><FLG=" << static_cast<unsigned>(flags) - << "><SEQ=" << seq << ":" << seq + len - << "><ACK=" << m_rcv_nxt - << "><WND=" << m_rcv_wnd - << "><TS=" << (now % 10000) - << "><TSR=" << (m_ts_recent % 10000) - << "><LEN=" << len << ">"; -#endif // _DEBUGMSG - - IPseudoTcpNotify::WriteResult wres = m_notify->TcpWritePacket(this, reinterpret_cast<char *>(buffer), len + HEADER_SIZE); - // Note: When data is NULL, this is an ACK packet. We don't read the return value for those, - // and thus we won't retry. So go ahead and treat the packet as a success (basically simulate - // as if it were dropped), which will prevent our timers from being messed up. - if ((wres != IPseudoTcpNotify::WR_SUCCESS) && (NULL != data)) - return wres; - - m_t_ack = 0; - if (len > 0) { - m_lastsend = now; - } - m_lasttraffic = now; - m_bOutgoing = true; - - return IPseudoTcpNotify::WR_SUCCESS; -} - -bool -PseudoTcp::parse(const uint8 * buffer, uint32 size) { - if (size < 12) - return false; - - Segment seg; - seg.conv = bytes_to_long(buffer); - seg.seq = bytes_to_long(buffer + 4); - seg.ack = bytes_to_long(buffer + 8); - seg.flags = buffer[13]; - seg.wnd = bytes_to_short(buffer + 14); - - seg.tsval = bytes_to_long(buffer + 16); - seg.tsecr = bytes_to_long(buffer + 20); - - seg.data = reinterpret_cast<const char *>(buffer) + HEADER_SIZE; - seg.len = size - HEADER_SIZE; - -#if _DEBUGMSG >= _DBG_VERBOSE - LOG(LS_INFO) << "--> <CONV=" << seg.conv - << "><FLG=" << static_cast<unsigned>(seg.flags) - << "><SEQ=" << seg.seq << ":" << seg.seq + seg.len - << "><ACK=" << seg.ack - << "><WND=" << seg.wnd - << "><TS=" << (seg.tsval % 10000) - << "><TSR=" << (seg.tsecr % 10000) - << "><LEN=" << seg.len << ">"; -#endif // _DEBUGMSG - - return process(seg); -} - -bool -PseudoTcp::clock_check(uint32 now, long& nTimeout) { - if (m_shutdown == SD_FORCEFUL) - return false; - - if ((m_shutdown == SD_GRACEFUL) - && ((m_state != TCP_ESTABLISHED) - || ((m_slen == 0) && (m_t_ack == 0)))) { - return false; - } - - if (m_state == TCP_CLOSED) { - nTimeout = CLOSED_TIMEOUT; - return true; - } - - nTimeout = DEFAULT_TIMEOUT; - - if (m_t_ack) { - nTimeout = talk_base::_min(nTimeout, - talk_base::TimeDiff(m_t_ack + ACK_DELAY, now)); - } - if (m_rto_base) { - nTimeout = talk_base::_min(nTimeout, - talk_base::TimeDiff(m_rto_base + m_rx_rto, now)); - } - if (m_snd_wnd == 0) { - nTimeout = talk_base::_min(nTimeout, talk_base::TimeDiff(m_lastsend + m_rx_rto, now)); - } -#if PSEUDO_KEEPALIVE - if (m_state == TCP_ESTABLISHED) { - nTimeout = talk_base::_min(nTimeout, - talk_base::TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now)); - } -#endif // PSEUDO_KEEPALIVE - return true; -} - -bool -PseudoTcp::process(Segment& seg) { - // If this is the wrong conversation, send a reset!?! (with the correct conversation?) - if (seg.conv != m_conv) { - //if ((seg.flags & FLAG_RST) == 0) { - // packet(tcb, seg.ack, 0, FLAG_RST, 0, 0); - //} - LOG_F(LS_ERROR) << "wrong conversation"; - return false; - } - - uint32 now = Now(); - m_lasttraffic = m_lastrecv = now; - m_bOutgoing = false; - - if (m_state == TCP_CLOSED) { - // !?! send reset? - LOG_F(LS_ERROR) << "closed"; - return false; - } - - // Check if this is a reset segment - if (seg.flags & FLAG_RST) { - closedown(ECONNRESET); - return false; - } - - // Check for control data - bool bConnect = false; - if (seg.flags & FLAG_CTL) { - if (seg.len == 0) { - LOG_F(LS_ERROR) << "Missing control code"; - return false; - } else if (seg.data[0] == CTL_CONNECT) { - bConnect = true; - if (m_state == TCP_LISTEN) { - m_state = TCP_SYN_RECEIVED; - LOG(LS_INFO) << "State: TCP_SYN_RECEIVED"; - //m_notify->associate(addr); - char buffer[1]; - buffer[0] = CTL_CONNECT; - queue(buffer, 1, true); - } else if (m_state == TCP_SYN_SENT) { - m_state = TCP_ESTABLISHED; - LOG(LS_INFO) << "State: TCP_ESTABLISHED"; - adjustMTU(); - if (m_notify) { - m_notify->OnTcpOpen(this); - } - //notify(evOpen); - } - } else { - LOG_F(LS_WARNING) << "Unknown control code: " << seg.data[0]; - return false; - } - } - - // Update timestamp - if ((seg.seq <= m_ts_lastack) && (m_ts_lastack < seg.seq + seg.len)) { - m_ts_recent = seg.tsval; - } - - // Check if this is a valuable ack - if ((seg.ack > m_snd_una) && (seg.ack <= m_snd_nxt)) { - // Calculate round-trip time - if (seg.tsecr) { - long rtt = talk_base::TimeDiff(now, seg.tsecr); - if (rtt >= 0) { - if (m_rx_srtt == 0) { - m_rx_srtt = rtt; - m_rx_rttvar = rtt / 2; - } else { - m_rx_rttvar = (3 * m_rx_rttvar + abs(long(rtt - m_rx_srtt))) / 4; - m_rx_srtt = (7 * m_rx_srtt + rtt) / 8; - } - m_rx_rto = bound(MIN_RTO, m_rx_srtt + talk_base::_max(1LU, 4 * m_rx_rttvar), MAX_RTO); -#if _DEBUGMSG >= _DBG_VERBOSE - LOG(LS_INFO) << "rtt: " << rtt - << " srtt: " << m_rx_srtt - << " rto: " << m_rx_rto; -#endif // _DEBUGMSG - } else { - ASSERT(false); - } - } - - m_snd_wnd = seg.wnd; - - uint32 nAcked = seg.ack - m_snd_una; - m_snd_una = seg.ack; - - m_rto_base = (m_snd_una == m_snd_nxt) ? 0 : now; - - m_slen -= nAcked; - memmove(m_sbuf, m_sbuf + nAcked, m_slen); - //LOG(LS_INFO) << "PseudoTcp::process - m_slen = " << m_slen; - - for (uint32 nFree = nAcked; nFree > 0; ) { - ASSERT(!m_slist.empty()); - if (nFree < m_slist.front().len) { - m_slist.front().len -= nFree; - nFree = 0; - } else { - if (m_slist.front().len > m_largest) { - m_largest = m_slist.front().len; - } - nFree -= m_slist.front().len; - m_slist.pop_front(); - } - } - - if (m_dup_acks >= 3) { - if (m_snd_una >= m_recover) { // NewReno - uint32 nInFlight = m_snd_nxt - m_snd_una; - m_cwnd = talk_base::_min(m_ssthresh, nInFlight + m_mss); // (Fast Retransmit) -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "exit recovery"; -#endif // _DEBUGMSG - m_dup_acks = 0; - } else { -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "recovery retransmit"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return false; - } - m_cwnd += m_mss - talk_base::_min(nAcked, m_cwnd); - } - } else { - m_dup_acks = 0; - // Slow start, congestion avoidance - if (m_cwnd < m_ssthresh) { - m_cwnd += m_mss; - } else { - m_cwnd += talk_base::_max(1LU, m_mss * m_mss / m_cwnd); - } - } - - // !?! A bit hacky - if ((m_state == TCP_SYN_RECEIVED) && !bConnect) { - m_state = TCP_ESTABLISHED; - LOG(LS_INFO) << "State: TCP_ESTABLISHED"; - adjustMTU(); - if (m_notify) { - m_notify->OnTcpOpen(this); - } - //notify(evOpen); - } - - // If we make room in the send queue, notify the user - // The goal it to make sure we always have at least enough data to fill the - // window. We'd like to notify the app when we are halfway to that point. - const uint32 kIdealRefillSize = (sizeof(m_sbuf) + sizeof(m_rbuf)) / 2; - if (m_bWriteEnable && (m_slen < kIdealRefillSize)) { - m_bWriteEnable = false; - if (m_notify) { - m_notify->OnTcpWriteable(this); - } - //notify(evWrite); - } - } else if (seg.ack == m_snd_una) { - // !?! Note, tcp says don't do this... but otherwise how does a closed window become open? - m_snd_wnd = seg.wnd; - - // Check duplicate acks - if (seg.len > 0) { - // it's a dup ack, but with a data payload, so don't modify m_dup_acks - } else if (m_snd_una != m_snd_nxt) { - m_dup_acks += 1; - if (m_dup_acks == 3) { // (Fast Retransmit) -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "enter recovery"; - LOG(LS_INFO) << "recovery retransmit"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return false; - } - m_recover = m_snd_nxt; - uint32 nInFlight = m_snd_nxt - m_snd_una; - m_ssthresh = talk_base::_max(nInFlight / 2, 2 * m_mss); - //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << " nInFlight: " << nInFlight << " m_mss: " << m_mss; - m_cwnd = m_ssthresh + 3 * m_mss; - } else if (m_dup_acks > 3) { - m_cwnd += m_mss; - } - } else { - m_dup_acks = 0; - } - } - - // Conditions were acks must be sent: - // 1) Segment is too old (they missed an ACK) (immediately) - // 2) Segment is too new (we missed a segment) (immediately) - // 3) Segment has data (so we need to ACK!) (delayed) - // ... so the only time we don't need to ACK, is an empty segment that points to rcv_nxt! - - SendFlags sflags = sfNone; - if (seg.seq != m_rcv_nxt) { - sflags = sfImmediateAck; // (Fast Recovery) - } else if (seg.len != 0) { - sflags = sfDelayedAck; - } -#if _DEBUGMSG >= _DBG_NORMAL - if (sflags == sfImmediateAck) { - if (seg.seq > m_rcv_nxt) { - LOG_F(LS_INFO) << "too new"; - } else if (seg.seq + seg.len <= m_rcv_nxt) { - LOG_F(LS_INFO) << "too old"; - } - } -#endif // _DEBUGMSG - - // Adjust the incoming segment to fit our receive buffer - if (seg.seq < m_rcv_nxt) { - uint32 nAdjust = m_rcv_nxt - seg.seq; - if (nAdjust < seg.len) { - seg.seq += nAdjust; - seg.data += nAdjust; - seg.len -= nAdjust; - } else { - seg.len = 0; - } - } - if ((seg.seq + seg.len - m_rcv_nxt) > (sizeof(m_rbuf) - m_rlen)) { - uint32 nAdjust = seg.seq + seg.len - m_rcv_nxt - (sizeof(m_rbuf) - m_rlen); - if (nAdjust < seg.len) { - seg.len -= nAdjust; - } else { - seg.len = 0; - } - } - - bool bIgnoreData = (seg.flags & FLAG_CTL) || (m_shutdown != SD_NONE); - bool bNewData = false; - - if (seg.len > 0) { - if (bIgnoreData) { - if (seg.seq == m_rcv_nxt) { - m_rcv_nxt += seg.len; - } - } else { - uint32 nOffset = seg.seq - m_rcv_nxt; - memcpy(m_rbuf + m_rlen + nOffset, seg.data, seg.len); - if (seg.seq == m_rcv_nxt) { - m_rlen += seg.len; - m_rcv_nxt += seg.len; - m_rcv_wnd -= seg.len; - bNewData = true; - - RList::iterator it = m_rlist.begin(); - while ((it != m_rlist.end()) && (it->seq <= m_rcv_nxt)) { - if (it->seq + it->len > m_rcv_nxt) { - sflags = sfImmediateAck; // (Fast Recovery) - uint32 nAdjust = (it->seq + it->len) - m_rcv_nxt; -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "Recovered " << nAdjust << " bytes (" << m_rcv_nxt << " -> " << m_rcv_nxt + nAdjust << ")"; -#endif // _DEBUGMSG - m_rlen += nAdjust; - m_rcv_nxt += nAdjust; - m_rcv_wnd -= nAdjust; - } - it = m_rlist.erase(it); - } - } else { -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "Saving " << seg.len << " bytes (" << seg.seq << " -> " << seg.seq + seg.len << ")"; -#endif // _DEBUGMSG - RSegment rseg; - rseg.seq = seg.seq; - rseg.len = seg.len; - RList::iterator it = m_rlist.begin(); - while ((it != m_rlist.end()) && (it->seq < rseg.seq)) { - ++it; - } - m_rlist.insert(it, rseg); - } - } - } - - attemptSend(sflags); - - // If we have new data, notify the user - if (bNewData && m_bReadEnable) { - m_bReadEnable = false; - if (m_notify) { - m_notify->OnTcpReadable(this); - } - //notify(evRead); - } - - return true; -} - -bool -PseudoTcp::transmit(const SList::iterator& seg, uint32 now) { - if (seg->xmit >= ((m_state == TCP_ESTABLISHED) ? 15 : 30)) { - LOG_F(LS_VERBOSE) << "too many retransmits"; - return false; - } - - uint32 nTransmit = talk_base::_min(seg->len, m_mss); - - while (true) { - uint32 seq = seg->seq; - uint8 flags = (seg->bCtrl ? FLAG_CTL : 0); - const char * buffer = m_sbuf + (seg->seq - m_snd_una); - IPseudoTcpNotify::WriteResult wres = this->packet(seq, flags, buffer, nTransmit); - - if (wres == IPseudoTcpNotify::WR_SUCCESS) - break; - - if (wres == IPseudoTcpNotify::WR_FAIL) { - LOG_F(LS_VERBOSE) << "packet failed"; - return false; - } - - ASSERT(wres == IPseudoTcpNotify::WR_TOO_LARGE); - - while (true) { - if (PACKET_MAXIMUMS[m_msslevel + 1] == 0) { - LOG_F(LS_VERBOSE) << "MTU too small"; - return false; - } - // !?! We need to break up all outstanding and pending packets and then retransmit!?! - - m_mss = PACKET_MAXIMUMS[++m_msslevel] - PACKET_OVERHEAD; - m_cwnd = 2 * m_mss; // I added this... haven't researched actual formula - if (m_mss < nTransmit) { - nTransmit = m_mss; - break; - } - } -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes"; -#endif // _DEBUGMSG - } - - if (nTransmit < seg->len) { - LOG_F(LS_VERBOSE) << "mss reduced to " << m_mss; - - SSegment subseg(seg->seq + nTransmit, seg->len - nTransmit, seg->bCtrl); - //subseg.tstamp = seg->tstamp; - subseg.xmit = seg->xmit; - seg->len = nTransmit; - - SList::iterator next = seg; - m_slist.insert(++next, subseg); - } - - if (seg->xmit == 0) { - m_snd_nxt += seg->len; - } - seg->xmit += 1; - //seg->tstamp = now; - if (m_rto_base == 0) { - m_rto_base = now; - } - - return true; -} - -void -PseudoTcp::attemptSend(SendFlags sflags) { - uint32 now = Now(); - - if (talk_base::TimeDiff(now, m_lastsend) > static_cast<long>(m_rx_rto)) { - m_cwnd = m_mss; - } - -#if _DEBUGMSG - bool bFirst = true; - UNUSED(bFirst); -#endif // _DEBUGMSG - - while (true) { - uint32 cwnd = m_cwnd; - if ((m_dup_acks == 1) || (m_dup_acks == 2)) { // Limited Transmit - cwnd += m_dup_acks * m_mss; - } - uint32 nWindow = talk_base::_min(m_snd_wnd, cwnd); - uint32 nInFlight = m_snd_nxt - m_snd_una; - uint32 nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0; - - uint32 nAvailable = talk_base::_min(m_slen - nInFlight, m_mss); - - if (nAvailable > nUseable) { - if (nUseable * 4 < nWindow) { - // RFC 813 - avoid SWS - nAvailable = 0; - } else { - nAvailable = nUseable; - } - } - -#if _DEBUGMSG >= _DBG_VERBOSE - if (bFirst) { - bFirst = false; - LOG(LS_INFO) << "[cwnd: " << m_cwnd - << " nWindow: " << nWindow - << " nInFlight: " << nInFlight - << " nAvailable: " << nAvailable - << " nQueued: " << m_slen - nInFlight - << " nEmpty: " << sizeof(m_sbuf) - m_slen - << " ssthresh: " << m_ssthresh << "]"; - } -#endif // _DEBUGMSG - - if (nAvailable == 0) { - if (sflags == sfNone) - return; - - // If this is an immediate ack, or the second delayed ack - if ((sflags == sfImmediateAck) || m_t_ack) { - packet(m_snd_nxt, 0, 0, 0); - } else { - m_t_ack = Now(); - } - return; - } - - // Nagle algorithm - if ((m_snd_nxt > m_snd_una) && (nAvailable < m_mss)) { - return; - } - - // Find the next segment to transmit - SList::iterator it = m_slist.begin(); - while (it->xmit > 0) { - ++it; - ASSERT(it != m_slist.end()); - } - SList::iterator seg = it; - - // If the segment is too large, break it into two - if (seg->len > nAvailable) { - SSegment subseg(seg->seq + nAvailable, seg->len - nAvailable, seg->bCtrl); - seg->len = nAvailable; - m_slist.insert(++it, subseg); - } - - if (!transmit(seg, now)) { - LOG_F(LS_VERBOSE) << "transmit failed"; - // TODO: consider closing socket - return; - } - - sflags = sfNone; - } -} - -void -PseudoTcp::closedown(uint32 err) { - m_slen = 0; - - LOG(LS_INFO) << "State: TCP_CLOSED"; - m_state = TCP_CLOSED; - if (m_notify) { - m_notify->OnTcpClosed(this, err); - } - //notify(evClose, err); -} - -void -PseudoTcp::adjustMTU() { - // Determine our current mss level, so that we can adjust appropriately later - for (m_msslevel = 0; PACKET_MAXIMUMS[m_msslevel + 1] > 0; ++m_msslevel) { - if (static_cast<uint16>(PACKET_MAXIMUMS[m_msslevel]) <= m_mtu_advise) { - break; - } - } - m_mss = m_mtu_advise - PACKET_OVERHEAD; - // !?! Should we reset m_largest here? -#if _DEBUGMSG >= _DBG_NORMAL - LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes"; -#endif // _DEBUGMSG - // Enforce minimums on ssthresh and cwnd - m_ssthresh = talk_base::_max(m_ssthresh, 2 * m_mss); - m_cwnd = talk_base::_max(m_cwnd, m_mss); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/pseudotcp.h b/third_party/libjingle/files/talk/p2p/base/pseudotcp.h deleted file mode 100644 index cce23e1..0000000 --- a/third_party/libjingle/files/talk/p2p/base/pseudotcp.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __PSEUDOTCP_H__ -#define __PSEUDOTCP_H__ - -#include <list> -#include "talk/base/basictypes.h" - -namespace cricket { - -////////////////////////////////////////////////////////////////////// -// IPseudoTcpNotify -////////////////////////////////////////////////////////////////////// - -class PseudoTcp; - -class IPseudoTcpNotify { -public: - // Notification of tcp events - virtual void OnTcpOpen(PseudoTcp * tcp) = 0; - virtual void OnTcpReadable(PseudoTcp * tcp) = 0; - virtual void OnTcpWriteable(PseudoTcp * tcp) = 0; - virtual void OnTcpClosed(PseudoTcp * tcp, uint32 nError) = 0; - - // Write the packet onto the network - enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL }; - virtual WriteResult TcpWritePacket(PseudoTcp * tcp, const char * buffer, size_t len) = 0; -}; - -////////////////////////////////////////////////////////////////////// -// PseudoTcp -////////////////////////////////////////////////////////////////////// - -class PseudoTcp { -public: - static uint32 Now(); - - PseudoTcp(IPseudoTcpNotify * notify, uint32 conv); - virtual ~PseudoTcp(); - - int Connect(); - int Recv(char * buffer, size_t len); - int Send(const char * buffer, size_t len); - void Close(bool force); - int GetError(); - - enum TcpState { TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED }; - TcpState State() const { return m_state; } - - // Call this when the PMTU changes. - void NotifyMTU(uint16 mtu); - - // Call this based on timeout value returned from GetNextClock. - // It's ok to call this too frequently. - void NotifyClock(uint32 now); - - // Call this whenever a packet arrives. - // Returns true if the packet was processed successfully. - bool NotifyPacket(const char * buffer, size_t len); - - // Call this to determine the next time NotifyClock should be called. - // Returns false if the socket is ready to be destroyed. - bool GetNextClock(uint32 now, long& timeout); - -protected: - enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck }; - enum { - // Note: can't go as high as 1024 * 64, because of uint16 precision - kRcvBufSize = 1024 * 60, - // Note: send buffer should be larger to make sure we can always fill the - // receiver window - kSndBufSize = 1024 * 90 - }; - - struct Segment { - uint32 conv, seq, ack; - uint8 flags; - uint16 wnd; - const char * data; - uint32 len; - uint32 tsval, tsecr; - }; - - struct SSegment { - uint32 seq, len; - //uint32 tstamp; - uint8 xmit; - bool bCtrl; - - SSegment(uint32 s, uint32 l, bool c) : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) { } - }; - typedef std::list<SSegment> SList; - - struct RSegment { - uint32 seq, len; - }; - - uint32 queue(const char * data, uint32 len, bool bCtrl); - - IPseudoTcpNotify::WriteResult packet(uint32 seq, uint8 flags, const char * data, uint32 len); - bool parse(const uint8 * buffer, uint32 size); - - void attemptSend(SendFlags sflags = sfNone); - - void closedown(uint32 err = 0); - - bool clock_check(uint32 now, long& nTimeout); - - bool process(Segment& seg); - bool transmit(const SList::iterator& seg, uint32 now); - - void adjustMTU(); - -private: - IPseudoTcpNotify * m_notify; - enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown; - int m_error; - - // TCB data - TcpState m_state; - uint32 m_conv; - bool m_bReadEnable, m_bWriteEnable, m_bOutgoing; - uint32 m_lasttraffic; - - // Incoming data - typedef std::list<RSegment> RList; - RList m_rlist; - char m_rbuf[kRcvBufSize]; - uint32 m_rcv_nxt, m_rcv_wnd, m_rlen, m_lastrecv; - - // Outgoing data - SList m_slist; - char m_sbuf[kSndBufSize]; - uint32 m_snd_nxt, m_snd_wnd, m_slen, m_lastsend, m_snd_una; - // Maximum segment size, estimated protocol level, largest segment sent - uint32 m_mss, m_msslevel, m_largest, m_mtu_advise; - // Retransmit timer - uint32 m_rto_base; - - // Timestamp tracking - uint32 m_ts_recent, m_ts_lastack; - - // Round-trip calculation - uint32 m_rx_rttvar, m_rx_srtt, m_rx_rto; - - // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs - uint32 m_ssthresh, m_cwnd; - uint8 m_dup_acks; - uint32 m_recover; - uint32 m_t_ack; -}; - -////////////////////////////////////////////////////////////////////// - -} // namespace cricket - -#endif // __PSEUDOTCP_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/rawtransport.cc b/third_party/libjingle/files/talk/p2p/base/rawtransport.cc deleted file mode 100644 index 0df4d5f..0000000 --- a/third_party/libjingle/files/talk/p2p/base/rawtransport.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/rawtransport.h" -#include "talk/base/common.h" -#include "talk/p2p/base/constants.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/base/rawtransportchannel.h" -#include "talk/xmllite/qname.h" -#include "talk/xmllite/xmlelement.h" -#include "talk/xmpp/xmppconstants.h" - -namespace cricket { - -const std::string kNsRawTransport("http://www.google.com/transport/raw-udp"); -const buzz::QName kQnRawTransport(true, kNsRawTransport, "transport"); -const buzz::QName kQnRawChannel(true, kNsRawTransport, "channel"); -const buzz::QName kQnRawBehindSymmetricNat(true, buzz::STR_EMPTY, - "behind-symmetric-nat"); -const buzz::QName kQnRawCanReceiveFromSymmetricNat(true, buzz::STR_EMPTY, - "can-receive-from-symmetric-nat"); - -RawTransport::RawTransport(SessionManager* session_manager) - : Transport(session_manager, kNsRawTransport) { -} - -RawTransport::~RawTransport() { - DestroyAllChannels(); -} - -buzz::XmlElement* RawTransport::CreateTransportOffer() { - buzz::XmlElement* xml = new buzz::XmlElement(kQnRawTransport, true); - - // Assume that we are behind a symmetric NAT. Also note that we can't - // handle the adjustment necessary to talk to someone else who is behind - // a symmetric NAT. - xml->AddAttr(kQnRawBehindSymmetricNat, "true"); - xml->AddAttr(kQnRawCanReceiveFromSymmetricNat, "false"); - - return xml; -} - -buzz::XmlElement* RawTransport::CreateTransportAnswer() { - return new buzz::XmlElement(kQnRawTransport, true); -} - -bool RawTransport::OnTransportOffer(const buzz::XmlElement* elem) { - ASSERT(elem->Name() == kQnRawTransport); - - // If the other side is behind a symmetric NAT then we can't talk to him. - // We also bail if this attribute isn't specified. - if (!elem->HasAttr(kQnRawBehindSymmetricNat) - || elem->Attr(kQnRawBehindSymmetricNat) != "false") { - return false; - } - - // If the other side doesn't explicitly state that he can receive from - // someone behind a symmetric NAT, we bail. - if (!elem->HasAttr(kQnRawCanReceiveFromSymmetricNat) - || elem->Attr(kQnRawCanReceiveFromSymmetricNat) != "true") { - return false; - } - - // We don't support any options, so we ignore them. - return true; -} - -bool RawTransport::OnTransportAnswer(const buzz::XmlElement* elem) { - ASSERT(elem->Name() == kQnRawTransport); - // We don't support any options. We fail if any are given. The other side - // should know from our request that we expected an empty response. - return elem->FirstChild() == NULL; -} - -bool RawTransport::OnTransportMessage(const buzz::XmlElement* msg, - const buzz::XmlElement* stanza) { - ASSERT(msg->Name() == kQnRawTransport); - for (const buzz::XmlElement* elem = msg->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - if (elem->Name() == kQnRawChannel) { - talk_base::SocketAddress addr; - if (!ParseAddress(stanza, elem, &addr)) - return false; - - ForwardChannelMessage(elem->Attr(buzz::QN_NAME), - new buzz::XmlElement(*elem)); - } - } - return true; -} - -bool RawTransport::OnTransportError(const buzz::XmlElement* session_msg, - const buzz::XmlElement* error) { - return true; -} - -bool RawTransport::ParseAddress(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - talk_base::SocketAddress* addr) { - // Make sure the required attributes exist - if (!elem->HasAttr(buzz::QN_NAME) || - !elem->HasAttr(QN_ADDRESS) || - !elem->HasAttr(QN_PORT)) { - return BadRequest(stanza, "channel missing required attribute", NULL); - } - - // Make sure the channel named actually exists. - if (!HasChannel(elem->Attr(buzz::QN_NAME))) - return BadRequest(stanza, "channel named does not exist", NULL); - - // Parse the address. - return Transport::ParseAddress(stanza, elem, addr); -} - -TransportChannelImpl* RawTransport::CreateTransportChannel( - const std::string& name, const std::string &session_type) { - return new RawTransportChannel( - name, session_type, this, session_manager()->port_allocator()); -} - -void RawTransport::DestroyTransportChannel(TransportChannelImpl* channel) { - delete channel; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/rawtransport.h b/third_party/libjingle/files/talk/p2p/base/rawtransport.h deleted file mode 100644 index d273b40..0000000 --- a/third_party/libjingle/files/talk/p2p/base/rawtransport.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_RAWTRANSPORT_H_ -#define _CRICKET_P2P_BASE_RAWTRANSPORT_H_ - -#include "talk/p2p/base/transport.h" - -namespace cricket { - -// Xml names used to name this transport and create our elements -extern const std::string kNsRawTransport; -extern const buzz::QName kQnRawTransport; -extern const buzz::QName kQnRawChannel; -extern const buzz::QName kQnRawNatType; -extern const buzz::QName kQnRawNatTypeAllowed; - -// Implements a transport that only sends raw packets, no STUN. As a result, -// it cannot do pings to determine connectivity, so it only uses a single port -// that it thinks will work. -class RawTransport: public Transport { - public: - RawTransport(SessionManager* session_manager); - virtual ~RawTransport(); - - // Handles the raw transport protocol descriptions, which are trivial. - virtual buzz::XmlElement* CreateTransportOffer(); - virtual buzz::XmlElement* CreateTransportAnswer(); - virtual bool OnTransportOffer(const buzz::XmlElement* elem); - virtual bool OnTransportAnswer(const buzz::XmlElement* elem); - - // Forwards messages containing channel addresses to the appropriate channel. - virtual bool OnTransportMessage(const buzz::XmlElement* msg, - const buzz::XmlElement* stanza); - virtual bool OnTransportError(const buzz::XmlElement* session_msg, - const buzz::XmlElement* error); - - protected: - // Creates and destroys raw channels. - virtual TransportChannelImpl* CreateTransportChannel( - const std::string& name, const std::string &session_type); - virtual void DestroyTransportChannel(TransportChannelImpl* channel); - - private: - // Parses the given element, which should describe the address to use for a - // given channel. This will return false and signal an error if the address - // or channel name is bad. - bool ParseAddress(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - talk_base::SocketAddress* addr); - - friend class RawTransportChannel; // For ParseAddress. - - DISALLOW_EVIL_CONSTRUCTORS(RawTransport); -}; - -} // namespace cricket - - -#endif // _CRICKET_P2P_BASE_RAWTRANSPORT_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.cc b/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.cc deleted file mode 100644 index 9b56530..0000000 --- a/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.cc +++ /dev/null @@ -1,259 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/rawtransportchannel.h" -#include "talk/base/common.h" -#include "talk/p2p/base/constants.h" -#include "talk/p2p/base/port.h" -#include "talk/p2p/base/portallocator.h" -#include "talk/p2p/base/rawtransport.h" -#include "talk/p2p/base/relayport.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/base/stunport.h" -#include "talk/xmllite/qname.h" -#include "talk/xmllite/xmlelement.h" -#include "talk/xmpp/xmppconstants.h" - -namespace { - -const int MSG_DESTROY_UNUSED_PORTS = 1; - -} // namespace - -namespace cricket { - -RawTransportChannel::RawTransportChannel( - const std::string &name, const std::string &session_type, RawTransport* transport, - PortAllocator *allocator) - : TransportChannelImpl(name, session_type), raw_transport_(transport), - allocator_(allocator), allocator_session_(NULL), stun_port_(NULL), - relay_port_(NULL), port_(NULL), use_relay_(false) { -} - -RawTransportChannel::~RawTransportChannel() { - delete allocator_session_; -} - -int RawTransportChannel::SendPacket(const char *data, size_t size) { - if (port_ == NULL) - return -1; - if (remote_address_.IsAny()) - return -1; - return port_->SendTo(data, size, remote_address_, true); -} - -int RawTransportChannel::SetOption(talk_base::Socket::Option opt, int value) { - // TODO: allow these to be set before we have a port - if (port_ == NULL) - return -1; - return port_->SetOption(opt, value); -} - -int RawTransportChannel::GetError() { - return (port_ != NULL) ? port_->GetError() : 0; -} - -void RawTransportChannel::Connect() { - // Create an allocator that only returns stun and relay ports. - allocator_session_ = allocator_->CreateSession(name(), session_type()); - - uint32 flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP; - -#if !defined(FEATURE_ENABLE_STUN_CLASSIFICATION) - flags |= PORTALLOCATOR_DISABLE_RELAY; -#endif - allocator_session_->set_flags(flags); - allocator_session_->SignalPortReady.connect( - this, &RawTransportChannel::OnPortReady); - allocator_session_->SignalCandidatesReady.connect( - this, &RawTransportChannel::OnCandidatesReady); - - // The initial ports will include stun. - allocator_session_->GetInitialPorts(); -} - -void RawTransportChannel::Reset() { - set_readable(false); - set_writable(false); - - delete allocator_session_; - - allocator_session_ = NULL; - stun_port_ = NULL; - relay_port_ = NULL; - port_ = NULL; - remote_address_ = talk_base::SocketAddress(); -} - -void RawTransportChannel::OnChannelMessage(const buzz::XmlElement* msg) { - bool valid = raw_transport_->ParseAddress(NULL, msg, &remote_address_); - ASSERT(valid); - ASSERT(!remote_address_.IsAny()); - set_readable(true); - - // We can write once we have a port and a remote address. - if (port_ != NULL) - SetWritable(); -} - -// Note about stun classification -// Code to classify our NAT type and use the relay port if we are behind an -// asymmetric NAT is under a FEATURE_ENABLE_STUN_CLASSIFICATION #define. -// To turn this one we will have to enable a second stun address and make sure -// that the relay server works for raw UDP. -// -// Another option is to classify the NAT type early and not offer the raw -// transport type at all if we can't support it. - -void RawTransportChannel::OnPortReady( - PortAllocatorSession* session, Port* port) { - ASSERT(session == allocator_session_); - - if (port->type() == STUN_PORT_TYPE) { - stun_port_ = static_cast<StunPort*>(port); - -#if defined(FEATURE_ENABLE_STUN_CLASSIFICATION) - // We need a secondary address to determine the NAT type. - stun_port_->PrepareSecondaryAddress(); -#endif - } else if (port->type() == RELAY_PORT_TYPE) { - relay_port_ = static_cast<RelayPort*>(port); - } else { - ASSERT(false); - } -} - -void RawTransportChannel::OnCandidatesReady( - PortAllocatorSession *session, const std::vector<Candidate>& candidates) { - ASSERT(session == allocator_session_); - ASSERT(candidates.size() >= 1); - - // The most recent candidate is the one we haven't seen yet. - Candidate c = candidates[candidates.size() - 1]; - - if (c.type() == STUN_PORT_TYPE) { - ASSERT(stun_port_ != NULL); - -#if defined(FEATURE_ENABLE_STUN_CLASSIFICATION) - // We need to wait until we have two addresses. - if (stun_port_->candidates().size() < 2) - return; - - // This is the second address. If these addresses are the same, then we - // are not behind a symmetric NAT. Hence, a stun port should be sufficient. - if (stun_port_->candidates()[0].address() == - stun_port_->candidates()[1].address()) { - SetPort(stun_port_); - return; - } - - // We will need to use relay. - use_relay_ = true; - - // If we weren't given a relay port, we'll need to request it. - if (relay_port_ == NULL) { - allocator_session_->StartGetAllPorts(); - return; - } - - // If we already have a relay address, we're good. Otherwise, we will need - // to wait until one arrives. - if (relay_port_->candidates().size() > 0) - SetPort(relay_port_); -#else // defined(FEATURE_ENABLE_STUN_CLASSIFICATION) - // Always use the stun port. We don't classify right now so just assume it - // will work fine. - SetPort(stun_port_); -#endif - } else if (c.type() == RELAY_PORT_TYPE) { - if (use_relay_) - SetPort(relay_port_); - } else { - ASSERT(false); - } -} - -void RawTransportChannel::SetPort(Port* port) { - ASSERT(port_ == NULL); - port_ = port; - - // We don't need any ports other than the one we picked. - allocator_session_->StopGetAllPorts(); - raw_transport_->session_manager()->worker_thread()->Post( - this, MSG_DESTROY_UNUSED_PORTS, NULL); - - // Send a message to the other client containing our address. - - ASSERT(port_->candidates().size() >= 1); - ASSERT(port_->candidates()[0].protocol() == "udp"); - talk_base::SocketAddress addr = port_->candidates()[0].address(); - - buzz::XmlElement* msg = new buzz::XmlElement(kQnRawChannel); - msg->SetAttr(buzz::QN_NAME, name()); - msg->SetAttr(QN_ADDRESS, addr.IPAsString()); - msg->SetAttr(QN_PORT, addr.PortAsString()); - SignalChannelMessage(this, msg); - - // Read all packets from this port. - port_->EnablePortPackets(); - port_->SignalReadPacket.connect(this, &RawTransportChannel::OnReadPacket); - - // We can write once we have a port and a remote address. - if (!remote_address_.IsAny()) - SetWritable(); -} - -void RawTransportChannel::SetWritable() { - ASSERT(port_ != NULL); - ASSERT(!remote_address_.IsAny()); - - set_writable(true); - - SignalRouteChange(this, remote_address_); -} - -void RawTransportChannel::OnReadPacket( - Port* port, const char* data, size_t size, - const talk_base::SocketAddress& addr) { - ASSERT(port_ == port); - SignalReadPacket(this, data, size); -} - -void RawTransportChannel::OnMessage(talk_base::Message* msg) { - ASSERT(msg->message_id == MSG_DESTROY_UNUSED_PORTS); - ASSERT(port_ != NULL); - if (port_ != stun_port_) { - stun_port_->Destroy(); - stun_port_ = NULL; - } - if (port_ != relay_port_ && relay_port_ != NULL) { - relay_port_->Destroy(); - relay_port_ = NULL; - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.h b/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.h deleted file mode 100644 index 9dcbae2..0000000 --- a/third_party/libjingle/files/talk/p2p/base/rawtransportchannel.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_ -#define _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_ - -#include "talk/base/messagequeue.h" -#include "talk/p2p/base/transportchannelimpl.h" -#include "talk/p2p/base/rawtransport.h" -#include "talk/p2p/base/candidate.h" - -namespace cricket { - -class Port; -class Connection; -class StunPort; -class RelayPort; -class PortAllocator; -class PortAllocatorSession; - -// Implements a channel that just sends bare packets once we have received the -// address of the other side. We pick a single address to send them based on -// a simple investigation of NAT type. -class RawTransportChannel : public TransportChannelImpl, - public talk_base::MessageHandler { - public: - RawTransportChannel(const std::string &name, - const std::string &session_type, - RawTransport* transport, - PortAllocator *allocator); - virtual ~RawTransportChannel(); - - // Implementation of normal channel packet sending. - virtual int SendPacket(const char *data, size_t len); - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - - // Returns the raw transport that created this channel. - virtual Transport* GetTransport() { return raw_transport_; } - - // Creates an allocator session to start figuring out which type of port we - // should send to the other client. This will send SignalChannelMessage once - // we have decided. - virtual void Connect(); - - // Resets state back to unconnected. - virtual void Reset(); - - // We don't actually worry about signaling since we can't send new candidates. - virtual void OnSignalingReady() {} - - // Handles a message setting the remote address. We are writable once we - // have this since we now know where to send. - virtual void OnChannelMessage(const buzz::XmlElement* msg); - - private: - RawTransport* raw_transport_; - PortAllocator* allocator_; - PortAllocatorSession* allocator_session_; - StunPort* stun_port_; - RelayPort* relay_port_; - Port* port_; - bool use_relay_; - talk_base::SocketAddress remote_address_; - - // Called when the allocator creates another port. - void OnPortReady(PortAllocatorSession* session, Port* port); - - // Called when one of the ports we are using has determined its address. - void OnCandidatesReady(PortAllocatorSession *session, - const std::vector<Candidate>& candidates); - - // Called once we have chosen the port to use for communication with the - // other client. This will send its address and prepare the port for use. - void SetPort(Port* port); - - // Called once we have a port and a remote address. This will set mark the - // channel as writable and signal the route to the client. - void SetWritable(); - - // Called when we receive a packet from the other client. - void OnReadPacket(Port* port, const char* data, size_t size, - const talk_base::SocketAddress& addr); - - // Handles a message to destroy unused ports. - virtual void OnMessage(talk_base::Message *msg); - - DISALLOW_EVIL_CONSTRUCTORS(RawTransportChannel); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/relayport.cc b/third_party/libjingle/files/talk/p2p/base/relayport.cc deleted file mode 100644 index c4b5066..0000000 --- a/third_party/libjingle/files/talk/p2p/base/relayport.cc +++ /dev/null @@ -1,635 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif -#include "talk/base/logging.h" -#include "talk/base/asynctcpsocket.h" -#include "talk/base/helpers.h" -#include "talk/p2p/base/relayport.h" -#include <iostream> -#include <cassert> -#include <cstring> -#ifdef OSX -#include <errno.h> -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std { - using ::strerror; -} -#endif - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -namespace talk_base { -class AsyncTCPSocket; -}; - -namespace cricket { - -const int KEEPALIVE_DELAY = 10 * 60 * 1000; -const int RETRY_DELAY = 50; // 50ms, from ICE spec -const uint32 RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs - -// Manages a single connection to the relayserver. We aim to use each -// connection for only a specific destination address so that we can avoid -// wrapping every packet in a STUN send / data indication. -class RelayEntry : public sigslot::has_slots<> { -public: - RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr, - const talk_base::SocketAddress& local_addr); - ~RelayEntry(); - - RelayPort* port() { return port_; } - - const talk_base::SocketAddress& address() const { return ext_addr_; } - void set_address(const talk_base::SocketAddress& addr) { ext_addr_ = addr; } - - talk_base::AsyncPacketSocket* socket() { return socket_; } - - bool connected() const { return connected_; } - bool locked() const { return locked_; } - - // Returns the last error on the socket of this entry. - int GetError() const { return socket_->GetError(); } - - // Sends the STUN requests to the server to initiate this connection. - void Connect(); - - // Called when this entry becomes connected. The address given is the one - // exposed to the outside world on the relay server. - void OnConnect(const talk_base::SocketAddress& mapped_addr); - - // Sends a packet to the given destination address using the socket of this - // entry. This will wrap the packet in STUN if necessary. - int SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr); - - // Schedules a keep-alive allocate request. - void ScheduleKeepAlive(); - - void SetServerIndex(size_t sindex) { server_index_ = sindex; } - size_t ServerIndex() const { return server_index_; } - - // Try a different server address - void HandleConnectFailure(); - -private: - RelayPort* port_; - talk_base::SocketAddress ext_addr_, local_addr_; - size_t server_index_; - talk_base::AsyncPacketSocket* socket_; - bool connected_; - bool locked_; - StunRequestManager requests_; - - // Called when a TCP connection is established or fails - void OnSocketConnect(talk_base::AsyncTCPSocket* socket); - void OnSocketClose(talk_base::AsyncTCPSocket* socket, int error); - - // Called when a packet is received on this socket. - void OnReadPacket( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - - // Called on behalf of a StunRequest to write data to the socket. This is - // already STUN intended for the server, so no wrapping is necessary. - void OnSendPacket(const void* data, size_t size, StunRequest* req); - - // Sends the given data on the socket to the server with no wrapping. This - // returns the number of bytes written or -1 if an error occurred. - int SendPacket(const void* data, size_t size); -}; - -// Handles an allocate request for a particular RelayEntry. -class AllocateRequest : public StunRequest { -public: - AllocateRequest(RelayEntry* entry); - virtual ~AllocateRequest() {} - - virtual void Prepare(StunMessage* request); - - virtual int GetNextDelay(); - - virtual void OnResponse(StunMessage* response); - virtual void OnErrorResponse(StunMessage* response); - virtual void OnTimeout(); - -private: - RelayEntry* entry_; - uint32 start_time_; -}; - -const std::string RELAY_PORT_TYPE("relay"); - -RelayPort::RelayPort( - talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, const talk_base::SocketAddress& local_addr, - const std::string& username, const std::string& password, - const std::string& magic_cookie) - : Port(thread, RELAY_PORT_TYPE, factory, network), local_addr_(local_addr), - ready_(false), magic_cookie_(magic_cookie), error_(0) { - - entries_.push_back( - new RelayEntry(this, talk_base::SocketAddress(), local_addr_)); - - set_username_fragment(username); - set_password(password); - - if (magic_cookie_.size() == 0) - magic_cookie_.append(STUN_MAGIC_COOKIE_VALUE, 4); -} - -RelayPort::~RelayPort() { - for (unsigned i = 0; i < entries_.size(); ++i) - delete entries_[i]; - thread_->Clear(this); -} - -void RelayPort::AddServerAddress(const ProtocolAddress& addr) { - // Since HTTP proxies usually only allow 443, let's up the priority on PROTO_SSLTCP - if ((addr.proto == PROTO_SSLTCP) - && ((proxy().type == talk_base::PROXY_HTTPS) - || (proxy().type == talk_base::PROXY_UNKNOWN))) { - server_addr_.push_front(addr); - } else { - server_addr_.push_back(addr); - } -} - -void RelayPort::AddExternalAddress(const ProtocolAddress& addr) { - std::string proto_name = ProtoToString(addr.proto); - for (std::vector<Candidate>::const_iterator it = candidates().begin(); it != candidates().end(); ++it) { - if ((it->address() == addr.address) && (it->protocol() == proto_name)) { - LOG(INFO) << "Redundant relay address: " << proto_name << " @ " << addr.address.ToString(); - return; - } - } - AddAddress(addr.address, proto_name, false); -} - -void RelayPort::SetReady() { - if (!ready_) { - ready_ = true; - SignalAddressReady(this); - } -} - -const ProtocolAddress * RelayPort::ServerAddress(size_t index) const { - if ((index >= 0) && (index < server_addr_.size())) - return &server_addr_[index]; - return 0; -} - -bool RelayPort::HasMagicCookie(const char* data, size_t size) { - if (size < 24 + magic_cookie_.size()) { - return false; - } else { - return 0 == std::memcmp(data + 24, - magic_cookie_.c_str(), - magic_cookie_.size()); - } -} - -void RelayPort::PrepareAddress() { - // We initiate a connect on the first entry. If this completes, it will fill - // in the server address as the address of this port. - assert(entries_.size() == 1); - entries_[0]->Connect(); - ready_ = false; -} - -Connection* RelayPort::CreateConnection(const Candidate& address, CandidateOrigin origin) { - // We only create connections to non-udp sockets if they are incoming on this port - if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT)) - return 0; - - // We don't support loopback on relays - if (address.type() == type()) - return 0; - - size_t index = 0; - for (size_t i = 0; i < candidates().size(); ++i) { - const Candidate& local = candidates()[i]; - if (local.protocol() == address.protocol()) { - index = i; - break; - } - } - - Connection * conn = new ProxyConnection(this, index, address); - AddConnection(conn); - return conn; -} - -int RelayPort::SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload) { - - // Try to find an entry for this specific address. Note that the first entry - // created was not given an address initially, so it can be set to the first - // address that comes along. - - RelayEntry* entry = 0; - - for (unsigned i = 0; i < entries_.size(); ++i) { - if (entries_[i]->address().IsAny() && payload) { - entry = entries_[i]; - entry->set_address(addr); - break; - } else if (entries_[i]->address() == addr) { - entry = entries_[i]; - break; - } - } - - // If we did not find one, then we make a new one. This will not be useable - // until it becomes connected, however. - if (!entry && payload) { - entry = new RelayEntry(this, addr, local_addr_); - if (!entries_.empty()) { - // Use the same port to connect to relay server - entry->SetServerIndex(entries_[0]->ServerIndex()); - } - entry->Connect(); - entries_.push_back(entry); - } - - // If the entry is connected, then we can send on it (though wrapping may - // still be necessary). Otherwise, we can't yet use this connection, so we - // default to the first one. - if (!entry || !entry->connected()) { - assert(!entries_.empty()); - entry = entries_[0]; - if (!entry->connected()) { - error_ = EWOULDBLOCK; - return SOCKET_ERROR; - } - } - - // Send the actual contents to the server using the usual mechanism. - int sent = entry->SendTo(data, size, addr); - if (sent <= 0) { - assert(sent < 0); - error_ = entry->GetError(); - return SOCKET_ERROR; - } - - // The caller of the function is expecting the number of user data bytes, - // rather than the size of the packet. - return (int)size; -} - -int RelayPort::SetOption(talk_base::Socket::Option opt, int value) { - int result = 0; - for (unsigned i = 0; i < entries_.size(); ++i) { - if (entries_[i]->socket()->SetOption(opt, value) < 0) { - result = -1; - error_ = entries_[i]->socket()->GetError(); - } - } - options_.push_back(OptionValue(opt, value)); - return result; -} - -int RelayPort::GetError() { - return error_; -} - -void RelayPort::OnReadPacket( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr) { - if (Connection* conn = GetConnection(remote_addr)) { - conn->OnReadPacket(data, size); - } else { - Port::OnReadPacket(data, size, remote_addr); - } -} - -void RelayPort::DisposeSocket(talk_base::AsyncPacketSocket * socket) { - thread_->Dispose(socket); -} - -RelayEntry::RelayEntry(RelayPort* port, - const talk_base::SocketAddress& ext_addr, - const talk_base::SocketAddress& local_addr) - : port_(port), ext_addr_(ext_addr), local_addr_(local_addr), server_index_(0), - socket_(0), connected_(false), locked_(false), requests_(port->thread()) { - - requests_.SignalSendPacket.connect(this, &RelayEntry::OnSendPacket); -} - -RelayEntry::~RelayEntry() { - delete socket_; -} - -void RelayEntry::Connect() { - assert(socket_ == 0); - const ProtocolAddress * ra = port()->ServerAddress(server_index_); - if (!ra) { - LOG(INFO) << "Out of relay server connections"; - return; - } - - LOG(INFO) << "Connecting to relay via " << ProtoToString(ra->proto) << " @ " << ra->address.ToString(); - - socket_ = port_->CreatePacketSocket(ra->proto); - assert(socket_ != 0); - - socket_->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket); - if (socket_->Bind(local_addr_) < 0) - LOG(INFO) << "bind: " << std::strerror(socket_->GetError()); - - for (unsigned i = 0; i < port_->options().size(); ++i) - socket_->SetOption(port_->options()[i].first, port_->options()[i].second); - - if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) { - talk_base::AsyncTCPSocket * tcp - = static_cast<talk_base::AsyncTCPSocket *>(socket_); - tcp->SignalClose.connect(this, &RelayEntry::OnSocketClose); - tcp->SignalConnect.connect(this, &RelayEntry::OnSocketConnect); - tcp->Connect(ra->address); - } else { - requests_.Send(new AllocateRequest(this)); - } -} - -void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr) { - ProtocolType proto = PROTO_UDP; - LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) << " @ " << mapped_addr.ToString(); - connected_ = true; - - port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto)); - port_->SetReady(); -} - -int RelayEntry::SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr) { - - // If this connection is locked to the address given, then we can send the - // packet with no wrapper. - if (locked_ && (ext_addr_ == addr)) - return SendPacket(data, size); - - // Otherwise, we must wrap the given data in a STUN SEND request so that we - // can communicate the destination address to the server. - // - // Note that we do not use a StunRequest here. This is because there is - // likely no reason to resend this packet. If it is late, we just drop it. - // The next send to this address will try again. - - StunMessage request; - request.SetType(STUN_SEND_REQUEST); - request.SetTransactionID(CreateRandomString(16)); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(port_->magic_cookie().c_str(), - (uint16)port_->magic_cookie().size()); - request.AddAttribute(magic_cookie_attr); - - StunByteStringAttribute* username_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username_attr->CopyBytes(port_->username_fragment().c_str(), - (uint16)port_->username_fragment().size()); - request.AddAttribute(username_attr); - - StunAddressAttribute* addr_attr = - StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); - addr_attr->SetFamily(1); - addr_attr->SetIP(addr.ip()); - addr_attr->SetPort(addr.port()); - request.AddAttribute(addr_attr); - - // Attempt to lock - if (ext_addr_ == addr) { - StunUInt32Attribute* options_attr = - StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS); - options_attr->SetValue(0x1); - request.AddAttribute(options_attr); - } - - StunByteStringAttribute* data_attr = - StunAttribute::CreateByteString(STUN_ATTR_DATA); - data_attr->CopyBytes(data, (uint16)size); - request.AddAttribute(data_attr); - - // TODO: compute the HMAC. - - talk_base::ByteBuffer buf; - request.Write(&buf); - - return SendPacket(buf.Data(), buf.Length()); -} - -void RelayEntry::ScheduleKeepAlive() { - requests_.SendDelayed(new AllocateRequest(this), KEEPALIVE_DELAY); -} - -void RelayEntry::HandleConnectFailure() { - //if (GetMillisecondCount() - start_time_ > RETRY_TIMEOUT) - // return; - //ScheduleKeepAlive(); - - connected_ = false; - port()->DisposeSocket(socket_); - socket_ = 0; - requests_.Clear(); - - server_index_ += 1; - Connect(); -} - -void RelayEntry::OnSocketConnect(talk_base::AsyncTCPSocket* socket) { - assert(socket == socket_); - LOG(INFO) << "relay tcp connected to " << socket->GetRemoteAddress().ToString(); - requests_.Send(new AllocateRequest(this)); -} - -void RelayEntry::OnSocketClose(talk_base::AsyncTCPSocket* socket, int error) { - assert(socket == socket_); - PLOG(LERROR, error) << "relay tcp connect failed"; - HandleConnectFailure(); -} - -void RelayEntry::OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - assert(socket == socket_); - //assert(remote_addr == port_->server_addr()); TODO: are we worried about this? - - // If the magic cookie is not present, then this is an unwrapped packet sent - // by the server, The actual remote address is the one we recorded. - if (!port_->HasMagicCookie(data, size)) { - if (locked_) { - port_->OnReadPacket(data, size, ext_addr_); - } else { - LOG(WARNING) << "Dropping packet: entry not locked"; - } - return; - } - - talk_base::ByteBuffer buf(data, size); - StunMessage msg; - if (!msg.Read(&buf)) { - LOG(INFO) << "Incoming packet was not STUN"; - return; - } - - // The incoming packet should be a STUN ALLOCATE response, SEND response, or - // DATA indication. - if (requests_.CheckResponse(&msg)) { - return; - } else if (msg.type() == STUN_SEND_RESPONSE) { - if (const StunUInt32Attribute* options_attr = msg.GetUInt32(STUN_ATTR_OPTIONS)) { - if (options_attr->value() & 0x1) { - locked_ = true; - } - } - return; - } else if (msg.type() != STUN_DATA_INDICATION) { - LOG(INFO) << "Received BAD stun type from server: " << msg.type() - ; - return; - } - - // This must be a data indication. - - const StunAddressAttribute* addr_attr = - msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2); - if (!addr_attr) { - LOG(INFO) << "Data indication has no source address"; - return; - } else if (addr_attr->family() != 1) { - LOG(INFO) << "Source address has bad family"; - return; - } - - talk_base::SocketAddress remote_addr2(addr_attr->ip(), addr_attr->port()); - - const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA); - if (!data_attr) { - LOG(INFO) << "Data indication has no data"; - return; - } - - // Process the actual data and remote address in the normal manner. - port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2); -} - -void RelayEntry::OnSendPacket(const void* data, size_t size, StunRequest* req) { - SendPacket(data, size); -} - -int RelayEntry::SendPacket(const void* data, size_t size) { - const ProtocolAddress * ra = port_->ServerAddress(server_index_); - if (!ra) { - if (socket_) - socket_->SetError(ENOTCONN); - return SOCKET_ERROR; - } - int sent = socket_->SendTo(data, size, ra->address); - if (sent <= 0) { - LOG(LS_VERBOSE) << "sendto: " << std::strerror(socket_->GetError()); - assert(sent < 0); - } - return sent; -} - -AllocateRequest::AllocateRequest(RelayEntry* entry) : entry_(entry) { - start_time_ = talk_base::GetMillisecondCount(); -} - -void AllocateRequest::Prepare(StunMessage* request) { - request->SetType(STUN_ALLOCATE_REQUEST); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes( - entry_->port()->magic_cookie().c_str(), - (uint16)entry_->port()->magic_cookie().size()); - request->AddAttribute(magic_cookie_attr); - - StunByteStringAttribute* username_attr = - StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username_attr->CopyBytes( - entry_->port()->username_fragment().c_str(), - (uint16)entry_->port()->username_fragment().size()); - request->AddAttribute(username_attr); -} - -int AllocateRequest::GetNextDelay() { - int delay = 100 * talk_base::_max(1 << count_, 2); - count_ += 1; - if (count_ == 5) - timeout_ = true; - return delay; -} - -void AllocateRequest::OnResponse(StunMessage* response) { - const StunAddressAttribute* addr_attr = - response->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - if (!addr_attr) { - LOG(INFO) << "Allocate response missing mapped address."; - } else if (addr_attr->family() != 1) { - LOG(INFO) << "Mapped address has bad family"; - } else { - talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port()); - entry_->OnConnect(addr); - } - - // We will do a keep-alive regardless of whether this request suceeds. - // This should have almost no impact on network usage. - entry_->ScheduleKeepAlive(); -} - -void AllocateRequest::OnErrorResponse(StunMessage* response) { - const StunErrorCodeAttribute* attr = response->GetErrorCode(); - if (!attr) { - LOG(INFO) << "Bad allocate response error code"; - } else { - LOG(INFO) << "Allocate error response:" - << " code=" << static_cast<int>(attr->error_code()) - << " reason='" << attr->reason() << "'"; - } - - if (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT) - entry_->ScheduleKeepAlive(); -} - -void AllocateRequest::OnTimeout() { - LOG(INFO) << "Allocate request timed out"; - entry_->HandleConnectFailure(); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/relayport.h b/third_party/libjingle/files/talk/p2p/base/relayport.h deleted file mode 100644 index 5691a6c..0000000 --- a/third_party/libjingle/files/talk/p2p/base/relayport.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __RELAYPORT_H__ -#define __RELAYPORT_H__ - -#include "talk/p2p/base/port.h" -#include "talk/p2p/base/stunrequest.h" -#include <vector> - -namespace cricket { - -extern const std::string RELAY_PORT_TYPE; -class RelayEntry; - -// Communicates using an allocated port on the relay server. -class RelayPort : public Port { -public: - RelayPort( - talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network*, const talk_base::SocketAddress& local_addr, - const std::string& username, const std::string& password, - const std::string& magic_cookie); - virtual ~RelayPort(); - - void AddServerAddress(const ProtocolAddress& addr); - void AddExternalAddress(const ProtocolAddress& addr); - - typedef std::pair<talk_base::Socket::Option, int> OptionValue; - const std::vector<OptionValue>& options() const { return options_; } - - const std::string& magic_cookie() const { return magic_cookie_; } - bool HasMagicCookie(const char* data, size_t size); - - virtual void PrepareAddress(); - virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin); - - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - - const ProtocolAddress * ServerAddress(size_t index) const; - - void DisposeSocket(talk_base::AsyncPacketSocket * socket); - -protected: - void SetReady(); - - virtual int SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload); - - // Dispatches the given packet to the port or connection as appropriate. - void OnReadPacket( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr); - -private: - friend class RelayEntry; - - talk_base::SocketAddress local_addr_; - std::deque<ProtocolAddress> server_addr_; - bool ready_; - std::vector<RelayEntry*> entries_; - std::vector<OptionValue> options_; - std::string magic_cookie_; - int error_; -}; - -} // namespace cricket - -#endif // __RELAYPORT_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/relayserver.cc b/third_party/libjingle/files/talk/p2p/base/relayserver.cc deleted file mode 100644 index 1f4a979..0000000 --- a/third_party/libjingle/files/talk/p2p/base/relayserver.cc +++ /dev/null @@ -1,671 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/relayserver.h" -#include "talk/base/helpers.h" -#include <algorithm> -#include <cassert> -#include <cstring> -#include <iostream> - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -namespace cricket { - -// By default, we require a ping every 90 seconds. -const int MAX_LIFETIME = 15 * 60 * 1000; - -// The number of bytes in each of the usernames we use. -const uint32 USERNAME_LENGTH = 16; - -// Calls SendTo on the given socket and logs any bad results. -void Send(talk_base::AsyncPacketSocket* socket, const char* bytes, size_t size, - const talk_base::SocketAddress& addr) { - int result = socket->SendTo(bytes, size, addr); - if (result < int(size)) { - std::cerr << "SendTo wrote only " << result << " of " << int(size) - << " bytes" << std::endl; - } else if (result < 0) { - std::cerr << "SendTo: " << std::strerror(errno) << std::endl; - } -} - -// Sends the given STUN message on the given socket. -void SendStun(const StunMessage& msg, - talk_base::AsyncPacketSocket* socket, - const talk_base::SocketAddress& addr) { - talk_base::ByteBuffer buf; - msg.Write(&buf); - Send(socket, buf.Data(), buf.Length(), addr); -} - -// Constructs a STUN error response and sends it on the given socket. -void SendStunError(const StunMessage& msg, talk_base::AsyncPacketSocket* socket, - const talk_base::SocketAddress& remote_addr, int error_code, - const char* error_desc, const std::string& magic_cookie) { - - StunMessage err_msg; - err_msg.SetType(GetStunErrorResponseType(msg.type())); - err_msg.SetTransactionID(msg.transaction_id()); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - if (magic_cookie.size() == 0) - magic_cookie_attr->CopyBytes(cricket::STUN_MAGIC_COOKIE_VALUE, 4); - else - magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size()); - err_msg.AddAttribute(magic_cookie_attr); - - StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode(); - err_code->SetErrorClass(error_code / 100); - err_code->SetNumber(error_code % 100); - err_code->SetReason(error_desc); - err_msg.AddAttribute(err_code); - - SendStun(err_msg, socket, remote_addr); -} - -RelayServer::RelayServer(talk_base::Thread* thread) - : thread_(thread), log_bindings_(true) { -} - -RelayServer::~RelayServer() { - for (unsigned i = 0; i < internal_sockets_.size(); i++) - delete internal_sockets_[i]; - for (unsigned i = 0; i < external_sockets_.size(); i++) - delete external_sockets_[i]; -} - -void RelayServer::AddInternalSocket(talk_base::AsyncPacketSocket* socket) { - assert(internal_sockets_.end() == - std::find(internal_sockets_.begin(), internal_sockets_.end(), socket)); - internal_sockets_.push_back(socket); - socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket); -} - -void RelayServer::RemoveInternalSocket(talk_base::AsyncPacketSocket* socket) { - SocketList::iterator iter = - std::find(internal_sockets_.begin(), internal_sockets_.end(), socket); - assert(iter != internal_sockets_.end()); - internal_sockets_.erase(iter); - socket->SignalReadPacket.disconnect(this); -} - -void RelayServer::AddExternalSocket(talk_base::AsyncPacketSocket* socket) { - assert(external_sockets_.end() == - std::find(external_sockets_.begin(), external_sockets_.end(), socket)); - external_sockets_.push_back(socket); - socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket); -} - -void RelayServer::RemoveExternalSocket(talk_base::AsyncPacketSocket* socket) { - SocketList::iterator iter = - std::find(external_sockets_.begin(), external_sockets_.end(), socket); - assert(iter != external_sockets_.end()); - external_sockets_.erase(iter); - socket->SignalReadPacket.disconnect(this); -} - -void RelayServer::OnInternalPacket( - const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - - // Get the address of the connection we just received on. - talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress()); - assert(!ap.destination().IsAny()); - - // If this did not come from an existing connection, it should be a STUN - // allocate request. - ConnectionMap::iterator piter = connections_.find(ap); - if (piter == connections_.end()) { - HandleStunAllocate(bytes, size, ap, socket); - return; - } - - RelayServerConnection* int_conn = piter->second; - - // Handle STUN requests to the server itself. - if (int_conn->binding()->HasMagicCookie(bytes, size)) { - HandleStun(int_conn, bytes, size); - return; - } - - // Otherwise, this is a non-wrapped packet that we are to forward. Make sure - // that this connection has been locked. (Otherwise, we would not know what - // address to forward to.) - if (!int_conn->locked()) { - std::cerr << "Dropping packet: connection not locked" << std::endl; - return; - } - - // Forward this to the destination address into the connection. - RelayServerConnection* ext_conn = int_conn->binding()->GetExternalConnection( - int_conn->default_destination()); - if (ext_conn && ext_conn->locked()) { - // TODO: Check the HMAC. - ext_conn->Send(bytes, size); - } else { - // This happens very often and is not an error. - //std::cerr << "Dropping packet: no external connection" << std::endl; - } -} - -void RelayServer::OnExternalPacket( - const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - - // Get the address of the connection we just received on. - talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress()); - assert(!ap.destination().IsAny()); - - // If this connection already exists, then forward the traffic. - ConnectionMap::iterator piter = connections_.find(ap); - if (piter != connections_.end()) { - // TODO: Check the HMAC. - RelayServerConnection* ext_conn = piter->second; - RelayServerConnection* int_conn = - ext_conn->binding()->GetInternalConnection( - ext_conn->addr_pair().source()); - assert(int_conn); - int_conn->Send(bytes, size, ext_conn->addr_pair().source()); - ext_conn->Lock(); // allow outgoing packets - return; - } - - // The first packet should always be a STUN / TURN packet. If it isn't, then - // we should just ignore this packet. - StunMessage msg; - talk_base::ByteBuffer buf = talk_base::ByteBuffer(bytes, size); - if (!msg.Read(&buf)) { - std::cerr << "Dropping packet: first packet not STUN" << std::endl; - return; - } - - // The initial packet should have a username (which identifies the binding). - const StunByteStringAttribute* username_attr = - msg.GetByteString(STUN_ATTR_USERNAME); - if (!username_attr) { - std::cerr << "Dropping packet: no username" << std::endl; - return; - } - - uint32 length = talk_base::_min(uint32(username_attr->length()), USERNAME_LENGTH); - std::string username(username_attr->bytes(), length); - // TODO: Check the HMAC. - - // The binding should already be present. - BindingMap::iterator biter = bindings_.find(username); - if (biter == bindings_.end()) { - // TODO: Turn this back on. This is the sign of a client bug. - //std::cerr << "Dropping packet: no binding with username" << std::endl; - return; - } - - // Add this authenticted connection to the binding. - RelayServerConnection* ext_conn = - new RelayServerConnection(biter->second, ap, socket); - ext_conn->binding()->AddExternalConnection(ext_conn); - AddConnection(ext_conn); - - // We always know where external packets should be forwarded, so we can lock - // them from the beginning. - ext_conn->Lock(); - - // Send this message on the appropriate internal connection. - RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection( - ext_conn->addr_pair().source()); - assert(int_conn); - int_conn->Send(bytes, size, ext_conn->addr_pair().source()); -} - -bool RelayServer::HandleStun( - const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket, std::string* username, StunMessage* msg) { - - // Parse this into a stun message. - talk_base::ByteBuffer buf = talk_base::ByteBuffer(bytes, size); - if (!msg->Read(&buf)) { - SendStunError(*msg, socket, remote_addr, 400, "Bad Request", ""); - return false; - } - - // The initial packet should have a username (which identifies the binding). - const StunByteStringAttribute* username_attr = - msg->GetByteString(STUN_ATTR_USERNAME); - if (!username_attr) { - SendStunError(*msg, socket, remote_addr, 432, "Missing Username", ""); - return false; - } - - // Record the username if requested. - if (username) - username->append(username_attr->bytes(), username_attr->length()); - - // TODO: Check for unknown attributes (<= 0x7fff) - - return true; -} - -void RelayServer::HandleStunAllocate( - const char* bytes, size_t size, const talk_base::SocketAddressPair& ap, - talk_base::AsyncPacketSocket* socket) { - - // Make sure this is a valid STUN request. - StunMessage request; - std::string username; - if (!HandleStun(bytes, size, ap.source(), socket, &username, &request)) - return; - - // Make sure this is a an allocate request. - if (request.type() != STUN_ALLOCATE_REQUEST) { - SendStunError(request, - socket, - ap.source(), - 600, - "Operation Not Supported", - ""); - return; - } - - // TODO: Check the HMAC. - - // Find or create the binding for this username. - - RelayServerBinding* binding; - - BindingMap::iterator biter = bindings_.find(username); - if (biter != bindings_.end()) { - - binding = biter->second; - - } else { - - // NOTE: In the future, bindings will be created by the bot only. This - // else-branch will then disappear. - - // Compute the appropriate lifetime for this binding. - uint32 lifetime = MAX_LIFETIME; - const StunUInt32Attribute* lifetime_attr = - request.GetUInt32(STUN_ATTR_LIFETIME); - if (lifetime_attr) - lifetime = talk_base::_min(lifetime, lifetime_attr->value() * 1000); - - binding = new RelayServerBinding(this, username, "0", lifetime); - binding->SignalTimeout.connect(this, &RelayServer::OnTimeout); - bindings_[username] = binding; - - if (log_bindings_) { - std::cout << "Added new binding: " << bindings_.size() << " total" - << std::endl; - } - } - - // Add this connection to the binding. It starts out unlocked. - RelayServerConnection* int_conn = - new RelayServerConnection(binding, ap, socket); - binding->AddInternalConnection(int_conn); - AddConnection(int_conn); - - // Now that we have a connection, this other method takes over. - HandleStunAllocate(int_conn, request); -} - -void RelayServer::HandleStun( - RelayServerConnection* int_conn, const char* bytes, size_t size) { - - // Make sure this is a valid STUN request. - StunMessage request; - std::string username; - if (!HandleStun(bytes, size, int_conn->addr_pair().source(), - int_conn->socket(), &username, &request)) - return; - - // Make sure the username is the one were were expecting. - if (username != int_conn->binding()->username()) { - int_conn->SendStunError(request, 430, "Stale Credentials"); - return; - } - - // TODO: Check the HMAC. - - // Send this request to the appropriate handler. - if (request.type() == STUN_SEND_REQUEST) - HandleStunSend(int_conn, request); - else if (request.type() == STUN_ALLOCATE_REQUEST) - HandleStunAllocate(int_conn, request); - else - int_conn->SendStunError(request, 600, "Operation Not Supported"); -} - -void RelayServer::HandleStunAllocate( - RelayServerConnection* int_conn, const StunMessage& request) { - - // Create a response message that includes an address with which external - // clients can communicate. - - StunMessage response; - response.SetType(STUN_ALLOCATE_RESPONSE); - response.SetTransactionID(request.transaction_id()); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(), - int_conn->binding()->magic_cookie().size()); - response.AddAttribute(magic_cookie_attr); - - size_t index = rand() % external_sockets_.size(); - talk_base::SocketAddress ext_addr = external_sockets_[index]->GetLocalAddress(); - - StunAddressAttribute* addr_attr = - StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); - addr_attr->SetFamily(1); - addr_attr->SetIP(ext_addr.ip()); - addr_attr->SetPort(ext_addr.port()); - response.AddAttribute(addr_attr); - - StunUInt32Attribute* res_lifetime_attr = - StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME); - res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000); - response.AddAttribute(res_lifetime_attr); - - // TODO: Support transport-prefs (preallocate RTCP port). - // TODO: Support bandwidth restrictions. - // TODO: Add message integrity check. - - // Send a response to the caller. - int_conn->SendStun(response); -} - -void RelayServer::HandleStunSend( - RelayServerConnection* int_conn, const StunMessage& request) { - - const StunAddressAttribute* addr_attr = - request.GetAddress(STUN_ATTR_DESTINATION_ADDRESS); - if (!addr_attr) { - int_conn->SendStunError(request, 400, "Bad Request"); - return; - } - - const StunByteStringAttribute* data_attr = - request.GetByteString(STUN_ATTR_DATA); - if (!data_attr) { - int_conn->SendStunError(request, 400, "Bad Request"); - return; - } - - talk_base::SocketAddress ext_addr(addr_attr->ip(), addr_attr->port()); - RelayServerConnection* ext_conn = - int_conn->binding()->GetExternalConnection(ext_addr); - if (!ext_conn) { - // Create a new connection to establish the relationship with this binding. - assert(external_sockets_.size() == 1); - talk_base::AsyncPacketSocket* socket = external_sockets_[0]; - talk_base::SocketAddressPair ap(ext_addr, socket->GetLocalAddress()); - ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket); - ext_conn->binding()->AddExternalConnection(ext_conn); - AddConnection(ext_conn); - } - - // If this connection has pinged us, then allow outgoing traffic. - if (ext_conn->locked()) - ext_conn->Send(data_attr->bytes(), data_attr->length()); - - const StunUInt32Attribute* options_attr = - request.GetUInt32(STUN_ATTR_OPTIONS); - if (options_attr && (options_attr->value() & 0x01 != 0)) { - int_conn->set_default_destination(ext_addr); - int_conn->Lock(); - - StunMessage response; - response.SetType(STUN_SEND_RESPONSE); - response.SetTransactionID(request.transaction_id()); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(), - int_conn->binding()->magic_cookie().size()); - response.AddAttribute(magic_cookie_attr); - - StunUInt32Attribute* options2_attr = - StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS); - options2_attr->SetValue(0x01); - response.AddAttribute(options2_attr); - - int_conn->SendStun(response); - } -} - -void RelayServer::AddConnection(RelayServerConnection* conn) { - assert(connections_.find(conn->addr_pair()) == connections_.end()); - connections_[conn->addr_pair()] = conn; -} - -void RelayServer::RemoveConnection(RelayServerConnection* conn) { - ConnectionMap::iterator iter = connections_.find(conn->addr_pair()); - assert(iter != connections_.end()); - connections_.erase(iter); -} - -void RelayServer::RemoveBinding(RelayServerBinding* binding) { - BindingMap::iterator iter = bindings_.find(binding->username()); - assert(iter != bindings_.end()); - bindings_.erase(iter); - - if (log_bindings_) { - std::cout << "Removed a binding: " << bindings_.size() << " remaining" - << std::endl; - } -} - -void RelayServer::OnTimeout(RelayServerBinding* binding) { - // This call will result in all of the necessary clean-up. - delete binding; -} - -RelayServerConnection::RelayServerConnection( - RelayServerBinding* binding, const talk_base::SocketAddressPair& addrs, - talk_base::AsyncPacketSocket* socket) - : binding_(binding), addr_pair_(addrs), socket_(socket), locked_(false) { - - // The creation of a new connection constitutes a use of the binding. - binding_->NoteUsed(); -} - -RelayServerConnection::~RelayServerConnection() { - // Remove this connection from the server's map (if it exists there). - binding_->server()->RemoveConnection(this); -} - -void RelayServerConnection::Send(const char* data, size_t size) { - // Note that the binding has been used again. - binding_->NoteUsed(); - - cricket::Send(socket_, data, size, addr_pair_.source()); -} - -void RelayServerConnection::Send( - const char* data, size_t size, const talk_base::SocketAddress& from_addr) { - // If the from address is known to the client, we don't need to send it. - if (locked() && (from_addr == default_dest_)) { - Send(data, size); - return; - } - - // Wrap the given data in a data-indication packet. - - StunMessage msg; - msg.SetType(STUN_DATA_INDICATION); - msg.SetTransactionID("0000000000000000"); - - StunByteStringAttribute* magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(), - binding_->magic_cookie().size()); - msg.AddAttribute(magic_cookie_attr); - - StunAddressAttribute* addr_attr = - StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2); - addr_attr->SetFamily(1); - addr_attr->SetIP(from_addr.ip()); - addr_attr->SetPort(from_addr.port()); - msg.AddAttribute(addr_attr); - - StunByteStringAttribute* data_attr = - StunAttribute::CreateByteString(STUN_ATTR_DATA); - assert(size <= 65536); - data_attr->CopyBytes(data, uint16(size)); - msg.AddAttribute(data_attr); - - SendStun(msg); -} - -void RelayServerConnection::SendStun(const StunMessage& msg) { - // Note that the binding has been used again. - binding_->NoteUsed(); - - cricket::SendStun(msg, socket_, addr_pair_.source()); -} - -void RelayServerConnection::SendStunError( - const StunMessage& request, int error_code, const char* error_desc) { - // An error does not indicate use. If no legitimate use off the binding - // occurs, we want it to be cleaned up even if errors are still occuring. - - cricket::SendStunError( - request, socket_, addr_pair_.source(), error_code, error_desc, - binding_->magic_cookie()); -} - -void RelayServerConnection::Lock() { - locked_ = true; -} - -void RelayServerConnection::Unlock() { - locked_ = false; -} - -// IDs used for posted messages: -const uint32 MSG_LIFETIME_TIMER = 1; - -RelayServerBinding::RelayServerBinding( - RelayServer* server, const std::string& username, - const std::string& password, uint32 lifetime) - : server_(server), username_(username), password_(password), - lifetime_(lifetime) { - - // For now, every connection uses the standard magic cookie value. - magic_cookie_.append( - reinterpret_cast<const char*>(STUN_MAGIC_COOKIE_VALUE), 4); - - // Initialize the last-used time to now. - NoteUsed(); - - // Set the first timeout check. - server_->thread()->PostDelayed(lifetime_, this, MSG_LIFETIME_TIMER); -} - -RelayServerBinding::~RelayServerBinding() { - // Clear the outstanding timeout check. - server_->thread()->Clear(this); - - // Clean up all of the connections. - for (size_t i = 0; i < internal_connections_.size(); ++i) - delete internal_connections_[i]; - for (size_t i = 0; i < external_connections_.size(); ++i) - delete external_connections_[i]; - - // Remove this binding from the server's map. - server_->RemoveBinding(this); -} - -void RelayServerBinding::AddInternalConnection(RelayServerConnection* conn) { - internal_connections_.push_back(conn); -} - -void RelayServerBinding::AddExternalConnection(RelayServerConnection* conn) { - external_connections_.push_back(conn); -} - -void RelayServerBinding::NoteUsed() { - last_used_ = talk_base::Time(); -} - -bool RelayServerBinding::HasMagicCookie(const char* bytes, size_t size) const { - if (size < 24 + magic_cookie_.size()) { - return false; - } else { - return 0 == std::memcmp( - bytes + 24, magic_cookie_.c_str(), magic_cookie_.size()); - } -} - -RelayServerConnection* RelayServerBinding::GetInternalConnection( - const talk_base::SocketAddress& ext_addr) { - - // Look for an internal connection that is locked to this address. - for (size_t i = 0; i < internal_connections_.size(); ++i) { - if (internal_connections_[i]->locked() && - (ext_addr == internal_connections_[i]->default_destination())) - return internal_connections_[i]; - } - - // If one was not found, we send to the first connection. - assert(internal_connections_.size() > 0); - return internal_connections_[0]; -} - -RelayServerConnection* RelayServerBinding::GetExternalConnection( - const talk_base::SocketAddress& ext_addr) { - for (size_t i = 0; i < external_connections_.size(); ++i) { - if (ext_addr == external_connections_[i]->addr_pair().source()) - return external_connections_[i]; - } - return 0; -} - -void RelayServerBinding::OnMessage(talk_base::Message *pmsg) { - if (pmsg->message_id == MSG_LIFETIME_TIMER) { - assert(!pmsg->pdata); - - // If the lifetime timeout has been exceeded, then send a signal. - // Otherwise, just keep waiting. - if (talk_base::Time() >= last_used_ + lifetime_) { - SignalTimeout(this); - } else { - server_->thread()->PostDelayed(lifetime_, this, MSG_LIFETIME_TIMER); - } - - } else { - assert(false); - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/relayserver.h b/third_party/libjingle/files/talk/p2p/base/relayserver.h deleted file mode 100644 index b99c632..0000000 --- a/third_party/libjingle/files/talk/p2p/base/relayserver.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __RELAYSERVER_H__ -#define __RELAYSERVER_H__ - -#include "talk/base/asyncudpsocket.h" -#include "talk/base/socketaddresspair.h" -#include "talk/base/thread.h" -#include "talk/base/time.h" -#include "talk/p2p/base/stun.h" - -#include <string> -#include <vector> -#include <map> - -namespace cricket { - -class RelayServerBinding; -class RelayServerConnection; - -// Relays traffic between connections to the server that are "bound" together. -// All connections created with the same username/password are bound together. -class RelayServer : public sigslot::has_slots<> { -public: - // Creates a server, which will use this thread to post messages to itself. - RelayServer(talk_base::Thread* thread); - ~RelayServer(); - - talk_base::Thread* thread() { return thread_; } - - // Indicates whether we will print updates of the number of bindings. - bool log_bindings() const { return log_bindings_; } - void set_log_bindings(bool log_bindings) { log_bindings_ = log_bindings; } - - // Updates the set of sockets that the server uses to talk to "internal" - // clients. These are clients that do the "port allocations". - void AddInternalSocket(talk_base::AsyncPacketSocket* socket); - void RemoveInternalSocket(talk_base::AsyncPacketSocket* socket); - - // Updates the set of sockets that the server uses to talk to "external" - // clients. These are the clients that do not do allocations. They do not - // know that these addresses represent a relay server. - void AddExternalSocket(talk_base::AsyncPacketSocket* socket); - void RemoveExternalSocket(talk_base::AsyncPacketSocket* socket); - -private: - typedef std::vector<talk_base::AsyncPacketSocket*> SocketList; - typedef std::map<std::string,RelayServerBinding*> BindingMap; - typedef std::map<talk_base::SocketAddressPair,RelayServerConnection*> ConnectionMap; - - talk_base::Thread* thread_; - bool log_bindings_; - SocketList internal_sockets_; - SocketList external_sockets_; - BindingMap bindings_; - ConnectionMap connections_; - - // Called when a packet is received by the server on one of its sockets. - void OnInternalPacket( - const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - void OnExternalPacket( - const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - - // Processes the relevant STUN request types from the client. - bool HandleStun(const char* bytes, size_t size, - const talk_base::SocketAddress& remote_addr, talk_base::AsyncPacketSocket* socket, - std::string* username, StunMessage* msg); - void HandleStunAllocate(const char* bytes, size_t size, - const talk_base::SocketAddressPair& ap, - talk_base::AsyncPacketSocket* socket); - void HandleStun(RelayServerConnection* int_conn, const char* bytes, - size_t size); - void HandleStunAllocate(RelayServerConnection* int_conn, - const StunMessage& msg); - void HandleStunSend(RelayServerConnection* int_conn, const StunMessage& msg); - - // Adds/Removes the a connection or binding. - void AddConnection(RelayServerConnection* conn); - void RemoveConnection(RelayServerConnection* conn); - void RemoveBinding(RelayServerBinding* binding); - - // Called when the timer for checking lifetime times out. - void OnTimeout(RelayServerBinding* binding); - - friend class RelayServerConnection; - friend class RelayServerBinding; -}; - -// Maintains information about a connection to the server. Each connection is -// part of one and only one binding. -class RelayServerConnection { -public: - RelayServerConnection(RelayServerBinding* binding, - const talk_base::SocketAddressPair& addrs, - talk_base::AsyncPacketSocket* socket); - ~RelayServerConnection(); - - RelayServerBinding* binding() { return binding_; } - talk_base::AsyncPacketSocket* socket() { return socket_; } - - // Returns a pair where the source is the remote address and the destination - // is the local address. - const talk_base::SocketAddressPair& addr_pair() { return addr_pair_; } - - // Sends a packet to the connected client. If an address is provided, then - // we make sure the internal client receives it, wrapping if necessary. - void Send(const char* data, size_t size); - void Send(const char* data, size_t size, const talk_base::SocketAddress& ext_addr); - - // Sends a STUN message to the connected client with no wrapping. - void SendStun(const StunMessage& msg); - void SendStunError(const StunMessage& request, int code, const char* desc); - - // A locked connection is one for which we know the intended destination of - // any raw packet received. - bool locked() const { return locked_; } - void Lock(); - void Unlock(); - - // Records the address that raw packets should be forwarded to (for internal - // packets only; for external, we already know where they go). - const talk_base::SocketAddress& default_destination() const { return default_dest_; } - void set_default_destination(const talk_base::SocketAddress& addr) { - default_dest_ = addr; - } - -private: - RelayServerBinding* binding_; - talk_base::SocketAddressPair addr_pair_; - talk_base::AsyncPacketSocket* socket_; - bool locked_; - talk_base::SocketAddress default_dest_; -}; - -// Records a set of internal and external connections that we relay between, -// or in other words, that are "bound" together. -class RelayServerBinding : public talk_base::MessageHandler { -public: - RelayServerBinding( - RelayServer* server, const std::string& username, - const std::string& password, uint32 lifetime); - virtual ~RelayServerBinding(); - - RelayServer* server() { return server_; } - uint32 lifetime() { return lifetime_; } - const std::string& username() { return username_; } - const std::string& password() { return password_; } - const std::string& magic_cookie() { return magic_cookie_; } - - // Adds/Removes a connection into the binding. - void AddInternalConnection(RelayServerConnection* conn); - void AddExternalConnection(RelayServerConnection* conn); - - // We keep track of the use of each binding. If we detect that it was not - // used for longer than the lifetime, then we send a signal. - void NoteUsed(); - sigslot::signal1<RelayServerBinding*> SignalTimeout; - - // Determines whether the given packet has the magic cookie present (in the - // right place). - bool HasMagicCookie(const char* bytes, size_t size) const; - - // Determines the connection to use to send packets to or from the given - // external address. - RelayServerConnection* GetInternalConnection(const talk_base::SocketAddress& ext_addr); - RelayServerConnection* GetExternalConnection(const talk_base::SocketAddress& ext_addr); - - // MessageHandler: - void OnMessage(talk_base::Message *pmsg); - -private: - RelayServer* server_; - - std::string username_; - std::string password_; - std::string magic_cookie_; - - std::vector<RelayServerConnection*> internal_connections_; - std::vector<RelayServerConnection*> external_connections_; - - uint32 lifetime_; - uint32 last_used_; - // TODO: bandwidth -}; - -} // namespace cricket - -#endif // __RELAYSERVER_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/relayserver_main.cc b/third_party/libjingle/files/talk/p2p/base/relayserver_main.cc deleted file mode 100644 index cdd5fff..0000000 --- a/third_party/libjingle/files/talk/p2p/base/relayserver_main.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <cassert> -#include <iostream> -#include "talk/base/host.h" -#include "talk/base/thread.h" -#include "talk/p2p/base/relayserver.h" - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -using namespace cricket; - -int main(int argc, char **argv) { - if (argc != 1) { - std::cerr << "usage: relayserver" << std::endl; - return 1; - } - - assert(talk_base::LocalHost().networks().size() >= 2); - talk_base::SocketAddress int_addr(talk_base::LocalHost().networks()[1]->ip(), 5000); - talk_base::SocketAddress ext_addr(talk_base::LocalHost().networks()[1]->ip(), 5001); - - talk_base::Thread *pthMain = talk_base::Thread::Current(); - - talk_base::AsyncUDPSocket* int_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); - if (int_socket->Bind(int_addr) < 0) { - std::cerr << "bind: " << std::strerror(errno) << std::endl; - return 1; - } - - talk_base::AsyncUDPSocket* ext_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); - if (ext_socket->Bind(ext_addr) < 0) { - std::cerr << "bind: " << std::strerror(errno) << std::endl; - return 1; - } - - RelayServer server(pthMain); - server.AddInternalSocket(int_socket); - server.AddExternalSocket(ext_socket); - - std::cout << "Listening internally at " << int_addr.ToString() << std::endl; - std::cout << "Listening externally at " << ext_addr.ToString() << std::endl; - - pthMain->Run(); - return 0; -} diff --git a/third_party/libjingle/files/talk/p2p/base/session.cc b/third_party/libjingle/files/talk/p2p/base/session.cc deleted file mode 100644 index 7d2a91b..0000000 --- a/third_party/libjingle/files/talk/p2p/base/session.cc +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/session.h" -#include "talk/base/common.h" -#include "talk/base/logging.h" -#include "talk/base/helpers.h" -#include "talk/xmpp/xmppconstants.h" -#include "talk/xmpp/jid.h" -#include "talk/p2p/base/sessionclient.h" -#include "talk/p2p/base/transport.h" -#include "talk/p2p/base/transportchannelproxy.h" -#include "talk/p2p/base/p2ptransport.h" -#include "talk/p2p/base/constants.h" - -namespace { - -const uint32 MSG_TIMEOUT = 1; -const uint32 MSG_ERROR = 2; -const uint32 MSG_STATE = 3; - -// This will be initialized at run time to hold the list of default transports. -std::string* gDefaultTransports = NULL; -size_t gNumDefaultTransports = 0; - -} // namespace - -namespace cricket { - -Session::Session(SessionManager *session_manager, const std::string& name, - const SessionID& id, const std::string& session_type, - SessionClient* client) { - ASSERT(session_manager->signaling_thread()->IsCurrent()); - ASSERT(client != NULL); - session_manager_ = session_manager; - name_ = name; - id_ = id; - session_type_ = session_type; - client_ = client; - error_ = ERROR_NONE; - state_ = STATE_INIT; - initiator_ = false; - description_ = NULL; - remote_description_ = NULL; - transport_ = NULL; - compatibility_mode_ = false; -} - -Session::~Session() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - ASSERT(state_ != STATE_DEINIT); - state_ = STATE_DEINIT; - SignalState(this, state_); - - delete description_; - delete remote_description_; - - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - iter->second->SignalDestroyed(iter->second); - delete iter->second; - } - - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - delete *iter; - } - - delete transport_; -} - -bool Session::Initiate(const std::string &to, - std::vector<buzz::XmlElement*>* extra_xml, - const SessionDescription *description) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Only from STATE_INIT - if (state_ != STATE_INIT) - return false; - - // Setup for signaling. - remote_name_ = to; - initiator_ = true; - description_ = description; - - // Make sure we have transports to negotiate. - CreateTransports(); - - // Send the initiate message, including the application and transport offers. - XmlElements elems; - elems.push_back(client_->TranslateSessionDescription(description)); - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - buzz::XmlElement* elem = (*iter)->CreateTransportOffer(); - elems.push_back(elem); - } - - if (extra_xml != NULL) { - std::vector<buzz::XmlElement*>::iterator iter = extra_xml->begin(); - for (std::vector<buzz::XmlElement*>::iterator iter = extra_xml->begin(); - iter != extra_xml->end(); - ++iter) { - elems.push_back(new buzz::XmlElement(**iter)); - } - } - - SendSessionMessage("initiate", elems); - - SetState(Session::STATE_SENTINITIATE); - - // We speculatively start attempting connection of the P2P transports. - ConnectDefaultTransportChannels(true); - return true; -} - -void Session::ConnectDefaultTransportChannels(bool create) { - Transport* transport = GetTransport(kNsP2pTransport); - if (transport) { - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - ASSERT(create != transport->HasChannel(iter->first)); - if (create) { - transport->CreateChannel(iter->first, session_type()); - } - } - transport->ConnectChannels(); - } -} - -void Session::CreateDefaultTransportChannel(const std::string& name) { - // This method is only relevant when we have created the default transport - // but not received a transport-accept. - ASSERT(transport_ == NULL); - ASSERT(state_ == STATE_SENTINITIATE); - - Transport* p2p_transport = GetTransport(kNsP2pTransport); - if (p2p_transport) { - ASSERT(!p2p_transport->HasChannel(name)); - p2p_transport->CreateChannel(name, session_type()); - } -} - -bool Session::Accept(const SessionDescription *description) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Only if just received initiate - if (state_ != STATE_RECEIVEDINITIATE) - return false; - - // Setup for signaling. - initiator_ = false; - description_ = description; - - // If we haven't selected a transport, wait for ChooseTransport to complete - if (transport_ == NULL) - return true; - - // Send the accept message. - XmlElements elems; - elems.push_back(client_->TranslateSessionDescription(description_)); - SendSessionMessage("accept", elems); - SetState(Session::STATE_SENTACCEPT); - - return true; -} - -bool Session::Reject() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Reject is sent in response to an initiate or modify, to reject the - // request - if (state_ != STATE_RECEIVEDINITIATE && state_ != STATE_RECEIVEDMODIFY) - return false; - - // Setup for signaling. - initiator_ = false; - - // Send the reject message. - SendSessionMessage("reject", XmlElements()); - SetState(STATE_SENTREJECT); - - return true; -} - -bool Session::Redirect(const std::string & target) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Redirect is sent in response to an initiate or modify, to redirect the - // request - if (state_ != STATE_RECEIVEDINITIATE) - return false; - - // Setup for signaling. - initiator_ = false; - - // Send a redirect message to the given target. We include an element that - // names the redirector (us), which may be useful to the other side. - - buzz::XmlElement* target_elem = new buzz::XmlElement(QN_REDIRECT_TARGET); - target_elem->AddAttr(buzz::QN_NAME, target); - - buzz::XmlElement* cookie = new buzz::XmlElement(QN_REDIRECT_COOKIE); - buzz::XmlElement* regarding = new buzz::XmlElement(QN_REDIRECT_REGARDING); - regarding->AddAttr(buzz::QN_NAME, name_); - cookie->AddElement(regarding); - - XmlElements elems; - elems.push_back(target_elem); - elems.push_back(cookie); - SendSessionMessage("redirect", elems); - - // A redirect puts us in the same state as reject. It just sends a different - // kind of reject message, if you like. - SetState(STATE_SENTREDIRECT); - - return true; -} - -bool Session::Terminate() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Either side can terminate, at any time. - switch (state_) { - case STATE_SENTTERMINATE: - case STATE_RECEIVEDTERMINATE: - return false; - - case STATE_SENTREDIRECT: - // We must not send terminate if we redirect. - break; - - case STATE_SENTREJECT: - case STATE_RECEIVEDREJECT: - // We don't need to send terminate if we sent or received a reject... - // it's implicit. - break; - - default: - SendSessionMessage("terminate", XmlElements()); - break; - } - - SetState(STATE_SENTTERMINATE); - return true; -} - -void Session::SendInfoMessage(const XmlElements& elems) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SendSessionMessage("info", elems); -} - -void Session::SetPotentialTransports(const std::string names[], size_t length) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - for (size_t i = 0; i < length; ++i) { - Transport* transport = NULL; - if (names[i] == kNsP2pTransport) { - transport = new P2PTransport(session_manager_); - } else { - ASSERT(false); - } - - if (transport) { - ASSERT(transport->name() == names[i]); - potential_transports_.push_back(transport); - transport->SignalConnecting.connect( - this, &Session::OnTransportConnecting); - transport->SignalWritableState.connect( - this, &Session::OnTransportWritable); - transport->SignalRequestSignaling.connect( - this, &Session::OnTransportRequestSignaling); - transport->SignalTransportMessage.connect( - this, &Session::OnTransportSendMessage); - transport->SignalTransportError.connect( - this, &Session::OnTransportSendError); - transport->SignalChannelGone.connect( - this, &Session::OnTransportChannelGone); - } - } -} - -Transport* Session::GetTransport(const std::string& name) { - if (transport_ != NULL) { - if (name == transport_->name()) - return transport_; - } else { - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - if (name == (*iter)->name()) - return *iter; - } - } - return NULL; -} - -TransportChannel* Session::CreateChannel(const std::string& name) { - //ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(channels_.find(name) == channels_.end()); - TransportChannelProxy* channel = new TransportChannelProxy(name, session_type_); - channels_[name] = channel; - if (transport_) { - ASSERT(!transport_->HasChannel(name)); - channel->SetImplementation(transport_->CreateChannel(name, session_type_)); - } else if (state_ == STATE_SENTINITIATE) { - // In this case, we have already speculatively created the default - // transport. We should create this channel as well so that it may begin - // early connection. - CreateDefaultTransportChannel(name); - } - return channel; -} - -TransportChannel* Session::GetChannel(const std::string& name) { - ChannelMap::iterator iter = channels_.find(name); - return (iter != channels_.end()) ? iter->second : NULL; -} - -void Session::DestroyChannel(TransportChannel* channel) { - ChannelMap::iterator iter = channels_.find(channel->name()); - ASSERT(iter != channels_.end()); - ASSERT(channel == iter->second); - channels_.erase(iter); - channel->SignalDestroyed(channel); - delete channel; -} - -TransportChannelImpl* Session::GetImplementation(TransportChannel* channel) { - ChannelMap::iterator iter = channels_.find(channel->name()); - return (iter != channels_.end()) ? iter->second->impl() : NULL; -} - -void Session::CreateTransports() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT((state_ == STATE_INIT) - || (state_ == STATE_RECEIVEDINITIATE)); - if (potential_transports_.empty()) { - if (gDefaultTransports == NULL) { - gNumDefaultTransports = 1; - gDefaultTransports = new std::string[1]; - gDefaultTransports[0] = kNsP2pTransport; - } - SetPotentialTransports(gDefaultTransports, gNumDefaultTransports); - } -} - -bool Session::ChooseTransport(const buzz::XmlElement* stanza) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(state_ == STATE_RECEIVEDINITIATE); - ASSERT(transport_ == NULL); - - // Make sure we have decided on our own transports. - CreateTransports(); - - // Retrieve the session message. - const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION); - ASSERT(session != NULL); - - // Try the offered transports until we find one that we support. - bool found_offer = false; - const buzz::XmlElement* elem = session->FirstElement(); - while (elem) { - if (elem->Name().LocalPart() == "transport") { - found_offer = true; - Transport* transport = GetTransport(elem->Name().Namespace()); - if (transport && transport->OnTransportOffer(elem)) { - SetTransport(transport); - break; - } - } - elem = elem->NextElement(); - } - - // If the offer did not include any transports, then we are talking to an - // old client. In that case, we turn on compatibility mode, and we assume - // an offer containing just P2P, which is all that old clients support. - if (!found_offer) { - compatibility_mode_ = true; - - Transport* transport = GetTransport(kNsP2pTransport); - ASSERT(transport != NULL); - - scoped_ptr<buzz::XmlElement> transport_offer( - new buzz::XmlElement(kQnP2pTransport, true)); - bool valid = transport->OnTransportOffer(transport_offer.get()); - ASSERT(valid); - if (valid) - SetTransport(transport); - } - - if (!transport_) { - SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ACCEPTABLE, "modify", - "no supported transport in offer", NULL); - return false; - } - - // Get the description of the transport we picked. - buzz::XmlElement* answer = transport_->CreateTransportAnswer(); - ASSERT(answer->Name() == buzz::QName(transport_->name(), "transport")); - - // Send a transport-accept message telling the other side our decision, - // unless this is an old client that is not expecting one. - if (!compatibility_mode_) { - XmlElements elems; - elems.push_back(answer); - SendSessionMessage("transport-accept", elems); - } - - // If the user wants to accept, allow that now - if (description_) { - Accept(description_); - } - - return true; -} - -void Session::SetTransport(Transport* transport) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(transport_ == NULL); - transport_ = transport; - - // Drop the transports that were not selected. - bool found = false; - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - if (*iter == transport_) { - found = true; - } else { - delete *iter; - } - } - potential_transports_.clear(); - - // We require the selected transport to be one of the potential transports - ASSERT(found); - - // Create implementations for all of the channels if they don't exist. - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - TransportChannelProxy* channel = iter->second; - TransportChannelImpl* impl = transport_->GetChannel(channel->name()); - if (impl == NULL) - impl = transport_->CreateChannel(channel->name(), session_type()); - ASSERT(impl != NULL); - channel->SetImplementation(impl); - } - - // Have this transport start connecting if it is not already. - // (We speculatively connect the most common transport right away.) - transport_->ConnectChannels(); -} - -void Session::SetState(State state) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - if (state != state_) { - state_ = state; - SignalState(this, state_); - session_manager_->signaling_thread()->Post(this, MSG_STATE); - } -} - -void Session::SetError(Error error) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - if (error != error_) { - error_ = error; - SignalError(this, error); - if (error_ != ERROR_NONE) - session_manager_->signaling_thread()->Post(this, MSG_ERROR); - } -} - -void Session::OnSignalingReady() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - // Forward this to every transport. Those that did not request it should - // ignore this call. - if (transport_ != NULL) { - transport_->OnSignalingReady(); - } else { - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - (*iter)->OnSignalingReady(); - } - } -} - -void Session::OnTransportConnecting(Transport* transport) { - // This is an indication that we should begin watching the writability - // state of the transport. - OnTransportWritable(transport); -} - -void Session::OnTransportWritable(Transport* transport) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT((NULL == transport_) || (transport == transport_)); - - // If the transport is not writable, start a timer to make sure that it - // becomes writable within a reasonable amount of time. If it does not, we - // terminate since we can't actually send data. If the transport is writable, - // cancel the timer. Note that writability transitions may occur repeatedly - // during the lifetime of the session. - - session_manager_->signaling_thread()->Clear(this, MSG_TIMEOUT); - if (transport->HasChannels() && !transport->writable()) { - session_manager_->signaling_thread()->PostDelayed( - session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT); - } -} - -void Session::OnTransportRequestSignaling(Transport* transport) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SignalRequestSignaling(this); -} - -void Session::OnTransportSendMessage(Transport* transport, - const XmlElements& elems) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - for (size_t i = 0; i < elems.size(); ++i) - ASSERT(elems[i]->Name() == buzz::QName(transport->name(), "transport")); - - if (compatibility_mode_) { - // In backward compatibility mode, we send a candidates message. - XmlElements candidates; - for (size_t i = 0; i < elems.size(); ++i) { - for (const buzz::XmlElement* elem = elems[i]->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - ASSERT(elem->Name() == kQnP2pCandidate); - - // Convert this candidate to an old style candidate (namespace change) - buzz::XmlElement* legacy_candidate = new buzz::XmlElement(*elem); - legacy_candidate->SetName(kQnLegacyCandidate); - candidates.push_back(legacy_candidate); - } - delete elems[i]; - } - - SendSessionMessage("candidates", candidates); - } else { - // If we haven't finished negotiation, then we may later discover that we - // need compatibility mode, in which case, we will need to re-send these. - if ((transport_ == NULL) && (transport->name() == kNsP2pTransport)) { - for (size_t i = 0; i < elems.size(); ++i) - candidates_.push_back(new buzz::XmlElement(*elems[i])); - } - - SendSessionMessage("transport-info", elems); - } -} - -void Session::OnTransportSendError(Transport* transport, - const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SignalErrorMessage(this, stanza, name, type, text, extra_info); -} - -void Session::OnTransportChannelGone(Transport* transport, - const std::string& name) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SignalChannelGone(this, name); -} - -void Session::SendSessionMessage( - const std::string& type, const std::vector<buzz::XmlElement*>& elems) { - scoped_ptr<buzz::XmlElement> iq(new buzz::XmlElement(buzz::QN_IQ)); - iq->SetAttr(buzz::QN_TO, remote_name_); - iq->SetAttr(buzz::QN_TYPE, buzz::STR_SET); - - buzz::XmlElement *session = new buzz::XmlElement(QN_SESSION, true); - session->AddAttr(buzz::QN_TYPE, type); - session->AddAttr(buzz::QN_ID, id_.id_str()); - session->AddAttr(QN_INITIATOR, id_.initiator()); - - for (size_t i = 0; i < elems.size(); ++i) - session->AddElement(elems[i]); - - iq->AddElement(session); - SignalOutgoingMessage(this, iq.get()); -} - -void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) { - scoped_ptr<buzz::XmlElement> ack(new buzz::XmlElement(buzz::QN_IQ)); - ack->SetAttr(buzz::QN_TO, remote_name_); - ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID)); - ack->SetAttr(buzz::QN_TYPE, "result"); - - SignalOutgoingMessage(this, ack.get()); -} - -void Session::OnIncomingMessage(const buzz::XmlElement* stanza) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(stanza->Name() == buzz::QN_IQ); - buzz::Jid remote(remote_name_); - buzz::Jid from(stanza->Attr(buzz::QN_FROM)); - ASSERT(state_ == STATE_INIT || from == remote); - - const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION); - ASSERT(session != NULL); - - if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET) { - ASSERT(false); - return; - } - - ASSERT(session->HasAttr(buzz::QN_TYPE)); - std::string type = session->Attr(buzz::QN_TYPE); - - bool valid = false; - - if (type == "initiate") { - valid = OnInitiateMessage(stanza, session); - } else if (type == "accept") { - valid = OnAcceptMessage(stanza, session); - } else if (type == "reject") { - valid = OnRejectMessage(stanza, session); - } else if (type == "redirect") { - valid = OnRedirectMessage(stanza, session); - } else if (type == "info") { - valid = OnInfoMessage(stanza, session); - } else if (type == "transport-accept") { - valid = OnTransportAcceptMessage(stanza, session); - } else if (type == "transport-info") { - valid = OnTransportInfoMessage(stanza, session); - } else if (type == "terminate") { - valid = OnTerminateMessage(stanza, session); - } else if (type == "candidates") { - // This is provided for backward compatibility. - // TODO: Remove this once old candidates are gone. - valid = OnCandidatesMessage(stanza, session); - } else { - SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - "unknown session message type", NULL); - } - - // If the message was not valid, we should have sent back an error above. - // If it was valid, then we send an acknowledgement here. - if (valid) - SendAcknowledgementMessage(stanza); -} - -void Session::OnFailedSend(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* error_stanza) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - - const buzz::XmlElement* orig_session = orig_stanza->FirstNamed(QN_SESSION); - ASSERT(orig_session != NULL); - - std::string error_type = "cancel"; - - const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR); - ASSERT(error != NULL); - if (error) { - ASSERT(error->HasAttr(buzz::QN_TYPE)); - error_type = error->Attr(buzz::QN_TYPE); - - LOG(LERROR) << "Session error:\n" << error->Str() << "\n" - << "in response to:\n" << orig_session->Str(); - } - - bool fatal_error = false; - - ASSERT(orig_session->HasAttr(buzz::QN_TYPE)); - if ((orig_session->Attr(buzz::QN_TYPE) == "transport-info") - || (orig_session->Attr(buzz::QN_TYPE) == "candidates")) { - // Transport messages frequently generate errors because they are sent right - // when we detect a network failure. For that reason, we ignore such - // errors, because if we do not establish writability again, we will - // terminate anyway. The exceptions are transport-specific error tags, - // which we pass on to the respective transport. - for (const buzz::XmlElement* elem = error->FirstElement(); - NULL != elem; elem = elem->NextElement()) { - if (Transport* transport = GetTransport(elem->Name().Namespace())) { - if (!transport->OnTransportError(orig_session, elem)) { - fatal_error = true; - break; - } - } - } - } else if ((error_type != "continue") && (error_type != "wait")) { - // We do not set an error if the other side said it is okay to continue - // (possibly after waiting). These errors can be ignored. - fatal_error = true; - } - - if (fatal_error) { - SetError(ERROR_RESPONSE); - } -} - -bool Session::OnInitiateMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - if (!CheckState(stanza, STATE_INIT)) - return false; - if (!FindRemoteSessionDescription(stanza, session)) - return false; - - initiator_ = false; - remote_name_ = stanza->Attr(buzz::QN_FROM); - SetState(STATE_RECEIVEDINITIATE); - return true; -} - -bool Session::OnAcceptMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - if (!CheckState(stanza, STATE_SENTINITIATE)) - return false; - if (!FindRemoteSessionDescription(stanza, session)) - return false; - - SetState(STATE_RECEIVEDACCEPT); - return true; -} - -bool Session::OnRejectMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - if (!CheckState(stanza, STATE_SENTINITIATE)) - return false; - - SetState(STATE_RECEIVEDREJECT); - return true; -} - -bool Session::OnRedirectMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - if (!CheckState(stanza, STATE_SENTINITIATE)) - return false; - - const buzz::XmlElement *redirect_target; - if (!FindRequiredElement(stanza, session, QN_REDIRECT_TARGET, - &redirect_target)) - return false; - - if (!FindRequiredAttribute(stanza, redirect_target, buzz::QN_NAME, - &remote_name_)) - return false; - - const buzz::XmlElement* redirect_cookie = - session->FirstNamed(QN_REDIRECT_COOKIE); - - XmlElements elems; - elems.push_back(client_->TranslateSessionDescription(description_)); - if (redirect_cookie) - elems.push_back(new buzz::XmlElement(*redirect_cookie)); - SendSessionMessage("initiate", elems); - - // Clear the connection timeout (if any). We will start the connection - // timer from scratch when SignalConnecting fires. - session_manager_->signaling_thread()->Clear(this, MSG_TIMEOUT); - - // Reset all of the sockets back into the initial state. - for (TransportList::iterator iter = potential_transports_.begin(); - iter != potential_transports_.end(); - ++iter) { - (*iter)->ResetChannels(); - } - - ConnectDefaultTransportChannels(false); - return true; -} - -bool Session::OnInfoMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - XmlElements elems; - for (const buzz::XmlElement* elem = session->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - elems.push_back(new buzz::XmlElement(*elem)); - } - - SignalInfoMessage(this, elems); - return true; -} - -bool Session::OnTransportAcceptMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - if (!CheckState(stanza, STATE_SENTINITIATE)) - return false; - - Transport* transport = NULL; - const buzz::XmlElement* transport_elem = NULL; - - for(const buzz::XmlElement* elem = session->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - if (elem->Name().LocalPart() == "transport") { - Transport* transport = GetTransport(elem->Name().Namespace()); - if (transport) { - if (transport_elem) { // trying to accept two transport? - SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, - "modify", "transport-accept has two answers", - NULL); - return false; - } - - transport_elem = elem; - if (!transport->OnTransportAnswer(transport_elem)) { - SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, - "modify", "transport-accept is not acceptable", - NULL); - return false; - } - SetTransport(transport); - } - } - } - - if (!transport_elem) { - SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify", - "no supported transport in answer", NULL); - return false; - } - - // If we discovered that we need compatibility mode and we have sent some - // candidates already (using transport-info), then we need to re-send them - // using the candidates message. - if (compatibility_mode_ && (candidates_.size() > 0)) { - ASSERT(transport_ != NULL); - ASSERT(transport_->name() == kNsP2pTransport); - OnTransportSendMessage(transport_, candidates_); - } else { - for (size_t i = 0; i < candidates_.size(); ++i) - delete candidates_[i]; - } - candidates_.clear(); - - return true; -} - -bool Session::OnTransportInfoMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - for(const buzz::XmlElement* elem = session->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - if (elem->Name().LocalPart() == "transport") { - Transport* transport = GetTransport(elem->Name().Namespace()); - if (transport) { - if (!transport->OnTransportMessage(elem, stanza)) - return false; - } - } - } - return true; -} - -bool Session::OnTerminateMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - for (const buzz::XmlElement *elem = session->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - // elem->Name().LocalPart() is the reason for termination - SignalReceivedTerminateReason(this, elem->Name().LocalPart()); - // elem->FirstElement() might contain a debug string for termination - const buzz::XmlElement *debugElement = elem->FirstElement(); - if (debugElement != NULL) { - LOG(LS_VERBOSE) << "Received error on call: " - << debugElement->Name().LocalPart(); - } - } - SetState(STATE_RECEIVEDTERMINATE); - return true; -} - -bool Session::OnCandidatesMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - // If we don't have a transport, then this is the first candidates message. - // We first create a fake transport-accept message in order to finish the - // negotiation and create a transport. - if (!transport_) { - compatibility_mode_ = true; - - scoped_ptr<buzz::XmlElement> transport_accept( - new buzz::XmlElement(QN_SESSION)); - transport_accept->SetAttr(buzz::QN_TYPE, "transport-accept"); - - buzz::XmlElement* transport_offer = - new buzz::XmlElement(kQnP2pTransport, true); - transport_accept->AddElement(transport_offer); - - // It is okay to pass the original stanza here. That is only used if we - // send an error message. Normal processing looks only at transport_accept. - bool valid = OnTransportAcceptMessage(stanza, transport_accept.get()); - ASSERT(valid); - } - - ASSERT(transport_ != NULL); - ASSERT(transport_->name() == kNsP2pTransport); - - // Wrap the candidates in a transport element as they would appear in a - // transport-info message and send this to the transport. - scoped_ptr<buzz::XmlElement> transport_info( - new buzz::XmlElement(kQnP2pTransport, true)); - for (const buzz::XmlElement* elem = session->FirstNamed(kQnLegacyCandidate); - elem != NULL; - elem = elem->NextNamed(kQnLegacyCandidate)) { - buzz::XmlElement* new_candidate = new buzz::XmlElement(*elem); - new_candidate->SetName(kQnP2pCandidate); - transport_info->AddElement(new_candidate); - } - return transport_->OnTransportMessage(transport_info.get(), stanza); -} - -bool Session::CheckState(const buzz::XmlElement* stanza, State state) { - ASSERT(state_ == state); - if (state_ != state) { - SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify", - "message not allowed in current state", NULL); - return false; - } - return true; -} - -bool Session::FindRequiredElement(const buzz::XmlElement* stanza, - const buzz::XmlElement* parent, - const buzz::QName& name, - const buzz::XmlElement** elem) { - *elem = parent->FirstNamed(name); - if (*elem == NULL) { - std::string text; - text += "element '" + parent->Name().Merged() + - "' missing required child '" + name.Merged() + "'"; - SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - text, NULL); - return false; - } - return true; -} - -bool Session::FindRemoteSessionDescription(const buzz::XmlElement* stanza, - const buzz::XmlElement* session) { - buzz::QName qn_session(session_type_, "description"); - const buzz::XmlElement* desc; - if (!FindRequiredElement(stanza, session, qn_session, &desc)) - return false; - remote_description_ = client_->CreateSessionDescription(desc); - return true; -} - -bool Session::FindRequiredAttribute(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - const buzz::QName& name, - std::string* value) { - if (!elem->HasAttr(name)) { - std::string text; - text += "element '" + elem->Name().Merged() + - "' missing required attribute '" + name.Merged() + "'"; - SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - text, NULL); - return false; - } else { - *value = elem->Attr(name); - return true; - } -} - -void Session::OnMessage(talk_base::Message *pmsg) { - switch(pmsg->message_id) { - case MSG_TIMEOUT: - // Session timeout has occured. - SetError(ERROR_TIME); - break; - - case MSG_ERROR: - // Any of the defined errors is most likely fatal. - Terminate(); - break; - - case MSG_STATE: - switch (state_) { - case STATE_SENTACCEPT: - case STATE_RECEIVEDACCEPT: - SetState(STATE_INPROGRESS); - ASSERT(transport_ != NULL); - break; - - case STATE_SENTREJECT: - case STATE_SENTREDIRECT: - case STATE_RECEIVEDREJECT: - Terminate(); - break; - - case STATE_SENTTERMINATE: - case STATE_RECEIVEDTERMINATE: - session_manager_->DestroySession(this); - break; - - default: - // Explicitly ignoring some states here. - break; - } - break; - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/session.h b/third_party/libjingle/files/talk/p2p/base/session.h deleted file mode 100644 index 5146ea0..0000000 --- a/third_party/libjingle/files/talk/p2p/base/session.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SESSION_H_ -#define _SESSION_H_ - -#include "talk/base/socketaddress.h" -#include "talk/p2p/base/sessiondescription.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/base/sessionclient.h" -#include "talk/p2p/base/sessionid.h" -#include "talk/p2p/base/port.h" -#include "talk/xmllite/xmlelement.h" -#include <string> - -namespace cricket { - -class SessionManager; -class Transport; -class TransportChannel; -class TransportChannelProxy; -class TransportChannelImpl; - -// A specific Session created by the SessionManager. A Session manages -// signaling for session setup and tear down. This setup includes negotiation -// of both the application-level and network-level protocols: the former -// defines what will be sent and the latter defines how it will be sent. Each -// network-level protocol is represented by a Transport object. Each Transport -// participates in the network-level negotiation. The individual streams of -// packets are represented by TransportChannels. -class Session : public talk_base::MessageHandler, public sigslot::has_slots<> { - public: - enum State { - STATE_INIT = 0, - STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject - STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject - STATE_SENTACCEPT, // sent accept. begin connecting transport - STATE_RECEIVEDACCEPT, // received accept. begin connecting transport - STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject - STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject - STATE_SENTREJECT, // sent reject after receiving initiate - STATE_RECEIVEDREJECT, // received reject after sending initiate - STATE_SENTREDIRECT, // sent direct after receiving initiate - STATE_SENTTERMINATE, // sent terminate (any time / either side) - STATE_RECEIVEDTERMINATE, // received terminate (any time / either side) - STATE_INPROGRESS, // session accepted and in progress - STATE_DEINIT, // session is being destroyed - }; - - enum Error { - ERROR_NONE = 0, // no error - ERROR_TIME, // no response to signaling - ERROR_RESPONSE, // error during signaling - ERROR_NETWORK, // network error, could not allocate network resources - }; - - // Returns the manager that created and owns this session. - SessionManager* session_manager() const { return session_manager_; } - - // Returns the XML namespace identifying the type of this session. - const std::string& session_type() const { return session_type_; } - - // Returns the client that is handling the application data of this session. - SessionClient* client() const { return client_; } - - // Returns the JID this client. - const std::string &name() const { return name_; } - - // Returns the JID of the other peer in this session. - const std::string &remote_name() const { return remote_name_; } - - // Indicates whether we initiated this session. - bool initiator() const { return initiator_; } - - // Holds the ID of this session, which should be unique across the world. - const SessionID& id() const { return id_; } - - // Returns the applicication-level description given by our client. This - // will be null until Initiate or Accept. - const SessionDescription *description() const { return description_; } - - // Returns the applicication-level description given by the other client. - // If we are the initiator, this will be null until we receive an accept. - const SessionDescription *remote_description() const { - return remote_description_; - } - - // Returns the current state of the session. See the enum above for details. - // Each time the state changes, we will fire this signal. - State state() const { return state_; } - sigslot::signal2<Session *, State> SignalState; - - // Fired whenever we receive a terminate message along with a reason - sigslot::signal2<Session *, const std::string &> SignalReceivedTerminateReason; - - // Returns the last error in the session. See the enum above for details. - // Each time the an error occurs, we will fire this signal. - Error error() const { return error_; } - sigslot::signal2<Session *, Error> SignalError; - - // Returns the transport that has been negotiated or NULL if negotiation is - // still in progress. - Transport* transport() const { return transport_; } - - // When a session was created by us, we are the initiator, and we send the - // initiate message when this method is invoked. The extra_xml parameter is - // a list of elements that will get inserted inside <Session> ... </Session> - bool Initiate(const std::string &to, std::vector<buzz::XmlElement*>* extra_xml, - const SessionDescription *description); - - // When we receive a session initiation from another client, we create a - // session in the RECEIVEDINITIATE state. We respond by accepting, - // rejecting, or redirecting the session somewhere else. - bool Accept(const SessionDescription *description); - bool Reject(); - bool Redirect(const std::string& target); - - // At any time, we may terminate an outstanding session. - bool Terminate(); - - // The two clients in the session may also send one another arbitrary XML - // messages, which are called "info" messages. Both of these functions take - // ownership of the XmlElements and delete them when done. - typedef std::vector<buzz::XmlElement*> XmlElements; - void SendInfoMessage(const XmlElements& elems); - sigslot::signal2<Session*, const XmlElements&> SignalInfoMessage; - - // Controls the set of transports that will be allowed for this session. If - // we are initiating, then this list will be used to construct the transports - // that we will offer to the other side. In that case, the order of the - // transport names indicates our preference (first has highest preference). - // If we are receiving, then this list indicates the set of transports that - // we will allow. We will choose the first transport in the offered list - // (1) whose name appears in the given list and (2) that can accept the offer - // provided (which may include parameters particular to the transport). - // - // If this function is not called (or if it is called with a NULL array), - // then we will use a default set of transports. - void SetPotentialTransports(const std::string names[], size_t length); - - // Once transports have been created (by SetTransports), this function will - // return the transport with the given name or NULL if none was created. - // Once a particular transport has been chosen, only that transport will be - // returned. - Transport* GetTransport(const std::string& name); - - // Creates a new channel with the given name. This method may be called - // immediately after creating the session. However, the actual - // implementation may not be fixed until transport negotiation completes. - TransportChannel* CreateChannel(const std::string& name); - - // Returns the channel with the given name. - TransportChannel* GetChannel(const std::string& name); - - // Destroys the given channel. - void DestroyChannel(TransportChannel* channel); - - // Note: This function is a hack and should not be used. - TransportChannelImpl* GetImplementation(TransportChannel* channel); - - // Invoked when we notice that there is no matching channel on our peer. - sigslot::signal2<Session*, const std::string&> SignalChannelGone; - - private: - typedef std::list<Transport*> TransportList; - typedef std::map<std::string, TransportChannelProxy*> ChannelMap; - - SessionManager *session_manager_; - std::string name_; - std::string remote_name_; - bool initiator_; - SessionID id_; - std::string session_type_; - SessionClient* client_; - const SessionDescription *description_; - const SessionDescription *remote_description_; - State state_; - Error error_; - std::string redirect_target_; - // Note that the following two members are mutually exclusive - TransportList potential_transports_; // order implies preference - Transport* transport_; // negotiated transport - ChannelMap channels_; - bool compatibility_mode_; // indicates talking to an old client - XmlElements candidates_; // holds candidates sent in case of compat-mode - - // Creates or destroys a session. (These are called only SessionManager.) - Session(SessionManager *session_manager, - const std::string& name, - const SessionID& id, - const std::string& session_type, - SessionClient* client); - ~Session(); - - // Updates the state, signaling if necessary. - void SetState(State state); - - // Updates the error state, signaling if necessary. - void SetError(Error error); - - // To improve connection time, this creates the channels on the most common - // transport type and initiates connection. - void ConnectDefaultTransportChannels(bool create); - - // If a new channel is created after we have created the default transport, - // then we should create this channel as well and let it connect. - void CreateDefaultTransportChannel(const std::string& name); - - // Creates a default set of transports if the client did not specify some. - void CreateTransports(); - - // Attempts to choose a transport that is in both our list and the other - // clients. This will examine the children of the given XML element to find - // the descriptions of the other client's transports. We will pick the first - // transport in the other client's list that we also support. - // (This is called only by SessionManager.) - bool ChooseTransport(const buzz::XmlElement* msg); - - // Called when a single transport has been negotiated. - void SetTransport(Transport* transport); - - // Called when the first channel of a transport begins connecting. We use - // this to start a timer, to make sure that the connection completes in a - // reasonable amount of time. - void OnTransportConnecting(Transport* transport); - - // Called when a transport changes its writable state. We track this to make - // sure that the transport becomes writable within a reasonable amount of - // time. If this does not occur, we signal an error. - void OnTransportWritable(Transport* transport); - - // Called when a transport requests signaling. - void OnTransportRequestSignaling(Transport* transport); - - // Called when a transport signals that it has a message to send. Note that - // these messages are just the transport part of the stanza; they need to be - // wrapped in the appropriate session tags. - void OnTransportSendMessage(Transport* transport, const XmlElements& elems); - - // Called when a transport signals that it found an error in an incoming - // message. - void OnTransportSendError(Transport* transport, - const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info); - - // Called when we notice that one of our local channels has no peer, so it - // should be destroyed. - void OnTransportChannelGone(Transport* transport, const std::string& name); - - // When the session needs to send signaling messages, it beings by requesting - // signaling. The client should handle this by calling OnSignalingReady once - // it is ready to send the messages. - // (These are called only by SessionManager.) - sigslot::signal1<Session*> SignalRequestSignaling; - void OnSignalingReady(); - - // Sends a message of the given type to the other client. The body will - // contain the given list of elements (which are consumed by the function). - void SendSessionMessage(const std::string& type, - const XmlElements& elems); - - // Sends a message back to the other client indicating that we have received - // and accepted their message. - void SendAcknowledgementMessage(const buzz::XmlElement* stanza); - - // Once signaling is ready, the session will use this signal to request the - // sending of each message. When messages are received by the other client, - // they should be handed to OnIncomingMessage. - // (These are called only by SessionManager.) - sigslot::signal2<Session *, const buzz::XmlElement*> SignalOutgoingMessage; - void OnIncomingMessage(const buzz::XmlElement* stanza); - - void OnFailedSend(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* error_stanza); - - // Invoked when an error is found in an incoming message. This is translated - // into the appropriate XMPP response by SessionManager. - sigslot::signal6<Session*, - const buzz::XmlElement*, - const buzz::QName&, - const std::string&, - const std::string&, - const buzz::XmlElement*> SignalErrorMessage; - - // Handlers for the various types of messages. These functions may take - // pointers to the whole stanza or to just the session element. - bool OnInitiateMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnAcceptMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnRejectMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnRedirectMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnInfoMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnTransportAcceptMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnTransportInfoMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnTerminateMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool OnCandidatesMessage(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - - // Helper functions for parsing various message types. CheckState verifies - // that we are in the appropriate state to receive this message. The latter - // three verify that an element has the required child or attribute. - bool CheckState(const buzz::XmlElement* stanza, State state); - bool FindRequiredElement(const buzz::XmlElement* stanza, - const buzz::XmlElement* parent, - const buzz::QName& name, - const buzz::XmlElement** elem); - bool FindRemoteSessionDescription(const buzz::XmlElement* stanza, - const buzz::XmlElement* session); - bool FindRequiredAttribute(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - const buzz::QName& name, - std::string* value); - - // Handles messages posted to us. - void OnMessage(talk_base::Message *pmsg); - - friend class SessionManager; // For access to constructor, destructor, - // and signaling related methods. -}; - -} // namespace cricket - -#endif // _SESSION_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/session_unittest.cc b/third_party/libjingle/files/talk/p2p/base/session_unittest.cc deleted file mode 100644 index 972ed9dc..0000000 --- a/third_party/libjingle/files/talk/p2p/base/session_unittest.cc +++ /dev/null @@ -1,1039 +0,0 @@ -#include <iostream> -#include <sstream> -#include <deque> -#include <map> - -#include "talk/base/common.h" -#include "talk/base/logging.h" -#include "talk/base/host.h" -#include "talk/base/natserver.h" -#include "talk/base/natsocketfactory.h" -#include "talk/base/helpers.h" -#include "talk/xmpp/constants.h" -#include "talk/p2p/base/constants.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/base/sessionclient.h" -#include "talk/p2p/base/session.h" -#include "talk/p2p/base/portallocator.h" -#include "talk/p2p/base/transportchannel.h" -#include "talk/p2p/base/udpport.h" -#include "talk/p2p/base/stunport.h" -#include "talk/p2p/base/relayport.h" -#include "talk/p2p/base/p2ptransport.h" -#include "talk/p2p/base/rawtransport.h" -#include "talk/p2p/base/stunserver.h" -#include "talk/p2p/base/relayserver.h" - -using namespace cricket; -using namespace buzz; - -const std::string kSessionType = "http://oink.splat/session"; - -const talk_base::SocketAddress kStunServerAddress("127.0.0.1", 7000); -const talk_base::SocketAddress kStunServerAddress2("127.0.0.1", 7001); - -const talk_base::SocketAddress kRelayServerIntAddress("127.0.0.1", 7002); -const talk_base::SocketAddress kRelayServerExtAddress("127.0.0.1", 7003); - -const int kNumPorts = 2; - -int gPort = 28653; -int GetNextPort() { - int p = gPort; - gPort += 5; - return p; -} - -int gID = 0; -std::string GetNextID() { - std::ostringstream ost; - ost << gID++; - return ost.str(); -} - -class TestPortAllocatorSession : public PortAllocatorSession { -public: - TestPortAllocatorSession(talk_base::Thread* worker_thread, talk_base::SocketFactory* factory, - const std::string& name, const std::string& session_type) - : PortAllocatorSession(0), worker_thread_(worker_thread), - factory_(factory), name_(name), ports_(kNumPorts), - address_("127.0.0.1", 0), network_("network", address_.ip()), - running_(false) { - } - - ~TestPortAllocatorSession() { - for (int i = 0; i < ports_.size(); i++) - delete ports_[i]; - } - - virtual void GetInitialPorts() { - // These are the flags set by the raw transport. - uint32 raw_flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP; - - // If the client doesn't care, just give them two UDP ports. - if (flags() == 0) { - for (int i = 0; i < kNumPorts; i++) { - ports_[i] = new UDPPort(worker_thread_, factory_, &network_, - GetAddress()); - AddPort(ports_[i]); - } - - // If the client requested just stun and relay, we have to oblidge. - } else if (flags() == raw_flags) { - StunPort* sport = new StunPort(worker_thread_, factory_, &network_, - GetAddress(), kStunServerAddress); - sport->set_server_addr2(kStunServerAddress2); - ports_[0] = sport; - AddPort(sport); - - std::string username = CreateRandomString(16); - std::string password = CreateRandomString(16); - RelayPort* rport = new RelayPort(worker_thread_, factory_, &network_, - GetAddress(), username, password, ""); - rport->AddServerAddress( - ProtocolAddress(kRelayServerIntAddress, PROTO_UDP)); - ports_[1] = rport; - AddPort(rport); - } else { - ASSERT(false); - } - } - - virtual void StartGetAllPorts() { running_ = true; } - virtual void StopGetAllPorts() { running_ = false; } - virtual bool IsGettingAllPorts() { return running_; } - - talk_base::SocketAddress GetAddress() const { - talk_base::SocketAddress addr(address_); - addr.SetPort(GetNextPort()); - return addr; - } - - void AddPort(Port* port) { - port->set_name(name_); - port->set_preference(1.0); - port->set_generation(0); - port->SignalDestroyed.connect( - this, &TestPortAllocatorSession::OnPortDestroyed); - port->SignalAddressReady.connect( - this, &TestPortAllocatorSession::OnAddressReady); - port->PrepareAddress(); - SignalPortReady(this, port); - } - - void OnPortDestroyed(Port* port) { - for (int i = 0; i < ports_.size(); i++) { - if (ports_[i] == port) - ports_[i] = NULL; - } - } - - void OnAddressReady(Port* port) { - SignalCandidatesReady(this, port->candidates()); - } - -private: - talk_base::Thread* worker_thread_; - talk_base::SocketFactory* factory_; - std::string name_; - std::vector<Port*> ports_; - talk_base::SocketAddress address_; - talk_base::Network network_; - bool running_; -}; - -class TestPortAllocator : public PortAllocator { -public: - TestPortAllocator(talk_base::Thread* worker_thread, talk_base::SocketFactory* factory) - : worker_thread_(worker_thread), factory_(factory) { - if (factory_ == NULL) - factory_ = worker_thread_->socketserver(); - } - - virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type) { - return new TestPortAllocatorSession(worker_thread_, factory_, name, session_type); - } - -private: - talk_base::Thread* worker_thread_; - talk_base::SocketFactory* factory_; -}; - -struct SessionManagerHandler : sigslot::has_slots<> { - SessionManagerHandler(SessionManager* m, const std::string& u) - : manager(m), username(u), create_count(0), destroy_count(0) { - manager->SignalSessionCreate.connect( - this, &SessionManagerHandler::OnSessionCreate); - manager->SignalSessionDestroy.connect( - this, &SessionManagerHandler::OnSessionDestroy); - manager->SignalOutgoingMessage.connect( - this, &SessionManagerHandler::OnOutgoingMessage); - manager->SignalRequestSignaling.connect( - this, &SessionManagerHandler::OnRequestSignaling); - } - - void OnSessionCreate(Session *session, bool initiate) { - create_count += 1; - last_id = session->id(); - } - - void OnSessionDestroy(Session *session) { - destroy_count += 1; - last_id = session->id(); - } - - void OnOutgoingMessage(const XmlElement* stanza) { - XmlElement* elem = new XmlElement(*stanza); - ASSERT(elem->Name() == QN_IQ); - ASSERT(elem->HasAttr(QN_TO)); - ASSERT(!elem->HasAttr(QN_FROM)); - ASSERT(elem->HasAttr(QN_TYPE)); - ASSERT((elem->Attr(QN_TYPE) == "set") || - (elem->Attr(QN_TYPE) == "result") || - (elem->Attr(QN_TYPE) == "error")); - - // Add in the appropriate "from". - elem->SetAttr(QN_FROM, username); - - // Add in the appropriate IQ ID. - if (elem->Attr(QN_TYPE) == "set") { - ASSERT(!elem->HasAttr(QN_ID)); - elem->SetAttr(QN_ID, GetNextID()); - } - - stanzas_.push_back(elem); - } - - void OnRequestSignaling() { - manager->OnSignalingReady(); - } - - - XmlElement* CheckNextStanza(const std::string& expected) { - // Get the next stanza, which should exist. - ASSERT(stanzas_.size() > 0); - XmlElement* stanza = stanzas_.front(); - stanzas_.pop_front(); - - // Make sure the stanza is correct. - std::string actual = stanza->Str(); - if (actual != expected) { - LOG(LERROR) << "Incorrect stanza: expected=\"" << expected - << "\" actual=\"" << actual << "\""; - ASSERT(actual == expected); - } - - return stanza; - } - - void CheckNoStanza() { - ASSERT(stanzas_.size() == 0); - } - - void PrintNextStanza() { - ASSERT(stanzas_.size() > 0); - printf("Stanza: %s\n", stanzas_.front()->Str().c_str()); - } - - SessionManager* manager; - std::string username; - SessionID last_id; - uint32 create_count; - uint32 destroy_count; - std::deque<XmlElement*> stanzas_; -}; - -struct SessionHandler : sigslot::has_slots<> { - SessionHandler(Session* s) : session(s) { - session->SignalState.connect(this, &SessionHandler::OnState); - session->SignalError.connect(this, &SessionHandler::OnError); - } - - void PrepareTransport() { - Transport* transport = session->GetTransport(kNsP2pTransport); - if (transport != NULL) - transport->set_allow_local_ips(true); - } - - void OnState(Session* session, Session::State state) { - ASSERT(session == this->session); - last_state = state; - } - - void OnError(Session* session, Session::Error error) { - ASSERT(session == this->session); - ASSERT(false); // errors are bad! - } - - Session* session; - Session::State last_state; -}; - -struct MySessionClient: public SessionClient, public sigslot::has_slots<> { - MySessionClient() : create_count(0), a(NULL), b(NULL) { } - - void AddManager(SessionManager* manager) { - manager->AddClient(kSessionType, this); - ASSERT(manager->GetClient(kSessionType) == this); - manager->SignalSessionCreate.connect( - this, &MySessionClient::OnSessionCreate); - } - - const SessionDescription* CreateSessionDescription( - const XmlElement* element) { - return new SessionDescription(); - } - - XmlElement* TranslateSessionDescription( - const SessionDescription* description) { - return new XmlElement(QName(kSessionType, "description")); - } - - void OnSessionCreate(Session *session, bool initiate) { - create_count += 1; - a = session->CreateChannel("a"); - b = session->CreateChannel("b"); - - if (transport_name.size() > 0) - session->SetPotentialTransports(&transport_name, 1); - } - - void OnSessionDestroy(Session *session) - { - } - - void SetTransports(bool p2p, bool raw) { - if (p2p && raw) - return; // this is the default - - if (p2p) { - transport_name = kNsP2pTransport; - } - } - - int create_count; - TransportChannel* a; - TransportChannel* b; - std::string transport_name; -}; - -struct ChannelHandler : sigslot::has_slots<> { - ChannelHandler(TransportChannel* p) - : channel(p), last_readable(false), last_writable(false), data_count(0), - last_size(0) { - p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState); - p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState); - p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket); - } - - void OnReadableState(TransportChannel* p) { - ASSERT(p == channel); - last_readable = channel->readable(); - } - - void OnWritableState(TransportChannel* p) { - ASSERT(p == channel); - last_writable = channel->writable(); - } - - void OnReadPacket(TransportChannel* p, const char* buf, size_t size) { - ASSERT(p == channel); - ASSERT(size <= sizeof(last_data)); - data_count += 1; - last_size = size; - std::memcpy(last_data, buf, size); - } - - void Send(const char* data, size_t size) { - int result = channel->SendPacket(data, size); - ASSERT(result == static_cast<int>(size)); - } - - TransportChannel* channel; - bool last_readable, last_writable; - int data_count; - char last_data[4096]; - size_t last_size; -}; - -char* Reverse(const char* str) { - int len = strlen(str); - char* rev = new char[len+1]; - for (int i = 0; i < len; i++) - rev[i] = str[len-i-1]; - rev[len] = '\0'; - return rev; -} - -// Sets up values that should be the same for every test. -void InitTest() { - SetRandomSeed(7); - gPort = 28653; - gID = 0; -} - -// Tests having client2 accept the session. -void TestAccept(talk_base::Thread* signaling_thread, - Session* session1, Session* session2, - SessionHandler* handler1, SessionHandler* handler2, - SessionManager* manager1, SessionManager* manager2, - SessionManagerHandler* manhandler1, - SessionManagerHandler* manhandler2) { - // Make sure the IQ ID is 5. - ASSERT(gID <= 5); - while (gID < 5) GetNextID(); - - // Accept the session. - SessionDescription* desc2 = new SessionDescription(); - bool valid = session2->Accept(desc2); - ASSERT(valid); - - scoped_ptr<buzz::XmlElement> stanza; - stanza.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"5\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"accept\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<ses:description xmlns:ses=\"http://oink.splat/session\"/>" - "</session>" - "</cli:iq>")); - manhandler2->CheckNoStanza(); - - // Simulate a tiny delay in sending. - signaling_thread->ProcessMessages(10); - - // Delivery the accept. - manager1->OnIncomingMessage(stanza.get()); - stanza.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" id=\"5\" type=\"result\" from=\"foo@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler1->CheckNoStanza(); - - // Both sessions should be in progress after a short wait. - signaling_thread->ProcessMessages(10); - ASSERT(handler1->last_state == Session::STATE_INPROGRESS); - ASSERT(handler2->last_state == Session::STATE_INPROGRESS); -} - -// Tests sending data between two clients, over two channels. -void TestSendRecv(ChannelHandler* chanhandler1a, ChannelHandler* chanhandler1b, - ChannelHandler* chanhandler2a, ChannelHandler* chanhandler2b, - talk_base::Thread* signaling_thread, bool first_dropped) { - const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam"; - const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce..."; - const char* dat2a = Reverse(dat1a); - const char* dat2b = Reverse(dat1b); - - // Sending from 2 -> 1 will enable 1 to send to 2 below. That will then - // enable 2 to send back to 1. So the code below will just work. - if (first_dropped) { - chanhandler2a->Send(dat2a, strlen(dat2a)); - chanhandler2b->Send(dat2b, strlen(dat2b)); - } - - for (int i = 0; i < 20; i++) { - chanhandler1a->Send(dat1a, strlen(dat1a)); - chanhandler1b->Send(dat1b, strlen(dat1b)); - chanhandler2a->Send(dat2a, strlen(dat2a)); - chanhandler2b->Send(dat2b, strlen(dat2b)); - - signaling_thread->ProcessMessages(10); - - ASSERT(chanhandler1a->data_count == i + 1); - ASSERT(chanhandler1b->data_count == i + 1); - ASSERT(chanhandler2a->data_count == i + 1); - ASSERT(chanhandler2b->data_count == i + 1); - - ASSERT(chanhandler1a->last_size == strlen(dat2a)); - ASSERT(chanhandler1b->last_size == strlen(dat2b)); - ASSERT(chanhandler2a->last_size == strlen(dat1a)); - ASSERT(chanhandler2b->last_size == strlen(dat1b)); - - ASSERT(std::memcmp(chanhandler1a->last_data, dat2a, strlen(dat2a)) == 0); - ASSERT(std::memcmp(chanhandler1b->last_data, dat2b, strlen(dat2b)) == 0); - ASSERT(std::memcmp(chanhandler2a->last_data, dat1a, strlen(dat1a)) == 0); - ASSERT(std::memcmp(chanhandler2b->last_data, dat1b, strlen(dat1b)) == 0); - } -} - -// Tests a session between two clients. The inputs indicate whether we should -// replace each client's output with what we would see from an old client. -void TestP2PCompatibility(const std::string& test_name, bool old1, bool old2) { - InitTest(); - - talk_base::Thread* signaling_thread = talk_base::Thread::Current(); - scoped_ptr<talk_base::Thread> worker_thread(new talk_base::Thread()); - worker_thread->Start(); - - scoped_ptr<PortAllocator> allocator( - new TestPortAllocator(worker_thread.get(), NULL)); - scoped_ptr<MySessionClient> client(new MySessionClient()); - client->SetTransports(true, false); - - scoped_ptr<SessionManager> manager1( - new SessionManager(allocator.get(), worker_thread.get())); - scoped_ptr<SessionManagerHandler> manhandler1( - new SessionManagerHandler(manager1.get(), "foo@baz.com")); - client->AddManager(manager1.get()); - - Session* session1 = manager1->CreateSession("foo@baz.com", kSessionType); - ASSERT(manhandler1->create_count == 1); - ASSERT(manhandler1->last_id == session1->id()); - scoped_ptr<SessionHandler> handler1(new SessionHandler(session1)); - - ASSERT(client->create_count == 1); - TransportChannel* chan1a = client->a; - ASSERT(chan1a->name() == "a"); - ASSERT(session1->GetChannel("a") == chan1a); - scoped_ptr<ChannelHandler> chanhandler1a(new ChannelHandler(chan1a)); - TransportChannel* chan1b = client->b; - ASSERT(chan1b->name() == "b"); - ASSERT(session1->GetChannel("b") == chan1b); - scoped_ptr<ChannelHandler> chanhandler1b(new ChannelHandler(chan1b)); - - SessionDescription* desc1 = new SessionDescription(); - ASSERT(session1->state() == Session::STATE_INIT); - bool valid = session1->Initiate("bar@baz.com", NULL, desc1); - ASSERT(valid); - handler1->PrepareTransport(); - - signaling_thread->ProcessMessages(100); - - ASSERT(handler1->last_state == Session::STATE_SENTINITIATE); - scoped_ptr<XmlElement> stanza1, stanza2; - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"initiate\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<ses:description xmlns:ses=\"http://oink.splat/session\"/>" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>" - "</session>" - "</cli:iq>")); - stanza2.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\"" - " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\"" - " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\"" - " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\"" - " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\"" - " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\"" - " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\"" - " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\"" - " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\"" - " network=\"network\"/>" - "</p:transport>" - "</session>" - "</cli:iq>")); - manhandler1->CheckNoStanza(); - - // If the first client were old, the initiate would have no transports and - // the candidates would be sent in a candidates message. - if (old1) { - stanza1.reset(XmlElement::ForStr( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"initiate\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<ses:description xmlns:ses=\"http://oink.splat/session\"/>" - "</session>" - "</cli:iq>")); - stanza2.reset(XmlElement::ForStr( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"candidates\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\"" - " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\"" - " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\"" - " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\"" - " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\"" - " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\"" - " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\"" - " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\"" - " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\"" - " network=\"network\"/>" - "</session>" - "</cli:iq>")); - } - - scoped_ptr<SessionManager> manager2( - new SessionManager(allocator.get(), worker_thread.get())); - scoped_ptr<SessionManagerHandler> manhandler2( - new SessionManagerHandler(manager2.get(), "bar@baz.com")); - client->AddManager(manager2.get()); - - // Deliver the initiate. - manager2->OnIncomingMessage(stanza1.get()); - stanza1.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" id=\"0\" type=\"result\" from=\"bar@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - - // If client1 is old, we will not see a transport-accept. If client2 is old, - // then we should act as if it did not send one. - if (!old1) { - stanza1.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"2\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\"" - " type=\"transport-accept\" id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>" - "</session>" - "</cli:iq>")); - } else { - GetNextID(); // Advance the ID count to be the same in all cases. - stanza1.reset(NULL); - } - if (old2) { - stanza1.reset(NULL); - } - manhandler2->CheckNoStanza(); - ASSERT(manhandler2->create_count == 1); - ASSERT(manhandler2->last_id == session1->id()); - - Session* session2 = manager2->GetSession(session1->id()); - ASSERT(session2); - ASSERT(session1->id() == session2->id()); - ASSERT(manhandler2->last_id == session2->id()); - ASSERT(session2->state() == Session::STATE_RECEIVEDINITIATE); - scoped_ptr<SessionHandler> handler2(new SessionHandler(session2)); - handler2->PrepareTransport(); - - ASSERT(session2->name() == session1->remote_name()); - ASSERT(session1->name() == session2->remote_name()); - - ASSERT(session2->transport() != NULL); - ASSERT(session2->transport()->name() == kNsP2pTransport); - - ASSERT(client->create_count == 2); - TransportChannel* chan2a = client->a; - scoped_ptr<ChannelHandler> chanhandler2a(new ChannelHandler(chan2a)); - TransportChannel* chan2b = client->b; - scoped_ptr<ChannelHandler> chanhandler2b(new ChannelHandler(chan2b)); - - // Deliver the candidates. - manager2->OnIncomingMessage(stanza2.get()); - stanza2.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" id=\"1\" type=\"result\" from=\"bar@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - - signaling_thread->ProcessMessages(10); - - // If client1 is old, we should see a candidates message instead of a - // transport-info. If client2 is old, we should act as if we did. - const char* kCandidates2 = - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"candidates\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\"" - " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\"" - " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\"" - " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\"" - " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\"" - " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\"" - " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\"" - " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\"" - " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\"" - " network=\"network\"/>" - "</session>" - "</cli:iq>"; - if (old1) { - stanza2.reset(manhandler2->CheckNextStanza(kCandidates2)); - } else { - stanza2.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\"" - " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\"" - " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\"" - " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\"" - " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\"" - " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\"" - " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\"" - " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\"" - " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\"" - " network=\"network\"/>" - "</p:transport>" - "</session>" - "</cli:iq>")); - } - if (old2) { - stanza2.reset(XmlElement::ForStr(kCandidates2)); - } - manhandler2->CheckNoStanza(); - - // Deliver the transport-accept if one exists. - if (stanza1.get() != NULL) { - manager1->OnIncomingMessage(stanza1.get()); - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" id=\"2\" type=\"result\" from=\"foo@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler1->CheckNoStanza(); - - // The first session should now have a transport. - ASSERT(session1->transport() != NULL); - ASSERT(session1->transport()->name() == kNsP2pTransport); - } - - // Deliver the candidates. If client2 is old (or is acting old because - // client1 is), then client1 will correct its earlier mistake of sending - // transport-info by sending a candidates message. If client1 is supposed to - // be old, then it sent candidates earlier, so we drop this. - manager1->OnIncomingMessage(stanza2.get()); - if (old1 || old2) { - stanza2.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"4\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"candidates\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\"" - " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\"" - " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\"" - " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\"" - " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\"" - " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\"" - " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\"" - " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\"" - " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\"" - " network=\"network\"/>" - "</session>" - "</cli:iq>")); - } else { - GetNextID(); // Advance the ID count to be the same in all cases. - stanza2.reset(NULL); - } - if (old1) { - stanza2.reset(NULL); - } - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" id=\"3\" type=\"result\" from=\"foo@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler1->CheckNoStanza(); - - // The first session must have a transport in either case now. - ASSERT(session1->transport() != NULL); - ASSERT(session1->transport()->name() == kNsP2pTransport); - - // If client1 just generated a candidates message, then we must deliver it. - if (stanza2.get() != NULL) { - manager2->OnIncomingMessage(stanza2.get()); - stanza2.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" id=\"4\" type=\"result\" from=\"bar@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler2->CheckNoStanza(); - } - - // The channels should be able to become writable at this point. This - // requires pinging, so it may take a little while. - signaling_thread->ProcessMessages(500); - ASSERT(chan1a->writable() && chan1a->readable()); - ASSERT(chan1b->writable() && chan1b->readable()); - ASSERT(chan2a->writable() && chan2a->readable()); - ASSERT(chan2b->writable() && chan2b->readable()); - ASSERT(chanhandler1a->last_writable); - ASSERT(chanhandler1b->last_writable); - ASSERT(chanhandler2a->last_writable); - ASSERT(chanhandler2b->last_writable); - - // Accept the session. - TestAccept(signaling_thread, session1, session2, - handler1.get(), handler2.get(), - manager1.get(), manager2.get(), - manhandler1.get(), manhandler2.get()); - - // Send a bunch of data between them. - TestSendRecv(chanhandler1a.get(), chanhandler1b.get(), chanhandler2a.get(), - chanhandler2b.get(), signaling_thread, false); - - manager1->DestroySession(session1); - manager2->DestroySession(session2); - - ASSERT(manhandler1->create_count == 1); - ASSERT(manhandler2->create_count == 1); - ASSERT(manhandler1->destroy_count == 1); - ASSERT(manhandler2->destroy_count == 1); - - worker_thread->Stop(); - - std::cout << "P2P Compatibility: " << test_name << ": PASS" << std::endl; -} - -// Tests the P2P transport. The flags indicate whether they clients will -// advertise support for raw as well. -void TestP2P(const std::string& test_name, bool raw1, bool raw2) { - InitTest(); - - talk_base::Thread* signaling_thread = talk_base::Thread::Current(); - scoped_ptr<talk_base::Thread> worker_thread(new talk_base::Thread()); - worker_thread->Start(); - - scoped_ptr<PortAllocator> allocator( - new TestPortAllocator(worker_thread.get(), NULL)); - scoped_ptr<MySessionClient> client1(new MySessionClient()); - client1->SetTransports(true, raw1); - scoped_ptr<MySessionClient> client2(new MySessionClient()); - client2->SetTransports(true, raw2); - - scoped_ptr<SessionManager> manager1( - new SessionManager(allocator.get(), worker_thread.get())); - scoped_ptr<SessionManagerHandler> manhandler1( - new SessionManagerHandler(manager1.get(), "foo@baz.com")); - client1->AddManager(manager1.get()); - - Session* session1 = manager1->CreateSession("foo@baz.com", kSessionType); - ASSERT(manhandler1->create_count == 1); - ASSERT(manhandler1->last_id == session1->id()); - scoped_ptr<SessionHandler> handler1(new SessionHandler(session1)); - - ASSERT(client1->create_count == 1); - TransportChannel* chan1a = client1->a; - ASSERT(chan1a->name() == "a"); - ASSERT(session1->GetChannel("a") == chan1a); - scoped_ptr<ChannelHandler> chanhandler1a(new ChannelHandler(chan1a)); - TransportChannel* chan1b = client1->b; - ASSERT(chan1b->name() == "b"); - ASSERT(session1->GetChannel("b") == chan1b); - scoped_ptr<ChannelHandler> chanhandler1b(new ChannelHandler(chan1b)); - - SessionDescription* desc1 = new SessionDescription(); - ASSERT(session1->state() == Session::STATE_INIT); - bool valid = session1->Initiate("bar@baz.com", NULL, desc1); - ASSERT(valid); - handler1->PrepareTransport(); - - signaling_thread->ProcessMessages(100); - - ASSERT(handler1->last_state == Session::STATE_SENTINITIATE); - scoped_ptr<XmlElement> stanza1, stanza2; - if (raw1) { - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"initiate\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<ses:description xmlns:ses=\"http://oink.splat/session\"/>" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>" - "<raw:transport xmlns:raw=\"http://www.google.com/transport/raw\"/>" - "</session>" - "</cli:iq>")); - } else { - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"initiate\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<ses:description xmlns:ses=\"http://oink.splat/session\"/>" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>" - "</session>" - "</cli:iq>")); - } - stanza2.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\"" - " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\"" - " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\"" - " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\"" - " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\"" - " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\"" - " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\"" - " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\"" - " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\"" - " network=\"network\"/>" - "</p:transport>" - "</session>" - "</cli:iq>")); - manhandler1->CheckNoStanza(); - - scoped_ptr<SessionManager> manager2( - new SessionManager(allocator.get(), worker_thread.get())); - scoped_ptr<SessionManagerHandler> manhandler2( - new SessionManagerHandler(manager2.get(), "bar@baz.com")); - client2->AddManager(manager2.get()); - - // Deliver the initiate. - manager2->OnIncomingMessage(stanza1.get()); - stanza1.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" id=\"0\" type=\"result\" from=\"bar@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - stanza1.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"2\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\"" - " type=\"transport-accept\" id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>" - "</session>" - "</cli:iq>")); - manhandler2->CheckNoStanza(); - ASSERT(manhandler2->create_count == 1); - ASSERT(manhandler2->last_id == session1->id()); - - Session* session2 = manager2->GetSession(session1->id()); - ASSERT(session2); - ASSERT(session1->id() == session2->id()); - ASSERT(manhandler2->last_id == session2->id()); - ASSERT(session2->state() == Session::STATE_RECEIVEDINITIATE); - scoped_ptr<SessionHandler> handler2(new SessionHandler(session2)); - handler2->PrepareTransport(); - - ASSERT(session2->name() == session1->remote_name()); - ASSERT(session1->name() == session2->remote_name()); - - ASSERT(session2->transport() != NULL); - ASSERT(session2->transport()->name() == kNsP2pTransport); - - ASSERT(client2->create_count == 1); - TransportChannel* chan2a = client2->a; - scoped_ptr<ChannelHandler> chanhandler2a(new ChannelHandler(chan2a)); - TransportChannel* chan2b = client2->b; - scoped_ptr<ChannelHandler> chanhandler2b(new ChannelHandler(chan2b)); - - // Deliver the candidates. - manager2->OnIncomingMessage(stanza2.get()); - stanza2.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" id=\"1\" type=\"result\" from=\"bar@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - - signaling_thread->ProcessMessages(10); - - stanza2.reset(manhandler2->CheckNextStanza( - "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\"" - " xmlns:cli=\"jabber:client\">" - "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\"" - " id=\"2154761789\" initiator=\"foo@baz.com\">" - "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\"" - " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\"" - " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\"" - " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\"" - " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\"" - " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\"" - " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\"" - " network=\"network\"/>" - "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\"" - " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\"" - " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\"" - " network=\"network\"/>" - "</p:transport>" - "</session>" - "</cli:iq>")); - manhandler2->CheckNoStanza(); - - // Deliver the transport-accept. - manager1->OnIncomingMessage(stanza1.get()); - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" id=\"2\" type=\"result\" from=\"foo@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler1->CheckNoStanza(); - - // The first session should now have a transport. - ASSERT(session1->transport() != NULL); - ASSERT(session1->transport()->name() == kNsP2pTransport); - - // Deliver the candidates. - manager1->OnIncomingMessage(stanza2.get()); - stanza1.reset(manhandler1->CheckNextStanza( - "<cli:iq to=\"bar@baz.com\" id=\"3\" type=\"result\" from=\"foo@baz.com\"" - " xmlns:cli=\"jabber:client\"/>")); - manhandler1->CheckNoStanza(); - - // The channels should be able to become writable at this point. This - // requires pinging, so it may take a little while. - signaling_thread->ProcessMessages(500); - ASSERT(chan1a->writable() && chan1a->readable()); - ASSERT(chan1b->writable() && chan1b->readable()); - ASSERT(chan2a->writable() && chan2a->readable()); - ASSERT(chan2b->writable() && chan2b->readable()); - ASSERT(chanhandler1a->last_writable); - ASSERT(chanhandler1b->last_writable); - ASSERT(chanhandler2a->last_writable); - ASSERT(chanhandler2b->last_writable); - - // Accept the session. - TestAccept(signaling_thread, session1, session2, - handler1.get(), handler2.get(), - manager1.get(), manager2.get(), - manhandler1.get(), manhandler2.get()); - - // Send a bunch of data between them. - TestSendRecv(chanhandler1a.get(), chanhandler1b.get(), chanhandler2a.get(), - chanhandler2b.get(), signaling_thread, false); - - manager1->DestroySession(session1); - manager2->DestroySession(session2); - - ASSERT(manhandler1->create_count == 1); - ASSERT(manhandler2->create_count == 1); - ASSERT(manhandler1->destroy_count == 1); - ASSERT(manhandler2->destroy_count == 1); - - worker_thread->Stop(); - - std::cout << "P2P: " << test_name << ": PASS" << std::endl; -} -// -int main(int argc, char* argv[]) { - talk_base::LogMessage::LogToDebug(talk_base::LS_WARNING); - - TestP2P("{p2p} => {p2p}", false, false); - TestP2P("{p2p} => {p2p,raw}", false, true); - TestP2P("{p2p,raw} => {p2p}", true, false); - TestP2P("{p2p,raw} => {p2p,raw}", true, true); - TestP2PCompatibility("New => New", false, false); - TestP2PCompatibility("Old => New", true, false); - TestP2PCompatibility("New => Old", false, true); - TestP2PCompatibility("Old => Old", true, true); - - return 0; -} diff --git a/third_party/libjingle/files/talk/p2p/base/sessionclient.h b/third_party/libjingle/files/talk/p2p/base/sessionclient.h deleted file mode 100644 index a92df1d..0000000 --- a/third_party/libjingle/files/talk/p2p/base/sessionclient.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_SESSIONCLIENT_H_ -#define _CRICKET_P2P_BASE_SESSIONCLIENT_H_ - -namespace buzz { -class XmlElement; -} - -namespace cricket { - -class Session; -class SessionDescription; - -// A SessionClient exists in 1-1 relation with each session. The implementor -// of this interface is the one that understands *what* the two sides are -// trying to send to one another. The lower-level layers only know how to send -// data; they do not know what is being sent. -class SessionClient { - public: - // Notifies the client of the creation / destruction of sessions of this type. - // - // IMPORTANT: The SessionClient, in its handling of OnSessionCreate, must - // create whatever channels are indicate in the description. This is because - // the remote client may already be attempting to connect those channels. If - // we do not create our channel right away, then connection may fail or be - // delayed. - virtual void OnSessionCreate(Session* session, bool received_initiate) = 0; - virtual void OnSessionDestroy(Session* session) = 0; - - // Provides functions to convert between the XML description of the session - // and the data structures useful to the client. The resulting objects are - // held by the Session for easy access. - virtual const SessionDescription* CreateSessionDescription( - const buzz::XmlElement* element) = 0; - virtual buzz::XmlElement* TranslateSessionDescription( - const SessionDescription* description) = 0; - -protected: - // The SessionClient interface explicitly does not include destructor - virtual ~SessionClient() { } -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_SESSIONCLIENT_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/sessiondescription.h b/third_party/libjingle/files/talk/p2p/base/sessiondescription.h deleted file mode 100644 index 28b7084..0000000 --- a/third_party/libjingle/files/talk/p2p/base/sessiondescription.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SESSIONDESCRIPTION_H_ -#define _SESSIONDESCRIPTION_H_ - -namespace cricket { - -// The client overrides this with whatever - -class SessionDescription { -public: - virtual ~SessionDescription() {} -}; - -} // namespace cricket - -#endif // _SESSIONDESCRIPTION_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/sessionid.h b/third_party/libjingle/files/talk/p2p/base/sessionid.h deleted file mode 100644 index a12535c..0000000 --- a/third_party/libjingle/files/talk/p2p/base/sessionid.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SESSIONID_H_ -#define _SESSIONID_H_ - -#include "talk/base/basictypes.h" -#include <string> -#include <sstream> - -namespace cricket { - -// Each session is identified by a pair (from,id), where id is only -// assumed to be unique to the machine identified by from. -class SessionID { -public: - SessionID() : id_str_("0") { - } - SessionID(const std::string& initiator, uint32 id) - : initiator_(initiator) { - set_id(id); - } - SessionID(const SessionID& sid) - : id_str_(sid.id_str_), initiator_(sid.initiator_) { - } - - void set_id(uint32 id) { - std::stringstream st; - st << id; - st >> id_str_; - } - const std::string id_str() const { - return id_str_; - } - void set_id_str(const std::string &id_str) { - id_str_ = id_str; - } - - const std::string &initiator() const { - return initiator_; - } - void set_initiator(const std::string &initiator) { - initiator_ = initiator; - } - - bool operator <(const SessionID& sid) const { - int r = initiator_.compare(sid.initiator_); - if (r == 0) - r = id_str_.compare(sid.id_str_); - return r < 0; - } - - bool operator ==(const SessionID& sid) const { - return (id_str_ == sid.id_str_) && (initiator_ == sid.initiator_); - } - - SessionID& operator =(const SessionID& sid) { - id_str_ = sid.id_str_; - initiator_ = sid.initiator_; - return *this; - } - -private: - std::string id_str_; - std::string initiator_; -}; - -} // namespace cricket - -#endif // _SESSIONID_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/sessionmanager.cc b/third_party/libjingle/files/talk/p2p/base/sessionmanager.cc deleted file mode 100644 index 1b0479e..0000000 --- a/third_party/libjingle/files/talk/p2p/base/sessionmanager.cc +++ /dev/null @@ -1,331 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/sessionmanager.h" -#include "talk/base/common.h" -#include "talk/base/helpers.h" -#include "talk/p2p/base/constants.h" -#include "talk/xmpp/xmppconstants.h" -#include "talk/xmpp/jid.h" - -namespace cricket { - -SessionManager::SessionManager(PortAllocator *allocator, - talk_base::Thread *worker) { - allocator_ = allocator; - signaling_thread_ = talk_base::Thread::Current(); - if (worker == NULL) { - worker_thread_ = talk_base::Thread::Current(); - } else { - worker_thread_ = worker; - } - timeout_ = 50; -} - -SessionManager::~SessionManager() { - // Note: Session::Terminate occurs asynchronously, so it's too late to - // delete them now. They better be all gone. - ASSERT(session_map_.empty()); - //TerminateAll(); -} - -void SessionManager::AddClient(const std::string& session_type, - SessionClient* client) { - ASSERT(client_map_.find(session_type) == client_map_.end()); - client_map_[session_type] = client; -} - -void SessionManager::RemoveClient(const std::string& session_type) { - ClientMap::iterator iter = client_map_.find(session_type); - ASSERT(iter != client_map_.end()); - client_map_.erase(iter); -} - -SessionClient* SessionManager::GetClient(const std::string& session_type) { - ClientMap::iterator iter = client_map_.find(session_type); - return (iter != client_map_.end()) ? iter->second : NULL; -} - -Session *SessionManager::CreateSession(const std::string& name, - const std::string& session_type) { - return CreateSession(name, SessionID(name, CreateRandomId()), session_type, - false); -} - -Session *SessionManager::CreateSession( - const std::string &name, const SessionID& id, - const std::string& session_type, bool received_initiate) { - SessionClient* client = GetClient(session_type); - ASSERT(client != NULL); - - Session *session = new Session(this, name, id, session_type, client); - session_map_[session->id()] = session; - session->SignalRequestSignaling.connect( - this, &SessionManager::OnRequestSignaling); - session->SignalOutgoingMessage.connect( - this, &SessionManager::OnOutgoingMessage); - session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage); - SignalSessionCreate(session, received_initiate); - session->client()->OnSessionCreate(session, received_initiate); - return session; -} - -void SessionManager::DestroySession(Session *session) { - if (session != NULL) { - SessionMap::iterator it = session_map_.find(session->id()); - if (it != session_map_.end()) { - SignalSessionDestroy(session); - session->client()->OnSessionDestroy(session); - session_map_.erase(it); - delete session; - } - } -} - -Session *SessionManager::GetSession(const SessionID& id) { - SessionMap::iterator it = session_map_.find(id); - if (it != session_map_.end()) - return it->second; - return NULL; -} - -void SessionManager::TerminateAll() { - while (session_map_.begin() != session_map_.end()) { - Session *session = session_map_.begin()->second; - session->Terminate(); - } -} - -bool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) { - if (stanza->Name() != buzz::QN_IQ) - return false; - if (!stanza->HasAttr(buzz::QN_TYPE)) - return false; - if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET) - return false; - - const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION); - if (!session) - return false; - if (!session->HasAttr(buzz::QN_TYPE)) - return false; - if (!session->HasAttr(buzz::QN_ID) || !session->HasAttr(QN_INITIATOR)) - return false; - - return true; -} - -Session* SessionManager::FindSessionForStanza(const buzz::XmlElement* stanza, - bool incoming) { - const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION); - ASSERT(session_xml != NULL); - - SessionID id; - id.set_id_str(session_xml->Attr(buzz::QN_ID)); - id.set_initiator(session_xml->Attr(QN_INITIATOR)); - - // Pass this message to the session in question. - SessionMap::iterator iter = session_map_.find(id); - if (iter == session_map_.end()) - return NULL; - - Session* session = iter->second; - - // match on "from"? or "to"? - buzz::QName attr = buzz::QN_TO; - if (incoming) { - attr = buzz::QN_FROM; - } - buzz::Jid remote(session->remote_name()); - buzz::Jid match(stanza->Attr(attr)); - if (remote == match) { - return session; - } - return NULL; -} - -void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) { - ASSERT(stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET); - - Session* session = FindSessionForStanza(stanza, true); - if (session) { - session->OnIncomingMessage(stanza); - return; - } - - const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION); - ASSERT(session_xml != NULL); - if (session_xml->Attr(buzz::QN_TYPE) == "initiate") { - std::string session_type = FindClient(session_xml); - if (session_type.size() == 0) { - SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - "unknown session description type", NULL); - } else { - SessionID id; - id.set_id_str(session_xml->Attr(buzz::QN_ID)); - id.set_initiator(session_xml->Attr(QN_INITIATOR)); - - session = CreateSession(stanza->Attr(buzz::QN_TO), - id, - session_type, true); - session->OnIncomingMessage(stanza); - - // If we haven't rejected, and we haven't selected a transport yet, - // let's do it now. - if ((session->state() != Session::STATE_SENTREJECT) && - (session->transport() == NULL)) { - session->ChooseTransport(stanza); - } - } - return; - } - - SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - "unknown session", NULL); -} - -void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* response_stanza) { - // We don't do anything with the response now. If we need to we can forward - // it to the session. - return; -} - -void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* error_stanza) { - Session* session = FindSessionForStanza(orig_stanza, false); - if (session) { - scoped_ptr<buzz::XmlElement> synthetic_error; - if (!error_stanza) { - // A failed send is semantically equivalent to an error response, so we - // can just turn the former into the latter. - synthetic_error.reset( - CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND, - "cancel", "Recipient did not respond", NULL)); - error_stanza = synthetic_error.get(); - } - - session->OnFailedSend(orig_stanza, error_stanza); - } -} - -std::string SessionManager::FindClient(const buzz::XmlElement* session) { - for (const buzz::XmlElement* elem = session->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - if (elem->Name().LocalPart() == "description") { - ClientMap::iterator iter = client_map_.find(elem->Name().Namespace()); - if (iter != client_map_.end()) - return iter->first; - } - } - return ""; -} - -void SessionManager::SendErrorMessage(const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info) { - scoped_ptr<buzz::XmlElement> msg( - CreateErrorMessage(stanza, name, type, text, extra_info)); - SignalOutgoingMessage(msg.get()); -} - -buzz::XmlElement* SessionManager::CreateErrorMessage( - const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info) { - buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ); - iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM)); - iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID)); - iq->SetAttr(buzz::QN_TYPE, "error"); - - for (const buzz::XmlElement* elem = stanza->FirstElement(); - elem != NULL; - elem = elem->NextElement()) { - iq->AddElement(new buzz::XmlElement(*elem)); - } - - buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR); - error->SetAttr(buzz::QN_TYPE, type); - iq->AddElement(error); - - // If the error name is not in the standard namespace, we have to first add - // some error from that namespace. - if (name.Namespace() != buzz::NS_STANZA) { - error->AddElement( - new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION)); - } - error->AddElement(new buzz::XmlElement(name)); - - if (extra_info) - error->AddElement(new buzz::XmlElement(*extra_info)); - - if (text.size() > 0) { - // It's okay to always use English here. This text is for debugging - // purposes only. - buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT); - text_elem->SetAttr(buzz::QN_XML_LANG, "en"); - text_elem->SetBodyText(text); - error->AddElement(text_elem); - } - - // TODO: Should we include error codes as well for SIP compatibility? - - return iq; -} - -void SessionManager::OnOutgoingMessage(Session* session, - const buzz::XmlElement* stanza) { - SignalOutgoingMessage(stanza); -} - -void SessionManager::OnErrorMessage(Session* session, - const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info) { - SendErrorMessage(stanza, name, type, text, extra_info); -} - -void SessionManager::OnSignalingReady() { - for (SessionMap::iterator it = session_map_.begin(); - it != session_map_.end(); - ++it) { - it->second->OnSignalingReady(); - } -} - -void SessionManager::OnRequestSignaling(Session* session) { - SignalRequestSignaling(); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/sessionmanager.h b/third_party/libjingle/files/talk/p2p/base/sessionmanager.h deleted file mode 100644 index fa008f2..0000000 --- a/third_party/libjingle/files/talk/p2p/base/sessionmanager.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SESSIONMANAGER_H_ -#define _SESSIONMANAGER_H_ - -#include "talk/base/thread.h" -#include "talk/p2p/base/portallocator.h" -#include "talk/p2p/base/session.h" -#include "talk/p2p/base/sessionid.h" -#include "talk/base/sigslot.h" - -#include <string> -#include <utility> -#include <map> - -namespace buzz { -class QName; -class XmlElement; -} - -namespace cricket { - -class Session; -class SessionClient; - -// SessionManager manages session instances - -class SessionManager : public sigslot::has_slots<> { - public: - SessionManager(PortAllocator *allocator, - talk_base::Thread *worker_thread = NULL); - virtual ~SessionManager(); - - PortAllocator *port_allocator() const { return allocator_; } - talk_base::Thread *worker_thread() const { return worker_thread_; } - talk_base::Thread *signaling_thread() const { return signaling_thread_; } - - int session_timeout() const { return timeout_; } - void set_session_timeout(int timeout) { timeout_ = timeout; } - - // Registers support for the given client. If we receive an initiate - // describing a session of the given type, we will automatically create a - // Session object and notify this client. The client may then accept or - // reject the session. - void AddClient(const std::string& session_type, SessionClient* client); - void RemoveClient(const std::string& session_type); - SessionClient* GetClient(const std::string& session_type); - - // Creates a new session. The given name is the JID of the client on whose - // behalf we initiate the session. - Session *CreateSession(const std::string& name, - const std::string& session_type); - - // Destroys the given session. - void DestroySession(Session *session); - - // Returns the session with the given ID or NULL if none exists. - Session *GetSession(const SessionID& id); - - // Terminates all of the sessions created by this manager. - void TerminateAll(); - - // These are signaled whenever the set of existing sessions changes. - sigslot::signal2<Session *, bool> SignalSessionCreate; - sigslot::signal1<Session *> SignalSessionDestroy; - - // Determines whether the given stanza is intended for some session. - bool IsSessionMessage(const buzz::XmlElement* stanza); - - // Given a stanza, this find the Session associated with that stanza - Session* FindSessionForStanza(const buzz::XmlElement* stanza, bool incoming); - - // Called when we receive a stanza for which IsSessionMessage is true. - void OnIncomingMessage(const buzz::XmlElement* stanza); - - // Called when we get a response to a message that we sent. - void OnIncomingResponse(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* response_stanza); - - // Called if an attempted to send times out or an error is returned. In the - // timeout case error_stanza will be NULL - void OnFailedSend(const buzz::XmlElement* orig_stanza, - const buzz::XmlElement* error_stanza); - - // Signalled each time a session generates a signaling message to send. - sigslot::signal1<const buzz::XmlElement*> SignalOutgoingMessage; - - // Signaled before sessions try to send certain signaling messages. The - // client should call OnSignalingReady once it is safe to send them. These - // steps are taken so that we don't send signaling messages trying to - // re-establish the connectivity of a session when the client cannot send - // the messages (and would probably just drop them on the floor). - // - // Note: you can connect this directly to OnSignalingReady(), if a signalling - // check is not supported. - sigslot::signal0<> SignalRequestSignaling; - void OnSignalingReady(); - - private: - typedef std::map<SessionID, Session *> SessionMap; - typedef std::map<std::string, SessionClient*> ClientMap; - - PortAllocator *allocator_; - talk_base::Thread *signaling_thread_; - talk_base::Thread *worker_thread_; - int timeout_; - SessionMap session_map_; - ClientMap client_map_; - - // Helper function for CreateSession. This is also invoked when we receive - // a message attempting to initiate a session with this client. - Session *CreateSession(const std::string& name, - const SessionID& id, - const std::string& session_type, - bool received_initiate); - - // Attempts to find a registered session type whose description appears as - // a child of the session element. Such a child should be present indicating - // the application they hope to initiate. - std::string FindClient(const buzz::XmlElement* session); - - // Sends a message back to the other client indicating that we found an error - // in the stanza they sent. name identifies the error, type is one of the - // standard XMPP types (cancel, continue, modify, auth, wait), and text is a - // description for debugging purposes. - void SendErrorMessage(const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info); - - // Creates and returns an error message from the given components. The - // caller is responsible for deleting this. - buzz::XmlElement* CreateErrorMessage( - const buzz::XmlElement* stanza, - const buzz::QName& name, - const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info); - - // Called each time a session requests signaling. - void OnRequestSignaling(Session* session); - - // Called each time a session has an outgoing message. - void OnOutgoingMessage(Session* session, const buzz::XmlElement* stanza); - - // Called each time a session has an error to send. - void OnErrorMessage(Session* session, const buzz::XmlElement* stanza, - const buzz::QName& name, const std::string& type, - const std::string& text, - const buzz::XmlElement* extra_info); -}; - -} // namespace cricket - -#endif // _SESSIONMANAGER_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/stun.cc b/third_party/libjingle/files/talk/p2p/base/stun.cc deleted file mode 100644 index 3d5ae66..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stun.cc +++ /dev/null @@ -1,579 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/base/logging.h" -#include "talk/p2p/base/stun.h" -#include <iostream> -#include <cassert> -#include <cstring> - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std { - using ::memcpy; -} -#endif - -using talk_base::ByteBuffer; - -namespace cricket { - -const std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST"; -const std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED"; -const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE"; -const std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS"; -const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE"; -const std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME"; -const std::string STUN_ERROR_REASON_USE_TLS = "USE TLS"; -const std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR"; -const std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE"; - -StunMessage::StunMessage() : type_(0), length_(0), - transaction_id_("0000000000000000") { - assert(transaction_id_.size() == 16); - attrs_ = new std::vector<StunAttribute*>(); -} - -StunMessage::~StunMessage() { - for (unsigned i = 0; i < attrs_->size(); i++) - delete (*attrs_)[i]; - delete attrs_; -} - -void StunMessage::SetTransactionID(const std::string& str) { - assert(str.size() == 16); - transaction_id_ = str; -} - -void StunMessage::AddAttribute(StunAttribute* attr) { - attrs_->push_back(attr); - length_ += attr->length() + 4; -} - -const StunAddressAttribute* -StunMessage::GetAddress(StunAttributeType type) const { - switch (type) { - case STUN_ATTR_MAPPED_ADDRESS: - case STUN_ATTR_RESPONSE_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS: - case STUN_ATTR_CHANGED_ADDRESS: - case STUN_ATTR_REFLECTED_FROM: - case STUN_ATTR_ALTERNATE_SERVER: - case STUN_ATTR_DESTINATION_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS2: - return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type)); - - default: - assert(0); - return 0; - } -} - -const StunUInt32Attribute* -StunMessage::GetUInt32(StunAttributeType type) const { - switch (type) { - case STUN_ATTR_CHANGE_REQUEST: - case STUN_ATTR_LIFETIME: - case STUN_ATTR_BANDWIDTH: - case STUN_ATTR_OPTIONS: - return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type)); - - default: - assert(0); - return 0; - } -} - -const StunByteStringAttribute* -StunMessage::GetByteString(StunAttributeType type) const { - switch (type) { - case STUN_ATTR_USERNAME: - case STUN_ATTR_PASSWORD: - case STUN_ATTR_MESSAGE_INTEGRITY: - case STUN_ATTR_DATA: - case STUN_ATTR_MAGIC_COOKIE: - return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type)); - - default: - assert(0); - return 0; - } -} - -const StunErrorCodeAttribute* StunMessage::GetErrorCode() const { - return reinterpret_cast<const StunErrorCodeAttribute*>( - GetAttribute(STUN_ATTR_ERROR_CODE)); -} - -const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const { - return reinterpret_cast<const StunUInt16ListAttribute*>( - GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES)); -} - -const StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const { - return reinterpret_cast<const StunTransportPrefsAttribute*>( - GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES)); -} - -const StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const { - for (unsigned i = 0; i < attrs_->size(); i++) { - if ((*attrs_)[i]->type() == type) - return (*attrs_)[i]; - } - return 0; -} - -bool StunMessage::Read(ByteBuffer* buf) { - if (!buf->ReadUInt16(type_)) - return false; - - if (!buf->ReadUInt16(length_)) - return false; - - std::string transaction_id; - if (!buf->ReadString(transaction_id, 16)) - return false; - assert(transaction_id.size() == 16); - transaction_id_ = transaction_id; - - if (length_ > buf->Length()) - return false; - - attrs_->resize(0); - - size_t rest = buf->Length() - length_; - while (buf->Length() > rest) { - uint16 attr_type, attr_length; - if (!buf->ReadUInt16(attr_type)) - return false; - if (!buf->ReadUInt16(attr_length)) - return false; - - StunAttribute* attr = StunAttribute::Create(attr_type, attr_length); - if (!attr || !attr->Read(buf)) - return false; - - attrs_->push_back(attr); - } - - if (buf->Length() != rest) { - // fixme: shouldn't be doing this - LOG(LERROR) << "wrong message length" - << " (" << (int)rest << " != " << (int)buf->Length() << ")"; - return false; - } - - return true; -} - -void StunMessage::Write(ByteBuffer* buf) const { - buf->WriteUInt16(type_); - buf->WriteUInt16(length_); - buf->WriteString(transaction_id_); - - for (unsigned i = 0; i < attrs_->size(); i++) { - buf->WriteUInt16((*attrs_)[i]->type()); - buf->WriteUInt16((*attrs_)[i]->length()); - (*attrs_)[i]->Write(buf); - } -} - -StunAttribute::StunAttribute(uint16 type, uint16 length) - : type_(type), length_(length) { -} - -StunAttribute* StunAttribute::Create(uint16 type, uint16 length) { - switch (type) { - case STUN_ATTR_MAPPED_ADDRESS: - case STUN_ATTR_RESPONSE_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS: - case STUN_ATTR_CHANGED_ADDRESS: - case STUN_ATTR_REFLECTED_FROM: - case STUN_ATTR_ALTERNATE_SERVER: - case STUN_ATTR_DESTINATION_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS2: - if (length != StunAddressAttribute::SIZE) - return 0; - return new StunAddressAttribute(type); - - case STUN_ATTR_CHANGE_REQUEST: - case STUN_ATTR_LIFETIME: - case STUN_ATTR_BANDWIDTH: - case STUN_ATTR_OPTIONS: - if (length != StunUInt32Attribute::SIZE) - return 0; - return new StunUInt32Attribute(type); - - case STUN_ATTR_USERNAME: - case STUN_ATTR_PASSWORD: - case STUN_ATTR_MAGIC_COOKIE: - return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0; - - case STUN_ATTR_MESSAGE_INTEGRITY: - return (length == 20) ? new StunByteStringAttribute(type, length) : 0; - - case STUN_ATTR_DATA: - return new StunByteStringAttribute(type, length); - - case STUN_ATTR_ERROR_CODE: - if (length < StunErrorCodeAttribute::MIN_SIZE) - return 0; - return new StunErrorCodeAttribute(type, length); - - case STUN_ATTR_UNKNOWN_ATTRIBUTES: - return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0; - - case STUN_ATTR_TRANSPORT_PREFERENCES: - if ((length != StunTransportPrefsAttribute::SIZE1) && - (length != StunTransportPrefsAttribute::SIZE2)) - return 0; - return new StunTransportPrefsAttribute(type, length); - - default: - return 0; - } -} - -StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) { - switch (type) { - case STUN_ATTR_MAPPED_ADDRESS: - case STUN_ATTR_RESPONSE_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS: - case STUN_ATTR_CHANGED_ADDRESS: - case STUN_ATTR_REFLECTED_FROM: - case STUN_ATTR_ALTERNATE_SERVER: - case STUN_ATTR_DESTINATION_ADDRESS: - case STUN_ATTR_SOURCE_ADDRESS2: - return new StunAddressAttribute(type); - - default: - assert(false); - return 0; - } -} - -StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) { - switch (type) { - case STUN_ATTR_CHANGE_REQUEST: - case STUN_ATTR_LIFETIME: - case STUN_ATTR_BANDWIDTH: - case STUN_ATTR_OPTIONS: - return new StunUInt32Attribute(type); - - default: - assert(false); - return 0; - } -} - -StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) { - switch (type) { - case STUN_ATTR_USERNAME: - case STUN_ATTR_PASSWORD: - case STUN_ATTR_MESSAGE_INTEGRITY: - case STUN_ATTR_DATA: - case STUN_ATTR_MAGIC_COOKIE: - return new StunByteStringAttribute(type, 0); - - default: - assert(false); - return 0; - } -} - -StunErrorCodeAttribute* StunAttribute::CreateErrorCode() { - return new StunErrorCodeAttribute( - STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE); -} - -StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() { - return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0); -} - -StunTransportPrefsAttribute* StunAttribute::CreateTransportPrefs() { - return new StunTransportPrefsAttribute( - STUN_ATTR_TRANSPORT_PREFERENCES, StunTransportPrefsAttribute::SIZE1); -} - -StunAddressAttribute::StunAddressAttribute(uint16 type) - : StunAttribute(type, SIZE), family_(0), port_(0), ip_(0) { -} - -bool StunAddressAttribute::Read(ByteBuffer* buf) { - uint8 dummy; - if (!buf->ReadUInt8(dummy)) - return false; - if (!buf->ReadUInt8(family_)) - return false; - if (!buf->ReadUInt16(port_)) - return false; - if (!buf->ReadUInt32(ip_)) - return false; - return true; -} - -void StunAddressAttribute::Write(ByteBuffer* buf) const { - buf->WriteUInt8(0); - buf->WriteUInt8(family_); - buf->WriteUInt16(port_); - buf->WriteUInt32(ip_); -} - -StunUInt32Attribute::StunUInt32Attribute(uint16 type) - : StunAttribute(type, SIZE), bits_(0) { -} - -bool StunUInt32Attribute::GetBit(int index) const { - assert((0 <= index) && (index < 32)); - return static_cast<bool>((bits_ >> index) & 0x1); -} - -void StunUInt32Attribute::SetBit(int index, bool value) { - assert((0 <= index) && (index < 32)); - bits_ &= ~(1 << index); - bits_ |= value ? (1 << index) : 0; -} - -bool StunUInt32Attribute::Read(ByteBuffer* buf) { - if (!buf->ReadUInt32(bits_)) - return false; - return true; -} - -void StunUInt32Attribute::Write(ByteBuffer* buf) const { - buf->WriteUInt32(bits_); -} - -StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length) - : StunAttribute(type, length), bytes_(0) { -} - -StunByteStringAttribute::~StunByteStringAttribute() { - delete [] bytes_; -} - -void StunByteStringAttribute::SetBytes(char* bytes, uint16 length) { - delete [] bytes_; - bytes_ = bytes; - SetLength(length); -} - -void StunByteStringAttribute::CopyBytes(const char* bytes) { - CopyBytes(bytes, (uint16)strlen(bytes)); -} - -void StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) { - char* new_bytes = new char[length]; - std::memcpy(new_bytes, bytes, length); - SetBytes(new_bytes, length); -} - -uint8 StunByteStringAttribute::GetByte(int index) const { - assert(bytes_); - assert((0 <= index) && (index < length())); - return static_cast<uint8>(bytes_[index]); -} - -void StunByteStringAttribute::SetByte(int index, uint8 value) { - assert(bytes_); - assert((0 <= index) && (index < length())); - bytes_[index] = value; -} - -bool StunByteStringAttribute::Read(ByteBuffer* buf) { - bytes_ = new char[length()]; - if (!buf->ReadBytes(bytes_, length())) - return false; - return true; -} - -void StunByteStringAttribute::Write(ByteBuffer* buf) const { - buf->WriteBytes(bytes_, length()); -} - -StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length) - : StunAttribute(type, length), class_(0), number_(0) { -} - -StunErrorCodeAttribute::~StunErrorCodeAttribute() { -} - -void StunErrorCodeAttribute::SetErrorCode(uint32 code) { - class_ = (uint8)((code >> 8) & 0x7); - number_ = (uint8)(code & 0xff); -} - -void StunErrorCodeAttribute::SetReason(const std::string& reason) { - SetLength(MIN_SIZE + (uint16)reason.size()); - reason_ = reason; -} - -bool StunErrorCodeAttribute::Read(ByteBuffer* buf) { - uint32 val; - if (!buf->ReadUInt32(val)) - return false; - - if ((val >> 11) != 0) - LOG(LERROR) << "error-code bits not zero"; - - SetErrorCode(val); - - if (!buf->ReadString(reason_, length() - 4)) - return false; - - return true; -} - -void StunErrorCodeAttribute::Write(ByteBuffer* buf) const { - buf->WriteUInt32(error_code()); - buf->WriteString(reason_); -} - -StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length) - : StunAttribute(type, length) { - attr_types_ = new std::vector<uint16>(); -} - -StunUInt16ListAttribute::~StunUInt16ListAttribute() { - delete attr_types_; -} - -size_t StunUInt16ListAttribute::Size() const { - return attr_types_->size(); -} - -uint16 StunUInt16ListAttribute::GetType(int index) const { - return (*attr_types_)[index]; -} - -void StunUInt16ListAttribute::SetType(int index, uint16 value) { - (*attr_types_)[index] = value; -} - -void StunUInt16ListAttribute::AddType(uint16 value) { - attr_types_->push_back(value); - SetLength((uint16)attr_types_->size() * 2); -} - -bool StunUInt16ListAttribute::Read(ByteBuffer* buf) { - for (int i = 0; i < length() / 2; i++) { - uint16 attr; - if (!buf->ReadUInt16(attr)) - return false; - attr_types_->push_back(attr); - } - return true; -} - -void StunUInt16ListAttribute::Write(ByteBuffer* buf) const { - for (unsigned i = 0; i < attr_types_->size(); i++) - buf->WriteUInt16((*attr_types_)[i]); -} - -StunTransportPrefsAttribute::StunTransportPrefsAttribute( - uint16 type, uint16 length) - : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) { -} - -StunTransportPrefsAttribute::~StunTransportPrefsAttribute() { - delete addr_; -} - -void StunTransportPrefsAttribute::SetPreallocateAddress( - StunAddressAttribute* addr) { - if (!addr) { - preallocate_ = false; - addr_ = 0; - SetLength(SIZE1); - } else { - preallocate_ = true; - addr_ = addr; - SetLength(SIZE2); - } -} - -bool StunTransportPrefsAttribute::Read(ByteBuffer* buf) { - uint32 val; - if (!buf->ReadUInt32(val)) - return false; - - if ((val >> 3) != 0) - LOG(LERROR) << "transport-preferences bits not zero"; - - preallocate_ = static_cast<bool>((val >> 2) & 0x1); - prefs_ = (uint8)(val & 0x3); - - if (preallocate_ && (prefs_ == 3)) - LOG(LERROR) << "transport-preferences imcompatible P and Typ"; - - if (!preallocate_) { - if (length() != StunUInt32Attribute::SIZE) - return false; - } else { - if (length() != StunUInt32Attribute::SIZE + StunAddressAttribute::SIZE) - return false; - - addr_ = new StunAddressAttribute(STUN_ATTR_SOURCE_ADDRESS); - addr_->Read(buf); - } - - return true; -} - -void StunTransportPrefsAttribute::Write(ByteBuffer* buf) const { - buf->WriteUInt32((preallocate_ ? 4 : 0) | prefs_); - - if (preallocate_) - addr_->Write(buf); -} - -StunMessageType GetStunResponseType(StunMessageType request_type) { - switch (request_type) { - case STUN_SHARED_SECRET_REQUEST: - return STUN_SHARED_SECRET_RESPONSE; - case STUN_ALLOCATE_REQUEST: - return STUN_ALLOCATE_RESPONSE; - case STUN_SEND_REQUEST: - return STUN_SEND_RESPONSE; - default: - return STUN_BINDING_RESPONSE; - } -} - -StunMessageType GetStunErrorResponseType(StunMessageType request_type) { - switch (request_type) { - case STUN_SHARED_SECRET_REQUEST: - return STUN_SHARED_SECRET_ERROR_RESPONSE; - case STUN_ALLOCATE_REQUEST: - return STUN_ALLOCATE_ERROR_RESPONSE; - case STUN_SEND_REQUEST: - return STUN_SEND_ERROR_RESPONSE; - default: - return STUN_BINDING_ERROR_RESPONSE; - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/stun.h b/third_party/libjingle/files/talk/p2p/base/stun.h deleted file mode 100644 index 4c0459b..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stun.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STUN_H__ -#define __STUN_H__ - -// This file contains classes for dealing with the STUN and TURN protocols. -// Both protocols use the same wire format. - -#include "talk/base/basictypes.h" -#include "talk/base/bytebuffer.h" -#include <string> -#include <vector> - -namespace cricket { - -// These are the types of STUN & TURN messages as of last check. -enum StunMessageType { - STUN_BINDING_REQUEST = 0x0001, - STUN_BINDING_RESPONSE = 0x0101, - STUN_BINDING_ERROR_RESPONSE = 0x0111, - STUN_SHARED_SECRET_REQUEST = 0x0002, - STUN_SHARED_SECRET_RESPONSE = 0x0102, - STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, - STUN_ALLOCATE_REQUEST = 0x0003, - STUN_ALLOCATE_RESPONSE = 0x0103, - STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, - STUN_SEND_REQUEST = 0x0004, - STUN_SEND_RESPONSE = 0x0104, - STUN_SEND_ERROR_RESPONSE = 0x0114, - STUN_DATA_INDICATION = 0x0115 -}; - -// These are the types of attributes defined in STUN & TURN. Next to each is -// the name of the class (T is StunTAttribute) that implements that type. -enum StunAttributeType { - STUN_ATTR_MAPPED_ADDRESS = 0x0001, // Address - STUN_ATTR_RESPONSE_ADDRESS = 0x0002, // Address - STUN_ATTR_CHANGE_REQUEST = 0x0003, // UInt32 - STUN_ATTR_SOURCE_ADDRESS = 0x0004, // Address - STUN_ATTR_CHANGED_ADDRESS = 0x0005, // Address - STUN_ATTR_USERNAME = 0x0006, // ByteString, multiple of 4 bytes - STUN_ATTR_PASSWORD = 0x0007, // ByteString, multiple of 4 bytes - STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, // ByteString, 20 bytes - STUN_ATTR_ERROR_CODE = 0x0009, // ErrorCode - STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, // UInt16List - STUN_ATTR_REFLECTED_FROM = 0x000b, // Address - STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, // TransportPrefs - STUN_ATTR_LIFETIME = 0x000d, // UInt32 - STUN_ATTR_ALTERNATE_SERVER = 0x000e, // Address - STUN_ATTR_MAGIC_COOKIE = 0x000f, // ByteString, 4 bytes - STUN_ATTR_BANDWIDTH = 0x0010, // UInt32 - STUN_ATTR_DESTINATION_ADDRESS = 0x0011, // Address - STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, // Address - STUN_ATTR_DATA = 0x0013, // ByteString - STUN_ATTR_OPTIONS = 0x8001 // UInt32 -}; - -enum StunErrorCodes { - STUN_ERROR_BAD_REQUEST = 400, - STUN_ERROR_UNAUTHORIZED = 401, - STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, - STUN_ERROR_STALE_CREDENTIALS = 430, - STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431, - STUN_ERROR_MISSING_USERNAME = 432, - STUN_ERROR_USE_TLS = 433, - STUN_ERROR_SERVER_ERROR = 500, - STUN_ERROR_GLOBAL_FAILURE = 600 -}; - -extern const std::string STUN_ERROR_REASON_BAD_REQUEST; -extern const std::string STUN_ERROR_REASON_UNAUTHORIZED; -extern const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE; -extern const std::string STUN_ERROR_REASON_STALE_CREDENTIALS; -extern const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE; -extern const std::string STUN_ERROR_REASON_MISSING_USERNAME; -extern const std::string STUN_ERROR_REASON_USE_TLS; -extern const std::string STUN_ERROR_REASON_SERVER_ERROR; -extern const std::string STUN_ERROR_REASON_GLOBAL_FAILURE; - -class StunAttribute; -class StunAddressAttribute; -class StunUInt32Attribute; -class StunByteStringAttribute; -class StunErrorCodeAttribute; -class StunUInt16ListAttribute; -class StunTransportPrefsAttribute; - -// Records a complete STUN/TURN message. Each message consists of a type and -// any number of attributes. Each attribute is parsed into an instance of an -// appropriate class (see above). The Get* methods will return instances of -// that attribute class. -class StunMessage { -public: - StunMessage(); - ~StunMessage(); - - StunMessageType type() const { return static_cast<StunMessageType>(type_); } - uint16 length() const { return length_; } - const std::string& transaction_id() const { return transaction_id_; } - - void SetType(StunMessageType type) { type_ = type; } - void SetTransactionID(const std::string& str); - - const StunAddressAttribute* GetAddress(StunAttributeType type) const; - const StunUInt32Attribute* GetUInt32(StunAttributeType type) const; - const StunByteStringAttribute* GetByteString(StunAttributeType type) const; - const StunErrorCodeAttribute* GetErrorCode() const; - const StunUInt16ListAttribute* GetUnknownAttributes() const; - const StunTransportPrefsAttribute* GetTransportPrefs() const; - - void AddAttribute(StunAttribute* attr); - - // Parses the STUN/TURN packet in the given buffer and records it here. The - // return value indicates whether this was successful. - bool Read(talk_base::ByteBuffer* buf); - - // Writes this object into a STUN/TURN packet. Return value is true if - // successful. - void Write(talk_base::ByteBuffer* buf) const; - -private: - uint16 type_; - uint16 length_; - std::string transaction_id_; - std::vector<StunAttribute*>* attrs_; - - const StunAttribute* GetAttribute(StunAttributeType type) const; -}; - -// Base class for all STUN/TURN attributes. -class StunAttribute { -public: - virtual ~StunAttribute() {} - - StunAttributeType type() const { - return static_cast<StunAttributeType>(type_); - } - uint16 length() const { return length_; } - - // Reads the body (not the type or length) for this type of attribute from - // the given buffer. Return value is true if successful. - virtual bool Read(talk_base::ByteBuffer* buf) = 0; - - // Writes the body (not the type or length) to the given buffer. Return - // value is true if successful. - virtual void Write(talk_base::ByteBuffer* buf) const = 0; - - // Creates an attribute object with the given type and len. - static StunAttribute* Create(uint16 type, uint16 length); - - // Creates an attribute object with the given type and smallest length. - static StunAddressAttribute* CreateAddress(uint16 type); - static StunUInt32Attribute* CreateUInt32(uint16 type); - static StunByteStringAttribute* CreateByteString(uint16 type); - static StunErrorCodeAttribute* CreateErrorCode(); - static StunUInt16ListAttribute* CreateUnknownAttributes(); - static StunTransportPrefsAttribute* CreateTransportPrefs(); - -protected: - StunAttribute(uint16 type, uint16 length); - - void SetLength(uint16 length) { length_ = length; } - -private: - uint16 type_; - uint16 length_; -}; - -// Implements STUN/TURN attributes that record an Internet address. -class StunAddressAttribute : public StunAttribute { -public: - StunAddressAttribute(uint16 type); - -#if (_MSC_VER < 1300) - enum { SIZE = 8 }; -#else - static const uint16 SIZE = 8; -#endif - - uint8 family() const { return family_; } - uint16 port() const { return port_; } - uint32 ip() const { return ip_; } - - void SetFamily(uint8 family) { family_ = family; } - void SetIP(uint32 ip) { ip_ = ip; } - void SetPort(uint16 port) { port_ = port; } - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - uint8 family_; - uint16 port_; - uint32 ip_; -}; - -// Implements STUN/TURN attributs that record a 32-bit integer. -class StunUInt32Attribute : public StunAttribute { -public: - StunUInt32Attribute(uint16 type); - -#if (_MSC_VER < 1300) - enum { SIZE = 4 }; -#else - static const uint16 SIZE = 4; -#endif - - uint32 value() const { return bits_; } - - void SetValue(uint32 bits) { bits_ = bits; } - - bool GetBit(int index) const; - void SetBit(int index, bool value); - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - uint32 bits_; -}; - -// Implements STUN/TURN attributs that record an arbitrary byte string -class StunByteStringAttribute : public StunAttribute { -public: - StunByteStringAttribute(uint16 type, uint16 length); - ~StunByteStringAttribute(); - - const char* bytes() const { return bytes_; } - - void SetBytes(char* bytes, uint16 length); - - void CopyBytes(const char* bytes); // uses strlen - void CopyBytes(const void* bytes, uint16 length); - - uint8 GetByte(int index) const; - void SetByte(int index, uint8 value); - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - char* bytes_; -}; - -// Implements STUN/TURN attributs that record an error code. -class StunErrorCodeAttribute : public StunAttribute { -public: - StunErrorCodeAttribute(uint16 type, uint16 length); - ~StunErrorCodeAttribute(); - -#if (_MSC_VER < 1300) - enum { MIN_SIZE = 4 }; -#else - static const uint16 MIN_SIZE = 4; -#endif - - uint32 error_code() const { return (class_ << 8) | number_; } - uint8 error_class() const { return class_; } - uint8 number() const { return number_; } - const std::string& reason() const { return reason_; } - - void SetErrorCode(uint32 code); - void SetErrorClass(uint8 eclass) { class_ = eclass; } - void SetNumber(uint8 number) { number_ = number; } - void SetReason(const std::string& reason); - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - uint8 class_; - uint8 number_; - std::string reason_; -}; - -// Implements STUN/TURN attributs that record a list of attribute names. -class StunUInt16ListAttribute : public StunAttribute { -public: - StunUInt16ListAttribute(uint16 type, uint16 length); - ~StunUInt16ListAttribute(); - - size_t Size() const; - uint16 GetType(int index) const; - void SetType(int index, uint16 value); - void AddType(uint16 value); - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - std::vector<uint16>* attr_types_; -}; - -// Implements the TURN TRANSPORT-PREFS attribute, which provides information -// about the ports to allocate. -class StunTransportPrefsAttribute : public StunAttribute { -public: - StunTransportPrefsAttribute(uint16 type, uint16 length); - ~StunTransportPrefsAttribute(); - -#if (_MSC_VER < 1300) - enum { SIZE1 = 4, SIZE2 = 12 }; -#else - static const uint16 SIZE1 = 4; - static const uint16 SIZE2 = 12; -#endif - - bool preallocate() const { return preallocate_; } - uint8 preference_type() const { return prefs_; } - const StunAddressAttribute* address() const { return addr_; } - - void SetPreferenceType(uint8 prefs) { prefs_ = prefs; } - - // Sets the preallocate address to the given value, or if 0 is given, it sets - // to not preallocate. - void SetPreallocateAddress(StunAddressAttribute* addr); - - bool Read(talk_base::ByteBuffer* buf); - void Write(talk_base::ByteBuffer* buf) const; - -private: - bool preallocate_; - uint8 prefs_; - StunAddressAttribute* addr_; -}; - -// The special MAGIC-COOKIE attribute is used to distinguish TURN packets from -// other kinds of traffic. -const char STUN_MAGIC_COOKIE_VALUE[] = { 0x72, char(0xc6), 0x4b, char(0xc6) }; - -// Returns the (successful) response type for the given request type. -StunMessageType GetStunResponseType(StunMessageType request_type); - -// Returns the error response type for the given request type. -StunMessageType GetStunErrorResponseType(StunMessageType request_type); - -} // namespace cricket - -#endif // __STUN_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/stunport.cc b/third_party/libjingle/files/talk/p2p/base/stunport.cc deleted file mode 100644 index 8fa3fd8..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunport.cc +++ /dev/null @@ -1,204 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif -#include <iostream> -#include <cassert> -#include "talk/base/common.h" -#include "talk/base/logging.h" -#include "talk/base/helpers.h" -#include "talk/p2p/base/stunport.h" - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std { - using ::strerror; -} -#endif - -#ifdef POSIX -#include <errno.h> -#endif // POSIX - -namespace cricket { - -const int KEEPALIVE_DELAY = 10 * 1000; // 10 seconds - sort timeouts -const int RETRY_DELAY = 50; // 50ms, from ICE spec -const uint32 RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs - -// Handles a binding request sent to the STUN server. -class StunPortBindingRequest : public StunRequest { -public: - StunPortBindingRequest(StunPort* port, bool keep_alive, - const talk_base::SocketAddress& addr) - : port_(port), keep_alive_(keep_alive), server_addr_(addr) { - start_time_ = talk_base::GetMillisecondCount(); - } - - virtual ~StunPortBindingRequest() { - } - - const talk_base::SocketAddress& server_addr() const { return server_addr_; } - - virtual void Prepare(StunMessage* request) { - request->SetType(STUN_BINDING_REQUEST); - } - - virtual void OnResponse(StunMessage* response) { - const StunAddressAttribute* addr_attr = - response->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - if (!addr_attr) { - LOG(LERROR) << "Binding response missing mapped address."; - } else if (addr_attr->family() != 1) { - LOG(LERROR) << "Binding address has bad family"; - } else { - talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port()); - port_->AddAddress(addr, "udp", true); - } - - // We will do a keep-alive regardless of whether this request suceeds. - // This should have almost no impact on network usage. - if (keep_alive_) { - port_->requests_.SendDelayed( - new StunPortBindingRequest(port_, true, server_addr_), - KEEPALIVE_DELAY); - } - } - - virtual void OnErrorResponse(StunMessage* response) { - const StunErrorCodeAttribute* attr = response->GetErrorCode(); - if (!attr) { - LOG(LERROR) << "Bad allocate response error code"; - } else { - LOG(LERROR) << "Binding error response:" - << " class=" << attr->error_class() - << " number=" << attr->number() - << " reason='" << attr->reason() << "'"; - } - - port_->SignalAddressError(port_); - - if (keep_alive_ - && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) { - port_->requests_.SendDelayed( - new StunPortBindingRequest(port_, true, server_addr_), - KEEPALIVE_DELAY); - } - } - - virtual void OnTimeout() { - LOG(LERROR) << "Binding request timed out from " - << port_->GetLocalAddress().ToString() - << " (" << port_->network()->name() << ")"; - - port_->SignalAddressError(port_); - - if (keep_alive_ - && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) { - port_->requests_.SendDelayed( - new StunPortBindingRequest(port_, true, server_addr_), - RETRY_DELAY); - } - } - -private: - StunPort* port_; - bool keep_alive_; - talk_base::SocketAddress server_addr_; - uint32 start_time_; -}; - -const std::string STUN_PORT_TYPE("stun"); - -StunPort::StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, - const talk_base::SocketAddress& local_addr, - const talk_base::SocketAddress& server_addr) - : UDPPort(thread, STUN_PORT_TYPE, factory, network), - server_addr_(server_addr), requests_(thread), error_(0) { - - socket_ = CreatePacketSocket(PROTO_UDP); - socket_->SignalReadPacket.connect(this, &StunPort::OnReadPacket); - if (socket_->Bind(local_addr) < 0) - PLOG(LERROR, socket_->GetError()) << "bind"; - - requests_.SignalSendPacket.connect(this, &StunPort::OnSendPacket); -} - -StunPort::~StunPort() { - delete socket_; -} - -void StunPort::PrepareAddress() { - // We will keep pinging the stun server to make sure our NAT pin-hole stays - // open during the call. - requests_.Send(new StunPortBindingRequest(this, true, server_addr_)); -} - -void StunPort::PrepareSecondaryAddress() { - ASSERT(!server_addr2_.IsAny()); - requests_.Send(new StunPortBindingRequest(this, false, server_addr2_)); -} - -int StunPort::SendTo( - const void* data, size_t size, const talk_base::SocketAddress& addr, - bool payload) { - int sent = socket_->SendTo(data, size, addr); - if (sent < 0) - error_ = socket_->GetError(); - return sent; -} - -int StunPort::SetOption(talk_base::Socket::Option opt, int value) { - return socket_->SetOption(opt, value); -} - -int StunPort::GetError() { - return error_; -} - -void StunPort::OnReadPacket( - const char* data, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - assert(socket == socket_); - - // Look for a response to a binding request. - if (requests_.CheckResponse(data, size)) - return; - - // Process this data packet in the normal manner. - UDPPort::OnReadPacket(data, size, remote_addr); -} - -void StunPort::OnSendPacket(const void* data, size_t size, StunRequest* req) { - StunPortBindingRequest* sreq = static_cast<StunPortBindingRequest*>(req); - if (socket_->SendTo(data, size, sreq->server_addr()) < 0) - PLOG(LERROR, socket_->GetError()) << "sendto"; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/stunport.h b/third_party/libjingle/files/talk/p2p/base/stunport.h deleted file mode 100644 index 4b62181..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunport.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STUNPORT_H__ -#define __STUNPORT_H__ - -#include "talk/base/asyncudpsocket.h" -#include "talk/p2p/base/udpport.h" -#include "talk/p2p/base/stunrequest.h" - -namespace cricket { - -extern const std::string STUN_PORT_TYPE; - -// Communicates using the address on the outside of a NAT. -class StunPort : public UDPPort { -public: - StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, - const talk_base::SocketAddress& local_addr, - const talk_base::SocketAddress& server_addr); - virtual ~StunPort(); - - const talk_base::SocketAddress& server_addr() const { return server_addr_; } - void set_server_addr(const talk_base::SocketAddress& addr) - { server_addr_ = addr; } - - const talk_base::SocketAddress& server_addr2() const { return server_addr2_; } - void set_server_addr2(const talk_base::SocketAddress& addr) - { server_addr2_ = addr; } - - virtual void PrepareAddress(); - - // This will contact the secondary server and signal another candidate - // address for this port (which may be the same as the first address). - void PrepareSecondaryAddress(); - - talk_base::SocketAddress GetLocalAddress() const { - if (socket_) - return socket_->GetLocalAddress(); - return talk_base::SocketAddress(); - } - - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - -protected: - virtual int SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload); - - void OnReadPacket( - const char* data, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - -private: - talk_base::AsyncPacketSocket* socket_; - talk_base::SocketAddress server_addr_; - talk_base::SocketAddress server_addr2_; - StunRequestManager requests_; - int error_; - - friend class StunPortBindingRequest; - - // Sends STUN requests to the server. - void OnSendPacket(const void* data, size_t size, StunRequest* req); -}; - -} // namespace cricket - -#endif // __STUNPORT_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/stunrequest.cc b/third_party/libjingle/files/talk/p2p/base/stunrequest.cc deleted file mode 100644 index a4cbe7b..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunrequest.cc +++ /dev/null @@ -1,198 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif -#include "talk/base/logging.h" -#include "talk/base/helpers.h" -#include "talk/p2p/base/stunrequest.h" -#include <iostream> -#include <cassert> - -namespace cricket { - -const uint32 MSG_STUN_SEND = 1; - -const int MAX_SENDS = 9; -const int DELAY_UNIT = 100; // 100 milliseconds -const int DELAY_MAX_FACTOR = 16; - -StunRequestManager::StunRequestManager(talk_base::Thread* thread) - : thread_(thread) { - } - -StunRequestManager::~StunRequestManager() { - while (requests_.begin() != requests_.end()) { - StunRequest *request = requests_.begin()->second; - requests_.erase(requests_.begin()); - delete request; - } -} - -void StunRequestManager::Send(StunRequest* request) { - SendDelayed(request, 0); -} - -void StunRequestManager::SendDelayed(StunRequest* request, int delay) { - request->set_manager(this); - assert(requests_.find(request->id()) == requests_.end()); - requests_[request->id()] = request; - thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL); -} - -void StunRequestManager::Remove(StunRequest* request) { - assert(request->manager() == this); - RequestMap::iterator iter = requests_.find(request->id()); - if (iter != requests_.end()) { - assert(iter->second == request); - requests_.erase(iter); - thread_->Clear(request); - } -} - -void StunRequestManager::Clear() { - std::vector<StunRequest*> requests; - for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) - requests.push_back(i->second); - - for (uint32 i = 0; i < requests.size(); ++i) - Remove(requests[i]); -} - -bool StunRequestManager::CheckResponse(StunMessage* msg) { - RequestMap::iterator iter = requests_.find(msg->transaction_id()); - if (iter == requests_.end()) - return false; - StunRequest* request = iter->second; - if (msg->type() == GetStunResponseType(request->type())) { - request->OnResponse(msg); - } else if (msg->type() == GetStunErrorResponseType(request->type())) { - request->OnErrorResponse(msg); - } else { - LOG(LERROR) << "Received response with wrong type: " << msg->type() - << " (expecting " << GetStunResponseType(request->type()) << ")"; - return false; - } - - delete request; - return true; -} - -bool StunRequestManager::CheckResponse(const char* data, size_t size) { - // Check the appropriate bytes of the stream to see if they match the - // transaction ID of a response we are expecting. - - if (size < 20) - return false; - - std::string id; - id.append(data + 4, 16); - - RequestMap::iterator iter = requests_.find(id); - if (iter == requests_.end()) - return false; - - // Parse the STUN message and continue processing as usual. - - talk_base::ByteBuffer buf(data, size); - StunMessage msg; - if (!msg.Read(&buf)) - return false; - - return CheckResponse(&msg); -} - -StunRequest::StunRequest() - : manager_(0), id_(CreateRandomString(16)), msg_(0), count_(0), - timeout_(false), tstamp_(0) { -} - -StunRequest::StunRequest(StunMessage* request) - : manager_(0), id_(request->transaction_id()), msg_(request), - count_(0), timeout_(false) { -} - -StunRequest::~StunRequest() { - assert(manager_ != NULL); - if (manager_) { - manager_->Remove(this); - manager_->thread_->Clear(this); - } - delete msg_; -} - -StunMessageType StunRequest::type() { - assert(msg_); - return msg_->type(); -} - -void StunRequest::set_manager(StunRequestManager* manager) { - assert(!manager_); - manager_ = manager; -} - -void StunRequest::OnMessage(talk_base::Message* pmsg) { - assert(manager_); - assert(pmsg->message_id == MSG_STUN_SEND); - - if (!msg_) { - msg_ = new StunMessage(); - msg_->SetTransactionID(id_); - Prepare(msg_); - assert(msg_->transaction_id() == id_); - } - - if (timeout_) { - OnTimeout(); - delete this; - return; - } - - tstamp_ = talk_base::GetMillisecondCount(); - - talk_base::ByteBuffer buf; - msg_->Write(&buf); - manager_->SignalSendPacket(buf.Data(), buf.Length(), this); - - int delay = GetNextDelay(); - manager_->thread_->PostDelayed(delay, this, MSG_STUN_SEND, NULL); -} - -uint32 StunRequest::Elapsed() const { - return (talk_base::GetMillisecondCount() - tstamp_); -} - -int StunRequest::GetNextDelay() { - int delay = DELAY_UNIT * talk_base::_min(1 << count_, DELAY_MAX_FACTOR); - count_ += 1; - if (count_ == MAX_SENDS) - timeout_ = true; - return delay; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/stunrequest.h b/third_party/libjingle/files/talk/p2p/base/stunrequest.h deleted file mode 100644 index c3d79f9..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunrequest.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STUNREQUESTMANAGER_H__ -#define __STUNREQUESTMANAGER_H__ - -#include "talk/base/sigslot.h" -#include "talk/base/thread.h" -#include "talk/p2p/base/stun.h" -#include <map> -#include <string> - -namespace cricket { - -class StunRequest; - -// Manages a set of STUN requests, sending and resending until we receive a -// response or determine that the request has timed out. -class StunRequestManager { -public: - StunRequestManager(talk_base::Thread* thread); - ~StunRequestManager(); - - // Starts sending the given request (perhaps after a delay). - void Send(StunRequest* request); - void SendDelayed(StunRequest* request, int delay); - - // Removes a stun request that was added previously. This will happen - // automatically when a request succeeds, fails, or times out. - void Remove(StunRequest* request); - - // Removes all stun requests that were added previously. - void Clear(); - - // Determines whether the given message is a response to one of the - // outstanding requests, and if so, processes it appropriately. - bool CheckResponse(StunMessage* msg); - bool CheckResponse(const char* data, size_t size); - - // Raised when there are bytes to be sent. - sigslot::signal3<const void*, size_t, StunRequest*> SignalSendPacket; - -private: - typedef std::map<std::string, StunRequest*> RequestMap; - - talk_base::Thread* thread_; - RequestMap requests_; - - friend class StunRequest; -}; - -// Represents an individual request to be sent. The STUN message can either be -// constructed beforehand or built on demand. -class StunRequest : public talk_base::MessageHandler { -public: - StunRequest(); - StunRequest(StunMessage* request); - virtual ~StunRequest(); - - // The manager handling this request (if it has been scheduled for sending). - StunRequestManager* manager() { return manager_; } - - // Returns the transaction ID of this request. - const std::string& id() { return id_; } - - // Returns the STUN type of the request message. - StunMessageType type(); - - // Handles messages for sending and timeout. - void OnMessage(talk_base::Message* pmsg); - - // Time elapsed since last send (in ms) - uint32 Elapsed() const; - -protected: - int count_; - bool timeout_; - - // Fills in the actual request to be sent. Note that the transaction ID will - // already be set and cannot be changed. - virtual void Prepare(StunMessage* request) {} - - // Called when the message receives a response or times out. - virtual void OnResponse(StunMessage* response) {} - virtual void OnErrorResponse(StunMessage* response) {} - virtual void OnTimeout() {} - virtual int GetNextDelay(); - -private: - StunRequestManager* manager_; - std::string id_; - StunMessage* msg_; - uint32 tstamp_; - - void set_manager(StunRequestManager* manager); - - friend class StunRequestManager; -}; - -} // namespace cricket - -#endif // __STUNREQUESTMANAGER_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/stunserver.cc b/third_party/libjingle/files/talk/p2p/base/stunserver.cc deleted file mode 100644 index 5fc61ac..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunserver.cc +++ /dev/null @@ -1,160 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/base/bytebuffer.h" -#include "talk/p2p/base/stunserver.h" -#include <iostream> - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -namespace cricket { - -StunServer::StunServer(talk_base::AsyncUDPSocket* socket) : socket_(socket) { - socket_->SignalReadPacket.connect(this, &StunServer::OnPacket); -} - -StunServer::~StunServer() { - socket_->SignalReadPacket.disconnect(this); -} - -void StunServer::OnPacket( - const char* buf, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - - // TODO: If appropriate, look for the magic cookie before parsing. - - // Parse the STUN message. - talk_base::ByteBuffer bbuf(buf, size); - StunMessage msg; - if (!msg.Read(&bbuf)) { - SendErrorResponse(msg, remote_addr, 400, "Bad Request"); - return; - } - - // TODO: If this is UDP, then we shouldn't allow non-fully-parsed messages. - - // TODO: If unknown non-optiional (<= 0x7fff) attributes are found, send a - // 420 "Unknown Attribute" response. - - // TODO: Check that a message-integrity attribute was given (or send 401 - // "Unauthorized"). Check that a username attribute was given (or send - // 432 "Missing Username"). Look up the username and password. If it - // is missing or the HMAC is wrong, send 431 "Integrity Check Failure". - - // Send the message to the appropriate handler function. - switch (msg.type()) { - case STUN_BINDING_REQUEST: - OnBindingRequest(&msg, remote_addr); - return; - - case STUN_ALLOCATE_REQUEST: - OnAllocateRequest(&msg, remote_addr); - return; - - default: - SendErrorResponse(msg, remote_addr, 600, "Operation Not Supported"); - } -} - -void StunServer::OnBindingRequest( - StunMessage* msg, const talk_base::SocketAddress& remote_addr) { - StunMessage response; - response.SetType(STUN_BINDING_RESPONSE); - response.SetTransactionID(msg->transaction_id()); - - // Tell the user the address that we received their request from. - StunAddressAttribute* mapped_addr = - StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); - mapped_addr->SetFamily(1); - mapped_addr->SetPort(remote_addr.port()); - mapped_addr->SetIP(remote_addr.ip()); - response.AddAttribute(mapped_addr); - - // Tell the user the address that we are sending the response from. - talk_base::SocketAddress local_addr = socket_->GetLocalAddress(); - StunAddressAttribute* source_addr = - StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS); - source_addr->SetFamily(1); - source_addr->SetPort(local_addr.port()); - source_addr->SetIP(local_addr.ip()); - response.AddAttribute(source_addr); - - // TODO: Add username and message-integrity. - - // TODO: Add changed-address. (Keep information about three other servers.) - - SendResponse(response, remote_addr); -} - -void StunServer::OnAllocateRequest( - StunMessage* msg, const talk_base::SocketAddress& addr) { - SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); -} - -void StunServer::OnSharedSecretRequest( - StunMessage* msg, const talk_base::SocketAddress& addr) { - SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); -} - -void StunServer::OnSendRequest(StunMessage* msg, const talk_base::SocketAddress& addr) { - SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); -} - -void StunServer::SendErrorResponse( - const StunMessage& msg, const talk_base::SocketAddress& addr, int error_code, - const char* error_desc) { - - StunMessage err_msg; - err_msg.SetType(GetStunErrorResponseType(msg.type())); - err_msg.SetTransactionID(msg.transaction_id()); - - StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode(); - err_code->SetErrorClass(error_code / 100); - err_code->SetNumber(error_code % 100); - err_code->SetReason(error_desc); - err_msg.AddAttribute(err_code); - - SendResponse(err_msg, addr); -} - -void StunServer::SendResponse( - const StunMessage& msg, const talk_base::SocketAddress& addr) { - - talk_base::ByteBuffer buf; - msg.Write(&buf); - - // TODO: Allow response addr attribute if sent from another stun server. - - if (socket_->SendTo(buf.Data(), buf.Length(), addr) < 0) - std::cerr << "sendto: " << std::strerror(errno) << std::endl; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/stunserver.h b/third_party/libjingle/files/talk/p2p/base/stunserver.h deleted file mode 100644 index 0e57a18..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunserver.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STUNSERVER_H__ -#define __STUNSERVER_H__ - -#include "talk/base/asyncudpsocket.h" -#include "talk/p2p/base/stun.h" - -namespace cricket { - -const int STUN_SERVER_PORT = 3478; - -class StunServer : public sigslot::has_slots<> { -public: - // Creates a STUN server, which will listen on the given socket. - StunServer(talk_base::AsyncUDPSocket* socket); - - // Removes the STUN server from the socket, but does not delete the socket. - ~StunServer(); - -protected: - - // Slot for AsyncSocket.PacketRead: - void OnPacket( - const char* buf, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - - // Handlers for the different types of STUN/TURN requests: - void OnBindingRequest(StunMessage* msg, const talk_base::SocketAddress& addr); - void OnAllocateRequest(StunMessage* msg, const talk_base::SocketAddress& addr); - void OnSharedSecretRequest(StunMessage* msg, const talk_base::SocketAddress& addr); - void OnSendRequest(StunMessage* msg, const talk_base::SocketAddress& addr); - - // Sends an error response to the given message back to the user. - void SendErrorResponse( - const StunMessage& msg, const talk_base::SocketAddress& addr, int error_code, - const char* error_desc); - - // Sends the given message to the appropriate destination. - void SendResponse(const StunMessage& msg, const talk_base::SocketAddress& addr); - -private: - talk_base::AsyncUDPSocket* socket_; -}; - -} // namespace cricket - -#endif // __STUNSERVER_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/stunserver_main.cc b/third_party/libjingle/files/talk/p2p/base/stunserver_main.cc deleted file mode 100644 index 8aa200e..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunserver_main.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/base/host.h" -#include "talk/base/thread.h" -#include "talk/p2p/base/stunserver.h" -#include <iostream> - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -using namespace cricket; - -int main(int argc, char* argv[]) { - if (argc != 1) { - std::cerr << "usage: stunserver" << std::endl; - return 1; - } - - talk_base::SocketAddress server_addr(talk_base::LocalHost().networks()[1]->ip(), 7000); - - talk_base::Thread *pthMain = talk_base::Thread::Current(); - - talk_base::AsyncUDPSocket* server_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); - if (server_socket->Bind(server_addr) < 0) { - std::cerr << "bind: " << std::strerror(errno) << std::endl; - return 1; - } - - StunServer* server = new StunServer(server_socket); - - std::cout << "Listening at " << server_addr.ToString() << std::endl; - - pthMain->Run(); - - delete server; - delete server_socket; - return 0; -} diff --git a/third_party/libjingle/files/talk/p2p/base/stunserver_unittest.cc b/third_party/libjingle/files/talk/p2p/base/stunserver_unittest.cc deleted file mode 100644 index b56da4e..0000000 --- a/third_party/libjingle/files/talk/p2p/base/stunserver_unittest.cc +++ /dev/null @@ -1,107 +0,0 @@ -#include "talk/base/testclient.h" -#include "talk/base/thread.h" -#include "talk/base/physicalsocketserver.h" -#include "talk/base/host.h" -#include "talk/p2p/base/stunserver.h" -#include <cstring> -#include <iostream> -#include <cassert> - -using namespace cricket; - -StunMessage* GetResponse(talk_base::TestClient* client) { - talk_base::TestClient::Packet* packet = client->NextPacket(); - assert(packet); - talk_base::ByteBuffer buf(packet->buf, packet->size); - StunMessage* msg = new StunMessage(); - assert(msg->Read(&buf)); - delete packet; - return msg; -} - -int main(int argc, char* argv[]) { - assert(talk_base::LocalHost().networks().size() >= 2); - talk_base::SocketAddress server_addr(talk_base::LocalHost().networks()[1]->ip(), 7000); - talk_base::SocketAddress client_addr(talk_base::LocalHost().networks()[1]->ip(), 6000); - - talk_base::Thread th; - - talk_base::AsyncUDPSocket* server_socket = 0; - StunServer* server = 0; - if (argc >= 2) { - server_addr.SetIP(argv[1]); - client_addr.SetIP(0); - if (argc == 3) - server_addr.SetPort(atoi(argv[2])); - std::cout << "Using server at " << server_addr.ToString() << std::endl; - } else { - server_socket = talk_base::CreateAsyncUDPSocket(th.socketserver()); - assert(server_socket->Bind(server_addr) >= 0); - server = new StunServer(server_socket); - } - - talk_base::AsyncUDPSocket* client_socket = talk_base::CreateAsyncUDPSocket(th.socketserver()); - assert(client_socket->Bind(client_addr) >= 0); - talk_base::TestClient* client = new talk_base::TestClient(client_socket, &th); - - th.Start(); - - const char* bad = "this is a completely nonsensical message whose only " - "purpose is to make the parser go 'ack'. it doesn't " - "look anything like a normal stun message"; - - client->SendTo(bad, std::strlen(bad), server_addr); - StunMessage* msg = GetResponse(client); - assert(msg->type() == STUN_BINDING_ERROR_RESPONSE); - - const StunErrorCodeAttribute* err = msg->GetErrorCode(); - assert(err); - assert(err->error_class() == 4); - assert(err->number() == 0); - assert(err->reason() == std::string("Bad Request")); - - delete msg; - - std::string transaction_id = "0123456789abcdef"; - - StunMessage req; - req.SetType(STUN_BINDING_REQUEST); - req.SetTransactionID(transaction_id); - - talk_base::ByteBuffer buf; - req.Write(&buf); - - client->SendTo(buf.Data(), buf.Length(), server_addr); - StunMessage* msg2 = GetResponse(client); - assert(msg2->type() == STUN_BINDING_RESPONSE); - assert(msg2->transaction_id() == transaction_id); - - const StunAddressAttribute* mapped_addr = - msg2->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - assert(mapped_addr); - assert(mapped_addr->family() == 1); - assert(mapped_addr->port() == client_addr.port()); - if (mapped_addr->ip() != client_addr.ip()) { - printf("Warning: mapped IP (%s) != local IP (%s)\n", - talk_base::SocketAddress::IPToString(mapped_addr->ip()).c_str(), - client_addr.IPAsString().c_str()); - } - - const StunAddressAttribute* source_addr = - msg2->GetAddress(STUN_ATTR_SOURCE_ADDRESS); - assert(source_addr); - assert(source_addr->family() == 1); - assert(source_addr->port() == server_addr.port()); - assert(source_addr->ip() == server_addr.ip()); - - delete msg2; - - th.Stop(); - - delete server; - delete server_socket; - delete client; - - std::cout << "PASS" << std::endl; - return 0; -} diff --git a/third_party/libjingle/files/talk/p2p/base/tcpport.cc b/third_party/libjingle/files/talk/p2p/base/tcpport.cc deleted file mode 100644 index 57e2a4f..0000000 --- a/third_party/libjingle/files/talk/p2p/base/tcpport.cc +++ /dev/null @@ -1,271 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -#include <cassert> -#include <iostream> - -#include "talk/base/common.h" -#include "talk/base/logging.h" -#ifdef WIN32 -#include "talk/base/winfirewall.h" -#endif // WIN32 -#include "talk/p2p/base/tcpport.h" - -namespace cricket { - -#ifdef WIN32 -static talk_base::WinFirewall win_firewall; -#endif // WIN32 - -TCPPort::TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, - const talk_base::SocketAddress& address) - : Port(thread, LOCAL_PORT_TYPE, factory, network), address_(address), - incoming_only_(address_.port() != 0), error_(0) { - socket_ = thread->socketserver()->CreateAsyncSocket(SOCK_STREAM); - socket_->SignalReadEvent.connect(this, &TCPPort::OnAcceptEvent); - if (socket_->Bind(address_) < 0) { - LOG_F(LS_ERROR) << "Bind error: " << socket_->GetError(); - } -} - -TCPPort::~TCPPort() { - delete socket_; -} - -Connection* TCPPort::CreateConnection(const Candidate& address, - CandidateOrigin origin) { - // We only support TCP protocols - if ((address.protocol() != "tcp") && (address.protocol() != "ssltcp")) - return 0; - - // We can't accept TCP connections incoming on other ports - if (origin == ORIGIN_OTHER_PORT) - return 0; - - // Check if we are allowed to make outgoing TCP connections - if (incoming_only_ && (origin == ORIGIN_MESSAGE)) - return 0; - - // We don't know how to act as an ssl server yet - if ((address.protocol() == "ssltcp") && (origin == ORIGIN_THIS_PORT)) - return 0; - - TCPConnection* conn = 0; - if (talk_base::AsyncTCPSocket * socket - = GetIncoming(address.address(), true)) { - socket->SignalReadPacket.disconnect(this); - conn = new TCPConnection(this, address, socket); - } else { - conn = new TCPConnection(this, address); - } - AddConnection(conn); - return conn; -} - -void TCPPort::PrepareAddress() { - assert(socket_); - - bool allow_listen = true; -#ifdef WIN32 - if (win_firewall.Initialize()) { - char module_path[MAX_PATH + 1] = { 0 }; - ::GetModuleFileNameA(NULL, module_path, MAX_PATH); - if (win_firewall.Enabled() && !win_firewall.Authorized(module_path)) { - allow_listen = false; - } - } -#endif // WIN32 - if (!allow_listen) { - LOG_F(LS_VERBOSE) << "Not listening due to firewall restrictions"; - } else if (socket_->Listen(5) < 0) { - LOG_F(LS_ERROR) << "Listen error: " << socket_->GetError(); - } - // Note: We still add the address, since otherwise the remote side won't - // recognize our incoming TCP connections. - AddAddress(socket_->GetLocalAddress(), "tcp", true); -} - -int TCPPort::SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload) { - talk_base::AsyncTCPSocket * socket = 0; - - if (TCPConnection * conn = static_cast<TCPConnection*>(GetConnection(addr))) { - socket = conn->socket(); - } else { - socket = GetIncoming(addr); - } - if (!socket) { - LOG_F(LS_ERROR) << "Unknown destination: " << addr.ToString(); - return -1; // TODO: Set error_ - } - - //LOG_F(INFO) << "(" << size << ", " << addr.ToString() << ")"; - - int sent = socket->Send(data, size); - if (sent < 0) { - error_ = socket->GetError(); - LOG_F(LS_ERROR) << "(" << size << ", " << addr.ToString() - << ") Send error: " << error_; - } - return sent; -} - -int TCPPort::SetOption(talk_base::Socket::Option opt, int value) { - return socket_->SetOption(opt, value); -} - -int TCPPort::GetError() { - assert(socket_); - return error_; -} - -void TCPPort::OnAcceptEvent(talk_base::AsyncSocket* socket) { - assert(socket == socket_); - - Incoming incoming; - talk_base::AsyncSocket * newsocket - = static_cast<talk_base::AsyncSocket *>(socket->Accept(&incoming.addr)); - if (!newsocket) { - // TODO: Do something better like forwarding the error to the user. - LOG_F(LS_ERROR) << "Accept error: " << socket_->GetError(); - return; - } - incoming.socket = new talk_base::AsyncTCPSocket(newsocket); - incoming.socket->SignalReadPacket.connect(this, &TCPPort::OnReadPacket); - - LOG_F(LS_VERBOSE) << "(" << incoming.addr.ToString() << ")"; - incoming_.push_back(incoming); - - // Prime a read event in case data is waiting - newsocket->SignalReadEvent(newsocket); -} - -talk_base::AsyncTCPSocket * TCPPort::GetIncoming( - const talk_base::SocketAddress& addr, bool remove) { - talk_base::AsyncTCPSocket * socket = 0; - for (std::list<Incoming>::iterator it = incoming_.begin(); - it != incoming_.end(); ++it) { - if (it->addr == addr) { - socket = it->socket; - if (remove) - incoming_.erase(it); - break; - } - } - return socket; -} - -void TCPPort::OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - Port::OnReadPacket(data, size, remote_addr); -} - -TCPConnection::TCPConnection(TCPPort* port, const Candidate& candidate, - talk_base::AsyncTCPSocket* socket) - : Connection(port, 0, candidate), socket_(socket), error_(0) { - bool outgoing = (socket_ == 0); - if (outgoing) { - socket_ = static_cast<talk_base::AsyncTCPSocket *>(port->CreatePacketSocket( - (candidate.protocol() == "ssltcp") ? PROTO_SSLTCP : PROTO_TCP)); - } else { - // Incoming connections should match the network address - ASSERT(socket_->GetLocalAddress().EqualIPs(port->address_)); - } - socket_->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket); - socket_->SignalClose.connect(this, &TCPConnection::OnClose); - if (outgoing) { - set_connected(false); - talk_base::SocketAddress local_address(port->address_.ip(), 0); - socket_->SignalConnect.connect(this, &TCPConnection::OnConnect); - socket_->Bind(local_address); - socket_->Connect(candidate.address()); - LOG_F(LS_VERBOSE) << "Connecting from " << local_address.ToString() - << " to " << candidate.address().ToString(); - } -} - -TCPConnection::~TCPConnection() { - delete socket_; -} - -int TCPConnection::Send(const void* data, size_t size) { - if (write_state() != STATE_WRITABLE) { - // TODO: Should STATE_WRITE_TIMEOUT return a non-blocking error? - error_ = EWOULDBLOCK; - return SOCKET_ERROR; - } - int sent = socket_->Send(data, size); - if (sent < 0) { - error_ = socket_->GetError(); - } else { - sent_total_bytes_ += sent; - } - return sent; -} - -int TCPConnection::GetError() { - return error_; -} - -TCPPort* TCPConnection::tcpport() { - return static_cast<TCPPort*>(port_); -} - -void TCPConnection::OnConnect(talk_base::AsyncTCPSocket* socket) { - assert(socket == socket_); - LOG_F(LS_VERBOSE) << "(" << socket->GetRemoteAddress().ToString() << ")"; - set_connected(true); -} - -void TCPConnection::OnClose(talk_base::AsyncTCPSocket* socket, int error) { - assert(socket == socket_); - LOG_F(LS_VERBOSE) << "(" << error << ")"; - set_connected(false); - set_write_state(STATE_WRITE_TIMEOUT); -} - -void TCPConnection::OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - assert(socket == socket_); - //LOG_F(LS_INFO) << "(" << size << ", " << remote_addr.ToString() << ")"; - Connection::OnReadPacket(data, size); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/tcpport.h b/third_party/libjingle/files/talk/p2p/base/tcpport.h deleted file mode 100644 index 24555ae..0000000 --- a/third_party/libjingle/files/talk/p2p/base/tcpport.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __TCPPORT_H__ -#define __TCPPORT_H__ - -#include <list> -#include "talk/base/asynctcpsocket.h" -#include "talk/p2p/base/port.h" - -namespace cricket { - -class TCPConnection; - -extern const std::string LOCAL_PORT_TYPE; // type of TCP ports - -// Communicates using a local TCP port. -// -// This class is designed to allow subclasses to take advantage of the -// connection management provided by this class. A subclass should take of all -// packet sending and preparation, but when a packet is received, it should -// call this TCPPort::OnReadPacket (3 arg) to dispatch to a connection. -class TCPPort : public Port { -public: - TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, const talk_base::SocketAddress& address); - virtual ~TCPPort(); - - virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin); - - virtual void PrepareAddress(); - - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - -protected: - // Handles sending using the local TCP socket. - virtual int SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload); - - // Creates TCPConnection for incoming sockets - void OnAcceptEvent(talk_base::AsyncSocket* socket); - - talk_base::AsyncSocket* socket() { return socket_; } - -private: - // Note: use this until Network ips are stable, then use network->ip - talk_base::SocketAddress address_; - bool incoming_only_; - talk_base::AsyncSocket* socket_; - int error_; - - struct Incoming { - talk_base::SocketAddress addr; - talk_base::AsyncTCPSocket * socket; - }; - std::list<Incoming> incoming_; - - talk_base::AsyncTCPSocket * GetIncoming(const talk_base::SocketAddress& addr, - bool remove = false); - - // Receives packet signal from the local TCP Socket. - void OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - - friend class TCPConnection; -}; - -class TCPConnection : public Connection { -public: - // Connection is outgoing unless socket is specified - TCPConnection(TCPPort* port, const Candidate& candidate, - talk_base::AsyncTCPSocket* socket = 0); - virtual ~TCPConnection(); - - virtual int Send(const void* data, size_t size); - virtual int GetError(); - - talk_base::AsyncTCPSocket * socket() { return socket_; } - -private: - TCPPort* tcpport(); - talk_base::AsyncTCPSocket* socket_; - int error_; - - void OnConnect(talk_base::AsyncTCPSocket* socket); - void OnClose(talk_base::AsyncTCPSocket* socket, int error); - void OnReadPacket(const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); - - friend class TCPPort; -}; - -} // namespace cricket - -#endif // __TCPPORT_H__ diff --git a/third_party/libjingle/files/talk/p2p/base/transport.cc b/third_party/libjingle/files/talk/p2p/base/transport.cc deleted file mode 100644 index 0eac128..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transport.cc +++ /dev/null @@ -1,441 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/base/common.h" -#include "talk/p2p/base/transport.h" -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/base/transportchannelimpl.h" -#include "talk/p2p/base/constants.h" -#include "talk/xmllite/xmlelement.h" -#include "talk/xmpp/xmppconstants.h" - -namespace { - -struct ChannelParams { - std::string name; - std::string session_type; - cricket::TransportChannelImpl* channel; - buzz::XmlElement* elem; - - ChannelParams() : channel(NULL), elem(NULL) {} -}; -typedef talk_base::TypedMessageData<ChannelParams*> ChannelMessage; - -const int MSG_CREATECHANNEL = 1; -const int MSG_DESTROYCHANNEL = 2; -const int MSG_DESTROYALLCHANNELS = 3; -const int MSG_CONNECTCHANNELS = 4; -const int MSG_RESETCHANNELS = 5; -const int MSG_ONSIGNALINGREADY = 6; -const int MSG_FORWARDCHANNELMESSAGE = 7; -const int MSG_READSTATE = 8; -const int MSG_WRITESTATE = 9; -const int MSG_REQUESTSIGNALING = 10; -const int MSG_ONCHANNELMESSAGE = 11; -const int MSG_CONNECTING = 12; - -} // namespace - -namespace cricket { - -Transport::Transport(SessionManager* session_manager, const std::string& name) - : session_manager_(session_manager), name_(name), destroyed_(false), - readable_(false), writable_(false), connect_requested_(false), - allow_local_ips_(false) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); -} - -Transport::~Transport() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(destroyed_); -} - -TransportChannelImpl* Transport::CreateChannel(const std::string& name, const std::string &session_type) { - ChannelParams params; - params.name = name; - params.session_type = session_type; - ChannelMessage msg(¶ms); - session_manager_->worker_thread()->Send(this, MSG_CREATECHANNEL, &msg); - return msg.data()->channel; -} - -TransportChannelImpl* Transport::CreateChannel_w(const std::string& name, const std::string &session_type) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - - TransportChannelImpl* impl = CreateTransportChannel(name, session_type); - impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState); - impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); - impl->SignalRequestSignaling.connect( - this, &Transport::OnChannelRequestSignaling); - impl->SignalChannelMessage.connect(this, &Transport::OnChannelMessage); - - talk_base::CritScope cs(&crit_); - ASSERT(channels_.find(name) == channels_.end()); - channels_[name] = impl; - destroyed_ = false; - if (connect_requested_) { - impl->Connect(); - if (channels_.size() == 1) { - // If this is the first channel, then indicate that we have started - // connecting. - session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL); - } - } - return impl; -} - -TransportChannelImpl* Transport::GetChannel(const std::string& name) { - talk_base::CritScope cs(&crit_); - ChannelMap::iterator iter = channels_.find(name); - return (iter != channels_.end()) ? iter->second : NULL; -} - -bool Transport::HasChannels() { - talk_base::CritScope cs(&crit_); - return !channels_.empty(); -} - -void Transport::DestroyChannel(const std::string& name) { - ChannelParams params; - params.name = name; - ChannelMessage msg(¶ms); - session_manager_->worker_thread()->Send(this, MSG_DESTROYCHANNEL, &msg); -} - -void Transport::DestroyChannel_w(const std::string& name) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - TransportChannelImpl* impl = NULL; - { - talk_base::CritScope cs(&crit_); - ChannelMap::iterator iter = channels_.find(name); - ASSERT(iter != channels_.end()); - impl = iter->second; - channels_.erase(iter); - } - - if (connect_requested_ && channels_.empty()) { - // We're not longer attempting to connect. - session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL); - } - - if (impl) - DestroyTransportChannel(impl); -} - -void Transport::ConnectChannels() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - session_manager_->worker_thread()->Post(this, MSG_CONNECTCHANNELS, NULL); -} - -void Transport::ConnectChannels_w() { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - if (connect_requested_) - return; - connect_requested_ = true; - session_manager_->signaling_thread()->Post(this, MSG_ONCHANNELMESSAGE, NULL); - CallChannels_w(&TransportChannelImpl::Connect); - if (!channels_.empty()) { - session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL); - } -} - -void Transport::OnConnecting_s() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SignalConnecting(this); -} - -void Transport::DestroyAllChannels() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - session_manager_->worker_thread()->Send(this, MSG_DESTROYALLCHANNELS, NULL); - destroyed_ = true; -} - -void Transport::DestroyAllChannels_w() { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - std::vector<TransportChannelImpl*> impls; - { - talk_base::CritScope cs(&crit_); - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - impls.push_back(iter->second); - } - channels_.clear(); - } - - for (size_t i = 0; i < impls.size(); ++i) - DestroyTransportChannel(impls[i]); -} - -void Transport::ResetChannels() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - session_manager_->worker_thread()->Post(this, MSG_RESETCHANNELS, NULL); -} - -void Transport::ResetChannels_w() { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - - // We are no longer attempting to connect - connect_requested_ = false; - - // Clear out the old messages, they aren't relevant - talk_base::CritScope cs(&crit_); - for (size_t i=0; i<messages_.size(); ++i) { - delete messages_[i]; - } - messages_.clear(); - - // Reset all of the channels - CallChannels_w(&TransportChannelImpl::Reset); -} - -void Transport::OnSignalingReady() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - session_manager_->worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL); - - // Notify the subclass. - OnTransportSignalingReady(); -} - -void Transport::CallChannels_w(TransportChannelFunc func) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - talk_base::CritScope cs(&crit_); - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - ((iter->second)->*func)(); - } -} - -void Transport::ForwardChannelMessage(const std::string& name, - buzz::XmlElement* elem) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(HasChannel(name)); - ChannelParams* params = new ChannelParams(); - params->name = name; - params->elem = elem; - ChannelMessage* msg = new ChannelMessage(params); - session_manager_->worker_thread()->Post(this, MSG_FORWARDCHANNELMESSAGE, msg); -} - -void Transport::ForwardChannelMessage_w(const std::string& name, - buzz::XmlElement* elem) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - ChannelMap::iterator iter = channels_.find(name); - // It's ok for a channel to go away while this message is in transit. - if (iter != channels_.end()) { - iter->second->OnChannelMessage(elem); - } - delete elem; -} - -void Transport::OnChannelReadableState(TransportChannel* channel) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - session_manager_->signaling_thread()->Post(this, MSG_READSTATE, NULL); -} - -void Transport::OnChannelReadableState_s() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - bool readable = GetTransportState_s(true); - if (readable_ != readable) { - readable_ = readable; - SignalReadableState(this); - } -} - -void Transport::OnChannelWritableState(TransportChannel* channel) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - session_manager_->signaling_thread()->Post(this, MSG_WRITESTATE, NULL); -} - -void Transport::OnChannelWritableState_s() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - bool writable = GetTransportState_s(false); - if (writable_ != writable) { - writable_ = writable; - SignalWritableState(this); - } -} - -bool Transport::GetTransportState_s(bool read) { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - bool result = false; - talk_base::CritScope cs(&crit_); - for (ChannelMap::iterator iter = channels_.begin(); - iter != channels_.end(); - ++iter) { - bool b = (read ? iter->second->readable() : iter->second->writable()); - result = result || b; - } - return result; -} - -void Transport::OnChannelRequestSignaling() { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - session_manager_->signaling_thread()->Post(this, MSG_REQUESTSIGNALING, NULL); -} - -void Transport::OnChannelRequestSignaling_s() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - SignalRequestSignaling(this); -} - -void Transport::OnChannelMessage(TransportChannelImpl* impl, - buzz::XmlElement* elem) { - ASSERT(session_manager_->worker_thread()->IsCurrent()); - talk_base::CritScope cs(&crit_); - messages_.push_back(elem); - - // We hold any messages until the client lets us connect. - if (connect_requested_) { - session_manager_->signaling_thread()->Post( - this, MSG_ONCHANNELMESSAGE, NULL); - } -} - -void Transport::OnChannelMessage_s() { - ASSERT(session_manager_->signaling_thread()->IsCurrent()); - ASSERT(connect_requested_); - - std::vector<buzz::XmlElement*> msgs; - { - talk_base::CritScope cs(&crit_); - msgs.swap(messages_); - } - - if (!msgs.empty()) - OnTransportChannelMessages(msgs); -} - -void Transport::OnTransportChannelMessages( - const std::vector<buzz::XmlElement*>& msgs) { - std::vector<buzz::XmlElement*> elems; - for (size_t i = 0; i < msgs.size(); ++i) { - buzz::XmlElement* elem = - new buzz::XmlElement(buzz::QName(name(), "transport")); - elem->AddElement(msgs[i]); - elems.push_back(elem); - } - SignalTransportMessage(this, elems); -} - -void Transport::OnMessage(talk_base::Message* msg) { - switch (msg->message_id) { - case MSG_CREATECHANNEL: - { - ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data(); - params->channel = CreateChannel_w(params->name, params->session_type); - } - break; - case MSG_DESTROYCHANNEL: - { - ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data(); - DestroyChannel_w(params->name); - } - break; - case MSG_CONNECTCHANNELS: - ConnectChannels_w(); - break; - case MSG_RESETCHANNELS: - ResetChannels_w(); - break; - case MSG_DESTROYALLCHANNELS: - DestroyAllChannels_w(); - break; - case MSG_ONSIGNALINGREADY: - CallChannels_w(&TransportChannelImpl::OnSignalingReady); - break; - case MSG_FORWARDCHANNELMESSAGE: - { - ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data(); - ForwardChannelMessage_w(params->name, params->elem); - delete params; - } - break; - case MSG_CONNECTING: - OnConnecting_s(); - break; - case MSG_READSTATE: - OnChannelReadableState_s(); - break; - case MSG_WRITESTATE: - OnChannelWritableState_s(); - break; - case MSG_REQUESTSIGNALING: - OnChannelRequestSignaling_s(); - break; - case MSG_ONCHANNELMESSAGE: - OnChannelMessage_s(); - break; - } -} - -bool Transport::BadRequest(const buzz::XmlElement* stanza, - const std::string& text, - const buzz::XmlElement* extra_info) { - SignalTransportError(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify", - text, extra_info); - return false; -} - -bool Transport::ParseAddress(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - talk_base::SocketAddress* address) { - ASSERT(elem->HasAttr(QN_ADDRESS)); - ASSERT(elem->HasAttr(QN_PORT)); - - // Record the parts of the address. - address->SetIP(elem->Attr(QN_ADDRESS)); - std::istringstream ist(elem->Attr(QN_PORT)); - int port; - ist >> port; - address->SetPort(port); - - // No address zero. - if (address->IsAny()) - return BadRequest(stanza, "candidate has address of zero", NULL); - - // Always disallow addresses that refer to the local host. - if (address->IsLocalIP() && !allow_local_ips_) - return BadRequest(stanza, "candidate has local IP address", NULL); - - // Disallow all ports below 1024, except for 80 and 443 on public addresses. - if (port < 1024) { - if ((port != 80) && (port != 443)) - return BadRequest(stanza, - "candidate has port below 1024, but not 80 or 443", - NULL); - if (address->IsPrivateIP()) { - return BadRequest(stanza, "candidate has port of 80 or 443 with private " - "IP address", NULL); - } - } - - return true; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/transport.h b/third_party/libjingle/files/talk/p2p/base/transport.h deleted file mode 100644 index 826fd26..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transport.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// A Transport manages a set of named channels of the same type. -// -// Subclasses choose the appropriate class to instantiate for each channel; -// however, this base class keeps track of the channels by name, watches their -// state changes (in order to update the manager's state), and forwards -// requests to begin connecting or to reset to each of the channels. -// -// On Threading: Transport performs work on both the signaling and worker -// threads. For subclasses, the rule is that all signaling related calls will -// be made on the signaling thread and all channel related calls (including -// signaling for a channel) will be made on the worker thread. When -// information needs to be sent between the two threads, this class should do -// the work (e.g., ForwardChannelMessage). -// -// Note: Subclasses must call DestroyChannels() in their own constructors. -// It is not possible to do so here because the subclass constructor will -// already have run. - -#ifndef _CRICKET_P2P_BASE_TRANSPORT_H_ -#define _CRICKET_P2P_BASE_TRANSPORT_H_ - -#include <string> -#include <map> -#include <vector> -#include "talk/base/criticalsection.h" -#include "talk/base/messagequeue.h" -#include "talk/base/sigslot.h" - -namespace buzz { -class QName; -class XmlElement; -} - -namespace cricket { - -class SessionManager; -class Session; -class TransportChannel; -class TransportChannelImpl; - -class Transport : public talk_base::MessageHandler, public sigslot::has_slots<> { - public: - Transport(SessionManager* session_manager, const std::string& name); - virtual ~Transport(); - - // Returns a pointer to the singleton session manager. - SessionManager* session_manager() const { return session_manager_; } - - // Returns the name of this transport. - const std::string& name() const { return name_; } - - // Returns the readable and states of this manager. These bits are the ORs - // of the corresponding bits on the managed channels. Each time one of these - // states changes, a signal is raised. - bool readable() const { return readable_; } - bool writable() const { return writable_; } - sigslot::signal1<Transport*> SignalReadableState; - sigslot::signal1<Transport*> SignalWritableState; - - // Returns whether the client has requested the channels to connect. - bool connect_requested() const { return connect_requested_; } - - // Create, destroy, and lookup the channels of this type by their names. - TransportChannelImpl* CreateChannel(const std::string& name, const std::string &session_type); - // Note: GetChannel may lead to race conditions, since the mutex is not held - // after the pointer is returned. - TransportChannelImpl* GetChannel(const std::string& name); - // Note: HasChannel does not lead to race conditions, unlike GetChannel. - bool HasChannel(const std::string& name) { return (NULL != GetChannel(name)); } - bool HasChannels(); - void DestroyChannel(const std::string& name); - - // Tells all current and future channels to start connecting. When the first - // channel begins connecting, the following signal is raised. - void ConnectChannels(); - sigslot::signal1<Transport*> SignalConnecting; - - // Resets all of the channels back to their initial state. They are no - // longer connecting. - void ResetChannels(); - - // Destroys every channel created so far. - void DestroyAllChannels(); - - // The session handshake includes negotiation of both the application and the - // transport. The initiating transport creates an "offer" describing what - // options it supports and the responding transport creates an "answer" - // describing which options it has accepted. If OnTransport* returns false, - // that indicates that no acceptable options given and this transport cannot - // be negotiated. - // - // The transport negotiation operates as follows. When the initiating client - // creates the session, but before they send the initiate, we create the - // supported transports. The client may override these, but otherwise they - // get a default set. When the initiate is sent, we ask each transport to - // produce an offer. When the receiving client gets the initiate, they will - // iterate through the transport offers in order of their own preference. - // For each one, they create the transport (if they know what it is) and - // call OnTransportOffer. If this returns true, then we're good; otherwise, - // we continue iterating. If no transport works, then we reject the session. - // Otherwise, we have a single transport, and we send back a transport-accept - // message that contains the answer. When this arrives at the initiating - // client, we destroy all transports but the one in the answer and then pass - // the answer to it. If this transport cannot be found or it cannot accept - // the answer, then we reject the session. Otherwise, we're in good shape. - virtual buzz::XmlElement* CreateTransportOffer() = 0; - virtual buzz::XmlElement* CreateTransportAnswer() = 0; - virtual bool OnTransportOffer(const buzz::XmlElement* elem) = 0; - virtual bool OnTransportAnswer(const buzz::XmlElement* elem) = 0; - - // Before any stanza is sent, the manager will request signaling. Once - // signaling is available, the client should call OnSignalingReady. Once - // this occurs, the transport (or its channels) can send any waiting stanzas. - // OnSignalingReady invokes OnTransportSignalingReady and then forwards this - // signal to each channel. - sigslot::signal1<Transport*> SignalRequestSignaling; - void OnSignalingReady(); - - // Handles sending and receiving of stanzas related to negotiating the - // connections of the channels. Different transports may have very different - // signaling, so the XML is handled by the subclass. The msg variable holds - // the element whose name matches this transport, while stanza holds the - // entire stanza. The latter is needed when sending an error response. - // SignalTransportMessage is given the elements that will become the children - // of the transport-info message. Each element must have a name that matches - // the transport's name. - virtual bool OnTransportMessage(const buzz::XmlElement* msg, - const buzz::XmlElement* stanza) = 0; - sigslot::signal2<Transport*, const std::vector<buzz::XmlElement*>&> - SignalTransportMessage; - - // A transport message has generated an transport-specific error. The - // stanza that caused the error is available in session_msg. If false is - // returned, the error is considered unrecoverable, and the session is - // terminated. - virtual bool OnTransportError(const buzz::XmlElement* session_msg, - const buzz::XmlElement* error) = 0; - sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&, - const std::string&, const std::string&, - const buzz::XmlElement*> - SignalTransportError; - - sigslot::signal2<Transport*, const std::string&> SignalChannelGone; - - // (For testing purposes only.) This indicates whether we will allow local - // IPs (e.g. 127.*) to be used as addresses for P2P. - bool allow_local_ips() const { return allow_local_ips_; } - void set_allow_local_ips(bool value) { allow_local_ips_ = value; } - - protected: - // Helper function to bad-request error for a stanza passed to - // OnTransportMessage. Returns false. - bool BadRequest(const buzz::XmlElement* stanza, const std::string& text, - const buzz::XmlElement* extra_info); - - // Helper function to parse an element describing an address. This retrieves - // the IP and port from the given element (using QN_ADDRESS and QN_PORT) and - // verifies that they look like plausible values. - bool ParseAddress(const buzz::XmlElement* stanza, - const buzz::XmlElement* elem, - talk_base::SocketAddress* address); - - // These are called by Create/DestroyChannel above in order to create or - // destroy the appropriate type of channel. - virtual TransportChannelImpl* CreateTransportChannel( - const std::string& name, const std::string &session_type) = 0; - virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0; - - // Informs the subclass that we received the signaling ready message. - virtual void OnTransportSignalingReady() {} - - // Forwards the given XML element to the channel on the worker thread. This - // occurs asynchronously, so we take ownership of the element. Furthermore, - // the channel will not be able to return an error if the XML is invalid, so - // the transport should have checked its validity already. - void ForwardChannelMessage(const std::string& name, - buzz::XmlElement* elem); - - // Handles a set of messages sent by the channels. The default - // implementation simply forwards each as its own transport message by - // wrapping it in an element identifying this transport and then invoking - // SignalTransportMessage. Smarter transports may be able to place multiple - // channel messages within one transport message. - // - // Note: The implementor of this method is responsible for deleting the XML - // elements passed in, unless they are sent to SignalTransportMessage, where - // the receiver will delete them. - virtual void OnTransportChannelMessages( - const std::vector<buzz::XmlElement*>& msgs); - - private: - typedef std::map<std::string, TransportChannelImpl*> ChannelMap; - typedef std::vector<buzz::XmlElement*> XmlElementList; - - SessionManager* session_manager_; - std::string name_; - bool destroyed_; - bool readable_; - bool writable_; - bool connect_requested_; - ChannelMap channels_; - XmlElementList messages_; - talk_base::CriticalSection crit_; // Protects changes to channels and messages - bool allow_local_ips_; - - // Called when the state of a channel changes. - void OnChannelReadableState(TransportChannel* channel); - void OnChannelWritableState(TransportChannel* channel); - - // Called when a channel requests signaling. - void OnChannelRequestSignaling(); - - // Called when a channel wishes to send a transport message. - void OnChannelMessage(TransportChannelImpl* impl, buzz::XmlElement* elem); - - // Dispatches messages to the appropriate handler (below). - void OnMessage(talk_base::Message* msg); - - // These are versions of the above methods that are called only on a - // particular thread (s = signaling, w = worker). The above methods post or - // send a message to invoke this version. - TransportChannelImpl* CreateChannel_w(const std::string& name, const std::string& session_type); - void DestroyChannel_w(const std::string& name); - void ConnectChannels_w(); - void ResetChannels_w(); - void DestroyAllChannels_w(); - void ForwardChannelMessage_w(const std::string& name, - buzz::XmlElement* elem); - void OnChannelReadableState_s(); - void OnChannelWritableState_s(); - void OnChannelRequestSignaling_s(); - void OnConnecting_s(); - - // Helper function that invokes the given function on every channel. - typedef void (TransportChannelImpl::* TransportChannelFunc)(); - void CallChannels_w(TransportChannelFunc func); - - // Computes the OR of the channel's read or write state (argument picks). - bool GetTransportState_s(bool read); - - // Invoked when there are messages waiting to send in the messages_ list. - // We wait to send any messages until the client asks us to connect. - void OnChannelMessage_s(); - - DISALLOW_EVIL_CONSTRUCTORS(Transport); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_TRANSPORT_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/transportchannel.cc b/third_party/libjingle/files/talk/p2p/base/transportchannel.cc deleted file mode 100644 index ba076ac..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transportchannel.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sstream> -#include "talk/p2p/base/transportchannel.h" - -namespace cricket { - -std::string TransportChannel::ToString() const { - const char READABLE_ABBREV[2] = { '_', 'R' }; - const char WRITABLE_ABBREV[2] = { '_', 'W' }; - std::stringstream ss; - ss << "Channel[" << name_ << "|" << READABLE_ABBREV[readable_] - << WRITABLE_ABBREV[writable_] << "]"; - return ss.str(); -} - -void TransportChannel::set_readable(bool readable) { - if (readable_ != readable) { - readable_ = readable; - SignalReadableState(this); - } -} - -void TransportChannel::set_writable(bool writable) { - if (writable_ != writable) { - writable_ = writable; - SignalWritableState(this); - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/transportchannel.h b/third_party/libjingle/files/talk/p2p/base/transportchannel.h deleted file mode 100644 index 68b8fd1..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transportchannel.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_ -#define _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_ - -#include <string> -#include "talk/base/basictypes.h" -#include "talk/base/sigslot.h" -#include "talk/base/socket.h" - -namespace cricket { - -// A TransportChannel represents one logical stream of packets that are sent -// between the two sides of a session. -class TransportChannel: public sigslot::has_slots<> { - public: - TransportChannel(const std::string& name, const std::string &session_type) - : name_(name), session_type_(session_type), readable_(false), writable_(false) {} - virtual ~TransportChannel() {} - - // Returns the name of this channel. - const std::string& name() const { return name_; } - const std::string& session_type() const { return session_type_; } - - // Returns the readable and states of this channel. Each time one of these - // states changes, a signal is raised. These states are aggregated by the - // TransportManager. - bool readable() const { return readable_; } - bool writable() const { return writable_; } - sigslot::signal1<TransportChannel*> SignalReadableState; - sigslot::signal1<TransportChannel*> SignalWritableState; - - // Attempts to send the given packet. The return value is < 0 on failure. - virtual int SendPacket(const char *data, size_t len) = 0; - - // Sets a socket option on this channel. Note that not all options are - // supported by all transport types. - virtual int SetOption(talk_base::Socket::Option opt, int value) = 0; - - // Returns the most recent error that occurred on this channel. - virtual int GetError() = 0; - - // Signalled each time a packet is received on this channel. - sigslot::signal3<TransportChannel*, const char*, size_t> SignalReadPacket; - - // This signal occurs when there is a change in the way that packets are - // being routed. The address indicates the address of the first hop in the - // new route, if this is known. If this cannot be determined or is not well- - // defined, then the channel may give an address of 0. - sigslot::signal2<TransportChannel*, const talk_base::SocketAddress&> - SignalRouteChange; - - // Invoked when the channel is being destroyed. - sigslot::signal1<TransportChannel*> SignalDestroyed; - - // TODO: Generalize network monitoring. - - // Debugging description of this transport channel. - std::string ToString() const; - - protected: - // Sets the readable state, signaling if necessary. - void set_readable(bool readable); - - // Sets the writable state, signaling if necessary. - void set_writable(bool writable); - - private: - std::string name_; - std::string session_type_; - bool readable_; - bool writable_; - - DISALLOW_EVIL_CONSTRUCTORS(TransportChannel); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/transportchannelimpl.h b/third_party/libjingle/files/talk/p2p/base/transportchannelimpl.h deleted file mode 100644 index 742d307..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transportchannelimpl.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_ -#define _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_ - -#include <string> -#include "talk/p2p/base/transportchannel.h" - -namespace buzz { class XmlElement; } - -namespace cricket { - -class Transport; - -// Base class for real implementations of TransportChannel. This includes some -// methods called only by Transport, which do not need to be exposed to the -// client. -class TransportChannelImpl: public TransportChannel { - public: - TransportChannelImpl(const std::string& name, const std::string& session_type) - : TransportChannel(name, session_type) {} - - // Returns the transport that created this channel. - virtual Transport* GetTransport() = 0; - - // Begins the process of attempting to make a connection to the other client. - virtual void Connect() = 0; - - // Resets this channel back to the initial state (i.e., not connecting). - virtual void Reset() = 0; - - // Allows an individual channel to request signaling and be notified when it - // is ready. This is useful if the individual named channels have need to - // send their own transport-info stanzas. - sigslot::signal0<> SignalRequestSignaling; - virtual void OnSignalingReady() = 0; - - // Handles sending and receiving of stanzas related to this particular - // channel. Any channel may send whatever messages it wants. The Transport - // receives all incoming messages and may forward them to the relevant - // channel. The transport will delete signaled messages. - // - // Note: Since these messages are delivered asynchronously to the channel, - // they cannot return an error if the message is invalid. It is assumed that - // the Transport will have checked validity before forwarding. - virtual void OnChannelMessage(const buzz::XmlElement* msg) = 0; - sigslot::signal2<TransportChannelImpl*, - buzz::XmlElement*> SignalChannelMessage; - - private: - DISALLOW_EVIL_CONSTRUCTORS(TransportChannelImpl); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.cc b/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.cc deleted file mode 100644 index bc94d67..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/base/transportchannelproxy.h" -#include "talk/base/common.h" -#include "talk/p2p/base/transport.h" -#include "talk/p2p/base/transportchannelimpl.h" - -namespace cricket { - -TransportChannelProxy::TransportChannelProxy(const std::string& name, const std::string &session_type) - : TransportChannel(name, session_type), impl_(NULL) { -} - -TransportChannelProxy::~TransportChannelProxy() { - if (impl_) - impl_->GetTransport()->DestroyChannel(impl_->name()); -} - -void TransportChannelProxy::SetImplementation(TransportChannelImpl* impl) { - impl_ = impl; - impl_->SignalReadableState.connect( - this, &TransportChannelProxy::OnReadableState); - impl_->SignalWritableState.connect( - this, &TransportChannelProxy::OnWritableState); - impl_->SignalReadPacket.connect(this, &TransportChannelProxy::OnReadPacket); - impl_->SignalRouteChange.connect(this, &TransportChannelProxy::OnRouteChange); - for (OptionList::iterator it = pending_options_.begin(); - it != pending_options_.end(); - ++it) { - impl_->SetOption(it->first, it->second); - } - pending_options_.clear(); -} - -int TransportChannelProxy::SendPacket(const char *data, size_t len) { - ASSERT(impl_ != NULL); // should not be used until channel is writable - return impl_->SendPacket(data, len); -} - -int TransportChannelProxy::SetOption(talk_base::Socket::Option opt, int value) { - if (impl_) - return impl_->SetOption(opt, value); - pending_options_.push_back(OptionPair(opt, value)); - return 0; -} - -int TransportChannelProxy::GetError() { - ASSERT(impl_ != NULL); // should not be used until channel is writable - return impl_->GetError(); -} - -void TransportChannelProxy::OnReadableState(TransportChannel* channel) { - ASSERT(channel == impl_); - set_readable(impl_->readable()); -} - -void TransportChannelProxy::OnWritableState(TransportChannel* channel) { - ASSERT(channel == impl_); - set_writable(impl_->writable()); -} - -void TransportChannelProxy::OnReadPacket( - TransportChannel* channel, const char* data, size_t size) { - ASSERT(channel == impl_); - SignalReadPacket(this, data, size); -} - -void TransportChannelProxy::OnRouteChange(TransportChannel* channel, - const talk_base::SocketAddress& address) { - ASSERT(channel == impl_); - SignalRouteChange(this, address); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.h b/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.h deleted file mode 100644 index 46d8a44..0000000 --- a/third_party/libjingle/files/talk/p2p/base/transportchannelproxy.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_ -#define _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_ - -#include <string> -#include <vector> -#include "talk/p2p/base/transportchannel.h" - -namespace cricket { - -class TransportChannelImpl; - -// Proxies calls between the client and the transport channel implementation. -// This is needed because clients are allowed to create channels before the -// network negotiation is complete. Hence, we create a proxy up front, and -// when negotiation completes, connect the proxy to the implementaiton. -class TransportChannelProxy: public TransportChannel { - public: - TransportChannelProxy(const std::string& name, const std::string &session_type); - virtual ~TransportChannelProxy(); - - TransportChannelImpl* impl() const { return impl_; } - - // Sets the implementation to which we will proxy. - void SetImplementation(TransportChannelImpl* impl); - - // Implementation of the TransportChannel interface. These simply forward to - // the implementation. - virtual int SendPacket(const char *data, size_t len); - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - - private: - typedef std::pair<talk_base::Socket::Option, int> OptionPair; - typedef std::vector<OptionPair> OptionList; - TransportChannelImpl* impl_; - OptionList pending_options_; - - // Catch signals from the implementation channel. These just forward to the - // client (after updating our state to match). - void OnReadableState(TransportChannel* channel); - void OnWritableState(TransportChannel* channel); - void OnReadPacket(TransportChannel* channel, const char* data, size_t size); - void OnRouteChange(TransportChannel* channel, const talk_base::SocketAddress& address); - - DISALLOW_EVIL_CONSTRUCTORS(TransportChannelProxy); -}; - -} // namespace cricket - -#endif // _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_ diff --git a/third_party/libjingle/files/talk/p2p/base/udpport.cc b/third_party/libjingle/files/talk/p2p/base/udpport.cc deleted file mode 100644 index fa47eba9..0000000 --- a/third_party/libjingle/files/talk/p2p/base/udpport.cc +++ /dev/null @@ -1,121 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif -#include "talk/base/logging.h" -#include "talk/p2p/base/udpport.h" -#include <iostream> -#include <cassert> - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std { - using ::strerror; -} -#endif - -#ifdef POSIX -extern "C" { -#include <errno.h> -} -#endif // POSIX - -namespace cricket { - -const std::string LOCAL_PORT_TYPE("local"); - -UDPPort::UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, - const talk_base::SocketAddress& address) - : Port(thread, LOCAL_PORT_TYPE, factory, network), error_(0) { - socket_ = CreatePacketSocket(PROTO_UDP); - socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacketSlot); - if (socket_->Bind(address) < 0) - PLOG(LERROR, socket_->GetError()) << "bind"; -} - -UDPPort::UDPPort(talk_base::Thread* thread, const std::string &type, - talk_base::SocketFactory* factory, talk_base::Network* network) - : Port(thread, type, factory, network), socket_(0), error_(0) { -} - -UDPPort::~UDPPort() { - delete socket_; -} - -void UDPPort::PrepareAddress() { - assert(socket_); - AddAddress(socket_->GetLocalAddress(), "udp", true); -} - -Connection* UDPPort::CreateConnection(const Candidate& address, - CandidateOrigin origin) { - if (address.protocol() != "udp") - return 0; - - Connection * conn = new ProxyConnection(this, 0, address); - AddConnection(conn); - return conn; -} - -int UDPPort::SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload) { - assert(socket_); - int sent = socket_->SendTo(data, size, addr); - if (sent < 0) - error_ = socket_->GetError(); - return sent; -} - -int UDPPort::SetOption(talk_base::Socket::Option opt, int value) { - return socket_->SetOption(opt, value); -} - -int UDPPort::GetError() { - assert(socket_); - return error_; -} - -void UDPPort::OnReadPacketSlot( - const char* data, size_t size, const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket) { - assert(socket == socket_); - OnReadPacket(data, size, remote_addr); -} - -void UDPPort::OnReadPacket( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr) { - if (Connection* conn = GetConnection(remote_addr)) { - conn->OnReadPacket(data, size); - } else { - Port::OnReadPacket(data, size, remote_addr); - } -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/base/udpport.h b/third_party/libjingle/files/talk/p2p/base/udpport.h deleted file mode 100644 index 9fcfa69..0000000 --- a/third_party/libjingle/files/talk/p2p/base/udpport.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __UDPPORT_H__ -#define __UDPPORT_H__ - -#include "talk/base/asyncudpsocket.h" -#include "talk/p2p/base/port.h" - -namespace talk_base { - class Thread; - class Network; - class SocketAddress; -} // namespace talk_base - -namespace cricket { - -extern const std::string LOCAL_PORT_TYPE; // type of UDP ports - -// Communicates using a local UDP port. -// -// This class is designed to allow subclasses to take advantage of the -// connection management provided by this class. A subclass should take of all -// packet sending and preparation, but when a packet is received, it should -// call this UDPPort::OnReadPacket (3 arg) to dispatch to a connection. -class UDPPort : public Port { -public: - UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory, - talk_base::Network* network, const talk_base::SocketAddress& address); - virtual ~UDPPort(); - - virtual void PrepareAddress(); - virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin); - - virtual int SetOption(talk_base::Socket::Option opt, int value); - virtual int GetError(); - -protected: - UDPPort(talk_base::Thread* thread, const std::string &type, - talk_base::SocketFactory* factory, talk_base::Network* network); - - // Handles sending using the local UDP socket. - virtual int SendTo(const void* data, size_t size, - const talk_base::SocketAddress& addr, bool payload); - - // Dispatches the given packet to the port or connection as appropriate. - void OnReadPacket( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr); - - talk_base::AsyncPacketSocket* socket() { return socket_; } - -private: - talk_base::AsyncPacketSocket* socket_; - int error_; - - // Receives packet signal from the local UDP Socket. - void OnReadPacketSlot( - const char* data, size_t size, - const talk_base::SocketAddress& remote_addr, - talk_base::AsyncPacketSocket* socket); -}; - -} // namespace cricket - -#endif // __UDPPORT_H__ diff --git a/third_party/libjingle/files/talk/p2p/client/Makefile.am b/third_party/libjingle/files/talk/p2p/client/Makefile.am deleted file mode 100644 index 11447f7..0000000 --- a/third_party/libjingle/files/talk/p2p/client/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -libcricketp2pclient_la_SOURCES = basicportallocator.cc \ - httpportallocator.cc \ - socketmonitor.cc - -noinst_HEADERS = basicportallocator.h \ - socketmonitor.h \ - sessionmanagertask.h \ - sessionsendtask.h \ - httpportallocator.h - -AM_CPPFLAGS = -I../../.. -DLINUX -DPOSIX -DINTERNAL_BUILD - -noinst_LTLIBRARIES = libcricketp2pclient.la diff --git a/third_party/libjingle/files/talk/p2p/client/basicportallocator.cc b/third_party/libjingle/files/talk/p2p/client/basicportallocator.cc deleted file mode 100644 index b7960f4..0000000 --- a/third_party/libjingle/files/talk/p2p/client/basicportallocator.cc +++ /dev/null @@ -1,690 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif - -#include "talk/base/common.h" -#include "talk/base/helpers.h" -#include "talk/base/host.h" -#include "talk/base/logging.h" -#include "talk/p2p/client/basicportallocator.h" -#include "talk/p2p/base/common.h" -#include "talk/p2p/base/port.h" -#include "talk/p2p/base/relayport.h" -#include "talk/p2p/base/stunport.h" -#include "talk/p2p/base/tcpport.h" -#include "talk/p2p/base/udpport.h" - -namespace { - -const uint32 MSG_CONFIG_START = 1; -const uint32 MSG_CONFIG_READY = 2; -const uint32 MSG_ALLOCATE = 3; -const uint32 MSG_ALLOCATION_PHASE = 4; -const uint32 MSG_SHAKE = 5; - -const uint32 ALLOCATE_DELAY = 250; -const uint32 ALLOCATION_STEP_DELAY = 1 * 1000; - -const int PHASE_UDP = 0; -const int PHASE_RELAY = 1; -const int PHASE_TCP = 2; -const int PHASE_SSLTCP = 3; -const int kNumPhases = 4; - -const float PREF_LOCAL_UDP = 1.0f; -const float PREF_LOCAL_STUN = 0.9f; -const float PREF_LOCAL_TCP = 0.8f; -const float PREF_RELAY = 0.5f; - -const float RELAY_PRIMARY_PREF_MODIFIER = 0.0f; // modifiers of the above constants -const float RELAY_BACKUP_PREF_MODIFIER = -0.2f; - - -// Returns the phase in which a given local candidate (or rather, the port that -// gave rise to that local candidate) would have been created. -int LocalCandidateToPhase(const cricket::Candidate& candidate) { - cricket::ProtocolType proto; - bool result = cricket::StringToProto(candidate.protocol().c_str(), proto); - if (result) { - if (candidate.type() == cricket::LOCAL_PORT_TYPE) { - switch (proto) { - case cricket::PROTO_UDP: return PHASE_UDP; - case cricket::PROTO_TCP: return PHASE_TCP; - default: assert(false); - } - } else if (candidate.type() == cricket::STUN_PORT_TYPE) { - return PHASE_UDP; - } else if (candidate.type() == cricket::RELAY_PORT_TYPE) { - switch (proto) { - case cricket::PROTO_UDP: return PHASE_RELAY; - case cricket::PROTO_TCP: return PHASE_TCP; - case cricket::PROTO_SSLTCP: return PHASE_SSLTCP; - default: assert(false); - } - } else { - assert(false); - } - } else { - assert(false); - } - return PHASE_UDP; // reached only with assert failure -} - -const int SHAKE_MIN_DELAY = 45 * 1000; // 45 seconds -const int SHAKE_MAX_DELAY = 90 * 1000; // 90 seconds - -int ShakeDelay() { - int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1; - return SHAKE_MIN_DELAY + cricket::CreateRandomId() % range; -} - -} - -namespace cricket { - -// Performs the allocation of ports, in a sequenced (timed) manner, for a given -// network and IP address. -class AllocationSequence : public talk_base::MessageHandler { -public: - AllocationSequence(BasicPortAllocatorSession* session, - talk_base::Network* network, - PortConfiguration* config); - ~AllocationSequence(); - - // Determines whether this sequence is operating on an equivalent network - // setup to the one given. - bool IsEquivalent(talk_base::Network* network); - - // Starts and stops the sequence. When started, it will continue allocating - // new ports on its own timed schedule. - void Start(); - void Stop(); - - // MessageHandler: - void OnMessage(talk_base::Message* msg); - - void EnableProtocol(ProtocolType proto); - bool ProtocolEnabled(ProtocolType proto) const; - -private: - BasicPortAllocatorSession* session_; - talk_base::Network* network_; - uint32 ip_; - PortConfiguration* config_; - bool running_; - int step_; - int step_of_phase_[kNumPhases]; - - typedef std::vector<ProtocolType> ProtocolList; - ProtocolList protocols_; - - void CreateUDPPorts(); - void CreateTCPPorts(); - void CreateStunPorts(); - void CreateRelayPorts(); -}; - - -// BasicPortAllocator - -BasicPortAllocator::BasicPortAllocator( - talk_base::NetworkManager* network_manager) - : network_manager_(network_manager), best_writable_phase_(-1), - stun_address_(NULL), relay_address_(NULL) { -} - -BasicPortAllocator::BasicPortAllocator( - talk_base::NetworkManager* network_manager, - talk_base::SocketAddress* stun_address, - talk_base::SocketAddress *relay_address) - : network_manager_(network_manager), best_writable_phase_(-1), - stun_address_(stun_address), relay_address_(relay_address) { -} - -BasicPortAllocator::~BasicPortAllocator() { -} - -int BasicPortAllocator::best_writable_phase() const { - // If we are configured with an HTTP proxy, the best bet is to use the relay - if ((best_writable_phase_ == -1) - && ((proxy().type == talk_base::PROXY_HTTPS) - || (proxy().type == talk_base::PROXY_UNKNOWN))) { - return PHASE_RELAY; - } - return best_writable_phase_; -} - -PortAllocatorSession *BasicPortAllocator::CreateSession( - const std::string &name, const std::string &session_type) { - return new BasicPortAllocatorSession(this, name, session_type, stun_address_, - relay_address_); -} - -void BasicPortAllocator::AddWritablePhase(int phase) { - if ((best_writable_phase_ == -1) || (phase < best_writable_phase_)) - best_writable_phase_ = phase; -} - -// BasicPortAllocatorSession - -BasicPortAllocatorSession::BasicPortAllocatorSession( - BasicPortAllocator *allocator, - const std::string &name, - const std::string &session_type) - : PortAllocatorSession(allocator->flags()), allocator_(allocator), - name_(name), network_thread_(NULL), session_type_(session_type), - allocation_started_(false), running_(false), stun_address_(NULL), - relay_address_(NULL) { -} - -BasicPortAllocatorSession::BasicPortAllocatorSession( - BasicPortAllocator *allocator, - const std::string &name, - const std::string &session_type, - talk_base::SocketAddress *stun_address, - talk_base::SocketAddress *relay_address) - : PortAllocatorSession(allocator->flags()), allocator_(allocator), - name_(name), session_type_(session_type), network_thread_(NULL), - allocation_started_(false), running_(false), stun_address_(stun_address), - relay_address_(relay_address) { -} - -BasicPortAllocatorSession::~BasicPortAllocatorSession() { - if (network_thread_ != NULL) - network_thread_->Clear(this); - - std::vector<PortData>::iterator it; - for (it = ports_.begin(); it != ports_.end(); it++) - delete it->port; - - for (uint32 i = 0; i < configs_.size(); ++i) - delete configs_[i]; - - for (uint32 i = 0; i < sequences_.size(); ++i) - delete sequences_[i]; -} - -void BasicPortAllocatorSession::GetInitialPorts() { - network_thread_ = talk_base::Thread::Current(); - - network_thread_->Post(this, MSG_CONFIG_START); - - if (flags() & PORTALLOCATOR_ENABLE_SHAKER) - network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE); -} - -void BasicPortAllocatorSession::StartGetAllPorts() { - assert(talk_base::Thread::Current() == network_thread_); - running_ = true; - if (allocation_started_) - network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE); - for (uint32 i = 0; i < sequences_.size(); ++i) - sequences_[i]->Start(); - for (size_t i = 0; i < ports_.size(); ++i) - ports_[i].port->Start(); -} - -void BasicPortAllocatorSession::StopGetAllPorts() { - assert(talk_base::Thread::Current() == network_thread_); - running_ = false; - network_thread_->Clear(this, MSG_ALLOCATE); - for (uint32 i = 0; i < sequences_.size(); ++i) - sequences_[i]->Stop(); -} - -void BasicPortAllocatorSession::OnMessage(talk_base::Message *message) { - switch (message->message_id) { - case MSG_CONFIG_START: - assert(talk_base::Thread::Current() == network_thread_); - GetPortConfigurations(); - break; - - case MSG_CONFIG_READY: - assert(talk_base::Thread::Current() == network_thread_); - OnConfigReady(static_cast<PortConfiguration*>(message->pdata)); - break; - - case MSG_ALLOCATE: - assert(talk_base::Thread::Current() == network_thread_); - OnAllocate(); - break; - - case MSG_SHAKE: - assert(talk_base::Thread::Current() == network_thread_); - OnShake(); - break; - - default: - assert(false); - } -} - -void BasicPortAllocatorSession::GetPortConfigurations() { - PortConfiguration* config = NULL; - if (stun_address_ != NULL) - config = new PortConfiguration(*stun_address_, - CreateRandomString(16), - CreateRandomString(16), - ""); - PortConfiguration::PortList ports; - if (relay_address_ != NULL) { - ports.push_back(ProtocolAddress(*relay_address_, PROTO_UDP)); - config->AddRelay(ports, RELAY_PRIMARY_PREF_MODIFIER); - } - - ConfigReady(config); -} - -void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) { - network_thread_->Post(this, MSG_CONFIG_READY, config); -} - -// Adds a configuration to the list. -void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) { - if (config) - configs_.push_back(config); - - AllocatePorts(); -} - -void BasicPortAllocatorSession::AllocatePorts() { - assert(talk_base::Thread::Current() == network_thread_); - - if (allocator_->proxy().type != talk_base::PROXY_NONE) - Port::set_proxy(allocator_->user_agent(), allocator_->proxy()); - - network_thread_->Post(this, MSG_ALLOCATE); -} - -// For each network, see if we have a sequence that covers it already. If not, -// create a new sequence to create the appropriate ports. -void BasicPortAllocatorSession::OnAllocate() { - std::vector<talk_base::Network*> networks; - allocator_->network_manager()->GetNetworks(networks); - - for (uint32 i = 0; i < networks.size(); ++i) { - if (HasEquivalentSequence(networks[i])) - continue; - - PortConfiguration* config = NULL; - if (configs_.size() > 0) - config = configs_.back(); - - AllocationSequence* sequence = - new AllocationSequence(this, networks[i], config); - if (running_) - sequence->Start(); - - sequences_.push_back(sequence); - } - - allocation_started_ = true; - if (running_) - network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE); -} - -bool BasicPortAllocatorSession::HasEquivalentSequence( - talk_base::Network* network) { - for (uint32 i = 0; i < sequences_.size(); ++i) - if (sequences_[i]->IsEquivalent(network)) - return true; - return false; -} - -void BasicPortAllocatorSession::AddAllocatedPort(Port* port, - AllocationSequence * seq, - float pref, - bool prepare_address) { - if (!port) - return; - - port->set_name(name_); - port->set_preference(pref); - port->set_generation(generation()); - PortData data; - data.port = port; - data.sequence = seq; - data.ready = false; - ports_.push_back(data); - port->SignalAddressReady.connect(this, &BasicPortAllocatorSession::OnAddressReady); - port->SignalConnectionCreated.connect(this, &BasicPortAllocatorSession::OnConnectionCreated); - port->SignalDestroyed.connect(this, &BasicPortAllocatorSession::OnPortDestroyed); - LOG_J(LS_INFO, port) << "Added port to allocator"; - if (prepare_address) - port->PrepareAddress(); - if (running_) - port->Start(); -} - -void BasicPortAllocatorSession::OnAddressReady(Port *port) { - assert(talk_base::Thread::Current() == network_thread_); - std::vector<PortData>::iterator it - = std::find(ports_.begin(), ports_.end(), port); - assert(it != ports_.end()); - if (it->ready) - return; - it->ready = true; - SignalPortReady(this, port); - - // Only accumulate the candidates whose protocol has been enabled - std::vector<Candidate> candidates; - const std::vector<Candidate>& potentials = port->candidates(); - for (size_t i=0; i<potentials.size(); ++i) { - ProtocolType pvalue; - if (!StringToProto(potentials[i].protocol().c_str(), pvalue)) - continue; - if (it->sequence->ProtocolEnabled(pvalue)) { - candidates.push_back(potentials[i]); - } - } - if (!candidates.empty()) { - SignalCandidatesReady(this, candidates); - } -} - -void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence * seq, - ProtocolType proto) { - std::vector<Candidate> candidates; - for (std::vector<PortData>::iterator it = ports_.begin(); it != ports_.end(); ++it) { - if (!it->ready || (it->sequence != seq)) - continue; - - const std::vector<Candidate>& potentials = it->port->candidates(); - for (size_t i=0; i<potentials.size(); ++i) { - ProtocolType pvalue; - if (!StringToProto(potentials[i].protocol().c_str(), pvalue)) - continue; - if (pvalue == proto) { - candidates.push_back(potentials[i]); - } - } - } - if (!candidates.empty()) { - SignalCandidatesReady(this, candidates); - } -} - -void BasicPortAllocatorSession::OnPortDestroyed(Port* port) { - assert(talk_base::Thread::Current() == network_thread_); - std::vector<PortData>::iterator iter = - find(ports_.begin(), ports_.end(), port); - assert(iter != ports_.end()); - ports_.erase(iter); - - LOG_J(LS_INFO, port) << "Removed port from allocator (" - << static_cast<int>(ports_.size()) << " remaining)"; -} - -void BasicPortAllocatorSession::OnConnectionCreated(Port* port, - Connection* conn) { - conn->SignalStateChange.connect(this, - &BasicPortAllocatorSession::OnConnectionStateChange); -} - -void BasicPortAllocatorSession::OnConnectionStateChange(Connection* conn) { - if (conn->write_state() == Connection::STATE_WRITABLE) - allocator_->AddWritablePhase( - LocalCandidateToPhase(conn->local_candidate())); -} - -void BasicPortAllocatorSession::OnShake() { - LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<"; - - std::vector<Port*> ports; - std::vector<Connection*> connections; - - for (size_t i = 0; i < ports_.size(); ++i) { - if (ports_[i].ready) - ports.push_back(ports_[i].port); - } - - for (size_t i = 0; i < ports.size(); ++i) { - Port::AddressMap::const_iterator iter; - for (iter = ports[i]->connections().begin(); - iter != ports[i]->connections().end(); - ++iter) { - connections.push_back(iter->second); - } - } - - LOG(INFO) << ">>>>> Destroying " << (int)ports.size() << " ports and " - << (int)connections.size() << " connections"; - - for (size_t i = 0; i < connections.size(); ++i) - connections[i]->Destroy(); - - if (running_ || (ports.size() > 0) || (connections.size() > 0)) - network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE); -} - -// AllocationSequence - -AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session, - talk_base::Network* network, - PortConfiguration* config) - : session_(session), network_(network), ip_(network->ip()), config_(config), - running_(false), step_(0) { - - // All of the phases up until the best-writable phase so far run in step 0. - // The other phases follow sequentially in the steps after that. If there is - // no best-writable so far, then only phase 0 occurs in step 0. - int last_phase_in_step_zero = - talk_base::_max(0, session->allocator()->best_writable_phase()); - for (int phase = 0; phase < kNumPhases; ++phase) - step_of_phase_[phase] = talk_base::_max(0, phase - last_phase_in_step_zero); - - // Immediately perform phase 0. - OnMessage(NULL); -} - -AllocationSequence::~AllocationSequence() { - session_->network_thread()->Clear(this); -} - -bool AllocationSequence::IsEquivalent(talk_base::Network* network) { - return (network == network_) && (ip_ == network->ip()); -} - -void AllocationSequence::Start() { - running_ = true; - session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY, - this, - MSG_ALLOCATION_PHASE); -} - -void AllocationSequence::Stop() { - running_ = false; - session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE); -} - -void AllocationSequence::OnMessage(talk_base::Message* msg) { - assert(talk_base::Thread::Current() == session_->network_thread()); - if (msg) - assert(msg->message_id == MSG_ALLOCATION_PHASE); - - const char* const PHASE_NAMES[kNumPhases] = { - "Udp", "Relay", "Tcp", "SslTcp" - }; - - // Perform all of the phases in the current step. - for (int phase = 0; phase < kNumPhases; phase++) { - if (step_of_phase_[phase] != step_) - continue; - - LOG_J(LS_INFO, network_) << "Allocation Phase=" << PHASE_NAMES[phase] - << " (Step=" << step_ << ")"; - - switch (phase) { - case PHASE_UDP: - CreateUDPPorts(); - CreateStunPorts(); - EnableProtocol(PROTO_UDP); - break; - - case PHASE_RELAY: - CreateRelayPorts(); - break; - - case PHASE_TCP: - CreateTCPPorts(); - EnableProtocol(PROTO_TCP); - break; - - case PHASE_SSLTCP: - EnableProtocol(PROTO_SSLTCP); - break; - - default: - ASSERT(false); - } - } - - // TODO: use different delays for each stage - step_ += 1; - if (running_) { - session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY, - this, - MSG_ALLOCATION_PHASE); - } -} - -void AllocationSequence::EnableProtocol(ProtocolType proto) { - if (!ProtocolEnabled(proto)) { - protocols_.push_back(proto); - session_->OnProtocolEnabled(this, proto); - } -} - -bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const { - for (ProtocolList::const_iterator it = protocols_.begin(); it != protocols_.end(); ++it) { - if (*it == proto) - return true; - } - return false; -} - -void AllocationSequence::CreateUDPPorts() { - if (session_->flags() & PORTALLOCATOR_DISABLE_UDP) - return; - - Port* port = new UDPPort(session_->network_thread(), NULL, network_, - talk_base::SocketAddress(ip_, 0)); - session_->AddAllocatedPort(port, this, PREF_LOCAL_UDP); -} - -void AllocationSequence::CreateTCPPorts() { - if (session_->flags() & PORTALLOCATOR_DISABLE_TCP) - return; - - Port* port = new TCPPort(session_->network_thread(), NULL, network_, - talk_base::SocketAddress(ip_, 0)); - session_->AddAllocatedPort(port, this, PREF_LOCAL_TCP); -} - -void AllocationSequence::CreateStunPorts() { - if (session_->flags() & PORTALLOCATOR_DISABLE_STUN) - return; - - if (!config_ || config_->stun_address.IsAny()) - return; - - Port* port = new StunPort(session_->network_thread(), NULL, network_, - talk_base::SocketAddress(ip_, 0), - config_->stun_address); - session_->AddAllocatedPort(port, this, PREF_LOCAL_STUN); -} - -void AllocationSequence::CreateRelayPorts() { - if (session_->flags() & PORTALLOCATOR_DISABLE_RELAY) - return; - - if (!config_) - return; - - PortConfiguration::RelayList::const_iterator relay; - for (relay = config_->relays.begin(); - relay != config_->relays.end(); - ++relay) { - - RelayPort *port = new RelayPort(session_->network_thread(), NULL, network_, - talk_base::SocketAddress(ip_, 0), - config_->username, config_->password, - config_->magic_cookie); - // Note: We must add the allocated port before we add addresses because - // the latter will create candidates that need name and preference - // settings. However, we also can't prepare the address (normally - // done by AddAllocatedPort) until we have these addresses. So we - // wait to do that until below. - session_->AddAllocatedPort(port, this, PREF_RELAY + relay->pref_modifier, - false); - - // Add the addresses of this protocol. - PortConfiguration::PortList::const_iterator relay_port; - for (relay_port = relay->ports.begin(); - relay_port != relay->ports.end(); - ++relay_port) { - port->AddServerAddress(*relay_port); - port->AddExternalAddress(*relay_port); - } - - // Start fetching an address for this port. - port->PrepareAddress(); - } -} - -// PortConfiguration - -PortConfiguration::PortConfiguration(const talk_base::SocketAddress& sa, - const std::string& un, - const std::string& pw, - const std::string& mc) - : stun_address(sa), username(un), password(pw), magic_cookie(mc) { -} - -void PortConfiguration::AddRelay(const PortList& ports, float pref_modifier) { - RelayServer relay; - relay.ports = ports; - relay.pref_modifier = pref_modifier; - relays.push_back(relay); -} - -bool PortConfiguration::SupportsProtocol( - const PortConfiguration::RelayServer& relay, ProtocolType type) { - PortConfiguration::PortList::const_iterator relay_port; - for (relay_port = relay.ports.begin(); - relay_port != relay.ports.end(); - ++relay_port) { - if (relay_port->proto == type) - return true; - } - return false; -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/client/basicportallocator.h b/third_party/libjingle/files/talk/p2p/client/basicportallocator.h deleted file mode 100644 index 0e3d313..0000000 --- a/third_party/libjingle/files/talk/p2p/client/basicportallocator.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _BASICPORTALLOCATOR_H_ -#define _BASICPORTALLOCATOR_H_ - -#include "talk/base/thread.h" -#include "talk/base/messagequeue.h" -#include "talk/base/network.h" -#include "talk/p2p/base/portallocator.h" -#include <string> -#include <vector> - -namespace cricket { - -class BasicPortAllocator : public PortAllocator { -public: - BasicPortAllocator(talk_base::NetworkManager* network_manager); - BasicPortAllocator(talk_base::NetworkManager* network_manager, - talk_base::SocketAddress *stun_server, talk_base::SocketAddress *relay_server); - virtual ~BasicPortAllocator(); - - talk_base::NetworkManager* network_manager() { return network_manager_; } - - // Returns the best (highest preference) phase that has produced a port that - // produced a writable connection. If no writable connections have been - // produced, this returns -1. - int best_writable_phase() const; - - virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type); - - // Called whenever a connection becomes writable with the argument being the - // phase that the corresponding port was created in. - void AddWritablePhase(int phase); - -private: - talk_base::NetworkManager* network_manager_; - talk_base::SocketAddress* stun_address_; - talk_base::SocketAddress* relay_address_; - int best_writable_phase_; -}; - -struct PortConfiguration; -class AllocationSequence; - -class BasicPortAllocatorSession: public PortAllocatorSession, - public talk_base::MessageHandler { -public: - BasicPortAllocatorSession(BasicPortAllocator *allocator, - const std::string &name, - const std::string &session_type); - BasicPortAllocatorSession(BasicPortAllocator *allocator, - const std::string &name, - const std::string &session_type, - talk_base::SocketAddress *stun_address, - talk_base::SocketAddress *relay_address); - ~BasicPortAllocatorSession(); - - BasicPortAllocator* allocator() { return allocator_; } - const std::string& name() const { return name_; } - const std::string& session_type() const { return session_type_; } - talk_base::Thread* network_thread() { return network_thread_; } - - virtual void GetInitialPorts(); - virtual void StartGetAllPorts(); - virtual void StopGetAllPorts(); - virtual bool IsGettingAllPorts() { return running_; } - -protected: - // Starts the process of getting the port configurations. - virtual void GetPortConfigurations(); - - // Adds a port configuration that is now ready. Once we have one for each - // network (or a timeout occurs), we will start allocating ports. - void ConfigReady(PortConfiguration* config); - - // MessageHandler. Can be overriden if message IDs do not conflict. - virtual void OnMessage(talk_base::Message *message); - -private: - void OnConfigReady(PortConfiguration* config); - void OnConfigTimeout(); - void AllocatePorts(); - void OnAllocate(); - bool HasEquivalentSequence(talk_base::Network* network); - void AddAllocatedPort(Port* port, AllocationSequence * seq, float pref, - bool prepare_address = true); - void OnAddressReady(Port *port); - void OnProtocolEnabled(AllocationSequence * seq, ProtocolType proto); - void OnPortDestroyed(Port* port); - void OnConnectionCreated(Port* port, Connection* conn); - void OnConnectionStateChange(Connection* conn); - void OnShake(); - - BasicPortAllocator *allocator_; - std::string name_; - std::string session_type_; - talk_base::Thread* network_thread_; - bool configuration_done_; - bool allocation_started_; - bool running_; // set when StartGetAllPorts is called - std::vector<PortConfiguration*> configs_; - std::vector<AllocationSequence*> sequences_; - talk_base::SocketAddress *stun_address_; - talk_base::SocketAddress *relay_address_; - - struct PortData { - Port * port; - AllocationSequence * sequence; - bool ready; - - bool operator==(Port * rhs) const { return (port == rhs); } - }; - std::vector<PortData> ports_; - - friend class AllocationSequence; -}; - -// Records configuration information useful in creating ports. -struct PortConfiguration : public talk_base::MessageData { - talk_base::SocketAddress stun_address; - std::string username; - std::string password; - std::string magic_cookie; - - typedef std::vector<ProtocolAddress> PortList; - struct RelayServer { - PortList ports; - float pref_modifier; // added to the protocol modifier to get the - // preference for this particular server - }; - - typedef std::vector<RelayServer> RelayList; - RelayList relays; - - PortConfiguration(const talk_base::SocketAddress& stun_address, - const std::string& username, - const std::string& password, - const std::string& magic_cookie); - - // Adds another relay server, with the given ports and modifier, to the list. - void AddRelay(const PortList& ports, float pref_modifier); - - // Determines whether the given relay server supports the given protocol. - static bool SupportsProtocol(const PortConfiguration::RelayServer& relay, - ProtocolType type); -}; - -} // namespace cricket - -#endif // _BASICPORTALLOCATOR_H_ diff --git a/third_party/libjingle/files/talk/p2p/client/httpportallocator.cc b/third_party/libjingle/files/talk/p2p/client/httpportallocator.cc deleted file mode 100644 index 17b1566..0000000 --- a/third_party/libjingle/files/talk/p2p/client/httpportallocator.cc +++ /dev/null @@ -1,185 +0,0 @@ -#if defined(_MSC_VER) && _MSC_VER < 1300 -#pragma warning(disable:4786) -#endif -#include "talk/base/asynchttprequest.h" -#include "talk/base/basicdefs.h" -#include "talk/base/common.h" -#include "talk/base/helpers.h" -#include "talk/base/logging.h" -#include "talk/base/signalthread.h" -#include "talk/p2p/client/httpportallocator.h" -#include <cassert> -#include <ctime> - -namespace { - -// Records the port on the hosts that will receive HTTP requests. -const uint16 kHostPort = 80; - -// Records the URL that we will GET in order to create a session. -const std::string kCreateSessionURL = "/create_session"; - -// The number of HTTP requests we should attempt before giving up. -const size_t kNumRetries = 5; - -// The delay before we give up on an HTTP request; -const int TIMEOUT = 5 * 1000; // 5 seconds - -const uint32 MSG_TIMEOUT = 100; // must not conflict with BasicPortAllocator.cpp - -// Helper routine to remove whitespace from the ends of a string. -void Trim(std::string& str) { - size_t first = str.find_first_not_of(" \t\r\n"); - if (first == std::string::npos) { - str.clear(); - return; - } - - size_t last = str.find_last_not_of(" \t\r\n"); - ASSERT(last != std::string::npos); -} - -// Parses the lines in the result of the HTTP request that are of the form -// 'a=b' and returns them in a map. -typedef std::map<std::string,std::string> StringMap; -void ParseMap(const std::string& string, StringMap& map) { - size_t start_of_line = 0; - size_t end_of_line = 0; - - for (;;) { // for each line - start_of_line = string.find_first_not_of("\r\n", end_of_line); - if (start_of_line == std::string::npos) - break; - - end_of_line = string.find_first_of("\r\n", start_of_line); - if (end_of_line == std::string::npos) { - end_of_line = string.length(); - } - - size_t equals = string.find('=', start_of_line); - if ((equals >= end_of_line) || (equals == std::string::npos)) - continue; - - std::string key(string, start_of_line, equals - start_of_line); - std::string value(string, equals + 1, end_of_line - equals - 1); - - Trim(key); - Trim(value); - - if ((key.size() > 0) && (value.size() > 0)) - map[key] = value; - } -} - -} - -namespace cricket { - -// HttpPortAllocator - -HttpPortAllocator::HttpPortAllocator(talk_base::NetworkManager* network_manager, const std::string &user_agent) - : BasicPortAllocator(network_manager), agent_(user_agent) { - relay_hosts_.push_back("relay.google.com"); - stun_hosts_.push_back(talk_base::SocketAddress("stun.l.google.com",19302)); -} - -HttpPortAllocator::~HttpPortAllocator() { -} - -PortAllocatorSession *HttpPortAllocator::CreateSession(const std::string &name, const std::string &session_type) { - return new HttpPortAllocatorSession(this, name, session_type, stun_hosts_, relay_hosts_, relay_token_, agent_); -} - -// HttpPortAllocatorSession - -HttpPortAllocatorSession::HttpPortAllocatorSession(HttpPortAllocator* allocator, const std::string &name, - const std::string &session_type, - const std::vector<talk_base::SocketAddress> &stun_hosts, - const std::vector<std::string> &relay_hosts, - const std::string &relay_token, - const std::string &user_agent) - : BasicPortAllocatorSession(allocator, name, session_type), - attempts_(0), relay_hosts_(relay_hosts), stun_hosts_(stun_hosts), relay_token_(relay_token), agent_(user_agent) { -} - -void HttpPortAllocatorSession::GetPortConfigurations() { - - if (attempts_ == kNumRetries) { - LOG(WARNING) << "HttpPortAllocator: maximum number of requests reached"; - return; - } - - // Choose the next host to try. - std::string host = relay_hosts_[attempts_ % relay_hosts_.size()]; - attempts_++; - LOG(INFO) << "HTTPPortAllocator: sending to host " << host; - - // Initiate an HTTP request to create a session through the chosen host. - - talk_base::AsyncHttpRequest* request = new talk_base::AsyncHttpRequest(agent_); - request->SignalWorkDone.connect(this, &HttpPortAllocatorSession::OnRequestDone); - - request->set_proxy(allocator()->proxy()); - request->response().document.reset(new talk_base::MemoryStream); - request->request().verb = talk_base::HV_GET; - request->request().path = kCreateSessionURL; - request->request().addHeader("X-Talk-Google-Relay-Auth", relay_token_, true); - request->request().addHeader("X-Google-Relay-Auth", relay_token_, true); - request->request().addHeader("X-Session-Type", session_type(), true); - request->set_host(host); - request->set_port(kHostPort); - request->Start(); - request->Release(); -} - -void HttpPortAllocatorSession::OnRequestDone(talk_base::SignalThread* data) { - talk_base::AsyncHttpRequest *request = - static_cast<talk_base::AsyncHttpRequest*> (data); - if (request->response().scode != 200) { - LOG(WARNING) << "HTTPPortAllocator: request " - << " received error " << request->response().scode; - GetPortConfigurations(); - return; - } - LOG(INFO) << "HTTPPortAllocator: request succeeded"; - - StringMap map; - talk_base::MemoryStream *stream = static_cast<talk_base::MemoryStream*>(request->response().document.get()); - stream->Rewind(); - size_t length; - stream->GetSize(&length); - std::string resp = std::string(stream->GetBuffer(), length); - ParseMap(resp, map); - - std::string username = map["username"]; - std::string password = map["password"]; - std::string magic_cookie = map["magic_cookie"]; - - std::string relay_ip = map["relay.ip"]; - std::string relay_udp_port = map["relay.udp_port"]; - std::string relay_tcp_port = map["relay.tcp_port"]; - std::string relay_ssltcp_port = map["relay.ssltcp_port"]; - - PortConfiguration* config = new PortConfiguration(stun_hosts_[0], - username, - password, - magic_cookie); - - PortConfiguration::PortList ports; - if (!relay_udp_port.empty()) { - talk_base::SocketAddress address(relay_ip, atoi(relay_udp_port.c_str())); - ports.push_back(ProtocolAddress(address, PROTO_UDP)); - } - if (!relay_tcp_port.empty()) { - talk_base::SocketAddress address(relay_ip, atoi(relay_tcp_port.c_str())); - ports.push_back(ProtocolAddress(address, PROTO_TCP)); - } - if (!relay_ssltcp_port.empty()) { - talk_base::SocketAddress address(relay_ip, atoi(relay_ssltcp_port.c_str())); - ports.push_back(ProtocolAddress(address, PROTO_SSLTCP)); - } - config->AddRelay(ports, 0.0f); - ConfigReady(config); -} - -} // namespace cricket diff --git a/third_party/libjingle/files/talk/p2p/client/httpportallocator.h b/third_party/libjingle/files/talk/p2p/client/httpportallocator.h deleted file mode 100644 index 96f3e72..0000000 --- a/third_party/libjingle/files/talk/p2p/client/httpportallocator.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _HTTPPORTALLOCATOR_H_ -#define _HTTPPORTALLOCATOR_H_ - -#include "talk/p2p/client/basicportallocator.h" - -namespace talk_base { - class SignalThread; -} - -namespace cricket { - -class HttpPortAllocator : public BasicPortAllocator { -public: - HttpPortAllocator(talk_base::NetworkManager* network_manager, const std::string &user_agent); - virtual ~HttpPortAllocator(); - - virtual PortAllocatorSession *CreateSession(const std::string &name, - const std::string &session_type); - void SetStunHosts(const std::vector<talk_base::SocketAddress> &hosts) {stun_hosts_ = hosts;} - void SetRelayHosts(const std::vector<std::string> &hosts) {relay_hosts_ = hosts;} - void SetRelayToken(const std::string &relay) {relay_token_ = relay;} - std::string relay_token() const { return relay_token_; } -private: - std::vector<talk_base::SocketAddress> stun_hosts_; - std::vector<std::string> relay_hosts_; - std::string relay_token_; - std::string agent_; -}; - -class RequestData; - -class HttpPortAllocatorSession : public BasicPortAllocatorSession { - public: - HttpPortAllocatorSession(HttpPortAllocator *allocator, - const std::string &name, - const std::string &session_type, - const std::vector<talk_base::SocketAddress> &stun_hosts, - const std::vector<std::string> &relay_hosts, - const std::string &relay, - const std::string &agent); - ~HttpPortAllocatorSession() {}; - -protected: - virtual void GetPortConfigurations(); - -private: - std::vector<std::string> relay_hosts_; - std::vector<talk_base::SocketAddress> stun_hosts_; - std::string relay_token_; - std::string agent_; - - void OnRequestDone(talk_base::SignalThread* request); - HttpPortAllocator* http_allocator() { - return static_cast<HttpPortAllocator*>(allocator()); - } - int attempts_; -}; - -} // namespace cricket - -#endif // _XMPPPORTALLOCATOR_H_ diff --git a/third_party/libjingle/files/talk/p2p/client/sessionmanagertask.h b/third_party/libjingle/files/talk/p2p/client/sessionmanagertask.h deleted file mode 100644 index 2a05357..0000000 --- a/third_party/libjingle/files/talk/p2p/client/sessionmanagertask.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SESSIONMANAGERTASK_H_ -#define _SESSIONMANAGERTASK_H_ - -#include "talk/p2p/base/sessionmanager.h" -#include "talk/p2p/client/sessionsendtask.h" -#include "talk/xmpp/xmppengine.h" -#include "talk/xmpp/xmpptask.h" - -namespace cricket { - -// This class handles sending and receiving XMPP messages on behalf of the -// SessionManager. The sending part is handed over to SessionSendTask. - -class SessionManagerTask : public buzz::XmppTask { - public: - SessionManagerTask(Task *parent, SessionManager *session_manager) - : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE) { - session_manager_ = session_manager; - } - - ~SessionManagerTask() { - } - - // Turns on simple support for sending messages, using SessionSendTask. - void EnableOutgoingMessages() { - session_manager_->SignalOutgoingMessage.connect( - this, &SessionManagerTask::OnOutgoingMessage); - session_manager_->SignalRequestSignaling.connect( - session_manager_, &SessionManager::OnSignalingReady); - } - - virtual int ProcessStart() { - const buzz::XmlElement *stanza = NextStanza(); - if (stanza == NULL) - return STATE_BLOCKED; - session_manager_->OnIncomingMessage(stanza); - return STATE_START; - } - - protected: - virtual bool HandleStanza(const buzz::XmlElement *stanza) { - if (!session_manager_->IsSessionMessage(stanza)) - return false; - // Responses are handled by the SessionSendTask that sent the request. - //if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET) - // return false; - QueueStanza(stanza); - return true; - } - - private: - SessionManager* session_manager_; - - void OnOutgoingMessage(const buzz::XmlElement* stanza) { - cricket::SessionSendTask* sender = - new cricket::SessionSendTask(GetParent(), session_manager_); - sender->Send(stanza); - sender->Start(); - } -}; - -} // namespace cricket - -#endif // _SESSIONMANAGERTASK_H_ diff --git a/third_party/libjingle/files/talk/p2p/client/sessionsendtask.h b/third_party/libjingle/files/talk/p2p/client/sessionsendtask.h deleted file mode 100644 index 3beb9d4..0000000 --- a/third_party/libjingle/files/talk/p2p/client/sessionsendtask.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_ -#define _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_ - -#include "talk/base/common.h" -#include "talk/xmpp/constants.h" -#include "talk/xmpp/xmppclient.h" -#include "talk/xmpp/xmppengine.h" -#include "talk/xmpp/xmpptask.h" -#include "talk/p2p/base/sessionmanager.h" - -namespace cricket { - -// The job of this task is to send an IQ stanza out (after stamping it with -// an ID attribute) and then wait for a response. If not response happens -// within 5 seconds, it will signal failure on a SessionManager. If an error -// happens it will also signal failure. If, however, the send succeeds this -// task will quietly go away. - -class SessionSendTask : public buzz::XmppTask { -public: - SessionSendTask(Task *parent, SessionManager *session_manager) - : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE), - session_manager_(session_manager) { - set_timeout_seconds(15); - } - - virtual ~SessionSendTask() { - SignalDone(this); - } - - void Send(const buzz::XmlElement* stanza) { - ASSERT(stanza_.get() == NULL); - - // This should be an IQ of type set, result, or error. In the first case, - // we supply an ID. In the others, it should be present. - ASSERT(stanza->Name() == buzz::QN_IQ); - ASSERT(stanza->HasAttr(buzz::QN_TYPE)); - if (stanza->Attr(buzz::QN_TYPE) == "set") { - ASSERT(!stanza->HasAttr(buzz::QN_ID)); - } else { - ASSERT((stanza->Attr(buzz::QN_TYPE) == "result") || - (stanza->Attr(buzz::QN_TYPE) == "error")); - ASSERT(stanza->HasAttr(buzz::QN_ID)); - } - - stanza_.reset(new buzz::XmlElement(*stanza)); - if (stanza_->HasAttr(buzz::QN_ID)) { - set_task_id(stanza_->Attr(buzz::QN_ID)); - } else { - stanza_->SetAttr(buzz::QN_ID, task_id()); - } - } - - sigslot::signal1<SessionSendTask *> SignalDone; - -protected: - virtual int OnTimeout() { - session_manager_->OnFailedSend(stanza_.get(), NULL); - - return XmppTask::OnTimeout(); - } - - virtual int ProcessStart() { - SendStanza(stanza_.get()); - if (stanza_->Attr(buzz::QN_TYPE) == buzz::STR_SET) { - return STATE_RESPONSE; - } else { - return STATE_DONE; - } - } - - virtual int ProcessResponse() { - if (GetClient()->GetState() != buzz::XmppEngine::STATE_OPEN) { - return STATE_DONE; - } - - const buzz::XmlElement* next = NextStanza(); - if (next == NULL) - return STATE_BLOCKED; - - if (next->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) { - session_manager_->OnIncomingResponse(stanza_.get(), next); - } else { - session_manager_->OnFailedSend(stanza_.get(), next); - } - - return STATE_DONE; - } - - virtual bool HandleStanza(const buzz::XmlElement *stanza) { - if (!MatchResponseIq(stanza, - buzz::Jid(stanza_->Attr(buzz::QN_TO)), task_id())) - return false; - if (stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT || - stanza->Attr(buzz::QN_TYPE) == buzz::STR_ERROR) { - QueueStanza(stanza); - return true; - } - return false; - } - -private: - SessionManager *session_manager_; - talk_base::scoped_ptr<buzz::XmlElement> stanza_; - bool timed_out_; -}; - -} - -#endif // _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_ diff --git a/third_party/libjingle/files/talk/p2p/client/socketmonitor.cc b/third_party/libjingle/files/talk/p2p/client/socketmonitor.cc deleted file mode 100644 index 88d37ce..0000000 --- a/third_party/libjingle/files/talk/p2p/client/socketmonitor.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/p2p/client/socketmonitor.h" -#include "talk/base/common.h" - -namespace cricket { - -const uint32 MSG_MONITOR_POLL = 1; -const uint32 MSG_MONITOR_START = 2; -const uint32 MSG_MONITOR_STOP = 3; -const uint32 MSG_MONITOR_SIGNAL = 4; - -SocketMonitor::SocketMonitor(Session* session, - TransportChannel* channel, - talk_base::Thread *monitor_thread) { - session_ = session; - channel_ = channel; - channel_thread_ = session->session_manager()->worker_thread(); - monitoring_thread_ = monitor_thread; - monitoring_ = false; -} - -SocketMonitor::~SocketMonitor() { - channel_thread_->Clear(this); - monitoring_thread_->Clear(this); -} - -void SocketMonitor::Start(int milliseconds) { - rate_ = milliseconds; - if (rate_ < 250) - rate_ = 250; - channel_thread_->Post(this, MSG_MONITOR_START); -} - -void SocketMonitor::Stop() { - channel_thread_->Post(this, MSG_MONITOR_STOP); -} - -void SocketMonitor::OnMessage(talk_base::Message *message) { - talk_base::CritScope cs(&crit_); - - switch (message->message_id) { - case MSG_MONITOR_START: - ASSERT(talk_base::Thread::Current() == channel_thread_); - if (!monitoring_) { - monitoring_ = true; - if (GetP2PChannel() != NULL) { - GetP2PChannel()->SignalConnectionMonitor.connect( - this, &SocketMonitor::OnConnectionMonitor); - } - PollSocket(true); - } - break; - - case MSG_MONITOR_STOP: - ASSERT(talk_base::Thread::Current() == channel_thread_); - if (monitoring_) { - monitoring_ = false; - if (GetP2PChannel() != NULL) - GetP2PChannel()->SignalConnectionMonitor.disconnect(this); - channel_thread_->Clear(this); - } - break; - - case MSG_MONITOR_POLL: - ASSERT(talk_base::Thread::Current() == channel_thread_); - PollSocket(true); - break; - - case MSG_MONITOR_SIGNAL: - { - ASSERT(talk_base::Thread::Current() == monitoring_thread_); - std::vector<ConnectionInfo> infos = connection_infos_; - crit_.Leave(); - SignalUpdate(this, infos); - crit_.Enter(); - } - break; - } -} - -void SocketMonitor::OnConnectionMonitor(P2PTransportChannel* channel) { - talk_base::CritScope cs(&crit_); - if (monitoring_) - PollSocket(false); -} - -void SocketMonitor::PollSocket(bool poll) { - ASSERT(talk_base::Thread::Current() == channel_thread_); - talk_base::CritScope cs(&crit_); - - // Gather connection infos - - P2PTransportChannel* p2p_channel = GetP2PChannel(); - if (p2p_channel != NULL) { - connection_infos_.clear(); - const std::vector<Connection *> &connections = p2p_channel->connections(); - std::vector<Connection *>::const_iterator it; - for (it = connections.begin(); it != connections.end(); it++) { - Connection *connection = *it; - ConnectionInfo info; - info.best_connection = p2p_channel->best_connection() == connection; - info.readable = connection->read_state() == Connection::STATE_READABLE; - info.writable = connection->write_state() == Connection::STATE_WRITABLE; - info.timeout = connection->write_state() == Connection::STATE_WRITE_TIMEOUT; - info.new_connection = !connection->reported(); - connection->set_reported(true); - info.rtt = connection->rtt(); - info.sent_total_bytes = connection->sent_total_bytes(); - info.sent_bytes_second = connection->sent_bytes_second(); - info.recv_total_bytes = connection->recv_total_bytes(); - info.recv_bytes_second = connection->recv_bytes_second(); - info.local_candidate = connection->local_candidate(); - info.remote_candidate = connection->remote_candidate(); - info.est_quality = connection->port()->network()->quality(); - info.key = reinterpret_cast<void *>(connection); - connection_infos_.push_back(info); - } - } - - // Signal the monitoring thread, start another poll timer - - monitoring_thread_->Post(this, MSG_MONITOR_SIGNAL); - if (poll) - channel_thread_->PostDelayed(rate_, this, MSG_MONITOR_POLL); -} - -P2PTransportChannel* SocketMonitor::GetP2PChannel() { - if (session_->transport() == NULL) - return NULL; - if (session_->transport()->name() != kNsP2pTransport) - return NULL; - TransportChannelImpl* impl = session_->GetImplementation(channel_); - if (impl == NULL) - return NULL; - return static_cast<P2PTransportChannel*>(impl); -} - -} diff --git a/third_party/libjingle/files/talk/p2p/client/socketmonitor.h b/third_party/libjingle/files/talk/p2p/client/socketmonitor.h deleted file mode 100644 index ced86b8..0000000 --- a/third_party/libjingle/files/talk/p2p/client/socketmonitor.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * libjingle - * Copyright 2004--2005, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SOCKETMONITOR_H_ -#define _SOCKETMONITOR_H_ - -#include "talk/base/thread.h" -#include "talk/base/sigslot.h" -#include "talk/base/criticalsection.h" -#include "talk/p2p/base/session.h" -#include "talk/p2p/base/p2ptransportchannel.h" -#include "talk/p2p/base/port.h" -#include <vector> - -namespace cricket { - -struct ConnectionInfo { - bool best_connection; - bool writable; - bool readable; - bool timeout; - bool new_connection; - size_t rtt; - size_t sent_total_bytes; - size_t sent_bytes_second; - size_t recv_total_bytes; - size_t recv_bytes_second; - Candidate local_candidate; - Candidate remote_candidate; - double est_quality; - void *key; -}; - -class SocketMonitor : public talk_base::MessageHandler, - public sigslot::has_slots<> { -public: - SocketMonitor(Session* session, TransportChannel* channel, - talk_base::Thread *monitor_thread); - ~SocketMonitor(); - - void Start(int cms); - void Stop(); - - talk_base::Thread *monitor_thread() { return monitoring_thread_; } - - sigslot::signal2<SocketMonitor *, - const std::vector<ConnectionInfo> &> SignalUpdate; - -protected: - void OnMessage(talk_base::Message *message); - void OnConnectionMonitor(P2PTransportChannel* channel); - void PollSocket(bool poll); - P2PTransportChannel* GetP2PChannel(); - - std::vector<ConnectionInfo> connection_infos_; - Session* session_; - TransportChannel* channel_; - talk_base::Thread* channel_thread_; - talk_base::Thread* monitoring_thread_; - talk_base::CriticalSection crit_; - uint32 rate_; - bool monitoring_; -}; - -} - -#endif // _SOCKETMONITOR_H_ diff --git a/third_party/libjingle/files/talk/xmpp/xmppclientsettings.h b/third_party/libjingle/files/talk/xmpp/xmppclientsettings.h index f5ff0a6..fa81d5d 100644 --- a/third_party/libjingle/files/talk/xmpp/xmppclientsettings.h +++ b/third_party/libjingle/files/talk/xmpp/xmppclientsettings.h @@ -28,8 +28,21 @@ #ifndef _XMPPCLIENTSETTINGS_H_ #define _XMPPCLIENTSETTINGS_H_ -#include "talk/p2p/base/port.h" #include "talk/base/cryptstring.h" +#include "talk/base/proxyinfo.h" + +namespace cricket { + +// This enum was taken from talk/p2p/base/port.h, which is the only +// thing we actually need from the p2p directory. +enum ProtocolType { + PROTO_UDP, + PROTO_TCP, + PROTO_SSLTCP, + PROTO_LAST = PROTO_SSLTCP +}; + +} // namespace cricket namespace buzz { diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp index db0f5bd..180f8a3 100644 --- a/third_party/libjingle/libjingle.gyp +++ b/third_party/libjingle/libjingle.gyp @@ -54,8 +54,7 @@ 'type': '<(library)', 'sources': [ - # 'files/talk/p2p/client/socketmonitor.cc', # unneeded - # 'files/talk/p2p/client/socketmonitor.h', # unneeded + # everything in files/talk/p2p is unneeded and has been removed # 'files/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h', # openssl # 'files/talk/base/basictypes.h', # overridden # 'files/talk/base/natserver_main.cc', # has a main() @@ -167,51 +166,6 @@ 'files/talk/base/virtualsocketserver.cc', 'files/talk/base/virtualsocketserver.h', 'files/talk/base/winsock_initializer.h', - 'files/talk/p2p/base/candidate.h', - 'files/talk/p2p/base/common.h', - 'files/talk/p2p/base/constants.cc', - 'files/talk/p2p/base/constants.h', - 'files/talk/p2p/base/p2ptransport.cc', - 'files/talk/p2p/base/p2ptransport.h', - 'files/talk/p2p/base/p2ptransportchannel.cc', - 'files/talk/p2p/base/p2ptransportchannel.h', - 'files/talk/p2p/base/port.cc', - 'files/talk/p2p/base/port.h', - 'files/talk/p2p/base/portallocator.h', - 'files/talk/p2p/base/rawtransport.cc', - 'files/talk/p2p/base/rawtransport.h', - 'files/talk/p2p/base/rawtransportchannel.cc', - 'files/talk/p2p/base/rawtransportchannel.h', - 'files/talk/p2p/base/relayport.cc', - 'files/talk/p2p/base/relayport.h', - 'files/talk/p2p/base/session.cc', - 'files/talk/p2p/base/session.h', - 'files/talk/p2p/base/sessionclient.h', - 'files/talk/p2p/base/sessiondescription.h', - 'files/talk/p2p/base/sessionid.h', - 'files/talk/p2p/base/sessionmanager.cc', - 'files/talk/p2p/base/sessionmanager.h', - 'files/talk/p2p/base/stun.cc', - 'files/talk/p2p/base/stun.h', - 'files/talk/p2p/base/stunport.cc', - 'files/talk/p2p/base/stunport.h', - 'files/talk/p2p/base/stunrequest.cc', - 'files/talk/p2p/base/stunrequest.h', - 'files/talk/p2p/base/tcpport.cc', - 'files/talk/p2p/base/tcpport.h', - 'files/talk/p2p/base/transport.cc', - 'files/talk/p2p/base/transport.h', - 'files/talk/p2p/base/transportchannel.cc', - 'files/talk/p2p/base/transportchannel.h', - 'files/talk/p2p/base/transportchannelimpl.h', - 'files/talk/p2p/base/transportchannelproxy.cc', - 'files/talk/p2p/base/transportchannelproxy.h', - 'files/talk/p2p/base/udpport.cc', - 'files/talk/p2p/base/udpport.h', - 'files/talk/p2p/client/basicportallocator.cc', - 'files/talk/p2p/client/basicportallocator.h', - 'files/talk/p2p/client/httpportallocator.cc', - 'files/talk/p2p/client/httpportallocator.h', 'files/talk/xmllite/qname.cc', 'files/talk/xmllite/qname.h', 'files/talk/xmllite/xmlbuilder.cc', diff --git a/third_party/libjingle/mods-since-v0_4_0.diff b/third_party/libjingle/mods-since-v0_4_0.diff index e95fa7f..a3a6be6 100644 --- a/third_party/libjingle/mods-since-v0_4_0.diff +++ b/third_party/libjingle/mods-since-v0_4_0.diff @@ -1155,77 +1155,10 @@ Only in libjingle/files/talk/base: winsock_initializer.h Only in libjingle-0.4.0/talk: examples Only in libjingle-0.4.0/talk: libjingle.sln Only in libjingle-0.4.0/talk: libjingle.vcproj +Only in libjingle-0.4.0/talk/p2p: Makefile.am Only in libjingle-0.4.0/talk/p2p: Makefile.in -Only in libjingle-0.4.0/talk/p2p/base: Makefile.in -diff -r libjingle-0.4.0/talk/p2p/base/candidate.h libjingle/files/talk/p2p/base/candidate.h -52c52 -< const float preference() const { return preference_; } ---- -> float preference() const { return preference_; } -diff -r libjingle-0.4.0/talk/p2p/base/p2ptransport.cc libjingle/files/talk/p2p/base/p2ptransport.cc -37c37 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -diff -r libjingle-0.4.0/talk/p2p/base/port.cc libjingle/files/talk/p2p/base/port.cc -34a35 -> #include <cstring> -270c271 -< talk_base::scoped_ptr<StunMessage> stun_msg(new StunMessage()); ---- -> scoped_ptr<StunMessage> stun_msg(new StunMessage()); -diff -r libjingle-0.4.0/talk/p2p/base/rawtransport.cc libjingle/files/talk/p2p/base/rawtransport.cc -35c35 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -diff -r libjingle-0.4.0/talk/p2p/base/rawtransportchannel.cc libjingle/files/talk/p2p/base/rawtransportchannel.cc -39c39 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -diff -r libjingle-0.4.0/talk/p2p/base/relayport.cc libjingle/files/talk/p2p/base/relayport.cc -36a37 -> #include <cstring> -diff -r libjingle-0.4.0/talk/p2p/base/session.cc libjingle/files/talk/p2p/base/session.cc -32c32 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -diff -r libjingle-0.4.0/talk/p2p/base/sessionmanager.cc libjingle/files/talk/p2p/base/sessionmanager.cc -32c32 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -diff -r libjingle-0.4.0/talk/p2p/base/sessionmanager.h libjingle/files/talk/p2p/base/sessionmanager.h -159c159 -< buzz::XmlElement* SessionManager::CreateErrorMessage( ---- -> buzz::XmlElement* CreateErrorMessage( -diff -r libjingle-0.4.0/talk/p2p/base/stun.cc libjingle/files/talk/p2p/base/stun.cc -31a32 -> #include <cstring> -diff -r libjingle-0.4.0/talk/p2p/base/stunrequest.cc libjingle/files/talk/p2p/base/stunrequest.cc -149c149 -< const StunMessageType StunRequest::type() { ---- -> StunMessageType StunRequest::type() { -diff -r libjingle-0.4.0/talk/p2p/base/stunrequest.h libjingle/files/talk/p2p/base/stunrequest.h -91c91 -< const StunMessageType type(); ---- -> StunMessageType type(); -diff -r libjingle-0.4.0/talk/p2p/base/transport.cc libjingle/files/talk/p2p/base/transport.cc -34c34 -< #include "talk/xmpp/constants.h" ---- -> #include "talk/xmpp/xmppconstants.h" -Only in libjingle-0.4.0/talk/p2p/client: Makefile.in -diff -r libjingle-0.4.0/talk/p2p/client/httpportallocator.cc libjingle/files/talk/p2p/client/httpportallocator.cc -82c82 -< relay_hosts_.push_back("relay.l.google.com"); ---- -> relay_hosts_.push_back("relay.google.com"); +Only in libjingle-0.4.0/talk/p2p: base +Only in libjingle-0.4.0/talk/p2p: client Only in libjingle-0.4.0/talk: session Only in libjingle-0.4.0/talk: third_party Only in libjingle-0.4.0/talk/xmllite: Makefile.in @@ -1450,13 +1383,30 @@ diff -r libjingle-0.4.0/talk/xmpp/xmppclient.h libjingle/files/talk/xmpp/xmppcli --- > std::string GetStateName(int state) const { diff -r libjingle-0.4.0/talk/xmpp/xmppclientsettings.h libjingle/files/talk/xmpp/xmppclientsettings.h -59a60,62 +31d30 +< #include "talk/p2p/base/port.h" +32a32,45 +> #include "talk/base/proxyinfo.h" +> +> namespace cricket { +> +> // This enum was taken from talk/p2p/base/port.h, which is the only +> // thing we actually need from the p2p directory. +> enum ProtocolType { +> PROTO_UDP, +> PROTO_TCP, +> PROTO_SSLTCP, +> PROTO_LAST = PROTO_SSLTCP +> }; +> +> } // namespace cricket +59a73,75 > void set_token_service(const std::string & token_service) { > token_service_ = token_service; > } -75a79 +75a92 > const std::string & token_service() const { return token_service_; } -93a98 +93a111 > std::string token_service_; Only in libjingle/files/talk/xmpp: xmppconstants.cc Only in libjingle/files/talk/xmpp: xmppconstants.h |