/* * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Andrew Galante, haiku.galante@gmail.com * Axel Dörfler, axeld@pinc-software.de * Hugo Santos, hugosantos@gmail.com */ #ifndef TCP_ENDPOINT_H #define TCP_ENDPOINT_H #include "BufferQueue.h" #include "EndpointManager.h" #include "tcp.h" #include #include #include #include #include #include #include class WaitList { public: WaitList(const char *name); ~WaitList(); status_t InitCheck() const; status_t Wait(MutexLocker &, bigtime_t timeout, bool wakeNext = true); void Signal(); private: int32 fCondition; sem_id fSem; }; class TCPEndpoint : public net_protocol, public ProtocolSocket { public: TCPEndpoint(net_socket *socket); ~TCPEndpoint(); status_t InitCheck() const; status_t Open(); status_t Close(); status_t Free(); status_t Connect(const struct sockaddr *address); status_t Accept(struct net_socket **_acceptedSocket); status_t Bind(const sockaddr *address); status_t Unbind(struct sockaddr *address); status_t Listen(int count); status_t Shutdown(int direction); status_t SendData(net_buffer *buffer); ssize_t SendAvailable(); status_t ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer); ssize_t ReadAvailable(); status_t FillStat(struct net_stat *stat); status_t SetSendBufferSize(size_t length); status_t SetReceiveBufferSize(size_t length); status_t SetOption(int option, const void *value, int length); tcp_state State() const { return fState; } bool IsBound() const; status_t DelayedAcknowledge(); status_t SendAcknowledge(bool force); status_t UpdateTimeWait(); int32 SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); int32 Spawn(TCPEndpoint *parent, tcp_segment_header& segment, net_buffer *buffer); void DumpInternalState() const; private: friend class EndpointManager; void _StartPersistTimer(); void _EnterTimeWait(); uint8 _CurrentFlags(); bool _ShouldSendSegment(tcp_segment_header &segment, uint32 length, uint32 segmentMaxSize, uint32 flightSize); status_t _SendQueued(bool force = false); status_t _SendQueued(bool force, uint32 sendWindow); int _MaxSegmentSize(const struct sockaddr *) const; status_t _ShutdownEgress(bool closing); ssize_t _AvailableData() const; void _NotifyReader(); bool _ShouldReceive() const; void _HandleReset(status_t error); int32 _ListenReceive(tcp_segment_header& segment, net_buffer *buffer); int32 _SynchronizeSentReceive(tcp_segment_header& segment, net_buffer *buffer); int32 _SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); int32 _Receive(tcp_segment_header& segment, net_buffer *buffer); void _UpdateTimestamps(tcp_segment_header& segment, size_t segmentLength); void _MarkEstablished(); status_t _WaitForEstablished(MutexLocker &lock, bigtime_t timeout); bool _AddData(tcp_segment_header &segment, net_buffer *buffer); void _PrepareReceivePath(tcp_segment_header &segment); status_t _PrepareSendPath(const sockaddr *peer); void _Acknowledged(tcp_segment_header &segment); void _Retransmit(); void _UpdateSRTT(int32 roundTripTime); void _ResetSlowStart(); void _DuplicateAcknowledge(tcp_segment_header &segment); static void _TimeWaitTimer(net_timer *timer, void *data); static void _RetransmitTimer(net_timer *timer, void *data); static void _PersistTimer(net_timer *timer, void *data); static void _DelayedAcknowledgeTimer(net_timer *timer, void *data); EndpointManager *fManager; HashTableLink fConnectionHashLink; HashTableLink fEndpointHashLink; friend class ConnectionHashDefinition; friend class EndpointHashDefinition; mutex fLock; WaitList fReceiveList; WaitList fSendList; sem_id fAcceptSemaphore; uint8 fOptions; uint8 fSendWindowShift; uint8 fReceiveWindowShift; tcp_sequence fSendUnacknowledged; tcp_sequence fSendNext; tcp_sequence fSendMax; uint32 fSendWindow; uint32 fSendMaxWindow; uint32 fSendMaxSegmentSize; BufferQueue fSendQueue; tcp_sequence fLastAcknowledgeSent; tcp_sequence fInitialSendSequence; uint32 fDuplicateAcknowledgeCount; net_route *fRoute; // TODO: don't use a net_route, but a net_route_info!!! tcp_sequence fReceiveNext; tcp_sequence fReceiveMaxAdvertised; uint32 fReceiveWindow; uint32 fReceiveMaxSegmentSize; BufferQueue fReceiveQueue; tcp_sequence fInitialReceiveSequence; // round trip time and retransmit timeout computation int32 fRoundTripTime; int32 fRoundTripDeviation; bigtime_t fRetransmitTimeout; uint32 fReceivedTimestamp; uint32 fCongestionWindow; uint32 fSlowStartThreshold; tcp_state fState; uint32 fFlags; // timer net_timer fRetransmitTimer; net_timer fPersistTimer; net_timer fDelayedAcknowledgeTimer; net_timer fTimeWaitTimer; }; #endif // TCP_ENDPOINT_H