aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp
blob: b68748e2ab744f39c8826f38e8607c99f6f3e1a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 
// ICMPSocketImpl.cpp 
// 
// Library: Net 
// Package: ICMP 
// Module:  ICMPSocketImpl 
// 
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. 
// and Contributors. 
// 
// SPDX-License-Identifier:	BSL-1.0 
// 
 
 
#include "Poco/Net/ICMPSocketImpl.h" 
#include "Poco/Net/NetException.h" 
#include "Poco/Timespan.h" 
#include "Poco/Timestamp.h" 
#include "Poco/Exception.h" 
#include "Poco/Buffer.h" 
 
 
using Poco::TimeoutException; 
using Poco::Timespan; 
using Poco::Exception; 
 
 
namespace Poco { 
namespace Net { 
 
 
ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout): 
	RawSocketImpl(family, IPPROTO_ICMP), 
	_icmpPacket(family, dataSize), 
	_ttl(ttl), 
	_timeout(timeout) 
{ 
	setOption(IPPROTO_IP, IP_TTL, ttl); 
	setReceiveTimeout(Timespan(timeout)); 
} 
 
 
ICMPSocketImpl::~ICMPSocketImpl() 
{ 
} 
 
 
int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int flags) 
{ 
	int n = SocketImpl::sendTo(_icmpPacket.packet(), _icmpPacket.packetSize(), address, flags); 
	return n; 
} 
 
 
int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags) 
{ 
	int maxPacketSize = _icmpPacket.maxPacketSize(); 
	Poco::Buffer<unsigned char> buffer(maxPacketSize); 
 
	try 
	{ 
		Poco::Timestamp ts; 
		do 
		{ 
			if (ts.isElapsed(_timeout)) 
			{ 
				// This guards against a possible DoS attack, where sending 
				// fake ping responses will cause an endless loop. 
				throw TimeoutException(); 
			} 
			SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags); 
		} 
		while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)); 
	} 
	catch (TimeoutException&) 
	{ 
		throw; 
	} 
	catch (Exception&) 
	{ 
		std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize); 
		if (!err.empty()) 
			throw ICMPException(err); 
		else 
			throw; 
	} 
 
	struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize); 
	struct timeval now  = _icmpPacket.time(); 
 
	int elapsed	= (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000; 
 
	return elapsed; 
} 
 
 
} } // namespace Poco::Net