mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
bc7b42d81f
- Fixed retransmit algorithm. Much more closely matched to TCP standard: http://tools.ietf.org/html/rfc2988 - This increases retransmit timeouts, and reduces the number of packets resent. - Added better debugging for retrans/close as separate #defines. - Further testing is required ;) git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5252 b45a01b8-16f6-495d-af2f-9b41ad6348cc
273 lines
6.3 KiB
C++
273 lines
6.3 KiB
C++
/*
|
|
* "$Id: tcpstream.h,v 1.5 2007-02-18 21:46:50 rmf24 Exp $"
|
|
*
|
|
* TCP-on-UDP (tou) network interface for RetroShare.
|
|
*
|
|
* Copyright 2004-2006 by Robert Fernie.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License Version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA.
|
|
*
|
|
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TOU_TCP_PROTO_H
|
|
#define TOU_TCP_PROTO_H
|
|
|
|
|
|
/* so the packet will contain
|
|
* a tcp header + data.
|
|
*
|
|
* This is done simplistically for speed.
|
|
*/
|
|
|
|
#include "tcppacket.h"
|
|
#include "udppeer.h"
|
|
|
|
// WINDOWS doesn't like UDP packets bigger than 1492 (truncates them).
|
|
// We have up to 64 bytes of headers: 28(udp) + 16(relay) + 20(tou) = 64 bytes.
|
|
// 64 bytes + 1400 = 1464, leaves a small margin, but close to maximum throughput.
|
|
//#define MAX_SEG 1400
|
|
// We are going to start at 1000 (to avoid any fragmentation, and work up).
|
|
#define MAX_SEG 1000
|
|
|
|
#define TCP_MAX_SEQ UINT_MAX
|
|
#define TCP_MAX_WIN 65500
|
|
#define TCP_ALIVE_TIMEOUT 15 /* 15 sec ... < 20 sec UDP state limit on some firewalls */
|
|
#define TCP_RETRANS_TIMEOUT 1 /* 1 sec (Initial value) */
|
|
#define TCP_RETRANS_MAX_TIMEOUT 15 /* 15 secs */
|
|
#define kNoPktTimeout 60 /* 1 min */
|
|
|
|
|
|
#define TCP_CLOSED 0
|
|
#define TCP_LISTEN 1
|
|
#define TCP_SYN_SENT 2
|
|
#define TCP_SYN_RCVD 3
|
|
#define TCP_ESTABLISHED 4
|
|
#define TCP_FIN_WAIT_1 5
|
|
#define TCP_FIN_WAIT_2 6
|
|
#define TCP_TIMED_WAIT 7
|
|
#define TCP_CLOSING 8
|
|
#define TCP_CLOSE_WAIT 9
|
|
#define TCP_LAST_ACK 10
|
|
|
|
class dataBuffer
|
|
{
|
|
public:
|
|
uint8 data[MAX_SEG];
|
|
};
|
|
|
|
#include <list>
|
|
#include <deque>
|
|
|
|
|
|
class TcpStream: public UdpPeer
|
|
{
|
|
public:
|
|
/* Top-Level exposed */
|
|
|
|
TcpStream(UdpSubReceiver *udp);
|
|
virtual ~TcpStream() { return; }
|
|
|
|
/* user interface */
|
|
int status(std::ostream &out);
|
|
int connect(const struct sockaddr_in &raddr, uint32_t conn_period);
|
|
int listenfor(const struct sockaddr_in &raddr);
|
|
bool isConnected();
|
|
|
|
/* get tcp information */
|
|
bool getRemoteAddress(struct sockaddr_in &raddr);
|
|
uint8 TcpState();
|
|
int TcpErrorState();
|
|
|
|
/* stream Interface */
|
|
int write(char *dta, int size); /* write -> pkt -> net */
|
|
int read(char *dta, int size); /* net -> pkt -> read */
|
|
|
|
/* check ahead for allowed bytes */
|
|
int write_allowed();
|
|
int read_pending();
|
|
|
|
int closeWrite(); /* non-standard, but for clean exit */
|
|
int close(); /* standard unix behaviour */
|
|
|
|
int tick(); /* check iface etc */
|
|
|
|
/* Callback Funcion from UDP Layers */
|
|
virtual void recvPkt(void *data, int size); /* overloaded */
|
|
|
|
|
|
|
|
/* Exposed Data Counting */
|
|
bool widle(); /* write idle */
|
|
bool ridle(); /* read idle */
|
|
uint32 wbytes();
|
|
uint32 rbytes();
|
|
|
|
/* Exposed for debugging */
|
|
int dumpstate(std::ostream &out);
|
|
|
|
private:
|
|
|
|
/* Internal Functions - use the Mutex (not reentrant) */
|
|
/* Internal Functions - that don't need mutex protection */
|
|
|
|
uint32 genSequenceNo();
|
|
bool isOldSequence(uint32 tst, uint32 curr);
|
|
|
|
RsMutex tcpMtx;
|
|
|
|
/* Internal Functions - only called inside mutex protection */
|
|
|
|
int dumpstate_locked(std::ostream &out);
|
|
int status_locked(std::ostream &out);
|
|
|
|
int cleanup();
|
|
|
|
/* incoming data */
|
|
int recv_check();
|
|
int handleIncoming(TcpPacket *pkt);
|
|
int incoming_Closed(TcpPacket *pkt);
|
|
int incoming_SynSent(TcpPacket *pkt);
|
|
int incoming_SynRcvd(TcpPacket *pkt);
|
|
int incoming_Established(TcpPacket *pkt);
|
|
int incoming_FinWait1(TcpPacket *pkt);
|
|
int incoming_FinWait2(TcpPacket *pkt);
|
|
int incoming_TimedWait(TcpPacket *pkt);
|
|
int incoming_Closing(TcpPacket *pkt);
|
|
int incoming_CloseWait(TcpPacket *pkt);
|
|
int incoming_LastAck(TcpPacket *pkt);
|
|
int check_InPkts();
|
|
int UpdateInWinSize();
|
|
int int_read_pending();
|
|
|
|
/* outgoing data */
|
|
int send();
|
|
int toSend(TcpPacket *pkt, bool retrans = true);
|
|
void acknowledge();
|
|
int retrans();
|
|
int sendAck();
|
|
void setRemoteAddress(const struct sockaddr_in &raddr);
|
|
|
|
int getTTL() { return ttl; }
|
|
void setTTL(int t) { ttl = t; }
|
|
|
|
/* retransmission */
|
|
void startRetransmitTimer();
|
|
void restartRetransmitTimer();
|
|
void stopRetransmitTimer();
|
|
void resetRetransmitTimer();
|
|
void incRetransmitTimeout();
|
|
|
|
|
|
/* data counting */
|
|
uint32 int_wbytes();
|
|
uint32 int_rbytes();
|
|
|
|
/* Internal Data - must have mutex to access! */
|
|
|
|
/* data (in -> pkts) && (pkts -> out) */
|
|
|
|
/* for small amounts of data */
|
|
uint8 inData[MAX_SEG];
|
|
uint32 inSize;
|
|
|
|
|
|
/* two variable sized buffers required here */
|
|
uint8 outDataRead[MAX_SEG];
|
|
uint32 outSizeRead;
|
|
uint8 outDataNet[MAX_SEG];
|
|
uint32 outSizeNet;
|
|
|
|
/* get packed into here as size increases */
|
|
std::deque<dataBuffer *> inQueue, outQueue;
|
|
|
|
/* packets waiting for acks */
|
|
std::list<TcpPacket *> inPkt, outPkt;
|
|
|
|
|
|
uint8 state; /* stream state */
|
|
bool inStreamActive;
|
|
bool outStreamActive;
|
|
|
|
uint32 outSeqno; /* next out */
|
|
uint32 outAcked; /* other size has received */
|
|
uint32 outWinSize; /* we allowed to send */
|
|
|
|
uint32 inAckno; /* next expected */
|
|
uint32 inWinSize; /* allowing other to send */
|
|
|
|
/* some (initially) consts */
|
|
uint32 maxWinSize;
|
|
uint32 keepAliveTimeout;
|
|
|
|
/* retransmit */
|
|
bool retransTimerOn;
|
|
double retransTimeout;
|
|
double retransTimerTs;
|
|
|
|
/* some timers */
|
|
double keepAliveTimer;
|
|
double lastIncomingPkt;
|
|
|
|
/* tracking */
|
|
uint32 lastSentAck;
|
|
uint32 lastSentWinSize;
|
|
uint32 initOurSeqno;
|
|
uint32 initPeerSeqno;
|
|
|
|
uint32 lastWriteTF,lastReadTF;
|
|
uint16 wcount, rcount;
|
|
|
|
int errorState;
|
|
|
|
/* RoundTripTime estimations */
|
|
double rtt_est;
|
|
double rtt_dev;
|
|
|
|
/* congestion limits */
|
|
uint32 congestThreshold;
|
|
uint32 congestWinSize;
|
|
uint32 congestUpdate;
|
|
|
|
/* existing TTL for this stream (tweaked at startup) */
|
|
int ttl;
|
|
|
|
double mTTL_period;
|
|
double mTTL_start;
|
|
double mTTL_end;
|
|
|
|
struct sockaddr_in peeraddr;
|
|
bool peerKnown;
|
|
|
|
/* UdpSubReceiver (has own Mutex!) */
|
|
UdpSubReceiver *udp;
|
|
|
|
};
|
|
|
|
|
|
/* for debugging */
|
|
|
|
#ifdef TCP_DEBUG_STREAM_EXTRA /* for extra checking! */
|
|
int setupBinaryCheck(std::string fname);
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|