]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Merge branch 'moy.nonblocking-api'
authorMoises Silva <moy@sangoma.com>
Tue, 4 Jan 2011 17:32:30 +0000 (12:32 -0500)
committerMoises Silva <moy@sangoma.com>
Tue, 4 Jan 2011 17:32:30 +0000 (12:32 -0500)
Conflicts:
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c

1  2 
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c

Simple merge
index 8792b519d070c86c539762aac6a0620050f0a6d1,37c760ce94944073dc5ca7bdb502779e0a66cbf0..f1ef61ce9fdc4efccf9548a466b584293384fa05
@@@ -1656,183 -1627,161 +1653,173 @@@ static ftdm_status_t ftdm_r2_state_adva
        sigev.span_id = ftdmchan->span_id;
        sigev.channel = ftdmchan;
  
-       ret = 0;
-       /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept
-        * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this 
-        * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting
-        * to complete (the processing is media-bound)
-        * */
-       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) 
-                       && (r2call->chanstate != ftdmchan->state)) {
-               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
-               r2call->chanstate = ftdmchan->state;
-               if (IS_ACCEPTING_PENDING(ftdmchan)) {
-                       /* 
-                          Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting
-                          the call in R2 means sending a tone, then waiting for the acknowledge from the other end,
-                          since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100)
-                          which means during that time the user should not try to perform any operations like answer, hangup or anything
-                          else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block
-                          the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag,
-                          otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, 
-                          if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */
-                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state));
-               } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){
-                       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
-                       ftdm_channel_complete_state(ftdmchan);
-               }
-               switch (ftdmchan->state) {
-                       /* starting an incoming call */
-                       case FTDM_CHANNEL_STATE_COLLECT: 
-                               {
-                                       uint32_t interval = 0;
-                                       ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
-                                       ftdm_assert(interval != 0, "Invalid interval!");
-                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval);
-                                       openr2_chan_enable_read(r2chan);
-                               }
-                               break;
-                               /* starting an outgoing call */
-                       case FTDM_CHANNEL_STATE_DIALING:
-                               {
-                                       uint32_t interval = 0;
-                                       ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
-                                       ftdm_assert(interval != 0, "Invalid interval!");
-                                       ftdm_log_chan(ftdmchan, 
-                                               FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval);
-                                       openr2_chan_enable_read(r2chan);
-                               }
-                               break;
+       ret = FTDM_SUCCESS;
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
+       if (IS_ACCEPTING_PENDING(ftdmchan)) {
+               /* 
+                  Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting
+                  the call in R2 means sending a tone, then waiting for the acknowledge from the other end,
+                  since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100)
+                  which means during that time the user should not try to perform any operations like answer, hangup or anything
+                  else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block
+                  the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag,
+                  otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, 
+                  if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state));
+       } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){
+               ftdm_channel_complete_state(ftdmchan);
+       }
+       switch (ftdmchan->state) {
+               /* starting an incoming call */
+               case FTDM_CHANNEL_STATE_COLLECT: 
+                       {
+                               uint32_t interval = 0;
+                               ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
+                               ftdm_assert(interval != 0, "Invalid interval!");
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval);
+                               openr2_chan_enable_read(r2chan);
+                       }
+                       break;
  
-                               /* incoming call was offered */
-                       case FTDM_CHANNEL_STATE_RING:
+                       /* starting an outgoing call */
+               case FTDM_CHANNEL_STATE_DIALING:
+                       {
+                               uint32_t interval = 0;
+                               ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
+                               ftdm_assert(interval != 0, "Invalid interval!");
+                               ftdm_log_chan(ftdmchan, 
+                                       FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval);
+                               openr2_chan_enable_read(r2chan);
+                       }
+                       break;
  
-                               /* notify the user about the new call */
-                               sigev.event_id = FTDM_SIGEVENT_START;
+                       /* incoming call was offered */
+               case FTDM_CHANNEL_STATE_RING:
  
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-                               r2call->ftdm_call_started = 1; 
+                       /* notify the user about the new call */
+                       sigev.event_id = FTDM_SIGEVENT_START;
  
-                               break;
+                       ftdm_span_send_signal(ftdmchan->span, &sigev);
+                       r2call->ftdm_call_started = 1; 
  
-                               /* the call is making progress */
-                       case FTDM_CHANNEL_STATE_PROGRESS:
-                       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-                               {
-                                       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-                                               if (!r2call->accepted) {
-                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n");
-                                                       ft_r2_accept_call(ftdmchan);
-                                               } 
-                                       } else {
-                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
-                                               sigev.event_id = FTDM_SIGEVENT_PROCEED;
-                                               ftdm_span_send_signal(ftdmchan->span, &sigev);
+                       break;
  
-                                               sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
-                                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-                                       }
+                       /* the call is making progress */
+               case FTDM_CHANNEL_STATE_PROGRESS:
+               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+                       {
+                               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                       if (!r2call->accepted) {
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n");
+                                               ft_r2_accept_call(ftdmchan);
+                                       } 
+                               } else {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
+                                       sigev.event_id = FTDM_SIGEVENT_PROCEED;
+                                       ftdm_span_send_signal(ftdmchan->span, &sigev);
+                                       sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
+                                       ftdm_span_send_signal(ftdmchan->span, &sigev);
                                }
-                               break;
+                       }
+                       break;
  
