1 /*
2    Copyright 2013-2014 EditShare, 2013-2015 Skytechnology sp. z o.o.
3 
4    This file is part of LizardFS.
5 
6    LizardFS is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, version 3.
9 
10    LizardFS is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with LizardFS. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "common/platform.h"
22 
23 #include <inttypes.h>
24 #include <vector>
25 
26 #include "common/datapack.h"
27 #include "common/massert.h"
28 #include "protocol/packet.h"
29 
30 /*
31  * A class which can be used to read LizardFS commands from a socket
32  */
33 class MessageReceiveBuffer {
34 public:
35 	/*
36 	 * @param size - maximum size of a message to read
37 	 */
MessageReceiveBuffer(size_t size)38 	MessageReceiveBuffer(size_t size) : buffer_(size), bytesReceived_(0) {
39 	}
40 
41 	/*
42 	 * Read some data from a descriptor into the buffer
43 	 */
44 	ssize_t readFrom(int fd);
45 
46 	/*
47 	 * Removes the first message from the buffer
48 	 */
49 	void removeMessage();
50 
51 	/*
52 	 * If this is true, one can access this->getMessageHeader()
53 	 */
hasMessageHeader()54 	bool hasMessageHeader() const {
55 		return bytesReceived_ >= PacketHeader::kSize;
56 	}
57 
58 	/*
59 	 * This is true when the whole message has been read.
60 	 */
hasMessageData()61 	bool hasMessageData() const {
62 		if (!hasMessageHeader()) {
63 			return false;
64 		}
65 		return bytesReceived_ >= PacketHeader::kSize + getMessageHeader().length;
66 	}
67 
68 	/*
69 	 * This is true if the message currently read is bigger than a size of the buffer,
70 	 * making it impossible to read the whole message body.
71 	 */
isMessageTooBig()72 	bool isMessageTooBig() const {
73 		if (!hasMessageHeader()) {
74 			return false;
75 		}
76 		return PacketHeader::kSize + getMessageHeader().length > buffer_.size();
77 	}
78 
getMessageHeader()79 	PacketHeader getMessageHeader() const {
80 		sassert(hasMessageHeader());
81 		PacketHeader header;
82 		deserialize(buffer_, header);
83 		return header;
84 	}
85 
getMessageData()86 	const uint8_t* getMessageData() const {
87 		return buffer_.data() + PacketHeader::kSize;
88 	}
89 
90 private:
91 	std::vector<uint8_t> buffer_;
92 	size_t bytesReceived_;
93 };
94