| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of PortaPack. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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 2, 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; see the file COPYING.  If not, write to | 
					
						
							|  |  |  |  * the Free Software Foundation, Inc., 51 Franklin Street, | 
					
						
							|  |  |  |  * Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __PACKET_BUILDER_H__
 | 
					
						
							|  |  |  | #define __PACKET_BUILDER_H__
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <cstdint>
 | 
					
						
							|  |  |  | #include <cstddef>
 | 
					
						
							|  |  |  | #include <bitset>
 | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | #include <functional>
 | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | #include "bit_pattern.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | #include "packet.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-09-26 14:15:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-16 10:33:50 -08:00
										 |  |  | struct NeverMatch { | 
					
						
							|  |  |  | 	bool operator()(const BitHistory&, const size_t) const { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct FixedLength { | 
					
						
							|  |  |  | 	bool operator()(const BitHistory&, const size_t symbols_received) const { | 
					
						
							|  |  |  | 		return symbols_received >= length; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const size_t length; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | template<typename PreambleMatcher, typename UnstuffMatcher, typename EndMatcher> | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | class PacketBuilder { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 	using PayloadHandlerFunc = std::function<void(const ::Packet& packet)>; | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	PacketBuilder( | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 		const PreambleMatcher preamble_matcher, | 
					
						
							|  |  |  | 		const UnstuffMatcher unstuff_matcher, | 
					
						
							|  |  |  | 		const EndMatcher end_matcher, | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | 		const PayloadHandlerFunc payload_handler | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 	) : payload_handler { payload_handler }, | 
					
						
							|  |  |  | 		preamble(preamble_matcher), | 
					
						
							|  |  |  | 		unstuff(unstuff_matcher), | 
					
						
							|  |  |  | 		end(end_matcher) | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 14:37:59 -07:00
										 |  |  | 	void configure( | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 		const PreambleMatcher preamble_matcher, | 
					
						
							|  |  |  | 		const UnstuffMatcher unstuff_matcher | 
					
						
							|  |  |  | 	) { | 
					
						
							|  |  |  | 		preamble = preamble_matcher; | 
					
						
							|  |  |  | 		unstuff = unstuff_matcher; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		reset_state(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	void execute( | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | 		const uint_fast8_t symbol | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 		bit_history.add(symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 		switch(state) { | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 		case State::Preamble: | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 			if( preamble(bit_history, packet.size()) ) { | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 				state = State::Payload; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case State::Payload: | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 			if( !unstuff(bit_history, packet.size()) ) { | 
					
						
							|  |  |  | 				packet.add(symbol); | 
					
						
							| 
									
										
										
										
											2015-09-28 12:36:04 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 			if( end(bit_history, packet.size()) ) { | 
					
						
							|  |  |  | 				payload_handler(packet); | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 				reset_state(); | 
					
						
							| 
									
										
										
										
											2015-10-02 22:54:59 -07:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				if( packet_truncated() ) { | 
					
						
							|  |  |  | 					reset_state(); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			reset_state(); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 	enum State { | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 		Preamble, | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 		Payload, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 	bool packet_truncated() const { | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 		return packet.size() >= packet.capacity(); | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 12:46:44 -07:00
										 |  |  | 	const PayloadHandlerFunc payload_handler; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 	BitHistory bit_history; | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 	PreambleMatcher preamble; | 
					
						
							|  |  |  | 	UnstuffMatcher unstuff; | 
					
						
							|  |  |  | 	EndMatcher end; | 
					
						
							| 
									
										
										
										
											2015-09-28 12:05:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	State state { State::Preamble }; | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 	::Packet packet; | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 	void reset_state() { | 
					
						
							| 
									
										
										
										
											2015-12-07 12:35:05 -08:00
										 |  |  | 		packet.clear(); | 
					
						
							| 
									
										
										
										
											2015-11-09 14:38:09 -08:00
										 |  |  | 		state = State::Preamble; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-08 08:39:24 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif/*__PACKET_BUILDER_H__*/
 |