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
17typedef DoublyLinkedList<struct net_buffer,
18	DoublyLinkedListCLink<struct net_buffer> > SegmentList;
19
20class BufferQueue {
21public:
22								BufferQueue(size_t maxBytes);
23								~BufferQueue();
24
25			void				SetMaxBytes(size_t maxBytes);
26			void				SetInitialSequence(tcp_sequence sequence);
27
28			void				Add(net_buffer* buffer);
29			void				Add(net_buffer* buffer, tcp_sequence sequence);
30			status_t			RemoveUntil(tcp_sequence sequence);
31			status_t			Get(net_buffer* buffer, tcp_sequence sequence,
32									size_t bytes);
33			status_t			Get(size_t bytes, bool remove,
34									net_buffer** _buffer);
35
36			size_t				Available() const { return fContiguousBytes; }
37			size_t				Available(tcp_sequence sequence) const;
38
39	inline	size_t				PushedData() const;
40			void				SetPushPointer();
41			int				PopulateSackInfo(tcp_sequence sequence, int maxSackCount, tcp_sack* sacks);
42
43			size_t				Used() const { return fNumBytes; }
44	inline	size_t				Free() const;
45			size_t				Size() const { return fMaxBytes; }
46
47			bool				IsContiguous() const
48									{ return fNumBytes == fContiguousBytes; }
49
50			tcp_sequence		FirstSequence() const { return fFirstSequence; }
51			tcp_sequence		LastSequence() const { return fLastSequence; }
52			tcp_sequence		NextSequence() const
53									{ return fFirstSequence + fContiguousBytes; }
54
55#if DEBUG_TCP_BUFFER_QUEUE
56			void				Verify() const;
57			void				Dump() const;
58#endif
59
60private:
61			SegmentList			fList;
62			size_t				fMaxBytes;
63			size_t				fNumBytes;
64			size_t				fContiguousBytes;
65			tcp_sequence		fFirstSequence;
66			tcp_sequence		fLastSequence;
67			tcp_sequence		fPushPointer;
68};
69
70
71size_t
72BufferQueue::PushedData() const
73{
74	// We must check if fPushPointer is not 0 here due to
75	// tcp_sequence's special handling of >
76	return fPushPointer != 0 && fPushPointer > fFirstSequence
77		? (fPushPointer - fFirstSequence).Number() : 0;
78}
79
80
81size_t
82BufferQueue::Free() const
83{
84	// Max bytes is a soft limit, so it can be lower than the actual amount of
85	// data in the queue. TCP should never advertize a window outside the max
86	// buffer size, though.
87	if (fMaxBytes > fNumBytes)
88		return fMaxBytes - fNumBytes;
89
90	return 0;
91}
92
93#endif	// BUFFER_QUEUE_H
94