LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/ice - ice_media_stream.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 469 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : Copyright (c) 2007, Adobe Systems, Incorporated
       3             : All rights reserved.
       4             : 
       5             : Redistribution and use in source and binary forms, with or without
       6             : modification, are permitted provided that the following conditions are
       7             : met:
       8             : 
       9             : * Redistributions of source code must retain the above copyright
      10             :   notice, this list of conditions and the following disclaimer.
      11             : 
      12             : * Redistributions in binary form must reproduce the above copyright
      13             :   notice, this list of conditions and the following disclaimer in the
      14             :   documentation and/or other materials provided with the distribution.
      15             : 
      16             : * Neither the name of Adobe Systems, Network Resonance nor the names of its
      17             :   contributors may be used to endorse or promote products derived from
      18             :   this software without specific prior written permission.
      19             : 
      20             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             : */
      32             : 
      33             : 
      34             : 
      35             : static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
      36             : 
      37             : #include <string.h>
      38             : #include <assert.h>
      39             : #include <nr_api.h>
      40             : #include <r_assoc.h>
      41             : #include <async_timer.h>
      42             : #include "ice_util.h"
      43             : #include "ice_ctx.h"
      44             : 
      45             : static char *nr_ice_media_stream_states[]={"INVALID",
      46             :   "UNPAIRED","FROZEN","ACTIVE","CONNECTED","FAILED"
      47             : };
      48             : 
      49             : int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
      50             : 
      51           0 : int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
      52             :   {
      53             :     int r,_status;
      54           0 :     nr_ice_media_stream *stream=0;
      55           0 :     nr_ice_component *comp=0;
      56             :     int i;
      57             : 
      58           0 :     if(!(stream=RCALLOC(sizeof(nr_ice_media_stream))))
      59           0 :       ABORT(R_NO_MEMORY);
      60             : 
      61           0 :     if(!(stream->label=r_strdup(label)))
      62           0 :       ABORT(R_NO_MEMORY);
      63             : 
      64           0 :     stream->ctx=ctx;
      65             : 
      66           0 :     STAILQ_INIT(&stream->components);
      67           0 :     for(i=0;i<components;i++){
      68             :       /* component-id must be > 0, so increment by 1 */
      69           0 :       if(r=nr_ice_component_create(stream, i+1, &comp))
      70           0 :         ABORT(r);
      71             : 
      72             :     }
      73             : 
      74           0 :     TAILQ_INIT(&stream->check_list);
      75           0 :     TAILQ_INIT(&stream->trigger_check_queue);
      76             : 
      77           0 :     stream->disconnected = 0;
      78           0 :     stream->component_ct=components;
      79           0 :     stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
      80           0 :     *streamp=stream;
      81             : 
      82           0 :     _status=0;
      83             :   abort:
      84           0 :     if(_status){
      85           0 :       nr_ice_media_stream_destroy(&stream);
      86             :     }
      87           0 :     return(_status);
      88             :   }
      89             : 
      90           0 : int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
      91             :   {
      92             :     nr_ice_media_stream *stream;
      93             :     nr_ice_component *c1,*c2;
      94             :     nr_ice_cand_pair *p1,*p2;
      95           0 :     if(!streamp || !*streamp)
      96           0 :       return(0);
      97             : 
      98           0 :     stream=*streamp;
      99           0 :     *streamp=0;
     100             : 
     101           0 :     STAILQ_FOREACH_SAFE(c1, &stream->components, entry, c2){
     102           0 :       STAILQ_REMOVE(&stream->components,c1,nr_ice_component_,entry);
     103           0 :       nr_ice_component_destroy(&c1);
     104             :     }
     105             : 
     106             :     /* Note: all the entries from the trigger check queue are held in here as
     107             :      *       well, so we only clean up the super set. */
     108           0 :     TAILQ_FOREACH_SAFE(p1, &stream->check_list, check_queue_entry, p2){
     109           0 :       TAILQ_REMOVE(&stream->check_list,p1,check_queue_entry);
     110           0 :       nr_ice_candidate_pair_destroy(&p1);
     111             :     }
     112             : 
     113           0 :     RFREE(stream->label);
     114             : 
     115           0 :     RFREE(stream->ufrag);
     116           0 :     RFREE(stream->pwd);
     117           0 :     RFREE(stream->r2l_user);
     118           0 :     RFREE(stream->l2r_user);
     119           0 :     r_data_zfree(&stream->r2l_pass);
     120           0 :     r_data_zfree(&stream->l2r_pass);
     121             : 
     122           0 :     if(stream->timer)
     123           0 :       NR_async_timer_cancel(stream->timer);
     124             : 
     125           0 :     RFREE(stream);
     126             : 
     127           0 :     return(0);
     128             :   }
     129             : 
     130           0 : int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
     131             :   {
     132             :     int r,_status;
     133             :     nr_ice_component *comp;
     134             : 
     135           0 :     comp=STAILQ_FIRST(&stream->components);
     136           0 :     while(comp){
     137           0 :       if(r=nr_ice_component_initialize(ctx,comp))
     138           0 :         ABORT(r);
     139           0 :       comp=STAILQ_NEXT(comp,entry);
     140             :     }
     141             : 
     142           0 :     _status=0;
     143             :   abort:
     144           0 :     return(_status);
     145             :   }
     146             : 
     147             : 
     148           0 : int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
     149             :   {
     150           0 :     int attrct=0;
     151             :     nr_ice_component *comp;
     152           0 :     char **attrs=0;
     153           0 :     int index=0;
     154             :     nr_ice_candidate *cand;
     155             :     int r,_status;
     156             : 
     157           0 :     *attrctp=0;
     158             : 
     159             :     /* First find out how many attributes we need */
     160           0 :     comp=STAILQ_FIRST(&stream->components);
     161           0 :     while(comp){
     162           0 :       if (comp->state != NR_ICE_COMPONENT_DISABLED) {
     163           0 :         cand = TAILQ_FIRST(&comp->candidates);
     164           0 :         while(cand){
     165           0 :           if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
     166           0 :             ++attrct;
     167             :           }
     168             : 
     169           0 :           cand = TAILQ_NEXT(cand, entry_comp);
     170             :         }
     171             :       }
     172           0 :       comp=STAILQ_NEXT(comp,entry);
     173             :     }
     174             : 
     175           0 :     if(attrct < 1){
     176           0 :       r_log(LOG_ICE,LOG_ERR,"ICE-STREAM(%s): Failed to find any components for stream",stream->label);
     177           0 :       ABORT(R_FAILED);
     178             :     }
     179             : 
     180             :     /* Make the array we'll need */
     181           0 :     if(!(attrs=RCALLOC(sizeof(char *)*attrct)))
     182           0 :       ABORT(R_NO_MEMORY);
     183           0 :     for(index=0;index<attrct;index++){
     184           0 :       if(!(attrs[index]=RMALLOC(NR_ICE_MAX_ATTRIBUTE_SIZE)))
     185           0 :         ABORT(R_NO_MEMORY);
     186             :     }
     187             : 
     188           0 :     index=0;
     189             :     /* Now format the attributes */
     190           0 :     comp=STAILQ_FIRST(&stream->components);
     191           0 :     while(comp){
     192           0 :       if (comp->state != NR_ICE_COMPONENT_DISABLED) {
     193             :         nr_ice_candidate *cand;
     194             : 
     195           0 :         cand=TAILQ_FIRST(&comp->candidates);
     196           0 :         while(cand){
     197           0 :           if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
     198           0 :             assert(index < attrct);
     199             : 
     200           0 :             if (index >= attrct)
     201           0 :               ABORT(R_INTERNAL);
     202             : 
     203           0 :             if(r=nr_ice_format_candidate_attribute(cand, attrs[index],NR_ICE_MAX_ATTRIBUTE_SIZE))
     204           0 :               ABORT(r);
     205             : 
     206           0 :             index++;
     207             :           }
     208             : 
     209           0 :           cand=TAILQ_NEXT(cand,entry_comp);
     210             :         }
     211             :       }
     212           0 :       comp=STAILQ_NEXT(comp,entry);
     213             :     }
     214             : 
     215           0 :     *attrsp=attrs;
     216           0 :     *attrctp=attrct;
     217             : 
     218           0 :     _status=0;
     219             :   abort:
     220           0 :     if(_status){
     221           0 :       if(attrs){
     222           0 :         for(index=0;index<attrct;index++){
     223           0 :           RFREE(attrs[index]);
     224             :         }
     225           0 :         RFREE(attrs);
     226             :       }
     227             :     }
     228           0 :     return(_status);
     229             :   }
     230             : 
     231             : /* Get a default candidate per 4.1.4 */
     232           0 : int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
     233             :   {
     234             :     int r,_status;
     235             :     nr_ice_component *comp;
     236             : 
     237           0 :     comp=STAILQ_FIRST(&stream->components);
     238           0 :     while(comp){
     239           0 :       if (comp->component_id == component)
     240           0 :         break;
     241             : 
     242           0 :       comp=STAILQ_NEXT(comp,entry);
     243             :     }
     244             : 
     245           0 :     if (!comp)
     246           0 :       ABORT(R_NOT_FOUND);
     247             : 
     248             :     /* If there aren't any IPV4 candidates, try IPV6 */
     249           0 :     if((r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV4)) &&
     250             :        (r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV6))) {
     251           0 :       ABORT(r);
     252             :     }
     253             : 
     254           0 :     _status=0;
     255             :   abort:
     256           0 :     return(_status);
     257             :   }
     258             : 
     259             : 
     260           0 : int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
     261             :   {
     262             :     int r,_status;
     263             :     nr_ice_component *pcomp,*lcomp;
     264             : 
     265           0 :     pcomp=STAILQ_FIRST(&pstream->components);
     266           0 :     lcomp=STAILQ_FIRST(&lstream->components);
     267           0 :     while(pcomp){
     268           0 :       if ((lcomp->state != NR_ICE_COMPONENT_DISABLED) &&
     269           0 :           (pcomp->state != NR_ICE_COMPONENT_DISABLED)) {
     270           0 :         if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
     271           0 :           ABORT(r);
     272             :       }
     273             : 
     274           0 :       lcomp=STAILQ_NEXT(lcomp,entry);
     275           0 :       pcomp=STAILQ_NEXT(pcomp,entry);
     276             :     };
     277             : 
     278           0 :     if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
     279           0 :       nr_ice_media_stream_set_state(pstream, NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
     280             :     }
     281             : 
     282           0 :     _status=0;
     283             :   abort:
     284           0 :     return(_status);
     285             :   }
     286             : 
     287           0 : int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, nr_ice_media_stream *pstream, int *serviced)
     288             :   {
     289             :     nr_ice_component *pcomp;
     290             :     int r,_status;
     291           0 :     char *user = 0;
     292             : 
     293           0 :     if (serviced)
     294           0 :       *serviced = 0;
     295             : 
     296           0 :     pcomp=STAILQ_FIRST(&pstream->components);
     297           0 :     while(pcomp){
     298           0 :       int serviced_inner=0;
     299             : 
     300             :       /* Flush all the pre-answer requests */
     301           0 :       if(r=nr_ice_component_service_pre_answer_requests(pctx, pcomp, pstream->r2l_user, &serviced_inner))
     302           0 :         ABORT(r);
     303           0 :       if (serviced)
     304           0 :         *serviced += serviced_inner;
     305             : 
     306           0 :       pcomp=STAILQ_NEXT(pcomp,entry);
     307             :     }
     308             : 
     309           0 :     _status=0;
     310             :    abort:
     311           0 :     RFREE(user);
     312           0 :     return(_status);
     313             :   }
     314             : 
     315             : /* S 5.8 -- run the first pair from the triggered check queue (even after
     316             :  * checks have completed S 8.1.2) or run the highest priority WAITING pair or
     317             :  * if not available FROZEN pair from the check queue */
     318           0 : static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
     319             :   {
     320             :     int r,_status;
     321           0 :     nr_ice_media_stream *stream=cb_arg;
     322           0 :     nr_ice_cand_pair *pair = 0;
     323           0 :     int timer_multiplier=stream->pctx->active_streams ? stream->pctx->active_streams : 1;
     324           0 :     int timer_val=stream->pctx->ctx->Ta*timer_multiplier;
     325             : 
     326           0 :     assert(timer_val>0);
     327             : 
     328           0 :     r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
     329           0 :     stream->timer=0;
     330             : 
     331             :     /* The trigger check queue has the highest priority */
     332           0 :     pair=TAILQ_FIRST(&stream->trigger_check_queue);
     333           0 :     while(pair){
     334           0 :       if(pair->state==NR_ICE_PAIR_STATE_WAITING){
     335             :         /* Remove the pair from he trigger check queue */
     336           0 :         r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Removing pair from trigger check queue %s",stream->pctx->label,pair->as_string);
     337           0 :         TAILQ_REMOVE(&stream->trigger_check_queue,pair,triggered_check_queue_entry);
     338           0 :         break;
     339             :       }
     340           0 :       pair=TAILQ_NEXT(pair,triggered_check_queue_entry);
     341             :     }
     342             : 
     343           0 :     if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
     344           0 :       if(!pair){
     345             :         /* Find the highest priority WAITING check and move it to RUNNING */
     346           0 :         pair=TAILQ_FIRST(&stream->check_list);
     347           0 :         while(pair){
     348           0 :           if(pair->state==NR_ICE_PAIR_STATE_WAITING)
     349           0 :             break;
     350           0 :           pair=TAILQ_NEXT(pair,check_queue_entry);
     351             :         }
     352             :       }
     353             : 
     354             :       /* Hmmm... No WAITING. Let's look for FROZEN */
     355           0 :       if(!pair){
     356           0 :         pair=TAILQ_FIRST(&stream->check_list);
     357             : 
     358           0 :         while(pair){
     359           0 :           if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
     360           0 :             if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
     361           0 :               ABORT(r);
     362           0 :             break;
     363             :           }
     364           0 :           pair=TAILQ_NEXT(pair,check_queue_entry);
     365             :         }
     366             :       }
     367             :     }
     368             : 
     369           0 :     if(pair){
     370           0 :       nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
     371           0 :       NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
     372             :     }
     373             :     else {
     374           0 :       r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): no pairs for %s",stream->pctx->label,stream->label);
     375             :     }
     376             : 
     377           0 :     _status=0;
     378             :   abort:
     379           0 :     return;
     380             :   }
     381             : 
     382             : /* Start checks for this media stream (aka check list) */
     383           0 : int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
     384             :   {
     385             :     int r,_status;
     386             : 
     387             :     /* Don't start the check timer if the stream is failed */
     388           0 :     if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FAILED) {
     389           0 :       assert(0);
     390             :       ABORT(R_INTERNAL);
     391             :     }
     392             : 
     393             :     /* Even if the stream is completed already remote can still create a new
     394             :      * triggered check request which needs to fire, but not change our stream
     395             :      * state. */
     396           0 :     if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
     397           0 :       if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)) {
     398           0 :         ABORT(r);
     399             :       }
     400             :     }
     401             : 
     402           0 :     if (!stream->timer) {
     403           0 :       r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): Starting check timer for stream.",pctx->label,stream->label);
     404           0 :       nr_ice_media_stream_check_timer_cb(0,0,stream);
     405             :     }
     406             : 
     407           0 :     nr_ice_peer_ctx_stream_started_checks(pctx, stream);
     408             : 
     409           0 :     _status=0;
     410             :   abort:
     411           0 :     return(_status);
     412             :   }
     413             : 
     414             : /* Start checks for this media stream (aka check list) S 5.7 */
     415           0 : int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
     416             :   {
     417             :     int r,_status;
     418           0 :     r_assoc *assoc=0;
     419           0 :     nr_ice_cand_pair *pair=0;
     420             : 
     421             :     /* Already seen assoc */
     422           0 :     if(r=r_assoc_create(&assoc,r_assoc_crc32_hash_compute,5))
     423           0 :       ABORT(r);
     424             : 
     425             :     /* S 5.7.4. Set the highest priority pairs in each foundation to WAITING */
     426           0 :     pair=TAILQ_FIRST(&stream->check_list);
     427           0 :     while(pair){
     428             :       void *v;
     429             : 
     430           0 :       if(r=r_assoc_fetch(assoc,pair->foundation,strlen(pair->foundation),&v)){
     431           0 :         if(r!=R_NOT_FOUND)
     432           0 :           ABORT(r);
     433           0 :         if(r=nr_ice_candidate_pair_unfreeze(pctx,pair))
     434           0 :           ABORT(r);
     435             : 
     436           0 :         if(r=r_assoc_insert(assoc,pair->foundation,strlen(pair->foundation),
     437             :           0,0,0,R_ASSOC_NEW))
     438           0 :           ABORT(r);
     439             :       }
     440             : 
     441             :       /* Already exists... fall through */
     442           0 :       pair=TAILQ_NEXT(pair,check_queue_entry);
     443             :     }
     444             : 
     445           0 :     _status=0;
     446             :   abort:
     447           0 :     r_assoc_destroy(&assoc);
     448           0 :     return(_status);
     449             :   }
     450             : 
     451           0 : static int nr_ice_media_stream_unfreeze_pairs_match(nr_ice_media_stream *stream, char *foundation)
     452             :   {
     453             :     nr_ice_cand_pair *pair;
     454             :     int r,_status;
     455           0 :     int unfroze=0;
     456             : 
     457           0 :     pair=TAILQ_FIRST(&stream->check_list);
     458           0 :     while(pair){
     459           0 :       if(pair->state==NR_ICE_PAIR_STATE_FROZEN &&
     460           0 :         !strcmp(foundation,pair->foundation)){
     461           0 :         if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
     462           0 :           ABORT(r);
     463           0 :         unfroze++;
     464             :       }
     465           0 :       pair=TAILQ_NEXT(pair,check_queue_entry);
     466             :     }
     467             : 
     468           0 :     if(!unfroze)
     469           0 :       return(R_NOT_FOUND);
     470             : 
     471           0 :     _status=0;
     472             :   abort:
     473           0 :     return(_status);
     474             :   }
     475             : 
     476             : /* S 7.1.2.2 */
     477           0 : int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation)
     478             :   {
     479             :     int r,_status;
     480             :     nr_ice_media_stream *str;
     481             :        nr_ice_component *comp;
     482           0 :     int invalid_comps=0;
     483             : 
     484             :     /* 1. Unfreeze all frozen pairs with the same foundation
     485             :        in this stream */
     486           0 :     if(r=nr_ice_media_stream_unfreeze_pairs_match(stream,foundation)){
     487           0 :       if(r!=R_NOT_FOUND)
     488           0 :         ABORT(r);
     489             :     }
     490             : 
     491             :     /* 2. See if there is a pair in the valid list for every component */
     492           0 :     comp=STAILQ_FIRST(&stream->components);
     493           0 :     while(comp){
     494           0 :       if(!comp->valid_pairs)
     495           0 :         invalid_comps++;
     496             : 
     497           0 :       comp=STAILQ_NEXT(comp,entry);
     498             :     }
     499             : 
     500             :     /* If there is a pair in the valid list for every component... */
     501             :     /* Now go through the check lists for the other streams */
     502           0 :     str=STAILQ_FIRST(&stream->pctx->peer_streams);
     503           0 :     while(str){
     504           0 :       if(str!=stream){
     505           0 :         switch(str->ice_state){
     506             :           case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
     507             :             /* Unfreeze matching pairs */
     508           0 :             if(r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation)){
     509           0 :               if(r!=R_NOT_FOUND)
     510           0 :                 ABORT(r);
     511             :             }
     512           0 :             break;
     513             :           case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
     514             :             /* Unfreeze matching pairs if any */
     515           0 :             r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation);
     516           0 :             if(r){
     517           0 :               if(r!=R_NOT_FOUND)
     518           0 :                 ABORT(r);
     519             : 
     520             :               /* OK, no matching pairs: execute the algorithm from 5.7
     521             :                  for this stream */
     522           0 :               if(r=nr_ice_media_stream_unfreeze_pairs(str->pctx,str))
     523           0 :                 ABORT(r);
     524             :             }
     525           0 :             if(r=nr_ice_media_stream_start_checks(str->pctx,str))
     526           0 :               ABORT(r);
     527             : 
     528           0 :             break;
     529             :           default:
     530           0 :             break;
     531             :         }
     532             :       }
     533             : 
     534           0 :       str=STAILQ_NEXT(str,entry);
     535             :     }
     536             : 
     537             : /*    nr_ice_media_stream_dump_state(stream->pctx,stream,stderr); */
     538             : 
     539             : 
     540           0 :     _status=0;
     541             :   abort:
     542           0 :     return(_status);
     543             :   }
     544             : 
     545             : 
     546           0 : int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out)
     547             :   {
     548             :     nr_ice_cand_pair *pair;
     549             : 
     550             :     /* r_log(LOG_ICE,LOG_DEBUG,"MEDIA-STREAM(%s): state dump", stream->label); */
     551           0 :     pair=TAILQ_FIRST(&stream->check_list);
     552           0 :     while(pair){
     553           0 :       nr_ice_candidate_pair_dump_state(pair,out);
     554             : 
     555           0 :       pair=TAILQ_NEXT(pair,check_queue_entry);
     556             :     }
     557             : 
     558           0 :     return(0);
     559             :   }
     560             : 
     561           0 : int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state)
     562             :   {
     563             :     /* Make no-change a no-op */
     564           0 :     if (state == str->ice_state)
     565           0 :       return 0;
     566             : 
     567           0 :     assert(state < sizeof(nr_ice_media_stream_states)/sizeof(char *));
     568           0 :     assert(str->ice_state < sizeof(nr_ice_media_stream_states)/sizeof(char *));
     569             : 
     570           0 :     r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): stream %s state %s->%s",
     571           0 :       str->pctx->label,str->label,
     572           0 :       nr_ice_media_stream_states[str->ice_state],
     573             :       nr_ice_media_stream_states[state]);
     574             : 
     575           0 :     if(state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)
     576           0 :       str->pctx->active_streams++;
     577           0 :     if(str->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)
     578           0 :       str->pctx->active_streams--;
     579             : 
     580           0 :     r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): %d active streams",
     581           0 :       str->pctx->label, str->pctx->active_streams);
     582             : 
     583           0 :     str->ice_state=state;
     584             : 
     585           0 :     return(0);
     586             :   }
     587             : 
     588             : 
     589           0 : void nr_ice_media_stream_refresh_consent_all(nr_ice_media_stream *stream)
     590             :   {
     591             :     nr_ice_component *comp;
     592             : 
     593           0 :     comp=STAILQ_FIRST(&stream->components);
     594           0 :     while(comp){
     595           0 :       if(comp->disconnected) {
     596           0 :         nr_ice_component_refresh_consent_now(comp);
     597             :       }
     598             : 
     599           0 :       comp=STAILQ_NEXT(comp,entry);
     600             :     }
     601           0 :   }
     602             : 
     603           0 : void nr_ice_media_stream_disconnect_all_components(nr_ice_media_stream *stream)
     604             :   {
     605             :     nr_ice_component *comp;
     606             : 
     607           0 :     comp=STAILQ_FIRST(&stream->components);
     608           0 :     while(comp){
     609           0 :       comp->disconnected = 1;
     610             : 
     611           0 :       comp=STAILQ_NEXT(comp,entry);
     612             :     }
     613           0 :   }
     614             : 
     615           0 : void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disconnected)
     616             :   {
     617           0 :     if (stream->disconnected == disconnected) {
     618           0 :       return;
     619             :     }
     620             : 
     621           0 :     if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
     622           0 :       return;
     623             :     }
     624           0 :     stream->disconnected = disconnected;
     625             : 
     626           0 :     if (disconnected == NR_ICE_MEDIA_STREAM_DISCONNECTED) {
     627           0 :       nr_ice_peer_ctx_disconnected(stream->pctx);
     628             :     } else {
     629           0 :       nr_ice_peer_ctx_check_if_connected(stream->pctx);
     630             :     }
     631             :   }
     632             : 
     633           0 : int nr_ice_media_stream_check_if_connected(nr_ice_media_stream *stream)
     634             :   {
     635             :     nr_ice_component *comp;
     636             : 
     637           0 :     comp=STAILQ_FIRST(&stream->components);
     638           0 :     while(comp){
     639           0 :       if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
     640           0 :          (comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
     641           0 :          comp->disconnected)
     642           0 :         break;
     643             : 
     644           0 :       comp=STAILQ_NEXT(comp,entry);
     645             :     }
     646             : 
     647             :     /* At least one disconnected component */
     648           0 :     if(comp)
     649           0 :       goto done;
     650             : 
     651           0 :     nr_ice_media_stream_set_disconnected(stream, NR_ICE_MEDIA_STREAM_CONNECTED);
     652             : 
     653             :   done:
     654           0 :     return(0);
     655             :   }
     656             : 
     657             : /* S OK, this component has a nominated. If every component has a nominated,
     658             :    the stream is ready */
     659           0 : int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component)
     660             :   {
     661             :     int r,_status;
     662             :     nr_ice_component *comp;
     663             : 
     664           0 :     comp=STAILQ_FIRST(&stream->components);
     665           0 :     while(comp){
     666           0 :       if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
     667           0 :          (comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
     668           0 :          !comp->nominated)
     669           0 :         break;
     670             : 
     671           0 :       comp=STAILQ_NEXT(comp,entry);
     672             :     }
     673             : 
     674             :     /* At least one un-nominated component */
     675           0 :     if(comp)
     676           0 :       goto done;
     677             : 
     678             :     /* All done... */
     679           0 :     r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all active components have nominated candidate pairs",stream->pctx->label,stream->label);
     680           0 :     nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED);
     681             : 
     682             :     /* Cancel our timer */
     683           0 :     if(stream->timer){
     684           0 :       NR_async_timer_cancel(stream->timer);
     685           0 :       stream->timer=0;
     686             :     }
     687             : 
     688           0 :     if (stream->pctx->handler) {
     689           0 :       stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
     690             :     }
     691             : 
     692             :     /* Now tell the peer_ctx that we're connected */
     693           0 :     if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx))
     694           0 :       ABORT(r);
     695             : 
     696             :   done:
     697           0 :     _status=0;
     698             :   abort:
     699           0 :     return(_status);
     700             :   }
     701             : 
     702           0 : int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component)
     703             :   {
     704             :     int r,_status;
     705             :     nr_ice_cand_pair *p2;
     706             : 
     707           0 :     component->state=NR_ICE_COMPONENT_FAILED;
     708             : 
     709             :     /* at least one component failed in this media stream, so the entire
     710             :      * media stream is marked failed */
     711             : 
     712           0 :     nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_FAILED);
     713             : 
     714             :     /* OK, we need to cancel off everything on this component */
     715           0 :     p2=TAILQ_FIRST(&stream->check_list);
     716           0 :     while(p2){
     717           0 :       if(r=nr_ice_candidate_pair_cancel(p2->pctx,p2,0))
     718           0 :         ABORT(r);
     719             : 
     720           0 :       p2=TAILQ_NEXT(p2,check_queue_entry);
     721             :     }
     722             : 
     723             :     /* Cancel our timer */
     724           0 :     if(stream->timer){
     725           0 :       NR_async_timer_cancel(stream->timer);
     726           0 :       stream->timer=0;
     727             :     }
     728             : 
     729             :     /* Cancel consent timers in case it is running already */
     730           0 :     nr_ice_component_consent_destroy(component);
     731             : 
     732           0 :     if (stream->pctx->handler) {
     733           0 :       stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
     734             :     }
     735             : 
     736             :     /* Now tell the peer_ctx that we're connected */
     737           0 :     if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx))
     738           0 :       ABORT(r);
     739             : 
     740           0 :     _status=0;
     741             :   abort:
     742           0 :     return(_status);
     743             :   }
     744             : 
     745           0 : int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp)
     746             :   {
     747             :     nr_ice_candidate *cand;
     748           0 :     nr_ice_candidate *best_cand=0;
     749             :     nr_ice_component *comp;
     750             :     int r,_status;
     751             : 
     752           0 :     if(r=nr_ice_media_stream_find_component(str,component,&comp))
     753           0 :       ABORT(r);
     754             : 
     755           0 :     cand=TAILQ_FIRST(&comp->candidates);
     756           0 :     while(cand){
     757           0 :       if(cand->state==NR_ICE_CAND_STATE_INITIALIZED){
     758           0 :         if(!best_cand || (cand->priority>best_cand->priority))
     759           0 :           best_cand=cand;
     760             : 
     761             :       }
     762           0 :       cand=TAILQ_NEXT(cand,entry_comp);
     763             :     }
     764             : 
     765           0 :     if(!best_cand)
     766           0 :       ABORT(R_NOT_FOUND);
     767             : 
     768           0 :     *candp=best_cand;
     769             : 
     770           0 :     _status=0;
     771             :   abort:
     772           0 :     return(_status);
     773             :   }
     774             : 
     775             : 
     776             : /* OK, we have the stream the user created, but that reflects the base
     777             :    ICE ctx, not the peer_ctx. So, find the related stream in the pctx,
     778             :    and then find the component */
     779           0 : int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp)
     780             :   {
     781             :     int _status;
     782             :     nr_ice_component *comp;
     783             : 
     784           0 :     comp=STAILQ_FIRST(&str->components);
     785           0 :     while(comp){
     786           0 :       if(comp->component_id==comp_id)
     787           0 :         break;
     788             : 
     789           0 :       comp=STAILQ_NEXT(comp,entry);
     790             :     }
     791           0 :     if(!comp)
     792           0 :       ABORT(R_NOT_FOUND);
     793             : 
     794           0 :     *compp=comp;
     795             : 
     796           0 :     _status=0;
     797             :   abort:
     798           0 :     return(_status);
     799             :   }
     800             : 
     801           0 : int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len)
     802             :   {
     803             :     int r,_status;
     804             :     nr_ice_component *comp;
     805             : 
     806             :     /* First find the peer component */
     807           0 :     if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
     808           0 :       ABORT(r);
     809             : 
     810             :     /* Do we have an active pair yet? We should... */
     811           0 :     if(!comp->active)
     812           0 :       ABORT(R_NOT_FOUND);
     813             : 
     814             :     /* Does fresh ICE consent exist? */
     815           0 :     if(!comp->can_send)
     816           0 :       ABORT(R_FAILED);
     817             : 
     818             :     /* OK, write to that pair, which means:
     819             :        1. Use the socket on our local side.
     820             :        2. Use the address on the remote side
     821             :     */
     822           0 :     if(r=nr_socket_sendto(comp->active->local->osock,data,len,0,
     823           0 :                           &comp->active->remote->addr)) {
     824           0 :       if ((r==R_IO_ERROR) || (r==R_EOD)) {
     825           0 :         nr_ice_component_disconnected(comp);
     826             :       }
     827           0 :       ABORT(r);
     828             :     }
     829             : 
     830             :     // accumulate the sent bytes for the active candidate pair
     831           0 :     comp->active->bytes_sent += len;
     832           0 :     gettimeofday(&comp->active->last_sent, 0);
     833             : 
     834           0 :     _status=0;
     835             :   abort:
     836           0 :     return(_status);
     837             :   }
     838             : 
     839             : /* Returns R_REJECTED if the component is unpaired or has been disabled. */
     840           0 : int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote)
     841             :   {
     842             :     int r,_status;
     843             :     nr_ice_component *comp;
     844             : 
     845             :     /* First find the peer component */
     846           0 :     if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
     847           0 :       ABORT(r);
     848             : 
     849           0 :     if (comp->state == NR_ICE_COMPONENT_UNPAIRED ||
     850           0 :         comp->state == NR_ICE_COMPONENT_DISABLED)
     851           0 :       ABORT(R_REJECTED);
     852             : 
     853           0 :     if(!comp->active)
     854           0 :       ABORT(R_NOT_FOUND);
     855             : 
     856           0 :     if (local) *local = comp->active->local;
     857           0 :     if (remote) *remote = comp->active->remote;
     858             : 
     859           0 :     _status=0;
     860             :   abort:
     861           0 :     return(_status);
     862             :   }
     863             : 
     864           0 : int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote)
     865             :   {
     866             :     int r,_status;
     867             :     nr_ice_component *comp;
     868             : 
     869             :     /* First find the peer component */
     870           0 :     if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
     871           0 :       ABORT(r);
     872             : 
     873             :     /* Do we have an active pair yet? We should... */
     874           0 :     if(!comp->active)
     875           0 :       ABORT(R_BAD_ARGS);
     876             : 
     877             :     /* Use the socket on our local side */
     878           0 :     if(r=nr_socket_getaddr(comp->active->local->osock,local))
     879           0 :       ABORT(r);
     880             : 
     881             :     /* Use the address on the remote side */
     882           0 :     if(r=nr_transport_addr_copy(remote,&comp->active->remote->addr))
     883           0 :       ABORT(r);
     884             : 
     885           0 :     _status=0;
     886             :   abort:
     887           0 :     return(_status);
     888             :   }
     889             : 
     890             : 
     891             : 
     892           0 : int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr)
     893             :   {
     894             :     nr_ice_component *lcomp,*rcomp;
     895             : 
     896           0 :     r_log(LOG_ICE,LOG_DEBUG,"Finalizing media stream %s, peer=%s",lstr->label,
     897             :       rstr?rstr->label:"NONE");
     898             : 
     899           0 :     lcomp=STAILQ_FIRST(&lstr->components);
     900           0 :     if(rstr)
     901           0 :       rcomp=STAILQ_FIRST(&rstr->components);
     902             :     else
     903           0 :       rcomp=0;
     904             : 
     905           0 :     while(lcomp){
     906           0 :       nr_ice_component_finalize(lcomp,rcomp);
     907             : 
     908           0 :       lcomp=STAILQ_NEXT(lcomp,entry);
     909           0 :       if(rcomp){
     910           0 :         rcomp=STAILQ_NEXT(rcomp,entry);
     911             :       }
     912             :     }
     913             : 
     914           0 :     return(0);
     915             :   }
     916             : 
     917           0 : int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand)
     918             :   {
     919             :     int r,_status;
     920             :     nr_ice_component *comp;
     921             : 
     922           0 :     if ((r=nr_ice_media_stream_find_component(pstream, cand->component_id, &comp)))
     923           0 :       ABORT(R_NOT_FOUND);
     924             : 
     925           0 :     if (r=nr_ice_component_pair_candidate(pctx, comp, cand, 1))
     926           0 :       ABORT(r);
     927             : 
     928           0 :     _status=0;
     929             :   abort:
     930           0 :     return(_status);
     931             :   }
     932             : 
     933           0 : int nr_ice_media_stream_get_consent_status(nr_ice_media_stream *stream, int
     934             : component_id, int *can_send, struct timeval *ts)
     935             :   {
     936             :     int r,_status;
     937             :     nr_ice_component *comp;
     938             : 
     939           0 :     if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
     940           0 :       ABORT(r);
     941             : 
     942           0 :     *can_send = comp->can_send;
     943           0 :     ts->tv_sec = comp->consent_last_seen.tv_sec;
     944           0 :     ts->tv_usec = comp->consent_last_seen.tv_usec;
     945           0 :     _status=0;
     946             :   abort:
     947           0 :     return(_status);
     948             :   }
     949             : 
     950           0 : int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
     951             :   {
     952             :     int r,_status;
     953             :     nr_ice_component *comp;
     954             : 
     955           0 :     if (stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)
     956           0 :       ABORT(R_FAILED);
     957             : 
     958           0 :     if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
     959           0 :       ABORT(r);
     960             : 
     961             :     /* Can only disable before pairing */
     962           0 :     if (comp->state != NR_ICE_COMPONENT_UNPAIRED &&
     963           0 :         comp->state != NR_ICE_COMPONENT_DISABLED)
     964           0 :       ABORT(R_FAILED);
     965             : 
     966           0 :     comp->state = NR_ICE_COMPONENT_DISABLED;
     967             : 
     968           0 :     _status=0;
     969             :   abort:
     970           0 :     return(_status);
     971             :   }
     972             : 
     973           0 : void nr_ice_media_stream_role_change(nr_ice_media_stream *stream)
     974             :   {
     975             :     nr_ice_cand_pair *pair,*temp_pair;
     976             :     /* Changing role causes candidate pair priority to change, which requires
     977             :      * re-sorting the check list. */
     978             :     nr_ice_cand_pair_head old_checklist;
     979             : 
     980           0 :     assert(stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED);
     981             : 
     982             :     /* Move check_list to old_checklist (not POD, have to do the hard way) */
     983           0 :     TAILQ_INIT(&old_checklist);
     984           0 :     TAILQ_FOREACH_SAFE(pair,&stream->check_list,check_queue_entry,temp_pair) {
     985           0 :       TAILQ_REMOVE(&stream->check_list,pair,check_queue_entry);
     986           0 :       TAILQ_INSERT_TAIL(&old_checklist,pair,check_queue_entry);
     987             :     }
     988             : 
     989             :     /* Re-insert into the check list */
     990           0 :     TAILQ_FOREACH_SAFE(pair,&old_checklist,check_queue_entry,temp_pair) {
     991           0 :       TAILQ_REMOVE(&old_checklist,pair,check_queue_entry);
     992           0 :       nr_ice_candidate_pair_role_change(pair);
     993           0 :       nr_ice_candidate_pair_insert(&stream->check_list,pair);
     994             :     }
     995           0 :   }
     996             : 
     997           0 : int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *lcand, nr_ice_candidate *rcand, nr_ice_cand_pair **pair)
     998             :   {
     999           0 :     nr_ice_cand_pair_head *head = &str->check_list;
    1000             :     nr_ice_cand_pair *c1;
    1001             : 
    1002           0 :     c1=TAILQ_FIRST(head);
    1003           0 :     while(c1){
    1004           0 :       if(c1->local == lcand &&
    1005           0 :          c1->remote == rcand) {
    1006           0 :         *pair=c1;
    1007           0 :         return(0);
    1008             :       }
    1009             : 
    1010           0 :       c1=TAILQ_NEXT(c1,check_queue_entry);
    1011             :     }
    1012             : 
    1013           0 :     return(R_NOT_FOUND);
    1014             :   }

Generated by: LCOV version 1.13