1 /*
2  * common/PacketReader.hpp
3  *
4  * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity.
5  *
6  * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau
7  *
8  * Leges Motus is free and open source software.  You may redistribute it and/or
9  * modify it under the terms of version 2, or (at your option) version 3, of the
10  * GNU General Public License (GPL), as published by the Free Software Foundation.
11  *
12  * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY
13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14  * PARTICULAR PURPOSE.  See the full text of the GNU General Public License for
15  * further detail.
16  *
17  * For a full copy of the GNU General Public License, please see the COPYING file
18  * in the root of the source code tree.  You may also retrieve a copy from
19  * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the
20  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307  USA
22  *
23  */
24 
25 #ifndef LM_COMMON_PACKETREADER_HPP
26 #define LM_COMMON_PACKETREADER_HPP
27 
28 #include "network.hpp"
29 #include "PacketHeader.hpp"
30 #include "StringTokenizer.hpp"
31 #include <string>
32 #include <stdint.h>
33 #include <iosfwd>
34 #include <algorithm>
35 
36 namespace LM {
37 	class UDPPacket;
38 
39 	/*
40 	 * The packet reader provides a convenient inteface for reading fields from packets.
41 	 * You can access the packet type and packet ID at any time,
42 	 * and read fields sequentially from the packet using the >> operator.
43 	 *
44 	 * Example:
45 	 * 	PacketReader	reader("4\f15123512\f5\fB\fCover me, I'm going for the gate!");
46 	 * 	reader.packet_type();	// Would return 4
47 	 * 	reader.packet_id();	// Would return 15123512
48 	 *
49 	 * 	int		sender_id;
50 	 * 	std::string	recipient_id;
51 	 * 	std::string	message_text;
52 	 * 	reader >> sender_id >> recipient_id >> message_text;
53 	 *
54 	 *	// sender_id is now 5
55 	 *	// recipient_id is now "B"
56 	 *	// message_text is now "Cover me, I'm going for the gate!"
57 	 */
58 
59 	class PacketReader : public StringTokenizer {
60 	private:
61 		PacketHeader	m_header;
62 
63 	public:
64 		// Construct a packet reader from the given raw packet data
65 		explicit PacketReader(const char* packet_data, char separator =PACKET_FIELD_SEPARATOR);
66 		explicit PacketReader(const UDPPacket& packet);
67 
68 		// Get the packet type and sequence NO at any time:
packet_type() const69 		uint32_t	packet_type() const { return m_header.packet_type; }
sequence_no() const70 		uint64_t	sequence_no() const { return m_header.sequence_no; }
connection_id() const71 		uint32_t	connection_id() const { return m_header.connection_id; }
72 
73 		// Import operations from the base class:
74 		using StringTokenizer::discard_next;
75 		using StringTokenizer::get_rest;
76 		using StringTokenizer::operator>>;
77 		using StringTokenizer::has_more;
78 
79 		// To test whether there are any tokens left for processing
operator !() const80 		bool		operator! () const { return !has_more(); }
operator const void*() const81 				operator const void* () const { return has_more() ? this : NULL; }
82 
83 		void		swap(PacketReader& other);
84 	};
85 
86 	// Write the remaining un-processed raw packet data to an output stream:
87 	std::ostream&	operator<<(std::ostream& out, const PacketReader& packet_reader);
88 }
89 
90 namespace std {
swap(LM::PacketReader & x,LM::PacketReader & y)91 	template<> inline void swap (LM::PacketReader& x, LM::PacketReader& y) { x.swap(y); }
92 }
93 
94 #endif
95