1/*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel Dörfler, axeld@pinc-software.de
7 */
8#ifndef BUFFER_QUEUE_H
9#define BUFFER_QUEUE_H
10
11
12#include "tcp.h"
13
14#include <util/DoublyLinkedList.h>
15
16#ifndef DEBUG_BUFFER_QUEUE
17#	define DEBUG_BUFFER_QUEUE 1
18#endif
19
20
21typedef DoublyLinkedList<struct net_buffer,
22	DoublyLinkedListCLink<struct net_buffer> > SegmentList;
23
24class BufferQueue {
25public:
26								BufferQueue(size_t maxBytes);
27								~BufferQueue();
28
29			void				SetMaxBytes(size_t maxBytes);
30			void				SetInitialSequence(tcp_sequence sequence);
31
32			void				Add(net_buffer* buffer);
33			void				Add(net_buffer* buffer, tcp_sequence sequence);
34			status_t			RemoveUntil(tcp_sequence sequence);
35			status_t			Get(net_buffer* buffer, tcp_sequence sequence,
36									size_t bytes);
37			status_t			Get(size_t bytes, bool remove,
38									net_buffer** _buffer);
39
40			size_t				Available() const { return fContiguousBytes; }
41			size_t				Available(tcp_sequence sequence) const;
42
43	inline	size_t				PushedData() const;
44			void				SetPushPointer();
45
46			size_t				Used() const { return fNumBytes; }
47	inline	size_t				Free() const;
48			size_t				Size() const { return fMaxBytes; }
49
50			bool				IsContiguous() const
51									{ return fNumBytes == fContiguousBytes; }
52
53			tcp_sequence		FirstSequence() const { return fFirstSequence; }
54			tcp_sequence		LastSequence() const { return fLastSequence; }
55			tcp_sequence		NextSequence() const
56									{ return fFirstSequence + fContiguousBytes; }
57
58#if DEBUG_BUFFER_QUEUE
59			void				Verify() const;
60			void				Dump() const;
61#endif
62
63private:
64			SegmentList			fList;
65			size_t				fMaxBytes;
66			size_t				fNumBytes;
67			size_t				fContiguousBytes;
68			tcp_sequence		fFirstSequence;
69			tcp_sequence		fLastSequence;
70			tcp_sequence		fPushPointer;
71};
72
73
74size_t
75BufferQueue::PushedData() const
76{
77	// We must check if fPushPointer is not 0 here due to
78	// tcp_sequence's special handling of >
79	return fPushPointer != 0 && fPushPointer > fFirstSequence
80		? (fPushPointer - fFirstSequence).Number() : 0;
81}
82
83
84size_t
85BufferQueue::Free() const
86{
87	// Max bytes is a soft limit, so it can be lower than the actual amount of
88	// data in the queue. TCP should never advertize a window outside the max
89	// buffer size, though.
90	if (fMaxBytes > fNumBytes)
91		return fMaxBytes - fNumBytes;
92
93	return 0;
94}
95
96#endif	// BUFFER_QUEUE_H
97