ccRTP 2.1.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
queue.cpp
Go to the documentation of this file.
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 
40 #include "private.h"
41 #include <ccrtp/queuebase.h>
42 #include <ccrtp/ioqueue.h>
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 
65 class Digest : protected streambuf, public ostream
66 {
67 protected:
68  Digest();
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 
100  friend std::ostream &operator<<(std::ostream &os, Digest &ia)
101  {return ia.strDigest(os);}
102 
103 public:
107  virtual void initDigest(void) = 0;
108 };
109 
111 streambuf()
112 #ifdef HAVE_OLD_IOSTREAM
113 ,ostream()
114 #else
115 ,ostream((streambuf *)this)
116 #endif
117 {
118 #ifdef HAVE_OLD_IOSTREAM
119  init((streambuf *)this);
120 #endif
121 }
122 
129 class MD5Digest : public Digest
130 {
131 private:
132  unsigned long state[4];
133  unsigned long count[2];
134  unsigned char buf[64];
135  unsigned bpos;
136  unsigned char md5[16];
137  bool updated;
138 
139 protected:
140  int overflow(int c);
141 
142  void update(void);
143 
144  void commit(void);
145 
146  std::ostream &strDigest(std::ostream &os);
147 
148 public:
149  MD5Digest();
150 
151  void initDigest(void);
152 
153  inline unsigned getSize(void)
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 
165 #define S11 7
166 #define S12 12
167 #define S13 17
168 #define S14 22
169 #define S21 5
170 #define S22 9
171 #define S23 14
172 #define S24 20
173 #define S31 4
174 #define S32 11
175 #define S33 16
176 #define S34 23
177 #define S41 6
178 #define S42 10
179 #define S43 15
180 #define S44 21
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 
238 Digest()
239 {
240  initDigest();
241  updated = true;
242 }
243 
245 {
246  count[0] = count[1] = 0;
247  state[0] = 0x67452301;
248  state[1] = 0xefcdab89;
249  state[2] = 0x98badcfe;
250  state[3] = 0x10325476;
251  bpos = 0;
252  updated = true; // CCY Added
253  setp((char*)buf,(char*)buf+64);
254 }
255 
257 {
258  updated = true;
259  bpos = (unsigned char*)pptr()-buf;
260  if(bpos >= 64)
261  update();
262  if (c != EOF)
263  buf[bpos++] = (unsigned char)c;
264  setp((char*)buf+bpos,(char*)buf+64);
265 
266  return c;
267 }
268 
270 {
271  unsigned long x[16], a, b, c, d;
272  int i;
273 
274  if(!bpos)
275  return;
276 
277  while(bpos < 64)
278  buf[bpos++] = 0;
279  bpos = 0;
280 
281  if((count[0] += 512) < 512)
282  ++count[1];
283 
284  a = state[0];
285  b = state[1];
286  c = state[2];
287  d = state[3];
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 
363  state[0] += a;
364  state[1] += b;
365  state[2] += c;
366  state[3] += d;
367  updated = true;
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;
381  if(!updated && !bpos)
382  return;
383 
384  count[0] += (unsigned long)(bpos << 3);
385  if(count[0] < (unsigned long)(bpos << 3))
386  ++count[1];
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)
398  putDigest(pad, len);
399 
400  putDigest(cbuf, 8);
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  }
408  initDigest();
409 }
410 
411 unsigned MD5Digest::getDigest(unsigned char *buffer)
412 {
413  commit();
414 
415  memcpy(buffer, md5, 16);
416  return 16;
417 }
418 
419 void MD5Digest::putDigest(const unsigned char *buffer, unsigned len)
420 {
421  bpos = (unsigned char*)pptr()-buf;
422  if(bpos >= 64)
423  update();
424  while(len--) {
425  buf[bpos++] = *(buffer++);
426  if(bpos >= 64)
427  update();
428  }
429  setp((char*)buf+bpos,(char*)buf+64);
430 }
431 
432 std::ostream &MD5Digest::strDigest(std::ostream &os)
433 {
434  char dbuf[36];
435  int i;
436 
437  commit();
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,
477  defaultApplication().getSDESItem(SDESItemTypeCNAME).c_str(),10);
478 
479  // compute MD5.
480  MD5Digest 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 
492 uint32 random32()
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 
514 uint16 random16()
515 {
516  uint32 r32 = random32();
517  uint16 r16 = r32 & (r32 >> 16);
518  return r16;
519 }
520 
522 {
523  if ( NULL == ssrc )
525  else
526  setLocalSSRC(*ssrc);
527 
528  // assume a default rate and payload type.
530  // queue/session creation time
531  SysTime::gettimeofday(&initialTime,NULL);
532 }
533 
534 const uint32 RTPDataQueue::defaultSessionBw = 64000;
535 
538 {
539  initQueue();
540 }
541 
542 RTPDataQueue::RTPDataQueue(uint32* ssrc, uint32 size):
543 RTPQueueBase(ssrc), IncomingDataQueue(size), OutgoingDataQueue(), timeclock()
544 {
545  initQueue();
546  setLocalSSRC(*ssrc); // TODO - Strange - ssrc should be initialized via RTPQueueBase constructor
547 }
548 
549 // Initialize everything
551 {
552  dataServiceActive = false;
553  typeOfService = tosBestEffort; // assume a best effort network
555 }
556 
558 {
559  // stop executing the data service.
560  dataServiceActive = false;
561 
562  // purge both sending and receiving queues.
563 #ifdef CCXX_EXCEPTIONS
564  try {
565 #endif
568 #ifdef CCXX_EXCEPTIONS
569  } catch (...) { }
570 #endif
571  removeOutQueueCryptoContext(NULL); // remove the outgoing crypto context
572  removeInQueueCryptoContext(NULL); // Remove any incoming crypto contexts
573 }
574 
575 uint32
577 {
578  // translate from current time to timestamp
579  timeval now;
580  SysTime::gettimeofday(&now,NULL);
581 
582  int32 result = now.tv_usec - getInitialTime().tv_usec;
583  result *= (getCurrentRTPClockRate()/1000);
584  result /= 1000;
585  result += (now.tv_sec - getInitialTime().tv_sec) * getCurrentRTPClockRate();
586 
587  //result -= initialTimestamp;
588  return result;
589 }
590 
591 END_NAMESPACE
592 
Generic RTP input/output queues.
#define S41
Definition: queue.cpp:177
RTPDataQueue(uint32 size=defaultMembersHashSize)
Constructor.
Definition: queue.cpp:536
Best-effort network service.
Definition: ioqueue.h:99
ITU-T G.711. mu-law audio 8 Khz (RFC 1890)
Definition: formats.h:75
bool updated
Definition: queue.cpp:137
#define S11
Definition: queue.cpp:165
Tos typeOfService
Definition: ioqueue.h:318
#define S32
Definition: queue.cpp:174
Canonical end-point identifier.
Definition: rtcppkt.h:67
#define S34
Definition: queue.cpp:176
bool setPayloadFormat(const PayloadFormat &pf)
Set the payload format in use, for timing and payload type identification purposes.
Definition: queuebase.h:177
#define S42
Definition: queue.cpp:178
int overflow(int c)
Definition: queue.cpp:256
#define S43
Definition: queue.cpp:179
MD5Digest()
Definition: queue.cpp:237
Queue for incoming RTP data packets in an RTP session.
Definition: iqueue.h:883
static const uint32 defaultSessionBw
Definition: ioqueue.h:321
#define S13
Definition: queue.cpp:167
timeval getInitialTime() const
Definition: queuebase.h:201
Declaration of ccRTP internal stuff.
uint32 sessionBw
Definition: ioqueue.h:322
void putDigest(const unsigned char *buffer, unsigned len)
Put data into the digest bypassing the stream subsystem.
Definition: queue.cpp:419
#define S14
Definition: queue.cpp:168
void endQueue()
This method ends the queue.
Definition: queue.cpp:557
#define S31
Definition: queue.cpp:173
virtual std::ostream & strDigest(std::ostream &os)=0
print a digest string for export.
unsigned long state[4]
Definition: queue.cpp:132
#define S24
Definition: queue.cpp:172
unsigned char buf[64]
Definition: queue.cpp:134
void initDigest(void)
Reset the digest table to an initial default value.
Definition: queue.cpp:244
#define S23
Definition: queue.cpp:171
Digest()
Definition: queue.cpp:110
uint32 random32()
Definition: queue.cpp:492
Base classes for RTP queues.
void setLocalSSRC(uint32 ssrc)
Definition: queuebase.h:211
A md5 collection/computation accululator class.
Definition: queue.cpp:129
void purgeOutgoingQueue()
Definition: outqueue.cpp:203
unsigned long count[2]
Definition: queue.cpp:133
A virtual base class for RTP queue hierarchies.
Definition: queuebase.h:166
std::ostream & strDigest(std::ostream &os)
print a digest string for export.
Definition: queue.cpp:432
#define S12
Definition: queue.cpp:166
RTPQueueBase(uint32 *ssrc=NULL)
Definition: queue.cpp:521
uint16 random16()
Definition: queue.cpp:514
unsigned bpos
Definition: queue.cpp:135
#define S33
Definition: queue.cpp:175
uint32 getCurrentTimestamp() const
Get the timestamp that should be given for a packet whose payload sampling instant corresponds to the...
Definition: queue.cpp:576
void purgeIncomingQueue()
Definition: incqueue.cpp:105
void removeOutQueueCryptoContext(CryptoContext *cc)
Remove output queue CryptoContext.
Definition: outqueue.cpp:636
void update(void)
Definition: queue.cpp:269
void commit(void)
Definition: queue.cpp:370
unsigned char md5[16]
Definition: queue.cpp:136
#define S21
Definition: queue.cpp:169
#define S44
Definition: queue.cpp:180
timeval initialTime
Definition: queuebase.h:246
Static payload format objects.
Definition: formats.h:200
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).
Definition: queuebase.h:195
void initQueue()
Global queue initialization.
Definition: queue.cpp:550
friend std::ostream & operator<<(std::ostream &os, Digest &ia)
Definition: queue.cpp:100
A generic outgoing RTP data queue supporting multiple destinations.
Definition: oqueue.h:219
__EXPORT RTPApplication & defaultApplication()
Get the RTPApplication object for the "default" application (the only one used by common applications...
Definition: source.cpp:128
void removeInQueueCryptoContext(CryptoContext *cc)
Remove input queue CryptoContext.
Definition: incqueue.cpp:748
unsigned getSize(void)
Get the size of a digest in octets.
Definition: queue.cpp:153
#define S22
Definition: queue.cpp:170
uint32 getDefaultSessionBandwidth() const
Definition: ioqueue.h:215
unsigned getDigest(unsigned char *buffer)
Copy the binary digest buffer to user memory.
Definition: queue.cpp:411
The digest base class is used for implementing and deriving one way hashing functions.
Definition: queue.cpp:65
volatile bool dataServiceActive
Definition: ioqueue.h:317