Click
Loading...
Searching...
No Matches
flowbuffer.hh
1/*
2 * flowbuffer.hh - Class used to buffer the packets of a flow in order to be able to
3 * search, replace or remove data in them as in a contiguous flow.
4 * This file also declares the iterators used to achieve this goal.
5 *
6 * Romain Gaillard.
7 */
8
9#ifndef MIDDLEBOX_FLOWBUFFER_HH
10#define MIDDLEBOX_FLOWBUFFER_HH
11
12#include <clicknet/tcp.h>
13#include "memorypool.hh"
14#include <click/packet.hh>
15
16CLICK_DECLS
17
18class CTXElement;
19
20struct flowBufferEntry
21{
22 WritablePacket *packet;
23 struct flowBufferEntry *prev;
24 struct flowBufferEntry *next;
25};
26
28class FlowBufferChunkIter;
29class FlowBufferIter;
30class CTXElement;
31struct fcb;
32
40{
41public:
42 friend class FlowBufferIter;
43
47 FlowBuffer();
48
52
57
61 void enqueue(Packet *packet);
62
66 Packet* dequeue();
67
72
77
81 int getSize();
82
87
92
100 int searchInFlow(const char *pattern);
101
110 int removeInFlow(const char* pattern, const int pattern_length, CTXElement* remove);
111
121 int replaceInFlow(FlowBufferContentIter pos, const int pattern_length, const char *replacement, const int replacement_length, const bool repeat, CTXElement* owner);
122
126 FlowBufferContentIter contentBegin(int posInFirstPacket = 0);
127
132
133
137 void enqueueAll(PacketBatch* batch);
138
139
140 FlowBufferContentIter enqueueAllIter(PacketBatch* batch);
141 FlowBufferChunkIter enqueueAllChunkIter(PacketBatch* batch);
142
151 FlowBufferContentIter search(FlowBufferContentIter start, const char* pattern, int *feedback);
152 FlowBufferContentIter isearch(FlowBufferContentIter start, const char* pattern, int *feedback);
153 FlowBufferContentIter searchSSE(FlowBufferContentIter start, const char* pattern, const int pattern_length, int *feedback);
154
160 void remove(const FlowBufferContentIter start, uint32_t length, CTXElement* owner);
161
162
163private:
164 inline bool isInitialized() {
165 return head != 0;
166 }
167
168
169
170 PacketBatch *head;
171};
172
177{
178public:
183 inline FlowBufferIter(FlowBuffer *_flowBuffer, Packet* _entry);
184
189 inline bool operator==(const FlowBufferIter& other) const;
190
195 inline bool operator!=(const FlowBufferIter& other) const;
196
200 inline WritablePacket*& operator*();
201
205 inline FlowBufferIter& operator++();
206
207private:
208 FlowBuffer *flowBuffer;
209 WritablePacket* entry; // Current entry
210};
211
216{
217public:
218 friend class FlowBuffer;
219
220 inline FlowBufferContentIter() {}; //Invalid placeholder
221
226 inline FlowBufferContentIter(FlowBuffer *_flowBuffer, Packet* packet, int posInFirstPacket=0);
227
232 inline bool operator==(const FlowBufferContentIter& other) const;
233
238 inline bool operator!=(const FlowBufferContentIter& other) const;
239
243 inline unsigned char& operator*();
244
248 inline unsigned char* get_ptr();
249
254
258 inline FlowBufferContentIter& operator+=(int p);
259
260 inline operator bool() const {
261 return entry != 0;
262 }
263
267 inline PacketBatch* flush();
268
269 inline Packet* current() {
270 return entry;
271 }
272
273 inline bool lastChunk() {
274 return entry->next() == 0;
275 }
276
277 inline void moveToNextChunk() {
278 entry = entry->next();
279 offsetInPacket = 0;
280 }
281
282 inline int leftInChunk() {
283 if (!entry)
284 return 0;
285 return entry->length() - (entry->getContentOffset() + offsetInPacket);
286 }
287
288 void print_ascii() {
289 FlowBufferContentIter n = *this;
290 while (n) {
291 char buf[n.leftInChunk() + 1];
292 memcpy(buf, n.get_ptr(), n.leftInChunk());
293 buf[n.leftInChunk()] = '\0';
294 click_chatter("'%s'",buf);
295 n.moveToNextChunk();
296 }
297
298 }
299
300private:
305 void repair();
306
307 FlowBuffer *flowBuffer;
308 Packet* entry;
309 uint32_t offsetInPacket; // Current offset in the current packet content
310};
311
312class Chunk { public:
313 const unsigned char* bytes;
314 const unsigned length;
315};
316
320class FlowBufferChunkIter
321{
322public:
323 friend class FlowBuffer;
324
329 inline FlowBufferChunkIter(FlowBuffer *_flowBuffer, Packet* packet);
330
335 inline bool operator==(const FlowBufferChunkIter& other) const;
336
341 inline bool operator!=(const FlowBufferChunkIter& other) const;
342
346 inline Chunk operator*();
347
351 inline FlowBufferChunkIter& operator++();
352
353 inline operator bool() const {
354 return entry != 0;
355 }
356
360 inline PacketBatch* flush();
361
362 inline Packet* current() {
363 return entry;
364 }
365
366private:
367
368 FlowBuffer *flowBuffer;
369 Packet* entry;
370};
371
372
373// FlowBuffer Iterator
375 Packet* _entry) : flowBuffer(_flowBuffer)
376{
377 entry = static_cast<WritablePacket*>(_entry);
378}
379
381{
382 assert(entry != NULL);
383
384 return entry;
385}
386
388{
389 assert(entry != NULL);
390
391 entry = static_cast<WritablePacket*>(entry->next());
392
393 return *this;
394}
395
396
397inline bool FlowBufferIter::operator==(const FlowBufferIter& other) const
398{
399 if(this->flowBuffer != other.flowBuffer)
400 return false;
401
402 if(this->entry == NULL && other.entry == NULL)
403 return true;
404
405 if(this->entry != other.entry)
406 return false;
407
408 return true;
409}
410
411inline bool FlowBufferIter::operator!=(const FlowBufferIter& other) const
412{
413 return !(*this == other);
414}
415
416// FlowBufferContent Iterator
417inline FlowBufferContentIter::FlowBufferContentIter(FlowBuffer *_flowBuffer,
418 Packet* _entry, int posInFirstPacket) : flowBuffer(_flowBuffer), entry(_entry), offsetInPacket(posInFirstPacket)
419{
420 //The offset at first start must be valid
421 while (entry && entry->getContentOffset() + offsetInPacket >=
422 entry->length())
423 {
424 offsetInPacket = 0;
425 entry = entry->next();
426 }
427}
428
430{
431 if(this->flowBuffer != other.flowBuffer)
432 return false;
433
434 if(this->entry == NULL && other.entry == NULL)
435 return true;
436
437 if(this->entry != other.entry)
438 return false;
439
440 if(this->offsetInPacket != other.offsetInPacket)
441 return false;
442
443 return true;
444}
445
447{
448 return !(*this == other);
449}
450
451inline unsigned char& FlowBufferContentIter::operator*()
452{
453 unsigned char* content = static_cast<WritablePacket*>(entry)->getPacketContent();
454
455 return *(content + offsetInPacket);
456}
457
458
459inline unsigned char* FlowBufferContentIter::get_ptr()
460{
461 unsigned char* content = static_cast<WritablePacket*>(entry)->getPacketContent();
462
463 return content + offsetInPacket;
464}
465
466
468{
469 assert(entry != NULL);
470
471 offsetInPacket++;
472
473 // Check if we are at the end of the packet and must therefore switch to
474 // the next one. We may have multiple empty packet
475 while (entry && entry->getContentOffset() + offsetInPacket >=
476 entry->length())
477 {
478 offsetInPacket = 0;
479 entry = entry->next();
480 }
481
482 return *this;
483}
484
486{
487 assert(entry != NULL);
488
489 while (entry->getContentOffset() + offsetInPacket + p >= entry->length()) {
490 p -= entry->length() - entry->getContentOffset() + offsetInPacket; //Remove from p what was left in packet
491 offsetInPacket = 0;
492 entry = entry->next();
493 if (!entry)
494 return *this;
495 }
496
497 offsetInPacket += p;
498
499 return *this;
500}
501
502
504 if (entry == 0) {
505 return this->flowBuffer->dequeueAll();
506 } else {
507
508 return this->flowBuffer->dequeueUpTo(entry);
509 }
510}
511
512
513//FlowBufferChunkIter
514inline FlowBufferChunkIter::FlowBufferChunkIter(FlowBuffer *_flowBuffer,
515 Packet* _entry) : flowBuffer(_flowBuffer), entry(_entry)
516{
517 //The offset at first start must be valid
518 while (entry && entry->getContentOffset() == entry->length())
519 {
520 entry = entry->next();
521 }
522}
523
524inline bool FlowBufferChunkIter::operator==(const FlowBufferChunkIter& other) const
525{
526 if(this->flowBuffer != other.flowBuffer)
527 return false;
528
529 if(this->entry == NULL && other.entry == NULL)
530 return true;
531
532 if(this->entry != other.entry)
533 return false;
534
535 return true;
536}
537
538inline bool FlowBufferChunkIter::operator!=(const FlowBufferChunkIter& other) const
539{
540 return !(*this == other);
541}
542
543inline Chunk FlowBufferChunkIter::operator*()
544{
545 assert(entry != NULL);
546
547 WritablePacket* wp = static_cast<WritablePacket*>(entry);
548 int off = wp->getContentOffset();
549 unsigned char* content = wp->data() + off;
550
551 return Chunk{content, wp->length() - off};
552}
553
554
555inline FlowBufferChunkIter& FlowBufferChunkIter::operator++()
556{
557 assert(entry != NULL);
558
559 entry = entry->next();
560 //Advance while the entry have no content
561 while (entry && entry->getContentOffset() == entry->length())
562 {
563 entry = entry->next();
564 }
565
566 return *this;
567}
568
569
570inline PacketBatch* FlowBufferChunkIter::flush() {
571 if (entry == 0) {
572 return this->flowBuffer->dequeueAll();
573 } else {
574
575 return this->flowBuffer->dequeueUpTo(entry);
576 }
577}
578
579
580CLICK_ENDDECLS
581
582#endif
This iterator allows to iterate the content in the buffer seamlessly accross the packets.
Definition flowbuffer.hh:216
FlowBufferContentIter & operator++()
Move the iterator to the next byte in the buffer.
Definition flowbuffer.hh:467
PacketBatch * flush()
Definition flowbuffer.hh:503
FlowBufferContentIter & operator+=(int p)
Move the iterator to the next N bytes in the buffer.
Definition flowbuffer.hh:485
unsigned char * get_ptr()
Return the byte to which this iterator points.
Definition flowbuffer.hh:459
bool operator!=(const FlowBufferContentIter &other) const
Compare two FlowBufferContentIter.
Definition flowbuffer.hh:446
bool operator==(const FlowBufferContentIter &other) const
Compare two FlowBufferContentIter.
Definition flowbuffer.hh:429
unsigned char & operator*()
Return the byte to which this iterator points.
Definition flowbuffer.hh:451
This buffer allows to search, replace or remove data in the packets buffered as in a contiguous flow....
Definition flowbuffer.hh:40
FlowBufferContentIter search(FlowBufferContentIter start, const char *pattern, int *feedback)
Search a pattern in the buffer.
Definition flowbuffer.cc:301
int getSize()
Return the size of the buffer.
Definition flowbuffer.cc:127
FlowBuffer()
Construct a FlowBuffer The FlowBuffer must be initialized.
Definition flowbuffer.cc:19
int removeInFlow(const char *pattern, const int pattern_length, CTXElement *remove)
Remove a pattern in the buffer.
Definition flowbuffer.cc:348
FlowBufferContentIter contentBegin(int posInFirstPacket=0)
Return a content iterator pointing to the first byte of content in the buffer.
Definition flowbuffer.cc:78
FlowBufferContentIter contentEnd()
Return a content iterator pointing after the end of the content in the buffer.
Definition flowbuffer.cc:83
void remove(const FlowBufferContentIter start, uint32_t length, CTXElement *owner)
Remove data in the flow (across the packets)
Definition flowbuffer.cc:361
FlowBufferIter end()
Return an iterator pointing to the end of the buffer.
Definition flowbuffer.cc:169
Packet * dequeue()
Dequeue a packet from the beginning of the buffer @returnt The dequeued packet.
Definition flowbuffer.cc:100
void enqueue(Packet *packet)
Enqueue a packet at the end of the buffer.
Definition flowbuffer.cc:67
~FlowBuffer()
Destruct a FlowBuffer.
Definition flowbuffer.cc:27
PacketBatch * dequeueUpTo(Packet *)
Dequeue packet up to the given one, not included @returnt The dequeued packet.
Definition flowbuffer.cc:133
PacketBatch * dequeueAll()
Dequeue all packets @returnt The dequeued packet.
Definition flowbuffer.cc:116
MemoryPool< struct flowBufferEntry > * getMemoryPool()
Return a pointer to the MemoryPool used by this FlowBuffer.
int replaceInFlow(FlowBufferContentIter pos, const int pattern_length, const char *replacement, const int replacement_length, const bool repeat, CTXElement *owner)
Replace a pattern in the buffer.
Definition flowbuffer.cc:396
int searchInFlow(const char *pattern)
Search a pattern in the buffer.
Definition flowbuffer.cc:89
FlowBufferIter begin()
Return an iterator pointing to the first packet of the buffer.
Definition flowbuffer.cc:164
void enqueueAll(PacketBatch *batch)
Ensure a flow buffer is initialized and enqueue all packets.
Definition flowbuffer.cc:38
This iterator allows to iterate over the packets in a FlowBuffer.
Definition flowbuffer.hh:177
FlowBufferIter & operator++()
Move the iterator to the next packet in the buffer.
Definition flowbuffer.hh:387
bool operator!=(const FlowBufferIter &other) const
Compare two FlowBufferIter.
Definition flowbuffer.hh:411
FlowBufferIter(FlowBuffer *_flowBuffer, Packet *_entry)
Construct a FlowBufferIter.
Definition flowbuffer.hh:374
WritablePacket *& operator*()
Return the packet to which this iterator points.
Definition flowbuffer.hh:380
bool operator==(const FlowBufferIter &other) const
Compare two FlowBufferIter.
Definition flowbuffer.hh:397
Template for memory pools.
Definition memorypool.hh:20
Definition packetbatch.hh:415
A network packet.
Definition packet.hh:68
uint32_t length() const
Return the packet's length.
Definition packet.hh:1276
Packet * next() const
Return the next packet annotation.
Definition packet.hh:1327
A network packet believed not to be shared.
Definition packet.hh:1004
unsigned char * data() const
Definition packet.hh:2941
The Packet class models packets in Click.
Timestamp operator*(const Timestamp &a, double b)
Scale a by a factor of b and return the result.
Definition timestamp.hh:1447