forked from step21/desfire_rfid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Buffer.h
271 lines (218 loc) · 6.88 KB
/
Buffer.h
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/**************************************************************************
@author Elmü
This class is a safe buffer class which prevents buffer overflows.
The design of this class avoids the need for the 'new' operator which would lead to memory fragmentation.
Check for a new version on:
http://www.codeproject.com/Articles/1096861/DIY-electronic-RFID-Door-Lock-with-Battery-Backup
**************************************************************************/
#ifndef BUFFER_H
#define BUFFER_H
#include "Utils.h"
// These macros create a new buffer on the stack avoiding the use of the 'new' operator.
// ATTENTION:
// These macros will not work if you define the TxBuffer/RxBuffer as member of a class (see mi_CmacBuffer).
// They compile only inside the code of a function.
//
// TX_BUFFER(i_SessKey, 16)
// Creates an instance i_SessKey with the size of 16 bytes and is equivalent to:
// byte i_SessKey_Buffer[16];
// TxBuffer i_SessKey(i_SessKey_Buffer, 16);
//
// The byte buffer is created outside the class to avoid the need of a template class which would have several disadvantages.
// The operator "##" tells the preprocessor to concatenate two strings.
#define TX_BUFFER(buffer_name, size) \
byte buffer_name##_Buffer[size]; \
TxBuffer buffer_name(buffer_name##_Buffer, size);
#define RX_BUFFER(buffer_name, size) \
byte buffer_name##_Buffer[size]; \
RxBuffer buffer_name(buffer_name##_Buffer, size);
// This class makes a buffer overflow impossible
class RxBuffer
{
public:
inline RxBuffer(byte* u8_Buffer, int s32_Size)
{
mu8_Buf = u8_Buffer;
ms32_Size = s32_Size;
ms32_Pos = 0;
memset(mu8_Buf, 0, s32_Size);
}
// This allows to shrink the available maximum buffer size, but it does not allow to make the buffer larger.
bool SetSize(int s32_NewSize)
{
ms32_Pos = 0;
if (!CheckPos(s32_NewSize))
return false;
ms32_Size = s32_NewSize;
return true;
}
inline int GetSize()
{
return ms32_Size;
}
inline byte* GetData()
{
return mu8_Buf;
}
inline operator byte*()
{
return mu8_Buf;
}
// reads 1 byte from the buffer and increments the pointer
uint8_t ReadUint8()
{
if (!CheckPos(1)) return 0;
uint8_t u8_Data = mu8_Buf[ms32_Pos];
ms32_Pos += 1;
return u8_Data;
}
// reads 2 bytes from the buffer and increments the pointer
uint16_t ReadUint16()
{
if (!CheckPos(2)) return 0;
uint16_t u16_Data;
memcpy(&u16_Data, mu8_Buf + ms32_Pos, 2);
ms32_Pos += 2;
return u16_Data;
}
// reads 3 bytes from the buffer and increments the pointer
uint32_t ReadUint24()
{
if (!CheckPos(3)) return 0;
uint32_t u32_Data = 0;
memcpy(&u32_Data, mu8_Buf + ms32_Pos, 3); // Copy only the lower 3 bytes
ms32_Pos += 3;
return u32_Data;
}
// reads 4 bytes from the buffer and increments the pointer
uint32_t ReadUint32()
{
if (!CheckPos(4)) return 0;
uint32_t u32_Data;
memcpy(&u32_Data, mu8_Buf + ms32_Pos, 4);
ms32_Pos += 4;
return u32_Data;
}
bool ReadBuf(byte* u8_Buffer, int s32_Count)
{
if (!CheckPos(s32_Count)) return false;
memcpy(u8_Buffer, mu8_Buf + ms32_Pos, s32_Count);
ms32_Pos += s32_Count;
return true;
}
private:
bool CheckPos(int s32_Count)
{
if (ms32_Pos + s32_Count <= ms32_Size)
return true;
Utils::Print("### RxBuffer Overflow ###\r\n");
return false;
}
byte* mu8_Buf;
int ms32_Size;
int ms32_Pos;
};
// ====================================================================================
// This class makes a buffer overflow impossible
class TxBuffer
{
public:
inline TxBuffer(byte* u8_Buffer, int s32_Size)
{
mu8_Buf = u8_Buffer;
ms32_Size = s32_Size;
ms32_Pos = 0;
memset(mu8_Buf, 0, s32_Size);
}
// Resets the byte counter
inline void Clear()
{
ms32_Pos = 0;
}
inline int GetSize()
{
return ms32_Size;
}
// returns the count of bytes that are currently free in the buffer
inline int GetFree()
{
return ms32_Size - ms32_Pos;
}
// returns the count of bytes that are currently occupied in the buffer
inline int GetCount()
{
return ms32_Pos;
}
// ATTENTION: Use this only after encrypting the buffer.
bool SetCount(int s32_Count)
{
ms32_Pos = 0;
if (!CheckPos(s32_Count))
return false;
ms32_Pos = s32_Count;
return true;
}
inline byte* GetData()
{
return mu8_Buf;
}
inline operator byte*()
{
return mu8_Buf;
}
// writes 1 byte to the buffer and increments the pointer
bool AppendUint8(uint8_t u8_Data)
{
if (!CheckPos(1)) return false;
mu8_Buf[ms32_Pos] = u8_Data;
ms32_Pos += 1;
return true;
}
// writes n bytes to the buffer and increments the pointer
bool AppendBuf(const uint8_t* u8_Data, int s32_Count)
{
// u8_Data may be NULL if s32_Count == 0!
if (s32_Count == 0)
return true;
if (!CheckPos(s32_Count)) return false;
memcpy(mu8_Buf + ms32_Pos, u8_Data, s32_Count);
ms32_Pos += s32_Count;
return true;
}
// writes 2 bytes to the buffer and increments the pointer
bool AppendUint16(uint16_t u16_Data)
{
if (!CheckPos(2)) return false;
memcpy(mu8_Buf + ms32_Pos, &u16_Data, 2);
ms32_Pos += 2;
return true;
}
// writes 3 bytes to the buffer and increments the pointer
bool AppendUint24(uint32_t u32_Data)
{
if (!CheckPos(3)) return false;
memcpy(mu8_Buf + ms32_Pos, &u32_Data, 3);
ms32_Pos += 3;
return true;
}
// writes 4 bytes to the buffer and increments the pointer
bool AppendUint32(uint32_t u32_Data)
{
if (!CheckPos(4)) return false;
memcpy(mu8_Buf + ms32_Pos, &u32_Data, 4);
ms32_Pos += 4;
return true;
}
private:
bool CheckPos(int s32_Count)
{
if (ms32_Pos + s32_Count <= ms32_Size)
return true;
Utils::Print("### TxBuffer Overflow ###\r\n");
return false;
}
byte* mu8_Buf;
int ms32_Size;
int ms32_Pos;
};
#endif // BUFFER_H