1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction. Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License. This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27 //
28 // This exception applies only to the code released under the name GNU
29 // ccRTP. If you copy code from other releases into a copy of GNU
30 // ccRTP, as the General Public License permits, the exception does
31 // not apply to the code that you add in this way. To avoid misleading
32 // anyone as to the status of such modified files, you must delete
33 // this exception notice from them.
34 //
35 // If you write modifications of your own for GNU ccRTP, it is your choice
36 // whether to permit this exception to apply to your modifications.
37 // If you do not wish that, delete this exception notice.
38 //
39
43 #include <cstdio>
44 #include <cstring>
45
46 #ifndef _MSWINDOWS_
47 #include <fcntl.h>
48 #endif
49
50 NAMESPACE_COMMONCPP
51 using namespace std;
52
53 // The first part of this file includes a copy of the MD5Digest class
54 // of Common C++. This may seem weird, but it would be the only
55 // dependency on libccext, so we prefer to reduce the library
56 // footprint.
57
66 {
67 protected:
69
75 virtual unsigned getSize(void) = 0;
76
83 virtual unsigned getDigest(unsigned char *buffer) = 0;
84
91 virtual void putDigest(const unsigned char *buffer, unsigned length) = 0;
92
98 virtual std::ostream &strDigest(std::ostream &os) = 0;
99
102
103 public:
107 virtual void initDigest(void) = 0;
108 };
109
112 #ifdef HAVE_OLD_IOSTREAM
114 #else
116 #endif
117 {
118 #ifdef HAVE_OLD_IOSTREAM
120 #endif
121 }
122
130 {
131 private:
138
139 protected:
141
143
145
146 std::ostream &
strDigest(std::ostream &os);
147
148 public:
150
152
154 {return 16;}
155
156 unsigned getDigest(
unsigned char *buffer);
157
158 void putDigest(
const unsigned char *buffer,
unsigned len);
159 };
160
161 #ifdef _MSWINDOWS_
162 #include <io.h>
163 #endif
164
181
182 static inline unsigned long rotate_left(unsigned long x, unsigned long n)
183 {
184 // is unsigned long > 32 bit mask
185 #if ~0lu != 0xfffffffflu
186 return (x << n) | ((x & 0xffffffffu) >> (32-n));
187 #else
188 return (x << n) | (x >> (32-n));
189 #endif
190 }
191
192 static inline unsigned long F(unsigned long x, unsigned long y, unsigned long z)
193 {
194 return (x & y) | (~x & z);
195 }
196
197 static inline unsigned long G(unsigned long x, unsigned long y, unsigned long z)
198 {
199 return (x & z) | (y & ~z);
200 }
201
202 static inline unsigned long H(unsigned long x, unsigned long y, unsigned long z)
203 {
204 return x ^ y ^ z;
205 }
206
207 static inline unsigned long md5I(unsigned long x, unsigned long y, unsigned long z)
208 {
209 return y ^ (x | ~z);
210 }
211
212
213 static void FF(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
214 {
215 a += F(b, c, d) + x + ac;
216 a = rotate_left(a, s) + b;
217 }
218
219 static void GG(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
220 {
221 a += G(b, c, d) + x + ac;
222 a = rotate_left(a, s) + b;
223 }
224
225 static void HH(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
226 {
227 a += H(b, c, d) + x + ac;
228 a = rotate_left(a, s) + b;
229 }
230
231 static void II(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
232 {
233 a += md5I(b, c, d) + x + ac;
234 a = rotate_left(a, s) + b;
235 }
236
239 {
242 }
243
245 {
247 state[0] = 0x67452301;
248 state[1] = 0xefcdab89;
249 state[2] = 0x98badcfe;
250 state[3] = 0x10325476;
253 setp((
char*)
buf,(
char*)
buf+64);
254 }
255
257 {
259 bpos = (
unsigned char*)pptr()-
buf;
262 if (c != EOF)
263 buf[
bpos++] = (
unsigned char)c;
265
266 return c;
267 }
268
270 {
271 unsigned long x[16], a, b, c, d;
272 int i;
273
275 return;
276
280
281 if((
count[0] += 512) < 512)
283
288
289 for(i = 0; i < 16; ++i)
290 x[i] = (
unsigned long)(
buf[i * 4]) |
291 (
unsigned long)(
buf[i * 4 + 1] << 8) |
292 (
unsigned long)(
buf[i * 4 + 2] << 16) |
293 (
unsigned long)(
buf[i * 4 + 3] << 24);
294
295 FF(a, b, c, d, x[ 0],
S11, 0xd76aa478);
296 FF(d, a, b, c, x[ 1],
S12, 0xe8c7b756);
297 FF(c, d, a, b, x[ 2],
S13, 0x242070db);
298 FF(b, c, d, a, x[ 3],
S14, 0xc1bdceee);
299 FF(a, b, c, d, x[ 4],
S11, 0xf57c0faf);
300 FF(d, a, b, c, x[ 5],
S12, 0x4787c62a);
301 FF(c, d, a, b, x[ 6],
S13, 0xa8304613);
302 FF(b, c, d, a, x[ 7],
S14, 0xfd469501);
303 FF(a, b, c, d, x[ 8],
S11, 0x698098d8);
304 FF(d, a, b, c, x[ 9],
S12, 0x8b44f7af);
305 FF(c, d, a, b, x[10],
S13, 0xffff5bb1);
306 FF(b, c, d, a, x[11],
S14, 0x895cd7be);
307 FF(a, b, c, d, x[12],
S11, 0x6b901122);
308 FF(d, a, b, c, x[13],
S12, 0xfd987193);
309 FF(c, d, a, b, x[14],
S13, 0xa679438e);
310 FF(b, c, d, a, x[15],
S14, 0x49b40821);
311
312 GG(a, b, c, d, x[ 1],
S21, 0xf61e2562);
313 GG(d, a, b, c, x[ 6],
S22, 0xc040b340);
314 GG(c, d, a, b, x[11],
S23, 0x265e5a51);
315 GG(b, c, d, a, x[ 0],
S24, 0xe9b6c7aa);
316 GG(a, b, c, d, x[ 5],
S21, 0xd62f105d);
317 GG(d, a, b, c, x[10],
S22, 0x2441453);
318 GG(c, d, a, b, x[15],
S23, 0xd8a1e681);
319 GG(b, c, d, a, x[ 4],
S24, 0xe7d3fbc8);
320 GG(a, b, c, d, x[ 9],
S21, 0x21e1cde6);
321 GG(d, a, b, c, x[14],
S22, 0xc33707d6);
322 GG(c, d, a, b, x[ 3],
S23, 0xf4d50d87);
323 GG(b, c, d, a, x[ 8],
S24, 0x455a14ed);
324 GG(a, b, c, d, x[13],
S21, 0xa9e3e905);
325 GG(d, a, b, c, x[ 2],
S22, 0xfcefa3f8);
326 GG(c, d, a, b, x[ 7],
S23, 0x676f02d9);
327 GG(b, c, d, a, x[12],
S24, 0x8d2a4c8a);
328
329 HH(a, b, c, d, x[ 5],
S31, 0xfffa3942);
330 HH(d, a, b, c, x[ 8],
S32, 0x8771f681);
331 HH(c, d, a, b, x[11],
S33, 0x6d9d6122);
332 HH(b, c, d, a, x[14],
S34, 0xfde5380c);
333 HH(a, b, c, d, x[ 1],
S31, 0xa4beea44);
334 HH(d, a, b, c, x[ 4],
S32, 0x4bdecfa9);
335 HH(c, d, a, b, x[ 7],
S33, 0xf6bb4b60);
336 HH(b, c, d, a, x[10],
S34, 0xbebfbc70);
337 HH(a, b, c, d, x[13],
S31, 0x289b7ec6);
338 HH(d, a, b, c, x[ 0],
S32, 0xeaa127fa);
339 HH(c, d, a, b, x[ 3],
S33, 0xd4ef3085);
340 HH(b, c, d, a, x[ 6],
S34, 0x4881d05);
341 HH(a, b, c, d, x[ 9],
S31, 0xd9d4d039);
342 HH(d, a, b, c, x[12],
S32, 0xe6db99e5);
343 HH(c, d, a, b, x[15],
S33, 0x1fa27cf8);
344 HH(b, c, d, a, x[ 2],
S34, 0xc4ac5665);
345
346 II(a, b, c, d, x[ 0],
S41, 0xf4292244);
347 II(d, a, b, c, x[ 7],
S42, 0x432aff97);
348 II(c, d, a, b, x[14],
S43, 0xab9423a7);
349 II(b, c, d, a, x[ 5],
S44, 0xfc93a039);
350 II(a, b, c, d, x[12],
S41, 0x655b59c3);
351 II(d, a, b, c, x[ 3],
S42, 0x8f0ccc92);
352 II(c, d, a, b, x[10],
S43, 0xffeff47d);
353 II(b, c, d, a, x[ 1],
S44, 0x85845dd1);
354 II(a, b, c, d, x[ 8],
S41, 0x6fa87e4f);
355 II(d, a, b, c, x[15],
S42, 0xfe2ce6e0);
356 II(c, d, a, b, x[ 6],
S43, 0xa3014314);
357 II(b, c, d, a, x[13],
S44, 0x4e0811a1);
358 II(a, b, c, d, x[ 4],
S41, 0xf7537e82);
359 II(d, a, b, c, x[11],
S42, 0xbd3af235);
360 II(c, d, a, b, x[ 2],
S43, 0x2ad7d2bb);
361 II(b, c, d, a, x[ 9],
S44, 0xeb86d391);
362
368 }
369
371 {
372 unsigned char cbuf[8];
373 unsigned long i, len;
374
375 static unsigned char pad[64]={
376 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
379
380 bpos = (
unsigned char*)pptr()-
buf;
382 return;
383
385 if(
count[0] < (
unsigned long)(
bpos << 3))
387
388 for(i = 0; i < 2; ++i) {
389 cbuf[i * 4] = (
unsigned char)
count[i] & 0xff;
390 cbuf[i * 4 + 1] = (
unsigned char)((
count[i] >> 8) & 0xff);
391 cbuf[i * 4 + 2] = (
unsigned char)((
count[i] >> 16) & 0xff);
392 cbuf[i * 4 + 3] = (
unsigned char)((
count[i] >> 24) & 0xff);
393 }
394
395 i = (unsigned) ((
count[0] >> 3) & 0x3f);
396 len = (i < 56) ? (56 - i) : (120 - i);
397 if(len)
399
401
402 for(i = 0; i < 4; ++i) {
403 md5[i * 4] = (
unsigned char)
state[i] & 0xff;
404 md5[i * 4 + 1] = (
unsigned char)((
state[i] >> 8) & 0xff);
405 md5[i * 4 + 2] = (
unsigned char)((
state[i] >> 16) & 0xff);
406 md5[i * 4 + 3] = (
unsigned char)((
state[i] >> 24) & 0xff);
407 }
409 }
410
412 {
414
415 memcpy(buffer,
md5, 16);
416 return 16;
417 }
418
420 {
421 bpos = (
unsigned char*)pptr()-
buf;
424 while(len--) {
428 }
430 }
431
433 {
434 char dbuf[36];
435 int i;
436
438
439 for(i = 0; i < 16; ++i)
440 #ifdef _MSWINDOWS_
441 sprintf(dbuf + 2 * i,
"%02x",
md5[i]);
442 #else
443 std::sprintf(dbuf + 2 * i,
"%02x",
md5[i]);
444 #endif
445 os << dbuf;
446 return os;
447 }
448
449 static uint32 MD5BasedRandom32()
450 {
451 // for bizzare gcc wierdness with type visibility
452 typedef timeval md5time_t;
453
454 // This is the input to the MD5 algorithm.
455 union {
456 uint8 array[1];
457 struct {
458 md5time_t time;
459 void *address;
460 uint8 cname[10];
461 } data;
462 } message;
463
464 // the output from the MD5 algorithm will be put here.
465 union {
466 uint32 buf32[4];
467 uint8 buf8[16];
468 } digest;
469
470 SysTime::gettimeofday(&(message.data.time),NULL);
471 message.array[0] =
472 static_cast<uint8>(message.data.time.tv_sec *
473 message.data.time.tv_usec);
474
475 message.data.address = &message;
476 memcpy(message.data.cname,
478
479 // compute MD5.
481 md5.
putDigest(reinterpret_cast<unsigned char*>(message.array),
482 sizeof(message));
483 md5.
getDigest(reinterpret_cast<unsigned char*>(digest.buf8));
484
485 // Get result as xor of the four 32-bit words from the MD5 algorithm.
486 uint32 result = 0;
487 for ( int i = 0; i < 4; i ++ )
488 result ^= digest.buf32[i];
489 return result;
490 }
491
493 {
494 // If /dev/urandom fails, default to the MD5 based algorithm
495 // given in the RTP specification.
496 uint32 number;
497 #ifndef _MSWINDOWS_
498 bool success = true;
499 int fd = open("/dev/urandom",O_RDONLY);
500 if (fd == -1) {
501 success = false;
502 } else {
503 if ( read(fd,&number,sizeof(number)) != sizeof(number) ) {
504 success = false;
505 }
506 }
507 close(fd);
508 if ( !success )
509 #endif
510 number = MD5BasedRandom32();
511 return number;
512 }
513
515 {
517 uint16 r16 = r32 & (r32 >> 16);
518 return r16;
519 }
520
522 {
523 if ( NULL == ssrc )
525 else
527
528 // assume a default rate and payload type.
530 // queue/session creation time
532 }
533
535
538 {
540 }
541
544 {
546 setLocalSSRC(*ssrc);
// TODO - Strange - ssrc should be initialized via RTPQueueBase constructor
547 }
548
549 // Initialize everything
551 {
555 }
556
558 {
559 // stop executing the data service.
561
562 // purge both sending and receiving queues.
563 #ifdef CCXX_EXCEPTIONS
564 try {
565 #endif
568 #ifdef CCXX_EXCEPTIONS
569 } catch (...) { }
570 #endif
573 }
574
575 uint32
577 {
578 // translate from current time to timestamp
579 timeval now;
580 SysTime::gettimeofday(&now,NULL);
581
584 result /= 1000;
586
587 //result -= initialTimestamp;
588 return result;
589 }
590
591 END_NAMESPACE
592
Generic RTP input/output queues.
RTPDataQueue(uint32 size=defaultMembersHashSize)
Constructor.
Best-effort network service.
ITU-T G.711. mu-law audio 8 Khz (RFC 1890)
Canonical end-point identifier.
bool setPayloadFormat(const PayloadFormat &pf)
Set the payload format in use, for timing and payload type identification purposes.
Queue for incoming RTP data packets in an RTP session.
static const uint32 defaultSessionBw
timeval getInitialTime() const
Declaration of ccRTP internal stuff.
void putDigest(const unsigned char *buffer, unsigned len)
Put data into the digest bypassing the stream subsystem.
void endQueue()
This method ends the queue.
virtual std::ostream & strDigest(std::ostream &os)=0
print a digest string for export.
void initDigest(void)
Reset the digest table to an initial default value.
Base classes for RTP queues.
void setLocalSSRC(uint32 ssrc)
A md5 collection/computation accululator class.
void purgeOutgoingQueue()
A virtual base class for RTP queue hierarchies.
std::ostream & strDigest(std::ostream &os)
print a digest string for export.
RTPQueueBase(uint32 *ssrc=NULL)
uint32 getCurrentTimestamp() const
Get the timestamp that should be given for a packet whose payload sampling instant corresponds to the...
void purgeIncomingQueue()
void removeOutQueueCryptoContext(CryptoContext *cc)
Remove output queue CryptoContext.
uint32 getCurrentRTPClockRate() const
Get the clock rate in RTP clock units (for instance, 8000 units per second for PCMU, or 90000 units per second for MP2T).
void initQueue()
Global queue initialization.
friend std::ostream & operator<<(std::ostream &os, Digest &ia)
A generic outgoing RTP data queue supporting multiple destinations.
__EXPORT RTPApplication & defaultApplication()
Get the RTPApplication object for the "default" application (the only one used by common applications...
void removeInQueueCryptoContext(CryptoContext *cc)
Remove input queue CryptoContext.
unsigned getSize(void)
Get the size of a digest in octets.
uint32 getDefaultSessionBandwidth() const
unsigned getDigest(unsigned char *buffer)
Copy the binary digest buffer to user memory.
The digest base class is used for implementing and deriving one way hashing functions.
volatile bool dataServiceActive