1 #include "rtpconfig.h"
2 
3 // Let's assume that non-winsock platforms have SIGALRM and EINTR
4 #if !defined(RTP_SOCKETTYPE_WINSOCK) && defined(RTP_SUPPORT_THREAD)
5 
6 #include "rtpsession.h"
7 #include "rtpudpv4transmitter.h"
8 #include "rtpipv4address.h"
9 #include "rtpsessionparams.h"
10 #include "rtperrors.h"
11 #include "rtplibraryversion.h"
12 #include "rtpsourcedata.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <iostream>
16 #include <string>
17 #include <jthread/jthread.h>
18 
19 #include <signal.h>
20 #include <unistd.h>
21 
22 using namespace jrtplib;
23 using namespace jthread;
24 using namespace std;
25 
checkerror(int rtperr)26 void checkerror(int rtperr)
27 {
28 	if (rtperr < 0)
29 	{
30 		cout << "ERROR: " << RTPGetErrorString(rtperr) << endl;
31 		exit(-1);
32 	}
33 }
34 
35 class MyRTPSession : public RTPSession
36 {
37 protected:
OnValidatedRTPPacket(RTPSourceData * srcdat,RTPPacket * rtppack,bool isonprobation,bool * ispackethandled)38 	void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled)
39 	{
40 		printf("Got packet in OnValidatedRTPPacket from source 0x%04x!\n", srcdat->GetSSRC());
41 		DeletePacket(rtppack);
42 		*ispackethandled = true;
43 	}
44 
OnRTCPSDESItem(RTPSourceData * srcdat,RTCPSDESPacket::ItemType t,const void * itemdata,size_t itemlength)45 	void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength)
46 	{
47 		char msg[1024];
48 
49 		memset(msg, 0, sizeof(msg));
50 		if (itemlength >= sizeof(msg))
51 			itemlength = sizeof(msg)-1;
52 
53 		memcpy(msg, itemdata, itemlength);
54 		printf("SSRC %x: Received SDES item (%d): %s", (unsigned int)srcdat->GetSSRC(), (int)t, msg);
55 	}
56 };
57 
58 class MyThread : public JThread
59 {
60 public:
MyThread()61 	MyThread()
62 	{
63 		if (m_mutex.Init() < 0)
64 		{
65 			cerr << "Can't init mutex" << endl;
66 			exit(-1);
67 		}
68 		m_stop = false;
69 	}
70 
~MyThread()71 	~MyThread()
72 	{
73 		m_mutex.Lock();
74 		m_stop = true;
75 		m_mutex.Unlock();
76 
77 		while (IsRunning())
78 			RTPTime::Wait(RTPTime(0, 10000));
79 	}
80 
Thread()81 	void *Thread()
82 	{
83 		ThreadStarted();
84 
85 		bool done = false;
86 		pid_t pid = getpid();
87 
88 		while (!done)
89 		{
90 			kill(pid, SIGALRM);
91 
92 			RTPTime::Wait(RTPTime(0, 500000));
93 
94 			m_mutex.Lock();
95 			done = m_stop;
96 			m_mutex.Unlock();
97 		}
98 
99 		return 0;
100 	}
101 
102 private:
103 	JMutex m_mutex;
104 	bool m_stop;
105 };
106 
handler(int sig)107 void handler(int sig)
108 {
109 	cerr << "Signal " << sig << endl;
110 }
111 
main(void)112 int main(void)
113 {
114 	if (signal(SIGALRM, handler) == SIG_ERR)
115 	{
116 		cerr << "Unable to install signal handler" << endl;
117 		return -1;
118 	}
119 
120 	MyThread t;
121 
122 	if (t.Start() < 0)
123 	{
124 		cerr << "Unable to start thread that sends signals" << endl;
125 		return -1;
126 	}
127 
128 	cerr << "Waiting one second to verify that handler is called and program doesn't exit yet" << endl;
129 	RTPTime::Wait(RTPTime(1,0));
130 
131 	MyRTPSession sess;
132 	uint16_t portbase = 5000, destport = 5000;
133 	uint32_t destip;
134 	string ipstr = "127.0.0.1";
135 	int status,i,num;
136 
137 	destip = inet_addr(ipstr.c_str());
138 	if (destip == INADDR_NONE)
139 	{
140 		cerr << "Bad IP address specified" << endl;
141 		return -1;
142 	}
143 	destip = ntohl(destip);
144 
145 	num = 20;
146 
147 	// Now, we'll create a RTP session, set the destination, send some
148 	// packets and poll for incoming data.
149 
150 	RTPUDPv4TransmissionParams transparams;
151 	RTPSessionParams sessparams;
152 
153 	sessparams.SetOwnTimestampUnit(1.0/10.0);
154 	sessparams.SetAcceptOwnPackets(true);
155 	sessparams.SetUsePollThread(false);
156 	transparams.SetPortbase(portbase);
157 
158 	status = sess.Create(sessparams,&transparams);
159 	checkerror(status);
160 
161 	RTPIPv4Address addr(destip,destport);
162 
163 	status = sess.AddDestination(addr);
164 	checkerror(status);
165 
166 	for (i = 1 ; i <= num ; i++)
167 	{
168 		printf("\nSending packet %d/%d\n",i,num);
169 
170 		// send the packet
171 		status = sess.SendPacket((void *)"1234567890",10,0,false,10);
172 		checkerror(status);
173 
174 		// Either the background thread or the poll function itself will
175 		// cause the OnValidatedRTPPacket and OnRTCPSDESItem functions to
176 		// be called, so in this loop there's not much left to do.
177 
178 		status = sess.Poll();
179 		checkerror(status);
180 
181 		RTPTime startTime = RTPTime::CurrentTime();
182 		RTPTime diff(0,0);
183 		do
184 		{
185 			status = sess.WaitForIncomingData(RTPTime(0,100));
186 			checkerror(status);
187 
188 			diff = RTPTime::CurrentTime();
189 			diff -= startTime;
190 		} while (diff.GetDouble() < 1.0); // Make sure we wait a second
191 	}
192 
193 	return 0;
194 }
195 
196 #else
197 #include <iostream>
198 
199 using namespace std;
200 
main(void)201 int main(void)
202 {
203 	cerr << "Need JThread support and a unix-like platform for this test" << endl;
204 	return 0;
205 }
206 
207 #endif
208 
209