summaryrefslogtreecommitdiff
path: root/node/PacketDecoder.hpp
blob: 1a713ade125cad1bb19561b8a6d108bfb00dba44 (plain)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * ZeroTier One - Global Peer to Peer Ethernet
 * Copyright (C) 2012-2013  ZeroTier Networks LLC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * --
 *
 * ZeroTier may be used and distributed under the terms of the GPLv3, which
 * are available at: http://www.gnu.org/licenses/gpl-3.0.html
 *
 * If you would like to embed ZeroTier into a commercial application or
 * redistribute it in a modified binary form, please contact ZeroTier Networks
 * LLC. Start here: http://www.zerotier.com/
 */

#ifndef _ZT_PACKETDECODER_HPP
#define _ZT_PACKETDECODER_HPP

#include <stdexcept>

#include "Packet.hpp"
#include "Demarc.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
#include "Peer.hpp"

namespace ZeroTier {

class RuntimeEnvironment;

/**
 * Subclass of packet that handles the decoding of it
 */
class PacketDecoder : public Packet
{
	friend class SharedPtr<PacketDecoder>;

public:
	/**
	 * Create a new packet-in-decode
	 *
	 * @param b Source buffer with raw packet data
	 * @param localPort Local port on which packet was received
	 * @param remoteAddress Address from which packet came
	 * @throws std::out_of_range Range error processing packet
	 */
	template<unsigned int C2>
	PacketDecoder(const Buffer<C2> &b,Demarc::Port localPort,const InetAddress &remoteAddress)
 		throw(std::out_of_range) :
 		Packet(b),
 		_receiveTime(Utils::now()),
 		_localPort(localPort),
 		_remoteAddress(remoteAddress),
 		_step(DECODE_WAITING_FOR_SENDER_LOOKUP),
 		__refCount()
	{
	}

	/**
	 * Attempt to decode this packet
	 *
	 * Note that this returns 'true' if processing is complete. This says nothing
	 * about whether the packet was valid. A rejection is 'complete.'
	 *
	 * Once true is returned, this should not be called again.
	 *
	 * @param _r Runtime environment
	 * @return True if decoding and processing is complete, false if caller should try again
	 * @throws std::out_of_range Range error processing packet (should be discarded)
	 * @throws std::runtime_error Other error processing packet (should be discarded)
	 */
	bool tryDecode(const RuntimeEnvironment *_r)
		throw(std::out_of_range,std::runtime_error);

	/**
	 * @return Time of packet receipt
	 */
	inline uint64_t receiveTime() const throw() { return _receiveTime; }

private:
	struct _CBaddPeerFromHello_Data
	{
		const RuntimeEnvironment *renv;
		Address source;
		InetAddress remoteAddress;
		Demarc::Port localPort;
		unsigned int vMajor,vMinor,vRevision;
		uint64_t helloPacketId;
		uint64_t helloTimestamp;
	};
	static void _CBaddPeerFromHello(
		void *arg, // _CBaddPeerFromHello_Data
		const SharedPtr<Peer> &p,
		Topology::PeerVerifyResult result);

	static void _CBaddPeerFromWhois(
		void *arg, // RuntimeEnvironment
		const SharedPtr<Peer> &p,
		Topology::PeerVerifyResult result);

	// These are called internally to handle packet contents once it has
	// been authenticated, decrypted, decompressed, and classified.
	bool _doERROR(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doHELLO(const RuntimeEnvironment *_r);
	bool _doOK(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doWHOIS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doMULTICAST_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
	bool _doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);

	uint64_t _receiveTime;
	Demarc::Port _localPort;
	InetAddress _remoteAddress;

	enum {
		DECODE_WAITING_FOR_SENDER_LOOKUP, // on initial receipt, we need peer's identity
		DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP,
	} _step;

	AtomicCounter __refCount;
};

} // namespace ZeroTier

#endif