Skip to content

Commit da4fa89

Browse files
committed
Tested closing tcp connections, updated docs
1 parent 1e74890 commit da4fa89

File tree

4 files changed

+74
-26
lines changed

4 files changed

+74
-26
lines changed

src/rtptcpaddress.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ namespace jrtplib
4949
class RTPMemoryManager;
5050

5151
/** Represents a TCP 'address' and port.
52-
* This class is used by the TCP transmission component.
52+
* This class is used by the TCP transmission component, to specify which sockets
53+
* should be used to send/receive data, and to know on which socket incoming data
54+
* was received.
5355
*/
5456
class JRTPLIB_IMPORTEXPORT RTPTCPAddress : public RTPAddress
5557
{

src/rtptcptransmitter.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,13 @@ int RTPTCPTransmitter::Poll()
305305
if (status == ERR_RTP_OUTOFMEM)
306306
break;
307307
else
308+
{
308309
errSockets.push_back(sock);
310+
// Don't let this count as an error (due to a closed connection for example),
311+
// otherwise the poll thread (if used) will stop because of this. Since there
312+
// may be more than one connection, that's not desirable in general.
313+
status = 0;
314+
}
309315
}
310316
++it;
311317
}
@@ -899,17 +905,20 @@ int RTPTCPTransmitter::SendRTPRTCPData(const void *data, size_t len)
899905

900906
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
901907
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
902-
int status = 0;
903908

904909
vector<SocketType> errSockets;
910+
int flags = 0;
911+
#ifndef RTP_SOCKETTYPE_WINSOCK // TODO: replace this by a test
912+
flags = MSG_NOSIGNAL;
913+
#endif
905914

906915
while (it != end)
907916
{
908917
uint8_t lengthBytes[2] = { (uint8_t)((len >> 8)&0xff), (uint8_t)(len&0xff) };
909918
SocketType sock = it->first;
910919

911-
if (send(sock,(const char *)lengthBytes,2,0) < 0 ||
912-
send(sock,(const char *)data,len,0) < 0)
920+
if (send(sock,(const char *)lengthBytes,2,flags) < 0 ||
921+
send(sock,(const char *)data,len,flags) < 0)
913922
errSockets.push_back(sock);
914923
++it;
915924
}
@@ -918,13 +927,14 @@ int RTPTCPTransmitter::SendRTPRTCPData(const void *data, size_t len)
918927

919928
if (errSockets.size() != 0)
920929
{
921-
status = ERR_RTP_TCPTRANS_ERRORINSEND;
922-
923930
for (size_t i = 0 ; i < errSockets.size() ; i++)
924931
OnSendError(errSockets[i]);
925932
}
926933

927-
return status;
934+
// Don't return an error code to avoid the poll thread exiting
935+
// due to one closed connection for example
936+
937+
return 0;
928938
}
929939

930940
int RTPTCPTransmitter::ValidateSocket(SocketType)

src/rtptcptransmitter.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class JRTPLIB_IMPORTEXPORT RTPTCPTransmissionParams : public RTPTransmissionPara
6060
RTPTCPTransmissionParams();
6161

6262
/** If non null, the specified abort descriptors will be used to cancel
63-
* the function that's waiting for packets to arrive; set to null (the default
63+
* the function that's waiting for packets to arrive; set to null (the default)
6464
* to let the transmitter create its own instance. */
6565
void SetCreatedAbortDescriptors(RTPAbortDescriptors *desc) { m_pAbortDesc = desc; }
6666

@@ -89,11 +89,25 @@ class JRTPLIB_IMPORTEXPORT RTPTCPTransmissionInfo : public RTPTransmissionInfo
8989
#define RTPTCPTRANS_HEADERSIZE (20+20+2) // 20 IP, 20 TCP, 2 for framing (RFC 4571)
9090

