]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: be more tolerant to a few read errors
authorMoises Silva <moy@sangoma.com>
Tue, 7 Jun 2011 21:35:49 +0000 (17:35 -0400)
committerMoises Silva <moy@sangoma.com>
Tue, 7 Jun 2011 21:35:49 +0000 (17:35 -0400)
libs/freetdm/mod_freetdm/mod_freetdm.c

index f188fc2d268050f5ee7724d8884133e9a82f054c..11c5353cc6c41b6c2b4bdf4bdb702ddd3590bcee 100755 (executable)
@@ -42,6 +42,9 @@
 #define FREETDM_VAR_PREFIX "freetdm_"
 #define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1) 
 
+/* How many consecutive IO errors before giving up */
+#define FTDM_MAX_READ_WRITE_ERRORS 10
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown);
 SWITCH_MODULE_DEFINITION(mod_freetdm, mod_freetdm_load, mod_freetdm_shutdown, NULL);
@@ -110,7 +113,8 @@ struct private_object {
        switch_mutex_t *mutex;
        switch_mutex_t *flag_mutex;
        ftdm_channel_t *ftdmchan;
-       uint32_t wr_error;
+       uint32_t write_error;
+       uint32_t read_error;
 };
 
 /* private data attached to FTDM channels (only FXS for now) */
@@ -624,12 +628,11 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
        ftdm_status_t status;
        int total_to;
        int chunk, do_break = 0;
-
+       uint32_t span_id, chan_id;
 
        channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
        
-       
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
 
@@ -638,6 +641,13 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
                return SWITCH_STATUS_FALSE;
        } 
 
+       if (!tech_pvt->ftdmchan) {
+               return SWITCH_STATUS_FALSE;
+       } 
+
+       span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
+       chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
+
        /* Digium Cards sometimes timeout several times in a row here. 
           Yes, we support digium cards, ain't we nice.......
           6 double length intervals should compensate */
@@ -697,8 +707,13 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 
        len = tech_pvt->read_frame.buflen;
        if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_WARNING, "failed to read from device\n");
-               goto fail;
+               ftdm_log(FTDM_LOG_WARNING, "failed to read from device %d:%d\n", span_id, chan_id);
+               if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on device %d:%d!\n", span_id, chan_id);
+                       goto fail;
+               }
+       } else {
+               tech_pvt->read_error = 0;
        }
 
        *frame = &tech_pvt->read_frame;
@@ -736,6 +751,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
        ftdm_size_t len;
        unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
        ftdm_wait_flag_t wflags = FTDM_WRITE;
+       uint32_t span_id, chan_id;
 
        channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
@@ -743,10 +759,6 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
 
-       if (!tech_pvt->ftdmchan) {
-               return SWITCH_STATUS_FALSE;
-       } 
-
        if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
                return SWITCH_STATUS_FALSE;
        }
@@ -758,6 +770,14 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
        if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
                goto fail;
        }
+
+       if (!tech_pvt->ftdmchan) {
+               return SWITCH_STATUS_FALSE;
+       } 
+
+       span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
+       chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
+
        
        if (switch_test_flag(frame, SFF_CNG)) {
                frame->data = data;
@@ -779,12 +799,14 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 
        len = frame->datalen;
        if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
-               if (++tech_pvt->wr_error > 10) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O write errors!\n");
+               ftdm_log(FTDM_LOG_WARNING, "failed to write to device %d:%d\n", span_id, chan_id);
+               if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, 
+                                       SWITCH_LOG_ERROR, "too many I/O write errors on device %d:%d!\n", span_id, chan_id);
                        goto fail;
                }
        } else {
-               tech_pvt->wr_error = 0;
+               tech_pvt->write_error = 0;
        }
 
        return SWITCH_STATUS_SUCCESS;