| 
									
										
										
										
											2018-11-03 05:43:00 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  packet_buffer.h                                                      */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2018-11-03 05:43:00 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef PACKET_BUFFER_H
 | 
					
						
							|  |  |  | #define PACKET_BUFFER_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "core/os/copymem.h"
 | 
					
						
							|  |  |  | #include "core/ring_buffer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T> | 
					
						
							|  |  |  | class PacketBuffer { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 	typedef struct { | 
					
						
							|  |  |  | 		uint32_t size; | 
					
						
							|  |  |  | 		T info; | 
					
						
							|  |  |  | 	} _Packet; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	RingBuffer<_Packet> _packets; | 
					
						
							|  |  |  | 	RingBuffer<uint8_t> _payload; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	Error write_packet(const uint8_t *p_payload, uint32_t p_size, const T *p_info) { | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | 		// Verbose buffer warnings
 | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 		if (p_payload && _payload.space_left() < (int32_t)p_size) { | 
					
						
							| 
									
										
										
										
											2018-11-03 05:43:00 +01:00
										 |  |  | 			ERR_PRINT("Buffer payload full! Dropping data."); | 
					
						
							|  |  |  | 			ERR_FAIL_V(ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (p_info && _packets.space_left() < 1) { | 
					
						
							|  |  |  | 			ERR_PRINT("Too many packets in queue! Dropping data."); | 
					
						
							|  |  |  | 			ERR_FAIL_V(ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-02-27 10:07:30 +01:00
										 |  |  | 		ERR_FAIL_COND_V(p_payload && (uint32_t)_payload.space_left() < p_size, ERR_OUT_OF_MEMORY); | 
					
						
							| 
									
										
										
										
											2018-11-03 05:43:00 +01:00
										 |  |  | 		ERR_FAIL_COND_V(p_info && _packets.space_left() < 1, ERR_OUT_OF_MEMORY); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If p_info is NULL, only the payload is written
 | 
					
						
							|  |  |  | 		if (p_info) { | 
					
						
							|  |  |  | 			_Packet p; | 
					
						
							|  |  |  | 			p.size = p_size; | 
					
						
							|  |  |  | 			copymem(&p.info, p_info, sizeof(T)); | 
					
						
							|  |  |  | 			_packets.write(p); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If p_payload is NULL, only the packet information is written.
 | 
					
						
							|  |  |  | 		if (p_payload) { | 
					
						
							|  |  |  | 			_payload.write((const uint8_t *)p_payload, p_size); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Error read_packet(uint8_t *r_payload, int p_bytes, T *r_info, int &r_read) { | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(_packets.data_left() < 1, ERR_UNAVAILABLE); | 
					
						
							|  |  |  | 		_Packet p; | 
					
						
							|  |  |  | 		_packets.read(&p, 1); | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 		ERR_FAIL_COND_V(_payload.data_left() < (int)p.size, ERR_BUG); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(p_bytes < (int)p.size, ERR_OUT_OF_MEMORY); | 
					
						
							| 
									
										
										
										
											2018-11-03 05:43:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		r_read = p.size; | 
					
						
							|  |  |  | 		copymem(r_info, &p.info, sizeof(T)); | 
					
						
							|  |  |  | 		_payload.read(r_payload, p.size); | 
					
						
							|  |  |  | 		return OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void discard_payload(int p_size) { | 
					
						
							|  |  |  | 		_packets.decrease_write(p_size); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void resize(int p_pkt_shift, int p_buf_shift) { | 
					
						
							|  |  |  | 		_packets.resize(p_pkt_shift); | 
					
						
							|  |  |  | 		_payload.resize(p_buf_shift); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int packets_left() const { | 
					
						
							|  |  |  | 		return _packets.data_left(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void clear() { | 
					
						
							|  |  |  | 		_payload.resize(0); | 
					
						
							|  |  |  | 		_packets.resize(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PacketBuffer() { | 
					
						
							|  |  |  | 		clear(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~PacketBuffer() { | 
					
						
							|  |  |  | 		clear(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // PACKET_BUFFER_H
 |