summaryrefslogtreecommitdiff
path: root/lib/server/Protocol.h
blob: e037e33c10f2d4a7636d0f277e61a054622e931a (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// --------------------------------------------------------------------------
//
// File
//		Name:    Protocol.h
//		Purpose: Generic protocol support
//		Created: 2003/08/19
//
// --------------------------------------------------------------------------

#ifndef PROTOCOL__H
#define PROTOCOL__H

#include <sys/types.h>

class IOStream;
#include "ProtocolObject.h"
#include <memory>
#include <vector>
#include <string>

// default timeout is 15 minutes
#define PROTOCOL_DEFAULT_TIMEOUT	(15*60*1000)
// 16 default maximum object size -- should be enough
#define PROTOCOL_DEFAULT_MAXOBJSIZE	(16*1024)

// --------------------------------------------------------------------------
//
// Class
//		Name:    Protocol
//		Purpose: Generic command / response protocol support
//		Created: 2003/08/19
//
// --------------------------------------------------------------------------
class Protocol
{
public:
	Protocol(IOStream &rStream);
	virtual ~Protocol();
	
private:
	Protocol(const Protocol &rToCopy);

public:
	void Handshake();
	std::auto_ptr<ProtocolObject> Receive();
	void Send(const ProtocolObject &rObject);
	
	std::auto_ptr<IOStream> ReceiveStream();
	void SendStream(IOStream &rStream);
	
	enum
	{
		NoError = -1,
		UnknownError = 0
	};

	bool GetLastError(int &rTypeOut, int &rSubTypeOut);

	// --------------------------------------------------------------------------
	//
	// Function
	//		Name:    Protocol::SetTimeout(int)
	//		Purpose: Sets the timeout for sending and reciving
	//		Created: 2003/08/19
	//
	// --------------------------------------------------------------------------	
	void SetTimeout(int NewTimeout) {mTimeout = NewTimeout;}
	
	
	// --------------------------------------------------------------------------
	//
	// Function
	//		Name:    Protocol::GetTimeout() 
	//		Purpose: Get current timeout for sending and receiving
	//		Created: 2003/09/06
	//
	// --------------------------------------------------------------------------
	int GetTimeout() {return mTimeout;}

	// --------------------------------------------------------------------------
	//
	// Function
	//		Name:    Protocol::SetMaxObjectSize(int)
	//		Purpose: Sets the maximum size of an object which will be accepted
	//		Created: 2003/08/19
	//
	// --------------------------------------------------------------------------	
	void SetMaxObjectSize(unsigned int NewMaxObjSize) {mMaxObjectSize = NewMaxObjSize;}

	// For ProtocolObject derived classes
	void Read(void *Buffer, int Size);
	void Read(std::string &rOut, int Size);
	void Read(int64_t &rOut);
	void Read(int32_t &rOut);
	void Read(int16_t &rOut);
	void Read(int8_t &rOut);
	void Read(bool &rOut) {int8_t read; Read(read); rOut = (read == true);}
	void Read(std::string &rOut);
	template<typename type>
	void Read(type &rOut)
	{
		rOut.ReadFromProtocol(*this);
	}
	// --------------------------------------------------------------------------
	//
	// Function
	//		Name:    Protocol::ReadVector(std::vector<> &)
	//		Purpose: Reads a vector/list of items from the stream
	//		Created: 2003/08/19
	//
	// --------------------------------------------------------------------------
	template<typename type>
	void ReadVector(std::vector<type> &rOut)
	{
		rOut.clear();
		int16_t num = 0;
		Read(num);
		for(int16_t n = 0; n < num; ++n)
		{
			type v;
			Read(v);
			rOut.push_back(v);
		}
	}
	
	void Write(const void *Buffer, int Size);
	void Write(int64_t Value);
	void Write(int32_t Value);
	void Write(int16_t Value);
	void Write(int8_t Value);
	void Write(bool Value) {int8_t write = Value; Write(write);}
	void Write(const std::string &rValue);
	template<typename type>
	void Write(const type &rValue)
	{
		rValue.WriteToProtocol(*this);
	}
	template<typename type>
	// --------------------------------------------------------------------------
	//
	// Function
	//		Name:    Protocol::WriteVector(const std::vector<> &)
	//		Purpose: Writes a vector/list of items from the stream
	//		Created: 2003/08/19
	//
	// --------------------------------------------------------------------------
	void WriteVector(const std::vector<type> &rValue)
	{
		int16_t num = rValue.size();
		Write(num);
		for(int16_t n = 0; n < num; ++n)
		{
			Write(rValue[n]);
		}
	}

public:
	static const uint16_t sProtocolStreamHeaderLengths[256];
	enum
	{
		ProtocolStreamHeader_EndOfStream = 0,
		ProtocolStreamHeader_MaxEncodedSizeValue = 252,
		ProtocolStreamHeader_SizeIs64k = 253,
		ProtocolStreamHeader_Reserved1 = 254,
		ProtocolStreamHeader_Reserved2 = 255
	};
	enum
	{
		ProtocolStream_SizeUncertain = 0xffffffff
	};

protected:	
	virtual std::auto_ptr<ProtocolObject> MakeProtocolObject(int ObjType) = 0;
	virtual const char *GetIdentString() = 0;
	void SetError(int Type, int SubType) {mLastErrorType = Type; mLastErrorSubType = SubType;}
	void CheckAndReadHdr(void *hdr);	// don't use type here to avoid dependency
	
	// Will be used for logging
	virtual void InformStreamReceiving(u_int32_t Size);
	virtual void InformStreamSending(u_int32_t Size);
	
private:
	void EnsureBufferAllocated(int Size);
	int SendStreamSendBlock(uint8_t *Block, int BytesInBlock);

private:
	IOStream &mrStream;
	bool mHandshakeDone;
	unsigned int mMaxObjectSize;
	int mTimeout;
	char *mpBuffer;
	int mBufferSize;
	int mReadOffset;
	int mWriteOffset;
	int mValidDataSize;
	int mLastErrorType;
	int mLastErrorSubType;
};

#endif // PROTOCOL__H