move xmpp and p2p to webrtc
Create a copy of talk/xmpp and talk/p2p under webrtc/libjingle/xmpp and
webrtc/p2p. Also makes libjingle use those version instead of the one in the talk folder.
BUG=3379
Review URL: https://webrtc-codereview.appspot.com/26999004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7549 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/p2p/base/stunrequest.cc b/webrtc/p2p/base/stunrequest.cc
new file mode 100644
index 0000000..65eb027
--- /dev/null
+++ b/webrtc/p2p/base/stunrequest.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/p2p/base/stunrequest.h"
+
+#include "webrtc/base/common.h"
+#include "webrtc/base/helpers.h"
+#include "webrtc/base/logging.h"
+
+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(rtc::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());
+ request->Construct();
+ 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) {
+ // StunRequest destructor calls Remove() which deletes requests
+ // from |requests_|.
+ delete 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() == GetStunSuccessResponseType(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 "
+ << GetStunSuccessResponseType(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 + kStunTransactionIdOffset, kStunTransactionIdLength);
+
+ RequestMap::iterator iter = requests_.find(id);
+ if (iter == requests_.end())
+ return false;
+
+ // Parse the STUN message and continue processing as usual.
+
+ rtc::ByteBuffer buf(data, size);
+ rtc::scoped_ptr<StunMessage> response(iter->second->msg_->CreateNew());
+ if (!response->Read(&buf))
+ return false;
+
+ return CheckResponse(response.get());
+}
+
+StunRequest::StunRequest()
+ : count_(0), timeout_(false), manager_(0),
+ msg_(new StunMessage()), tstamp_(0) {
+ msg_->SetTransactionID(
+ rtc::CreateRandomString(kStunTransactionIdLength));
+}
+
+StunRequest::StunRequest(StunMessage* request)
+ : count_(0), timeout_(false), manager_(0),
+ msg_(request), tstamp_(0) {
+ msg_->SetTransactionID(
+ rtc::CreateRandomString(kStunTransactionIdLength));
+}
+
+StunRequest::~StunRequest() {
+ ASSERT(manager_ != NULL);
+ if (manager_) {
+ manager_->Remove(this);
+ manager_->thread_->Clear(this);
+ }
+ delete msg_;
+}
+
+void StunRequest::Construct() {
+ if (msg_->type() == 0) {
+ Prepare(msg_);
+ ASSERT(msg_->type() != 0);
+ }
+}
+
+int StunRequest::type() {
+ ASSERT(msg_ != NULL);
+ return msg_->type();
+}
+
+const StunMessage* StunRequest::msg() const {
+ return msg_;
+}
+
+uint32 StunRequest::Elapsed() const {
+ return rtc::TimeSince(tstamp_);
+}
+
+
+void StunRequest::set_manager(StunRequestManager* manager) {
+ ASSERT(!manager_);
+ manager_ = manager;
+}
+
+void StunRequest::OnMessage(rtc::Message* pmsg) {
+ ASSERT(manager_ != NULL);
+ ASSERT(pmsg->message_id == MSG_STUN_SEND);
+
+ if (timeout_) {
+ OnTimeout();
+ delete this;
+ return;
+ }
+
+ tstamp_ = rtc::Time();
+
+ rtc::ByteBuffer buf;
+ msg_->Write(&buf);
+ manager_->SignalSendPacket(buf.Data(), buf.Length(), this);
+
+ int delay = GetNextDelay();
+ manager_->thread_->PostDelayed(delay, this, MSG_STUN_SEND, NULL);
+}
+
+int StunRequest::GetNextDelay() {
+ int delay = DELAY_UNIT * rtc::_min(1 << count_, DELAY_MAX_FACTOR);
+ count_ += 1;
+ if (count_ == MAX_SENDS)
+ timeout_ = true;
+ return delay;
+}
+
+} // namespace cricket