1:
2:
3: /**********************
4: * *
5: * COMPILER INCLUDES *
6: * *
7: **********************/
8:
9:
10: #include <cassert>
11:
12:
13: /*********************
14: * *
15: * PROJECT INCLUDES *
16: * *
17: *********************/
18:
19:
20: #include "buffer.h"
21: #include "dnsutil.h"
22:
23:
24: using std::memset;
25: using std::memcmp;
26:
27:
28: /***********************
29: * *
30: * BUFFER CONSTRUCTOR *
31: * *
32: ***********************/
33:
34:
35: Buffer::Buffer(size_t i_szBufferMax) {
36: m_szBuffer = 0;
37: m_szBufferMax = i_szBufferMax;
38: m_ucpBuffer = new unsigned char[m_szBufferMax];
39: m_ofPos = 0;
40: memset(m_ucpBuffer,0,m_szBufferMax);
41: }
42:
43:
44: /***********************
45: * *
46: * METHOD FINDINRANGE *
47: * *
48: ***********************/
49:
50:
51: off_t Buffer::FindInRange(off_t i_ofBegin, off_t i_ofEnd, const unsigned char *ci_ucpFind, size_t i_szFind) {
52: off_t i_ofMax = i_ofEnd - i_szFind;
53: while(i_ofBegin<i_ofMax) {
54: if (memcmp(m_ucpBuffer+i_ofBegin,ci_ucpFind,i_szFind)==0) return i_ofBegin;
55: i_ofBegin++;
56: }
57: return i_ofEnd;
58: }
59:
60:
61: /*********************************
62: * *
63: * METHOD FINDPREVIOUSLABELLIST *
64: * *
65: *********************************/
66:
67:
68: off_t Buffer::FindPreviousLabelList(off_t i_ofBegin, off_t i_ofEnd, const unsigned char *ci_ucpFind, size_t i_szFind) {
69: while(i_ofBegin<i_ofEnd) {
70: if (TestLabelList(ci_ucpFind,i_szFind,i_ofBegin)==true) return i_ofBegin;
71: i_ofBegin++;
72: }
73: return i_ofEnd;
74: }
75:
76:
77: /*******************
78: * *
79: * METHOD READBIT *
80: * *
81: *******************/
82:
83:
84: /*
85: * Note that the RFC simply doesn't represent bit values in a fashion that
86: * makes sense to me. It shows:
87: *
88: * 1 1 1 1 1 1
89: * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
90: *
91: * Whereas the sensible values for my purposes are:
92: *
93: * (byte 0)------> (byte 1)------>
94: * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
95: *
96: * Hence, ReadBit/WriteBit use this approach.
97: */
98:
99:
100: bool Buffer::ReadBit(off_t i_off, unsigned char i_ucBit) const {
101: assert(i_off<(off_t)m_szBuffer);
102: unsigned char ucVal = 1;
103: ucVal <<= i_ucBit;
104: if ((m_ucpBuffer[i_off]&ucVal)==ucVal) return true;
105: return false;
106: }
107:
108:
109: /********************
110: * *
111: * METHOD READBITS *
112: * *
113: ********************/
114:
115:
116: void Buffer::ReadBits(bool &o_br7, bool &o_br6, bool &o_br5, bool &o_br4, bool &o_br3, bool &o_br2, bool &o_br1, bool &o_br0) const {
117: unsigned char uc;
118: this->Read(uc);
119: o_br7 = ((uc&128)==128);
120: o_br6 = ((uc&64)==64);
121: o_br5 = ((uc&32)==32);
122: o_br4 = ((uc&16)==16);
123: o_br3 = ((uc&8)==8);
124: o_br2 = ((uc&4)==4);
125: o_br1 = ((uc&2)==2);
126: o_br0 = ((uc&1)==1);
127: }
128:
129:
130: /********************
131: * *
132: * METHOD READDATA *
133: * *
134: ********************/
135:
136:
137: void Buffer::ReadData(void *o_ptrData, size_t i_szData) const {
138: this->ReadData(o_ptrData,i_szData,m_ofPos);
139: }
140:
141:
142: void Buffer::ReadData(void *o_ptrData, size_t i_szData, off_t &io_of) const {
143: assert(o_ptrData!=NULL);
144: //cerr << "ReadData: " << i_szData << " bytes at " << io_off << " of " << m_szBuffer << endl;
145: if (io_of+i_szData>m_szBuffer)
146: throw BufferEx(FOUT("Buffer::ReadData: overflow reading ",i_szData," bytes at ",io_of," (max ",m_szBuffer-1,")"));
147: memcpy(o_ptrData,m_ucpBuffer+io_of,i_szData);
148: /* DEBUG: this->DumpRange(cerr,m_ucpBuffer+io_of,i_szData); */
149: io_of += i_szData;
150: }
151:
152:
153: /*************************
154: * *
155: * METHOD READLABELLIST *
156: * *
157: *************************/
158:
159:
160: void Buffer::ReadLabelList(unsigned char *o_ucpOut, size_t i_szOut, unsigned short &o_usLength, bool i_bUseCompression) const {
161: o_usLength = 0;
162: this->ReadLabelList(o_ucpOut,i_szOut,o_usLength,i_bUseCompression,m_ofPos);
163: }
164:
165:
166:
167: void Buffer::ReadLabelList(unsigned char *o_ucpOut, size_t i_szOut, unsigned short &o_usLength, bool i_bUseCompression, off_t &io_ofrPos) const {
168: unsigned char uc;
169: LogHandle lh(LF_PACKETFORMAT,LY_DEBUG);
170:
171: lh << "LABEL(" << io_ofrPos << "): ";
172: uc = this->Get(io_ofrPos++);
173: while(uc!=0) {
174: if ((uc>=192)&&(i_bUseCompression==true)) {
175: off_t offCache;
176: offCache = uc - 192;
177: offCache <<= 8;
178: offCache += this->Get(io_ofrPos++);
179: // cerr << " J"; // DEBUG
180: return this->ReadLabelList(o_ucpOut,i_szOut,o_usLength,i_bUseCompression,offCache);
181: }
182: if (uc>=64) {
183: lh << "!" << (unsigned)uc << " at " << (io_ofrPos-1) << endl;
184: throw BadParseEx(FOUT("Buffer::ReadLabelList: unexpected high bit at ",io_ofrPos-1));
185: }
186: // STUB: check for overflow
187: *o_ucpOut++ = uc;
188: i_szOut--;
189: this->ReadData(o_ucpOut,uc,io_ofrPos);
190: //for(unsigned char i=0;i<uc;i++) cerr << o_ucpOut[i]; // DEBUG
191: o_ucpOut += uc;
192: i_szOut -= uc;
193: o_usLength += (uc + 1);
194: uc = this->Get(io_ofrPos++);
195: lh << ".";
196: }
197: *o_ucpOut = 0;
198: i_szOut--;
199: o_usLength++;
200: }
201:
202:
203: void Buffer::ReadLabelList(LabelListPtr &o_llpr, bool i_bUseCompression) const {
204: unsigned char uca[256];
205: unsigned short us;
206: this->ReadLabelList(uca,255,us,i_bUseCompression);
207: o_llpr = new LabelList(uca);
208: }
209:
210:
211: /*************************
212: * *
213: * METHOD TESTLABELLIST *
214: * *
215: *************************/
216:
217:
218: bool Buffer::TestLabelList(const unsigned char *i_ucpLabels, size_t i_szLabels, off_t i_ofPos) {
219: unsigned short us;
220: while(1) {
221: //cerr << "TestLabelList: " << i_ofPos << endl;
222: if ((*i_ucpLabels==0)&&(m_ucpBuffer[i_ofPos]==0)) return true;
223: if (m_ucpBuffer[i_ofPos]>=192) {
224: this->PReadNBO(us,i_ofPos);
225: us -= 0xC000;
226: if(us>=i_ofPos) return false;
227: return this->TestLabelList(i_ucpLabels,i_szLabels,us);
228: }
229: if (*i_ucpLabels != m_ucpBuffer[i_ofPos]) return false;
230: if (MemCaseCmp((const char*)i_ucpLabels+1,(const char*)m_ucpBuffer+i_ofPos+1,*i_ucpLabels)!=0) return false;
231: i_ucpLabels += (*i_ucpLabels + 1);
232: i_ofPos += (m_ucpBuffer[i_ofPos] + 1);
233: }
234: }
235:
236:
237:
238: /**************************
239: * *
240: * METHOD TRYCOMPRESSION *
241: * *
242: **************************/
243:
244:
245: // INFO: this compression technique causes a TC if there isn't enough room to write
246: // the uncompressed label, but there is enough room w/compression. I prefer this
247: // approach, because the extra copy is not worth it for such a rare case.
248:
249: void Buffer::TryCompression(off_t i_ofStart) {
250: assert(i_ofStart<=m_ofPos);
251: unsigned short usPrev;
252: size_t sz = size_t(m_ofPos - i_ofStart);
253:
254: while(sz>3) {
255: //cerr << "TryCompression: " << i_ofStart << " - " << m_ofPos << " (" << sz << ")" << endl;
256: usPrev = this->FindPreviousLabelList(12,i_ofStart,m_ucpBuffer+i_ofStart,sz);
257: if (usPrev!=i_ofStart) {
258: //cerr << "TryCompression: success " << i_ofStart << " to " << usPrev << endl;
259: usPrev += 0xC000;
260: this->SetPos(i_ofStart);
261: this->WriteNBO(usPrev);
262: return;
263: }
264: i_ofStart += (this->Get(i_ofStart) + 1);
265: sz = size_t(m_ofPos - i_ofStart);
266: }
267: //cerr << "TryCompression: no" << endl;
268: }
269:
270:
271: /********************
272: * *
273: * METHOD WRITEBIT *
274: * *
275: ********************/
276:
277:
278: void Buffer::WriteBit(bool i_bBit, off_t i_off, unsigned char i_ucBit) {
279: assert(i_off<(off_t)m_szBuffer);
280: unsigned char ucVal = (1 << i_ucBit);
281: if (i_bBit==false) {
282: ucVal = 255 - ucVal;
283: m_ucpBuffer[i_off] &= ucVal;
284: } else {
285: m_ucpBuffer[i_off] |= ucVal;
286: }
287: }
288:
289:
290: /*********************
291: * *
292: * METHOD WRITEBITS *
293: * *
294: *********************/
295:
296:
297: void Buffer::WriteBits(bool i_b7, bool i_b6, bool i_b5, bool i_b4, bool i_b3, bool i_b2, bool i_b1, bool i_b0) {
298: unsigned char uc = FromBits(i_b7,i_b6,i_b5,i_b4,i_b3,i_b2,i_b1,i_b0);
299: this->Write(uc);
300: }
301:
302:
303: /**********************
304: * *
305: * METHODS WRITEDATA *
306: * *
307: **********************/
308:
309:
310: void Buffer::WriteData(const void *i_ptrData, size_t i_szData) {
311: this->WriteData(i_ptrData,i_szData,m_ofPos);
312: m_ofPos += i_szData;
313: }
314:
315:
316: void Buffer::WriteData(const void *i_ptrData, size_t i_szData, off_t i_of) {
317: //cerr << "Writing " << i_szData << " bytes at " << i_of << "/" << m_szBufferMax << endl;
318: if ((i_of+i_szData) > m_szBufferMax)
319: throw BufferEx(FOUT("Buffer::WriteData: buffer overflow writing ",i_szData," bytes at ",i_of," (max ",m_szBufferMax-1,")"));
320: memcpy(m_ucpBuffer+i_of,i_ptrData,i_szData);
321: /* DEBUG:
322: HexDump(cerr,m_ucpBuffer+i_of,i_szData);
323: cerr << endl; */
324: if (m_szBuffer<(size_t)(i_of+i_szData)) m_szBuffer = (size_t)i_of + i_szData;
325: }
326:
327:
328: /**************************
329: * *
330: * METHOD WRITELABELLIST *
331: * *
332: **************************/
333:
334:
335: unsigned short Buffer::WriteLabelList(LabelListConstPtr ci_llp, bool i_bUseCompression) {
336: LabelList::const_iterator lni;
337: off_t ofStart = m_ofPos;
338:
339: for(lni=ci_llp->begin();lni!=ci_llp->end();++lni) {
340: assert((*lni).GetLength()<64);
341: this->Write((unsigned char)(*lni).GetLength());
342: this->WriteData( (*lni).GetString(), (*lni).GetLength());
343: }
344: this->Write((unsigned char)0);
345: this->TryCompression(ofStart);
346: return (unsigned short)(m_ofPos-ofStart);
347: }
348:
349:
350: /**********************
351: * *
352: * BUFFER DESTRUCTOR *
353: * *
354: **********************/
355:
356:
357: Buffer::~Buffer() {
358: SoftDeleteArray(m_ucpBuffer);
359: m_szBuffer = 0;
360: m_szBufferMax = 0;
361: }
362:
363:
364: /****************
365: * *
366: * OPERATOR << *
367: * *
368: ****************/
369:
370:
371: ostream& operator<<(ostream &io_smr, const Buffer &ci_bfr) {
372: ci_bfr.DumpRange(io_smr,0,ci_bfr.GetSize());
373: io_smr << std::endl;
374: return io_smr;
375: }
376:
377:
378: ostream& operator<<(ostream &io_smr, BufferConstPtr ci_bfp) {
379: io_smr << *ci_bfp;
380: return io_smr;
381: }
382:
383: