Deleted unused method EstimateMTU, and the WinPing class.
BUG=None Review-Url: https://codereview.webrtc.org/2866183004 Cr-Commit-Position: refs/heads/master@{#18077}
This commit is contained in:
@ -611,8 +611,6 @@ rtc_static_library("rtc_base") {
|
||||
"win32securityerrors.cc",
|
||||
"win32window.cc",
|
||||
"win32window.h",
|
||||
"winping.cc",
|
||||
"winping.h",
|
||||
]
|
||||
|
||||
libs += [
|
||||
|
||||
@ -100,10 +100,6 @@ AsyncSocket::ConnState AsyncSocketAdapter::GetState() const {
|
||||
return socket_->GetState();
|
||||
}
|
||||
|
||||
int AsyncSocketAdapter::EstimateMTU(uint16_t* mtu) {
|
||||
return socket_->EstimateMTU(mtu);
|
||||
}
|
||||
|
||||
int AsyncSocketAdapter::GetOption(Option opt, int* value) {
|
||||
return socket_->GetOption(opt, value);
|
||||
}
|
||||
|
||||
@ -66,7 +66,6 @@ class AsyncSocketAdapter : public AsyncSocket, public sigslot::has_slots<> {
|
||||
int GetError() const override;
|
||||
void SetError(int error) override;
|
||||
ConnState GetState() const override;
|
||||
int EstimateMTU(uint16_t* mtu) override;
|
||||
int GetOption(Option opt, int* value) override;
|
||||
int SetOption(Option opt, int value) override;
|
||||
|
||||
|
||||
@ -230,7 +230,6 @@ class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
|
||||
ConnState GetState() const override {
|
||||
return connected_ ? CS_CONNECTED : CS_CLOSED;
|
||||
}
|
||||
int EstimateMTU(uint16_t* mtu) override { return socket_->EstimateMTU(mtu); }
|
||||
int GetOption(Option opt, int* value) override {
|
||||
return socket_->GetOption(opt, value);
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@
|
||||
#include "webrtc/base/networkmonitor.h"
|
||||
#include "webrtc/base/nullsocketserver.h"
|
||||
#include "webrtc/base/timeutils.h"
|
||||
#include "webrtc/base/winping.h"
|
||||
#include "webrtc/base/win32socketinit.h"
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
@ -472,70 +471,6 @@ int PhysicalSocket::Close() {
|
||||
return err;
|
||||
}
|
||||
|
||||
int PhysicalSocket::EstimateMTU(uint16_t* mtu) {
|
||||
SocketAddress addr = GetRemoteAddress();
|
||||
if (addr.IsAnyIP()) {
|
||||
SetError(ENOTCONN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
|
||||
WinPing ping;
|
||||
if (!ping.IsValid()) {
|
||||
SetError(EINVAL); // can't think of a better error ID
|
||||
return -1;
|
||||
}
|
||||
int header_size = ICMP_HEADER_SIZE;
|
||||
if (addr.family() == AF_INET6) {
|
||||
header_size += IPV6_HEADER_SIZE;
|
||||
} else if (addr.family() == AF_INET) {
|
||||
header_size += IP_HEADER_SIZE;
|
||||
}
|
||||
|
||||
for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
|
||||
int32_t size = PACKET_MAXIMUMS[level] - header_size;
|
||||
WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
|
||||
ICMP_PING_TIMEOUT_MILLIS,
|
||||
1, false);
|
||||
if (result == WinPing::PING_FAIL) {
|
||||
SetError(EINVAL); // can't think of a better error ID
|
||||
return -1;
|
||||
} else if (result != WinPing::PING_TOO_LARGE) {
|
||||
*mtu = PACKET_MAXIMUMS[level];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RTC_NOTREACHED();
|
||||
return -1;
|
||||
#elif defined(WEBRTC_MAC)
|
||||
// No simple way to do this on Mac OS X.
|
||||
// SIOCGIFMTU would work if we knew which interface would be used, but
|
||||
// figuring that out is pretty complicated. For now we'll return an error
|
||||
// and let the caller pick a default MTU.
|
||||
SetError(EINVAL);
|
||||
return -1;
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
// Gets the path MTU.
|
||||
int value;
|
||||
socklen_t vlen = sizeof(value);
|
||||
int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
|
||||
if (err < 0) {
|
||||
UpdateLastError();
|
||||
return err;
|
||||
}
|
||||
|
||||
RTC_DCHECK((0 <= value) && (value <= 65536));
|
||||
*mtu = value;
|
||||
return 0;
|
||||
#elif defined(__native_client__)
|
||||
// Most socket operations, including this, will fail in NaCl's sandbox.
|
||||
error_ = EACCES;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
SOCKET PhysicalSocket::DoAccept(SOCKET socket,
|
||||
sockaddr* addr,
|
||||
socklen_t* addrlen) {
|
||||
|
||||
@ -151,8 +151,6 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
|
||||
|
||||
int Close() override;
|
||||
|
||||
int EstimateMTU(uint16_t* mtu) override;
|
||||
|
||||
SocketServer* socketserver() { return ss_; }
|
||||
|
||||
protected:
|
||||
|
||||
@ -171,11 +171,6 @@ class Socket {
|
||||
};
|
||||
virtual ConnState GetState() const = 0;
|
||||
|
||||
// Fills in the given uint16_t with the current estimate of the MTU along the
|
||||
// path to the address to which this socket is connected. NOTE: This method
|
||||
// can block for up to 10 seconds on Windows.
|
||||
virtual int EstimateMTU(uint16_t* mtu) = 0;
|
||||
|
||||
enum Option {
|
||||
OPT_DONTFRAGMENT,
|
||||
OPT_RCVBUF, // receive buffer size
|
||||
|
||||
@ -1013,30 +1013,6 @@ void SocketTest::GetSetOptionsInternal(const IPAddress& loopback) {
|
||||
int current_nd, desired_nd = 1;
|
||||
ASSERT_EQ(-1, socket->GetOption(Socket::OPT_NODELAY, ¤t_nd));
|
||||
ASSERT_EQ(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd));
|
||||
|
||||
// Skip the esimate MTU test for IPv6 for now.
|
||||
if (loopback.family() != AF_INET6) {
|
||||
// Try estimating MTU.
|
||||
std::unique_ptr<AsyncSocket> mtu_socket(
|
||||
ss_->CreateAsyncSocket(loopback.family(), SOCK_DGRAM));
|
||||
mtu_socket->Bind(SocketAddress(loopback, 0));
|
||||
uint16_t mtu;
|
||||
// should fail until we connect
|
||||
ASSERT_EQ(-1, mtu_socket->EstimateMTU(&mtu));
|
||||
mtu_socket->Connect(SocketAddress(loopback, 0));
|
||||
#if defined(WEBRTC_WIN)
|
||||
// now it should succeed
|
||||
ASSERT_NE(-1, mtu_socket->EstimateMTU(&mtu));
|
||||
ASSERT_GE(mtu, 1492); // should be at least the 1492 "plateau" on localhost
|
||||
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
// except on WEBRTC_MAC && !WEBRTC_IOS, where it's not yet implemented
|
||||
ASSERT_EQ(-1, mtu_socket->EstimateMTU(&mtu));
|
||||
#else
|
||||
// and the behavior seems unpredictable on Linux,
|
||||
// failing on the build machine
|
||||
// but succeeding on my Ubiquity instance.
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
|
||||
|
||||
@ -384,13 +384,6 @@ int VirtualSocket::SetOption(Option opt, int value) {
|
||||
return 0; // 0 is success to emulate setsockopt()
|
||||
}
|
||||
|
||||
int VirtualSocket::EstimateMTU(uint16_t* mtu) {
|
||||
if (CS_CONNECTED != state_)
|
||||
return ENOTCONN;
|
||||
else
|
||||
return 65536;
|
||||
}
|
||||
|
||||
void VirtualSocket::OnMessage(Message* pmsg) {
|
||||
if (pmsg->message_id == MSG_ID_PACKET) {
|
||||
RTC_DCHECK(nullptr != pmsg->pdata);
|
||||
|
||||
@ -311,7 +311,6 @@ class VirtualSocket : public AsyncSocket,
|
||||
ConnState GetState() const override;
|
||||
int GetOption(Option opt, int* value) override;
|
||||
int SetOption(Option opt, int value) override;
|
||||
int EstimateMTU(uint16_t* mtu) override;
|
||||
void OnMessage(Message* pmsg) override;
|
||||
|
||||
bool was_any() { return was_any_; }
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/nethelpers.h"
|
||||
#include "webrtc/base/win32.h"
|
||||
#include "webrtc/base/winping.h"
|
||||
|
||||
#if !defined(WEBRTC_WIN)
|
||||
#error Only for Windows
|
||||
@ -36,29 +35,6 @@ TEST_F(Win32Test, FileTimeToUInt64Test) {
|
||||
EXPECT_EQ(expected, ToUInt64(ft));
|
||||
}
|
||||
|
||||
TEST_F(Win32Test, WinPingTest) {
|
||||
WinPing ping;
|
||||
ASSERT_TRUE(ping.IsValid());
|
||||
|
||||
// Test valid ping cases.
|
||||
WinPing::PingResult result = ping.Ping(IPAddress(INADDR_LOOPBACK), 20, 50, 1,
|
||||
false);
|
||||
ASSERT_EQ(WinPing::PING_SUCCESS, result);
|
||||
if (HasIPv6Enabled()) {
|
||||
WinPing::PingResult v6result = ping.Ping(IPAddress(in6addr_loopback), 20,
|
||||
50, 1, false);
|
||||
ASSERT_EQ(WinPing::PING_SUCCESS, v6result);
|
||||
}
|
||||
|
||||
// Test invalid parameter cases.
|
||||
ASSERT_EQ(WinPing::PING_INVALID_PARAMS, ping.Ping(
|
||||
IPAddress(INADDR_LOOPBACK), 0, 50, 1, false));
|
||||
ASSERT_EQ(WinPing::PING_INVALID_PARAMS, ping.Ping(
|
||||
IPAddress(INADDR_LOOPBACK), 20, 0, 1, false));
|
||||
ASSERT_EQ(WinPing::PING_INVALID_PARAMS, ping.Ping(
|
||||
IPAddress(INADDR_LOOPBACK), 20, 50, 0, false));
|
||||
}
|
||||
|
||||
TEST_F(Win32Test, IPv6AddressCompression) {
|
||||
IPAddress ipv6;
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/win32window.h"
|
||||
#include "webrtc/base/winping.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
@ -525,37 +524,6 @@ int Win32Socket::Close() {
|
||||
return err;
|
||||
}
|
||||
|
||||
int Win32Socket::EstimateMTU(uint16_t* mtu) {
|
||||
SocketAddress addr = GetRemoteAddress();
|
||||
if (addr.IsAnyIP()) {
|
||||
error_ = ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WinPing ping;
|
||||
if (!ping.IsValid()) {
|
||||
error_ = EINVAL; // can't think of a better error ID
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
|
||||
int32_t size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
|
||||
WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
|
||||
ICMP_PING_TIMEOUT_MILLIS, 1, false);
|
||||
if (result == WinPing::PING_FAIL) {
|
||||
error_ = EINVAL; // can't think of a better error ID
|
||||
return -1;
|
||||
}
|
||||
if (result != WinPing::PING_TOO_LARGE) {
|
||||
*mtu = PACKET_MAXIMUMS[level];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RTC_NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Win32Socket::CreateSink() {
|
||||
RTC_DCHECK(nullptr == sink_);
|
||||
|
||||
|
||||
@ -55,7 +55,6 @@ class Win32Socket : public AsyncSocket {
|
||||
virtual int GetError() const;
|
||||
virtual void SetError(int error);
|
||||
virtual ConnState GetState() const;
|
||||
virtual int EstimateMTU(uint16_t* mtu);
|
||||
virtual int GetOption(Option opt, int* value);
|
||||
virtual int SetOption(Option opt, int value);
|
||||
|
||||
|
||||
@ -1,357 +0,0 @@
|
||||
/*
|
||||
* 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/base/winping.h"
|
||||
|
||||
#include <Iphlpapi.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "webrtc/base/byteorder.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/ipaddress.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/nethelpers.h"
|
||||
#include "webrtc/base/socketaddress.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Found in IPExport.h
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct icmp_echo_reply {
|
||||
ULONG Address; // Replying address
|
||||
ULONG Status; // Reply IP_STATUS
|
||||
ULONG RoundTripTime; // RTT in milliseconds
|
||||
USHORT DataSize; // Reply data size in bytes
|
||||
USHORT Reserved; // Reserved for system use
|
||||
PVOID Data; // Pointer to the reply data
|
||||
struct ip_option_information Options; // Reply options
|
||||
} ICMP_ECHO_REPLY, * PICMP_ECHO_REPLY;
|
||||
|
||||
typedef struct icmpv6_echo_reply_lh {
|
||||
sockaddr_in6 Address;
|
||||
ULONG Status;
|
||||
unsigned int RoundTripTime;
|
||||
} ICMPV6_ECHO_REPLY, *PICMPV6_ECHO_REPLY;
|
||||
|
||||
//
|
||||
// IP_STATUS codes returned from IP APIs
|
||||
//
|
||||
|
||||
#define IP_STATUS_BASE 11000
|
||||
|
||||
#define IP_SUCCESS 0
|
||||
#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
|
||||
#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
|
||||
#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
|
||||
#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
|
||||
#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
|
||||
#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
|
||||
#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
|
||||
#define IP_HW_ERROR (IP_STATUS_BASE + 8)
|
||||
#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
|
||||
#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
|
||||
#define IP_BAD_REQ (IP_STATUS_BASE + 11)
|
||||
#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
|
||||
#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
|
||||
#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
|
||||
#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
|
||||
#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
|
||||
#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
|
||||
#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
|
||||
|
||||
#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
|
||||
#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
|
||||
#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
|
||||
#define IP_UNLOAD (IP_STATUS_BASE + 22)
|
||||
#define IP_ADDR_ADDED (IP_STATUS_BASE + 23)
|
||||
#define IP_MEDIA_CONNECT (IP_STATUS_BASE + 24)
|
||||
#define IP_MEDIA_DISCONNECT (IP_STATUS_BASE + 25)
|
||||
#define IP_BIND_ADAPTER (IP_STATUS_BASE + 26)
|
||||
#define IP_UNBIND_ADAPTER (IP_STATUS_BASE + 27)
|
||||
#define IP_DEVICE_DOES_NOT_EXIST (IP_STATUS_BASE + 28)
|
||||
#define IP_DUPLICATE_ADDRESS (IP_STATUS_BASE + 29)
|
||||
#define IP_INTERFACE_METRIC_CHANGE (IP_STATUS_BASE + 30)
|
||||
#define IP_RECONFIG_SECFLTR (IP_STATUS_BASE + 31)
|
||||
#define IP_NEGOTIATING_IPSEC (IP_STATUS_BASE + 32)
|
||||
#define IP_INTERFACE_WOL_CAPABILITY_CHANGE (IP_STATUS_BASE + 33)
|
||||
#define IP_DUPLICATE_IPADD (IP_STATUS_BASE + 34)
|
||||
|
||||
#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
|
||||
#define MAX_IP_STATUS IP_GENERAL_FAILURE
|
||||
#define IP_PENDING (IP_STATUS_BASE + 255)
|
||||
|
||||
//
|
||||
// Values used in the IP header Flags field.
|
||||
//
|
||||
#define IP_FLAG_DF 0x2 // Don't fragment this packet.
|
||||
|
||||
//
|
||||
// Supported IP Option Types.
|
||||
//
|
||||
// These types define the options which may be used in the OptionsData field
|
||||
// of the ip_option_information structure. See RFC 791 for a complete
|
||||
// description of each.
|
||||
//
|
||||
#define IP_OPT_EOL 0 // End of list option
|
||||
#define IP_OPT_NOP 1 // No operation
|
||||
#define IP_OPT_SECURITY 0x82 // Security option
|
||||
#define IP_OPT_LSRR 0x83 // Loose source route
|
||||
#define IP_OPT_SSRR 0x89 // Strict source route
|
||||
#define IP_OPT_RR 0x7 // Record route
|
||||
#define IP_OPT_TS 0x44 // Timestamp
|
||||
#define IP_OPT_SID 0x88 // Stream ID (obsolete)
|
||||
#define IP_OPT_ROUTER_ALERT 0x94 // Router Alert Option
|
||||
|
||||
#define MAX_OPT_SIZE 40 // Maximum length of IP options in bytes
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Global Constants and Types
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char * const ICMP_DLL_NAME = "Iphlpapi.dll";
|
||||
const char * const ICMP_CREATE_FUNC = "IcmpCreateFile";
|
||||
const char * const ICMP_CLOSE_FUNC = "IcmpCloseHandle";
|
||||
const char * const ICMP_SEND_FUNC = "IcmpSendEcho";
|
||||
const char * const ICMP6_CREATE_FUNC = "Icmp6CreateFile";
|
||||
const char * const ICMP6_SEND_FUNC = "Icmp6SendEcho2";
|
||||
|
||||
inline uint32_t ReplySize(uint32_t data_size, int family) {
|
||||
if (family == AF_INET) {
|
||||
// A ping error message is 8 bytes long, so make sure we allow for at least
|
||||
// 8 bytes of reply data.
|
||||
return sizeof(ICMP_ECHO_REPLY) + std::max<uint32_t>(8, data_size);
|
||||
} else if (family == AF_INET6) {
|
||||
// Per MSDN, Send6IcmpEcho2 needs at least one ICMPV6_ECHO_REPLY,
|
||||
// 8 bytes for ICMP header, _and_ an IO_BLOCK_STATUS (2 pointers),
|
||||
// in addition to the data size.
|
||||
return sizeof(ICMPV6_ECHO_REPLY) + data_size + 8 + (2 * sizeof(DWORD*));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// WinPing
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
WinPing::WinPing()
|
||||
: dll_(0), hping_(INVALID_HANDLE_VALUE), create_(0), close_(0), send_(0),
|
||||
create6_(0), send6_(0), data_(0), dlen_(0), reply_(0),
|
||||
rlen_(0), valid_(false) {
|
||||
|
||||
dll_ = LoadLibraryA(ICMP_DLL_NAME);
|
||||
if (!dll_) {
|
||||
LOG(LERROR) << "LoadLibrary: " << GetLastError();
|
||||
return;
|
||||
}
|
||||
|
||||
create_ = (PIcmpCreateFile) GetProcAddress(dll_, ICMP_CREATE_FUNC);
|
||||
close_ = (PIcmpCloseHandle) GetProcAddress(dll_, ICMP_CLOSE_FUNC);
|
||||
send_ = (PIcmpSendEcho) GetProcAddress(dll_, ICMP_SEND_FUNC);
|
||||
if (!create_ || !close_ || !send_) {
|
||||
LOG(LERROR) << "GetProcAddress(ICMP_*): " << GetLastError();
|
||||
return;
|
||||
}
|
||||
hping_ = create_();
|
||||
if (hping_ == INVALID_HANDLE_VALUE) {
|
||||
LOG(LERROR) << "IcmpCreateFile: " << GetLastError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasIPv6Enabled()) {
|
||||
create6_ = (PIcmp6CreateFile) GetProcAddress(dll_, ICMP6_CREATE_FUNC);
|
||||
send6_ = (PIcmp6SendEcho2) GetProcAddress(dll_, ICMP6_SEND_FUNC);
|
||||
if (!create6_ || !send6_) {
|
||||
LOG(LERROR) << "GetProcAddress(ICMP6_*): " << GetLastError();
|
||||
return;
|
||||
}
|
||||
hping6_ = create6_();
|
||||
if (hping6_ == INVALID_HANDLE_VALUE) {
|
||||
LOG(LERROR) << "Icmp6CreateFile: " << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
dlen_ = 0;
|
||||
rlen_ = ReplySize(dlen_, AF_INET);
|
||||
data_ = new char[dlen_];
|
||||
reply_ = new char[rlen_];
|
||||
|
||||
valid_ = true;
|
||||
}
|
||||
|
||||
WinPing::~WinPing() {
|
||||
if ((hping_ != INVALID_HANDLE_VALUE) && close_) {
|
||||
if (!close_(hping_))
|
||||
LOG(WARNING) << "IcmpCloseHandle: " << GetLastError();
|
||||
}
|
||||
if ((hping6_ != INVALID_HANDLE_VALUE) && close_) {
|
||||
if (!close_(hping6_)) {
|
||||
LOG(WARNING) << "Icmp6CloseHandle: " << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (dll_)
|
||||
FreeLibrary(dll_);
|
||||
|
||||
delete[] data_;
|
||||
delete[] reply_;
|
||||
}
|
||||
|
||||
WinPing::PingResult WinPing::Ping(IPAddress ip,
|
||||
uint32_t data_size,
|
||||
uint32_t timeout,
|
||||
uint8_t ttl,
|
||||
bool allow_fragments) {
|
||||
if (data_size == 0 || timeout == 0 || ttl == 0) {
|
||||
LOG(LERROR) << "IcmpSendEcho: data_size/timeout/ttl is 0.";
|
||||
return PING_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
RTC_DCHECK(IsValid());
|
||||
|
||||
IP_OPTION_INFORMATION ipopt;
|
||||
memset(&ipopt, 0, sizeof(ipopt));
|
||||
if (!allow_fragments)
|
||||
ipopt.Flags |= IP_FLAG_DF;
|
||||
ipopt.Ttl = ttl;
|
||||
|
||||
uint32_t reply_size = ReplySize(data_size, ip.family());
|
||||
|
||||
if (data_size > dlen_) {
|
||||
delete [] data_;
|
||||
dlen_ = data_size;
|
||||
data_ = new char[dlen_];
|
||||
memset(data_, 'z', dlen_);
|
||||
}
|
||||
|
||||
if (reply_size > rlen_) {
|
||||
delete [] reply_;
|
||||
rlen_ = reply_size;
|
||||
reply_ = new char[rlen_];
|
||||
}
|
||||
DWORD result = 0;
|
||||
if (ip.family() == AF_INET) {
|
||||
result = send_(hping_, ip.ipv4_address().S_un.S_addr, data_,
|
||||
uint16_t(data_size), &ipopt, reply_, reply_size, timeout);
|
||||
} else if (ip.family() == AF_INET6) {
|
||||
sockaddr_in6 src = {0};
|
||||
sockaddr_in6 dst = {0};
|
||||
src.sin6_family = AF_INET6;
|
||||
dst.sin6_family = AF_INET6;
|
||||
dst.sin6_addr = ip.ipv6_address();
|
||||
result = send6_(hping6_, nullptr, nullptr, nullptr, &src, &dst, data_,
|
||||
int16_t(data_size), &ipopt, reply_, reply_size, timeout);
|
||||
}
|
||||
if (result == 0) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == IP_PACKET_TOO_BIG)
|
||||
return PING_TOO_LARGE;
|
||||
if (error == IP_REQ_TIMED_OUT)
|
||||
return PING_TIMEOUT;
|
||||
LOG(LERROR) << "IcmpSendEcho(" << ip.ToSensitiveString()
|
||||
<< ", " << data_size << "): " << error;
|
||||
return PING_FAIL;
|
||||
}
|
||||
|
||||
return PING_SUCCESS;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Microsoft Documenation
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Routine Name:
|
||||
//
|
||||
// IcmpCreateFile
|
||||
//
|
||||
// Routine Description:
|
||||
//
|
||||
// Opens a handle on which ICMP Echo Requests can be issued.
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// None.
|
||||
//
|
||||
// Return Value:
|
||||
//
|
||||
// An open file handle or INVALID_HANDLE_VALUE. Extended error information
|
||||
// is available by calling GetLastError().
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Routine Name:
|
||||
//
|
||||
// IcmpCloseHandle
|
||||
//
|
||||
// Routine Description:
|
||||
//
|
||||
// Closes a handle opened by ICMPOpenFile.
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// IcmpHandle - The handle to close.
|
||||
//
|
||||
// Return Value:
|
||||
//
|
||||
// TRUE if the handle was closed successfully, otherwise FALSE. Extended
|
||||
// error information is available by calling GetLastError().
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Routine Name:
|
||||
//
|
||||
// IcmpSendEcho
|
||||
//
|
||||
// Routine Description:
|
||||
//
|
||||
// Sends an ICMP Echo request and returns any replies. The
|
||||
// call returns when the timeout has expired or the reply buffer
|
||||
// is filled.
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// IcmpHandle - An open handle returned by ICMPCreateFile.
|
||||
//
|
||||
// DestinationAddress - The destination of the echo request.
|
||||
//
|
||||
// RequestData - A buffer containing the data to send in the
|
||||
// request.
|
||||
//
|
||||
// RequestSize - The number of bytes in the request data buffer.
|
||||
//
|
||||
// RequestOptions - Pointer to the IP header options for the request.
|
||||
// May be null.
|
||||
//
|
||||
// ReplyBuffer - A buffer to hold any replies to the request.
|
||||
// On return, the buffer will contain an array of
|
||||
// ICMP_ECHO_REPLY structures followed by the
|
||||
// options and data for the replies. The buffer
|
||||
// should be large enough to hold at least one
|
||||
// ICMP_ECHO_REPLY structure plus
|
||||
// MAX(RequestSize, 8) bytes of data since an ICMP
|
||||
// error message contains 8 bytes of data.
|
||||
//
|
||||
// ReplySize - The size in bytes of the reply buffer.
|
||||
//
|
||||
// Timeout - The time in milliseconds to wait for replies.
|
||||
//
|
||||
// Return Value:
|
||||
//
|
||||
// Returns the number of ICMP_ECHO_REPLY structures stored in ReplyBuffer.
|
||||
// The status of each reply is contained in the structure. If the return
|
||||
// value is zero, extended error information is available via
|
||||
// GetLastError().
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace rtc
|
||||
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_WINPING_H__
|
||||
#define WEBRTC_BASE_WINPING_H__
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
|
||||
#include "webrtc/base/win32.h"
|
||||
#include "webrtc/base/basictypes.h"
|
||||
#include "webrtc/base/ipaddress.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// This class wraps a Win32 API for doing ICMP pinging. This API, unlike the
|
||||
// the normal socket APIs (as implemented on Win9x), will return an error if
|
||||
// an ICMP packet with the dont-fragment bit set is too large. This means this
|
||||
// class can be used to detect the MTU to a given address.
|
||||
|
||||
typedef struct ip_option_information {
|
||||
UCHAR Ttl; // Time To Live
|
||||
UCHAR Tos; // Type Of Service
|
||||
UCHAR Flags; // IP header flags
|
||||
UCHAR OptionsSize; // Size in bytes of options data
|
||||
PUCHAR OptionsData; // Pointer to options data
|
||||
} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;
|
||||
|
||||
typedef HANDLE (WINAPI *PIcmpCreateFile)();
|
||||
|
||||
typedef BOOL (WINAPI *PIcmpCloseHandle)(HANDLE icmp_handle);
|
||||
|
||||
typedef HANDLE (WINAPI *PIcmp6CreateFile)();
|
||||
|
||||
typedef BOOL (WINAPI *PIcmp6CloseHandle)(HANDLE icmp_handle);
|
||||
|
||||
typedef DWORD (WINAPI *PIcmpSendEcho)(
|
||||
HANDLE IcmpHandle,
|
||||
ULONG DestinationAddress,
|
||||
LPVOID RequestData,
|
||||
WORD RequestSize,
|
||||
PIP_OPTION_INFORMATION RequestOptions,
|
||||
LPVOID ReplyBuffer,
|
||||
DWORD ReplySize,
|
||||
DWORD Timeout);
|
||||
|
||||
typedef DWORD (WINAPI *PIcmp6SendEcho2)(
|
||||
HANDLE IcmpHandle,
|
||||
HANDLE Event,
|
||||
FARPROC ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
struct sockaddr_in6 *SourceAddress,
|
||||
struct sockaddr_in6 *DestinationAddress,
|
||||
LPVOID RequestData,
|
||||
WORD RequestSize,
|
||||
PIP_OPTION_INFORMATION RequestOptions,
|
||||
LPVOID ReplyBuffer,
|
||||
DWORD ReplySize,
|
||||
DWORD Timeout
|
||||
);
|
||||
|
||||
class WinPing {
|
||||
public:
|
||||
WinPing();
|
||||
~WinPing();
|
||||
|
||||
// Determines whether the class was initialized correctly.
|
||||
bool IsValid() { return valid_; }
|
||||
|
||||
// Attempts to send a ping with the given parameters.
|
||||
enum PingResult { PING_FAIL, PING_INVALID_PARAMS,
|
||||
PING_TOO_LARGE, PING_TIMEOUT, PING_SUCCESS };
|
||||
PingResult Ping(IPAddress ip,
|
||||
uint32_t data_size,
|
||||
uint32_t timeout_millis,
|
||||
uint8_t ttl,
|
||||
bool allow_fragments);
|
||||
|
||||
private:
|
||||
HMODULE dll_;
|
||||
HANDLE hping_;
|
||||
HANDLE hping6_;
|
||||
PIcmpCreateFile create_;
|
||||
PIcmpCloseHandle close_;
|
||||
PIcmpSendEcho send_;
|
||||
PIcmp6CreateFile create6_;
|
||||
PIcmp6SendEcho2 send6_;
|
||||
char* data_;
|
||||
uint32_t dlen_;
|
||||
char* reply_;
|
||||
uint32_t rlen_;
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
#endif // WEBRTC_BASE_WINPING_H__
|
||||
Reference in New Issue
Block a user