
Chrome will only see stunprober.h and stunprobercontext.h and link with libstunprober.a. It has support for shared and non-shared mode. In shared mode, a socket will be used to ping all resolved IPs once. In non-shared mode, each ping will get a new socket. The thread scheduling will try to run MaybeScheduleStunRequest every 1 ms. When the time is up for next ping, it'll send it out. BUG=4576 R=pthatcher@webrtc.org Review URL: https://webrtc-codereview.appspot.com/51729004 Cr-Commit-Position: refs/heads/master@{#9194}
183 lines
5.4 KiB
C++
183 lines
5.4 KiB
C++
/*
|
|
* Copyright 2015 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.
|
|
*/
|
|
|
|
#ifndef WEBRTC_P2P_STUNPROBER_STUNPROBER_DEPENDENCIES_H_
|
|
#define WEBRTC_P2P_STUNPROBER_STUNPROBER_DEPENDENCIES_H_
|
|
|
|
#include "webrtc/base/checks.h"
|
|
#include "webrtc/base/helpers.h"
|
|
#include "webrtc/base/logging.h"
|
|
#include "webrtc/base/scoped_ptr.h"
|
|
#include "webrtc/base/thread.h"
|
|
#include "webrtc/base/timeutils.h"
|
|
#include "webrtc/p2p/stunprober/stunprober.h"
|
|
|
|
// Common classes used by both the command line driver and the unit tests.
|
|
namespace stunprober {
|
|
|
|
class Socket : public ClientSocketInterface,
|
|
public ServerSocketInterface,
|
|
public sigslot::has_slots<> {
|
|
public:
|
|
explicit Socket(rtc::AsyncSocket* socket) : socket_(socket) {
|
|
socket_->SignalReadEvent.connect(this, &Socket::OnReadEvent);
|
|
socket_->SignalWriteEvent.connect(this, &Socket::OnWriteEvent);
|
|
}
|
|
|
|
int Connect(const rtc::SocketAddress& addr) override {
|
|
return MapResult(socket_->Connect(addr));
|
|
}
|
|
|
|
int Bind(const rtc::SocketAddress& addr) override {
|
|
return MapResult(socket_->Bind(addr));
|
|
}
|
|
|
|
int SendTo(const rtc::SocketAddress& addr,
|
|
char* buf,
|
|
size_t buf_len,
|
|
AsyncCallback callback) override {
|
|
write_ = NetworkWrite(addr, buf, buf_len, callback);
|
|
return MapResult(socket_->SendTo(buf, buf_len, addr));
|
|
}
|
|
|
|
int RecvFrom(char* buf,
|
|
size_t buf_len,
|
|
rtc::SocketAddress* addr,
|
|
AsyncCallback callback) override {
|
|
read_ = NetworkRead(buf, buf_len, addr, callback);
|
|
return MapResult(socket_->RecvFrom(buf, buf_len, addr));
|
|
}
|
|
|
|
int GetLocalAddress(rtc::SocketAddress* local_address) override {
|
|
*local_address = socket_->GetLocalAddress();
|
|
return 0;
|
|
}
|
|
|
|
void Close() override { socket_->Close(); }
|
|
|
|
virtual ~Socket() {}
|
|
|
|
protected:
|
|
int MapResult(int rv) {
|
|
if (rv >= 0) {
|
|
return rv;
|
|
}
|
|
int err = socket_->GetError();
|
|
if (err == EWOULDBLOCK || err == EAGAIN) {
|
|
return IO_PENDING;
|
|
} else {
|
|
return FAILED;
|
|
}
|
|
}
|
|
|
|
void OnReadEvent(rtc::AsyncSocket* socket) {
|
|
DCHECK(socket_ == socket);
|
|
NetworkRead read = read_;
|
|
read_ = NetworkRead();
|
|
if (!read.callback.empty()) {
|
|
read.callback(socket_->RecvFrom(read.buf, read.buf_len, read.addr));
|
|
}
|
|
}
|
|
|
|
void OnWriteEvent(rtc::AsyncSocket* socket) {
|
|
DCHECK(socket_ == socket);
|
|
NetworkWrite write = write_;
|
|
write_ = NetworkWrite();
|
|
if (!write.callback.empty()) {
|
|
write.callback(socket_->SendTo(write.buf, write.buf_len, write.addr));
|
|
}
|
|
}
|
|
|
|
struct NetworkWrite {
|
|
NetworkWrite() : buf(nullptr), buf_len(0) {}
|
|
NetworkWrite(const rtc::SocketAddress& addr,
|
|
char* buf,
|
|
size_t buf_len,
|
|
AsyncCallback callback)
|
|
: buf(buf), buf_len(buf_len), addr(addr), callback(callback) {}
|
|
char* buf;
|
|
size_t buf_len;
|
|
rtc::SocketAddress addr;
|
|
AsyncCallback callback;
|
|
};
|
|
|
|
NetworkWrite write_;
|
|
|
|
struct NetworkRead {
|
|
NetworkRead() : buf(nullptr), buf_len(0) {}
|
|
NetworkRead(char* buf,
|
|
size_t buf_len,
|
|
rtc::SocketAddress* addr,
|
|
AsyncCallback callback)
|
|
: buf(buf), buf_len(buf_len), addr(addr), callback(callback) {}
|
|
|
|
char* buf;
|
|
size_t buf_len;
|
|
rtc::SocketAddress* addr;
|
|
AsyncCallback callback;
|
|
};
|
|
|
|
NetworkRead read_;
|
|
|
|
rtc::scoped_ptr<rtc::AsyncSocket> socket_;
|
|
};
|
|
|
|
class SocketFactory : public SocketFactoryInterface {
|
|
public:
|
|
ClientSocketInterface* CreateClientSocket() override {
|
|
return new Socket(
|
|
rtc::Thread::Current()->socketserver()->CreateAsyncSocket(SOCK_DGRAM));
|
|
}
|
|
ServerSocketInterface* CreateServerSocket(size_t send_buffer_size,
|
|
size_t recv_buffer_size) override {
|
|
rtc::scoped_ptr<rtc::AsyncSocket> socket(
|
|
rtc::Thread::Current()->socketserver()->CreateAsyncSocket(SOCK_DGRAM));
|
|
|
|
if (socket) {
|
|
socket->SetOption(rtc::AsyncSocket::OPT_SNDBUF,
|
|
static_cast<int>(send_buffer_size));
|
|
socket->SetOption(rtc::AsyncSocket::OPT_RCVBUF,
|
|
static_cast<int>(recv_buffer_size));
|
|
return new Socket(socket.release());
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
};
|
|
|
|
class TaskRunner : public TaskRunnerInterface, public rtc::MessageHandler {
|
|
protected:
|
|
class CallbackMessageData : public rtc::MessageData {
|
|
public:
|
|
explicit CallbackMessageData(rtc::Callback0<void> callback)
|
|
: callback_(callback) {}
|
|
rtc::Callback0<void> callback_;
|
|
};
|
|
|
|
public:
|
|
void PostTask(rtc::Callback0<void> callback, uint32_t delay_ms) {
|
|
if (delay_ms == 0) {
|
|
rtc::Thread::Current()->Post(this, 0, new CallbackMessageData(callback));
|
|
} else {
|
|
rtc::Thread::Current()->PostDelayed(delay_ms, this, 0,
|
|
new CallbackMessageData(callback));
|
|
}
|
|
}
|
|
|
|
void OnMessage(rtc::Message* msg) {
|
|
rtc::scoped_ptr<CallbackMessageData> callback(
|
|
reinterpret_cast<CallbackMessageData*>(msg->pdata));
|
|
callback->callback_();
|
|
}
|
|
};
|
|
|
|
} // namespace stunprober
|
|
#endif // WEBRTC_P2P_STUNPROBER_STUNPROBER_DEPENDENCIES_H_
|