Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/rtp_rtcp/source/ssrc_database.h"
     12 
     13 #include <assert.h>
     14 #include <stdlib.h>
     15 
     16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     17 
     18 #ifdef _WIN32
     19     #include <windows.h>
     20     #include <MMSystem.h> //timeGetTime
     21 
     22 // TODO(hellner): investigate if it is necessary to disable these warnings.
     23     #pragma warning(disable:4311)
     24     #pragma warning(disable:4312)
     25 #else
     26     #include <stdio.h>
     27     #include <string.h>
     28     #include <time.h>
     29     #include <sys/time.h>
     30 #endif
     31 
     32 namespace webrtc {
     33 SSRCDatabase*
     34 SSRCDatabase::StaticInstance(CountOperation count_operation)
     35 {
     36   SSRCDatabase* impl =
     37       GetStaticInstance<SSRCDatabase>(count_operation);
     38   return impl;
     39 }
     40 
     41 SSRCDatabase*
     42 SSRCDatabase::GetSSRCDatabase()
     43 {
     44     return StaticInstance(kAddRef);
     45 }
     46 
     47 void
     48 SSRCDatabase::ReturnSSRCDatabase()
     49 {
     50     StaticInstance(kRelease);
     51 }
     52 
     53 uint32_t
     54 SSRCDatabase::CreateSSRC()
     55 {
     56     CriticalSectionScoped lock(_critSect);
     57 
     58     uint32_t ssrc = GenerateRandom();
     59 
     60 #ifndef WEBRTC_NO_STL
     61 
     62     while(_ssrcMap.find(ssrc) != _ssrcMap.end())
     63     {
     64         ssrc = GenerateRandom();
     65     }
     66     _ssrcMap[ssrc] = 0;
     67 
     68 #else
     69     if(_sizeOfSSRC <= _numberOfSSRC)
     70     {
     71         // allocate more space
     72         const int newSize = _sizeOfSSRC + 10;
     73         uint32_t* tempSSRCVector = new uint32_t[newSize];
     74         memcpy(tempSSRCVector, _ssrcVector, _sizeOfSSRC*sizeof(uint32_t));
     75         delete [] _ssrcVector;
     76 
     77         _ssrcVector = tempSSRCVector;
     78         _sizeOfSSRC = newSize;
     79     }
     80 
     81     // check if in DB
     82     if(_ssrcVector)
     83     {
     84         for (int i=0; i<_numberOfSSRC; i++)
     85         {
     86             if (_ssrcVector[i] == ssrc)
     87             {
     88                 // we have a match
     89                 i = 0; // start over with a new ssrc
     90                 ssrc = GenerateRandom();
     91             }
     92 
     93         }
     94         //  add to database
     95         _ssrcVector[_numberOfSSRC] = ssrc;
     96         _numberOfSSRC++;
     97     }
     98 #endif
     99     return ssrc;
    100 }
    101 
    102 int32_t
    103 SSRCDatabase::RegisterSSRC(const uint32_t ssrc)
    104 {
    105     CriticalSectionScoped lock(_critSect);
    106 
    107 #ifndef WEBRTC_NO_STL
    108 
    109     _ssrcMap[ssrc] = 0;
    110 
    111 #else
    112     if(_sizeOfSSRC <= _numberOfSSRC)
    113     {
    114         // allocate more space
    115         const int newSize = _sizeOfSSRC + 10;
    116         uint32_t* tempSSRCVector = new uint32_t[newSize];
    117         memcpy(tempSSRCVector, _ssrcVector, _sizeOfSSRC*sizeof(uint32_t));
    118         delete [] _ssrcVector;
    119 
    120         _ssrcVector = tempSSRCVector;
    121         _sizeOfSSRC = newSize;
    122     }
    123     // check if in DB
    124     if(_ssrcVector)
    125     {
    126         for (int i=0; i<_numberOfSSRC; i++)
    127         {
    128             if (_ssrcVector[i] == ssrc)
    129             {
    130                 // we have a match
    131                 return -1;
    132             }
    133         }
    134         //  add to database
    135         _ssrcVector[_numberOfSSRC] = ssrc;
    136         _numberOfSSRC++;
    137     }
    138 #endif
    139     return 0;
    140 }
    141 
    142 int32_t
    143 SSRCDatabase::ReturnSSRC(const uint32_t ssrc)
    144 {
    145     CriticalSectionScoped lock(_critSect);
    146 
    147 #ifndef WEBRTC_NO_STL
    148     _ssrcMap.erase(ssrc);
    149 
    150 #else
    151     if(_ssrcVector)
    152     {
    153         for (int i=0; i<_numberOfSSRC; i++)
    154         {
    155             if (_ssrcVector[i] == ssrc)
    156             {
    157                 // we have a match
    158                 // remove from database
    159                 _ssrcVector[i] = _ssrcVector[_numberOfSSRC-1];
    160                 _numberOfSSRC--;
    161                 break;
    162             }
    163         }
    164     }
    165 #endif
    166     return 0;
    167 }
    168 
    169 SSRCDatabase::SSRCDatabase()
    170 {
    171     // we need to seed the random generator, otherwise we get 26500 each time, hardly a random value :)
    172 #ifdef _WIN32
    173     srand(timeGetTime());
    174 #else
    175     struct timeval tv;
    176     struct timezone tz;
    177     gettimeofday(&tv, &tz);
    178     srand(tv.tv_usec);
    179 #endif
    180 
    181 #ifdef WEBRTC_NO_STL
    182     _sizeOfSSRC = 10;
    183     _numberOfSSRC = 0;
    184     _ssrcVector = new uint32_t[10];
    185 #endif
    186     _critSect = CriticalSectionWrapper::CreateCriticalSection();
    187 }
    188 
    189 SSRCDatabase::~SSRCDatabase()
    190 {
    191 #ifdef WEBRTC_NO_STL
    192     delete [] _ssrcVector;
    193 #else
    194     _ssrcMap.clear();
    195 #endif
    196     delete _critSect;
    197 }
    198 
    199 uint32_t SSRCDatabase::GenerateRandom()
    200 {
    201     uint32_t ssrc = 0;
    202     do
    203     {
    204         ssrc = rand();
    205         ssrc = ssrc <<16;
    206         ssrc += rand();
    207 
    208     } while (ssrc == 0 || ssrc == 0xffffffff);
    209 
    210     return ssrc;
    211 }
    212 }  // namespace webrtc
    213