9191
/** A TCP transmission component.
92+
*
9293
* This class inherits the RTPTransmitter interface and implements a transmission component
9394
* which uses TCP to send and receive RTP and RTCP data. The component's parameters
9495
* are described by the class RTPTCPTransmissionParams. The functions which have an RTPAddress
95-
* argument require an argument of RTPTCPAddress. The GetTransmissionInfo member function
96+
* argument require an argument of RTPTCPAddress. The RTPTransmitter::GetTransmissionInfo member function
9697
* returns an instance of type RTPTCPTransmissionInfo.
98+
*
99+
* After this transmission component was created, no data will actually be sent or received
100+
* yet. You can specify over which TCP connections (which must be established first) data
101+
* should be transmitted by using the RTPTransmitter::AddDestination member function. This
102+
* takes an argument of type RTPTCPAddress, with which relevant the socket descriptor can
103+
* be passed to the transmitter.
104+
*
105+
* These sockets will also be used to check for incoming RTP or RTCP data. The RTPTCPAddress
106+
* instance that's associated with a received packet, will contain the socket descriptor
107+
* on which the data was received. This descriptor can be obtained using RTPTCPAddress::GetSocket.
108+
*
109+
* To get notified of an error when sending over or receiving from a socket, override the
110+
* RTPTCPTransmitter::OnSendError and RTPTCPTransmitter::OnReceiveError member functions.
97111
*/
98112
class JRTPLIB_IMPORTEXPORT RTPTCPTransmitter : public RTPTransmitter
99113
{
@@ -142,9 +156,9 @@ class JRTPLIB_IMPORTEXPORT RTPTCPTransmitter : public RTPTransmitter
142156
void Dump();
143157
#endif // RTPDEBUG
144158
protected:
145-
// TODO
159+
/** By overriding this function you can be notified of an error when sending over a socket. */
146160
virtual void OnSendError(SocketType sock);
147-
// TODO
161+
/** By overriding this function you can be notified of an error when receiving from a socket. */
148162
virtual void OnReceiveError(SocketType sock);
149163
private:
150164
class SocketData

tests/tcptest.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
#include "rtperrors.h"
77
#include "rtpsourcedata.h"
88
#include "rtptcpaddress.h"
9+
#include "rtptcptransmitter.h"
910
#include "rtppacket.h"
10-
#ifndef RTP_SOCKETTYPE_WINSOCK
11-
#include <netinet/tcp.h>
12-
#endif
1311
#include <string.h>
1412
#include <stdlib.h>
1513
#include <iostream>
@@ -54,19 +52,50 @@ class MyRTPSession : public RTPSession
5452
}
5553
};
5654

55+
class MyTCPTransmitter : public RTPTCPTransmitter
56+
{
57+
public:
58+
MyTCPTransmitter(const string &name) : RTPTCPTransmitter(0), m_name(name) { }
59+
60+
void OnSendError(SocketType sock)
61+
{
62+
cout << m_name << ": Error sending over socket " << sock << ", removing destination" << endl;
63+
DeleteDestination(RTPTCPAddress(sock));
64+
}
65+
66+
void OnReceiveError(SocketType sock)
67+
{
68+
cout << m_name << ": Error receiving from socket " << sock << ", removing destination" << endl;
69+
DeleteDestination(RTPTCPAddress(sock));
70+
}
71+
private:
72+
string m_name;
73+
};
74+
5775
void runTest(int sock1, int sock2)
5876
{
5977
const int packSize = 45678;
6078
RTPSessionParams sessParams;
79+
MyTCPTransmitter trans1("Transmitter1"), trans2("Transmitter2");
6180
MyRTPSession sess1, sess2;
6281

6382
sessParams.SetProbationType(RTPSources::NoProbation);
6483
sessParams.SetOwnTimestampUnit(1.0/packSize);
6584
sessParams.SetMaximumPacketSize(packSize + 64); // some extra room for rtp header
6685

67-
checkerror(sess1.Create(sessParams, 0, RTPTransmitter::TCPProto));
86+
bool threadsafe = false;
87+
#ifdef RTP_SUPPORT_THREAD
88+
threadsafe = true;
89+
#endif // RTP_SUPPORT_THREAD
90+
91+
checkerror(trans1.Init(threadsafe));
92+
checkerror(trans2.Init(threadsafe));
93+
checkerror(trans1.Create(65535, 0));
94+
checkerror(trans2.Create(65535, 0));
95+
96+
checkerror(sess1.Create(sessParams, &trans1));
6897
cout << "Session 1 created " << endl;
69-
checkerror(sess2.Create(sessParams, 0, RTPTransmitter::TCPProto));
98+
checkerror(sess2.Create(sessParams, &trans2));
7099
cout << "Session 2 created " << endl;
71100

72101
checkerror(sess1.AddDestination(RTPTCPAddress(sock1)));
@@ -83,6 +112,9 @@ void runTest(int sock1, int sock2)
83112
int len = (i%2 == 0)?pack.size():0;
84113
checkerror(sess1.SendPacket((void *)&pack[0],len,0,false,10));
85114

115+
if (i == 10)
116+
RTPCLOSE(sock1); // Induce an error when sending/receiving
117+
86118
// Either the background thread or the poll function itself will
87119
// cause the OnValidatedRTPPacket and OnRTCPSDESItem functions to
88120
// be called, so in this loop there's not much left to do.
@@ -154,16 +186,6 @@ int main(int argc, char *argv[])
154186
RTPCLOSE(listener);
155187

156188
cout << "Got connected socket pair" << endl;
157-
cout << "Turning off Nagle's algorithm" << endl;
158-
159-
int flag = 1;
160-
if (setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0 ||
161-
setsockopt(server, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)
162-
{
163-
cerr << "Unable to turn off Nagle's algorithm on a socket" << endl;
164-
return -1;
165-
}
166-
167189

168190
runTest(server, client);
169191

0 commit comments

Comments
 (0)