blob: 481c05f3f96f3293d8f07fefb15e6a8acc1f8474 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// test ccRTP functionality
2// Copyright (C) 2004 Federico Montesino Pouzols <fedemp@altern.org>
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18#include <cstdlib>
Alexandre Lisionddd731e2014-01-31 11:50:08 -050019#include <cstring>
Emeric Vigier2f625822012-08-06 11:09:52 -040020#include <ccrtp/rtp.h>
21#include <ccrtp/rtppkt.h>
Alexandre Lisionddd731e2014-01-31 11:50:08 -050022#include <ccrtp/crypto/SrtpSymCrypto.h>
Emeric Vigier2f625822012-08-06 11:09:52 -040023#include <ccrtp/CryptoContext.h>
Alexandre Lisionddd731e2014-01-31 11:50:08 -050024#include <ccrtp/CryptoContextCtrl.h>
Emeric Vigier2f625822012-08-06 11:09:52 -040025
26#ifdef CCXX_NAMESPACES
27using namespace ost;
28using namespace std;
29#endif
30
Alexandre Lisionddd731e2014-01-31 11:50:08 -050031// Select one of SrtpEncryptionAESF8, SrtpEncryptionAESCM, SrtpEncryptionTWOCM, SrtpEncryptionTWOF8
32// per RFC 3711 standard is: SrtpEncryptionAESCM
33static int cryptoAlgo = SrtpEncryptionAESCM;
Emeric Vigier2f625822012-08-06 11:09:52 -040034
35inline int hex_char_to_nibble(uint8_t c)
36{
37 switch(c) {
38 case ('0'): return 0x0;
39 case ('1'): return 0x1;
40 case ('2'): return 0x2;
41 case ('3'): return 0x3;
42 case ('4'): return 0x4;
43 case ('5'): return 0x5;
44 case ('6'): return 0x6;
45 case ('7'): return 0x7;
46 case ('8'): return 0x8;
47 case ('9'): return 0x9;
48 case ('a'): return 0xa;
49 case ('A'): return 0xa;
50 case ('b'): return 0xb;
51 case ('B'): return 0xb;
52 case ('c'): return 0xc;
53 case ('C'): return 0xc;
54 case ('d'): return 0xd;
55 case ('D'): return 0xd;
56 case ('e'): return 0xe;
57 case ('E'): return 0xe;
58 case ('f'): return 0xf;
59 case ('F'): return 0xf;
60 default: return -1; /* this flags an error */
61 }
62 /* NOTREACHED */
63 return -1; /* this keeps compilers from complaining */
64}
65
66/*
67 * hex_string_to_octet_string converts a hexadecimal string
68 * of length 2 * len to a raw octet string of length len
69 */
70
71int hex_string_to_octet_string(char *raw, char *hex, int len)
72{
73 uint8 x;
74 int tmp;
75 int hex_len;
76
77 hex_len = 0;
78 while (hex_len < len) {
79 tmp = hex_char_to_nibble(hex[0]);
80 if (tmp == -1)
81 return hex_len;
82 x = (tmp << 4);
83 hex_len++;
84 tmp = hex_char_to_nibble(hex[1]);
85 if (tmp == -1)
86 return hex_len;
87 x |= (tmp & 0xff);
88 hex_len++;
89 *raw++ = x;
90 hex += 2;
91 }
92 return hex_len;
93}
94
95class PacketsPattern
96{
97public:
98 inline const InetHostAddress& getDestinationAddress() const
99 { return destinationAddress; }
100
101 inline const tpport_t getDestinationPort() const
102 { return destinationPort; }
103
104 uint32 getPacketsNumber() const
105 { return packetsNumber; }
106
107 uint32 getSsrc() const
108 { return 0xdeadbeef; }
109
110 const unsigned char* getPacketData(uint32 i)
111 { return data; }
112
113 const size_t getPacketSize(uint32 i)
114 { return packetsSize; }
115
116private:
117 static const InetHostAddress destinationAddress;
118 static const uint16 destinationPort = 5002;
119 static const uint32 packetsNumber = 10;
120 static const uint32 packetsSize = 12;
121 static unsigned char data[];
122};
123
124const InetHostAddress PacketsPattern::destinationAddress =
125 InetHostAddress("localhost");
126
127unsigned char PacketsPattern::data[] = {
128 "0123456789\n"
129};
130
131PacketsPattern pattern;
132
133static char* fixKey = (char *)"c2479f224b21c2008deea6ef0e5dbd4a761aef98e7ebf8eed405986c4687";
134
135// static uint8* masterKey = (uint8*)"masterKeymasterKeymasterKeymaster";
136// static uint8* masterSalt = (uint8*)"NaClNaClNaClNa";
137
138uint8 masterKey[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
139 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
140
141uint8 masterSalt[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
142 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d };
143
144static uint8 binKeys[60];
145
146class SendPacketTransmissionTest: public Thread, public TimerPort
147{
148public:
149 void run() {
150 doTest();
151 }
152
153 int doTest()
154 {
155 // should be valid?
156 //RTPSession tx();
157 RTPSession tx(pattern.getSsrc(), InetHostAddress("localhost"));
158 tx.setSchedulingTimeout(10000);
159 tx.setExpireTimeout(1000000);
160
161 CryptoContext* txCryptoCtx =
162 new CryptoContext(pattern.getSsrc(),
163 0, // roc,
164 0L, // keydr << 48,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500165 cryptoAlgo, // encryption algo
Emeric Vigier2f625822012-08-06 11:09:52 -0400166 SrtpAuthenticationSha1Hmac, // authtication algo
167 masterKey, // Master Key
168 128 / 8, // Master Key length
169 masterSalt, // Master Salt
170 112 / 8, // Master Salt length
171 128 / 8, // encryption keyl
172 160 / 8, // authentication key len (SHA1))
173 112 / 8, // session salt len
174 80 / 8); // authentication tag len
175 txCryptoCtx->deriveSrtpKeys(0);
176
177 tx.setOutQueueCryptoContext(txCryptoCtx);
178
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500179 CryptoContextCtrl* txCryptoCtxCtrl = new CryptoContextCtrl(0,
180 cryptoAlgo, // encryption algo
181 SrtpAuthenticationSha1Hmac, // authtication algo
182 masterKey, // Master Key
183 128 / 8, // Master Key length
184 masterSalt, // Master Salt
185 112 / 8, // Master Salt length
186 128 / 8, // encryption keyl
187 160 / 8, // authentication key len (SHA1))
188 112 / 8, // session salt len
189 80 / 8); // authentication tag len
190 tx.setOutQueueCryptoContextCtrl(txCryptoCtxCtrl);
191
Emeric Vigier2f625822012-08-06 11:09:52 -0400192 tx.startRunning();
193
194 tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
195 if (!tx.addDestination(pattern.getDestinationAddress(), pattern.getDestinationPort()) ) {
196 return 1;
197 }
198
199 // 50 packets per second (packet duration of 20ms)
200 uint32 period = 20;
201 uint16 inc = tx.getCurrentRTPClockRate()/50;
202 TimerPort::setTimer(period);
203 for ( uint32 i = 0; i < pattern.getPacketsNumber(); i++ ) {
204 tx.putData(i*inc, pattern.getPacketData(i), pattern.getPacketSize(i));
205 cout << "Sent some data: " << i << endl;
206 Thread::sleep(TimerPort::getTimer());
207 TimerPort::incTimer(period);
208 }
209 return 0;
210 }
211};
212
213
214class RecvPacketTransmissionTest: public Thread
215{
216public:
217 void run() {
218 doTest();
219 }
220
221 int doTest()
222 {
223 RTPSession rx(pattern.getSsrc(), pattern.getDestinationAddress(),
224 pattern.getDestinationPort());
225
226 rx.setSchedulingTimeout(10000);
227 rx.setExpireTimeout(1000000);
228
229 CryptoContext* rxCryptoCtx =
230 new CryptoContext(0, // SSRC == 0 -> Context template
231 0, // roc,
232 0L, // keydr << 48,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500233 cryptoAlgo, // encryption algo
Emeric Vigier2f625822012-08-06 11:09:52 -0400234 SrtpAuthenticationSha1Hmac, // authtication algo
235 masterKey, // Master Key
236 128 / 8, // Master Key length
237 masterSalt, // Master Salt
238 112 / 8, // Master Salt length
239 128 / 8, // encryption keyl
240 160 / 8, // authentication keylen (SHA1))
241 112 / 8, // session salt len
242 80 / 8); // authentication tag len
243 rx.setInQueueCryptoContext(rxCryptoCtx);
244
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500245 CryptoContextCtrl* rxCryptoCtxCtrl = new CryptoContextCtrl(0,
246 cryptoAlgo, // encryption algo
247 SrtpAuthenticationSha1Hmac, // authtication algo
248 masterKey, // Master Key
249 128 / 8, // Master Key length
250 masterSalt, // Master Salt
251 112 / 8, // Master Salt length
252 128 / 8, // encryption keyl
253 160 / 8, // authentication key len (SHA1))
254 112 / 8, // session salt len
255 80 / 8); // authentication tag len
256
257 rx.setInQueueCryptoContextCtrl(rxCryptoCtxCtrl);
258
Emeric Vigier2f625822012-08-06 11:09:52 -0400259 rx.startRunning();
260 rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
261 // arbitrary number of loops
262 for ( int i = 0; i < 500 ; i++ ) {
263 const AppDataUnit* adu;
264 while ( (adu = rx.getData(rx.getFirstTimestamp())) ) {
265 cerr << "got some data: " << adu->getData() << endl;
266 delete adu;
267 }
268 Thread::sleep(70);
269 }
270 return 0;
271 }
272};
273
Emeric Vigier2f625822012-08-06 11:09:52 -0400274int main(int argc, char *argv[])
275{
276 int result = 0;
277 bool send = false;
278 bool recv = false;
279 bool f8Test = false;
280
Emeric Vigier2f625822012-08-06 11:09:52 -0400281 char* inputKey = NULL;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500282 char *args = *argv++;
Emeric Vigier2f625822012-08-06 11:09:52 -0400283
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500284 while(NULL != (args = *argv++)) {
285 if(*args == '-')
286 ++args;
287 if(!strcmp(args, "r") || !strcmp(args, "recv"))
Emeric Vigier2f625822012-08-06 11:09:52 -0400288 recv = true;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500289 else if(!strcmp(args, "s") || !strcmp(args, "send"))
Emeric Vigier2f625822012-08-06 11:09:52 -0400290 send = true;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500291 else if(!strcmp(args, "8") || !strcmp(args, "8test"))
Emeric Vigier2f625822012-08-06 11:09:52 -0400292 f8Test = true;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500293 else if(!strcmp(args, "k") || !strcmp(args, "key"))
294 inputKey = *argv++;
295 else
296 fprintf(stderr, "*** ccsrtptest: %s: unknown option\n", args);
Emeric Vigier2f625822012-08-06 11:09:52 -0400297 }
298
299 if (inputKey == NULL) {
300 inputKey = fixKey;
301 }
302 hex_string_to_octet_string((char*)binKeys, inputKey, 60);
303
304 if (send || recv) {
305 if (send) {
306 cout << "Running as sender" << endl;
307 }
308 else {
309 cout << "Running as receiver" << endl;
310 }
311 }
312 else if (f8Test) {
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500313 cout << "Running F8 test: ";
Emeric Vigier2f625822012-08-06 11:09:52 -0400314 int ret = testF8();
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500315 cout << ret << endl;
Emeric Vigier2f625822012-08-06 11:09:52 -0400316 exit(ret);
317 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400318 RecvPacketTransmissionTest *rx;
319 SendPacketTransmissionTest *tx;
320
321 // accept as parameter if must run as -s, -r, -8
322
323 // run several tests in parallel threads
324 if (send) {
325 tx = new SendPacketTransmissionTest();
326 tx->start();
327 tx->join();
328 } else if (recv) {
329 rx = new RecvPacketTransmissionTest();
330 rx->start();
331 rx->join();
332 }
333 exit(result);
334}
335
336/** EMACS **
337 * Local variables:
338 * mode: c++
339 * c-basic-offset: 4
340 * End:
341 */
342