-                               /* the call was answered */
-                       case FTDM_CHANNEL_STATE_UP:
-                               {
-                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n");
-                                       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-                                               if (!r2call->accepted) {
-                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n");
-                                                       // the answering will be done in the on_call_accepted handler
-                                                       ft_r2_accept_call(ftdmchan);
-                                                       r2call->answer_pending = 1;
-                                               } else {
-                                                       ft_r2_answer_call(ftdmchan);
-                                               }
+                       /* the call was answered */
+               case FTDM_CHANNEL_STATE_UP:
+                       {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n");
+                               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                       if (!r2call->accepted) {
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n");
+                                               // the answering will be done in the on_call_accepted handler
+                                               ft_r2_accept_call(ftdmchan);
+                                               r2call->answer_pending = 1;
                                        } else {
-                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n");
-                                               sigev.event_id = FTDM_SIGEVENT_UP;
-                                               ftdm_span_send_signal(ftdmchan->span, &sigev);
+                                               ft_r2_answer_call(ftdmchan);
                                        }
+                               } else {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n");
+                                       sigev.event_id = FTDM_SIGEVENT_UP;
+                                       ftdm_span_send_signal(ftdmchan->span, &sigev);
                                }
-                               break;
+                       }
+                       break;
  
-                               /* just got hangup */
-                       case FTDM_CHANNEL_STATE_HANGUP:
-                               {
-                                       if (!r2call->disconnect_rcvd) {
-                                               openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
-                                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
-                                               /* this will disconnect the call, but need to wait for the call end before moving to DOWN */
-                                               openr2_chan_disconnect_call(r2chan, disconnect_cause);
-                                       } else if (!r2call->protocol_error) {
-                                               /* just ack the hangup, on_call_end will be called by openr2 right after */
-                                               openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
-                                       } else {
-                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n");
-                                               /* do not set to down yet, give some time for recovery */
-                                               ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, 
-                                                               ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer);
-                                       }
+                       /* just got hangup */
+               case FTDM_CHANNEL_STATE_HANGUP:
+                       {
+                               if (!r2call->disconnect_rcvd) {
+                                       openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
+                                       /* this will disconnect the call, but need to wait for the call end before moving to DOWN */
+                                       openr2_chan_disconnect_call(r2chan, disconnect_cause);
+                               } else if (!r2call->protocol_error) {
+                                       /* just ack the hangup, on_call_end will be called by openr2 right after */
+                                       openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
+                               } else {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n");
+                                       /* do not set to down yet, give some time for recovery */
+                                       ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, 
+                                                       ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer);
                                }
-                               break;
-                       case FTDM_CHANNEL_STATE_TERMINATING:
-                               {
-                                       /* if the call has not been started yet we must go to HANGUP right here */ 
-                                       if (!r2call->ftdm_call_started) {
-                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
-                                       } else {
-                                               openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
-                                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
-                                               /* notify the user of the call terminating and we wait for the user to move us to hangup */
-                                               sigev.event_id = FTDM_SIGEVENT_STOP;
-                                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-                                       }
-                               }
-                               break;
+                       }
+                       break;
  
-                               /* finished call for good */
-                       case FTDM_CHANNEL_STATE_DOWN: 
-                               {
-                                       if (ftdmchan->last_state != FTDM_CHANNEL_STATE_RESET) {
-                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n");
-                                       }
-                                       ret = 1;
+               case FTDM_CHANNEL_STATE_TERMINATING:
+                       {
+                               /* if the call has not been started yet we must go to HANGUP right here */ 
+                               if (!r2call->ftdm_call_started) {
+                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
+                               } else {
+                                       openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
+                                       /* notify the user of the call terminating and we wait for the user to move us to hangup */
+                                       sigev.event_id = FTDM_SIGEVENT_STOP;
+                                       ftdm_span_send_signal(ftdmchan->span, &sigev);
                                }
-                               break;
+                       }
+                       break;
  
-                               /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */
-                       case FTDM_CHANNEL_STATE_RINGING: 
-                               {
-                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
+                       /* finished call for good */
+               case FTDM_CHANNEL_STATE_DOWN: 
+                       {
 -                              ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n");
++                              if (ftdmchan->last_state != FTDM_CHANNEL_STATE_RESET) {
++                                      ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n");
++                              } else {
++                                      ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Reset Complete\n");
 +                              }
-                               break;
+                               ret = FTDM_BREAK;
+                       }
+                       break;
  
-                               /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */
-                       case FTDM_CHANNEL_STATE_RESET:
-                               {
-                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n");
-                                       openr2_chan_set_idle(r2chan);
-                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-                               }
-                               break;
+                       /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */
+               case FTDM_CHANNEL_STATE_RINGING: 
+                       {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
+                       }
+                       break;
  
-                       default:
-                               {
-                                       ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
-                               }
-                               break;
++                      /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */
++              case FTDM_CHANNEL_STATE_RESET:
++                      {
++                              ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n");
++                              openr2_chan_set_idle(r2chan);
++                              ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
++                      }
++                      break;
 +
-               }
+               default:
+                       {
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
+                       }
+                       break;
 -
        }
  
-       if (ret) {
+       if (ret == FTDM_BREAK) {
                ftdm_channel_t *closed_chan;
                closed_chan = ftdmchan;
                ftdm_channel_close(&closed_chan);