1/*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Andrew Galante, haiku.galante@gmail.com
7 *		Axel D��rfler, axeld@pinc-software.de
8 *		Hugo Santos, hugosantos@gmail.com
9 */
10#ifndef TCP_ENDPOINT_H
11#define TCP_ENDPOINT_H
12
13
14#include "BufferQueue.h"
15#include "EndpointManager.h"
16#include "tcp.h"
17
18#include <ProtocolUtilities.h>
19#include <net_protocol.h>
20#include <net_stack.h>
21#include <condition_variable.h>
22#include <util/AutoLock.h>
23#include <util/DoublyLinkedList.h>
24#include <util/OpenHashTable.h>
25
26#include <stddef.h>
27
28
29class TCPEndpoint : public net_protocol, public ProtocolSocket {
30public:
31						TCPEndpoint(net_socket* socket);
32						~TCPEndpoint();
33
34			status_t	InitCheck() const;
35
36			status_t	Open();
37			status_t	Close();
38			void		Free();
39			status_t	Connect(const struct sockaddr* address);
40			status_t	Accept(struct net_socket** _acceptedSocket);
41			status_t	Bind(const sockaddr* address);
42			status_t	Unbind(struct sockaddr* address);
43			status_t	Listen(int count);
44			status_t	Shutdown(int direction);
45			status_t	SendData(net_buffer* buffer);
46			ssize_t		SendAvailable();
47			status_t	ReadData(size_t numBytes, uint32 flags,
48							net_buffer** _buffer);
49			ssize_t		ReadAvailable();
50
51			status_t	FillStat(struct net_stat* stat);
52
53			status_t	SetSendBufferSize(size_t length);
54			status_t	SetReceiveBufferSize(size_t length);
55
56			status_t	GetOption(int option, void* value, int* _length);
57			status_t	SetOption(int option, const void* value, int length);
58
59			tcp_state	State() const { return fState; }
60			bool		IsBound() const;
61			bool		IsLocal() const;
62
63			status_t	DelayedAcknowledge();
64
65			int32		SegmentReceived(tcp_segment_header& segment,
66							net_buffer* buffer);
67
68			void		Dump() const;
69
70private:
71			void		_StartPersistTimer();
72			void		_EnterTimeWait();
73			void		_UpdateTimeWait();
74			void		_Close();
75			void		_CancelConnectionTimers();
76
77			tcp_segment_header _PrepareSendSegment();
78			bool		_ShouldSendSegment(tcp_segment_header& segment,
79							uint32 length, uint32 segmentMaxSize,
80							uint32 flightSize);
81			status_t	_PrepareAndSend(tcp_segment_header& segment, net_buffer* buffer,
82							bool isRetransmit);
83			status_t	_SendAcknowledge(bool force = false);
84			status_t	_SendQueued(bool force = false);
85
86			status_t	_Disconnect(bool closing);
87			ssize_t		_AvailableData() const;
88			void		_NotifyReader();
89			bool		_ShouldReceive() const;
90			void		_HandleReset(status_t error);
91			int32		_Spawn(TCPEndpoint* parent, tcp_segment_header& segment,
92							net_buffer* buffer);
93			int32		_ListenReceive(tcp_segment_header& segment,
94							net_buffer* buffer);
95			int32		_SynchronizeSentReceive(tcp_segment_header& segment,
96							net_buffer* buffer);
97			int32		_SegmentReceived(tcp_segment_header& segment,
98							net_buffer* buffer);
99			int32		_Receive(tcp_segment_header& segment,
100							net_buffer* buffer);
101			void		_UpdateTimestamps(tcp_segment_header& segment,
102							size_t segmentLength);
103			void		_MarkEstablished();
104			status_t	_WaitForEstablished(MutexLocker& lock,
105							bigtime_t timeout);
106			bool		_AddData(tcp_segment_header& segment,
107							net_buffer* buffer);
108			int			_MaxSegmentSize(const struct sockaddr* address) const;
109			void		_PrepareReceivePath(tcp_segment_header& segment);
110			status_t	_PrepareSendPath(const sockaddr* peer);
111			void		_Acknowledged(tcp_segment_header& segment);
112			void		_Retransmit();
113			void		_UpdateRoundTripTime(int32 roundTripTime, int32 expectedSamples);
114			void		_ResetSlowStart();
115			void		_DuplicateAcknowledge(tcp_segment_header& segment);
116
117	static	void		_TimeWaitTimer(net_timer* timer, void* _endpoint);
118	static	void		_RetransmitTimer(net_timer* timer, void* _endpoint);
119	static	void		_PersistTimer(net_timer* timer, void* _endpoint);
120	static	void		_DelayedAcknowledgeTimer(net_timer* timer,
121							void* _endpoint);
122
123	static	status_t	_WaitForCondition(ConditionVariable& condition,
124							MutexLocker& locker, bigtime_t timeout);
125
126private:
127	TCPEndpoint*	fConnectionHashLink;
128	TCPEndpoint*	fEndpointHashLink;
129	friend class	EndpointManager;
130	friend struct	ConnectionHashDefinition;
131	friend class	EndpointHashDefinition;
132
133	mutex			fLock;
134	EndpointManager* fManager;
135	ConditionVariable
136					fReceiveCondition;
137	ConditionVariable
138					fSendCondition;
139	sem_id			fAcceptSemaphore;
140	uint8			fOptions;
141
142	uint8			fSendWindowShift;
143	uint8			fReceiveWindowShift;
144
145	tcp_sequence	fSendUnacknowledged;
146	tcp_sequence	fSendNext;
147	tcp_sequence	fSendMax;
148	tcp_sequence	fSendUrgentOffset;
149	uint32			fSendWindow;
150	uint32			fSendMaxWindow;
151	uint32			fSendMaxSegmentSize;
152	uint32			fSendMaxSegments;
153	BufferQueue		fSendQueue;
154	tcp_sequence	fLastAcknowledgeSent;
155	tcp_sequence	fInitialSendSequence;
156	tcp_sequence	fPreviousHighestAcknowledge;
157	uint32			fDuplicateAcknowledgeCount;
158	uint32			fPreviousFlightSize;
159	uint32			fRecover;
160
161	net_route		*fRoute;
162		// TODO: don't use a net_route, but a net_route_info!!!
163		// (the latter will automatically adapt to routing changes)
164
165	tcp_sequence	fReceiveNext;
166	tcp_sequence	fReceiveMaxAdvertised;
167	uint32			fReceiveWindow;
168	uint32			fReceiveMaxSegmentSize;
169	BufferQueue		fReceiveQueue;
170	bool			fFinishReceived;
171	tcp_sequence	fFinishReceivedAt;
172	tcp_sequence	fInitialReceiveSequence;
173
174	// round trip time and retransmit timeout computation
175	int32			fSmoothedRoundTripTime;
176	int32			fRoundTripVariation;
177	uint32			fSendTime;
178	tcp_sequence	fRoundTripStartSequence;
179	bigtime_t		fRetransmitTimeout;
180
181	uint32			fReceivedTimestamp;
182
183	uint32			fCongestionWindow;
184	uint32			fSlowStartThreshold;
185
186	tcp_state		fState;
187	uint32			fFlags;
188
189	// timer
190	net_timer		fRetransmitTimer;
191	net_timer		fPersistTimer;
192	net_timer		fDelayedAcknowledgeTimer;
193	net_timer		fTimeWaitTimer;
194};
195
196#endif	// TCP_ENDPOINT_H
197